From 7cba5cc10943b1f31cd7419760f2ab7281487787 Mon Sep 17 00:00:00 2001 From: Tiberiu Chibici Date: Sat, 26 Jul 2014 09:43:40 +0300 Subject: [PATCH] Fixed line endings and applied gitignore --- Build/Build.bat | 176 - Build/BuildLanguages.bat | 2 - Build/BuildVersion.bat | 2 - Build/DllExporter/AssemblyInfo.cs | 7 - Build/DllExporter/DllExporter.csproj | 82 - Build/DllExporter/Program.cs | 241 - Build/Installer/Header.bmp | Bin 10198 -> 0 bytes Build/Installer/Icon.ico | Bin 25214 -> 0 bytes Build/Installer/Installer.nsi | 959 - Build/Installer/MD5.dll | Bin 6656 -> 0 bytes Build/Installer/MoreInfo.dll | Bin 7168 -> 0 bytes Build/Installer/UAC.dll | Bin 13312 -> 0 bytes Build/Installer/UAC.nsh | 200 - Build/Installer/Wizard.bmp | Bin 52574 -> 0 bytes Build/Layouts/illustro default/Rainmeter.ini | 23 - .../Skins/illustro/@Resources/Background.png | Bin 1986 -> 0 bytes Build/Skins/illustro/Clock/Clock.ini | 138 - Build/Skins/illustro/Disk/1 Disk.ini | 149 - Build/Skins/illustro/Disk/2 Disks.ini | 209 - Build/Skins/illustro/Google/Google.ini | 119 - Build/Skins/illustro/Network/Network.ini | 215 - .../illustro/Recycle Bin/Recycle Bin.ini | 147 - Build/Skins/illustro/System/System.ini | 206 - Build/Skins/illustro/Welcome/Background.png | Bin 1836 -> 0 bytes Build/Skins/illustro/Welcome/Welcome.ini | 173 - Build/VS/Rainmeter.Cpp.Default.props | 31 - Build/VS/Rainmeter.Cpp.props | 129 - Build/VS/RainmeterPlugin.Cpp.props | 18 - Build/VS/RainmeterPlugin.Cs.props | 9 - Common/Common.vcxproj | 168 +- Common/Common.vcxproj.filters | 246 +- Common/Common_Test.vcxproj | 64 +- Common/Common_Test.vcxproj.filters | 14 +- Common/ControlTemplate.cpp | 98 +- Common/ControlTemplate.h | 176 +- Common/Dialog.cpp | 520 +- Common/Dialog.h | 194 +- Common/Gfx/Canvas.cpp | 142 +- Common/Gfx/Canvas.h | 226 +- Common/Gfx/CanvasD2D.cpp | 968 +- Common/Gfx/CanvasD2D.h | 234 +- Common/Gfx/CanvasGDIP.cpp | 484 +- Common/Gfx/CanvasGDIP.h | 178 +- Common/Gfx/FontCollection.cpp | 64 +- Common/Gfx/FontCollection.h | 84 +- Common/Gfx/FontCollectionD2D.cpp | 158 +- Common/Gfx/FontCollectionD2D.h | 110 +- Common/Gfx/FontCollectionGDIP.cpp | 108 +- Common/Gfx/FontCollectionGDIP.h | 108 +- Common/Gfx/TextFormat.cpp | 88 +- Common/Gfx/TextFormat.h | 158 +- Common/Gfx/TextFormatD2D.cpp | 734 +- Common/Gfx/TextFormatD2D.h | 160 +- Common/Gfx/TextFormatD2D_Test.cpp | 166 +- Common/Gfx/TextFormatGDIP.cpp | 268 +- Common/Gfx/TextFormatGDIP.h | 118 +- .../Gfx/Util/DWriteFontCollectionLoader.cpp | 134 +- Common/Gfx/Util/DWriteFontCollectionLoader.h | 104 +- Common/Gfx/Util/DWriteFontFileEnumerator.cpp | 156 +- Common/Gfx/Util/DWriteFontFileEnumerator.h | 110 +- Common/Gfx/Util/DWriteHelpers.cpp | 436 +- Common/Gfx/Util/DWriteHelpers.h | 114 +- Common/Gfx/Util/WICBitmapDIB.cpp | 272 +- Common/Gfx/Util/WICBitmapDIB.h | 150 +- Common/Gfx/Util/WICBitmapLockDIB.cpp | 182 +- Common/Gfx/Util/WICBitmapLockDIB.h | 122 +- Common/Gfx/Util/WICBitmapLockGDIP.cpp | 164 +- Common/Gfx/Util/WICBitmapLockGDIP.h | 120 +- Common/MathParser.cpp | 1812 +- Common/MathParser.h | 76 +- Common/MathParser_Test.cpp | 248 +- Common/MenuTemplate.cpp | 128 +- Common/MenuTemplate.h | 104 +- Common/PathUtil.cpp | 298 +- Common/PathUtil.h | 90 +- Common/PathUtil_Test.cpp | 212 +- Common/Platform.cpp | 202 +- Common/Platform.h | 64 +- Common/RawString.h | 184 +- Common/StringUtil.cpp | 190 +- Common/StringUtil.h | 158 +- Common/StringUtil_Test.cpp | 116 +- Common/Timer.h | 112 +- Common/UnitTest.h | 52 +- Docs/Building.md | 76 +- Docs/UnitTests.md | 64 +- Installer/Application.cpp | 200 +- Installer/Application.h | 64 +- Installer/DialogInstall.cpp | 988 +- Installer/DialogInstall.h | 194 +- Installer/Install.cpp | 294 +- Installer/Install.h | 88 +- Installer/Installer.rc | 108 +- Installer/Installer.vcxproj | 164 +- Installer/Installer.vcxproj.filters | 308 +- Installer/Resource.h | 12 +- Installer/StdAfx.cpp | 38 +- Installer/StdAfx.h | 70 +- Installer/Util.cpp | 560 +- Installer/Util.h | 80 +- Installer/lzma/7z.h | 406 +- Installer/lzma/7zAlloc.c | 152 +- Installer/lzma/7zAlloc.h | 30 +- Installer/lzma/7zBuf.c | 72 +- Installer/lzma/7zBuf.h | 78 +- Installer/lzma/7zCrc.c | 148 +- Installer/lzma/7zCrc.h | 50 +- Installer/lzma/7zCrcOpt.c | 68 +- Installer/lzma/7zDec.c | 962 +- Installer/lzma/7zFile.c | 576 +- Installer/lzma/7zFile.h | 166 +- Installer/lzma/7zIn.c | 2804 +- Installer/lzma/7zMemInStream.c | 168 +- Installer/lzma/7zMemInStream.h | 52 +- Installer/lzma/7zStream.c | 338 +- Installer/lzma/7zVersion.h | 14 +- Installer/lzma/Alloc.c | 254 +- Installer/lzma/Alloc.h | 76 +- Installer/lzma/Bcj2.c | 264 +- Installer/lzma/Bcj2.h | 76 +- Installer/lzma/Bra.c | 266 +- Installer/lzma/Bra.h | 136 +- Installer/lzma/Bra86.c | 170 +- Installer/lzma/CpuArch.c | 336 +- Installer/lzma/CpuArch.h | 310 +- Installer/lzma/LzmaDec.c | 1998 +- Installer/lzma/LzmaDec.h | 462 +- Installer/lzma/Types.h | 508 +- LICENSE | 678 +- Language/Arabic.nsh | 56 +- Language/Bulgarian.nsh | 56 +- Language/ChineseSimplified.nsh | 56 +- Language/ChineseTraditional.nsh | 56 +- Language/Croatian.nsh | 58 +- Language/Czech.nsh | 56 +- Language/Danish.nsh | 56 +- Language/Dutch.nsh | 56 +- Language/English.nsh | 56 +- Language/Finnish.nsh | 58 +- Language/French.nsh | 56 +- Language/German.nsh | 56 +- Language/Greek.nsh | 56 +- Language/Hebrew.nsh | 56 +- Language/Hungarian.nsh | 56 +- Language/Indonesian.nsh | 56 +- Language/Italian.nsh | 56 +- Language/Japanese.nsh | 58 +- Language/Korean.nsh | 56 +- Language/Language.rc | 4 +- Language/Language.vcxproj | 84 +- Language/Language.vcxproj.filters | 48 +- Language/Latvian.nsh | 56 +- Language/List | 62 +- Language/Lithuanian.nsh | 56 +- Language/NorwegianBokmal.nsh | 56 +- Language/Polish.nsh | 56 +- Language/PortugueseBrazil.nsh | 56 +- Language/PortuguesePortugal.nsh | 56 +- Language/Resource.rc | 346 +- Language/Romanian.nsh | 56 +- Language/Russian.nsh | 58 +- Language/SerbianCyrillic.nsh | 56 +- Language/SerbianLatin.nsh | 56 +- Language/Slovak.nsh | 56 +- Language/Slovenian.nsh | 56 +- Language/SpanishModern.nsh | 56 +- Language/Swedish.nsh | 56 +- Language/Turkish.nsh | 56 +- Language/Ukrainian.nsh | 56 +- Language/Vietnamese.nsh | 56 +- Library/CommandHandler.cpp | 1900 +- Library/CommandHandler.h | 296 +- Library/ConfigParser.cpp | 3172 +- Library/ConfigParser.h | 302 +- Library/ConfigParser_Test.cpp | 226 +- Library/ContextMenu.cpp | 1380 +- Library/ContextMenu.h | 116 +- Library/Dialog.cpp | 346 +- Library/Dialog.h | 146 +- Library/DialogAbout.cpp | 2662 +- Library/DialogAbout.h | 364 +- Library/DialogManage.cpp | 4272 +-- Library/DialogManage.h | 386 +- Library/Error.cpp | 44 +- Library/Error.h | 74 +- Library/Export.cpp | 524 +- Library/Export.h | 56 +- Library/Exports.def | 44 +- Library/Group.cpp | 130 +- Library/Group.h | 98 +- Library/IfActions.cpp | 734 +- Library/IfActions.h | 186 +- Library/Library.rc | 108 +- Library/Library.vcxproj | 342 +- Library/Library.vcxproj.filters | 714 +- Library/Litestep.cpp | 180 +- Library/Litestep.h | 80 +- Library/Logger.cpp | 552 +- Library/Logger.h | 258 +- Library/Measure.cpp | 1676 +- Library/Measure.h | 268 +- Library/MeasureCPU.cpp | 442 +- Library/MeasureCPU.h | 114 +- Library/MeasureCalc.cpp | 480 +- Library/MeasureCalc.h | 116 +- Library/MeasureDiskSpace.cpp | 490 +- Library/MeasureDiskSpace.h | 106 +- Library/MeasureMemory.cpp | 152 +- Library/MeasureMemory.h | 86 +- Library/MeasureNet.cpp | 1472 +- Library/MeasureNet.h | 158 +- Library/MeasureNetIn.cpp | 70 +- Library/MeasureNetIn.h | 68 +- Library/MeasureNetOut.cpp | 72 +- Library/MeasureNetOut.h | 68 +- Library/MeasureNetTotal.cpp | 72 +- Library/MeasureNetTotal.h | 68 +- Library/MeasurePhysicalMemory.cpp | 152 +- Library/MeasurePhysicalMemory.h | 86 +- Library/MeasurePlugin.cpp | 516 +- Library/MeasurePlugin.h | 166 +- Library/MeasureRegistry.cpp | 328 +- Library/MeasureRegistry.h | 98 +- Library/MeasureScript.cpp | 458 +- Library/MeasureScript.h | 110 +- Library/MeasureString.cpp | 134 +- Library/MeasureString.h | 90 +- Library/MeasureTime.cpp | 564 +- Library/MeasureTime.h | 104 +- Library/MeasureUptime.cpp | 206 +- Library/MeasureUptime.h | 92 +- Library/MeasureVirtualMemory.cpp | 154 +- Library/MeasureVirtualMemory.h | 86 +- Library/Meter.cpp | 1520 +- Library/Meter.h | 322 +- Library/MeterBar.cpp | 544 +- Library/MeterBar.h | 126 +- Library/MeterBitmap.cpp | 900 +- Library/MeterBitmap.h | 128 +- Library/MeterButton.cpp | 660 +- Library/MeterButton.h | 136 +- Library/MeterHistogram.cpp | 1318 +- Library/MeterHistogram.h | 176 +- Library/MeterImage.cpp | 732 +- Library/MeterImage.h | 134 +- Library/MeterLine.cpp | 898 +- Library/MeterLine.h | 120 +- Library/MeterRotator.cpp | 366 +- Library/MeterRotator.h | 112 +- Library/MeterRoundLine.cpp | 364 +- Library/MeterRoundLine.h | 118 +- Library/MeterString.cpp | 1364 +- Library/MeterString.h | 232 +- Library/MeterWindow.cpp | 9844 +++--- Library/MeterWindow.h | 876 +- Library/Mouse.cpp | 578 +- Library/Mouse.h | 304 +- Library/Rainmeter.cpp | 3380 +- Library/Rainmeter.h | 570 +- Library/RainmeterQuery.h | 250 +- Library/Section.cpp | 174 +- Library/Section.h | 146 +- Library/SkinRegistry.cpp | 484 +- Library/SkinRegistry.h | 210 +- Library/SkinRegistry_Test.cpp | 208 +- Library/StdAfx.cpp | 38 +- Library/StdAfx.h | 134 +- Library/System.cpp | 2812 +- Library/System.h | 226 +- Library/TintedImage.cpp | 1638 +- Library/TintedImage.h | 288 +- Library/TrayWindow.cpp | 1472 +- Library/TrayWindow.h | 202 +- Library/UpdateCheck.cpp | 194 +- Library/UpdateCheck.h | 48 +- Library/lua/LuaManager.cpp | 206 +- Library/lua/LuaManager.h | 144 +- Library/lua/LuaModifications.txt | 28 +- Library/lua/LuaScript.cpp | 522 +- Library/lua/LuaScript.h | 104 +- Library/lua/glue/LuaGlobal.cpp | 162 +- Library/lua/glue/LuaMeasure.cpp | 316 +- Library/lua/glue/LuaMeter.cpp | 350 +- Library/lua/glue/LuaMeterWindow.cpp | 480 +- Library/resource.h | 438 +- Plugins/API/RainmeterAPI.cs | 280 +- Plugins/API/RainmeterAPI.h | 250 +- Plugins/API/x32/Rainmeter.lib | Bin 4426 -> 0 bytes Plugins/API/x64/Rainmeter.lib | Bin 4276 -> 0 bytes Plugins/PluginAdvancedCPU/AdvancedCPU.cpp | 600 +- .../PluginAdvancedCPU/PluginAdvancedCPU.rc | 80 +- .../PluginAdvancedCPU.vcxproj | 86 +- Plugins/PluginCoreTemp/CoreTempProxy.cpp | 194 +- Plugins/PluginCoreTemp/CoreTempProxy.h | 68 +- Plugins/PluginCoreTemp/PluginCoreTemp.cpp | 424 +- Plugins/PluginCoreTemp/PluginCoreTemp.rc | 80 +- Plugins/PluginCoreTemp/PluginCoreTemp.vcxproj | 80 +- Plugins/PluginCoreTemp/SharedMem.cpp | 130 +- Plugins/PluginCoreTemp/SharedMem.h | 82 +- Plugins/PluginFileView/PluginFileView.cpp | 2484 +- Plugins/PluginFileView/PluginFileView.h | 568 +- Plugins/PluginFileView/PluginFileView.rc | 80 +- Plugins/PluginFileView/PluginFileView.vcxproj | 92 +- .../PluginFileView.vcxproj.filters | 24 +- Plugins/PluginFileView/StdAfx.h | 80 +- Plugins/PluginFolderInfo/FolderInfo.cpp | 388 +- Plugins/PluginFolderInfo/FolderInfo.h | 136 +- Plugins/PluginFolderInfo/FolderInfoPlugin.cpp | 316 +- Plugins/PluginFolderInfo/PluginFolderInfo.rc | 80 +- .../PluginFolderInfo/PluginFolderInfo.vcxproj | 86 +- .../PluginFolderInfo.vcxproj.filters | 64 +- Plugins/PluginInputText/AssemblyInfo.cs | 14 +- Plugins/PluginInputText/InputBox.Designer.cs | 208 +- Plugins/PluginInputText/InputBox.cs | 764 +- Plugins/PluginInputText/InputBox.resx | 238 +- Plugins/PluginInputText/Main.cs | 416 +- Plugins/PluginInputText/PluginCode.cs | 1048 +- .../PluginInputText/PluginInputText.csproj | 200 +- Plugins/PluginInputText/Rainmeter.cs | 266 +- Plugins/PluginMediaKey/PluginMediaKey.cpp | 144 +- Plugins/PluginMediaKey/PluginMediaKey.rc | 78 +- Plugins/PluginMediaKey/PluginMediaKey.vcxproj | 68 +- Plugins/PluginNowPlaying/Cover.cpp | 456 +- Plugins/PluginNowPlaying/Cover.h | 98 +- Plugins/PluginNowPlaying/Internet.cpp | 530 +- Plugins/PluginNowPlaying/Internet.h | 72 +- Plugins/PluginNowPlaying/Lyrics.cpp | 384 +- Plugins/PluginNowPlaying/Lyrics.h | 64 +- Plugins/PluginNowPlaying/NowPlaying.cpp | 1234 +- Plugins/PluginNowPlaying/NowPlaying.h | 120 +- Plugins/PluginNowPlaying/Player.cpp | 436 +- Plugins/PluginNowPlaying/Player.h | 278 +- Plugins/PluginNowPlaying/PlayerAIMP.cpp | 726 +- Plugins/PluginNowPlaying/PlayerAIMP.h | 128 +- Plugins/PluginNowPlaying/PlayerCAD.cpp | 1112 +- Plugins/PluginNowPlaying/PlayerCAD.h | 126 +- Plugins/PluginNowPlaying/PlayerITunes.cpp | 1282 +- Plugins/PluginNowPlaying/PlayerITunes.h | 192 +- Plugins/PluginNowPlaying/PlayerSpotify.cpp | 468 +- Plugins/PluginNowPlaying/PlayerSpotify.h | 126 +- Plugins/PluginNowPlaying/PlayerWLM.cpp | 414 +- Plugins/PluginNowPlaying/PlayerWLM.h | 102 +- Plugins/PluginNowPlaying/PlayerWMP.cpp | 1314 +- Plugins/PluginNowPlaying/PlayerWMP.h | 288 +- Plugins/PluginNowPlaying/PlayerWinamp.cpp | 1002 +- Plugins/PluginNowPlaying/PlayerWinamp.h | 138 +- Plugins/PluginNowPlaying/PluginNowPlaying.rc | 80 +- .../PluginNowPlaying/PluginNowPlaying.vcxproj | 370 +- .../PluginNowPlaying.vcxproj.filters | 770 +- .../PluginNowPlaying/SDKs/AIMP/aimp2_sdk.h | 1450 +- Plugins/PluginNowPlaying/SDKs/CAD/cad_sdk.h | 84 +- Plugins/PluginNowPlaying/SDKs/Winamp/wa_cmd.h | 194 +- Plugins/PluginNowPlaying/SDKs/Winamp/wa_dlg.h | 870 +- .../PluginNowPlaying/SDKs/Winamp/wa_hotkeys.h | 76 +- Plugins/PluginNowPlaying/SDKs/Winamp/wa_ipc.h | 4938 +-- .../SDKs/iTunes/iTunesCOMInterface.h | 28856 ++++++++-------- .../SDKs/iTunes/iTunesCOMInterface_i.c | 175 - Plugins/PluginNowPlaying/StdAfx.cpp | 38 +- Plugins/PluginNowPlaying/StdAfx.h | 78 +- Plugins/PluginNowPlaying/readme.txt | 12 +- .../PluginNowPlaying/taglib/taglib_config.h | 8 +- Plugins/PluginPerfMon/MakePtr.h | 20 +- Plugins/PluginPerfMon/ObjInst.cpp | 272 +- Plugins/PluginPerfMon/ObjInst.h | 116 +- Plugins/PluginPerfMon/ObjList.cpp | 164 +- Plugins/PluginPerfMon/ObjList.h | 90 +- Plugins/PluginPerfMon/PerfCntr.cpp | 244 +- Plugins/PluginPerfMon/PerfCntr.h | 68 +- Plugins/PluginPerfMon/PerfData.cpp | 412 +- Plugins/PluginPerfMon/PerfObj.cpp | 190 +- Plugins/PluginPerfMon/PerfObj.h | 88 +- Plugins/PluginPerfMon/PerfSnap.cpp | 328 +- Plugins/PluginPerfMon/PerfSnap.h | 84 +- Plugins/PluginPerfMon/PluginPerfMon.rc | 80 +- Plugins/PluginPerfMon/PluginPerfMon.vcxproj | 98 +- Plugins/PluginPerfMon/Titledb.cpp | 316 +- Plugins/PluginPerfMon/Titledb.h | 48 +- Plugins/PluginPing/Ping.cpp | 468 +- Plugins/PluginPing/PluginPing.rc | 80 +- Plugins/PluginPing/PluginPing.vcxproj | 70 +- Plugins/PluginPower/PluginPower.rc | 80 +- Plugins/PluginPower/PluginPower.vcxproj | 72 +- Plugins/PluginPower/PowerPlugin.cpp | 466 +- Plugins/PluginProcess/PluginProcess.cpp | 218 +- Plugins/PluginProcess/PluginProcess.rc | 80 +- Plugins/PluginProcess/PluginProcess.vcxproj | 70 +- Plugins/PluginQuote/PluginQuote.rc | 80 +- Plugins/PluginQuote/PluginQuote.vcxproj | 78 +- Plugins/PluginQuote/Quote.cpp | 656 +- .../PluginRecycleManager.rc | 80 +- .../PluginRecycleManager.vcxproj | 68 +- .../PluginRecycleManager/RecycleManager.cpp | 582 +- Plugins/PluginResMon/PluginResMon.rc | 80 +- Plugins/PluginResMon/PluginResMon.vcxproj | 70 +- Plugins/PluginResMon/ResMon.cpp | 374 +- Plugins/PluginSpeedFan/PluginSpeedFan.rc | 80 +- Plugins/PluginSpeedFan/PluginSpeedFan.vcxproj | 68 +- Plugins/PluginSpeedFan/SpeedFanPlugin.cpp | 390 +- Plugins/PluginSysInfo/PluginSysInfo.rc | 80 +- Plugins/PluginSysInfo/PluginSysInfo.vcxproj | 80 +- Plugins/PluginSysInfo/SysInfo.cpp | 1000 +- .../PluginVirtualDesktops/DexpotConstants.h | 234 +- .../PluginVirtualDesktops/DexpotMeasure.cpp | 1258 +- Plugins/PluginVirtualDesktops/DexpotMeasure.h | 420 +- .../PluginVirtualDesktops.rc | 80 +- .../PluginVirtualDesktops.vcxproj | 86 +- .../PluginVirtualDesktops.vcxproj.filters | 74 +- Plugins/PluginVirtualDesktops/VDMeasure.h | 130 +- .../VirtuaWinMeasure.cpp | 296 +- .../PluginVirtualDesktops/VirtuaWinMeasure.h | 114 +- .../PluginVirtualDesktops/VirtualDesktops.cpp | 324 +- Plugins/PluginWebParser/PluginWebParser.rc | 80 +- .../PluginWebParser/PluginWebParser.vcxproj | 88 +- .../PluginWebParser.vcxproj.filters | 78 +- Plugins/PluginWebParser/WebParser.cpp | 3330 +- Plugins/PluginWifiStatus/PluginWifiStatus.rc | 80 +- .../PluginWifiStatus/PluginWifiStatus.vcxproj | 70 +- Plugins/PluginWifiStatus/WifiStatus.cpp | 992 +- Plugins/PluginWin7Audio/PluginWin7Audio.rc | 80 +- .../PluginWin7Audio/PluginWin7Audio.vcxproj | 74 +- Plugins/PluginWin7Audio/PolicyConfig.h | 184 +- Plugins/PluginWin7Audio/Win7AudioPlugin.cpp | 878 +- .../PluginWindowMessage.rc | 80 +- .../PluginWindowMessage.vcxproj | 68 +- .../WindowMessagePlugin.cpp | 294 +- Plugins/PluginiTunes/PluginiTunes.rc | 80 +- Plugins/PluginiTunes/PluginiTunes.vcxproj | 78 +- .../iTunesCOMWindowsSDK/iTunesCOMInterface.h | 28768 +++++++-------- .../iTunesCOMInterface_i.c | 175 - Plugins/PluginiTunes/iTunesPlugin.cpp | 1958 +- README.md | 2 +- RainmeterEditor.exe.config | 6 +- RainmeterEditor.vshost.exe.config | 6 +- RainmeterEditor/App.xaml | 26 +- RainmeterEditor/App.xaml.cs | 44 +- RainmeterEditor/Business/DocumentManager.cs | 156 +- RainmeterEditor/Business/ProjectManager.cs | 32 +- RainmeterEditor/Documents/Ini/IniDocument.cs | 24 +- .../Documents/Ini/IniSkinDesigner.cs | 62 +- .../Documents/Ini/IniSkinDesignerControl.xaml | 22 +- .../Ini/IniSkinDesignerControl.xaml.cs | 54 +- .../Documents/Ini/IniSkinDesignerFactory.cs | 28 +- .../Documents/Text/TextDocument.cs | 70 +- RainmeterEditor/Documents/Text/TextEditor.cs | 54 +- .../Documents/Text/TextEditorControl.xaml | 22 +- .../Documents/Text/TextEditorControl.xaml.cs | 64 +- .../Documents/Text/TextEditorFactory.cs | 118 +- RainmeterEditor/Documents/Text/TextStorage.cs | 128 +- RainmeterEditor/Interop/NativeLibrary.cs | 106 +- RainmeterEditor/LICENSE | 40 +- RainmeterEditor/Model/DocumentFormat.cs | 28 +- .../Model/Events/DocumentOpenedEventArgs.cs | 34 +- RainmeterEditor/Model/IDocument.cs | 26 +- RainmeterEditor/Model/IDocumentEditor.cs | 272 +- .../Model/IDocumentEditorFactory.cs | 78 +- RainmeterEditor/Model/IDocumentStorage.cs | 52 +- RainmeterEditor/Model/Project.cs | 228 +- RainmeterEditor/Model/Property.cs | 60 +- RainmeterEditor/Model/RainmeterConfig.cs | 22 +- RainmeterEditor/Model/Reference.cs | 100 +- RainmeterEditor/Model/Tree.cs | 306 +- RainmeterEditor/Properties/AssemblyInfo.cs | 110 +- .../Properties/Resources.Designer.cs | 126 +- RainmeterEditor/Properties/Resources.resx | 232 +- .../Properties/Settings.Designer.cs | 52 +- RainmeterEditor/Properties/Settings.settings | 12 +- RainmeterEditor/Rainmeter.cs | 118 +- RainmeterEditor/RainmeterStudio.csproj | 426 +- RainmeterEditor/Resources/Strings.Designer.cs | 234 +- RainmeterEditor/Resources/Strings.resx | 274 +- RainmeterEditor/Storage/ProjectStorage.cs | 80 +- RainmeterEditor/Storage/SkinDirectory.cs | 50 +- RainmeterEditor/UI/Command.cs | 176 +- .../UI/Controller/DocumentController.cs | 154 +- .../UI/Dialogs/CreateDocumentDialog.xaml | 128 +- .../UI/Dialogs/CreateDocumentDialog.xaml.cs | 186 +- RainmeterEditor/UI/MainWindow.xaml | 232 +- RainmeterEditor/UI/MainWindow.xaml.cs | 148 +- RainmeterEditor/UI/SkinsPanel.xaml | 32 +- RainmeterEditor/UI/SkinsPanel.xaml.cs | 62 +- RainmeterEditor/UI/Styles/ButtonStyle.xaml | 108 +- RainmeterEditor/UI/Styles/Common.xaml | 10 +- RainmeterEditor/app.config | 6 +- RainmeterEditor/packages.config | 8 +- .../Properties/AssemblyInfo.cs | 72 +- .../RainmeterStudio.Tests.csproj | 190 +- .../Storage/ProjectStorageTest.cs | 220 +- RainmeterStudio.sln | 1070 +- SkinInstaller/DialogInstall.cpp | 2818 +- SkinInstaller/DialogInstall.h | 264 +- SkinInstaller/DialogPackage.cpp | 2804 +- SkinInstaller/DialogPackage.h | 254 +- SkinInstaller/SkinInstaller.cpp | 670 +- SkinInstaller/SkinInstaller.def | 8 +- SkinInstaller/SkinInstaller.h | 122 +- SkinInstaller/SkinInstaller.rc | 398 +- SkinInstaller/SkinInstaller.vcxproj | 218 +- SkinInstaller/SkinInstaller.vcxproj.filters | 334 +- SkinInstaller/SkinInstallerLauncher.cpp | 258 +- SkinInstaller/SkinInstallerLauncher.rc | 110 +- SkinInstaller/SkinInstallerLauncher.vcxproj | 98 +- .../SkinInstallerLauncher.vcxproj.filters | 52 +- SkinInstaller/StdAfx.cpp | 38 +- SkinInstaller/StdAfx.h | 98 +- SkinInstaller/resource.h | 146 +- SkinInstaller/zlib/gvmat64.asm | 1106 +- SkinInstaller/zlib/inffas32.asm | 2160 +- SkinInstaller/zlib/inffas8664.c | 372 +- SkinInstaller/zlib/inffasx64.asm | 792 +- SkinInstaller/zlib/match686.asm | 958 +- Version.cs | 22 +- Version.h | 18 +- .../AvalonDock.2.0.2000.nupkg | Bin 588883 -> 0 bytes .../AvalonDock.2.0.2000.nuspec | 19 - .../Xceed.Wpf.AvalonDock.Themes.Aero.dll | Bin 88576 -> 0 bytes .../Xceed.Wpf.AvalonDock.Themes.Aero.pdb | Bin 24064 -> 0 bytes ...Xceed.Wpf.AvalonDock.Themes.Expression.dll | Bin 97792 -> 0 bytes ...Xceed.Wpf.AvalonDock.Themes.Expression.pdb | Bin 32256 -> 0 bytes .../Xceed.Wpf.AvalonDock.Themes.Metro.dll | Bin 82432 -> 0 bytes .../Xceed.Wpf.AvalonDock.Themes.Metro.pdb | Bin 13824 -> 0 bytes .../Xceed.Wpf.AvalonDock.Themes.VS2010.dll | Bin 86528 -> 0 bytes .../Xceed.Wpf.AvalonDock.Themes.VS2010.pdb | Bin 13824 -> 0 bytes .../lib/net40/Xceed.Wpf.AvalonDock.dll | Bin 426496 -> 0 bytes .../lib/net40/Xceed.Wpf.AvalonDock.pdb | Bin 1013248 -> 0 bytes .../lib/net40/Xceed.Wpf.AvalonDock.xml | 4044 --- .../de/Xceed.Wpf.AvalonDock.resources.dll | Bin 6144 -> 0 bytes .../es/Xceed.Wpf.AvalonDock.resources.dll | Bin 5632 -> 0 bytes .../fr/Xceed.Wpf.AvalonDock.resources.dll | Bin 6144 -> 0 bytes .../hu/Xceed.Wpf.AvalonDock.resources.dll | Bin 5632 -> 0 bytes .../it/Xceed.Wpf.AvalonDock.resources.dll | Bin 5632 -> 0 bytes .../pt-BR/Xceed.Wpf.AvalonDock.resources.dll | Bin 6144 -> 0 bytes .../ro/Xceed.Wpf.AvalonDock.resources.dll | Bin 5632 -> 0 bytes .../ru/Xceed.Wpf.AvalonDock.resources.dll | Bin 6144 -> 0 bytes .../sv/Xceed.Wpf.AvalonDock.resources.dll | Bin 5632 -> 0 bytes .../Xceed.Wpf.AvalonDock.resources.dll | Bin 5632 -> 0 bytes packages/ini-parser.2.1.1/README.md | 56 - packages/ini-parser.2.1.1/content/LICENSE | 20 - .../ini-parser.2.1.1/ini-parser.2.1.1.nupkg | Bin 34647 -> 0 bytes .../ini-parser.2.1.1/ini-parser.2.1.1.nuspec | 17 - .../ini-parser.2.1.1/lib/INIFileParser.dll | Bin 26112 -> 0 bytes .../ini-parser.2.1.1/lib/INIFileParser.pdb | Bin 87552 -> 0 bytes packages/repositories.config | 4 - 542 files changed, 112014 insertions(+), 119759 deletions(-) delete mode 100644 Build/Build.bat delete mode 100644 Build/BuildLanguages.bat delete mode 100644 Build/BuildVersion.bat delete mode 100644 Build/DllExporter/AssemblyInfo.cs delete mode 100644 Build/DllExporter/DllExporter.csproj delete mode 100644 Build/DllExporter/Program.cs delete mode 100644 Build/Installer/Header.bmp delete mode 100644 Build/Installer/Icon.ico delete mode 100644 Build/Installer/Installer.nsi delete mode 100644 Build/Installer/MD5.dll delete mode 100644 Build/Installer/MoreInfo.dll delete mode 100644 Build/Installer/UAC.dll delete mode 100644 Build/Installer/UAC.nsh delete mode 100644 Build/Installer/Wizard.bmp delete mode 100644 Build/Layouts/illustro default/Rainmeter.ini delete mode 100644 Build/Skins/illustro/@Resources/Background.png delete mode 100644 Build/Skins/illustro/Clock/Clock.ini delete mode 100644 Build/Skins/illustro/Disk/1 Disk.ini delete mode 100644 Build/Skins/illustro/Disk/2 Disks.ini delete mode 100644 Build/Skins/illustro/Google/Google.ini delete mode 100644 Build/Skins/illustro/Network/Network.ini delete mode 100644 Build/Skins/illustro/Recycle Bin/Recycle Bin.ini delete mode 100644 Build/Skins/illustro/System/System.ini delete mode 100644 Build/Skins/illustro/Welcome/Background.png delete mode 100644 Build/Skins/illustro/Welcome/Welcome.ini delete mode 100644 Build/VS/Rainmeter.Cpp.Default.props delete mode 100644 Build/VS/Rainmeter.Cpp.props delete mode 100644 Build/VS/RainmeterPlugin.Cpp.props delete mode 100644 Build/VS/RainmeterPlugin.Cs.props delete mode 100644 Plugins/API/x32/Rainmeter.lib delete mode 100644 Plugins/API/x64/Rainmeter.lib delete mode 100644 Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface_i.c delete mode 100644 Plugins/PluginiTunes/iTunesCOMWindowsSDK/iTunesCOMInterface_i.c delete mode 100644 packages/AvalonDock.2.0.2000/AvalonDock.2.0.2000.nupkg delete mode 100644 packages/AvalonDock.2.0.2000/AvalonDock.2.0.2000.nuspec delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.Aero.dll delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.Aero.pdb delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.Expression.dll delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.Expression.pdb delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.Metro.dll delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.Metro.pdb delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.VS2010.dll delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.VS2010.pdb delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.dll delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.pdb delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.xml delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/de/Xceed.Wpf.AvalonDock.resources.dll delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/es/Xceed.Wpf.AvalonDock.resources.dll delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/fr/Xceed.Wpf.AvalonDock.resources.dll delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/hu/Xceed.Wpf.AvalonDock.resources.dll delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/it/Xceed.Wpf.AvalonDock.resources.dll delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/pt-BR/Xceed.Wpf.AvalonDock.resources.dll delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/ro/Xceed.Wpf.AvalonDock.resources.dll delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/ru/Xceed.Wpf.AvalonDock.resources.dll delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/sv/Xceed.Wpf.AvalonDock.resources.dll delete mode 100644 packages/AvalonDock.2.0.2000/lib/net40/zh-Hans/Xceed.Wpf.AvalonDock.resources.dll delete mode 100644 packages/ini-parser.2.1.1/README.md delete mode 100644 packages/ini-parser.2.1.1/content/LICENSE delete mode 100644 packages/ini-parser.2.1.1/ini-parser.2.1.1.nupkg delete mode 100644 packages/ini-parser.2.1.1/ini-parser.2.1.1.nuspec delete mode 100644 packages/ini-parser.2.1.1/lib/INIFileParser.dll delete mode 100644 packages/ini-parser.2.1.1/lib/INIFileParser.pdb delete mode 100644 packages/repositories.config diff --git a/Build/Build.bat b/Build/Build.bat deleted file mode 100644 index 1e3910de..00000000 --- a/Build/Build.bat +++ /dev/null @@ -1,176 +0,0 @@ -@echo off -setlocal EnableDelayedExpansion - -set VCVARSALL=%VS120COMNTOOLS%..\..\VC\vcvarsall.bat -set MAKENSIS=%PROGRAMFILES%\NSIS\MakeNSIS.exe -set GIT=%PROGRAMFILES%\Git\bin\git.exe - -:: Set VERSION_REVISION to non-zero value to override -set VERSION_MAJOR=3 -set VERSION_MINOR=2 -set VERSION_SUBMINOR=0 -set VERSION_REVISION=0 -set ISBETA=true - -if "%1" == "RELEASE" set ISBETA=false -if "%1" == "BUILDVERSION" goto BUILDVERSION -echo Rainmeter Build -echo ---------------------------------------------- -echo. - -if not exist "%VCVARSALL%" echo ERROR: vcvarsall.bat not found & goto END -call "%VCVARSALL%" x86 > nul - -set MSBUILD="msbuild.exe" /nologo^ - /p:PlatformToolset=v120_xp;VisualStudioVersion=12.0^ - /p:ExcludeTests=true^ - /p:Configuration=Release - -if exist "Certificate.bat" call "Certificate.bat" > nul -set SIGNTOOL="signtool.exe" sign /t http://time.certum.pl /f "%CERTFILE%" /p "%CERTKEY%" - -if "%1" == "BUILDLANGUAGES" goto BUILDLANGUAGES - -if exist "%MAKENSIS%" goto NSISFOUND -set MAKENSIS=%MAKENSIS:Program Files\=Program Files (x86)\% -if not exist "%MAKENSIS%" echo ERROR: MakeNSIS.exe not found & goto END -:NSISFOUND - -:BUILDVERSION - -if not exist "..\.git" goto UPDATEVERSION -if not "%VERSION_REVISION%" == "0" goto UPDATEVERSION - -:: git -if exist "%GIT%" goto GITFOUND -set GIT=%GIT:Program Files\=Program Files (x86)\% -if not exist "%GIT%" echo ERROR: git.exe not found & goto END -:GITFOUND -set /a VERSION_REVISION=0 -for /f "usebackq delims= " %%G in (`"%GIT%" rev-list --all --count`) do set VERSION_REVISION=%%G - -:UPDATEVERSION - -set VERSION_FULL=%VERSION_MAJOR%.%VERSION_MINOR%.%VERSION_SUBMINOR%.%VERSION_REVISION% -set VERSION_SHORT=%VERSION_MAJOR%.%VERSION_MINOR% -if not "%VERSION_SUBMINOR%" == "0" set VERSION_SHORT=!VERSION_SHORT!.%VERSION_SUBMINOR% - -:: Update Version.h -> "..\Version.h" echo #pragma once ->>"..\Version.h" echo #define FILEVER %VERSION_MAJOR%,%VERSION_MINOR%,%VERSION_SUBMINOR%,%VERSION_REVISION% ->>"..\Version.h" echo #define PRODUCTVER FILEVER ->>"..\Version.h" echo #define STRFILEVER "%VERSION_FULL%" ->>"..\Version.h" echo #define STRPRODUCTVER STRFILEVER ->>"..\Version.h" echo #define APPVERSION L"%VERSION_MAJOR%.%VERSION_MINOR%.%VERSION_SUBMINOR%" ->>"..\Version.h" echo #define RAINMETER_VERSION ((%VERSION_MAJOR% * 1000000) + (%VERSION_MINOR% * 1000) + %VERSION_SUBMINOR%) ->>"..\Version.h" echo const int revision_number = %VERSION_REVISION%; ->>"..\Version.h" echo const bool revision_beta = %ISBETA%; - -:: Update Version.cs -> "..\Version.cs" echo namespace Rainmeter ->>"..\Version.cs" echo { ->>"..\Version.cs" echo public class Version ->>"..\Version.cs" echo { ->>"..\Version.cs" echo #if X64 ->>"..\Version.cs" echo public const string Informational = "%VERSION_FULL% (64-bit)"; ->>"..\Version.cs" echo #else ->>"..\Version.cs" echo public const string Informational = "%VERSION_FULL% (32-bit)"; ->>"..\Version.cs" echo #endif ->>"..\Version.cs" echo } ->>"..\Version.cs" echo } - - -if "%1" == "BUILDVERSION" goto :eof -echo * Updated Version.h - -:: Set vcbuild environment variables and begin build -echo * Starting build for %VERSION_FULL% -for /F "tokens=1-4 delims=:.," %%a in ("%TIME%") do ( - set /A "BUILD_BEGIN_TIMESTAMP=(((%%a * 60) + 1%%b %% 100)* 60 + 1%%c %% 100) * 100 + 1%%d %% 100" -) - -:: Build Library -echo * Building 32-bit projects -%MSBUILD% /t:rebuild /p:Platform=Win32 /v:q /m ..\Rainmeter.sln > "BuildLog.txt" -if not %ERRORLEVEL% == 0 echo ERROR %ERRORLEVEL%: Build failed & goto END - -echo * Building 64-bit projects -%MSBUILD% /t:rebuild /p:Platform=x64 /v:q /m ..\Rainmeter.sln > "BuildLog.txt" -if not %ERRORLEVEL% == 0 echo ERROR %ERRORLEVEL%: Build failed & goto END - -:BUILDLANGUAGES -echo * Building languages - -:: Build all language libraries ->".\Installer\Languages.nsh" echo. -for /f "tokens=1,2,3 delims=," %%a in (..\Language\List) do ( - > "..\Language\Language.rc" echo #include "%%a.h" - >>"..\Language\Language.rc" echo #include "Resource.rc" - >>".\Installer\Languages.nsh" echo ${IncludeLanguage} "%%b" "%%a" - set LANGDLL_PARAMS='%%a - ${LANGFILE_%%b_NAME}' '${LANG_%%b}' '${LANG_%%b_CP}' !LANGDLL_PARAMS! - set LANGUAGE_IDS=${LANG_%%b},!LANGUAGE_IDS! - - %MSBUILD% /t:Language /p:Platform=Win32;TargetName=%%c /v:q ..\Rainmeter.sln > "BuildLog.txt" - if not %ERRORLEVEL% == 0 echo ERROR: Building language %%a failed & goto END -) ->>".\Installer\Languages.nsh" echo ^^!define LANGDLL_PARAMS "%LANGDLL_PARAMS%" ->>".\Installer\Languages.nsh" echo ^^!define LANGUAGE_IDS "%LANGUAGE_IDS%" - -:: Restore English -echo #include "English.h"> "..\Language\Language.rc" -echo #include "Resource.rc">> "..\Language\Language.rc" -if "%1" == "BUILDLANGUAGES" ( - xcopy /Q /S /Y ..\x32-Release\Languages\*.dll ..\x64-Release\Languages\ > nul - xcopy /Q /S /Y ..\x32-Release\Release\Languages\*.dll ..\x32-Debug\Languages\ > nul - xcopy /Q /S /Y ..\x32-Release\Release\Languages\*.dll ..\x64-Debug\Languages\ > nul - if exist "BuildLog.txt" del "BuildLog.txt" - goto END -) - -:: Sign binaries -if not "%CERTFILE%" == "" ( - echo * Signing binaries - for %%Z in (Rainmeter.dll Rainmeter.exe SkinInstaller.exe SkinInstaller.dll) do ( - %SIGNTOOL% ..\x32-Release\%%Z > BuildLog.txt - if not %ERRORLEVEL% == 0 echo ERROR %ERRORLEVEL%: Signing x32\%%Z failed & goto END - %SIGNTOOL% ..\x64-Release\%%Z > BuildLog.txt - if not %ERRORLEVEL% == 0 echo ERROR %ERRORLEVEL%: Signing x64\%%Z failed & goto END - ) -) - -:: Build installer -echo * Building installer - -set INSTALLER_NAME=Rainmeter-%VERSION_SHORT%.exe -if not "%1" == "RELEASE" set INSTALLER_NAME=Rainmeter-%VERSION_SHORT%-r%VERSION_REVISION%-beta.exe - -set INSTALLER_DEFINES=^ - /DOUTFILE="%INSTALLER_NAME%"^ - /DVERSION_FULL="%VERSION_FULL%"^ - /DVERSION_SHORT="%VERSION_SHORT%"^ - /DVERSION_REVISION="%VERSION_REVISION%" -if not "%1" == "RELEASE" set INSTALLER_DEFINES=!INSTALLER_DEFINES! /DBETA - -"%MAKENSIS%" %INSTALLER_DEFINES% .\Installer\Installer.nsi > "BuildLog.txt" -if not %ERRORLEVEL% == 0 echo ERROR %ERRORLEVEL%: Building installer failed & goto END - -:: Sign installer -if not "%CERTFILE%" == "" ( - echo * Signing installer - %SIGNTOOL% %INSTALLER_NAME% > BuildLog.txt - if not %ERRORLEVEL% == 0 echo ERROR %ERRORLEVEL%: Signing installer failed & goto END -) - -:: If we got here, build was successful so delete BuildLog.txt -if exist "BuildLog.txt" del "BuildLog.txt" - -for /F "tokens=1-4 delims=:.," %%a in ("%TIME%") do ( - set /A "BUILD_END_TIMESTAMP=(((%%a * 60) + 1%%b %% 100)* 60 + %%c %% 100) * 100 + 1%%d %% 100" -) -set /A "BUILD_ELAPSED_TIME=(%BUILD_END_TIMESTAMP% - %BUILD_BEGIN_TIMESTAMP%) / 100" -echo * Build complete. Elapsed time: %BUILD_ELAPSED_TIME% sec - -:END -if exist ".\Installer\Languages.nsh" del ".\Installer\Languages.nsh" -echo. -pause diff --git a/Build/BuildLanguages.bat b/Build/BuildLanguages.bat deleted file mode 100644 index 4a5f9b19..00000000 --- a/Build/BuildLanguages.bat +++ /dev/null @@ -1,2 +0,0 @@ -@echo off -"Build.bat" BUILDLANGUAGES \ No newline at end of file diff --git a/Build/BuildVersion.bat b/Build/BuildVersion.bat deleted file mode 100644 index 1ffcfc2b..00000000 --- a/Build/BuildVersion.bat +++ /dev/null @@ -1,2 +0,0 @@ -@echo off -"Build.bat" BUILDVERSION diff --git a/Build/DllExporter/AssemblyInfo.cs b/Build/DllExporter/AssemblyInfo.cs deleted file mode 100644 index c23d01a9..00000000 --- a/Build/DllExporter/AssemblyInfo.cs +++ /dev/null @@ -1,7 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyCopyright("© 2013 - Birunthan Mohanathas")] -[assembly: AssemblyVersion("1.0.1.0")] -[assembly: AssemblyProduct("Rainmeter")] \ No newline at end of file diff --git a/Build/DllExporter/DllExporter.csproj b/Build/DllExporter/DllExporter.csproj deleted file mode 100644 index 7079b9f3..00000000 --- a/Build/DllExporter/DllExporter.csproj +++ /dev/null @@ -1,82 +0,0 @@ - - - - Debug - x86 - 8.0.30703 - 2.0 - {49D56CA5-54AB-45C9-A245-EAE588FCBFE1} - Exe - Properties - DllExporter - DllExporter - v4.0 - 512 - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - $(SolutionDir)x32-$(Configuration)\Tools\ - $(SolutionDir)x64-$(Configuration)\Tools\ - - - x86 - true - full - false - DEBUG;TRACE - prompt - 4 - 1607 - - - x86 - none - true - TRACE - prompt - 4 - 1607 - - - OnOutputUpdated - - - true - DEBUG;TRACE - full - x64 - prompt - 1607 - - - TRACE - true - none - x64 - prompt - 1607 - - - - - - - - - - - - - \ No newline at end of file diff --git a/Build/DllExporter/Program.cs b/Build/DllExporter/Program.cs deleted file mode 100644 index 4b56fda4..00000000 --- a/Build/DllExporter/Program.cs +++ /dev/null @@ -1,241 +0,0 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Diagnostics; -using Microsoft.Build.Utilities; -using System.IO; - -namespace DllExporter -{ - class Program - { - static int Main(string[] args) - { - if (args.Length < 4) - { - Console.WriteLine("DllExporter error: Invalid arguments"); - return 1; - } - - string configurationName = args[0]; - string platformTarget = args[1]; - string targetDirectory = args[2]; - string targetDllName = targetDirectory + args[3]; - string targetIlName = targetDllName + ".il"; - string targetResName = targetDllName + ".res"; - - bool is64 = platformTarget.ToLower().Equals("x64"); - bool isDebug = configurationName.ToLower().Equals("debug"); - - string ilasmPath = FindIlasmPath(is64); - if (ilasmPath == null) - { - Console.WriteLine("DllExporter error: ilasm.exe not found"); - return 1; - } - - string ildasmPath = FindIldasmPath(); - if (ildasmPath == null) - { - Console.WriteLine("DllExporter error: ildasm.exe not found"); - return 1; - } - - Directory.SetCurrentDirectory(targetDirectory); - - // Disassemble - Process ildasmProc = new Process(); - string ildasmArgs = string.Format( - "/nobar {0} /output=\"{1}\" \"{2}\"", - isDebug ? "/linenum" : "", - targetIlName, - targetDllName); - - ildasmProc.StartInfo = new ProcessStartInfo(ildasmPath, ildasmArgs); - ildasmProc.StartInfo.UseShellExecute = false; - ildasmProc.StartInfo.CreateNoWindow = false; - ildasmProc.StartInfo.RedirectStandardOutput = true; - ildasmProc.Start(); - ildasmProc.WaitForExit(); - - if (ildasmProc.ExitCode != 0) - { - Console.WriteLine("DllExporter error: Unable to disassemble!"); - Console.WriteLine(ildasmProc.StandardOutput.ReadToEnd()); - return ildasmProc.ExitCode; - } - - bool hasResource = File.Exists(targetResName); - - // Read disassembly and find methods marked with DllExport attribute - List lines = new List(File.ReadAllLines(targetIlName)); - int attributeIndex = 0; - int exportCount = 0; - while (true) - { - attributeIndex = lines.FindIndex(attributeIndex, new Predicate(x => x.Contains(".custom instance void") && x.Contains("DllExport::.ctor()"))); - if (attributeIndex < 8) break; - - int methodIndex = lines.FindLastIndex(attributeIndex, attributeIndex, new Predicate(x => x.Contains(".method"))); - if (methodIndex == -1) - { - Console.WriteLine("DllExporter error: Unable to parse disassembly (.method not found)!"); - return 1; - } - - int functionIndex = lines.FindIndex(methodIndex, new Predicate(x => x.Contains("("))); - if (functionIndex == -1) - { - Console.WriteLine("DllExporter error: Unable to parse disassembly (bracket not found)!"); - return 1; - } - - int bracketPos = lines[functionIndex].IndexOf('('); - int functionNamePos = lines[functionIndex].LastIndexOf(' ', bracketPos); - string functionName = lines[functionIndex].Substring(functionNamePos, bracketPos - functionNamePos); - - // Change calling convention to cdecl - lines[functionIndex] = string.Format("{0} modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) {1}", lines[functionIndex].Substring(0, functionNamePos - 1), lines[functionIndex].Substring(functionNamePos)); - - int attributeBeginPos = lines[attributeIndex].IndexOf('.'); - string spaces = new string(' ', attributeBeginPos); - - // Replace attribute with export - ++exportCount; - lines[attributeIndex] = string.Format("{0}.export [{1}] as {2}", spaces, exportCount, functionName); - - ++attributeIndex; - } - - if (exportCount == 0) - { - Console.WriteLine("DllExporter warning: Nothing found to export."); - } - - // Remove the DllExport class - int classIndex = lines.FindIndex(new Predicate(x => x.Contains(".class ") && x.EndsWith(".DllExport"))); - if (classIndex == -1) - { - Console.WriteLine("DllExporter error: Unable to parse disassembly (DllExport class not found)!"); - return 1; - } - else - { - int classEndIndex = lines.FindIndex(classIndex, new Predicate(x => x.Contains("} // end of class") && x.EndsWith(".DllExport"))); - if (classEndIndex == -1) - { - Console.WriteLine("DllExporter error: Unable to parse disassembly (DllExport class end not found)!"); - return 1; - } - - lines.RemoveRange(classIndex, classEndIndex - classIndex + 2); - } - - // Write everything back - File.WriteAllLines(targetIlName, lines.ToArray()); - - // Reassemble - Process ilasmProc = new Process(); - string resource = hasResource ? string.Format("/resource=\"{0}\"", targetResName) : ""; - string ilasmArgs = string.Format("/nologo /quiet /dll {0} {1} /output=\"{2}\" {3} \"{4}\"", isDebug ? "/debug /pdb" : "/optimize", is64 ? "/x64 /PE64" : "", targetDllName, resource, targetIlName); - ilasmProc.StartInfo = new ProcessStartInfo(ilasmPath, ilasmArgs); - ilasmProc.StartInfo.UseShellExecute = false; - ilasmProc.StartInfo.CreateNoWindow = false; - ilasmProc.StartInfo.RedirectStandardOutput = true; - ilasmProc.Start(); - ilasmProc.WaitForExit(); - - if (ilasmProc.ExitCode != 0) - { - Console.WriteLine("DllExporter error: Unable to assemble!"); - Console.WriteLine(ilasmProc.StandardOutput.ReadToEnd()); - return ilasmProc.ExitCode; - } - - // Cleanup - File.Delete(targetIlName); - File.Delete(targetResName); - - Console.WriteLine("DllExporter: Processed {0}", args[3]); - - return 0; - } - - /// - /// Finds path to ilasm.exe. - /// - private static string FindIlasmPath(bool x64) - { - var arch = x64 ? DotNetFrameworkArchitecture.Bitness64 : DotNetFrameworkArchitecture.Bitness32; - var path = ToolLocationHelper.GetPathToDotNetFrameworkFile( - "ilasm.exe", TargetDotNetFrameworkVersion.Version20, arch); - return File.Exists(path) ? path : null; - } - - /// - /// Finds path to ildasm.exe. - /// - private static string FindIldasmPath() - { - var sdkPath = Environment.ExpandEnvironmentVariables(@"%ProgramFiles(x86)%\Microsoft SDKs\Windows\"); - if (!Directory.Exists(sdkPath)) - { - sdkPath = Environment.ExpandEnvironmentVariables(@"%ProgramFiles%\Microsoft SDKs\Windows\"); - } - - if (!Directory.Exists(sdkPath)) - { - throw new DirectoryNotFoundException("'Microsoft SDKs' directory not found"); - } - - // Get the version directories. - var sdkVersionDirectories = Directory.GetDirectories(sdkPath); - foreach (var sdkVersionDirectory in sdkVersionDirectories) - { - var binDirectory = Path.Combine(sdkVersionDirectory, @"bin"); - if (!Directory.Exists(binDirectory)) - { - continue; - } - - // Check for e.g. 'Microsoft SDKs\v8.0A\bin\ildasm.exe'. - var ildasmPath = Path.Combine(binDirectory, @"ildasm.exe"); - if (File.Exists(ildasmPath)) - { - return ildasmPath; - } - - // Check for e.g. 'Microsoft SDKs\v8.0A\bin\NETFX 4.0 Tools\ildasm.exe'. - var toolsDirectories = Directory.GetDirectories(binDirectory, "NETFX*Tools"); - foreach (var toolDirectory in toolsDirectories) - { - ildasmPath = Path.Combine(toolDirectory, @"ildasm.exe"); - if (File.Exists(ildasmPath)) - { - return ildasmPath; - } - } - } - - return null; - } - } -} diff --git a/Build/Installer/Header.bmp b/Build/Installer/Header.bmp deleted file mode 100644 index 9eb90fec4c57b21cb59f9c2a6e62c7de6a478ad1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10198 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�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 $LANGUAGE - ${AndIf} $NonDefaultLanguage != 1 - ; New install or better match - LangDLL::LangDialog "$(^SetupCaption)" "Please select the installer language.$\n$(SELECTLANGUAGE)" AC ${LANGDLL_PARAMS} "" - Pop $0 - ${If} $0 == "cancel" - Abort - ${EndIf} - - ${If} $0 <> $LANGUAGE - ; User selected non-default language - StrCpy $NonDefaultLanguage 1 - ${EndIf} - ${EndIf} - - StrCpy $LANGUAGE $0 - ${Else} - ${If} $0 != "" - StrCpy $LANGUAGE $0 - ${EndIf} - - ${GetParameters} $R1 - - ClearErrors - ${GetOptions} $R1 "/LANGUAGE=" $0 - ${IfNot} ${Errors} - ${If} $LANGUAGE != $0 - StrCpy $NonDefaultLanguage 1 - ${EndIf} - - StrCpy $LANGUAGE $0 - ${EndIf} - - ${GetOptions} $R1 "/STARTUP=" $0 - ${If} $0 = 1 - StrCpy $AutoStartup 1 - ${EndIf} - - ${GetOptions} $R1 "/PORTABLE=" $0 - ${If} $0 = 1 - StrCpy $InstallPortable 1 - ${Else} - ${IfNot} ${UAC_IsAdmin} - SetErrorLevel ${ERROR_NOTADMIN} - Quit - ${EndIf} - ${EndIf} - - ${GetOptions} $R1 "/VERSION=" $0 - ${If} $0 = 64 - StrCpy $Install64Bit 1 - - ${If} $INSTDIR == "" - StrCpy $INSTDIR "$PROGRAMFILES64\Rainmeter" - ${EndIf} - ${Else} - ${If} $INSTDIR == "" - StrCpy $INSTDIR "$PROGRAMFILES\Rainmeter" - ${EndIf} - ${EndIf} - - ClearErrors - CreateDirectory "$INSTDIR" - WriteINIStr "$INSTDIR\writetest~.rm" "1" "1" "1" - Delete "$INSTDIR\writetest~.rm" - - ${If} ${Errors} - RMDir "$INSTDIR" - SetErrorLevel ${ERROR_WRITEFAIL} - Quit - ${EndIf} - ${EndIf} - - ; If the language was set to a non-existent language, reset it back to English. - ${WordFind} ",${LANGUAGE_IDS}" ",$LANGUAGE," "E+1{" $0 - ${If} ${Errors} - StrCpy $LANGUAGE "1033" - ${EndIf} - ${Else} - ; Exchange settings with user instance - !insertmacro UAC_AsUser_Call Function ExchangeSettings ${UAC_SYNCREGISTERS} - StrCpy $AutoStartup $1 - StrCpy $Install64Bit $2 - StrCpy $NonDefaultLanguage $3 - StrCpy $LANGUAGE $4 - StrCpy $INSTDIR $5 - ${EndIf} -FunctionEnd - -Function ExchangeSettings - StrCpy $1 $AutoStartup - StrCpy $2 $Install64Bit - StrCpy $3 $NonDefaultLanguage - StrCpy $4 $LANGUAGE - StrCpy $5 $INSTDIR - HideWindow -FunctionEnd - -Function PageWelcome - ${If} ${UAC_IsInnerInstance} - ${If} ${UAC_IsAdmin} - ; Skip page - Abort - ${Else} - MessageBox MB_OK|MB_ICONSTOP "$(ADMINERROR) (Inner)" - Quit - ${EndIf} - ${EndIf} - - !insertmacro MUI_HEADER_TEXT "$(INSTALLOPTIONS)" "$(^ComponentsSubText1)" - nsDialogs::Create 1044 - Pop $0 - nsDialogs::SetRTL $(^RTL) - SetCtlColors $0 "" "${MUI_BGCOLOR}" - - ${NSD_CreateBitmap} 0u 0u 109u 193u "" - Pop $0 - ${NSD_SetImage} $0 "$PLUGINSDIR\modern-wizard.bmp" $R0 - - ${NSD_CreateLabel} 120u 10u 195u 38u "$(MUI_TEXT_WELCOME_INFO_TITLE)" - Pop $0 - SetCtlColors $0 "" "${MUI_BGCOLOR}" - CreateFont $1 "$(^Font)" "12" "700" - SendMessage $0 ${WM_SETFONT} $1 0 - - ${NSD_CreateLabel} 120u 55u 195u 12u "$(^ComponentsSubText1)" - Pop $0 - SetCtlColors $0 "" "${MUI_BGCOLOR}" - - ${NSD_CreateRadioButton} 120u 70u 205u 12u "$(STANDARDINST)" - Pop $R1 - SetCtlColors $R1 "" "${MUI_BGCOLOR}" - ${NSD_AddStyle} $R1 ${WS_GROUP} - SendMessage $R1 ${WM_SETFONT} $mui.Header.Text.Font 0 - - ${NSD_CreateLabel} 132u 82u 185u 24u "$(STANDARDINSTDESC)" - Pop $0 - SetCtlColors $0 "" "${MUI_BGCOLOR}" - - ${NSD_CreateRadioButton} 120u 106u 310u 12u "$(PORTABLEINST)" - Pop $R2 - SetCtlColors $R2 "" "${MUI_BGCOLOR}" - ${NSD_AddStyle} $R2 ${WS_TABSTOP} - SendMessage $R2 ${WM_SETFONT} $mui.Header.Text.Font 0 - - ${NSD_CreateLabel} 132u 118u 185u 52u "$(PORTABLEINSTDESC)" - Pop $0 - SetCtlColors $0 "" "${MUI_BGCOLOR}" - - ${If} $InstallPortable = 1 - ${NSD_Check} $R2 - ${Else} - ${NSD_Check} $R1 - ${EndIf} - - Call muiPageLoadFullWindow - - nsDialogs::Show - ${NSD_FreeImage} $R0 -FunctionEnd - -Function PageWelcomeOnLeave - ${NSD_GetState} $R2 $InstallPortable - Call muiPageUnloadFullWindow -FunctionEnd - -Function PageOptions - ${If} ${UAC_IsInnerInstance} - ${AndIf} ${UAC_IsAdmin} - ; Skip page - Abort - ${EndIf} - - !insertmacro MUI_HEADER_TEXT "$(INSTALLOPTIONS)" "$(INSTALLOPTIONSDESC)" - nsDialogs::Create 1018 - nsDialogs::SetRTL $(^RTL) - - ${NSD_CreateGroupBox} 0 0u -1u 36u "$(^DirSubText)" - - ${NSD_CreateDirRequest} 6u 14u 232u 14u "" - Pop $R0 - ${NSD_OnChange} $R0 PageOptionsDirectoryOnChange - - ${NSD_CreateBrowseButton} 242u 14u 50u 14u "$(^BrowseBtn)" - Pop $R1 - ${NSD_OnClick} $R1 PageOptionsBrowseOnClick - - StrCpy $1 0 - - StrCpy $R2 0 - ${If} ${RunningX64} - ${If} $InstallPortable = 1 - ${OrIf} $INSTDIR == "" - ${NSD_CreateCheckBox} 6u 54u 285u 12u "$(INSTALL64BIT)" - Pop $R2 - StrCpy $1 30u - ${EndIf} - ${EndIf} - - ${If} $InstallPortable <> 1 - ${If} $1 = 0 - StrCpy $0 54u - StrCpy $1 30u - ${Else} - StrCpy $0 66u - StrCpy $1 42u - ${EndIf} - - ${NSD_CreateCheckbox} 6u $0 285u 12u "$(AUTOSTARTUP)" - Pop $R3 - - ${If} $INSTDIR == "" - ${NSD_Check} $R3 - ${Else} - SetShellVarContext all - ${If} ${FileExists} "$SMSTARTUP\Rainmeter.lnk" - ${NSD_Check} $R3 - ${EndIf} - - SetShellVarContext current - ${If} ${FileExists} "$SMSTARTUP\Rainmeter.lnk" - ${NSD_Check} $R3 - ${EndIf} - ${EndIf} - ${Else} - StrCpy $R3 0 - ${EndIf} - - ${If} $1 <> 0 - ${NSD_CreateGroupBox} 0 42u -1u $1 "$(ADDITIONALOPTIONS)" - ${EndIf} - - ; Set default directory - ${If} $InstallPortable = 1 - ${GetRoot} "$WINDIR" $0 - ${NSD_SetText} $R0 "$0\Rainmeter" - ${Else} - ; Disable Directory editbox and Browse button if already installed - SendMessage $R0 ${EM_SETREADONLY} 1 0 - - ${If} $INSTDIR != "" - EnableWindow $R1 0 - ${NSD_SetText} $R0 "$INSTDIR" - ${Else} - ; Fresh install - ${If} ${RunningX64} - ${NSD_SetText} $R0 "$PROGRAMFILES64\Rainmeter" - ${NSD_Check} $R2 - ${Else} - ${NSD_SetText} $R0 "$PROGRAMFILES\Rainmeter" - ${EndIf} - ${EndIf} - ${EndIf} - - ; Show UAC shield on Install button if requiredd - GetDlgItem $0 $HWNDPARENT 1 - ${If} $InstallPortable = 1 - SendMessage $0 ${BCM_SETSHIELD} 0 0 - ${Else} - SendMessage $0 ${BCM_SETSHIELD} 0 1 - - ; Hide Back button - GetDlgItem $0 $HWNDPARENT 3 - ShowWindow $0 ${SW_HIDE} - ${EndIf} - - nsDialogs::Show -FunctionEnd - -Function PageOptionsDirectoryOnChange - ${NSD_GetText} $R0 $0 - - ; Disable Install button if not enough space - GetDlgItem $1 $HWNDPARENT 1 - ${GetRoot} $0 $2 - ${DriveSpace} "$2\" "/D=F /S=M" $3 - ${If} $3 < ${REQUIREDSPACE} - EnableWindow $1 0 - ${Else} - EnableWindow $1 1 - ${EndIf} - - StrCpy $Install64Bit 0 - ${If} ${RunningX64} - ${If} ${FileExists} "$0\Rainmeter.exe" - MoreInfo::GetProductVersion "$0\Rainmeter.exe" - Pop $0 - StrCpy $0 $0 2 -7 - ${If} $0 == 64 - StrCpy $Install64Bit 1 - ${EndIf} - - ${If} $R2 != 0 - ${NSD_SetState} $R2 $Install64Bit - EnableWindow $R2 0 - ${EndIf} - ${Else} - ${If} $R2 != 0 - EnableWindow $R2 1 - ${EndIf} - ${EndIf} - ${EndIf} -FunctionEnd - -Function PageOptionsBrowseOnClick - ${NSD_GetText} $R0 $0 - nsDialogs::SelectFolderDialog "$(^DirBrowseText)" $0 - Pop $1 - ${If} $1 != error - ${NSD_SetText} $R0 $1 - ${EndIf} -FunctionEnd - -Function PageOptionsOnLeave - ; Verify that selected folder is writable - ${NSD_GetText} $R0 $0 - ${If} $InstallPortable = 1 - ClearErrors - CreateDirectory "$0" - WriteINIStr "$0\writetest~.rm" "1" "1" "1" - Delete "$0\writetest~.rm" - - ${If} ${Errors} - RMDir "$0" - MessageBox MB_OK|MB_ICONEXCLAMATION "$(WRITEERROR)" - Abort - ${EndIf} - - RMDir "$0" - ${EndIf} - - StrCpy $INSTDIR $0 - - GetDlgItem $0 $HWNDPARENT 1 - EnableWindow $0 0 - - ${If} $R2 != 0 - ${NSD_GetState} $R2 $Install64Bit - ${EndIf} - - ${If} $R3 != 0 - ${NSD_GetState} $R3 $AutoStartup - ${EndIf} - - ${If} $InstallPortable <> 1 - ${IfNot} ${UAC_IsAdmin} - ; UAC_IsAdmin seems to return incorrect result sometimes. Recheck with UserInfo::GetAccountType to be sure. - UserInfo::GetAccountType - Pop $0 - ${If} $0 != "Admin" -UAC_TryAgain: - !insertmacro UAC_RunElevated - ${Switch} $0 - ${Case} 0 - ${IfThen} $1 = 1 ${|} Quit ${|} - ${IfThen} $3 <> 0 ${|} ${Break} ${|} - ${If} $1 = 3 - MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND "$(ADMINERROR)" /SD IDNO IDOK UAC_TryAgain IDNO 0 - ${EndIf} - ${Case} 1223 - Quit - ${Case} 1062 - MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND "$(LOGONERROR)" - Quit - ${Default} - MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND "$(UACERROR) ($0)" - Quit - ${EndSwitch} - ${EndIf} - ${EndIf} - ${EndIf} -FunctionEnd - -!macro InstallFiles DIR ARCH - SetOutPath "$INSTDIR" - File "..\..\${DIR}-Release\Rainmeter.exe" - File "..\..\${DIR}-Release\Rainmeter.dll" - File "..\..\${DIR}-Release\SkinInstaller.exe" - File "..\..\${DIR}-Release\SkinInstaller.dll" - - SetOutPath "$INSTDIR\Plugins" - File /x *Example*.dll "..\..\${DIR}-Release\Plugins\*.dll" - - SetOutPath "$INSTDIR\Runtime" - File "$%VS120COMNTOOLS%..\..\VC\redist\${ARCH}\Microsoft.VC120.CRT\msvcp120.dll" - File "$%VS120COMNTOOLS%..\..\VC\redist\${ARCH}\Microsoft.VC120.CRT\msvcr120.dll" -!macroend - -!macro RemoveStartMenuShortcuts STARTMENUPATH - Delete "${STARTMENUPATH}\Rainmeter.lnk" - Delete "${STARTMENUPATH}\Rainmeter Help.lnk" - Delete "${STARTMENUPATH}\Rainmeter Help.URL" - Delete "${STARTMENUPATH}\Remove Rainmeter.lnk" - Delete "${STARTMENUPATH}\RainThemes.lnk" - Delete "${STARTMENUPATH}\RainThemes Help.lnk" - Delete "${STARTMENUPATH}\RainBrowser.lnk" - Delete "${STARTMENUPATH}\RainBackup.lnk" - Delete "${STARTMENUPATH}\Rainstaller.lnk" - Delete "${STARTMENUPATH}\Skin Installer.lnk" - Delete "${STARTMENUPATH}\Rainstaller Help.lnk" - RMDir "${STARTMENUPATH}" -!macroend - -Section - SetOutPath "$PLUGINSDIR" - SetShellVarContext current - - Var /GLOBAL InstArc - ${If} $Install64Bit = 1 - StrCpy $InstArc "x64" - ${Else} - StrCpy $InstArc "x86" - ${EndIf} - - ${If} $InstallPortable <> 1 - ${AndIfNot} ${AtLeastWinVista} - ; Download and install .NET if required - ReadRegDWORD $0 HKLM "SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727" "Install" - ${If} $0 <> 1 - ${If} $Install64Bit <> 1 - NSISdl::download /TIMEOUT=30000 "http://download.microsoft.com/download/5/6/7/567758a3-759e-473e-bf8f-52154438565a/dotnetfx.exe" "$PLUGINSDIR\dotnetfx.exe" - ${Else} - NSISdl::download /TIMEOUT=30000 "http://download.microsoft.com/download/a/3/f/a3f1bf98-18f3-4036-9b68-8e6de530ce0a/NetFx64.exe" "$PLUGINSDIR\dotnetfx.exe" - ${EndIf} - Pop $0 - - ${If} $0 == "success" - ExecWait '"$PLUGINSDIR\dotnetfx.exe" /q:a /c:"install /q"' $0 - Delete "$PLUGINSDIR\dotnetfx.exe" - - ${If} $0 = 3010 - SetRebootFlag true - ${ElseIf} $0 <> 0 - MessageBox MB_OK|MB_ICONSTOP "$(DOTNETINSTERROR)" - Quit - ${EndIf} - ${ElseIf} $0 == "cancel" - Quit - ${Else} - MessageBox MB_OK|MB_ICONSTOP "$(DOTNETINSTERROR)" - Quit - ${EndIf} - ${EndIf} - ${EndIf} - - SetOutPath "$INSTDIR" - - ; Close Rainmeter (and wait up to five seconds) - ${ForEach} $0 10 0 - 1 - FindWindow $1 "DummyRainWClass" "Rainmeter control window" - ClearErrors - Delete "$INSTDIR\Rainmeter.exe" - ${If} $1 = 0 - ${AndIfNot} ${Errors} - ${Break} - ${EndIf} - - SendMessage $1 ${WM_CLOSE} 0 0 - - ${If} $0 = 0 - ${If} ${Silent} - SetErrorLevel ${ERROR_CLOSEFAIL} - Quit - ${Else} - MessageBox MB_RETRYCANCEL|MB_ICONSTOP "$(RAINMETERCLOSEERROR)" IDRETRY +2 - Quit - ${EndIf} - ${EndIf} - - Sleep 500 - ${Next} - - ; Move Rainmeter.ini to %APPDATA% if needed - ${IfNot} ${Silent} - ${AndIf} ${FileExists} "$INSTDIR\Rainmeter.ini" - ${If} $InstallPortable <> 1 - ${If} $Install64Bit = 1 - ${AndIf} "$INSTDIR" == "$PROGRAMFILES64\Rainmeter" - ${OrIf} "$INSTDIR" == "$PROGRAMFILES\Rainmeter" - MessageBox MB_YESNO|MB_ICONEXCLAMATION "$(SETTINGSFILEERROR)" IDNO SkipIniMove - StrCpy $0 1 - !insertmacro UAC_AsUser_Call Function CopyIniToAppData ${UAC_SYNCREGISTERS} - ${If} $0 = 1 - ; Copy succeeded - Delete "$INSTDIR\Rainmeter.ini" - ${Else} - MessageBox MB_OK|MB_ICONSTOP "$(SETTINGSMOVEERROR)" - ${EndIf} -SkipIniMove: - ${EndIf} - ${Else} - ReadINIStr $0 "$INSTDIR\Rainmeter.ini" "Rainmeter" "SkinPath" - ${If} $0 == "$INSTDIR\Skins\" - DeleteINIStr "$INSTDIR\Rainmeter.ini" "Rainmeter" "SkinPath" - ${EndIf} - ${EndIf} - ${EndIf} - - SetOutPath "$INSTDIR" - - ; Cleanup old stuff - Delete "$INSTDIR\Rainmeter.chm" - Delete "$INSTDIR\Default.ini" - Delete "$INSTDIR\Launcher.exe" - Delete "$INSTDIR\Defaults\Plugins\FileView.dll" - RMDir /r "$INSTDIR\Addons\Rainstaller" - RMDir /r "$INSTDIR\Addons\RainBackup" - - ${If} $InstallPortable <> 1 - CreateDirectory "$INSTDIR\Defaults" - Rename "$INSTDIR\Skins" "$INSTDIR\Defaults\Skins" - - Rename "$INSTDIR\Themes" "$INSTDIR\Defaults\Layouts" - Rename "$INSTDIR\Defaults\Themes" "$INSTDIR\Defaults\Layouts" - ${Locate} "$INSTDIR\Defaults\Layouts" "/L=F /M=Rainmeter.thm /G=1" "RenameToRainmeterIni" - - ${If} ${FileExists} "$INSTDIR\Addons\Backup" - ${OrIf} ${FileExists} "$INSTDIR\Plugins\Backup" - CreateDirectory "$INSTDIR\Defaults\Backup" - Rename "$INSTDIR\Addons\Backup" "$INSTDIR\Defaults\Backup\Addons" - Rename "$INSTDIR\Plugins\Backup" "$INSTDIR\Defaults\Backup\Plugins" - ${EndIf} - - Rename "$INSTDIR\Addons" "$INSTDIR\Defaults\Addons" - ${Locate} "$INSTDIR\Plugins" "/L=F /M=*.dll /G=0" "MoveNonDefaultPlugins" - ${EndIf} - -!ifdef INCLUDEFILES - File "..\..\Application\Rainmeter.exe.config" - - ${If} $instArc == "x86" - !insertmacro InstallFiles "x32" "x86" - ${Else} - !insertmacro InstallFiles "x64" "x64" - ${EndIf} - - RMDir /r "$INSTDIR\Languages" - SetOutPath "$INSTDIR\Languages" - File "..\..\x32-Release\Languages\*.*" - - SetOutPath "$INSTDIR\Defaults\Skins" - RMDir /r "$INSTDIR\Skins\illustro" - Delete "$INSTDIR\Skins\*.txt" - File /r "..\Skins\*.*" - - SetOutPath "$INSTDIR\Defaults\Layouts" - File /r "..\Layouts\*.*" -!endif - - SetOutPath "$INSTDIR" - - ${If} $InstallPortable <> 1 - ReadRegStr $0 HKLM "SOFTWARE\Rainmeter" "" - WriteRegStr HKLM "SOFTWARE\Rainmeter" "" "$INSTDIR" - WriteRegStr HKLM "SOFTWARE\Rainmeter" "Language" "$LANGUAGE" - WriteRegDWORD HKLM "SOFTWARE\Rainmeter" "NonDefault" $NonDefaultLanguage - - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rainmeter" "DisplayName" "Rainmeter" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rainmeter" "DisplayIcon" "$INSTDIR\Rainmeter.exe,0" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rainmeter" "URLInfoAbout" "http://rainmeter.net" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rainmeter" "UninstallString" "$INSTDIR\uninst.exe" - -!ifdef BETA - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rainmeter" "DisplayVersion" "${VERSION_SHORT} beta r${VERSION_REVISION}" -!else - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rainmeter" "DisplayVersion" "${VERSION_SHORT} r${VERSION_REVISION}" -!endif - - ; Create .rmskin association - WriteRegStr HKCR ".rmskin" "" "Rainmeter.SkinInstaller" - DeleteRegKey HKCR "Rainmeter skin" ; Old key - WriteRegStr HKCR "Rainmeter.SkinInstaller" "" "Rainmeter Skin Installer" - WriteRegStr HKCR "Rainmeter.SkinInstaller\shell" "" "open" - WriteRegStr HKCR "Rainmeter.SkinInstaller\DefaultIcon" "" "$INSTDIR\SkinInstaller.exe,0" - WriteRegStr HKCR "Rainmeter.SkinInstaller\shell\open\command" "" '"$INSTDIR\SkinInstaller.exe" %1' - WriteRegStr HKCR "Rainmeter.SkinInstaller\shell\edit" "" "Install Rainmeter skin" - WriteRegStr HKCR "Rainmeter.SkinInstaller\shell\edit\command" "" '"$INSTDIR\SkinInstaller.exe" %1' - - ; If .inc isn't associated, use the .ini association for it. - ReadRegStr $1 HKCR ".inc" "" - ${If} $1 == "" - ReadRegStr $1 HKCR ".ini" "" - ${If} $1 != "" - WriteRegStr HKCR ".inc" "" "$1" - ${EndIf} - ${EndIf} - - ; Refresh shell icons if new install - ${If} $0 == "" - ${RefreshShellIcons} - ${EndIf} - - ; Remove all start menu shortcuts - SetShellVarContext all - Call RemoveStartMenuShortcuts - - StrCpy $0 "$SMPROGRAMS\Rainmeter.lnk" - ${If} ${FileExists} "$SMPROGRAMS\Rainmeter" - StrCpy $0 "$SMPROGRAMS\Rainmeter\Rainmeter.lnk" - ${EndIf} - CreateShortcut "$0" "$INSTDIR\Rainmeter.exe" "" "$INSTDIR\Rainmeter.exe" 0 - - ${If} $AutoStartup = 1 - ${If} ${FileExists} "$SMSTARTUP\Rainmeter.lnk" - ; Remove user shortcut to prevent duplicate with all users shortcut - !insertmacro UAC_AsUser_Call Function RemoveUserStartupShortcut ${UAC_SYNCREGISTERS} - ${Else} - !insertmacro UAC_AsUser_Call Function CreateUserStartupShortcut ${UAC_SYNCREGISTERS} - ${EndIf} - ${EndIf} - - SetShellVarContext current - Call RemoveStartMenuShortcuts - - !insertmacro UAC_AsUser_Call Function RemoveStartMenuShortcuts ${UAC_SYNCREGISTERS} - - WriteUninstaller "$INSTDIR\uninst.exe" - ${Else} - ${IfNot} ${FileExists} "Rainmeter.ini" - CopyFiles /SILENT "$INSTDIR\Defaults\Layouts\illustro default\Rainmeter.ini" "$INSTDIR\Rainmeter.ini" - ${EndIf} - - WriteINIStr "$INSTDIR\Rainmeter.ini" "Rainmeter" "Language" "$LANGUAGE" - ${EndIf} -SectionEnd - -Function CopyIniToAppData - ClearErrors - CreateDirectory "$APPDATA\Rainmeter" - CopyFiles /SILENT "$INSTDIR\Rainmeter.ini" "$APPDATA\Rainmeter\Rainmeter.ini" - ${If} ${Errors} - StrCpy $0 0 - ${EndIf} -FunctionEnd - -Function RenameToRainmeterIni - ${If} ${FileExists} "$R8\Rainmeter.ini" - Delete "$R8\Rainmeter.thm" - ${Else} - Rename "$R9" "$R8\Rainmeter.ini" - ${EndIf} - - Push $0 -FunctionEnd - -Function MoveNonDefaultPlugins - ${If} $R7 != "AdvancedCPU.dll" - ${AndIf} $R7 != "CoreTemp.dll" - ${AndIf} $R7 != "FileView.dll" - ${AndIf} $R7 != "FolderInfo.dll" - ${AndIf} $R7 != "InputText.dll" - ${AndIf} $R7 != "iTunesPlugin.dll" - ${AndIf} $R7 != "MediaKey.dll" - ${AndIf} $R7 != "NowPlaying.dll" - ${AndIf} $R7 != "PerfMon.dll" - ${AndIf} $R7 != "PingPlugin.dll" - ${AndIf} $R7 != "PowerPlugin.dll" - ${AndIf} $R7 != "Process.dll" - ${AndIf} $R7 != "QuotePlugin.dll" - ${AndIf} $R7 != "RecycleManager.dll" - ${AndIf} $R7 != "ResMon.dll" - ${AndIf} $R7 != "SpeedFanPlugin.dll" - ${AndIf} $R7 != "SysInfo.dll" - ${AndIf} $R7 != "VirtualDesktops.dll" - ${AndIf} $R7 != "WebParser.dll" - ${AndIf} $R7 != "WifiStatus.dll" - ${AndIf} $R7 != "Win7AudioPlugin.dll" - ${AndIf} $R7 != "WindowMessagePlugin.dll" - CreateDirectory "$INSTDIR\Defaults\Plugins" - Delete "$INSTDIR\Defaults\Plugins\$R7" - Rename "$R9" "$INSTDIR\Defaults\Plugins\$R7" - ${EndIf} - - Push $0 -FunctionEnd - -Function RemoveStartMenuShortcuts - !insertmacro RemoveStartMenuShortcuts "$SMPROGRAMS\Rainmeter" -FunctionEnd - -Function CreateUserStartupShortcut - SetShellVarContext current - CreateShortcut "$SMSTARTUP\Rainmeter.lnk" "$INSTDIR\Rainmeter.exe" "" "$INSTDIR\Rainmeter.exe" 0 -FunctionEnd - -Function RemoveUserStartupShortcut - SetShellVarContext current - Delete "$SMSTARTUP\Rainmeter.lnk" -FunctionEnd - -Function FinishRun - !insertmacro UAC_AsUser_ExecShell "" "$INSTDIR\Rainmeter.exe" "" "" "" -FunctionEnd - - -; Uninstall -; -------------------------------------- -Function un.onInit -UAC_TryAgain: - ; Request administrative rights - !insertmacro UAC_RunElevated - ${Switch} $0 - ${Case} 0 - ${IfThen} $1 = 1 ${|} Quit ${|} - ${IfThen} $3 <> 0 ${|} ${Break} ${|} - ${If} $1 = 3 - MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND "$(ADMINERROR)" /SD IDNO IDOK UAC_TryAgain IDNO 0 - ${EndIf} - ${Case} 1223 - Quit - ${Case} 1062 - MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND "$(LOGONERROR)" - Quit - ${Default} - MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND "$(UACERROR) ($0)" - Quit - ${EndSwitch} - - ReadRegStr $0 HKLM "SOFTWARE\Rainmeter" "Language" - ${If} $0 != "" - StrCpy $LANGUAGE $0 - ${EndIf} -FunctionEnd - -Function un.PageOptions - !insertmacro MUI_HEADER_TEXT "$(UNSTALLOPTIONS)" "$(UNSTALLOPTIONSDESC)" - nsDialogs::Create 1018 - nsDialogs::SetRTL $(^RTL) - - ${NSD_CreateCheckbox} 0 0u 95% 12u "$(UNSTALLRAINMETER)" - Pop $0 - EnableWindow $0 0 - ${NSD_Check} $0 - - ${NSD_CreateCheckbox} 0 15u 70% 12u "$(UNSTALLSETTINGS)" - Pop $R0 - - ${NSD_CreateLabel} 16 26u 95% 12u "$(UNSTALLSETTINGSDESC)" - - nsDialogs::Show -FunctionEnd - -Function un.GetOptions - ${NSD_GetState} $R0 $un.DeleteAll -FunctionEnd - -Section Uninstall - ; Close Rainmeter (and wait up to five seconds) - ${ForEach} $0 10 0 - 1 - FindWindow $1 "DummyRainWClass" "Rainmeter control window" - ClearErrors - Delete "$INSTDIR\Rainmeter.exe" - ${If} $1 = 0 - ${AndIfNot} ${Errors} - ${Break} - ${EndIf} - - SendMessage $1 ${WM_CLOSE} 0 0 - - ${If} $0 = 0 - ${If} ${Silent} - SetErrorLevel ${ERROR_CLOSEFAIL} - Quit - ${Else} - MessageBox MB_RETRYCANCEL|MB_ICONSTOP "$(RAINMETERCLOSEERROR)" IDRETRY +2 - Quit - ${EndIf} - ${EndIf} - - Sleep 500 - ${Next} - - ; Old stuff - RMDir /r "$INSTDIR\Addons" - RMDir /r "$INSTDIR\Fonts" - - RMDir /r "$INSTDIR\Defaults" - RMDir /r "$INSTDIR\Languages" - RMDir /r "$INSTDIR\Plugins" - RMDir /r "$INSTDIR\Runtime" - RMDir /r "$INSTDIR\Skins" - Delete "$INSTDIR\Rainmeter.dll" - Delete "$INSTDIR\Rainmeter.exe" - Delete "$INSTDIR\Rainmeter.exe.config" - Delete "$INSTDIR\SkinInstaller.exe" - Delete "$INSTDIR\SkinInstaller.dll" - Delete "$INSTDIR\uninst.exe" - - RMDir "$INSTDIR" - - SetShellVarContext all - RMDir /r "$APPDATA\Rainstaller" - - SetShellVarContext current - Call un.RemoveShortcuts - ${If} $un.DeleteAll = 1 - RMDir /r "$APPDATA\Rainmeter" - RMDir /r "$DOCUMENTS\Rainmeter\Skins" - RMDir "$DOCUMENTS\Rainmeter" - RMDir /r "$1\Rainmeter" - ${EndIf} - - !insertmacro UAC_AsUser_Call Function un.RemoveShortcuts ${UAC_SYNCREGISTERS} - ${If} $un.DeleteAll = 1 - RMDir /r "$APPDATA\Rainmeter" - RMDir /r "$DOCUMENTS\Rainmeter\Skins" - RMDir "$DOCUMENTS\Rainmeter" - ${EndIf} - - SetShellVarContext all - Call un.RemoveShortcuts - Delete "$SMPROGRAMS\Rainmeter.lnk" - - DeleteRegKey HKLM "SOFTWARE\Rainmeter" - DeleteRegKey HKCR ".rmskin" - DeleteRegKey HKCR "Rainmeter.SkinInstaller" - DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Rainmeter" - ${RefreshShellIcons} -SectionEnd - -Function un.RemoveShortcuts - !insertmacro RemoveStartMenuShortcuts "$SMPROGRAMS\Rainmeter" - Delete "$SMSTARTUP\Rainmeter.lnk" - Delete "$DESKTOP\Rainmeter.lnk" -FunctionEnd diff --git a/Build/Installer/MD5.dll b/Build/Installer/MD5.dll deleted file mode 100644 index bde153f702f0d6c251d2b7ad7787fe950fd1725f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6656 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 X=Oue{UGoji?&hWZ^7#tB^a%VDdaRno diff --git a/Build/Installer/UAC.dll b/Build/Installer/UAC.dll deleted file mode 100644 index ccaa050e4cc877ef660d14c08fe9719ac8d8ae7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13312 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 bs-t#~0=CK8r9Dzdcj2Kd29TsZ&WHa$RDxLd diff --git a/Build/Layouts/illustro default/Rainmeter.ini b/Build/Layouts/illustro default/Rainmeter.ini deleted file mode 100644 index 1b9c400e..00000000 --- a/Build/Layouts/illustro default/Rainmeter.ini +++ /dev/null @@ -1,23 +0,0 @@ -[Rainmeter] - -[illustro\Clock] -Active=1 -WindowX=(#SCREENAREAWIDTH#-200) -WindowY=0 - -[illustro\Disk] -Active=2 -WindowX=(#SCREENAREAWIDTH#-200) -WindowY=176 - -[illustro\System] -Active=1 -WindowX=(#SCREENAREAWIDTH#-200) -WindowY=68 - -[illustro\Welcome] -Active=1 -WindowX=50.000000% -WindowY=50.000000% -AnchorX=50.000000% -AnchorY=50.000000% \ No newline at end of file diff --git a/Build/Skins/illustro/@Resources/Background.png b/Build/Skins/illustro/@Resources/Background.png deleted file mode 100644 index 1aa0d7d031147f3f1c1d35b6da3e8319882dabf8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1986 zcmcIl`8(TL7ym{|N+U0^?@A_!5L;@g+8UK$jH0AyD=kvqQLzt$SY9erh>UG)t+Dql ziCQ~-N=YdRYFA5XZ9}D|V=bngOrLq)|KR=Mob#OXeD1mDo^$W#(p+5}#KjcF000mt z;BjsOJ0=j^X%T_mt@*dIztv?nK@4*XQJ$l>taOWYgE>)jyslq{pk51SahX|_WJR=0%n2xWeYyJ zuu{Q90&KuPOphwMn}FyQ=EOC*W~`t}w0`%8^?)RiB=e9BHbPGaL*9B)sW71nw&JqH zmszkKRu0%jTZ<_*_@UvtuhK_#-Y+$5Mrx$PJA*1Kr`hmfBfkNhLQ6$vplcJ*NNjK9yHTdW%2SiH%e+1~%sBt3M0R3W2(nc97_wYAlrX7|<; z$?TNCO7s8YY?h+?a^*zl#)FzV-Kpej(YeNW|H2!J3Ac}qcYA)<7ioUI)$}Po(UO5L z&GD}+Ca%5B?BeKVt+?p3s@|8ElqfYLB>iGyp=Xw?$y+YVjM5cZOw!7J~fvN`Mb4(m8TsB=&ToB;JuU>z`3Ut8WG z&S-r^>NPI$lr+Nn=;w`}avz>`L>RgT_yq*4vWIT*!WA4eyeMl$`1qCQavP25+6<0O ze)93bHZ^3YE zQ3n9Sb-E=c@xcfhf-!*y$>-uh>2;UfGzkb=)g`g+B%GK54x6V)&>$eNZh#2FE$M87 z0QkkBN)wD9g>sS%)ftEs-06Rik3Eraf<`?<$UvPT1ihSHbtw-ICuB?iQxyW6_y4R) z4FzB1@x01*9<71r=H}ubc3vMa0UJsfx@t?S7E76;HNOtE|Jh`zQZ1Um?Oa$`I1eXa z5Q4dPZ*FdaOZua@26SBGlJmEWI6i%MYHG@hP25To(JAKGa4$PJ^q=vWl?jo(%C%Q! zFNtZi`plwNsU2Zs;j?32sC=stf1?rX-&e((E&_p22Uo+h&SgC;*!jAx48xn>C+akx z$0}7(Q&VfjzIE~ODVcgXtA)ja%~&lhyWji!`}fTIQB5*58M@)aih{u~(QC0oiQ&mYbb3ZV2AyQKFl^Q$#yc`g;UJxU{w(mG0_Z`O$mA!YiL=SdS zpBAxstDr={(g3vE$hr62yH0@9*@9R#l%1%JKwhxoMPgv`G< z7N~oB>d11o-#3soah*2{FFblM9)hI--C@x2|Iv0wl2pfA%m$sd;@@L1?d&1<-Uhm& zKJ)U}`NHV)PiBlWU9N%y=YuK&ILTqeyRkF ztuTI9sQt6;F9yIkJyZbIlF&aCAjLjRJneuS9wT8kW<|_1&re^e6)^X3(sFSHJ)-|l yD*U&ohw%?iYQkGOq3rMy#V7uxH$9X{Q8VEI_b#!8O|XrThi@(S(iw diff --git a/Build/Skins/illustro/Clock/Clock.ini b/Build/Skins/illustro/Clock/Clock.ini deleted file mode 100644 index 64bda3da..00000000 --- a/Build/Skins/illustro/Clock/Clock.ini +++ /dev/null @@ -1,138 +0,0 @@ -; Lines starting ; (semicolons) are commented out. -; That is, they do not affect the code and are here for demonstration purposes only. -; ---------------------------------- - -[Rainmeter] -; This section contains general settings that can be used to change how Rainmeter behaves. -Author=poiru -AppVersion=2003000 -Update=1000 -Background=#@#Background.png -; #@# is equal to Rainmeter\Skins\illustro\@Resources -BackgroundMode=3 -BackgroundMargins=0,34,0,14 - -[Metadata] -; Contains basic information of the skin. -Description=Displays the current date and time. -License=Creative Commons BY-NC-SA 3.0 -Version=1.0.0 - -[Variables] -; Variables declared here can be used later on between two # characters (e.g. #MyVariable#). -fontName=Trebuchet MS -textSize=8 -colorBar=235,170,0,255 -colorText=255,255,255,205 - -; ---------------------------------- -; MEASURES return some kind of value -; ---------------------------------- - -[measureTime] -; This measure returns the time in a 24-hour format (i.e. HH:MM). -Measure=Time -Format=%H:%M -; For a 12-hour clock, change the Format option above to: %I:%M %p -; Refer to the Rainmeter manual for other format codes. - -[measureDate] -; Returns the date as DD.MM.YYYY -Measure=Time -Format=%d.%m.%Y - -[measureDay] -; Returns the current day -Measure=Time -Format=%A - -; ---------------------------------- -; STYLES are used to "centralize" options -; ---------------------------------- - -[styleTitle] -StringAlign=CENTER -StringCase=UPPER -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,50 -FontColor=#colorText# -FontFace=#fontName# -FontSize=10 -AntiAlias=1 -ClipString=1 - -[styleLeftText] -StringAlign=LEFT -; Meters using styleLeftText will be left-aligned. -StringCase=NONE -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,20 -FontColor=#colorText# -FontFace=#fontName# -FontSize=#textSize# -AntiAlias=1 -ClipString=1 - -[styleRightText] -StringAlign=RIGHT -StringCase=NONE -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,20 -FontColor=#colorText# -FontFace=#fontName# -FontSize=#textSize# -AntiAlias=1 -ClipString=1 - -[styleSeperator] -SolidColor=255,255,255,15 - -; ---------------------------------- -; METERS display images, text, bars, etc. -; ---------------------------------- - -[meterTitle] -Meter=STRING -MeterStyle=styleTitle -; Using MeterStyle=styleTitle will basically "copy" the -; contents of the [styleTitle] section here during runtime. -MeasureName=measureTime -X=100 -Y=12 -W=190 -H=18 -Text="%1" -; %1 stands for the value of MeasureName (measureTime in this case). - -[meterDay] -Meter=STRING -MeterStyle=styleLeftText -MeasureName=measureDay -X=10 -Y=40 -W=190 -H=14 -Text="%1" - -[meterDate] -Meter=STRING -MeterStyle=styleRightText -MeasureName=measureDate -X=200 -Y=0r -; r stands for relative. In this case, the Y postition of meterValueCPU is 0 pixels -; below the Y value of the previous meter (i.e it's the same as in meterLabelCPU). -W=190 -H=14 -Text="%1" - -[meterSeperator] -Meter=IMAGE -MeterStyle=styleSeperator -X=10 -Y=52 -W=190 -H=1 \ No newline at end of file diff --git a/Build/Skins/illustro/Disk/1 Disk.ini b/Build/Skins/illustro/Disk/1 Disk.ini deleted file mode 100644 index 40deafc4..00000000 --- a/Build/Skins/illustro/Disk/1 Disk.ini +++ /dev/null @@ -1,149 +0,0 @@ -; Lines starting ; (semicolons) are commented out. -; That is, they do not affect the code and are here for demonstration purposes only. -; ---------------------------------- - -; NOTE! If you want to add more disks, take a look at 'Disks 2.ini'. - -[Rainmeter] -; This section contains general settings that can be used to change how Rainmeter behaves. -Author=poiru -AppVersion=2003000 -Update=1000 -Background=#@#Background.png -; #@# is equal to Rainmeter\Skins\illustro\@Resources -BackgroundMode=3 -BackgroundMargins=0,34,0,14 - -[Metadata] -; Contains basic information of the skin. -Description=Displays disk usage. -License=Creative Commons BY-NC-SA 3.0 -Version=1.0.0 - -[Variables] -; Variables declared here can be used later on between two # characters (e.g. #MyVariable#). -fontName=Trebuchet MS -textSize=8 -colorBar=235,170,0,255 -colorText=255,255,255,205 -disk1=C: - -; ---------------------------------- -; MEASURES return some kind of value -; ---------------------------------- - -[measureTotalDisk1] -; This measure returns the total disk space -Measure=FreeDiskSpace -Drive=#disk1# -Total=1 -UpdateDivider=120 - -[measureUsedDisk1] -; Returns inverted value of free disk space (i.e. used disk space) -Measure=FreeDiskSpace -Drive=#disk1# -InvertMeasure=1 -UpdateDivider=120 - -; ---------------------------------- -; STYLES are used to "centralize" options -; ---------------------------------- - -[styleTitle] -StringAlign=CENTER -StringCase=UPPER -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,50 -FontColor=#colorText# -FontFace=#fontName# -FontSize=10 -AntiAlias=1 -ClipString=1 - -[styleLeftText] -StringAlign=LEFT -; Meters using styleLeftText will be left-aligned. -StringCase=NONE -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,20 -FontColor=#colorText# -FontFace=#fontName# -FontSize=#textSize# -AntiAlias=1 -ClipString=1 - -[styleRightText] -StringAlign=RIGHT -StringCase=NONE -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,20 -FontColor=#colorText# -FontFace=#fontName# -FontSize=#textSize# -AntiAlias=1 -ClipString=1 - -[styleBar] -BarColor=#colorBar# -BarOrientation=HORIZONTAL -SolidColor=255,255,255,15 - -; ---------------------------------- -; METERS display images, text, bars, etc. -; ---------------------------------- - -[meterTitle] -Meter=STRING -MeterStyle=styleTitle -; Using MeterStyle=styleTitle will basically "copy" the -; contents of the [styleTitle] section here during runtime. -X=100 -Y=12 -W=190 -H=18 -Text="Disks" -; Even though the text is set to Disks, Rainmeter will display -; it as DISKS, because styleTitle contains StringCase=UPPER. - -[meterLabelDisk1] -Meter=STRING -MeterStyle=styleLeftText -X=10 -Y=40 -W=190 -H=14 -Text="#disk1#\" - -[meterValueDisk1] -Meter=STRING -MeterStyle=styleRightText -MeasureName=measureUsedDisk1 -MeasureName2=measureTotalDisk1 -X=200 -Y=0r -; r stands for relative. In this case, the Y postition of meterValueCPU is 0 pixels -; below the Y value of the previous meter (i.e it's the same as in meterLabelCPU). -W=190 -H=14 -Text="%1B/%2B used" -; %1 stands for the value of MeasureName (measureUsedDisk1 in this case). -; %2 stands for the value of MeasureName2. -NumOfDecimals=1 -AutoScale=1 -; Because disk measures return the free/used space in bytes, we must use AutoScale=1 to -; automatically scale the value into a more readable figure. -LeftMouseUpAction=!Execute ["#disk1#\"] -; Open #disk1# on click - -[meterBarDisk1] -Meter=BAR -MeterStyle=styleBar -MeasureName=measureUsedDisk1 -X=10 -Y=52 -W=190 -H=1 \ No newline at end of file diff --git a/Build/Skins/illustro/Disk/2 Disks.ini b/Build/Skins/illustro/Disk/2 Disks.ini deleted file mode 100644 index 78079f21..00000000 --- a/Build/Skins/illustro/Disk/2 Disks.ini +++ /dev/null @@ -1,209 +0,0 @@ -; Lines starting ; (semicolons) are commented out. -; That is, they do not affect the code and are here for demonstration purposes only. -; ---------------------------------- - -; HOWTO: Adding more disks -; ---------------------------------- -; Adding more disks is a pretty straightforward process. Follow the following steps to turn -; this 2 disks skin into a 3 disks skin. You can then extend it even further as you wish. -; -; 1) Create a new variable called disk3=X: directly below disk2=D: in the [Variables] section -; 2) Create a copy of the [measureTotalDisk2] and [measureUsedDisk2] sections -; 3) Rename the copied sections to [measureTotalDisk3] and [measureUsedDisk3], respectively. -; Also change Drive=#disk2# to Drive=#disk3# -; 4) Create a copy of the [meterLabelDisk2], [meterValueDisk2], and [meterBarDisk2]. -; Rename all Disk2's in the copied sections to Disk3. -; 5) Now we need to change the Y= values to adjust height. Change Y= under [meterLabelDisk3] -; to Y=80 (calculated by adding 20 to the Y= value of previous meterLabel). -; Then change Y= under [meterBarDisk3] to Y=92 (calculated by adding 20 to the Y= value of previous meterBar). -; 6) Save the file as '3 Disks.ini'. Now right-click on the Rainmeter tray icon and select -; 'Refresh All'. Now go activate the '3 Disks.ini' skin and enjoy! :) - -[Rainmeter] -; This section contains general settings that can be used to change how Rainmeter behaves. -Author=poiru -AppVersion=2003000 -Update=1000 -Background=#@#Background.png -; #@# is equal to Rainmeter\Skins\illustro\@Resources -BackgroundMode=3 -BackgroundMargins=0,34,0,14 - -[Metadata] -; Contains basic information of the skin. -Description=Displays disk usage. -License=Creative Commons BY-NC-SA 3.0 -Version=1.0.0 - -[Variables] -; Variables declared here can be used later on between two # characters (e.g. #MyVariable#). -fontName=Trebuchet MS -textSize=8 -colorBar=235,170,0,255 -colorText=255,255,255,205 -disk1=C: -disk2=D: - -; ---------------------------------- -; MEASURES return some kind of value -; ---------------------------------- - -[measureTotalDisk1] -; This measure returns the total disk space -Measure=FreeDiskSpace -Drive=#disk1# -Total=1 -UpdateDivider=120 - -[measureUsedDisk1] -; Returns inverted value of free disk space (i.e. used disk space) -Measure=FreeDiskSpace -Drive=#disk1# -InvertMeasure=1 -UpdateDivider=120 - -[measureTotalDisk2] -Measure=FreeDiskSpace -Drive=#disk2# -Total=1 -UpdateDivider=120 - -[measureUsedDisk2] -Measure=FreeDiskSpace -Drive=#disk2# -InvertMeasure=1 -UpdateDivider=120 - -; ---------------------------------- -; STYLES are used to "centralize" options -; ---------------------------------- - -[styleTitle] -StringAlign=CENTER -StringCase=UPPER -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,50 -FontColor=#colorText# -FontFace=#fontName# -FontSize=10 -AntiAlias=1 -ClipString=1 - -[styleLeftText] -StringAlign=LEFT -; Meters using styleLeftText will be left-aligned. -StringCase=NONE -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,20 -FontColor=#colorText# -FontFace=#fontName# -FontSize=#textSize# -AntiAlias=1 -ClipString=1 - -[styleRightText] -StringAlign=RIGHT -StringCase=NONE -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,20 -FontColor=#colorText# -FontFace=#fontName# -FontSize=#textSize# -AntiAlias=1 -ClipString=1 - -[styleBar] -BarColor=#colorBar# -BarOrientation=HORIZONTAL -SolidColor=255,255,255,15 - -; ---------------------------------- -; METERS display images, text, bars, etc. -; ---------------------------------- - -[meterTitle] -Meter=STRING -MeterStyle=styleTitle -; Using MeterStyle=styleTitle will basically "copy" the -; contents of the [styleTitle] section here during runtime. -X=100 -Y=12 -W=190 -H=18 -Text="Disk" -; Even though the text is set to Disk, Rainmeter will display -; it as DISK, because styleTitle contains StringCase=UPPER. - -[meterLabelDisk1] -Meter=STRING -MeterStyle=styleLeftText -X=10 -Y=40 -W=190 -H=14 -Text="#disk1#\" - -[meterValueDisk1] -Meter=STRING -MeterStyle=styleRightText -MeasureName=measureUsedDisk1 -MeasureName2=measureTotalDisk1 -X=200 -Y=0r -; r stands for relative. In this case, the Y postition of meterValueCPU is 0 pixels -; below the Y value of the previous meter (i.e it's the same as in meterLabelCPU). -W=190 -H=14 -Text="%1B/%2B used" -; %1 stands for the value of MeasureName (measureUsedDisk1 in this case). -; %2 stands for the value of MeasureName2. -NumOfDecimals=1 -AutoScale=1 -; Because disk measures return the free/used space in bytes, we must use AutoScale=1 to -; automatically scale the value into a more readable figure. -LeftMouseUpAction=!Execute ["#disk1#\"] -; Open #disk1# on click - -[meterBarDisk1] -Meter=BAR -MeterStyle=styleBar -MeasureName=measureUsedDisk1 -X=10 -Y=52 -W=190 -H=1 - -[meterLabelDisk2] -Meter=STRING -MeterStyle=styleLeftText -X=10 -Y=60 -W=190 -H=14 -Text="#disk2#\" -LeftMouseUpAction=!Execute ["#disk2#\"] - -[meterValueDisk2] -Meter=STRING -MeterStyle=styleRightText -MeasureName=measureUsedDisk2 -MeasureName2=measureTotalDisk2 -X=200 -Y=0r -W=190 -H=14 -Text="%1B/%2B used" -NumOfDecimals=1 -AutoScale=1 - -[meterBarDisk2] -Meter=BAR -MeterStyle=styleBar -MeasureName=measureUsedDisk2 -X=10 -Y=72 -W=190 -H=1 \ No newline at end of file diff --git a/Build/Skins/illustro/Google/Google.ini b/Build/Skins/illustro/Google/Google.ini deleted file mode 100644 index 2cf7dc04..00000000 --- a/Build/Skins/illustro/Google/Google.ini +++ /dev/null @@ -1,119 +0,0 @@ -; Lines starting ; (semicolons) are commented out. -; That is, they do not affect the code and are here for demonstration purposes only. -; ---------------------------------- - -[Rainmeter] -; This section contains general settings that can be used to change how Rainmeter behaves. -Author=poiru -AppVersion=2003000 -Update=1000 -Background=#@#Background.png -; #@# is equal to Rainmeter\Skins\illustro\@Resources -BackgroundMode=3 -BackgroundMargins=0,34,0,14 - -[Metadata] -; Contains basic information of the skin. -Description=Allows searching through Google. -License=Creative Commons BY-NC-SA 3.0 -Version=1.0.0 - -[Variables] -; Variables declared here can be used later on between two # characters (e.g. #MyVariable#). -fontName=Trebuchet MS -textSize=8 -colorBar=235,170,0,255 -colorText=255,255,255,205 - -; ---------------------------------- -; MEASURES return some kind of value -; ---------------------------------- - -[measureInput] -; The InputText.dll plugin has special powers: it allows user input. -; However, it's not the easiest way to start learning Rainmeter. Get a -; hold of the basics, and then check out the manual entry for InputText. -Measure=Plugin -Plugin=InputText.dll -SolidColor=20,20,20,255 -StringAlign=LEFT -StringCase=NONE -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,20 -FontColor=#colorText# -FontFace=#fontName# -FontSize=#textSize# -X=10 -Y=38 -W=188 -H=17 -FocusDismiss=1 -DefaultValue="" -Command1=!Execute ["http://www.google.com/search?q=$UserInput$"] -UpdateDivider=86400 - -; ---------------------------------- -; STYLES are used to "centralize" options -; ---------------------------------- - -[styleTitle] -StringAlign=CENTER -StringCase=UPPER -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,50 -FontColor=#colorText# -FontFace=#fontName# -FontSize=10 -AntiAlias=1 -ClipString=1 - -[styleLeftText] -StringAlign=LEFT -; Meters using styleLeftText will be left-aligned. -StringCase=NONE -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,20 -FontColor=#colorText# -FontFace=#fontName# -FontSize=#textSize# -AntiAlias=1 -ClipString=1 - -[styleSeperator] -SolidColor=255,255,255,15 - -; ---------------------------------- -; METERS display images, text, bars, etc. -; ---------------------------------- - -[meterTitle] -Meter=STRING -MeterStyle=styleTitle -; Using MeterStyle=styleTitle will basically "copy" the -; contents of the [styleTitle] section here during runtime. -X=100 -Y=12 -W=190 -H=18 -Text="Google" - -[meterSearch] -Meter=STRING -MeterStyle=styleLeftText -X=10 -Y=40 -W=190 -H=14 -Text="Search..." -LeftMouseUpAction=!PluginBang "measureInput ExecuteBatch 1" - -[meterSeperator] -Meter=IMAGE -MeterStyle=styleSeperator -X=10 -Y=52 -W=190 -H=1 \ No newline at end of file diff --git a/Build/Skins/illustro/Network/Network.ini b/Build/Skins/illustro/Network/Network.ini deleted file mode 100644 index 3669c330..00000000 --- a/Build/Skins/illustro/Network/Network.ini +++ /dev/null @@ -1,215 +0,0 @@ -; Lines starting ; (semicolons) are commented out. -; That is, they do not affect the code and are here for demonstration purposes only. -; ---------------------------------- - -[Rainmeter] -; This section contains general settings that can be used to change how Rainmeter behaves. -Author=poiru -AppVersion=2003000 -Update=1000 -Background=#@#Background.png -; #@# is equal to Rainmeter\Skins\illustro\@Resources -BackgroundMode=3 -BackgroundMargins=0,34,0,14 - -[Metadata] -; Contains basic information of the skin. -Description=Shows your IP address and network activity. -License=Creative Commons BY-NC-SA 3.0 -Version=1.0.0 - -[Variables] -; Variables declared here can be used later on between two # characters (e.g. #MyVariable#). -fontName=Trebuchet MS -textSize=8 -colorBar=235,170,0,255 -colorText=255,255,255,205 -maxDownload=10485760 -MaxUpload=10485760 -; Set maxDownload and maxUpload to your maximum download and upload speed in bits. -; To convert kilobits, megabits, kilobytes, and megabytes into bits, go to www.google.com -; and search for something like "10 megabytes in bits". - -; ---------------------------------- -; MEASURES return some kind of value -; ---------------------------------- - -[measureIP] -; This measure returns your IP. WebParser measures are relatively complicated. If you're a beginner with -; Rainmeter, take a look at some of the other illustro skins before modifying this one. -Measure=Plugin -Plugin=WebParser.dll -Url=http://checkip.dyndns.org -UpdateRate=14400 -RegExp="(?siU)Address: (.*)" -StringIndex=1 -Substitute="":"N/A" -; Substitute works as follows: "A":"B" where A is a string to substitute and B is a string -; to substitute with. In this case, it substutes "" (i.e. empty) to N/A - -[measureNetIn] -Measure=NetIn -NetInSpeed=#maxDownload# -; NetInSpeed must be set so your maximun download speed for the download bar to scale correctly - -[measureNetOut] -Measure=NetOut -NetOutSpeed=#maxUpload# - -; ---------------------------------- -; STYLES are used to "centralize" options -; ---------------------------------- - -[styleTitle] -StringAlign=CENTER -StringCase=UPPER -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,50 -FontColor=#colorText# -FontFace=#fontName# -FontSize=10 -AntiAlias=1 -ClipString=1 - -[styleLeftText] -StringAlign=LEFT -; Meters using styleLeftText will be left-aligned. -StringCase=NONE -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,20 -FontColor=#colorText# -FontFace=#fontName# -FontSize=#textSize# -AntiAlias=1 -ClipString=1 - -[styleRightText] -StringAlign=RIGHT -StringCase=NONE -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,20 -FontColor=#colorText# -FontFace=#fontName# -FontSize=#textSize# -AntiAlias=1 -ClipString=1 - -[styleBar] -BarColor=#colorBar# -BarOrientation=HORIZONTAL -SolidColor=255,255,255,15 - -[styleSeperator] -SolidColor=255,255,255,15 - -; ---------------------------------- -; METERS display images, text, bars, etc. -; ---------------------------------- - -[meterTitle] -Meter=STRING -MeterStyle=styleTitle -; Using MeterStyle=styleTitle will basically "copy" the -; contents of the [styleTitle] section here during runtime. -X=100 -Y=12 -W=190 -H=18 -Text="Network" -; Even though the text is set to Network, Rainmeter will display -; it as NETWORK, because styleTitle contains StringCase=UPPER. - -[meterIPLabel] -Meter=STRING -MeterStyle=styleLeftText -X=10 -Y=40 -W=190 -H=14 -Text="IP Address" - -[meterIPValue] -Meter=STRING -MeterStyle=styleRightText -MeasureName=measureIP -X=200 -Y=0r -; r stands for relative. In this case, the Y postition of meterValueCPU is 0 pixels -; below the Y value of the previous meter (i.e it's the same as in meterLabelCPU). -W=190 -H=14 -Text="%1" -; %1 stands for the value of MeasureName (measureIP in this case). - -[meterSeperator] -Meter=IMAGE -MeterStyle=styleSeperator -X=10 -Y=52 -W=190 -H=1 - -[meterUploadLabel] -Meter=STRING -MeterStyle=styleLeftText -X=10 -Y=60 -W=190 -H=14 -Text="Upload" - -[meterUploadValue] -Meter=STRING -MeterStyle=styleRightText -MeasureName=measureNetOut -X=200 -Y=0r -W=190 -H=14 -Text="%1B/s" -NumOfDecimals=1 -AutoScale=1 -; Because measureIP returns the current upload speed in bytes, we must use AutoScale=1 to -; automatically scale the value into a more readable figure. - -[meterUploadBar] -Meter=BAR -MeterStyle=styleBar -MeasureName=measureNetOut -X=10 -Y=72 -W=190 -H=1 - -[meterDownloadLabel] -Meter=STRING -MeterStyle=styleLeftText -X=10 -Y=80 -W=190 -H=14 -Text="Download" - -[meterDownloadValue] -Meter=STRING -MeterStyle=styleRightText -MeasureName=measureNetIn -X=200 -Y=0r -W=190 -H=14 -Text="%1B/s" -NumOfDecimals=1 -AutoScale=1 - -[meterDownloadBar] -Meter=BAR -MeterStyle=styleBar -MeasureName=measureNetIn -X=10 -Y=92 -W=190 -H=1 \ No newline at end of file diff --git a/Build/Skins/illustro/Recycle Bin/Recycle Bin.ini b/Build/Skins/illustro/Recycle Bin/Recycle Bin.ini deleted file mode 100644 index 1ecbd933..00000000 --- a/Build/Skins/illustro/Recycle Bin/Recycle Bin.ini +++ /dev/null @@ -1,147 +0,0 @@ -; Lines starting ; (semicolons) are commented out. -; That is, they do not affect the code and are here for demonstration purposes only. -; ---------------------------------- - -[Rainmeter] -; This section contains general settings that can be used to change how Rainmeter behaves. -Author=poiru -AppVersion=2003000 -Update=1000 -Background=#@#Background.png -; #@# is equal to Rainmeter\Skins\illustro\@Resources -BackgroundMode=3 -BackgroundMargins=0,34,0,14 - -[Metadata] -; Contains basic information of the skin. -Description=Shows the state and size of your Recycle Bin. -License=Creative Commons BY-NC-SA 3.0 -Version=1.0.0 - -[Variables] -; Variables declared here can be used later on between two # characters (e.g. #MyVariable#). -fontName=Trebuchet MS -textSize=8 -colorBar=235,170,0,255 -colorText=255,255,255,205 - -; ---------------------------------- -; MEASURES return some kind of value -; ---------------------------------- - -[measureBinItems] -; This measure returns the amount of items in the Recycle Bin. -Measure=Plugin -Plugin=RecycleManager.dll -RecycleType=COUNT -UpdateDivider=3 -; UpdateDivider sets the rate at which the value of the measure is updated. It is -; calculated as follows: UpdateDivider x Update. In this case, Update is set to -; 1000 milliseconds (in the [Rainmeter] section). 1000 x 3 = 3000 ms or 3 seconds. - -[measureBinSize] -; Returns the total size of the Recycle Bin in bytes. -Measure=Plugin -Plugin=RecycleManager.dll -RecycleType=SIZE -UpdateDivider=3 - -; ---------------------------------- -; STYLES are used to "centralize" options -; ---------------------------------- - -[styleTitle] -StringAlign=CENTER -StringCase=UPPER -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,50 -FontColor=#colorText# -FontFace=#fontName# -FontSize=10 -AntiAlias=1 -ClipString=1 - -[styleLeftText] -StringAlign=LEFT -; Meters using styleLeftText will be left-aligned. -StringCase=NONE -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,20 -FontColor=#colorText# -FontFace=#fontName# -FontSize=#textSize# -AntiAlias=1 -ClipString=1 - -[styleRightText] -StringAlign=RIGHT -StringCase=NONE -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,20 -FontColor=#colorText# -FontFace=#fontName# -FontSize=#textSize# -AntiAlias=1 -ClipString=1 - -[styleSeperator] -SolidColor=255,255,255,15 - -; ---------------------------------- -; METERS display images, text, bars, etc. -; ---------------------------------- - -[meterTitle] -Meter=STRING -MeterStyle=styleTitle -; Using MeterStyle=styleTitle will basically "copy" the -; contents of the [styleTitle] section here during runtime. -X=100 -Y=12 -W=190 -H=18 -Text="Recycle Bin" -; Even though the text is set to Recycle Bin, Rainmeter will display -; it as RECYCLE BIN, because styleTitle contains StringCase=UPPER. -LeftMouseUpAction=!Execute [!PluginBang "measureBinItems OpenBin"] -RightMouseUpAction=!Execute [!PluginBang "measureBinItems EmptyBin"] -ToolTipText="Left-click to open Recycle Bin#CRLF#Right-click to empty" -; Hovering over this meter will display a tooltip with the text above. -; The #CRLF# variable creates a new line. - -[meterBinItems] -Meter=STRING -MeterStyle=styleLeftText -MeasureName=measureBinItems -X=10 -Y=40 -W=190 -H=14 -Text="%1 items" -; %1 stands for the value of MeasureName (measureBinItems in this case). - -[meterBinSize] -Meter=STRING -MeterStyle=styleRightText -MeasureName=measureBinSize -X=200 -Y=0r -; r stands for relative. In this case, the Y postition of meterValueCPU is 0 pixels -; below the Y value of the previous meter (i.e it's the same as in meterLabelCPU). -W=190 -H=14 -Text="%1B" -AutoScale=1 -; Because measureBinSize returns the size in bytes, we must use AutoScale=1 to -; automatically scale the value into a more readable figure. - -[meterSeperator] -Meter=IMAGE -MeterStyle=styleSeperator -X=10 -Y=52 -W=190 -H=1 \ No newline at end of file diff --git a/Build/Skins/illustro/System/System.ini b/Build/Skins/illustro/System/System.ini deleted file mode 100644 index 5b92a963..00000000 --- a/Build/Skins/illustro/System/System.ini +++ /dev/null @@ -1,206 +0,0 @@ -; Lines starting ; (semicolons) are commented out. -; That is, they do not affect the code and are here for demonstration purposes only. -; ---------------------------------- - -[Rainmeter] -; This section contains general settings that can be used to change how Rainmeter behaves. -Author=poiru -AppVersion=2003000 -Update=1000 -Background=#@#Background.png -; #@# is equal to Rainmeter\Skins\illustro\@Resources -BackgroundMode=3 -BackgroundMargins=0,34,0,14 - -[Metadata] -; Contains basic information of the skin. -Description=Displays basic system stats. -License=Creative Commons BY-NC-SA 3.0 -Version=1.0.0 - -[Variables] -; Variables declared here can be used later on between two # characters (e.g. #MyVariable#). -fontName=Trebuchet MS -textSize=8 -colorBar=235,170,0,255 -colorText=255,255,255,205 - -; ---------------------------------- -; MEASURES return some kind of value -; ---------------------------------- - -[measureCPU] -; This measure returns the average CPU load between all cores. -Measure=CPU -Processor=0 - -[measureRAM] -; Returns the amount of RAM used in bytes. -Measure=PhysicalMemory -UpdateDivider=20 -; UpdateDivider sets the rate at which the value of the measure is updated. It is -; calculated as follows: UpdateDivider x Update. In this case, Update is set to -; 1000 milliseconds (in the [Rainmeter] section). 1000 x 20 = 20000 ms or 20 seconds. - -[measureSWAP] -; Returns the amount of SWAP (pagefile) used in bytes. -Measure=SWAPMemory -UpdateDivider=20 - -; ---------------------------------- -; STYLES are used to "centralize" options -; ---------------------------------- - -[styleTitle] -StringAlign=CENTER -StringCase=UPPER -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,50 -FontColor=#colorText# -FontFace=#fontName# -FontSize=10 -AntiAlias=1 -ClipString=1 - -[styleLeftText] -StringAlign=LEFT -; Meters using styleLeftText will be left-aligned. -StringCase=NONE -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,20 -FontColor=#colorText# -FontFace=#fontName# -FontSize=#textSize# -AntiAlias=1 -ClipString=1 - -[styleRightText] -StringAlign=RIGHT -StringCase=NONE -StringStyle=BOLD -StringEffect=SHADOW -FontEffectColor=0,0,0,20 -FontColor=#colorText# -FontFace=#fontName# -FontSize=#textSize# -AntiAlias=1 -ClipString=1 - -[styleBar] -BarColor=#colorBar# -BarOrientation=HORIZONTAL -SolidColor=255,255,255,15 - -; ---------------------------------- -; METERS display images, text, bars, etc. -; ---------------------------------- - -[meterTitle] -Meter=STRING -MeterStyle=styleTitle -; Using MeterStyle=styleTitle will basically "copy" the -; contents of the [styleTitle] section here during runtime. -X=100 -Y=12 -W=190 -H=18 -Text="System" -; Even though the text is set to System, Rainmeter will display -; it as SYSTEM, because styleTitle contains StringCase=UPPER. -LeftMouseUpAction=!Execute ["taskmgr.exe"] -; Left-clicking this meter will launch taskmgr.exe (the Task Manager). -ToolTipText="Open Task Manager" -; Hovering over this meter will display a tooltip with the text above. - -[meterLabelCPU] -Meter=STRING -MeterStyle=styleLeftText -X=10 -Y=40 -W=190 -H=14 -Text="CPU Usage" - -[meterValueCPU] -Meter=STRING -MeterStyle=styleRightText -MeasureName=measureCPU -X=200 -Y=0r -; r stands for relative. In this case, the Y postition of meterValueCPU is 0 pixels -; below the Y value of the previous meter (i.e it's the same as in meterLabelCPU). -W=190 -H=14 -Text="%1%" -; %1 stands for the value of MeasureName (measureCPU in this case). - -[meterBarCPU] -Meter=BAR -MeterStyle=styleBar -MeasureName=measureCPU -X=10 -Y=52 -W=190 -H=1 - -[meterLabelRAM] -Meter=STRING -MeterStyle=styleLeftText -X=10 -Y=60 -W=190 -H=14 -Text="RAM Usage" - -[meterValueRAM] -Meter=STRING -MeterStyle=styleRightText -MeasureName=measureRAM -X=200 -Y=0r -W=190 -H=14 -Text="%1%" -Percentual=1 -; Percentual=1 needs to be added her because measureRAM returns the amount -; of RAM used in bytes. Using Percentual=1 will convert that into a percentual value. - -[meterBarRAM] -Meter=BAR -MeterStyle=styleBar -MeasureName=measureRAM -X=10 -Y=72 -W=190 -H=1 - -[meterLabelSWAP] -Meter=STRING -MeterStyle=styleLeftText -X=10 -Y=80 -W=190 -H=14 -Text="SWAP Usage" - -[meterValueSWAP] -Meter=STRING -MeterStyle=styleRightText -MeasureName=measureSWAP -X=200 -Y=0r -W=190 -H=14 -Text="%1%" -Percentual=1 - -[meterBarSWAP] -Meter=BAR -MeterStyle=styleBar -MeasureName=measureSWAP -X=10 -Y=92 -W=190 -H=1 \ No newline at end of file diff --git a/Build/Skins/illustro/Welcome/Background.png b/Build/Skins/illustro/Welcome/Background.png deleted file mode 100644 index 5cf1119425bd04941f6bc0f64bab91067538edc8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1836 zcmeAS@N?(olHy`uVBq!ia0y~yVEh8aQXI@ckqd62UO>*&0G|+7AQuyagoFSEGcqzT zrAQLV%*@189~KrC8X5`|&&tZesvsvPM^aKUGBPqeJUlfum64H=iHQlQURG8XNOE&? z1IhgS{Pgtnyu3UkBO_s9VSj&rph_Vjq1@bD7BGm8j<&M0Dkvz3iHS*0PWJHd@bdBk z%CfVw1J!eIZ~#TLwY9Uevw?OQ8X6iH7z6|a@bdC{dU^s?N=Zq%xw!!y0CXWx3mY37 zFie0(0S%OslLJcG+S&p=0(4|xV4#ME2GC5P0tW{NdwY9FM@OLfK|w*m!NIDksz7Bx z5@@)yvop|zf`WoTyL^3pBO)Szjs(gAO>l8>QBzZccn#>yO5uVYpeNf)g8YJe)-&<2 z$%!PI`)e^Wurdp?$Z`s?^Kx;BYf6gp$?*FLa7$|ls>LUm`uZv>s+j2*_{@umGhEjr zrDW1&?BV8ZB;#hb$Z_?WAT5swld?kZm5WxDihGOn_Sq^b7YQrJx_5U++PHN1YiC;( z*~?njG=C)e57x|bd8oCBX#76kp8OXQi)tbL$U|`wr>Eakt5%=ceLEZxjJj@3) z-mbr~DL~}joBb(Qr)UanKNP8b{bqe(1s12D%XU6~ z=8f`#tpAtqcD}fNTJG;+1s-QciRmhAPi}snb!0-&ZMBkYbJpWpe0)tE&3#o2@9P=< z%P3SU>=&;2a8pl0X;Pu2s<=;zQ~J(0(Gxf7tr(^q`grWbs&~;#pB2vZ(u>$y8|!(w zK;4V&!|Zbb8NX{{{VpdO_uSK8Wb{7xwQT$Gf3S#J<&Z>8@YV@>MyKJIR>`D z%eT+|(r4`5Ap5e|uf61wqm>8yO9j~_%_S4~K%D>Xa3+d4m^1m`X}MYzRUTlPD>-tm zg`u&*r9k6b-JwqsuOp7#+xK8M??-;QNq6<%gfMe9r%k|oNrFFmH~#UeOJ z;_kaj7~zUg#b44?-0IR&?g>!GA=?WS_nuBu@rin|4Uj-VwRfVP?V7b*8g9RebkAIB zHmQwv5X^bwf2rBC%Kl9rr$*D)vx(+!(q9&uSO^8MJYSyOtntrVzEn?-^~wFKUmwP$ zi-cePlC}5xzMp~<>bIA(?|vI+>#H9gb@s`>L>-0q$NK#b-&}HY)s)L$+%&7|Dn%!h z=f9V?J|4Jo;!^gnQ=dHf{Q9?#L*3s^{^^=LhXN$rysvCCF_SQrSlk3e%3JbF<7J;G z-uE?suzS+xrqh3al>a{bQKdlO*6aF`gq=}d=cm7ZyYFV&&!nO$Hq|!q@B4pT3MtlA zSbTbA^^t`;p5$H^KU-8ZW!a0})27d`Ix^Y0-B_4u$!!(B8G%=ue(&2awWQ~*vyrBF zY3c?AwQYS2CaEPII(IKSrTaw+CFbx1e|W)nEb!2a^|n?g5+zy|Dn!lHn0K6xG(pdp6B{yI;3H{KT10rE-d*t2iFb;OnsR z_TG9g(dl$-c2?^;rkdsUw?prG=3S2T*tOd3^zSc>bA56g#oPJY=j3?qj9@(hOz8}s Lu6{1-oD!M - - - - $(SolutionDir)..\WinDDK\7600.16385.1\ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - Unicode - v120_xp - - \ No newline at end of file diff --git a/Build/VS/Rainmeter.Cpp.props b/Build/VS/Rainmeter.Cpp.props deleted file mode 100644 index 8a5fc870..00000000 --- a/Build/VS/Rainmeter.Cpp.props +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - $(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - - true - true - - - - true - - - - - $(SolutionDir)x32-$(Configuration)\ - $(SolutionDir)x64-$(Configuration)\ - - $(RmOutDirRoot) - $(OutDir)\Obj\$(ProjectName)\ - - - - - $(IntDir) - - - - - - false - - - Microsoft.VisualStudio.TestTools.CppUnitTestFramework.dll - Microsoft.VisualStudio.TestTools.CppUnitTestFramework.x64.dll - - - - - - - $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) - - - $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) - - - - - - - 4351;%(DisableSpecificWarnings) - - false - - - - WIN32;_WINDOWS;WINVER=0x0601;_WIN32_WINNT=0x0601;_WIN32_IE=0x0601;PSAPI_VERSION=1;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions) - Level3 - - - Windows - $(IntDir)$(TargetName).lib - $(IntDir)$(TargetName).pdb - false - - - 0x0409 - - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - EnableFastChecks - - - true - - - _DEBUG;%(PreprocessorDefinitions) - - - - - - true - MaxSpeed - NDEBUG;%(PreprocessorDefinitions) - true - true - /Gw %(AdditionalOptions) - - - false - UseLinkTimeCodeGeneration - .rdata=.text - true - true - - - NDEBUG;%(PreprocessorDefinitions) - - - - - - StreamingSIMDExtensions - - - MachineX86 - - - - - - _WIN64;%(PreprocessorDefinitions) - - - MachineX64 - - - \ No newline at end of file diff --git a/Build/VS/RainmeterPlugin.Cpp.props b/Build/VS/RainmeterPlugin.Cpp.props deleted file mode 100644 index 7677773f..00000000 --- a/Build/VS/RainmeterPlugin.Cpp.props +++ /dev/null @@ -1,18 +0,0 @@ - - - - false - $(OutDir)Plugins\ - - - - - $(SolutionDir)Plugins\API\x32\Rainmeter.lib;%(AdditionalDependencies) - - - - - $(SolutionDir)Plugins\API\x64\Rainmeter.lib;%(AdditionalDependencies) - - - \ No newline at end of file diff --git a/Build/VS/RainmeterPlugin.Cs.props b/Build/VS/RainmeterPlugin.Cs.props deleted file mode 100644 index 53b7ff31..00000000 --- a/Build/VS/RainmeterPlugin.Cs.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - $(SolutionDir)x32-$(Configuration)\ - $(SolutionDir)x64-$(Configuration)\ - - $(RmOutDirRoot)Plugins\ - - \ No newline at end of file diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index c91376d4..be7fb505 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -1,85 +1,85 @@ - - - - - {19312085-AA51-4BD6-BE92-4B6098CCA539} - StaticLibrary - - - - - - - - - - - - - .\;%(AdditionalIncludeDirectories) - _LIB;%(PreprocessorDefinitions) - Use - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + {19312085-AA51-4BD6-BE92-4B6098CCA539} + StaticLibrary + + + + + + + + + + + + + .\;%(AdditionalIncludeDirectories) + _LIB;%(PreprocessorDefinitions) + Use + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 5b54aacc..6b4575c3 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -1,124 +1,124 @@ - - - - - - - - - - - - Gfx - - - Gfx - - - Gfx - - - Gfx - - - Gfx - - - Gfx - - - Gfx - - - Gfx - - - Gfx - - - Gfx\Util - - - Gfx\Util - - - Gfx\Util - - - Gfx\Util - - - Gfx\Util - - - Gfx\Util - - - - - - - - - - - - - - - - Gfx - - - Gfx - - - Gfx - - - Gfx - - - Gfx - - - Gfx - - - Gfx - - - Gfx - - - Gfx - - - Gfx\Util - - - Gfx\Util - - - Gfx\Util - - - Gfx\Util - - - Gfx\Util - - - Gfx\Util - - - - - - {263d9d8c-b463-4f2a-87ab-5f6575a4cc38} - - - {c3efb431-e0f5-4085-9b07-33a7e34c4baa} - - + + + + + + + + + + + + Gfx + + + Gfx + + + Gfx + + + Gfx + + + Gfx + + + Gfx + + + Gfx + + + Gfx + + + Gfx + + + Gfx\Util + + + Gfx\Util + + + Gfx\Util + + + Gfx\Util + + + Gfx\Util + + + Gfx\Util + + + + + + + + + + + + + + + + Gfx + + + Gfx + + + Gfx + + + Gfx + + + Gfx + + + Gfx + + + Gfx + + + Gfx + + + Gfx + + + Gfx\Util + + + Gfx\Util + + + Gfx\Util + + + Gfx\Util + + + Gfx\Util + + + Gfx\Util + + + + + + {263d9d8c-b463-4f2a-87ab-5f6575a4cc38} + + + {c3efb431-e0f5-4085-9b07-33a7e34c4baa} + + \ No newline at end of file diff --git a/Common/Common_Test.vcxproj b/Common/Common_Test.vcxproj index 63d04470..0de45a0b 100644 --- a/Common/Common_Test.vcxproj +++ b/Common/Common_Test.vcxproj @@ -1,33 +1,33 @@ - - - - - {442084A6-2069-4927-B0C9-51525A720CB2} - DynamicLibrary - - - - - - $(IntDir) - - - - $(ExcludeTests) - - - $(ExcludeTests) - - - $(ExcludeTests) - - - - - {19312085-aa51-4bd6-be92-4b6098cca539} - - - - - + + + + + {442084A6-2069-4927-B0C9-51525A720CB2} + DynamicLibrary + + + + + + $(IntDir) + + + + $(ExcludeTests) + + + $(ExcludeTests) + + + $(ExcludeTests) + + + + + {19312085-aa51-4bd6-be92-4b6098cca539} + + + + + \ No newline at end of file diff --git a/Common/Common_Test.vcxproj.filters b/Common/Common_Test.vcxproj.filters index 7c40c33b..f33f0046 100644 --- a/Common/Common_Test.vcxproj.filters +++ b/Common/Common_Test.vcxproj.filters @@ -1,8 +1,8 @@ - - - - - - - + + + + + + + \ No newline at end of file diff --git a/Common/ControlTemplate.cpp b/Common/ControlTemplate.cpp index c6cc6142..dc6e600e 100644 --- a/Common/ControlTemplate.cpp +++ b/Common/ControlTemplate.cpp @@ -1,50 +1,50 @@ -/* - Copyright (C) 2012 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "ControlTemplate.h" - -namespace ControlTemplate -{ - -void CreateControls(const Control* cts, UINT ctCount, HWND parent, HFONT font, GetStringFunc getString) -{ - for (UINT i = 0; i < ctCount; ++i) - { - const Control& ct = cts[i]; - - WCHAR* text = ct.textId ? getString(ct.textId) : nullptr; - - RECT r = { ct.x, ct.y, ct.w, ct.h }; - MapDialogRect(parent, &r); - - HWND wnd = CreateWindowEx( - ct.exStyle, - ct.name, - text, - ct.style, - r.left, r.top, r.right, r.bottom, - parent, - (HMENU)ct.id, - nullptr, - nullptr); - SendMessage(wnd, WM_SETFONT, (WPARAM)font, FALSE); - } -} - +/* + Copyright (C) 2012 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "ControlTemplate.h" + +namespace ControlTemplate +{ + +void CreateControls(const Control* cts, UINT ctCount, HWND parent, HFONT font, GetStringFunc getString) +{ + for (UINT i = 0; i < ctCount; ++i) + { + const Control& ct = cts[i]; + + WCHAR* text = ct.textId ? getString(ct.textId) : nullptr; + + RECT r = { ct.x, ct.y, ct.w, ct.h }; + MapDialogRect(parent, &r); + + HWND wnd = CreateWindowEx( + ct.exStyle, + ct.name, + text, + ct.style, + r.left, r.top, r.right, r.bottom, + parent, + (HMENU)ct.id, + nullptr, + nullptr); + SendMessage(wnd, WM_SETFONT, (WPARAM)font, FALSE); + } +} + } // namespace ControlTemplate \ No newline at end of file diff --git a/Common/ControlTemplate.h b/Common/ControlTemplate.h index f9c192cb..120a4421 100644 --- a/Common/ControlTemplate.h +++ b/Common/ControlTemplate.h @@ -1,89 +1,89 @@ -/* - Copyright (C) 2012 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_COMMON_CONTROLTEMPLATE_H_ -#define RM_COMMON_CONTROLTEMPLATE_H_ - -#include - -namespace ControlTemplate -{ - -struct Control -{ - const WCHAR* name; - WORD id; - WORD textId; - short x; - short y; - short w; - short h; - DWORD style; - DWORD exStyle; -}; - -typedef WCHAR* (*GetStringFunc)(UINT id); - -void CreateControls(const Control* cts, UINT ctCount, HWND parent, HFONT font, GetStringFunc getString); - -// Helpers to declare control structs. -#define CT_ITEM(name, id, textId, x, y, w, h, style, exStyle) \ - { name, id, textId, x, y, w, h, WS_CHILD | style, exStyle } - -#define CT_BUTTON(id, textId, x, y, w, h, style, exStyle) \ - CT_ITEM(L"Button", id, textId, x, y, w, h, BS_PUSHBUTTON | style, exStyle) - -#define CT_CHECKBOX(id, textId, x, y, w, h, style, exStyle) \ - CT_ITEM(L"Button", id, textId, x, y, w, h, BS_AUTOCHECKBOX | style, exStyle) - -#define CT_COMBOBOX(id, textId, x, y, w, h, style, exStyle) \ - CT_ITEM(L"ComboBox", id, textId, x, y, w, h, style, exStyle) - -#define CT_EDIT(id, textId, x, y, w, h, style, exStyle) \ - CT_ITEM(L"Edit", id, textId, x, y, w, h, ES_LEFT | style, exStyle) - -#define CT_GROUPBOX(id, textId, x, y, w, h, style, exStyle) \ - CT_ITEM(L"Button", id, textId, x, y, w, h, BS_GROUPBOX | style, exStyle) - -#define CT_ICON(id, textId, x, y, w, h, style, exStyle) \ - CT_ITEM(L"Static", id, textId, x, y, w, h, SS_ICON | style, exStyle) - -#define CT_LABEL(id, textId, x, y, w, h, style, exStyle) \ - CT_ITEM(L"Static", id, textId, x, y, w, h, SS_LEFT | style, exStyle) - -#define CT_LINEH(id, textId, x, y, w, h, style, exStyle) \ - CT_ITEM(L"Static", id, textId, x, y, w, h, SS_ETCHEDHORZ | style, exStyle) - -#define CT_LINKLABEL(id, textId, x, y, w, h, style, exStyle) \ - CT_ITEM(L"SysLink", id, textId, x, y, w, h, style, exStyle) - -#define CT_LISTBOX(id, textId, x, y, w, h, style, exStyle) \ - CT_ITEM(L"ListBox", id, textId, x, y, w, h, style, exStyle) - -#define CT_LISTVIEW(id, textId, x, y, w, h, style, exStyle) \ - CT_ITEM(L"SysListView32", id, textId, x, y, w, h, style, exStyle) - -#define CT_TAB(id, textId, x, y, w, h, style, exStyle) \ - CT_ITEM(L"SysTabControl32", id, textId, x, y, w, h, TCS_TABS | style, exStyle) - -#define CT_TREEVIEW(id, textId, x, y, w, h, style, exStyle) \ - CT_ITEM(L"SysTreeView32", id, textId, x, y, w, h, style, exStyle) - -} // namespace ControlTemplate - +/* + Copyright (C) 2012 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_COMMON_CONTROLTEMPLATE_H_ +#define RM_COMMON_CONTROLTEMPLATE_H_ + +#include + +namespace ControlTemplate +{ + +struct Control +{ + const WCHAR* name; + WORD id; + WORD textId; + short x; + short y; + short w; + short h; + DWORD style; + DWORD exStyle; +}; + +typedef WCHAR* (*GetStringFunc)(UINT id); + +void CreateControls(const Control* cts, UINT ctCount, HWND parent, HFONT font, GetStringFunc getString); + +// Helpers to declare control structs. +#define CT_ITEM(name, id, textId, x, y, w, h, style, exStyle) \ + { name, id, textId, x, y, w, h, WS_CHILD | style, exStyle } + +#define CT_BUTTON(id, textId, x, y, w, h, style, exStyle) \ + CT_ITEM(L"Button", id, textId, x, y, w, h, BS_PUSHBUTTON | style, exStyle) + +#define CT_CHECKBOX(id, textId, x, y, w, h, style, exStyle) \ + CT_ITEM(L"Button", id, textId, x, y, w, h, BS_AUTOCHECKBOX | style, exStyle) + +#define CT_COMBOBOX(id, textId, x, y, w, h, style, exStyle) \ + CT_ITEM(L"ComboBox", id, textId, x, y, w, h, style, exStyle) + +#define CT_EDIT(id, textId, x, y, w, h, style, exStyle) \ + CT_ITEM(L"Edit", id, textId, x, y, w, h, ES_LEFT | style, exStyle) + +#define CT_GROUPBOX(id, textId, x, y, w, h, style, exStyle) \ + CT_ITEM(L"Button", id, textId, x, y, w, h, BS_GROUPBOX | style, exStyle) + +#define CT_ICON(id, textId, x, y, w, h, style, exStyle) \ + CT_ITEM(L"Static", id, textId, x, y, w, h, SS_ICON | style, exStyle) + +#define CT_LABEL(id, textId, x, y, w, h, style, exStyle) \ + CT_ITEM(L"Static", id, textId, x, y, w, h, SS_LEFT | style, exStyle) + +#define CT_LINEH(id, textId, x, y, w, h, style, exStyle) \ + CT_ITEM(L"Static", id, textId, x, y, w, h, SS_ETCHEDHORZ | style, exStyle) + +#define CT_LINKLABEL(id, textId, x, y, w, h, style, exStyle) \ + CT_ITEM(L"SysLink", id, textId, x, y, w, h, style, exStyle) + +#define CT_LISTBOX(id, textId, x, y, w, h, style, exStyle) \ + CT_ITEM(L"ListBox", id, textId, x, y, w, h, style, exStyle) + +#define CT_LISTVIEW(id, textId, x, y, w, h, style, exStyle) \ + CT_ITEM(L"SysListView32", id, textId, x, y, w, h, style, exStyle) + +#define CT_TAB(id, textId, x, y, w, h, style, exStyle) \ + CT_ITEM(L"SysTabControl32", id, textId, x, y, w, h, TCS_TABS | style, exStyle) + +#define CT_TREEVIEW(id, textId, x, y, w, h, style, exStyle) \ + CT_ITEM(L"SysTreeView32", id, textId, x, y, w, h, style, exStyle) + +} // namespace ControlTemplate + #endif \ No newline at end of file diff --git a/Common/Dialog.cpp b/Common/Dialog.cpp index 2a5714ce..95f133cb 100644 --- a/Common/Dialog.cpp +++ b/Common/Dialog.cpp @@ -1,260 +1,260 @@ -/* - Copyright (C) 2012 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Dialog.h" - -HWND Dialog::c_ActiveDialogWindow = nullptr; - -// -// BaseDialog -// - -BaseDialog::BaseDialog() : - m_Window() -{ -} - -/* -** Create (if not already) and show the dialog. -** -*/ -void BaseDialog::Show(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless) -{ - if (m_Window) - { - // Show existing window. - ShowWindow(m_Window, SW_SHOW); - SetForegroundWindow(m_Window); - return; - } - - const WCHAR* font = L"MS Shell Dlg 2"; - const size_t titleSize = (wcslen(title) + 1) * sizeof(WCHAR); - const size_t fontSize = (wcslen(font) + 1) * sizeof(WCHAR); - - const size_t dataSize = sizeof(DLGTEMPLATE) + - sizeof(WCHAR) + // Menu array. - sizeof(WCHAR) + // Class array. - titleSize + // Title array. - sizeof(WORD) + // Font point size. - fontSize; // Font array. - - DLGTEMPLATE* dt = (DLGTEMPLATE*)new BYTE[dataSize]; - dt->style = style | DS_SHELLFONT | WS_VISIBLE; - dt->dwExtendedStyle = exStyle; - dt->cdit = 0; - dt->x = x; - dt->y = y; - dt->cx = w; - dt->cy = h; - - BYTE* dtExtra = (BYTE*)dt + sizeof(DLGTEMPLATE); - - // Menu array. - *(WCHAR*)dtExtra = L'\0'; - dtExtra += sizeof(WCHAR); - - // Class array. - *(WCHAR*)dtExtra = L'\0'; - dtExtra += sizeof(WCHAR); - - // Title array. - memcpy(dtExtra, title, titleSize); - dtExtra += titleSize; - - // Font point size. - *(WORD*)dtExtra = 8; - dtExtra += sizeof(WORD); - - // Font array. - memcpy(dtExtra, font, fontSize); - - if (modeless) - { - CreateDialogIndirectParam(nullptr, dt, parent, InitialDlgProc, (LPARAM)this); - } - else - { - DialogBoxIndirectParam(nullptr, dt, parent, InitialDlgProc, (LPARAM)this); - } - - delete [] dt; -} - -void BaseDialog::CreateControls(const ControlTemplate::Control* cts, UINT ctCount, HFONT font, ControlTemplate::GetStringFunc getString) -{ - ControlTemplate::CreateControls(cts, ctCount, m_Window, font, getString); -} - -INT_PTR CALLBACK BaseDialog::InitialDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (uMsg == WM_INITDIALOG) - { - BaseDialog* dialog = (BaseDialog*)lParam; - dialog->m_Window = hWnd; - SetWindowLongPtr(hWnd, DWLP_USER, (LONG_PTR)dialog); - SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)MainDlgProc); - return dialog->HandleMessage(uMsg, wParam, lParam); - } - - return FALSE; -} - -INT_PTR CALLBACK BaseDialog::MainDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - BaseDialog* dialog = (BaseDialog*)GetWindowLongPtr(hWnd, DWLP_USER); - return dialog->HandleMessage(uMsg, wParam, lParam); -} - -// -// Dialog -// - -Dialog::Dialog() : BaseDialog(), - m_Font(), - m_FontBold() -{ - NONCLIENTMETRICS ncm; - ncm.cbSize = sizeof(NONCLIENTMETRICS) - sizeof(ncm.iPaddedBorderWidth); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0); - m_Font = CreateFontIndirect(&ncm.lfMenuFont); - ncm.lfMenuFont.lfWeight = FW_BOLD; - ncm.lfMenuFont.lfHeight -= 2; - m_FontBold = CreateFontIndirect(&ncm.lfMenuFont); -} - -Dialog::~Dialog() -{ - DestroyWindow(m_Window); - DeleteObject(m_Font); - DeleteObject(m_FontBold); -} - -void Dialog::ShowDialogWindow(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless) -{ - Show(title, x, y, w, h, style, exStyle, parent, modeless); -} - -INT_PTR Dialog::OnActivate(WPARAM wParam, LPARAM lParam) -{ - c_ActiveDialogWindow = wParam ? m_Window : nullptr; - return FALSE; -} - -bool Dialog::HandleMessage(MSG& msg) -{ - if (c_ActiveDialogWindow) - { - if (IsDialogMessage(c_ActiveDialogWindow, &msg)) - { - return true; - } - } - - return false; -} - -/* -** Subclass button control to draw arrow on the right. -** -*/ -void Dialog::SetMenuButton(HWND button) -{ - SetWindowSubclass(button, MenuButtonProc, 0, 0); -} - -LRESULT CALLBACK Dialog::MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) -{ - LRESULT result = DefSubclassProc(hWnd, uMsg, wParam, lParam); - - switch (uMsg) - { - case WM_PAINT: - { - // Draw arrow on top of the button - RECT buttonRect; - GetClientRect(hWnd, &buttonRect); - int arrowX = buttonRect.right - 18; - int arrowY = buttonRect.top + 4; - RECT arrowRect = { arrowX, arrowY, arrowX + 14, arrowY + 14 }; - - HDC dc = GetDC(hWnd); - const WORD DFCS_MENUARROWDOWN = 0x0010; // Undocumented - DWORD drawFlags = DFCS_TRANSPARENT | DFCS_MENUARROWDOWN | (IsWindowEnabled(hWnd) ? 0 : DFCS_INACTIVE); - DrawFrameControl(dc, &arrowRect, DFC_MENU, drawFlags); - ReleaseDC(hWnd, dc); - } - break; - - case WM_GETTEXT: - { - // Append 3 spaces to the button text to move text to the left so - // that it looks better with BS_CENTER. - WCHAR* str = (WCHAR*)lParam + result; - str[0] = str[1] = str[2] = L' '; - str[3] = '\0'; - result += 3; - } - break; - - case WM_GETTEXTLENGTH: - result += 3; - break; - - case WM_NCDESTROY: - RemoveWindowSubclass(hWnd, MenuButtonProc, uIdSubclass); - break; - } - - return result; -} - -// -// Tab -// - -Dialog::Tab::Tab() : BaseDialog(), - m_Initialized(false) -{ -} - -void Dialog::Tab::CreateTabWindow(short x, short y, short w, short h, HWND owner) -{ - const DWORD style = DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS; - const DWORD exStyle = WS_EX_CONTROLPARENT; - Show(L"", x, y, w, h, style, exStyle, owner, true); - - EnableThemeDialogTexture(m_Window, ETDT_ENABLETAB); -} - -Dialog::Tab::~Tab() -{ - DestroyWindow(m_Window); -} - -void Dialog::Tab::Activate() -{ - if (!m_Initialized) - { - Initialize(); - } - - EnableWindow(m_Window, TRUE); - BringWindowToTop(m_Window); -} +/* + Copyright (C) 2012 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Dialog.h" + +HWND Dialog::c_ActiveDialogWindow = nullptr; + +// +// BaseDialog +// + +BaseDialog::BaseDialog() : + m_Window() +{ +} + +/* +** Create (if not already) and show the dialog. +** +*/ +void BaseDialog::Show(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless) +{ + if (m_Window) + { + // Show existing window. + ShowWindow(m_Window, SW_SHOW); + SetForegroundWindow(m_Window); + return; + } + + const WCHAR* font = L"MS Shell Dlg 2"; + const size_t titleSize = (wcslen(title) + 1) * sizeof(WCHAR); + const size_t fontSize = (wcslen(font) + 1) * sizeof(WCHAR); + + const size_t dataSize = sizeof(DLGTEMPLATE) + + sizeof(WCHAR) + // Menu array. + sizeof(WCHAR) + // Class array. + titleSize + // Title array. + sizeof(WORD) + // Font point size. + fontSize; // Font array. + + DLGTEMPLATE* dt = (DLGTEMPLATE*)new BYTE[dataSize]; + dt->style = style | DS_SHELLFONT | WS_VISIBLE; + dt->dwExtendedStyle = exStyle; + dt->cdit = 0; + dt->x = x; + dt->y = y; + dt->cx = w; + dt->cy = h; + + BYTE* dtExtra = (BYTE*)dt + sizeof(DLGTEMPLATE); + + // Menu array. + *(WCHAR*)dtExtra = L'\0'; + dtExtra += sizeof(WCHAR); + + // Class array. + *(WCHAR*)dtExtra = L'\0'; + dtExtra += sizeof(WCHAR); + + // Title array. + memcpy(dtExtra, title, titleSize); + dtExtra += titleSize; + + // Font point size. + *(WORD*)dtExtra = 8; + dtExtra += sizeof(WORD); + + // Font array. + memcpy(dtExtra, font, fontSize); + + if (modeless) + { + CreateDialogIndirectParam(nullptr, dt, parent, InitialDlgProc, (LPARAM)this); + } + else + { + DialogBoxIndirectParam(nullptr, dt, parent, InitialDlgProc, (LPARAM)this); + } + + delete [] dt; +} + +void BaseDialog::CreateControls(const ControlTemplate::Control* cts, UINT ctCount, HFONT font, ControlTemplate::GetStringFunc getString) +{ + ControlTemplate::CreateControls(cts, ctCount, m_Window, font, getString); +} + +INT_PTR CALLBACK BaseDialog::InitialDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_INITDIALOG) + { + BaseDialog* dialog = (BaseDialog*)lParam; + dialog->m_Window = hWnd; + SetWindowLongPtr(hWnd, DWLP_USER, (LONG_PTR)dialog); + SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)MainDlgProc); + return dialog->HandleMessage(uMsg, wParam, lParam); + } + + return FALSE; +} + +INT_PTR CALLBACK BaseDialog::MainDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + BaseDialog* dialog = (BaseDialog*)GetWindowLongPtr(hWnd, DWLP_USER); + return dialog->HandleMessage(uMsg, wParam, lParam); +} + +// +// Dialog +// + +Dialog::Dialog() : BaseDialog(), + m_Font(), + m_FontBold() +{ + NONCLIENTMETRICS ncm; + ncm.cbSize = sizeof(NONCLIENTMETRICS) - sizeof(ncm.iPaddedBorderWidth); + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0); + m_Font = CreateFontIndirect(&ncm.lfMenuFont); + ncm.lfMenuFont.lfWeight = FW_BOLD; + ncm.lfMenuFont.lfHeight -= 2; + m_FontBold = CreateFontIndirect(&ncm.lfMenuFont); +} + +Dialog::~Dialog() +{ + DestroyWindow(m_Window); + DeleteObject(m_Font); + DeleteObject(m_FontBold); +} + +void Dialog::ShowDialogWindow(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless) +{ + Show(title, x, y, w, h, style, exStyle, parent, modeless); +} + +INT_PTR Dialog::OnActivate(WPARAM wParam, LPARAM lParam) +{ + c_ActiveDialogWindow = wParam ? m_Window : nullptr; + return FALSE; +} + +bool Dialog::HandleMessage(MSG& msg) +{ + if (c_ActiveDialogWindow) + { + if (IsDialogMessage(c_ActiveDialogWindow, &msg)) + { + return true; + } + } + + return false; +} + +/* +** Subclass button control to draw arrow on the right. +** +*/ +void Dialog::SetMenuButton(HWND button) +{ + SetWindowSubclass(button, MenuButtonProc, 0, 0); +} + +LRESULT CALLBACK Dialog::MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) +{ + LRESULT result = DefSubclassProc(hWnd, uMsg, wParam, lParam); + + switch (uMsg) + { + case WM_PAINT: + { + // Draw arrow on top of the button + RECT buttonRect; + GetClientRect(hWnd, &buttonRect); + int arrowX = buttonRect.right - 18; + int arrowY = buttonRect.top + 4; + RECT arrowRect = { arrowX, arrowY, arrowX + 14, arrowY + 14 }; + + HDC dc = GetDC(hWnd); + const WORD DFCS_MENUARROWDOWN = 0x0010; // Undocumented + DWORD drawFlags = DFCS_TRANSPARENT | DFCS_MENUARROWDOWN | (IsWindowEnabled(hWnd) ? 0 : DFCS_INACTIVE); + DrawFrameControl(dc, &arrowRect, DFC_MENU, drawFlags); + ReleaseDC(hWnd, dc); + } + break; + + case WM_GETTEXT: + { + // Append 3 spaces to the button text to move text to the left so + // that it looks better with BS_CENTER. + WCHAR* str = (WCHAR*)lParam + result; + str[0] = str[1] = str[2] = L' '; + str[3] = '\0'; + result += 3; + } + break; + + case WM_GETTEXTLENGTH: + result += 3; + break; + + case WM_NCDESTROY: + RemoveWindowSubclass(hWnd, MenuButtonProc, uIdSubclass); + break; + } + + return result; +} + +// +// Tab +// + +Dialog::Tab::Tab() : BaseDialog(), + m_Initialized(false) +{ +} + +void Dialog::Tab::CreateTabWindow(short x, short y, short w, short h, HWND owner) +{ + const DWORD style = DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS; + const DWORD exStyle = WS_EX_CONTROLPARENT; + Show(L"", x, y, w, h, style, exStyle, owner, true); + + EnableThemeDialogTexture(m_Window, ETDT_ENABLETAB); +} + +Dialog::Tab::~Tab() +{ + DestroyWindow(m_Window); +} + +void Dialog::Tab::Activate() +{ + if (!m_Initialized) + { + Initialize(); + } + + EnableWindow(m_Window, TRUE); + BringWindowToTop(m_Window); +} diff --git a/Common/Dialog.h b/Common/Dialog.h index b29a7950..6f2f97bb 100644 --- a/Common/Dialog.h +++ b/Common/Dialog.h @@ -1,97 +1,97 @@ -/* - Copyright (C) 2012 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_COMMON_DIALOG_H_ -#define RM_COMMON_DIALOG_H_ - -#include -#include "ControlTemplate.h" - -// Shared base class for Dialog and Tab. -class BaseDialog -{ -public: - HWND GetControl(WORD id) { return GetDlgItem(m_Window, id); } - -protected: - BaseDialog(); - virtual ~BaseDialog() {} - - void Show(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless); - - void CreateControls(const ControlTemplate::Control* cts, UINT ctCount, HFONT font, ControlTemplate::GetStringFunc getString); - - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { return FALSE; } - - HWND m_Window; - -private: - BaseDialog(const BaseDialog& r); - - static INT_PTR CALLBACK InitialDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - static INT_PTR CALLBACK MainDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -}; - -class Dialog : public BaseDialog -{ -public: - HWND GetWindow() { return m_Window; } - - static bool HandleMessage(MSG& msg); - -protected: - class Tab : public BaseDialog - { - public: - HWND GetWindow() { return m_Window; } - bool IsInitialized() { return m_Initialized; } - void Activate(); - - virtual void Initialize() {} - virtual void Resize(int w, int h) {} - - protected: - Tab(); - virtual ~Tab(); - - void CreateTabWindow(short x, short y, short w, short h, HWND owner); - - bool m_Initialized; - }; - - Dialog(); - virtual ~Dialog(); - - void ShowDialogWindow(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless = true); - - INT_PTR OnActivate(WPARAM wParam, LPARAM lParam); - - static void SetMenuButton(HWND button); - - HFONT m_Font; - HFONT m_FontBold; - -private: - Dialog(const Dialog& r); - - static LRESULT CALLBACK MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData); - - static HWND c_ActiveDialogWindow; -}; - -#endif +/* + Copyright (C) 2012 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_COMMON_DIALOG_H_ +#define RM_COMMON_DIALOG_H_ + +#include +#include "ControlTemplate.h" + +// Shared base class for Dialog and Tab. +class BaseDialog +{ +public: + HWND GetControl(WORD id) { return GetDlgItem(m_Window, id); } + +protected: + BaseDialog(); + virtual ~BaseDialog() {} + + void Show(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless); + + void CreateControls(const ControlTemplate::Control* cts, UINT ctCount, HFONT font, ControlTemplate::GetStringFunc getString); + + virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { return FALSE; } + + HWND m_Window; + +private: + BaseDialog(const BaseDialog& r); + + static INT_PTR CALLBACK InitialDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + static INT_PTR CALLBACK MainDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +}; + +class Dialog : public BaseDialog +{ +public: + HWND GetWindow() { return m_Window; } + + static bool HandleMessage(MSG& msg); + +protected: + class Tab : public BaseDialog + { + public: + HWND GetWindow() { return m_Window; } + bool IsInitialized() { return m_Initialized; } + void Activate(); + + virtual void Initialize() {} + virtual void Resize(int w, int h) {} + + protected: + Tab(); + virtual ~Tab(); + + void CreateTabWindow(short x, short y, short w, short h, HWND owner); + + bool m_Initialized; + }; + + Dialog(); + virtual ~Dialog(); + + void ShowDialogWindow(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless = true); + + INT_PTR OnActivate(WPARAM wParam, LPARAM lParam); + + static void SetMenuButton(HWND button); + + HFONT m_Font; + HFONT m_FontBold; + +private: + Dialog(const Dialog& r); + + static LRESULT CALLBACK MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData); + + static HWND c_ActiveDialogWindow; +}; + +#endif diff --git a/Common/Gfx/Canvas.cpp b/Common/Gfx/Canvas.cpp index 9b8a7270..c2cd9b33 100644 --- a/Common/Gfx/Canvas.cpp +++ b/Common/Gfx/Canvas.cpp @@ -1,71 +1,71 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Canvas.h" -#include "CanvasD2D.h" -#include "CanvasGDIP.h" - -namespace Gfx { - -Canvas::Canvas() : - m_W(), - m_H(), - m_AccurateText(false) -{ -} - -Canvas::~Canvas() -{ -} - -Canvas* Canvas::Create(Renderer renderer) -{ - if (renderer == Renderer::GDIP) - { - return new CanvasGDIP(); - } - else if (renderer == Renderer::D2D && IsWindows7OrGreater()) - { - if (CanvasD2D::Initialize()) - { - return new CanvasD2D(); - } - - CanvasD2D::Finalize(); - } - else if (renderer == Renderer::PreferD2D) - { - if (Canvas* canvas = Create(Renderer::D2D)) - { - return canvas; - } - - return Create(Renderer::GDIP); - } - - return nullptr; -}; - -void Canvas::Resize(int w, int h) -{ - m_W = w; - m_H = h; -} - -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Canvas.h" +#include "CanvasD2D.h" +#include "CanvasGDIP.h" + +namespace Gfx { + +Canvas::Canvas() : + m_W(), + m_H(), + m_AccurateText(false) +{ +} + +Canvas::~Canvas() +{ +} + +Canvas* Canvas::Create(Renderer renderer) +{ + if (renderer == Renderer::GDIP) + { + return new CanvasGDIP(); + } + else if (renderer == Renderer::D2D && IsWindows7OrGreater()) + { + if (CanvasD2D::Initialize()) + { + return new CanvasD2D(); + } + + CanvasD2D::Finalize(); + } + else if (renderer == Renderer::PreferD2D) + { + if (Canvas* canvas = Create(Renderer::D2D)) + { + return canvas; + } + + return Create(Renderer::GDIP); + } + + return nullptr; +}; + +void Canvas::Resize(int w, int h) +{ + m_W = w; + m_H = h; +} + +} // namespace Gfx diff --git a/Common/Gfx/Canvas.h b/Common/Gfx/Canvas.h index c330a363..03d80209 100644 --- a/Common/Gfx/Canvas.h +++ b/Common/Gfx/Canvas.h @@ -1,114 +1,114 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_GFX_CANVAS_H_ -#define RM_GFX_CANVAS_H_ - -#include "FontCollection.h" -#include "TextFormat.h" - -namespace Gfx { - -enum class Renderer -{ - GDIP, - D2D, - - // Attempts to use D2D. If D2D is not available, fallbacks to use GDI+. - PreferD2D -}; - -// Provides methods for drawing text, bitmaps, etc. -class __declspec(novtable) Canvas -{ -public: - virtual ~Canvas(); - - Canvas(const Canvas& other) = delete; - - // Creates the canvas using the specified rendering engine. May return nullptr. - static Canvas* Create(Renderer renderer); - - int GetW() const { return m_W; } - int GetH() const { return m_H; } - - void SetAccurateText(bool option) { m_AccurateText = option; } - - // Resize the draw area of the Canvas. This function must not be called if BeginDraw() has been - // called and has not yet been matched by a correspoding call to EndDraw. - virtual void Resize(int w, int h); - - // BeginDraw() must be matched by a corresponding call to EndDraw(). Drawing functions must be - // be called only between BeginDraw() and EndDraw(). - virtual bool BeginDraw() = 0; - virtual void EndDraw() = 0; - - // Allows the use of Gdiplus::Graphics to perform drawing. Must be called between BeginDraw() - // and EndDraw(). BeginGdiplusGraphicsContext() must be matched by a corresponding call to - // EndGdiplusGraphicsContext(). While in the Gdiplus context, non-const member functions of - // this class must not be called. - virtual Gdiplus::Graphics& BeginGdiplusContext() = 0; - virtual void EndGdiplusContext() = 0; - - // Returns a read-only DC. Must be called between BeginDraw() and EndDraw(). GetDC() must be - // matched by a corresponding call to ReleaseDC(). While in the Gdiplus context, non-const - // member functions of this class must not be called. - virtual HDC GetDC() = 0; - virtual void ReleaseDC(HDC dc) = 0; - - // The Create* functions allocate objects specific to this Canvas object. - virtual FontCollection* CreateFontCollection() = 0; - virtual TextFormat* CreateTextFormat() = 0; - - virtual bool IsTransparentPixel(int x, int y) = 0; - - virtual void SetTransform(const Gdiplus::Matrix& matrix) = 0; - virtual void ResetTransform() = 0; - virtual void RotateTransform(float angle, float x, float y, float dx, float dy) = 0; - - virtual void SetAntiAliasing(bool enable) = 0; - virtual void SetTextAntiAliasing(bool enable) = 0; - - virtual void Clear(const Gdiplus::Color& color = Gdiplus::Color(0, 0, 0, 0)) = 0; - - virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) = 0; - virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) = 0; - virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) = 0; - - virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) = 0; - - virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) = 0; - -protected: - Canvas(); - - int m_W; - int m_H; - - // GDI+, by default, includes padding around the string and also has a larger character spacing - // compared to DirectWrite. In order to minimize diffeences between the text renderers, - // an option is provided to enable accurate (typographic) text rendering. If set to |true|, - // it is expected that there is no padding around the text and that the output is similar to - // the default DirectWrite output. Otherwise, the expected result should be similar to that of - // non-typographic GDI+. - bool m_AccurateText; -}; - -} // namespace Gfx - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_CANVAS_H_ +#define RM_GFX_CANVAS_H_ + +#include "FontCollection.h" +#include "TextFormat.h" + +namespace Gfx { + +enum class Renderer +{ + GDIP, + D2D, + + // Attempts to use D2D. If D2D is not available, fallbacks to use GDI+. + PreferD2D +}; + +// Provides methods for drawing text, bitmaps, etc. +class __declspec(novtable) Canvas +{ +public: + virtual ~Canvas(); + + Canvas(const Canvas& other) = delete; + + // Creates the canvas using the specified rendering engine. May return nullptr. + static Canvas* Create(Renderer renderer); + + int GetW() const { return m_W; } + int GetH() const { return m_H; } + + void SetAccurateText(bool option) { m_AccurateText = option; } + + // Resize the draw area of the Canvas. This function must not be called if BeginDraw() has been + // called and has not yet been matched by a correspoding call to EndDraw. + virtual void Resize(int w, int h); + + // BeginDraw() must be matched by a corresponding call to EndDraw(). Drawing functions must be + // be called only between BeginDraw() and EndDraw(). + virtual bool BeginDraw() = 0; + virtual void EndDraw() = 0; + + // Allows the use of Gdiplus::Graphics to perform drawing. Must be called between BeginDraw() + // and EndDraw(). BeginGdiplusGraphicsContext() must be matched by a corresponding call to + // EndGdiplusGraphicsContext(). While in the Gdiplus context, non-const member functions of + // this class must not be called. + virtual Gdiplus::Graphics& BeginGdiplusContext() = 0; + virtual void EndGdiplusContext() = 0; + + // Returns a read-only DC. Must be called between BeginDraw() and EndDraw(). GetDC() must be + // matched by a corresponding call to ReleaseDC(). While in the Gdiplus context, non-const + // member functions of this class must not be called. + virtual HDC GetDC() = 0; + virtual void ReleaseDC(HDC dc) = 0; + + // The Create* functions allocate objects specific to this Canvas object. + virtual FontCollection* CreateFontCollection() = 0; + virtual TextFormat* CreateTextFormat() = 0; + + virtual bool IsTransparentPixel(int x, int y) = 0; + + virtual void SetTransform(const Gdiplus::Matrix& matrix) = 0; + virtual void ResetTransform() = 0; + virtual void RotateTransform(float angle, float x, float y, float dx, float dy) = 0; + + virtual void SetAntiAliasing(bool enable) = 0; + virtual void SetTextAntiAliasing(bool enable) = 0; + + virtual void Clear(const Gdiplus::Color& color = Gdiplus::Color(0, 0, 0, 0)) = 0; + + virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) = 0; + virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) = 0; + virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) = 0; + + virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) = 0; + + virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) = 0; + +protected: + Canvas(); + + int m_W; + int m_H; + + // GDI+, by default, includes padding around the string and also has a larger character spacing + // compared to DirectWrite. In order to minimize diffeences between the text renderers, + // an option is provided to enable accurate (typographic) text rendering. If set to |true|, + // it is expected that there is no padding around the text and that the output is similar to + // the default DirectWrite output. Otherwise, the expected result should be similar to that of + // non-typographic GDI+. + bool m_AccurateText; +}; + +} // namespace Gfx + #endif \ No newline at end of file diff --git a/Common/Gfx/CanvasD2D.cpp b/Common/Gfx/CanvasD2D.cpp index 55c79f1d..8f390228 100644 --- a/Common/Gfx/CanvasD2D.cpp +++ b/Common/Gfx/CanvasD2D.cpp @@ -1,484 +1,484 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "CanvasD2D.h" -#include "TextFormatD2D.h" -#include "Util/DWriteFontCollectionLoader.h" -#include "Util/DWriteHelpers.h" -#include "Util/WICBitmapLockGDIP.h" -#include "../../Library/Litestep.h" - -namespace { - -D2D1_COLOR_F ToColorF(const Gdiplus::Color& color) -{ - return D2D1::ColorF(color.GetR() / 255.0f, color.GetG() / 255.0f, color.GetB() / 255.0f, color.GetA() / 255.0f); -} - -D2D1_RECT_F ToRectF(const Gdiplus::Rect& rect) -{ - return D2D1::RectF((FLOAT)rect.X, (FLOAT)rect.Y, (FLOAT)(rect.X + rect.Width), (FLOAT)(rect.Y + rect.Height)); -} - -D2D1_RECT_F ToRectF(const Gdiplus::RectF& rect) -{ - return D2D1::RectF(rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height); -} - -} // namespace - -namespace Gfx { - -UINT CanvasD2D::c_Instances = 0; -Microsoft::WRL::ComPtr CanvasD2D::c_D2DFactory; -Microsoft::WRL::ComPtr CanvasD2D::c_DWFactory; -Microsoft::WRL::ComPtr CanvasD2D::c_DWGDIInterop; -Microsoft::WRL::ComPtr CanvasD2D::c_WICFactory; - -CanvasD2D::CanvasD2D() : Canvas(), - m_Bitmap(), - m_TextAntiAliasing(false), - m_CanUseAxisAlignClip(false) -{ -} - -CanvasD2D::~CanvasD2D() -{ - Finalize(); -} - -bool CanvasD2D::Initialize() -{ - ++c_Instances; - if (c_Instances == 1) - { - if (!IsWindows7OrGreater()) return false; - - D2D1_FACTORY_OPTIONS fo = {}; -#ifdef _DEBUG - fo.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; -#endif - - HRESULT hr = D2D1CreateFactory( - D2D1_FACTORY_TYPE_SINGLE_THREADED, - fo, - c_D2DFactory.GetAddressOf()); - if (FAILED(hr)) return false; - - hr = CoCreateInstance( - CLSID_WICImagingFactory, - nullptr, - CLSCTX_INPROC_SERVER, - IID_IWICImagingFactory, - (LPVOID*)c_WICFactory.GetAddressOf()); - if (FAILED(hr)) return false; - - hr = DWriteCreateFactory( - DWRITE_FACTORY_TYPE_SHARED, - __uuidof(c_DWFactory), - (IUnknown**)c_DWFactory.GetAddressOf()); - if (FAILED(hr)) return false; - - hr = c_DWFactory->GetGdiInterop(c_DWGDIInterop.GetAddressOf()); - if (FAILED(hr)) return false; - - hr = c_DWFactory->RegisterFontCollectionLoader(Util::DWriteFontCollectionLoader::GetInstance()); - if (FAILED(hr)) return false; - } - - return true; -} - -void CanvasD2D::Finalize() -{ - --c_Instances; - if (c_Instances == 0) - { - c_D2DFactory.Reset(); - c_WICFactory.Reset(); - c_DWGDIInterop.Reset(); - - if (c_DWFactory) - { - c_DWFactory->UnregisterFontCollectionLoader(Util::DWriteFontCollectionLoader::GetInstance()); - c_DWFactory.Reset(); - } - } -} - -void CanvasD2D::Resize(int w, int h) -{ - __super::Resize(w, h); - - m_Target.Reset(); - - m_Bitmap.Resize(w, h); - - m_GdipBitmap.reset(new Gdiplus::Bitmap(w, h, w * 4, PixelFormat32bppPARGB, m_Bitmap.GetData())); - m_GdipGraphics.reset(new Gdiplus::Graphics(m_GdipBitmap.get())); -} - -bool CanvasD2D::BeginDraw() -{ - return true; -} - -void CanvasD2D::EndDraw() -{ - EndTargetDraw(); -} - -bool CanvasD2D::BeginTargetDraw() -{ - if (m_Target) return true; - - const D2D1_PIXEL_FORMAT format = D2D1::PixelFormat( - DXGI_FORMAT_B8G8R8A8_UNORM, - D2D1_ALPHA_MODE_PREMULTIPLIED); - - const D2D1_RENDER_TARGET_PROPERTIES properties = D2D1::RenderTargetProperties( - D2D1_RENDER_TARGET_TYPE_DEFAULT, - format, - 0.0f, // Default DPI - 0.0f, // Default DPI - D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE); - - // A new Direct2D render target must be created for each sequence of Direct2D draw operations - // since we use GDI+ to render to the same pixel data. Without creating a new render target - // each time, it has been found that Direct2D may overwrite the draws by GDI+ since it is - // unaware of the changes made by GDI+. By creating a new render target and then releasing it - // before the next GDI+ draw operations, we ensure that the pixel data result is as expected - // Once GDI+ drawing is no longer needed, we change to recreate the render target only when the - // bitmap size is changed. - HRESULT hr = c_D2DFactory->CreateWicBitmapRenderTarget(&m_Bitmap, properties, &m_Target); - if (SUCCEEDED(hr)) - { - SetTextAntiAliasing(m_TextAntiAliasing); - - m_Target->BeginDraw(); - - // Apply any transforms that occurred before creation of |m_Target|. - UpdateTargetTransform(); - - return true; - } - - return false; -} - -void CanvasD2D::EndTargetDraw() -{ - if (m_Target) - { - m_Target->EndDraw(); - m_Target.Reset(); - } -} - -Gdiplus::Graphics& CanvasD2D::BeginGdiplusContext() -{ - EndTargetDraw(); - return *m_GdipGraphics; -} - -void CanvasD2D::EndGdiplusContext() -{ -} - -HDC CanvasD2D::GetDC() -{ - EndTargetDraw(); - - HDC dcMemory = CreateCompatibleDC(nullptr); - SelectObject(dcMemory, m_Bitmap.GetHandle()); - return dcMemory; -} - -void CanvasD2D::ReleaseDC(HDC dc) -{ - DeleteDC(dc); -} - -bool CanvasD2D::IsTransparentPixel(int x, int y) -{ - if (!(x >= 0 && y >= 0 && x < m_W && y < m_H)) return false; - - bool transparent = true; - - DWORD* data = (DWORD*)m_Bitmap.GetData(); - if (data) - { - DWORD pixel = data[y * m_W + x]; // Top-down DIB. - transparent = (pixel & 0xFF000000) != 0; - } - - return transparent; -} - -void CanvasD2D::UpdateTargetTransform() -{ - Gdiplus::Matrix gdipMatrix; - m_GdipGraphics->GetTransform(&gdipMatrix); - - D2D1_MATRIX_3X2_F d2dMatrix; - gdipMatrix.GetElements((Gdiplus::REAL*)&d2dMatrix); - - m_Target->SetTransform(d2dMatrix); - m_CanUseAxisAlignClip = - d2dMatrix._12 == 0.0f && d2dMatrix._21 == 0.0f && - d2dMatrix._31 == 0.0f && d2dMatrix._32 == 0.0f; -} - -void CanvasD2D::SetTransform(const Gdiplus::Matrix& matrix) -{ - m_GdipGraphics->SetTransform(&matrix); - - if (m_Target) - { - UpdateTargetTransform(); - } -} - -void CanvasD2D::ResetTransform() -{ - m_GdipGraphics->ResetTransform(); - - if (m_Target) - { - m_Target->SetTransform(D2D1::Matrix3x2F::Identity()); - } -} - -void CanvasD2D::RotateTransform(float angle, float x, float y, float dx, float dy) -{ - m_GdipGraphics->TranslateTransform(x, y); - m_GdipGraphics->RotateTransform(angle); - m_GdipGraphics->TranslateTransform(dx, dy); - - if (m_Target) - { - UpdateTargetTransform(); - } -} - -void CanvasD2D::SetAntiAliasing(bool enable) -{ - // TODO: Set m_Target aliasing? - m_GdipGraphics->SetSmoothingMode( - enable ? Gdiplus::SmoothingModeHighQuality : Gdiplus::SmoothingModeNone); - m_GdipGraphics->SetPixelOffsetMode( - enable ? Gdiplus::PixelOffsetModeHighQuality : Gdiplus::PixelOffsetModeDefault); -} - -void CanvasD2D::SetTextAntiAliasing(bool enable) -{ - // TODO: Add support for D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE? - m_TextAntiAliasing = enable; - - if (m_Target) - { - m_Target->SetTextAntialiasMode( - m_TextAntiAliasing ? D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE : D2D1_TEXT_ANTIALIAS_MODE_ALIASED); - } -} - -void CanvasD2D::Clear(const Gdiplus::Color& color) -{ - if (!m_Target) // Use GDI+ if D2D render target has not been created. - { - m_GdipGraphics->Clear(color); - return; - } - - m_Target->Clear(ToColorF(color)); -} - -void CanvasD2D::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) -{ - if (!BeginTargetDraw()) return; - - Gdiplus::Color color; - brush.GetColor(&color); - - Microsoft::WRL::ComPtr solidBrush; - HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf()); - if (FAILED(hr)) return; - - TextFormatD2D& formatD2D = (TextFormatD2D&)format; - if (!formatD2D.CreateLayout( - str, strLen, rect.Width, rect.Height, !m_AccurateText && m_TextAntiAliasing)) return; - - D2D1_POINT_2F drawPosition; - drawPosition.x = [&]() - { - if (!m_AccurateText) - { - const float xOffset = formatD2D.m_TextFormat->GetFontSize() / 6.0f; - switch (formatD2D.GetHorizontalAlignment()) - { - case HorizontalAlignment::Left: return rect.X + xOffset; - case HorizontalAlignment::Right: return rect.X - xOffset; - } - } - - return rect.X; - } (); - - drawPosition.y = [&]() - { - // GDI+ compatibility. - float yPos = rect.Y - formatD2D.m_LineGap; - switch (formatD2D.GetVerticalAlignment()) - { - case VerticalAlignment::Bottom: yPos -= formatD2D.m_ExtraHeight; break; - case VerticalAlignment::Center: yPos -= formatD2D.m_ExtraHeight / 2; break; - } - - return yPos; - } (); - - if (formatD2D.m_Trimming) - { - D2D1_RECT_F clipRect = ToRectF(rect); - - if (m_CanUseAxisAlignClip) - { - m_Target->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_ALIASED); - } - else - { - const D2D1_LAYER_PARAMETERS layerParams = - D2D1::LayerParameters(clipRect, nullptr, D2D1_ANTIALIAS_MODE_ALIASED); - m_Target->PushLayer(layerParams, nullptr); - } - } - - m_Target->DrawTextLayout(drawPosition, formatD2D.m_TextLayout.Get(), solidBrush.Get()); - - if (formatD2D.m_Trimming) - { - if (m_CanUseAxisAlignClip) - { - m_Target->PopAxisAlignedClip(); - } - else - { - m_Target->PopLayer(); - } - } -} - -bool CanvasD2D::MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) -{ - TextFormatD2D& formatD2D = (TextFormatD2D&)format; - const DWRITE_TEXT_METRICS metrics = formatD2D.GetMetrics(str, strLen, !m_AccurateText); - rect.Width = metrics.width; - rect.Height = metrics.height; - return true; -} - -bool CanvasD2D::MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) -{ - TextFormatD2D& formatD2D = (TextFormatD2D&)format; - formatD2D.m_TextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_WRAP); - - const DWRITE_TEXT_METRICS metrics = formatD2D.GetMetrics(str, strLen, !m_AccurateText, rect.Width); - rect.Width = metrics.width; - rect.Height = metrics.height; - lines = metrics.lineCount; - - if (rect.Height > 0.0f) - { - // GDI+ draws multi-line text even though the last line may be clipped slightly at the - // bottom. This is a workaround to emulate that behaviour. - rect.Height += 1.0f; - } - else - { - // GDI+ compatibility: Zero height text has no visible lines. - lines = 0; - } - return true; -} - -void CanvasD2D::DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) -{ - if (srcRect.Width != dstRect.Width || srcRect.Height != dstRect.Height) - { - // If the bitmap needs to be scaled, get rid of the D2D target and use the GDI+ code path - // to draw the bitmap. This is due to antialiasing differences between GDI+ and D2D on - // scaled bitmaps. - EndTargetDraw(); - } - - if (!m_Target) // Use GDI+ if D2D render target has not been created. - { - m_GdipGraphics->DrawImage( - bitmap, dstRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Gdiplus::UnitPixel); - return; - } - - // The D2D DrawBitmap seems to perform exactly like Gdiplus::Graphics::DrawImage since we are - // not using a hardware accelerated render target. Nevertheless, we will use it to avoid - // the EndDraw() call needed for GDI+ drawing. - Util::WICBitmapLockGDIP* bitmapLock = new Util::WICBitmapLockGDIP(); - Gdiplus::Rect lockRect(0, 0, bitmap->GetWidth(), bitmap->GetHeight()); - Gdiplus::Status status = bitmap->LockBits( - &lockRect, Gdiplus::ImageLockModeRead, PixelFormat32bppPARGB, bitmapLock->GetBitmapData()); - if (status == Gdiplus::Ok) - { - D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties( - D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED)); - Microsoft::WRL::ComPtr d2dBitmap; - HRESULT hr = m_Target->CreateSharedBitmap( - __uuidof(IWICBitmapLock), bitmapLock, &props, d2dBitmap.GetAddressOf()); - if (SUCCEEDED(hr)) - { - auto rDst = ToRectF(dstRect); - auto rSrc = ToRectF(srcRect); - m_Target->DrawBitmap(d2dBitmap.Get(), rDst, 1.0F, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, rSrc); - } - - // D2D will still use the pixel data after this call (at the next Flush() or EndDraw()). - bitmap->UnlockBits(bitmapLock->GetBitmapData()); - } - - bitmapLock->Release(); -} - -void CanvasD2D::FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) -{ - if (!m_Target) // Use GDI+ if D2D render target has not been created. - { - m_GdipGraphics->FillRectangle(&brush, rect); - return; - } - - Gdiplus::Color color; - brush.GetColor(&color); - - Microsoft::WRL::ComPtr solidBrush; - HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf()); - if (SUCCEEDED(hr)) - { - m_Target->FillRectangle(ToRectF(rect), solidBrush.Get()); - } -} - -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "CanvasD2D.h" +#include "TextFormatD2D.h" +#include "Util/DWriteFontCollectionLoader.h" +#include "Util/DWriteHelpers.h" +#include "Util/WICBitmapLockGDIP.h" +#include "../../Library/Litestep.h" + +namespace { + +D2D1_COLOR_F ToColorF(const Gdiplus::Color& color) +{ + return D2D1::ColorF(color.GetR() / 255.0f, color.GetG() / 255.0f, color.GetB() / 255.0f, color.GetA() / 255.0f); +} + +D2D1_RECT_F ToRectF(const Gdiplus::Rect& rect) +{ + return D2D1::RectF((FLOAT)rect.X, (FLOAT)rect.Y, (FLOAT)(rect.X + rect.Width), (FLOAT)(rect.Y + rect.Height)); +} + +D2D1_RECT_F ToRectF(const Gdiplus::RectF& rect) +{ + return D2D1::RectF(rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height); +} + +} // namespace + +namespace Gfx { + +UINT CanvasD2D::c_Instances = 0; +Microsoft::WRL::ComPtr CanvasD2D::c_D2DFactory; +Microsoft::WRL::ComPtr CanvasD2D::c_DWFactory; +Microsoft::WRL::ComPtr CanvasD2D::c_DWGDIInterop; +Microsoft::WRL::ComPtr CanvasD2D::c_WICFactory; + +CanvasD2D::CanvasD2D() : Canvas(), + m_Bitmap(), + m_TextAntiAliasing(false), + m_CanUseAxisAlignClip(false) +{ +} + +CanvasD2D::~CanvasD2D() +{ + Finalize(); +} + +bool CanvasD2D::Initialize() +{ + ++c_Instances; + if (c_Instances == 1) + { + if (!IsWindows7OrGreater()) return false; + + D2D1_FACTORY_OPTIONS fo = {}; +#ifdef _DEBUG + fo.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; +#endif + + HRESULT hr = D2D1CreateFactory( + D2D1_FACTORY_TYPE_SINGLE_THREADED, + fo, + c_D2DFactory.GetAddressOf()); + if (FAILED(hr)) return false; + + hr = CoCreateInstance( + CLSID_WICImagingFactory, + nullptr, + CLSCTX_INPROC_SERVER, + IID_IWICImagingFactory, + (LPVOID*)c_WICFactory.GetAddressOf()); + if (FAILED(hr)) return false; + + hr = DWriteCreateFactory( + DWRITE_FACTORY_TYPE_SHARED, + __uuidof(c_DWFactory), + (IUnknown**)c_DWFactory.GetAddressOf()); + if (FAILED(hr)) return false; + + hr = c_DWFactory->GetGdiInterop(c_DWGDIInterop.GetAddressOf()); + if (FAILED(hr)) return false; + + hr = c_DWFactory->RegisterFontCollectionLoader(Util::DWriteFontCollectionLoader::GetInstance()); + if (FAILED(hr)) return false; + } + + return true; +} + +void CanvasD2D::Finalize() +{ + --c_Instances; + if (c_Instances == 0) + { + c_D2DFactory.Reset(); + c_WICFactory.Reset(); + c_DWGDIInterop.Reset(); + + if (c_DWFactory) + { + c_DWFactory->UnregisterFontCollectionLoader(Util::DWriteFontCollectionLoader::GetInstance()); + c_DWFactory.Reset(); + } + } +} + +void CanvasD2D::Resize(int w, int h) +{ + __super::Resize(w, h); + + m_Target.Reset(); + + m_Bitmap.Resize(w, h); + + m_GdipBitmap.reset(new Gdiplus::Bitmap(w, h, w * 4, PixelFormat32bppPARGB, m_Bitmap.GetData())); + m_GdipGraphics.reset(new Gdiplus::Graphics(m_GdipBitmap.get())); +} + +bool CanvasD2D::BeginDraw() +{ + return true; +} + +void CanvasD2D::EndDraw() +{ + EndTargetDraw(); +} + +bool CanvasD2D::BeginTargetDraw() +{ + if (m_Target) return true; + + const D2D1_PIXEL_FORMAT format = D2D1::PixelFormat( + DXGI_FORMAT_B8G8R8A8_UNORM, + D2D1_ALPHA_MODE_PREMULTIPLIED); + + const D2D1_RENDER_TARGET_PROPERTIES properties = D2D1::RenderTargetProperties( + D2D1_RENDER_TARGET_TYPE_DEFAULT, + format, + 0.0f, // Default DPI + 0.0f, // Default DPI + D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE); + + // A new Direct2D render target must be created for each sequence of Direct2D draw operations + // since we use GDI+ to render to the same pixel data. Without creating a new render target + // each time, it has been found that Direct2D may overwrite the draws by GDI+ since it is + // unaware of the changes made by GDI+. By creating a new render target and then releasing it + // before the next GDI+ draw operations, we ensure that the pixel data result is as expected + // Once GDI+ drawing is no longer needed, we change to recreate the render target only when the + // bitmap size is changed. + HRESULT hr = c_D2DFactory->CreateWicBitmapRenderTarget(&m_Bitmap, properties, &m_Target); + if (SUCCEEDED(hr)) + { + SetTextAntiAliasing(m_TextAntiAliasing); + + m_Target->BeginDraw(); + + // Apply any transforms that occurred before creation of |m_Target|. + UpdateTargetTransform(); + + return true; + } + + return false; +} + +void CanvasD2D::EndTargetDraw() +{ + if (m_Target) + { + m_Target->EndDraw(); + m_Target.Reset(); + } +} + +Gdiplus::Graphics& CanvasD2D::BeginGdiplusContext() +{ + EndTargetDraw(); + return *m_GdipGraphics; +} + +void CanvasD2D::EndGdiplusContext() +{ +} + +HDC CanvasD2D::GetDC() +{ + EndTargetDraw(); + + HDC dcMemory = CreateCompatibleDC(nullptr); + SelectObject(dcMemory, m_Bitmap.GetHandle()); + return dcMemory; +} + +void CanvasD2D::ReleaseDC(HDC dc) +{ + DeleteDC(dc); +} + +bool CanvasD2D::IsTransparentPixel(int x, int y) +{ + if (!(x >= 0 && y >= 0 && x < m_W && y < m_H)) return false; + + bool transparent = true; + + DWORD* data = (DWORD*)m_Bitmap.GetData(); + if (data) + { + DWORD pixel = data[y * m_W + x]; // Top-down DIB. + transparent = (pixel & 0xFF000000) != 0; + } + + return transparent; +} + +void CanvasD2D::UpdateTargetTransform() +{ + Gdiplus::Matrix gdipMatrix; + m_GdipGraphics->GetTransform(&gdipMatrix); + + D2D1_MATRIX_3X2_F d2dMatrix; + gdipMatrix.GetElements((Gdiplus::REAL*)&d2dMatrix); + + m_Target->SetTransform(d2dMatrix); + m_CanUseAxisAlignClip = + d2dMatrix._12 == 0.0f && d2dMatrix._21 == 0.0f && + d2dMatrix._31 == 0.0f && d2dMatrix._32 == 0.0f; +} + +void CanvasD2D::SetTransform(const Gdiplus::Matrix& matrix) +{ + m_GdipGraphics->SetTransform(&matrix); + + if (m_Target) + { + UpdateTargetTransform(); + } +} + +void CanvasD2D::ResetTransform() +{ + m_GdipGraphics->ResetTransform(); + + if (m_Target) + { + m_Target->SetTransform(D2D1::Matrix3x2F::Identity()); + } +} + +void CanvasD2D::RotateTransform(float angle, float x, float y, float dx, float dy) +{ + m_GdipGraphics->TranslateTransform(x, y); + m_GdipGraphics->RotateTransform(angle); + m_GdipGraphics->TranslateTransform(dx, dy); + + if (m_Target) + { + UpdateTargetTransform(); + } +} + +void CanvasD2D::SetAntiAliasing(bool enable) +{ + // TODO: Set m_Target aliasing? + m_GdipGraphics->SetSmoothingMode( + enable ? Gdiplus::SmoothingModeHighQuality : Gdiplus::SmoothingModeNone); + m_GdipGraphics->SetPixelOffsetMode( + enable ? Gdiplus::PixelOffsetModeHighQuality : Gdiplus::PixelOffsetModeDefault); +} + +void CanvasD2D::SetTextAntiAliasing(bool enable) +{ + // TODO: Add support for D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE? + m_TextAntiAliasing = enable; + + if (m_Target) + { + m_Target->SetTextAntialiasMode( + m_TextAntiAliasing ? D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE : D2D1_TEXT_ANTIALIAS_MODE_ALIASED); + } +} + +void CanvasD2D::Clear(const Gdiplus::Color& color) +{ + if (!m_Target) // Use GDI+ if D2D render target has not been created. + { + m_GdipGraphics->Clear(color); + return; + } + + m_Target->Clear(ToColorF(color)); +} + +void CanvasD2D::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) +{ + if (!BeginTargetDraw()) return; + + Gdiplus::Color color; + brush.GetColor(&color); + + Microsoft::WRL::ComPtr solidBrush; + HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf()); + if (FAILED(hr)) return; + + TextFormatD2D& formatD2D = (TextFormatD2D&)format; + if (!formatD2D.CreateLayout( + str, strLen, rect.Width, rect.Height, !m_AccurateText && m_TextAntiAliasing)) return; + + D2D1_POINT_2F drawPosition; + drawPosition.x = [&]() + { + if (!m_AccurateText) + { + const float xOffset = formatD2D.m_TextFormat->GetFontSize() / 6.0f; + switch (formatD2D.GetHorizontalAlignment()) + { + case HorizontalAlignment::Left: return rect.X + xOffset; + case HorizontalAlignment::Right: return rect.X - xOffset; + } + } + + return rect.X; + } (); + + drawPosition.y = [&]() + { + // GDI+ compatibility. + float yPos = rect.Y - formatD2D.m_LineGap; + switch (formatD2D.GetVerticalAlignment()) + { + case VerticalAlignment::Bottom: yPos -= formatD2D.m_ExtraHeight; break; + case VerticalAlignment::Center: yPos -= formatD2D.m_ExtraHeight / 2; break; + } + + return yPos; + } (); + + if (formatD2D.m_Trimming) + { + D2D1_RECT_F clipRect = ToRectF(rect); + + if (m_CanUseAxisAlignClip) + { + m_Target->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_ALIASED); + } + else + { + const D2D1_LAYER_PARAMETERS layerParams = + D2D1::LayerParameters(clipRect, nullptr, D2D1_ANTIALIAS_MODE_ALIASED); + m_Target->PushLayer(layerParams, nullptr); + } + } + + m_Target->DrawTextLayout(drawPosition, formatD2D.m_TextLayout.Get(), solidBrush.Get()); + + if (formatD2D.m_Trimming) + { + if (m_CanUseAxisAlignClip) + { + m_Target->PopAxisAlignedClip(); + } + else + { + m_Target->PopLayer(); + } + } +} + +bool CanvasD2D::MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) +{ + TextFormatD2D& formatD2D = (TextFormatD2D&)format; + const DWRITE_TEXT_METRICS metrics = formatD2D.GetMetrics(str, strLen, !m_AccurateText); + rect.Width = metrics.width; + rect.Height = metrics.height; + return true; +} + +bool CanvasD2D::MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) +{ + TextFormatD2D& formatD2D = (TextFormatD2D&)format; + formatD2D.m_TextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_WRAP); + + const DWRITE_TEXT_METRICS metrics = formatD2D.GetMetrics(str, strLen, !m_AccurateText, rect.Width); + rect.Width = metrics.width; + rect.Height = metrics.height; + lines = metrics.lineCount; + + if (rect.Height > 0.0f) + { + // GDI+ draws multi-line text even though the last line may be clipped slightly at the + // bottom. This is a workaround to emulate that behaviour. + rect.Height += 1.0f; + } + else + { + // GDI+ compatibility: Zero height text has no visible lines. + lines = 0; + } + return true; +} + +void CanvasD2D::DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) +{ + if (srcRect.Width != dstRect.Width || srcRect.Height != dstRect.Height) + { + // If the bitmap needs to be scaled, get rid of the D2D target and use the GDI+ code path + // to draw the bitmap. This is due to antialiasing differences between GDI+ and D2D on + // scaled bitmaps. + EndTargetDraw(); + } + + if (!m_Target) // Use GDI+ if D2D render target has not been created. + { + m_GdipGraphics->DrawImage( + bitmap, dstRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Gdiplus::UnitPixel); + return; + } + + // The D2D DrawBitmap seems to perform exactly like Gdiplus::Graphics::DrawImage since we are + // not using a hardware accelerated render target. Nevertheless, we will use it to avoid + // the EndDraw() call needed for GDI+ drawing. + Util::WICBitmapLockGDIP* bitmapLock = new Util::WICBitmapLockGDIP(); + Gdiplus::Rect lockRect(0, 0, bitmap->GetWidth(), bitmap->GetHeight()); + Gdiplus::Status status = bitmap->LockBits( + &lockRect, Gdiplus::ImageLockModeRead, PixelFormat32bppPARGB, bitmapLock->GetBitmapData()); + if (status == Gdiplus::Ok) + { + D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties( + D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED)); + Microsoft::WRL::ComPtr d2dBitmap; + HRESULT hr = m_Target->CreateSharedBitmap( + __uuidof(IWICBitmapLock), bitmapLock, &props, d2dBitmap.GetAddressOf()); + if (SUCCEEDED(hr)) + { + auto rDst = ToRectF(dstRect); + auto rSrc = ToRectF(srcRect); + m_Target->DrawBitmap(d2dBitmap.Get(), rDst, 1.0F, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, rSrc); + } + + // D2D will still use the pixel data after this call (at the next Flush() or EndDraw()). + bitmap->UnlockBits(bitmapLock->GetBitmapData()); + } + + bitmapLock->Release(); +} + +void CanvasD2D::FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) +{ + if (!m_Target) // Use GDI+ if D2D render target has not been created. + { + m_GdipGraphics->FillRectangle(&brush, rect); + return; + } + + Gdiplus::Color color; + brush.GetColor(&color); + + Microsoft::WRL::ComPtr solidBrush; + HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf()); + if (SUCCEEDED(hr)) + { + m_Target->FillRectangle(ToRectF(rect), solidBrush.Get()); + } +} + +} // namespace Gfx diff --git a/Common/Gfx/CanvasD2D.h b/Common/Gfx/CanvasD2D.h index bc20f5ee..b30465aa 100644 --- a/Common/Gfx/CanvasD2D.h +++ b/Common/Gfx/CanvasD2D.h @@ -1,118 +1,118 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_GFX_CANVASD2D_H_ -#define RM_GFX_CANVASD2D_H_ - -#include "Canvas.h" -#include "FontCollectionD2D.h" -#include "TextFormatD2D.h" -#include "Util/WICBitmapDIB.h" -#include -#include -#include // For Gdiplus.h. -#include -#include -#include -#include -#include -#include - -namespace Gfx { - -// Provides a Direct2D/DirectWrite implementation of Canvas. -class CanvasD2D : public Canvas -{ -public: - static bool Initialize(); - static void Finalize(); - - virtual void Resize(int w, int h); - - virtual bool BeginDraw(); - virtual void EndDraw(); - - virtual Gdiplus::Graphics& BeginGdiplusContext() override; - virtual void EndGdiplusContext() override; - - virtual HDC GetDC() override; - virtual void ReleaseDC(HDC dc) override; - - virtual FontCollection* CreateFontCollection() override { return new FontCollectionD2D(); } - virtual TextFormat* CreateTextFormat() override { return new TextFormatD2D(); } - - virtual bool IsTransparentPixel(int x, int y) override; - - virtual void SetTransform(const Gdiplus::Matrix& matrix) override; - virtual void ResetTransform() override; - virtual void RotateTransform(float angle, float x, float y, float dx, float dy) override; - - virtual void SetAntiAliasing(bool enable) override; - virtual void SetTextAntiAliasing(bool enable) override; - - virtual void Clear(const Gdiplus::Color& color) override; - - virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) override; - virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) override; - virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) override; - - virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) override; - - virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) override; - -private: - friend class Canvas; - friend class FontCollectionD2D; - friend class TextFormatD2D; - - CanvasD2D(); - ~CanvasD2D(); - - CanvasD2D(const CanvasD2D& other) = delete; - CanvasD2D& operator=(CanvasD2D other) = delete; - - bool BeginTargetDraw(); - void EndTargetDraw(); - - // Sets the |m_Target| transformation to be equal to that of |m_GdipGraphics|. - void UpdateTargetTransform(); - - Microsoft::WRL::ComPtr m_Target; - - // Underlying pixel data shared by both m_Target and m_GdipBitmap. - Util::WICBitmapDIB m_Bitmap; - - // GDI+ objects that share the pixel data of m_Bitmap. - std::unique_ptr m_GdipGraphics; - std::unique_ptr m_GdipBitmap; - - bool m_TextAntiAliasing; - - // |true| if PushAxisAlignedClip()/PopAxisAlignedClip() can be used. - bool m_CanUseAxisAlignClip; - - static UINT c_Instances; - static Microsoft::WRL::ComPtr c_D2DFactory; - static Microsoft::WRL::ComPtr c_DWFactory; - static Microsoft::WRL::ComPtr c_DWGDIInterop; - static Microsoft::WRL::ComPtr c_WICFactory; -}; - -} // namespace Gfx - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_CANVASD2D_H_ +#define RM_GFX_CANVASD2D_H_ + +#include "Canvas.h" +#include "FontCollectionD2D.h" +#include "TextFormatD2D.h" +#include "Util/WICBitmapDIB.h" +#include +#include +#include // For Gdiplus.h. +#include +#include +#include +#include +#include +#include + +namespace Gfx { + +// Provides a Direct2D/DirectWrite implementation of Canvas. +class CanvasD2D : public Canvas +{ +public: + static bool Initialize(); + static void Finalize(); + + virtual void Resize(int w, int h); + + virtual bool BeginDraw(); + virtual void EndDraw(); + + virtual Gdiplus::Graphics& BeginGdiplusContext() override; + virtual void EndGdiplusContext() override; + + virtual HDC GetDC() override; + virtual void ReleaseDC(HDC dc) override; + + virtual FontCollection* CreateFontCollection() override { return new FontCollectionD2D(); } + virtual TextFormat* CreateTextFormat() override { return new TextFormatD2D(); } + + virtual bool IsTransparentPixel(int x, int y) override; + + virtual void SetTransform(const Gdiplus::Matrix& matrix) override; + virtual void ResetTransform() override; + virtual void RotateTransform(float angle, float x, float y, float dx, float dy) override; + + virtual void SetAntiAliasing(bool enable) override; + virtual void SetTextAntiAliasing(bool enable) override; + + virtual void Clear(const Gdiplus::Color& color) override; + + virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) override; + virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) override; + virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) override; + + virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) override; + + virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) override; + +private: + friend class Canvas; + friend class FontCollectionD2D; + friend class TextFormatD2D; + + CanvasD2D(); + ~CanvasD2D(); + + CanvasD2D(const CanvasD2D& other) = delete; + CanvasD2D& operator=(CanvasD2D other) = delete; + + bool BeginTargetDraw(); + void EndTargetDraw(); + + // Sets the |m_Target| transformation to be equal to that of |m_GdipGraphics|. + void UpdateTargetTransform(); + + Microsoft::WRL::ComPtr m_Target; + + // Underlying pixel data shared by both m_Target and m_GdipBitmap. + Util::WICBitmapDIB m_Bitmap; + + // GDI+ objects that share the pixel data of m_Bitmap. + std::unique_ptr m_GdipGraphics; + std::unique_ptr m_GdipBitmap; + + bool m_TextAntiAliasing; + + // |true| if PushAxisAlignedClip()/PopAxisAlignedClip() can be used. + bool m_CanUseAxisAlignClip; + + static UINT c_Instances; + static Microsoft::WRL::ComPtr c_D2DFactory; + static Microsoft::WRL::ComPtr c_DWFactory; + static Microsoft::WRL::ComPtr c_DWGDIInterop; + static Microsoft::WRL::ComPtr c_WICFactory; +}; + +} // namespace Gfx + #endif \ No newline at end of file diff --git a/Common/Gfx/CanvasGDIP.cpp b/Common/Gfx/CanvasGDIP.cpp index d4adc185..be6a70ad 100644 --- a/Common/Gfx/CanvasGDIP.cpp +++ b/Common/Gfx/CanvasGDIP.cpp @@ -1,242 +1,242 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "CanvasGDIP.h" - -namespace Gfx { - -CanvasGDIP::CanvasGDIP() : Canvas(), - m_DIBSection(), - m_DIBSectionPixels() -{ -} - -CanvasGDIP::~CanvasGDIP() -{ - Dispose(); -} - -void CanvasGDIP::Dispose() -{ - if (m_DIBSection) - { - DeleteObject(m_DIBSection); - m_DIBSection = nullptr; - m_DIBSectionPixels = nullptr; - } -} - -void CanvasGDIP::Resize(int w, int h) -{ - __super::Resize(w, h); - - Dispose(); - - BITMAPV4HEADER bh = {sizeof(BITMAPV4HEADER)}; - bh.bV4Width = w; - bh.bV4Height = -h; // Top-down DIB - bh.bV4Planes = 1; - bh.bV4BitCount = 32; - bh.bV4V4Compression = BI_BITFIELDS; - bh.bV4RedMask = 0x00FF0000; - bh.bV4GreenMask = 0x0000FF00; - bh.bV4BlueMask = 0x000000FF; - bh.bV4AlphaMask = 0xFF000000; - - m_DIBSection = CreateDIBSection( - nullptr, - (BITMAPINFO*)&bh, - DIB_RGB_COLORS, - (void**)&m_DIBSectionPixels, - nullptr, - 0); - - // Create GDI+ bitmap from the DIBSection pixels - m_Bitmap.reset(new Gdiplus::Bitmap(w, h, w * 4, PixelFormat32bppPARGB, (BYTE*)m_DIBSectionPixels)); - m_Graphics.reset(new Gdiplus::Graphics(m_Bitmap.get())); -} - -bool CanvasGDIP::BeginDraw() -{ - m_Graphics->SetInterpolationMode(Gdiplus::InterpolationModeDefault); - m_Graphics->SetCompositingQuality(Gdiplus::CompositingQualityDefault); - return true; -} - -void CanvasGDIP::EndDraw() -{ -} - -Gdiplus::Graphics& CanvasGDIP::BeginGdiplusContext() -{ - return *m_Graphics; -} - -void CanvasGDIP::EndGdiplusContext() -{ -} - -HDC CanvasGDIP::GetDC() -{ - HDC dcMemory = CreateCompatibleDC(nullptr); - SelectObject(dcMemory, m_DIBSection); - return dcMemory; -} - -void CanvasGDIP::ReleaseDC(HDC dc) -{ - DeleteDC(dc); -} - -bool CanvasGDIP::IsTransparentPixel(int x, int y) -{ - if (m_DIBSectionPixels && x >= 0 && y >= 0 && x < m_W && y < m_H) - { - DWORD pixel = m_DIBSectionPixels[y * m_W + x]; // top-down DIB - return ((pixel & 0xFF000000) != 0); - } - - return false; -} - -void CanvasGDIP::SetTransform(const Gdiplus::Matrix& matrix) -{ - m_Graphics->SetTransform(&matrix); -} - -void CanvasGDIP::ResetTransform() -{ - m_Graphics->ResetTransform(); -} - -void CanvasGDIP::RotateTransform(float angle, float x, float y, float dx, float dy) -{ - m_Graphics->TranslateTransform(x, y); - m_Graphics->RotateTransform(angle); - m_Graphics->TranslateTransform(dx, dy); -} - -void CanvasGDIP::SetAntiAliasing(bool enable) -{ - m_Graphics->SetSmoothingMode( - enable ? Gdiplus::SmoothingModeHighQuality : Gdiplus::SmoothingModeNone); - m_Graphics->SetPixelOffsetMode( - enable ? Gdiplus::PixelOffsetModeHighQuality : Gdiplus::PixelOffsetModeDefault); -} - -void CanvasGDIP::SetTextAntiAliasing(bool enable) -{ - m_Graphics->SetTextRenderingHint( - enable ? Gdiplus::TextRenderingHintAntiAlias : Gdiplus::TextRenderingHintSingleBitPerPixelGridFit); -} - -void CanvasGDIP::Clear(const Gdiplus::Color& color) -{ - if (color.GetValue() == 0x00000000) - { - memset(m_DIBSectionPixels, 0, m_W * m_H * 4); - } - else - { - m_Graphics->Clear(color); - } -} - -void CanvasGDIP::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) -{ - Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat; - Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic(); - - if (m_AccurateText) - { - tStringFormat.SetTrimming(stringFormat.GetTrimming()); - tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags()); - tStringFormat.SetAlignment(stringFormat.GetAlignment()); - tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment()); - } - - m_Graphics->DrawString( - str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect, - m_AccurateText ? &tStringFormat : &stringFormat, &brush); -} - -bool CanvasGDIP::MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) -{ - Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat; - Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic(); - - if (m_AccurateText) - { - tStringFormat.SetTrimming(stringFormat.GetTrimming()); - tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags()); - tStringFormat.SetAlignment(stringFormat.GetAlignment()); - tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment()); - } - - const Gdiplus::Status status = m_Graphics->MeasureString( - str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect, - m_AccurateText ? &tStringFormat : &stringFormat, &rect); - - return status == Gdiplus::Ok; -} - -bool CanvasGDIP::MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) -{ - Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat; - Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic(); - - // Set trimming and format temporarily. - const Gdiplus::StringTrimming stringTrimming = stringFormat.GetTrimming(); - stringFormat.SetTrimming(Gdiplus::StringTrimmingNone); - - const INT stringFormatFlags = stringFormat.GetFormatFlags(); - stringFormat.SetFormatFlags(Gdiplus::StringFormatFlagsNoClip); - - if (m_AccurateText) - { - tStringFormat.SetTrimming(stringFormat.GetTrimming()); - tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags()); - tStringFormat.SetAlignment(stringFormat.GetAlignment()); - tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment()); - } - - INT linesFilled = 0; - const Gdiplus::Status status = m_Graphics->MeasureString( - str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect, - m_AccurateText ? &tStringFormat : &stringFormat, &rect, nullptr, &linesFilled); - lines = linesFilled; - - // Restore old options. - stringFormat.SetTrimming(stringTrimming); - stringFormat.SetFormatFlags(stringFormatFlags); - - return status == Gdiplus::Ok; -} - -void CanvasGDIP::DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) -{ - m_Graphics->DrawImage(bitmap, dstRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Gdiplus::UnitPixel); -} - -void CanvasGDIP::FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) -{ - m_Graphics->FillRectangle(&brush, rect); -} - -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "CanvasGDIP.h" + +namespace Gfx { + +CanvasGDIP::CanvasGDIP() : Canvas(), + m_DIBSection(), + m_DIBSectionPixels() +{ +} + +CanvasGDIP::~CanvasGDIP() +{ + Dispose(); +} + +void CanvasGDIP::Dispose() +{ + if (m_DIBSection) + { + DeleteObject(m_DIBSection); + m_DIBSection = nullptr; + m_DIBSectionPixels = nullptr; + } +} + +void CanvasGDIP::Resize(int w, int h) +{ + __super::Resize(w, h); + + Dispose(); + + BITMAPV4HEADER bh = {sizeof(BITMAPV4HEADER)}; + bh.bV4Width = w; + bh.bV4Height = -h; // Top-down DIB + bh.bV4Planes = 1; + bh.bV4BitCount = 32; + bh.bV4V4Compression = BI_BITFIELDS; + bh.bV4RedMask = 0x00FF0000; + bh.bV4GreenMask = 0x0000FF00; + bh.bV4BlueMask = 0x000000FF; + bh.bV4AlphaMask = 0xFF000000; + + m_DIBSection = CreateDIBSection( + nullptr, + (BITMAPINFO*)&bh, + DIB_RGB_COLORS, + (void**)&m_DIBSectionPixels, + nullptr, + 0); + + // Create GDI+ bitmap from the DIBSection pixels + m_Bitmap.reset(new Gdiplus::Bitmap(w, h, w * 4, PixelFormat32bppPARGB, (BYTE*)m_DIBSectionPixels)); + m_Graphics.reset(new Gdiplus::Graphics(m_Bitmap.get())); +} + +bool CanvasGDIP::BeginDraw() +{ + m_Graphics->SetInterpolationMode(Gdiplus::InterpolationModeDefault); + m_Graphics->SetCompositingQuality(Gdiplus::CompositingQualityDefault); + return true; +} + +void CanvasGDIP::EndDraw() +{ +} + +Gdiplus::Graphics& CanvasGDIP::BeginGdiplusContext() +{ + return *m_Graphics; +} + +void CanvasGDIP::EndGdiplusContext() +{ +} + +HDC CanvasGDIP::GetDC() +{ + HDC dcMemory = CreateCompatibleDC(nullptr); + SelectObject(dcMemory, m_DIBSection); + return dcMemory; +} + +void CanvasGDIP::ReleaseDC(HDC dc) +{ + DeleteDC(dc); +} + +bool CanvasGDIP::IsTransparentPixel(int x, int y) +{ + if (m_DIBSectionPixels && x >= 0 && y >= 0 && x < m_W && y < m_H) + { + DWORD pixel = m_DIBSectionPixels[y * m_W + x]; // top-down DIB + return ((pixel & 0xFF000000) != 0); + } + + return false; +} + +void CanvasGDIP::SetTransform(const Gdiplus::Matrix& matrix) +{ + m_Graphics->SetTransform(&matrix); +} + +void CanvasGDIP::ResetTransform() +{ + m_Graphics->ResetTransform(); +} + +void CanvasGDIP::RotateTransform(float angle, float x, float y, float dx, float dy) +{ + m_Graphics->TranslateTransform(x, y); + m_Graphics->RotateTransform(angle); + m_Graphics->TranslateTransform(dx, dy); +} + +void CanvasGDIP::SetAntiAliasing(bool enable) +{ + m_Graphics->SetSmoothingMode( + enable ? Gdiplus::SmoothingModeHighQuality : Gdiplus::SmoothingModeNone); + m_Graphics->SetPixelOffsetMode( + enable ? Gdiplus::PixelOffsetModeHighQuality : Gdiplus::PixelOffsetModeDefault); +} + +void CanvasGDIP::SetTextAntiAliasing(bool enable) +{ + m_Graphics->SetTextRenderingHint( + enable ? Gdiplus::TextRenderingHintAntiAlias : Gdiplus::TextRenderingHintSingleBitPerPixelGridFit); +} + +void CanvasGDIP::Clear(const Gdiplus::Color& color) +{ + if (color.GetValue() == 0x00000000) + { + memset(m_DIBSectionPixels, 0, m_W * m_H * 4); + } + else + { + m_Graphics->Clear(color); + } +} + +void CanvasGDIP::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) +{ + Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat; + Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic(); + + if (m_AccurateText) + { + tStringFormat.SetTrimming(stringFormat.GetTrimming()); + tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags()); + tStringFormat.SetAlignment(stringFormat.GetAlignment()); + tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment()); + } + + m_Graphics->DrawString( + str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect, + m_AccurateText ? &tStringFormat : &stringFormat, &brush); +} + +bool CanvasGDIP::MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) +{ + Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat; + Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic(); + + if (m_AccurateText) + { + tStringFormat.SetTrimming(stringFormat.GetTrimming()); + tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags()); + tStringFormat.SetAlignment(stringFormat.GetAlignment()); + tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment()); + } + + const Gdiplus::Status status = m_Graphics->MeasureString( + str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect, + m_AccurateText ? &tStringFormat : &stringFormat, &rect); + + return status == Gdiplus::Ok; +} + +bool CanvasGDIP::MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) +{ + Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat; + Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic(); + + // Set trimming and format temporarily. + const Gdiplus::StringTrimming stringTrimming = stringFormat.GetTrimming(); + stringFormat.SetTrimming(Gdiplus::StringTrimmingNone); + + const INT stringFormatFlags = stringFormat.GetFormatFlags(); + stringFormat.SetFormatFlags(Gdiplus::StringFormatFlagsNoClip); + + if (m_AccurateText) + { + tStringFormat.SetTrimming(stringFormat.GetTrimming()); + tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags()); + tStringFormat.SetAlignment(stringFormat.GetAlignment()); + tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment()); + } + + INT linesFilled = 0; + const Gdiplus::Status status = m_Graphics->MeasureString( + str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect, + m_AccurateText ? &tStringFormat : &stringFormat, &rect, nullptr, &linesFilled); + lines = linesFilled; + + // Restore old options. + stringFormat.SetTrimming(stringTrimming); + stringFormat.SetFormatFlags(stringFormatFlags); + + return status == Gdiplus::Ok; +} + +void CanvasGDIP::DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) +{ + m_Graphics->DrawImage(bitmap, dstRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Gdiplus::UnitPixel); +} + +void CanvasGDIP::FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) +{ + m_Graphics->FillRectangle(&brush, rect); +} + +} // namespace Gfx diff --git a/Common/Gfx/CanvasGDIP.h b/Common/Gfx/CanvasGDIP.h index 808cc49f..a989cbca 100644 --- a/Common/Gfx/CanvasGDIP.h +++ b/Common/Gfx/CanvasGDIP.h @@ -1,90 +1,90 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_GFX_CANVASGDIP_H_ -#define RM_GFX_CANVASGDIP_H_ - -#include "Canvas.h" -#include "FontCollectionGDIP.h" -#include "TextFormatGDIP.h" -#include -#include -#include // For Gdiplus.h. -#include - -namespace Gfx { - -// Provides a GDI+ implementation of Canvas. -class CanvasGDIP : public Canvas -{ -public: - virtual void Resize(int w, int h); - - virtual bool BeginDraw(); - virtual void EndDraw(); - - virtual Gdiplus::Graphics& BeginGdiplusContext() override; - virtual void EndGdiplusContext() override; - - virtual HDC GetDC() override; - virtual void ReleaseDC(HDC dc) override; - - virtual FontCollection* CreateFontCollection() override { return new FontCollectionGDIP(); } - virtual TextFormat* CreateTextFormat() override { return new TextFormatGDIP(); } - - virtual bool IsTransparentPixel(int x, int y) override; - - virtual void SetTransform(const Gdiplus::Matrix& matrix) override; - virtual void ResetTransform() override; - virtual void RotateTransform(float angle, float x, float y, float dx, float dy) override; - - virtual void SetAntiAliasing(bool enable) override; - virtual void SetTextAntiAliasing(bool enable) override; - - virtual void Clear(const Gdiplus::Color& color) override; - - virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) override; - virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) override; - virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) override; - - virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) override; - - virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) override; - -private: - friend class Canvas; - - CanvasGDIP(); - ~CanvasGDIP(); - - CanvasGDIP(const CanvasGDIP& other) = delete; - CanvasGDIP& operator=(CanvasGDIP other) = delete; - - void Dispose(); - - std::unique_ptr m_Graphics; - std::unique_ptr m_Bitmap; - HBITMAP m_DIBSection; - LPDWORD m_DIBSectionPixels; - - //static ULONG_PTR c_GdiToken; -}; - -} // namespace Gfx - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_CANVASGDIP_H_ +#define RM_GFX_CANVASGDIP_H_ + +#include "Canvas.h" +#include "FontCollectionGDIP.h" +#include "TextFormatGDIP.h" +#include +#include +#include // For Gdiplus.h. +#include + +namespace Gfx { + +// Provides a GDI+ implementation of Canvas. +class CanvasGDIP : public Canvas +{ +public: + virtual void Resize(int w, int h); + + virtual bool BeginDraw(); + virtual void EndDraw(); + + virtual Gdiplus::Graphics& BeginGdiplusContext() override; + virtual void EndGdiplusContext() override; + + virtual HDC GetDC() override; + virtual void ReleaseDC(HDC dc) override; + + virtual FontCollection* CreateFontCollection() override { return new FontCollectionGDIP(); } + virtual TextFormat* CreateTextFormat() override { return new TextFormatGDIP(); } + + virtual bool IsTransparentPixel(int x, int y) override; + + virtual void SetTransform(const Gdiplus::Matrix& matrix) override; + virtual void ResetTransform() override; + virtual void RotateTransform(float angle, float x, float y, float dx, float dy) override; + + virtual void SetAntiAliasing(bool enable) override; + virtual void SetTextAntiAliasing(bool enable) override; + + virtual void Clear(const Gdiplus::Color& color) override; + + virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) override; + virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) override; + virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) override; + + virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) override; + + virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) override; + +private: + friend class Canvas; + + CanvasGDIP(); + ~CanvasGDIP(); + + CanvasGDIP(const CanvasGDIP& other) = delete; + CanvasGDIP& operator=(CanvasGDIP other) = delete; + + void Dispose(); + + std::unique_ptr m_Graphics; + std::unique_ptr m_Bitmap; + HBITMAP m_DIBSection; + LPDWORD m_DIBSectionPixels; + + //static ULONG_PTR c_GdiToken; +}; + +} // namespace Gfx + #endif \ No newline at end of file diff --git a/Common/Gfx/FontCollection.cpp b/Common/Gfx/FontCollection.cpp index 60dd314c..305c68b0 100644 --- a/Common/Gfx/FontCollection.cpp +++ b/Common/Gfx/FontCollection.cpp @@ -1,32 +1,32 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "FontCollection.h" - -namespace Gfx { - -FontCollection::FontCollection() -{ -} - -FontCollection::~FontCollection() -{ -} - -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "FontCollection.h" + +namespace Gfx { + +FontCollection::FontCollection() +{ +} + +FontCollection::~FontCollection() +{ +} + +} // namespace Gfx diff --git a/Common/Gfx/FontCollection.h b/Common/Gfx/FontCollection.h index 6d3e1a45..07ed2ab5 100644 --- a/Common/Gfx/FontCollection.h +++ b/Common/Gfx/FontCollection.h @@ -1,43 +1,43 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_GFX_FONTCOLLECTION_H_ -#define RM_GFX_FONTCOLLECTION_H_ - -#include - -namespace Gfx { - -// Interface for a collection of fonts that may or may not be installed on the system. -class __declspec(novtable) FontCollection -{ -public: - virtual ~FontCollection(); - - FontCollection(const FontCollection& other) = delete; - - // Adds a file to the collection. Returns true if the file was successfully added. - virtual bool AddFile(const WCHAR* file) = 0; - -protected: - FontCollection(); -}; - -} // namespace Gfx - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_FONTCOLLECTION_H_ +#define RM_GFX_FONTCOLLECTION_H_ + +#include + +namespace Gfx { + +// Interface for a collection of fonts that may or may not be installed on the system. +class __declspec(novtable) FontCollection +{ +public: + virtual ~FontCollection(); + + FontCollection(const FontCollection& other) = delete; + + // Adds a file to the collection. Returns true if the file was successfully added. + virtual bool AddFile(const WCHAR* file) = 0; + +protected: + FontCollection(); +}; + +} // namespace Gfx + #endif \ No newline at end of file diff --git a/Common/Gfx/FontCollectionD2D.cpp b/Common/Gfx/FontCollectionD2D.cpp index 764512f4..29c1b6dc 100644 --- a/Common/Gfx/FontCollectionD2D.cpp +++ b/Common/Gfx/FontCollectionD2D.cpp @@ -1,79 +1,79 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "FontCollectionD2D.h" -#include "CanvasD2D.h" -#include "Util/DWriteFontCollectionLoader.h" - -namespace Gfx { - -FontCollectionD2D::FontCollectionD2D() : FontCollection(), - m_Collection() -{ -} - -FontCollectionD2D::~FontCollectionD2D() -{ - Dispose(); -} - -void FontCollectionD2D::Dispose() -{ - for (IDWriteFontFile* fileReference : m_FileReferences) - { - fileReference->Release(); - } - m_FileReferences.clear(); -} - -bool FontCollectionD2D::InitializeCollection() -{ - if (!m_Collection) - { - auto loader = Util::DWriteFontCollectionLoader::GetInstance(); - CanvasD2D::c_DWFactory->CreateCustomFontCollection( - loader, &m_FileReferences, sizeof(m_FileReferences), &m_Collection); - } - - return m_Collection != nullptr; -} - -bool FontCollectionD2D::AddFile(const WCHAR* file) -{ - // If DirecWrite font collection already exists, we need to destroy it as fonts cannot be added to - // an existing collection. The collection will be recreated on the next call to - // InitializeCollection(). - if (m_Collection) - { - m_Collection->Release(); - m_Collection = nullptr; - } - - IDWriteFontFile* fileReference; - HRESULT hr = CanvasD2D::c_DWFactory->CreateFontFileReference(file, nullptr, &fileReference); - if (SUCCEEDED(hr)) - { - m_FileReferences.push_back(fileReference); - return true; - } - - return false; -} - -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "FontCollectionD2D.h" +#include "CanvasD2D.h" +#include "Util/DWriteFontCollectionLoader.h" + +namespace Gfx { + +FontCollectionD2D::FontCollectionD2D() : FontCollection(), + m_Collection() +{ +} + +FontCollectionD2D::~FontCollectionD2D() +{ + Dispose(); +} + +void FontCollectionD2D::Dispose() +{ + for (IDWriteFontFile* fileReference : m_FileReferences) + { + fileReference->Release(); + } + m_FileReferences.clear(); +} + +bool FontCollectionD2D::InitializeCollection() +{ + if (!m_Collection) + { + auto loader = Util::DWriteFontCollectionLoader::GetInstance(); + CanvasD2D::c_DWFactory->CreateCustomFontCollection( + loader, &m_FileReferences, sizeof(m_FileReferences), &m_Collection); + } + + return m_Collection != nullptr; +} + +bool FontCollectionD2D::AddFile(const WCHAR* file) +{ + // If DirecWrite font collection already exists, we need to destroy it as fonts cannot be added to + // an existing collection. The collection will be recreated on the next call to + // InitializeCollection(). + if (m_Collection) + { + m_Collection->Release(); + m_Collection = nullptr; + } + + IDWriteFontFile* fileReference; + HRESULT hr = CanvasD2D::c_DWFactory->CreateFontFileReference(file, nullptr, &fileReference); + if (SUCCEEDED(hr)) + { + m_FileReferences.push_back(fileReference); + return true; + } + + return false; +} + +} // namespace Gfx diff --git a/Common/Gfx/FontCollectionD2D.h b/Common/Gfx/FontCollectionD2D.h index bf056a21..033ee6ae 100644 --- a/Common/Gfx/FontCollectionD2D.h +++ b/Common/Gfx/FontCollectionD2D.h @@ -1,56 +1,56 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_GFX_FONTCOLLECTIOND2D_H_ -#define RM_GFX_FONTCOLLECTIOND2D_H_ - -#include "FontCollection.h" -#include -#include - -namespace Gfx { - -// Wraps the DirectWrite IDWriteFontCollection for use with CanvasD2D. -class FontCollectionD2D final : public FontCollection -{ -public: - virtual ~FontCollectionD2D(); - - FontCollectionD2D(const FontCollectionD2D& other) = delete; - FontCollectionD2D& operator=(FontCollectionD2D other) = delete; - - virtual bool AddFile(const WCHAR* file) override; - -protected: - FontCollectionD2D(); - -private: - friend class CanvasD2D; - friend class TextFormatD2D; - - void Dispose(); - - bool InitializeCollection(); - - std::vector m_FileReferences; - IDWriteFontCollection* m_Collection; -}; - -} // namespace Gfx - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_FONTCOLLECTIOND2D_H_ +#define RM_GFX_FONTCOLLECTIOND2D_H_ + +#include "FontCollection.h" +#include +#include + +namespace Gfx { + +// Wraps the DirectWrite IDWriteFontCollection for use with CanvasD2D. +class FontCollectionD2D final : public FontCollection +{ +public: + virtual ~FontCollectionD2D(); + + FontCollectionD2D(const FontCollectionD2D& other) = delete; + FontCollectionD2D& operator=(FontCollectionD2D other) = delete; + + virtual bool AddFile(const WCHAR* file) override; + +protected: + FontCollectionD2D(); + +private: + friend class CanvasD2D; + friend class TextFormatD2D; + + void Dispose(); + + bool InitializeCollection(); + + std::vector m_FileReferences; + IDWriteFontCollection* m_Collection; +}; + +} // namespace Gfx + #endif \ No newline at end of file diff --git a/Common/Gfx/FontCollectionGDIP.cpp b/Common/Gfx/FontCollectionGDIP.cpp index 6a3c33f2..3f725d0d 100644 --- a/Common/Gfx/FontCollectionGDIP.cpp +++ b/Common/Gfx/FontCollectionGDIP.cpp @@ -1,54 +1,54 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "FontCollectionGDIP.h" - -namespace Gfx { - -FontCollectionGDIP::FontCollectionGDIP() : FontCollection(), - m_PrivateCollection() -{ -} - -FontCollectionGDIP::~FontCollectionGDIP() -{ - Dispose(); -} - -void FontCollectionGDIP::Dispose() -{ - if (m_PrivateCollection) - { - delete m_PrivateCollection; - m_PrivateCollection = nullptr; - } -} - -bool FontCollectionGDIP::AddFile(const WCHAR* file) -{ - if (!m_PrivateCollection) - { - m_PrivateCollection = new Gdiplus::PrivateFontCollection(); - } - - const Gdiplus::Status status = m_PrivateCollection->AddFontFile(file); - return status == Gdiplus::Ok; -} - -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "FontCollectionGDIP.h" + +namespace Gfx { + +FontCollectionGDIP::FontCollectionGDIP() : FontCollection(), + m_PrivateCollection() +{ +} + +FontCollectionGDIP::~FontCollectionGDIP() +{ + Dispose(); +} + +void FontCollectionGDIP::Dispose() +{ + if (m_PrivateCollection) + { + delete m_PrivateCollection; + m_PrivateCollection = nullptr; + } +} + +bool FontCollectionGDIP::AddFile(const WCHAR* file) +{ + if (!m_PrivateCollection) + { + m_PrivateCollection = new Gdiplus::PrivateFontCollection(); + } + + const Gdiplus::Status status = m_PrivateCollection->AddFontFile(file); + return status == Gdiplus::Ok; +} + +} // namespace Gfx diff --git a/Common/Gfx/FontCollectionGDIP.h b/Common/Gfx/FontCollectionGDIP.h index a35fbdf6..4c231432 100644 --- a/Common/Gfx/FontCollectionGDIP.h +++ b/Common/Gfx/FontCollectionGDIP.h @@ -1,55 +1,55 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_GFX_FONTCOLLECTIONGDIP_H_ -#define RM_GFX_FONTCOLLECTIONGDIP_H_ - -#include "FontCollection.h" - -namespace Gdiplus { -class PrivateFontCollection; -} - -namespace Gfx { - -// Wraps the GDI+ PrivateFontCollection for use with CanvasGDIP. -class FontCollectionGDIP final : public FontCollection -{ -public: - virtual ~FontCollectionGDIP(); - - FontCollectionGDIP(const FontCollectionGDIP& other) = delete; - FontCollectionGDIP& operator=(FontCollectionGDIP other) = delete; - - virtual bool AddFile(const WCHAR* file) override; - -protected: - FontCollectionGDIP(); - -private: - friend class CanvasGDIP; - friend class TextFormatGDIP; - - void Dispose(); - - Gdiplus::PrivateFontCollection* m_PrivateCollection; -}; - -} // namespace Gfx - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_FONTCOLLECTIONGDIP_H_ +#define RM_GFX_FONTCOLLECTIONGDIP_H_ + +#include "FontCollection.h" + +namespace Gdiplus { +class PrivateFontCollection; +} + +namespace Gfx { + +// Wraps the GDI+ PrivateFontCollection for use with CanvasGDIP. +class FontCollectionGDIP final : public FontCollection +{ +public: + virtual ~FontCollectionGDIP(); + + FontCollectionGDIP(const FontCollectionGDIP& other) = delete; + FontCollectionGDIP& operator=(FontCollectionGDIP other) = delete; + + virtual bool AddFile(const WCHAR* file) override; + +protected: + FontCollectionGDIP(); + +private: + friend class CanvasGDIP; + friend class TextFormatGDIP; + + void Dispose(); + + Gdiplus::PrivateFontCollection* m_PrivateCollection; +}; + +} // namespace Gfx + #endif \ No newline at end of file diff --git a/Common/Gfx/TextFormat.cpp b/Common/Gfx/TextFormat.cpp index 71049dd6..877da201 100644 --- a/Common/Gfx/TextFormat.cpp +++ b/Common/Gfx/TextFormat.cpp @@ -1,44 +1,44 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "TextFormat.h" - -namespace Gfx { - -TextFormat::TextFormat() : - m_HorizontalAlignment(HorizontalAlignment::Left), - m_VerticalAlignment(VerticalAlignment::Top) -{ -} - -TextFormat::~TextFormat() -{ -} - -void TextFormat::SetHorizontalAlignment(HorizontalAlignment alignment) -{ - m_HorizontalAlignment = alignment; -} - -void TextFormat::SetVerticalAlignment(VerticalAlignment alignment) -{ - m_VerticalAlignment = alignment; -} - -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "TextFormat.h" + +namespace Gfx { + +TextFormat::TextFormat() : + m_HorizontalAlignment(HorizontalAlignment::Left), + m_VerticalAlignment(VerticalAlignment::Top) +{ +} + +TextFormat::~TextFormat() +{ +} + +void TextFormat::SetHorizontalAlignment(HorizontalAlignment alignment) +{ + m_HorizontalAlignment = alignment; +} + +void TextFormat::SetVerticalAlignment(VerticalAlignment alignment) +{ + m_VerticalAlignment = alignment; +} + +} // namespace Gfx diff --git a/Common/Gfx/TextFormat.h b/Common/Gfx/TextFormat.h index 7b6eea57..9bafec9a 100644 --- a/Common/Gfx/TextFormat.h +++ b/Common/Gfx/TextFormat.h @@ -1,80 +1,80 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_GFX_TEXTFORMAT_H_ -#define RM_GFX_TEXTFORMAT_H_ - -#include - -namespace Gfx { - -class FontCollection; - -enum class HorizontalAlignment : BYTE -{ - Left, - Center, - Right -}; - -enum class VerticalAlignment : BYTE -{ - Top, - Center, - Bottom -}; - -// Represents the logical font properties used to format text. -class __declspec(novtable) TextFormat -{ -public: - virtual ~TextFormat(); - - TextFormat(const TextFormat& other) = delete; - - // Returns true if this TextFormat object is valid for use in draw operations. - virtual bool IsInitialized() const = 0; - - // Sets the logical properties of the font to use. If the font is not found in the system font - // collection, the given |fontCollection| is also searched. |fontCollection| may be nullptr. - virtual void SetProperties( - const WCHAR* fontFamily, int size, bool bold, bool italic, - const FontCollection* fontCollection) = 0; - - // Sets the trimming and wrapping of the text. If |trim| is true, subsequent draws using this - // TextFormat object will produce clipped text with an ellipsis if the text overflows the - // bounding rectangle. - virtual void SetTrimming(bool trim) = 0; - - virtual void SetHorizontalAlignment(HorizontalAlignment alignment); - HorizontalAlignment GetHorizontalAlignment() const { return m_HorizontalAlignment; } - - virtual void SetVerticalAlignment(VerticalAlignment alignment); - VerticalAlignment GetVerticalAlignment() const { return m_VerticalAlignment; } - -protected: - TextFormat(); - -private: - HorizontalAlignment m_HorizontalAlignment; - VerticalAlignment m_VerticalAlignment; -}; - -} // namespace Gfx - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_TEXTFORMAT_H_ +#define RM_GFX_TEXTFORMAT_H_ + +#include + +namespace Gfx { + +class FontCollection; + +enum class HorizontalAlignment : BYTE +{ + Left, + Center, + Right +}; + +enum class VerticalAlignment : BYTE +{ + Top, + Center, + Bottom +}; + +// Represents the logical font properties used to format text. +class __declspec(novtable) TextFormat +{ +public: + virtual ~TextFormat(); + + TextFormat(const TextFormat& other) = delete; + + // Returns true if this TextFormat object is valid for use in draw operations. + virtual bool IsInitialized() const = 0; + + // Sets the logical properties of the font to use. If the font is not found in the system font + // collection, the given |fontCollection| is also searched. |fontCollection| may be nullptr. + virtual void SetProperties( + const WCHAR* fontFamily, int size, bool bold, bool italic, + const FontCollection* fontCollection) = 0; + + // Sets the trimming and wrapping of the text. If |trim| is true, subsequent draws using this + // TextFormat object will produce clipped text with an ellipsis if the text overflows the + // bounding rectangle. + virtual void SetTrimming(bool trim) = 0; + + virtual void SetHorizontalAlignment(HorizontalAlignment alignment); + HorizontalAlignment GetHorizontalAlignment() const { return m_HorizontalAlignment; } + + virtual void SetVerticalAlignment(VerticalAlignment alignment); + VerticalAlignment GetVerticalAlignment() const { return m_VerticalAlignment; } + +protected: + TextFormat(); + +private: + HorizontalAlignment m_HorizontalAlignment; + VerticalAlignment m_VerticalAlignment; +}; + +} // namespace Gfx + #endif \ No newline at end of file diff --git a/Common/Gfx/TextFormatD2D.cpp b/Common/Gfx/TextFormatD2D.cpp index 57f4b45b..99745b32 100644 --- a/Common/Gfx/TextFormatD2D.cpp +++ b/Common/Gfx/TextFormatD2D.cpp @@ -1,367 +1,367 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "TextFormatD2D.h" -#include "CanvasD2D.h" -#include "Util/DWriteHelpers.h" - -namespace Gfx { - -TextFormatD2D::TextFormatD2D() : - m_ExtraHeight(), - m_LineGap(), - m_Trimming() -{ -} - -TextFormatD2D::~TextFormatD2D() -{ -} - -void TextFormatD2D::Dispose() -{ - m_TextFormat.Reset(); - m_TextLayout.Reset(); - m_InlineEllipsis.Reset(); - - m_ExtraHeight = 0.0f; - m_LineGap = 0.0f; -} - -bool TextFormatD2D::CreateLayout( - const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation) -{ - bool strChanged = false; - if (strLen != m_LastString.length() || - memcmp(str, m_LastString.c_str(), (strLen + 1) * sizeof(WCHAR)) != 0) - { - strChanged = true; - m_LastString.assign(str, strLen); - } - - // The width and height of a DirectWrite layout must be non-negative. - maxW = max(0.0f, maxW); - maxH = max(0.0f, maxH); - - if (m_Trimming) - { - // GDI+ compatibility: If we trimming (i.e. clipping), GDI+ draws text lines even if they - // would be clipped. This is arguably a bad 'feature', but some in some cases the height - // might be just a pixel or two too small. In order to render those cases correctly (but - // still clipped as CanvasD2D::DrawTextW() will clip), we'll increase the max height of - // the layout. - maxH += 2.0f; - } - - if (m_TextLayout && !strChanged) - { - if (maxW != m_TextLayout->GetMaxWidth()) - { - m_TextLayout->SetMaxWidth(maxW); - } - - if (maxH != m_TextLayout->GetMaxHeight()) - { - m_TextLayout->SetMaxHeight(maxH); - } - } - else - { - CanvasD2D::c_DWFactory->CreateTextLayout( - str, strLen, m_TextFormat.Get(), maxW, maxH, m_TextLayout.ReleaseAndGetAddressOf()); - if (!m_TextLayout) return false; - - if (gdiEmulation) - { - Microsoft::WRL::ComPtr textLayout1; - m_TextLayout.As(&textLayout1); - - const float xOffset = m_TextFormat->GetFontSize() / 6.0f; - const float emOffset = xOffset / 24.0f; - const DWRITE_TEXT_RANGE range = {0, strLen}; - textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range); - } - - UINT32 lineCount = 0; - DWRITE_LINE_METRICS lineMetrics[2]; - HRESULT hr = m_TextLayout->GetLineMetrics(lineMetrics, _countof(lineMetrics), &lineCount); - if (SUCCEEDED(hr)) - { - // If only one line is visible, disable wrapping so that as much text as possible is shown - // after trimming. - // TODO: Fix this for when more than one line is visible. - if (lineCount >= 2 && - lineMetrics[0].isTrimmed && - lineMetrics[1].isTrimmed && - lineMetrics[1].height == 0.0f) - { - m_TextLayout->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); - } - } - } - - return true; -} - -void TextFormatD2D::SetProperties( - const WCHAR* fontFamily, int size, bool bold, bool italic, - const FontCollection* fontCollection) -{ - auto fontCollectionD2D = (FontCollectionD2D*)fontCollection; - - Dispose(); - - WCHAR dwriteFamilyName[LF_FACESIZE]; - DWRITE_FONT_WEIGHT dwriteFontWeight = - bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_REGULAR; - DWRITE_FONT_STYLE dwriteFontStyle = - italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; - DWRITE_FONT_STRETCH dwriteFontStretch = DWRITE_FONT_STRETCH_NORMAL; - const float dwriteFontSize = size * (4.0f / 3.0f); - - // |fontFamily| uses the GDI/GDI+ font naming convention so try to create DirectWrite font - // using the GDI family name and then create a text format using the DirectWrite family name - // obtained from it. - HRESULT hr = Util::GetDWritePropertiesFromGDIProperties( - CanvasD2D::c_DWFactory.Get(), fontFamily, bold, italic, dwriteFontWeight, dwriteFontStyle, - dwriteFontStretch, dwriteFamilyName, _countof(dwriteFamilyName)); - if (SUCCEEDED(hr)) - { - hr = CanvasD2D::c_DWFactory->CreateTextFormat( - dwriteFamilyName, - nullptr, - dwriteFontWeight, - dwriteFontStyle, - dwriteFontStretch, - dwriteFontSize, - L"", - &m_TextFormat); - } - - if (FAILED(hr)) - { - IDWriteFontCollection* dwriteFontCollection = nullptr; - - // If |fontFamily| is not in the system collection, use the font collection from - // |fontCollectionD2D| if possible. - if (!Util::IsFamilyInSystemFontCollection(CanvasD2D::c_DWFactory.Get(), fontFamily) && - (fontCollectionD2D && fontCollectionD2D->InitializeCollection())) - { - IDWriteFont* dwriteFont = Util::FindDWriteFontInFontCollectionByGDIFamilyName( - fontCollectionD2D->m_Collection, fontFamily); - if (dwriteFont) - { - hr = Util::GetFamilyNameFromDWriteFont( - dwriteFont, dwriteFamilyName, _countof(dwriteFamilyName)); - if (SUCCEEDED(hr)) - { - fontFamily = dwriteFamilyName; - Util::GetPropertiesFromDWriteFont( - dwriteFont, bold, italic, &dwriteFontWeight, &dwriteFontStyle, - &dwriteFontStretch); - } - - dwriteFont->Release(); - } - - dwriteFontCollection = fontCollectionD2D->m_Collection; - } - - // Fallback in case above fails. - hr = CanvasD2D::c_DWFactory->CreateTextFormat( - fontFamily, - dwriteFontCollection, - dwriteFontWeight, - dwriteFontStyle, - dwriteFontStretch, - dwriteFontSize, - L"", - &m_TextFormat); - } - - if (SUCCEEDED(hr)) - { - SetHorizontalAlignment(GetHorizontalAlignment()); - SetVerticalAlignment(GetVerticalAlignment()); - - // Get the family name to in case CreateTextFormat() fallbacked on some other family name. - hr = m_TextFormat->GetFontFamilyName(dwriteFamilyName, _countof(dwriteFamilyName)); - if (FAILED(hr)) return; - - Microsoft::WRL::ComPtr collection; - Microsoft::WRL::ComPtr fontFamily; - UINT32 familyNameIndex; - BOOL exists; - if (FAILED(m_TextFormat->GetFontCollection(collection.GetAddressOf())) || - FAILED(collection->FindFamilyName(dwriteFamilyName, &familyNameIndex, &exists)) || - FAILED(collection->GetFontFamily(familyNameIndex, fontFamily.GetAddressOf()))) - { - return; - } - - Microsoft::WRL::ComPtr font; - hr = fontFamily->GetFirstMatchingFont( - m_TextFormat->GetFontWeight(), - m_TextFormat->GetFontStretch(), - m_TextFormat->GetFontStyle(), - font.GetAddressOf()); - if (FAILED(hr)) return; - - DWRITE_FONT_METRICS fmetrics; - font->GetMetrics(&fmetrics); - - // GDI+ compatibility: GDI+ adds extra padding below the string when |m_AccurateText| is - // |false|. The bottom padding seems to be based on the font metrics so we can calculate it - // once and keep using it regardless of the actual string. In some cases, GDI+ also adds - // the line gap to the overall height so we will store it as well. - const float pixelsPerDesignUnit = dwriteFontSize / (float)fmetrics.designUnitsPerEm; - m_ExtraHeight = - (((float)fmetrics.designUnitsPerEm / 8.0f) - fmetrics.lineGap) * pixelsPerDesignUnit; - m_LineGap = fmetrics.lineGap * pixelsPerDesignUnit; - } - else - { - Dispose(); - } -} - -DWRITE_TEXT_METRICS TextFormatD2D::GetMetrics( - const WCHAR* str, UINT strLen, bool gdiEmulation, float maxWidth) -{ - // GDI+ compatibility: If the last character is a newline, GDI+ measurements seem to ignore it. - bool strippedLastNewLine = false; - if (strLen > 2 && str[strLen - 1] == L'\n') - { - strippedLastNewLine = true; - --strLen; - - if (str[strLen - 1] == L'\r') - { - --strLen; - } - } - - DWRITE_TEXT_METRICS metrics = {0}; - Microsoft::WRL::ComPtr textLayout; - HRESULT hr = CanvasD2D::c_DWFactory->CreateTextLayout( - str, - strLen, - m_TextFormat.Get(), - maxWidth, - 10000, - textLayout.GetAddressOf()); - if (SUCCEEDED(hr)) - { - const float xOffset = m_TextFormat->GetFontSize() / 6.0f; - if (gdiEmulation) - { - Microsoft::WRL::ComPtr textLayout1; - textLayout.As(&textLayout1); - - const float emOffset = xOffset / 24.0f; - const DWRITE_TEXT_RANGE range = {0, strLen}; - textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range); - } - - textLayout->GetMetrics(&metrics); - if (metrics.width > 0.0f) - { - if (gdiEmulation) - { - metrics.width += xOffset * 2; - metrics.height += m_ExtraHeight; - - // GDI+ compatibility: If the string contains a newline (even if it is the - // stripped last character), GDI+ adds the line gap to the overall height. - if (strippedLastNewLine || wmemchr(str, L'\n', strLen) != nullptr) - { - metrics.height += m_LineGap; - } - } - else - { - // GDI+ compatibility: With accurate metrics, the line gap needs to be subtracted - // from the overall height if the string does not contain newlines. - if (!strippedLastNewLine && wmemchr(str, L'\n', strLen) == nullptr) - { - metrics.height -= m_LineGap; - } - } - } - else - { - // GDI+ compatibility: Get rid of the height that DirectWrite assigns to zero-width - // strings. - metrics.height = 0.0f; - } - } - - return metrics; -} - -void TextFormatD2D::SetTrimming(bool trim) -{ - m_Trimming = trim; - IDWriteInlineObject* inlineObject = nullptr; - DWRITE_TRIMMING trimming = {}; - DWRITE_WORD_WRAPPING wordWrapping = DWRITE_WORD_WRAPPING_NO_WRAP; - if (trim) - { - if (!m_InlineEllipsis) - { - CanvasD2D::c_DWFactory->CreateEllipsisTrimmingSign( - m_TextFormat.Get(), m_InlineEllipsis.GetAddressOf()); - } - - inlineObject = m_InlineEllipsis.Get(); - trimming.granularity = DWRITE_TRIMMING_GRANULARITY_CHARACTER; - wordWrapping = DWRITE_WORD_WRAPPING_WRAP; - } - - m_TextFormat->SetTrimming(&trimming, inlineObject); - m_TextFormat->SetWordWrapping(wordWrapping); -} - -void TextFormatD2D::SetHorizontalAlignment(HorizontalAlignment alignment) -{ - __super::SetHorizontalAlignment(alignment); - - if (m_TextFormat) - { - m_TextFormat->SetTextAlignment( - (alignment == HorizontalAlignment::Left) ? DWRITE_TEXT_ALIGNMENT_LEADING : - (alignment == HorizontalAlignment::Center) ? DWRITE_TEXT_ALIGNMENT_CENTER : - DWRITE_TEXT_ALIGNMENT_TRAILING); - } -} - -void TextFormatD2D::SetVerticalAlignment(VerticalAlignment alignment) -{ - __super::SetVerticalAlignment(alignment); - - if (m_TextFormat) - { - m_TextFormat->SetParagraphAlignment( - (alignment == VerticalAlignment::Top) ? DWRITE_PARAGRAPH_ALIGNMENT_NEAR : - (alignment == VerticalAlignment::Center) ? DWRITE_PARAGRAPH_ALIGNMENT_CENTER : - DWRITE_PARAGRAPH_ALIGNMENT_FAR); - } -} - -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "TextFormatD2D.h" +#include "CanvasD2D.h" +#include "Util/DWriteHelpers.h" + +namespace Gfx { + +TextFormatD2D::TextFormatD2D() : + m_ExtraHeight(), + m_LineGap(), + m_Trimming() +{ +} + +TextFormatD2D::~TextFormatD2D() +{ +} + +void TextFormatD2D::Dispose() +{ + m_TextFormat.Reset(); + m_TextLayout.Reset(); + m_InlineEllipsis.Reset(); + + m_ExtraHeight = 0.0f; + m_LineGap = 0.0f; +} + +bool TextFormatD2D::CreateLayout( + const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation) +{ + bool strChanged = false; + if (strLen != m_LastString.length() || + memcmp(str, m_LastString.c_str(), (strLen + 1) * sizeof(WCHAR)) != 0) + { + strChanged = true; + m_LastString.assign(str, strLen); + } + + // The width and height of a DirectWrite layout must be non-negative. + maxW = max(0.0f, maxW); + maxH = max(0.0f, maxH); + + if (m_Trimming) + { + // GDI+ compatibility: If we trimming (i.e. clipping), GDI+ draws text lines even if they + // would be clipped. This is arguably a bad 'feature', but some in some cases the height + // might be just a pixel or two too small. In order to render those cases correctly (but + // still clipped as CanvasD2D::DrawTextW() will clip), we'll increase the max height of + // the layout. + maxH += 2.0f; + } + + if (m_TextLayout && !strChanged) + { + if (maxW != m_TextLayout->GetMaxWidth()) + { + m_TextLayout->SetMaxWidth(maxW); + } + + if (maxH != m_TextLayout->GetMaxHeight()) + { + m_TextLayout->SetMaxHeight(maxH); + } + } + else + { + CanvasD2D::c_DWFactory->CreateTextLayout( + str, strLen, m_TextFormat.Get(), maxW, maxH, m_TextLayout.ReleaseAndGetAddressOf()); + if (!m_TextLayout) return false; + + if (gdiEmulation) + { + Microsoft::WRL::ComPtr textLayout1; + m_TextLayout.As(&textLayout1); + + const float xOffset = m_TextFormat->GetFontSize() / 6.0f; + const float emOffset = xOffset / 24.0f; + const DWRITE_TEXT_RANGE range = {0, strLen}; + textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range); + } + + UINT32 lineCount = 0; + DWRITE_LINE_METRICS lineMetrics[2]; + HRESULT hr = m_TextLayout->GetLineMetrics(lineMetrics, _countof(lineMetrics), &lineCount); + if (SUCCEEDED(hr)) + { + // If only one line is visible, disable wrapping so that as much text as possible is shown + // after trimming. + // TODO: Fix this for when more than one line is visible. + if (lineCount >= 2 && + lineMetrics[0].isTrimmed && + lineMetrics[1].isTrimmed && + lineMetrics[1].height == 0.0f) + { + m_TextLayout->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); + } + } + } + + return true; +} + +void TextFormatD2D::SetProperties( + const WCHAR* fontFamily, int size, bool bold, bool italic, + const FontCollection* fontCollection) +{ + auto fontCollectionD2D = (FontCollectionD2D*)fontCollection; + + Dispose(); + + WCHAR dwriteFamilyName[LF_FACESIZE]; + DWRITE_FONT_WEIGHT dwriteFontWeight = + bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_REGULAR; + DWRITE_FONT_STYLE dwriteFontStyle = + italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; + DWRITE_FONT_STRETCH dwriteFontStretch = DWRITE_FONT_STRETCH_NORMAL; + const float dwriteFontSize = size * (4.0f / 3.0f); + + // |fontFamily| uses the GDI/GDI+ font naming convention so try to create DirectWrite font + // using the GDI family name and then create a text format using the DirectWrite family name + // obtained from it. + HRESULT hr = Util::GetDWritePropertiesFromGDIProperties( + CanvasD2D::c_DWFactory.Get(), fontFamily, bold, italic, dwriteFontWeight, dwriteFontStyle, + dwriteFontStretch, dwriteFamilyName, _countof(dwriteFamilyName)); + if (SUCCEEDED(hr)) + { + hr = CanvasD2D::c_DWFactory->CreateTextFormat( + dwriteFamilyName, + nullptr, + dwriteFontWeight, + dwriteFontStyle, + dwriteFontStretch, + dwriteFontSize, + L"", + &m_TextFormat); + } + + if (FAILED(hr)) + { + IDWriteFontCollection* dwriteFontCollection = nullptr; + + // If |fontFamily| is not in the system collection, use the font collection from + // |fontCollectionD2D| if possible. + if (!Util::IsFamilyInSystemFontCollection(CanvasD2D::c_DWFactory.Get(), fontFamily) && + (fontCollectionD2D && fontCollectionD2D->InitializeCollection())) + { + IDWriteFont* dwriteFont = Util::FindDWriteFontInFontCollectionByGDIFamilyName( + fontCollectionD2D->m_Collection, fontFamily); + if (dwriteFont) + { + hr = Util::GetFamilyNameFromDWriteFont( + dwriteFont, dwriteFamilyName, _countof(dwriteFamilyName)); + if (SUCCEEDED(hr)) + { + fontFamily = dwriteFamilyName; + Util::GetPropertiesFromDWriteFont( + dwriteFont, bold, italic, &dwriteFontWeight, &dwriteFontStyle, + &dwriteFontStretch); + } + + dwriteFont->Release(); + } + + dwriteFontCollection = fontCollectionD2D->m_Collection; + } + + // Fallback in case above fails. + hr = CanvasD2D::c_DWFactory->CreateTextFormat( + fontFamily, + dwriteFontCollection, + dwriteFontWeight, + dwriteFontStyle, + dwriteFontStretch, + dwriteFontSize, + L"", + &m_TextFormat); + } + + if (SUCCEEDED(hr)) + { + SetHorizontalAlignment(GetHorizontalAlignment()); + SetVerticalAlignment(GetVerticalAlignment()); + + // Get the family name to in case CreateTextFormat() fallbacked on some other family name. + hr = m_TextFormat->GetFontFamilyName(dwriteFamilyName, _countof(dwriteFamilyName)); + if (FAILED(hr)) return; + + Microsoft::WRL::ComPtr collection; + Microsoft::WRL::ComPtr fontFamily; + UINT32 familyNameIndex; + BOOL exists; + if (FAILED(m_TextFormat->GetFontCollection(collection.GetAddressOf())) || + FAILED(collection->FindFamilyName(dwriteFamilyName, &familyNameIndex, &exists)) || + FAILED(collection->GetFontFamily(familyNameIndex, fontFamily.GetAddressOf()))) + { + return; + } + + Microsoft::WRL::ComPtr font; + hr = fontFamily->GetFirstMatchingFont( + m_TextFormat->GetFontWeight(), + m_TextFormat->GetFontStretch(), + m_TextFormat->GetFontStyle(), + font.GetAddressOf()); + if (FAILED(hr)) return; + + DWRITE_FONT_METRICS fmetrics; + font->GetMetrics(&fmetrics); + + // GDI+ compatibility: GDI+ adds extra padding below the string when |m_AccurateText| is + // |false|. The bottom padding seems to be based on the font metrics so we can calculate it + // once and keep using it regardless of the actual string. In some cases, GDI+ also adds + // the line gap to the overall height so we will store it as well. + const float pixelsPerDesignUnit = dwriteFontSize / (float)fmetrics.designUnitsPerEm; + m_ExtraHeight = + (((float)fmetrics.designUnitsPerEm / 8.0f) - fmetrics.lineGap) * pixelsPerDesignUnit; + m_LineGap = fmetrics.lineGap * pixelsPerDesignUnit; + } + else + { + Dispose(); + } +} + +DWRITE_TEXT_METRICS TextFormatD2D::GetMetrics( + const WCHAR* str, UINT strLen, bool gdiEmulation, float maxWidth) +{ + // GDI+ compatibility: If the last character is a newline, GDI+ measurements seem to ignore it. + bool strippedLastNewLine = false; + if (strLen > 2 && str[strLen - 1] == L'\n') + { + strippedLastNewLine = true; + --strLen; + + if (str[strLen - 1] == L'\r') + { + --strLen; + } + } + + DWRITE_TEXT_METRICS metrics = {0}; + Microsoft::WRL::ComPtr textLayout; + HRESULT hr = CanvasD2D::c_DWFactory->CreateTextLayout( + str, + strLen, + m_TextFormat.Get(), + maxWidth, + 10000, + textLayout.GetAddressOf()); + if (SUCCEEDED(hr)) + { + const float xOffset = m_TextFormat->GetFontSize() / 6.0f; + if (gdiEmulation) + { + Microsoft::WRL::ComPtr textLayout1; + textLayout.As(&textLayout1); + + const float emOffset = xOffset / 24.0f; + const DWRITE_TEXT_RANGE range = {0, strLen}; + textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range); + } + + textLayout->GetMetrics(&metrics); + if (metrics.width > 0.0f) + { + if (gdiEmulation) + { + metrics.width += xOffset * 2; + metrics.height += m_ExtraHeight; + + // GDI+ compatibility: If the string contains a newline (even if it is the + // stripped last character), GDI+ adds the line gap to the overall height. + if (strippedLastNewLine || wmemchr(str, L'\n', strLen) != nullptr) + { + metrics.height += m_LineGap; + } + } + else + { + // GDI+ compatibility: With accurate metrics, the line gap needs to be subtracted + // from the overall height if the string does not contain newlines. + if (!strippedLastNewLine && wmemchr(str, L'\n', strLen) == nullptr) + { + metrics.height -= m_LineGap; + } + } + } + else + { + // GDI+ compatibility: Get rid of the height that DirectWrite assigns to zero-width + // strings. + metrics.height = 0.0f; + } + } + + return metrics; +} + +void TextFormatD2D::SetTrimming(bool trim) +{ + m_Trimming = trim; + IDWriteInlineObject* inlineObject = nullptr; + DWRITE_TRIMMING trimming = {}; + DWRITE_WORD_WRAPPING wordWrapping = DWRITE_WORD_WRAPPING_NO_WRAP; + if (trim) + { + if (!m_InlineEllipsis) + { + CanvasD2D::c_DWFactory->CreateEllipsisTrimmingSign( + m_TextFormat.Get(), m_InlineEllipsis.GetAddressOf()); + } + + inlineObject = m_InlineEllipsis.Get(); + trimming.granularity = DWRITE_TRIMMING_GRANULARITY_CHARACTER; + wordWrapping = DWRITE_WORD_WRAPPING_WRAP; + } + + m_TextFormat->SetTrimming(&trimming, inlineObject); + m_TextFormat->SetWordWrapping(wordWrapping); +} + +void TextFormatD2D::SetHorizontalAlignment(HorizontalAlignment alignment) +{ + __super::SetHorizontalAlignment(alignment); + + if (m_TextFormat) + { + m_TextFormat->SetTextAlignment( + (alignment == HorizontalAlignment::Left) ? DWRITE_TEXT_ALIGNMENT_LEADING : + (alignment == HorizontalAlignment::Center) ? DWRITE_TEXT_ALIGNMENT_CENTER : + DWRITE_TEXT_ALIGNMENT_TRAILING); + } +} + +void TextFormatD2D::SetVerticalAlignment(VerticalAlignment alignment) +{ + __super::SetVerticalAlignment(alignment); + + if (m_TextFormat) + { + m_TextFormat->SetParagraphAlignment( + (alignment == VerticalAlignment::Top) ? DWRITE_PARAGRAPH_ALIGNMENT_NEAR : + (alignment == VerticalAlignment::Center) ? DWRITE_PARAGRAPH_ALIGNMENT_CENTER : + DWRITE_PARAGRAPH_ALIGNMENT_FAR); + } +} + +} // namespace Gfx diff --git a/Common/Gfx/TextFormatD2D.h b/Common/Gfx/TextFormatD2D.h index 0f78b0cb..77416841 100644 --- a/Common/Gfx/TextFormatD2D.h +++ b/Common/Gfx/TextFormatD2D.h @@ -1,81 +1,81 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_GFX_TEXTFORMATD2D_H_ -#define RM_GFX_TEXTFORMATD2D_H_ - -#include "TextFormat.h" -#include -#include -#include - -namespace Gfx { - -// Provides a Direct2D/DirectWrite implementation of TextFormat for use with CanvasD2D. -class TextFormatD2D : public TextFormat -{ -public: - TextFormatD2D(); - virtual ~TextFormatD2D(); - - TextFormatD2D(const TextFormatD2D& other) = delete; - TextFormatD2D& operator=(TextFormatD2D other) = delete; - - virtual bool IsInitialized() const override { return m_TextFormat != nullptr; } - - virtual void SetProperties( - const WCHAR* fontFamily, int size, bool bold, bool italic, - const FontCollection* fontCollection) override; - - virtual void SetTrimming(bool trim) override; - - virtual void SetHorizontalAlignment(HorizontalAlignment alignment) override; - virtual void SetVerticalAlignment(VerticalAlignment alignment) override; - -private: - friend class CanvasD2D; - - friend class Common_Gfx_TextFormatD2D_Test; - - void Dispose(); - - // Creates a new DirectWrite text layout if |str| has changed since last call. Since creating - // the layout is costly, it is more efficient to keep reusing the text layout until the text - // changes. Returns true if the layout is valid for use. - bool CreateLayout(const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation); - - DWRITE_TEXT_METRICS GetMetrics( - const WCHAR* str, UINT strLen, bool gdiEmulation, float maxWidth = 10000.0f); - - Microsoft::WRL::ComPtr m_TextFormat; - Microsoft::WRL::ComPtr m_TextLayout; - Microsoft::WRL::ComPtr m_InlineEllipsis; - - std::wstring m_LastString; - - // Used to emulate GDI+ behaviour. - float m_ExtraHeight; - float m_LineGap; - - // Contains the value passed to the last call of of SetTrimming(). - bool m_Trimming; -}; - -} // namespace Gfx - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_TEXTFORMATD2D_H_ +#define RM_GFX_TEXTFORMATD2D_H_ + +#include "TextFormat.h" +#include +#include +#include + +namespace Gfx { + +// Provides a Direct2D/DirectWrite implementation of TextFormat for use with CanvasD2D. +class TextFormatD2D : public TextFormat +{ +public: + TextFormatD2D(); + virtual ~TextFormatD2D(); + + TextFormatD2D(const TextFormatD2D& other) = delete; + TextFormatD2D& operator=(TextFormatD2D other) = delete; + + virtual bool IsInitialized() const override { return m_TextFormat != nullptr; } + + virtual void SetProperties( + const WCHAR* fontFamily, int size, bool bold, bool italic, + const FontCollection* fontCollection) override; + + virtual void SetTrimming(bool trim) override; + + virtual void SetHorizontalAlignment(HorizontalAlignment alignment) override; + virtual void SetVerticalAlignment(VerticalAlignment alignment) override; + +private: + friend class CanvasD2D; + + friend class Common_Gfx_TextFormatD2D_Test; + + void Dispose(); + + // Creates a new DirectWrite text layout if |str| has changed since last call. Since creating + // the layout is costly, it is more efficient to keep reusing the text layout until the text + // changes. Returns true if the layout is valid for use. + bool CreateLayout(const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation); + + DWRITE_TEXT_METRICS GetMetrics( + const WCHAR* str, UINT strLen, bool gdiEmulation, float maxWidth = 10000.0f); + + Microsoft::WRL::ComPtr m_TextFormat; + Microsoft::WRL::ComPtr m_TextLayout; + Microsoft::WRL::ComPtr m_InlineEllipsis; + + std::wstring m_LastString; + + // Used to emulate GDI+ behaviour. + float m_ExtraHeight; + float m_LineGap; + + // Contains the value passed to the last call of of SetTrimming(). + bool m_Trimming; +}; + +} // namespace Gfx + #endif \ No newline at end of file diff --git a/Common/Gfx/TextFormatD2D_Test.cpp b/Common/Gfx/TextFormatD2D_Test.cpp index 78c21538..1faecd01 100644 --- a/Common/Gfx/TextFormatD2D_Test.cpp +++ b/Common/Gfx/TextFormatD2D_Test.cpp @@ -1,83 +1,83 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "Canvas.h" -#include "TextFormatD2D.h" -#include "../UnitTest.h" -#include - -namespace Gfx { - -TEST_CLASS(Common_Gfx_TextFormatD2D_Test) -{ -public: - std::unique_ptr m_D2D; - - Common_Gfx_TextFormatD2D_Test() : - m_D2D(Canvas::Create(Gfx::Renderer::D2D)) - { - // TODO: Handle this in CanvasD2D. - ULONG_PTR gdiplusToken; - Gdiplus::GdiplusStartupInput gdiplusStartupInput; - Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr); - - m_D2D->Resize(10, 10); - m_D2D->SetAntiAliasing(true); - } - - TEST_METHOD(TestInaccurateText) - { - std::unique_ptr textFormat((TextFormatD2D*)m_D2D->CreateTextFormat()); - textFormat->SetProperties(L"Arial", 10, false, false, nullptr); - - DWRITE_TEXT_METRICS metrics; - - metrics = textFormat->GetMetrics(L"test", 4, true); - Assert::AreEqual(26, (int)metrics.width); - Assert::AreEqual(16, (int)metrics.height); - - metrics = textFormat->GetMetrics(L"test", 4, false); - Assert::AreEqual(21, (int)metrics.width); - Assert::AreEqual(14, (int)metrics.height); - } - - TEST_METHOD(TestTrailingNewlineGdipCompatibility) - { - std::unique_ptr textFormat((TextFormatD2D*)m_D2D->CreateTextFormat()); - textFormat->SetProperties(L"Arial", 10, false, false, nullptr); - - DWRITE_TEXT_METRICS metrics; - - metrics = textFormat->GetMetrics(L"test\n", 5, false); - Assert::AreEqual(15, (int)metrics.height); - metrics = textFormat->GetMetrics(L"test\r\n", 6, false); - Assert::AreEqual(15, (int)metrics.height); - - metrics = textFormat->GetMetrics(L"test\n ", 6, false); - Assert::AreEqual(30, (int)metrics.height); - metrics = textFormat->GetMetrics(L"test\r\n ", 7, false); - Assert::AreEqual(30, (int)metrics.height); - - metrics = textFormat->GetMetrics(L"test\n\n", 6, false); - Assert::AreEqual(30, (int)metrics.height); - metrics = textFormat->GetMetrics(L"test\r\n\r\n", 8, false); - Assert::AreEqual(30, (int)metrics.height); - } -}; - -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "Canvas.h" +#include "TextFormatD2D.h" +#include "../UnitTest.h" +#include + +namespace Gfx { + +TEST_CLASS(Common_Gfx_TextFormatD2D_Test) +{ +public: + std::unique_ptr m_D2D; + + Common_Gfx_TextFormatD2D_Test() : + m_D2D(Canvas::Create(Gfx::Renderer::D2D)) + { + // TODO: Handle this in CanvasD2D. + ULONG_PTR gdiplusToken; + Gdiplus::GdiplusStartupInput gdiplusStartupInput; + Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr); + + m_D2D->Resize(10, 10); + m_D2D->SetAntiAliasing(true); + } + + TEST_METHOD(TestInaccurateText) + { + std::unique_ptr textFormat((TextFormatD2D*)m_D2D->CreateTextFormat()); + textFormat->SetProperties(L"Arial", 10, false, false, nullptr); + + DWRITE_TEXT_METRICS metrics; + + metrics = textFormat->GetMetrics(L"test", 4, true); + Assert::AreEqual(26, (int)metrics.width); + Assert::AreEqual(16, (int)metrics.height); + + metrics = textFormat->GetMetrics(L"test", 4, false); + Assert::AreEqual(21, (int)metrics.width); + Assert::AreEqual(14, (int)metrics.height); + } + + TEST_METHOD(TestTrailingNewlineGdipCompatibility) + { + std::unique_ptr textFormat((TextFormatD2D*)m_D2D->CreateTextFormat()); + textFormat->SetProperties(L"Arial", 10, false, false, nullptr); + + DWRITE_TEXT_METRICS metrics; + + metrics = textFormat->GetMetrics(L"test\n", 5, false); + Assert::AreEqual(15, (int)metrics.height); + metrics = textFormat->GetMetrics(L"test\r\n", 6, false); + Assert::AreEqual(15, (int)metrics.height); + + metrics = textFormat->GetMetrics(L"test\n ", 6, false); + Assert::AreEqual(30, (int)metrics.height); + metrics = textFormat->GetMetrics(L"test\r\n ", 7, false); + Assert::AreEqual(30, (int)metrics.height); + + metrics = textFormat->GetMetrics(L"test\n\n", 6, false); + Assert::AreEqual(30, (int)metrics.height); + metrics = textFormat->GetMetrics(L"test\r\n\r\n", 8, false); + Assert::AreEqual(30, (int)metrics.height); + } +}; + +} // namespace Gfx diff --git a/Common/Gfx/TextFormatGDIP.cpp b/Common/Gfx/TextFormatGDIP.cpp index 29854c6b..066b4b69 100644 --- a/Common/Gfx/TextFormatGDIP.cpp +++ b/Common/Gfx/TextFormatGDIP.cpp @@ -1,134 +1,134 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "TextFormatGDIP.h" -#include "FontCollectionGDIP.h" - -namespace Gfx { - -TextFormatGDIP::TextFormatGDIP() -{ -} - -TextFormatGDIP::~TextFormatGDIP() -{ -} - -void TextFormatGDIP::SetProperties( - const WCHAR* fontFamily, int size, bool bold, bool italic, - const FontCollection* fontCollection) -{ - auto fontCollectionGDIP = (FontCollectionGDIP*)fontCollection; - - m_Font.reset(); - - m_FontFamily.reset(new Gdiplus::FontFamily(fontFamily)); - if (m_FontFamily->GetLastStatus() != Gdiplus::Ok) - { - m_FontFamily.reset(); - - // Not found in system collection so try the private collection. - if (fontCollectionGDIP && fontCollectionGDIP->m_PrivateCollection) - { - m_FontFamily.reset(new Gdiplus::FontFamily(fontFamily, fontCollectionGDIP->m_PrivateCollection)); - if (m_FontFamily->GetLastStatus() != Gdiplus::Ok) - { - m_FontFamily.reset(); - } - } - } - - Gdiplus::FontStyle style = Gdiplus::FontStyleRegular; - if (bold && italic) - { - style = Gdiplus::FontStyleBoldItalic; - } - else if (bold) - { - style = Gdiplus::FontStyleBold; - } - else if (italic) - { - style = Gdiplus::FontStyleItalic; - } - - if (size != 0) - { - // Adjust the font size with screen DPI. - HDC dc = GetDC(0); - const int dpi = GetDeviceCaps(dc, LOGPIXELSX); - ReleaseDC(0, dc); - const Gdiplus::REAL fontSize = (Gdiplus::REAL)size * (96.0f / dpi); - - if (m_FontFamily) - { - m_Font.reset(new Gdiplus::Font(m_FontFamily.get(), fontSize, style)); - if (m_Font->GetLastStatus() != Gdiplus::Ok) - { - m_Font.reset(); - } - } - - if (!m_Font) - { - // Use default font ("Arial" or GenericSansSerif). - m_Font.reset(new Gdiplus::Font(L"Arial", fontSize, style)); - if (m_Font->GetLastStatus() != Gdiplus::Ok) - { - m_Font.reset(); - } - } - } -} - -void TextFormatGDIP::SetTrimming(bool trim) -{ - if (trim) - { - m_StringFormat.SetTrimming(Gdiplus::StringTrimmingEllipsisCharacter); - m_StringFormat.SetFormatFlags(0x0); - } - else - { - m_StringFormat.SetTrimming(Gdiplus::StringTrimmingNone); - m_StringFormat.SetFormatFlags(Gdiplus::StringFormatFlagsNoClip | Gdiplus::StringFormatFlagsNoWrap); - } -} - -void TextFormatGDIP::SetHorizontalAlignment(HorizontalAlignment alignment) -{ - static_assert(Gdiplus::StringAlignmentNear == (int)HorizontalAlignment::Left, "Enum mismatch"); - static_assert(Gdiplus::StringAlignmentCenter == (int)HorizontalAlignment::Center, "Enum mismatch"); - static_assert(Gdiplus::StringAlignmentFar == (int)HorizontalAlignment::Right, "Enum mismatch"); - - __super::SetHorizontalAlignment(alignment); - m_StringFormat.SetAlignment((Gdiplus::StringAlignment)alignment); -} - -void TextFormatGDIP::SetVerticalAlignment(VerticalAlignment alignment) -{ - static_assert(Gdiplus::StringAlignmentNear == (int)VerticalAlignment::Top, "Enum mismatch"); - static_assert(Gdiplus::StringAlignmentCenter == (int)VerticalAlignment::Center, "Enum mismatch"); - static_assert(Gdiplus::StringAlignmentFar == (int)VerticalAlignment::Bottom, "Enum mismatch"); - - __super::SetVerticalAlignment(alignment); - m_StringFormat.SetLineAlignment((Gdiplus::StringAlignment)alignment); -} - -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "TextFormatGDIP.h" +#include "FontCollectionGDIP.h" + +namespace Gfx { + +TextFormatGDIP::TextFormatGDIP() +{ +} + +TextFormatGDIP::~TextFormatGDIP() +{ +} + +void TextFormatGDIP::SetProperties( + const WCHAR* fontFamily, int size, bool bold, bool italic, + const FontCollection* fontCollection) +{ + auto fontCollectionGDIP = (FontCollectionGDIP*)fontCollection; + + m_Font.reset(); + + m_FontFamily.reset(new Gdiplus::FontFamily(fontFamily)); + if (m_FontFamily->GetLastStatus() != Gdiplus::Ok) + { + m_FontFamily.reset(); + + // Not found in system collection so try the private collection. + if (fontCollectionGDIP && fontCollectionGDIP->m_PrivateCollection) + { + m_FontFamily.reset(new Gdiplus::FontFamily(fontFamily, fontCollectionGDIP->m_PrivateCollection)); + if (m_FontFamily->GetLastStatus() != Gdiplus::Ok) + { + m_FontFamily.reset(); + } + } + } + + Gdiplus::FontStyle style = Gdiplus::FontStyleRegular; + if (bold && italic) + { + style = Gdiplus::FontStyleBoldItalic; + } + else if (bold) + { + style = Gdiplus::FontStyleBold; + } + else if (italic) + { + style = Gdiplus::FontStyleItalic; + } + + if (size != 0) + { + // Adjust the font size with screen DPI. + HDC dc = GetDC(0); + const int dpi = GetDeviceCaps(dc, LOGPIXELSX); + ReleaseDC(0, dc); + const Gdiplus::REAL fontSize = (Gdiplus::REAL)size * (96.0f / dpi); + + if (m_FontFamily) + { + m_Font.reset(new Gdiplus::Font(m_FontFamily.get(), fontSize, style)); + if (m_Font->GetLastStatus() != Gdiplus::Ok) + { + m_Font.reset(); + } + } + + if (!m_Font) + { + // Use default font ("Arial" or GenericSansSerif). + m_Font.reset(new Gdiplus::Font(L"Arial", fontSize, style)); + if (m_Font->GetLastStatus() != Gdiplus::Ok) + { + m_Font.reset(); + } + } + } +} + +void TextFormatGDIP::SetTrimming(bool trim) +{ + if (trim) + { + m_StringFormat.SetTrimming(Gdiplus::StringTrimmingEllipsisCharacter); + m_StringFormat.SetFormatFlags(0x0); + } + else + { + m_StringFormat.SetTrimming(Gdiplus::StringTrimmingNone); + m_StringFormat.SetFormatFlags(Gdiplus::StringFormatFlagsNoClip | Gdiplus::StringFormatFlagsNoWrap); + } +} + +void TextFormatGDIP::SetHorizontalAlignment(HorizontalAlignment alignment) +{ + static_assert(Gdiplus::StringAlignmentNear == (int)HorizontalAlignment::Left, "Enum mismatch"); + static_assert(Gdiplus::StringAlignmentCenter == (int)HorizontalAlignment::Center, "Enum mismatch"); + static_assert(Gdiplus::StringAlignmentFar == (int)HorizontalAlignment::Right, "Enum mismatch"); + + __super::SetHorizontalAlignment(alignment); + m_StringFormat.SetAlignment((Gdiplus::StringAlignment)alignment); +} + +void TextFormatGDIP::SetVerticalAlignment(VerticalAlignment alignment) +{ + static_assert(Gdiplus::StringAlignmentNear == (int)VerticalAlignment::Top, "Enum mismatch"); + static_assert(Gdiplus::StringAlignmentCenter == (int)VerticalAlignment::Center, "Enum mismatch"); + static_assert(Gdiplus::StringAlignmentFar == (int)VerticalAlignment::Bottom, "Enum mismatch"); + + __super::SetVerticalAlignment(alignment); + m_StringFormat.SetLineAlignment((Gdiplus::StringAlignment)alignment); +} + +} // namespace Gfx diff --git a/Common/Gfx/TextFormatGDIP.h b/Common/Gfx/TextFormatGDIP.h index df9bbe1e..46041a7e 100644 --- a/Common/Gfx/TextFormatGDIP.h +++ b/Common/Gfx/TextFormatGDIP.h @@ -1,60 +1,60 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_GFX_TEXTFORMATGDIP_H_ -#define RM_GFX_TEXTFORMATGDIP_H_ - -#include "TextFormat.h" -#include -#include // For Gdiplus.h. -#include - -namespace Gfx { - -// Provides a GDI+ implementation of TextFormat for use with CanvasGDIP. -class TextFormatGDIP : public TextFormat -{ -public: - TextFormatGDIP(); - virtual ~TextFormatGDIP(); - - TextFormatGDIP(const TextFormatGDIP& other) = delete; - TextFormatGDIP& operator=(TextFormatGDIP other) = delete; - - virtual bool IsInitialized() const override { return m_Font != nullptr; } - - virtual void SetProperties( - const WCHAR* fontFamily, int size, bool bold, bool italic, - const FontCollection* fontCollection) override; - - virtual void SetTrimming(bool trim) override; - - virtual void SetHorizontalAlignment(HorizontalAlignment alignment) override; - virtual void SetVerticalAlignment(VerticalAlignment alignment) override; - -private: - friend class CanvasGDIP; - - std::unique_ptr m_Font; - std::unique_ptr m_FontFamily; - Gdiplus::StringFormat m_StringFormat; -}; - -} // namespace Gfx - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_TEXTFORMATGDIP_H_ +#define RM_GFX_TEXTFORMATGDIP_H_ + +#include "TextFormat.h" +#include +#include // For Gdiplus.h. +#include + +namespace Gfx { + +// Provides a GDI+ implementation of TextFormat for use with CanvasGDIP. +class TextFormatGDIP : public TextFormat +{ +public: + TextFormatGDIP(); + virtual ~TextFormatGDIP(); + + TextFormatGDIP(const TextFormatGDIP& other) = delete; + TextFormatGDIP& operator=(TextFormatGDIP other) = delete; + + virtual bool IsInitialized() const override { return m_Font != nullptr; } + + virtual void SetProperties( + const WCHAR* fontFamily, int size, bool bold, bool italic, + const FontCollection* fontCollection) override; + + virtual void SetTrimming(bool trim) override; + + virtual void SetHorizontalAlignment(HorizontalAlignment alignment) override; + virtual void SetVerticalAlignment(VerticalAlignment alignment) override; + +private: + friend class CanvasGDIP; + + std::unique_ptr m_Font; + std::unique_ptr m_FontFamily; + Gdiplus::StringFormat m_StringFormat; +}; + +} // namespace Gfx + #endif \ No newline at end of file diff --git a/Common/Gfx/Util/DWriteFontCollectionLoader.cpp b/Common/Gfx/Util/DWriteFontCollectionLoader.cpp index 0afd4a5c..5691cd1e 100644 --- a/Common/Gfx/Util/DWriteFontCollectionLoader.cpp +++ b/Common/Gfx/Util/DWriteFontCollectionLoader.cpp @@ -1,67 +1,67 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "DWriteFontCollectionLoader.h" -#include "DWriteFontFileEnumerator.h" - -namespace Gfx { -namespace Util { - -DWriteFontCollectionLoader* DWriteFontCollectionLoader::GetInstance() -{ - static DWriteFontCollectionLoader s_Instance; - return &s_Instance; -} - -ULONG STDMETHODCALLTYPE DWriteFontCollectionLoader::AddRef() -{ - // This is a singleton class so return a dummy value. - return 1; -} - -ULONG STDMETHODCALLTYPE DWriteFontCollectionLoader::Release() -{ - // This is a singleton class so return a dummy value. - return 1; -} - -HRESULT STDMETHODCALLTYPE DWriteFontCollectionLoader::QueryInterface(IID const& riid, void** ppvObject) -{ - if (riid == IID_IUnknown || - riid == __uuidof(IDWriteFontCollectionLoader)) - { - *ppvObject = this; - return S_OK; - } - - *ppvObject = nullptr; - return E_NOINTERFACE; -} - -HRESULT STDMETHODCALLTYPE DWriteFontCollectionLoader::CreateEnumeratorFromKey( - IDWriteFactory* factory, void const* collectionKey, UINT32 collectionKeySize, - IDWriteFontFileEnumerator** fontFileEnumerator) -{ - *fontFileEnumerator = new DWriteFontFileEnumerator( - *(const std::vector*)collectionKey); - return S_OK; -} - -} // namespace Util -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "DWriteFontCollectionLoader.h" +#include "DWriteFontFileEnumerator.h" + +namespace Gfx { +namespace Util { + +DWriteFontCollectionLoader* DWriteFontCollectionLoader::GetInstance() +{ + static DWriteFontCollectionLoader s_Instance; + return &s_Instance; +} + +ULONG STDMETHODCALLTYPE DWriteFontCollectionLoader::AddRef() +{ + // This is a singleton class so return a dummy value. + return 1; +} + +ULONG STDMETHODCALLTYPE DWriteFontCollectionLoader::Release() +{ + // This is a singleton class so return a dummy value. + return 1; +} + +HRESULT STDMETHODCALLTYPE DWriteFontCollectionLoader::QueryInterface(IID const& riid, void** ppvObject) +{ + if (riid == IID_IUnknown || + riid == __uuidof(IDWriteFontCollectionLoader)) + { + *ppvObject = this; + return S_OK; + } + + *ppvObject = nullptr; + return E_NOINTERFACE; +} + +HRESULT STDMETHODCALLTYPE DWriteFontCollectionLoader::CreateEnumeratorFromKey( + IDWriteFactory* factory, void const* collectionKey, UINT32 collectionKeySize, + IDWriteFontFileEnumerator** fontFileEnumerator) +{ + *fontFileEnumerator = new DWriteFontFileEnumerator( + *(const std::vector*)collectionKey); + return S_OK; +} + +} // namespace Util +} // namespace Gfx diff --git a/Common/Gfx/Util/DWriteFontCollectionLoader.h b/Common/Gfx/Util/DWriteFontCollectionLoader.h index 16ab2b36..66c7e8e3 100644 --- a/Common/Gfx/Util/DWriteFontCollectionLoader.h +++ b/Common/Gfx/Util/DWriteFontCollectionLoader.h @@ -1,53 +1,53 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_GFX_UTIL_DWRITEFONTCOLLECTIONLOADER_H_ -#define RM_GFX_UTIL_DWRITEFONTCOLLECTIONLOADER_H_ - -#include - -namespace Gfx { -namespace Util { - -// Implements the IDWriteFontCollectionLoader interface as a singleton object. When -// CreateEnumeratorFromKey is called, a new DWriteFontFileEnumerator object is created using -// |fontCollectionKey| (which is assumed to be a pointer to std::vector). -class DWriteFontCollectionLoader : public IDWriteFontCollectionLoader -{ -public: - static DWriteFontCollectionLoader* GetInstance(); - - // IUnknown - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override; - virtual ULONG STDMETHODCALLTYPE AddRef() override; - virtual ULONG STDMETHODCALLTYPE Release() override; - - // IFontCollectionLoader - virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey( - IDWriteFactory* factory, void const* fontCollectionKey, UINT32 fontCollectionKeySize, - IDWriteFontFileEnumerator** fontFileEnumerator) override; - -private: - DWriteFontCollectionLoader() {} - DWriteFontCollectionLoader(const DWriteFontCollectionLoader& other) {} -}; - -} // namespace Util -} // namespace Gfx - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_UTIL_DWRITEFONTCOLLECTIONLOADER_H_ +#define RM_GFX_UTIL_DWRITEFONTCOLLECTIONLOADER_H_ + +#include + +namespace Gfx { +namespace Util { + +// Implements the IDWriteFontCollectionLoader interface as a singleton object. When +// CreateEnumeratorFromKey is called, a new DWriteFontFileEnumerator object is created using +// |fontCollectionKey| (which is assumed to be a pointer to std::vector). +class DWriteFontCollectionLoader : public IDWriteFontCollectionLoader +{ +public: + static DWriteFontCollectionLoader* GetInstance(); + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override; + virtual ULONG STDMETHODCALLTYPE AddRef() override; + virtual ULONG STDMETHODCALLTYPE Release() override; + + // IFontCollectionLoader + virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey( + IDWriteFactory* factory, void const* fontCollectionKey, UINT32 fontCollectionKeySize, + IDWriteFontFileEnumerator** fontFileEnumerator) override; + +private: + DWriteFontCollectionLoader() {} + DWriteFontCollectionLoader(const DWriteFontCollectionLoader& other) {} +}; + +} // namespace Util +} // namespace Gfx + #endif \ No newline at end of file diff --git a/Common/Gfx/Util/DWriteFontFileEnumerator.cpp b/Common/Gfx/Util/DWriteFontFileEnumerator.cpp index 4a036279..b8b255ad 100644 --- a/Common/Gfx/Util/DWriteFontFileEnumerator.cpp +++ b/Common/Gfx/Util/DWriteFontFileEnumerator.cpp @@ -1,78 +1,78 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "DWriteFontFileEnumerator.h" - -namespace Gfx { -namespace Util { - -DWriteFontFileEnumerator::DWriteFontFileEnumerator(const std::vector& fontFiles) : - m_RefCount(1), - m_FontFiles(fontFiles), - m_CurrentFontFileIndex(-1) -{ -} - -ULONG STDMETHODCALLTYPE DWriteFontFileEnumerator::AddRef() -{ - ++m_RefCount; - return m_RefCount; -} - -ULONG STDMETHODCALLTYPE DWriteFontFileEnumerator::Release() -{ - --m_RefCount; - if (m_RefCount == 0) - { - delete this; - return 0; - } - return m_RefCount; -} - -HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::QueryInterface(IID const& riid, void** ppvObject) -{ - if (riid == IID_IUnknown || - riid == __uuidof(IDWriteFontFileEnumerator)) - { - *ppvObject = this; - AddRef(); - return S_OK; - } - - *ppvObject = nullptr; - return E_NOINTERFACE; -} - -HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) -{ - *hasCurrentFile = (++m_CurrentFontFileIndex < (int)m_FontFiles.size()); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) -{ - IDWriteFontFile* currentFontFile = m_FontFiles[m_CurrentFontFileIndex]; - currentFontFile->AddRef(); - *fontFile = currentFontFile; - return S_OK; -} - -} // namespace Util -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "DWriteFontFileEnumerator.h" + +namespace Gfx { +namespace Util { + +DWriteFontFileEnumerator::DWriteFontFileEnumerator(const std::vector& fontFiles) : + m_RefCount(1), + m_FontFiles(fontFiles), + m_CurrentFontFileIndex(-1) +{ +} + +ULONG STDMETHODCALLTYPE DWriteFontFileEnumerator::AddRef() +{ + ++m_RefCount; + return m_RefCount; +} + +ULONG STDMETHODCALLTYPE DWriteFontFileEnumerator::Release() +{ + --m_RefCount; + if (m_RefCount == 0) + { + delete this; + return 0; + } + return m_RefCount; +} + +HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::QueryInterface(IID const& riid, void** ppvObject) +{ + if (riid == IID_IUnknown || + riid == __uuidof(IDWriteFontFileEnumerator)) + { + *ppvObject = this; + AddRef(); + return S_OK; + } + + *ppvObject = nullptr; + return E_NOINTERFACE; +} + +HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) +{ + *hasCurrentFile = (++m_CurrentFontFileIndex < (int)m_FontFiles.size()); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) +{ + IDWriteFontFile* currentFontFile = m_FontFiles[m_CurrentFontFileIndex]; + currentFontFile->AddRef(); + *fontFile = currentFontFile; + return S_OK; +} + +} // namespace Util +} // namespace Gfx diff --git a/Common/Gfx/Util/DWriteFontFileEnumerator.h b/Common/Gfx/Util/DWriteFontFileEnumerator.h index d01c9187..07f872ab 100644 --- a/Common/Gfx/Util/DWriteFontFileEnumerator.h +++ b/Common/Gfx/Util/DWriteFontFileEnumerator.h @@ -1,56 +1,56 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_GFX_UTIL_DWRITEFONTFILEENUMERATOR_H_ -#define RM_GFX_UTIL_DWRITEFONTFILEENUMERATOR_H_ - -#include -#include - -namespace Gfx { -namespace Util { - -// Implements IDWriteFontFileEnumerator by enumerating over std::vector. -class DWriteFontFileEnumerator : public IDWriteFontFileEnumerator -{ -public: - DWriteFontFileEnumerator(const std::vector& fontFiles); - - // IUnknown - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override; - virtual ULONG STDMETHODCALLTYPE AddRef() override; - virtual ULONG STDMETHODCALLTYPE Release() override; - - // IDWriteFontFileEnumerator - virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile) override; - virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** currentFontFile) override; - -private: - ULONG m_RefCount; - - const std::vector& m_FontFiles; - - // Current index of |m_FontFiles|. The type is int instead of size_t as it starts from -1 as - // required by IDWriteFontFileEnumerator. - int m_CurrentFontFileIndex; -}; - -} // namespace Util -} // namespace Gfx - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_UTIL_DWRITEFONTFILEENUMERATOR_H_ +#define RM_GFX_UTIL_DWRITEFONTFILEENUMERATOR_H_ + +#include +#include + +namespace Gfx { +namespace Util { + +// Implements IDWriteFontFileEnumerator by enumerating over std::vector. +class DWriteFontFileEnumerator : public IDWriteFontFileEnumerator +{ +public: + DWriteFontFileEnumerator(const std::vector& fontFiles); + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override; + virtual ULONG STDMETHODCALLTYPE AddRef() override; + virtual ULONG STDMETHODCALLTYPE Release() override; + + // IDWriteFontFileEnumerator + virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile) override; + virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** currentFontFile) override; + +private: + ULONG m_RefCount; + + const std::vector& m_FontFiles; + + // Current index of |m_FontFiles|. The type is int instead of size_t as it starts from -1 as + // required by IDWriteFontFileEnumerator. + int m_CurrentFontFileIndex; +}; + +} // namespace Util +} // namespace Gfx + #endif \ No newline at end of file diff --git a/Common/Gfx/Util/DWriteHelpers.cpp b/Common/Gfx/Util/DWriteHelpers.cpp index 0676167f..c15852e7 100644 --- a/Common/Gfx/Util/DWriteHelpers.cpp +++ b/Common/Gfx/Util/DWriteHelpers.cpp @@ -1,218 +1,218 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "DWriteHelpers.h" - -namespace Gfx { -namespace Util { - -HRESULT GetDWritePropertiesFromGDIProperties( - IDWriteFactory* factory, const WCHAR* gdiFamilyName, const bool gdiBold, const bool gdiItalic, - DWRITE_FONT_WEIGHT& dwriteFontWeight, DWRITE_FONT_STYLE& dwriteFontStyle, - DWRITE_FONT_STRETCH& dwriteFontStretch, WCHAR* dwriteFamilyName, UINT dwriteFamilyNameSize) -{ - HRESULT hr = E_FAIL; - IDWriteFont* dwriteFont = CreateDWriteFontFromGDIFamilyName(factory, gdiFamilyName); - if (dwriteFont) - { - hr = GetFamilyNameFromDWriteFont(dwriteFont, dwriteFamilyName, dwriteFamilyNameSize); - if (SUCCEEDED(hr)) - { - GetPropertiesFromDWriteFont( - dwriteFont, gdiBold, gdiItalic, &dwriteFontWeight, &dwriteFontStyle, &dwriteFontStretch); - } - - dwriteFont->Release(); - } - - return hr; -} - -void GetPropertiesFromDWriteFont( - IDWriteFont* dwriteFont, const bool bold, const bool italic, - DWRITE_FONT_WEIGHT* dwriteFontWeight, DWRITE_FONT_STYLE* dwriteFontStyle, - DWRITE_FONT_STRETCH* dwriteFontStretch) -{ - *dwriteFontWeight = dwriteFont->GetWeight(); - if (bold) - { - if (*dwriteFontWeight == DWRITE_FONT_WEIGHT_NORMAL) - { - *dwriteFontWeight = DWRITE_FONT_WEIGHT_BOLD; - } - else if (*dwriteFontWeight < DWRITE_FONT_WEIGHT_ULTRA_BOLD) - { - // If 'gdiFamilyName' was e.g. 'Segoe UI Light', |dwFontWeight| wil be equal to - // DWRITE_FONT_WEIGHT_LIGHT. If |gdiBold| is true in that case, we need to - // increase the weight a little more for similar results with GDI+. - // TODO: Is +100 enough? - *dwriteFontWeight = (DWRITE_FONT_WEIGHT)(*dwriteFontWeight + 100); - } - } - - *dwriteFontStyle = dwriteFont->GetStyle(); - if (italic && *dwriteFontStyle == DWRITE_FONT_STYLE_NORMAL) - { - *dwriteFontStyle = DWRITE_FONT_STYLE_ITALIC; - } - - *dwriteFontStretch = dwriteFont->GetStretch(); -} - -IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* gdiFamilyName) -{ - Microsoft::WRL::ComPtr dwGdiInterop; - HRESULT hr = factory->GetGdiInterop(dwGdiInterop.GetAddressOf()); - if (SUCCEEDED(hr)) - { - LOGFONT lf = {}; - wcscpy_s(lf.lfFaceName, gdiFamilyName); - lf.lfHeight = -12; - lf.lfWeight = FW_DONTCARE; - lf.lfCharSet = DEFAULT_CHARSET; - lf.lfOutPrecision = OUT_DEFAULT_PRECIS; - lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; - lf.lfQuality = ANTIALIASED_QUALITY; - lf.lfPitchAndFamily = VARIABLE_PITCH; - - IDWriteFont* dwFont; - hr = dwGdiInterop->CreateFontFromLOGFONT(&lf, &dwFont); - if (SUCCEEDED(hr)) - { - return dwFont; - } - } - - return nullptr; -} - -HRESULT GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, const UINT bufferSize) -{ - IDWriteFontFamily* dwriteFontFamily; - HRESULT hr = font->GetFontFamily(&dwriteFontFamily); - if (SUCCEEDED(hr)) - { - hr = GetFamilyNameFromDWriteFontFamily(dwriteFontFamily, buffer, bufferSize); - dwriteFontFamily->Release(); - } - - return hr; -} - -HRESULT GetFamilyNameFromDWriteFontFamily( - IDWriteFontFamily* fontFamily, WCHAR* buffer, const UINT bufferSize) -{ - IDWriteLocalizedStrings* dwFamilyNames; - HRESULT hr = fontFamily->GetFamilyNames(&dwFamilyNames); - if (SUCCEEDED(hr)) - { - // TODO: Determine the best index? - hr = dwFamilyNames->GetString(0, buffer, bufferSize); - dwFamilyNames->Release(); - } - - return hr; -} - -bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* familyName) -{ - bool result = false; - IDWriteFontCollection* systemFontCollection; - HRESULT hr = factory->GetSystemFontCollection(&systemFontCollection); - if (SUCCEEDED(hr)) - { - UINT32 familyNameIndex; - BOOL familyNameFound; - HRESULT hr = systemFontCollection->FindFamilyName( - familyName, &familyNameIndex, &familyNameFound); - if (SUCCEEDED(hr) && familyNameFound) - { - result = true; - } - - systemFontCollection->Release(); - } - - return result; -} - -HRESULT GetGDIFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize) -{ - Microsoft::WRL::ComPtr strings; - BOOL stringsExist; - font->GetInformationalStrings( - DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, strings.GetAddressOf(), &stringsExist); - if (strings && stringsExist) - { - return strings->GetString(0, buffer, bufferSize); - } - - return E_FAIL; -} - -IDWriteFont* FindDWriteFontInFontFamilyByGDIFamilyName( - IDWriteFontFamily* fontFamily, const WCHAR* gdiFamilyName) -{ - const UINT32 fontFamilyFontCount = fontFamily->GetFontCount(); - for (UINT32 j = 0; j < fontFamilyFontCount; ++j) - { - IDWriteFont* font; - HRESULT hr = fontFamily->GetFont(j, &font); - if (SUCCEEDED(hr)) - { - WCHAR buffer[LF_FACESIZE]; - hr = GetGDIFamilyNameFromDWriteFont(font, buffer, _countof(buffer)); - if (SUCCEEDED(hr) && _wcsicmp(gdiFamilyName, buffer) == 0) - { - return font; - } - - font->Release(); - } - } - - return nullptr; -} - -IDWriteFont* FindDWriteFontInFontCollectionByGDIFamilyName( - IDWriteFontCollection* fontCollection, const WCHAR* gdiFamilyName) -{ - const UINT32 fontCollectionFamilyCount = fontCollection->GetFontFamilyCount(); - for (UINT32 i = 0; i < fontCollectionFamilyCount; ++i) - { - IDWriteFontFamily* fontFamily; - HRESULT hr = fontCollection->GetFontFamily(i, &fontFamily); - if (SUCCEEDED(hr)) - { - IDWriteFont* font = FindDWriteFontInFontFamilyByGDIFamilyName( - fontFamily, gdiFamilyName); - fontFamily->Release(); - - if (font) - { - return font; - } - } - } - - return nullptr; -} - -} // namespace Util -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "DWriteHelpers.h" + +namespace Gfx { +namespace Util { + +HRESULT GetDWritePropertiesFromGDIProperties( + IDWriteFactory* factory, const WCHAR* gdiFamilyName, const bool gdiBold, const bool gdiItalic, + DWRITE_FONT_WEIGHT& dwriteFontWeight, DWRITE_FONT_STYLE& dwriteFontStyle, + DWRITE_FONT_STRETCH& dwriteFontStretch, WCHAR* dwriteFamilyName, UINT dwriteFamilyNameSize) +{ + HRESULT hr = E_FAIL; + IDWriteFont* dwriteFont = CreateDWriteFontFromGDIFamilyName(factory, gdiFamilyName); + if (dwriteFont) + { + hr = GetFamilyNameFromDWriteFont(dwriteFont, dwriteFamilyName, dwriteFamilyNameSize); + if (SUCCEEDED(hr)) + { + GetPropertiesFromDWriteFont( + dwriteFont, gdiBold, gdiItalic, &dwriteFontWeight, &dwriteFontStyle, &dwriteFontStretch); + } + + dwriteFont->Release(); + } + + return hr; +} + +void GetPropertiesFromDWriteFont( + IDWriteFont* dwriteFont, const bool bold, const bool italic, + DWRITE_FONT_WEIGHT* dwriteFontWeight, DWRITE_FONT_STYLE* dwriteFontStyle, + DWRITE_FONT_STRETCH* dwriteFontStretch) +{ + *dwriteFontWeight = dwriteFont->GetWeight(); + if (bold) + { + if (*dwriteFontWeight == DWRITE_FONT_WEIGHT_NORMAL) + { + *dwriteFontWeight = DWRITE_FONT_WEIGHT_BOLD; + } + else if (*dwriteFontWeight < DWRITE_FONT_WEIGHT_ULTRA_BOLD) + { + // If 'gdiFamilyName' was e.g. 'Segoe UI Light', |dwFontWeight| wil be equal to + // DWRITE_FONT_WEIGHT_LIGHT. If |gdiBold| is true in that case, we need to + // increase the weight a little more for similar results with GDI+. + // TODO: Is +100 enough? + *dwriteFontWeight = (DWRITE_FONT_WEIGHT)(*dwriteFontWeight + 100); + } + } + + *dwriteFontStyle = dwriteFont->GetStyle(); + if (italic && *dwriteFontStyle == DWRITE_FONT_STYLE_NORMAL) + { + *dwriteFontStyle = DWRITE_FONT_STYLE_ITALIC; + } + + *dwriteFontStretch = dwriteFont->GetStretch(); +} + +IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* gdiFamilyName) +{ + Microsoft::WRL::ComPtr dwGdiInterop; + HRESULT hr = factory->GetGdiInterop(dwGdiInterop.GetAddressOf()); + if (SUCCEEDED(hr)) + { + LOGFONT lf = {}; + wcscpy_s(lf.lfFaceName, gdiFamilyName); + lf.lfHeight = -12; + lf.lfWeight = FW_DONTCARE; + lf.lfCharSet = DEFAULT_CHARSET; + lf.lfOutPrecision = OUT_DEFAULT_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfQuality = ANTIALIASED_QUALITY; + lf.lfPitchAndFamily = VARIABLE_PITCH; + + IDWriteFont* dwFont; + hr = dwGdiInterop->CreateFontFromLOGFONT(&lf, &dwFont); + if (SUCCEEDED(hr)) + { + return dwFont; + } + } + + return nullptr; +} + +HRESULT GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, const UINT bufferSize) +{ + IDWriteFontFamily* dwriteFontFamily; + HRESULT hr = font->GetFontFamily(&dwriteFontFamily); + if (SUCCEEDED(hr)) + { + hr = GetFamilyNameFromDWriteFontFamily(dwriteFontFamily, buffer, bufferSize); + dwriteFontFamily->Release(); + } + + return hr; +} + +HRESULT GetFamilyNameFromDWriteFontFamily( + IDWriteFontFamily* fontFamily, WCHAR* buffer, const UINT bufferSize) +{ + IDWriteLocalizedStrings* dwFamilyNames; + HRESULT hr = fontFamily->GetFamilyNames(&dwFamilyNames); + if (SUCCEEDED(hr)) + { + // TODO: Determine the best index? + hr = dwFamilyNames->GetString(0, buffer, bufferSize); + dwFamilyNames->Release(); + } + + return hr; +} + +bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* familyName) +{ + bool result = false; + IDWriteFontCollection* systemFontCollection; + HRESULT hr = factory->GetSystemFontCollection(&systemFontCollection); + if (SUCCEEDED(hr)) + { + UINT32 familyNameIndex; + BOOL familyNameFound; + HRESULT hr = systemFontCollection->FindFamilyName( + familyName, &familyNameIndex, &familyNameFound); + if (SUCCEEDED(hr) && familyNameFound) + { + result = true; + } + + systemFontCollection->Release(); + } + + return result; +} + +HRESULT GetGDIFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize) +{ + Microsoft::WRL::ComPtr strings; + BOOL stringsExist; + font->GetInformationalStrings( + DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, strings.GetAddressOf(), &stringsExist); + if (strings && stringsExist) + { + return strings->GetString(0, buffer, bufferSize); + } + + return E_FAIL; +} + +IDWriteFont* FindDWriteFontInFontFamilyByGDIFamilyName( + IDWriteFontFamily* fontFamily, const WCHAR* gdiFamilyName) +{ + const UINT32 fontFamilyFontCount = fontFamily->GetFontCount(); + for (UINT32 j = 0; j < fontFamilyFontCount; ++j) + { + IDWriteFont* font; + HRESULT hr = fontFamily->GetFont(j, &font); + if (SUCCEEDED(hr)) + { + WCHAR buffer[LF_FACESIZE]; + hr = GetGDIFamilyNameFromDWriteFont(font, buffer, _countof(buffer)); + if (SUCCEEDED(hr) && _wcsicmp(gdiFamilyName, buffer) == 0) + { + return font; + } + + font->Release(); + } + } + + return nullptr; +} + +IDWriteFont* FindDWriteFontInFontCollectionByGDIFamilyName( + IDWriteFontCollection* fontCollection, const WCHAR* gdiFamilyName) +{ + const UINT32 fontCollectionFamilyCount = fontCollection->GetFontFamilyCount(); + for (UINT32 i = 0; i < fontCollectionFamilyCount; ++i) + { + IDWriteFontFamily* fontFamily; + HRESULT hr = fontCollection->GetFontFamily(i, &fontFamily); + if (SUCCEEDED(hr)) + { + IDWriteFont* font = FindDWriteFontInFontFamilyByGDIFamilyName( + fontFamily, gdiFamilyName); + fontFamily->Release(); + + if (font) + { + return font; + } + } + } + + return nullptr; +} + +} // namespace Util +} // namespace Gfx diff --git a/Common/Gfx/Util/DWriteHelpers.h b/Common/Gfx/Util/DWriteHelpers.h index 1140e2a5..74c1c2a3 100644 --- a/Common/Gfx/Util/DWriteHelpers.h +++ b/Common/Gfx/Util/DWriteHelpers.h @@ -1,58 +1,58 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_GFX_UTIL_DWRITEHELPERS_H_ -#define RM_GFX_UTIL_DWRITEHELPERS_H_ - -#include - -namespace Gfx { -namespace Util { - -// Maps the GDI family name and italic/bold flags to the DirectWrite family name, weight, style, -// and stretch. -HRESULT GetDWritePropertiesFromGDIProperties( - IDWriteFactory* factory, const WCHAR* gdiFamilyName, const bool gdiBold, const bool gdiItalic, - DWRITE_FONT_WEIGHT& dwriteFontWeight, DWRITE_FONT_STYLE& dwriteFontStyle, - DWRITE_FONT_STRETCH& dwriteFontStretch, WCHAR* dwriteFamilyName, UINT dwriteFamilyNameSize); - -void GetPropertiesFromDWriteFont( - IDWriteFont* dwriteFont, const bool bold, const bool italic, - DWRITE_FONT_WEIGHT* dwriteFontWeight, DWRITE_FONT_STYLE* dwriteFontStyle, - DWRITE_FONT_STRETCH* dwriteFontStretch); - -// Creates a IDWriteFont using the GDI family name instead of the DirectWrite family name. For -// example, 'Segoe UI' and 'Segoe UI Semibold' are separate family names with GDI whereas -// DirectWrite uses the family name 'Segoe UI' for both and differentiates them by the font -// style. -IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* fontFamily); - -HRESULT GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize); - -HRESULT GetFamilyNameFromDWriteFontFamily( - IDWriteFontFamily* fontFamily, WCHAR* buffer, UINT bufferSize); - -bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* familyName); - -IDWriteFont* FindDWriteFontInFontCollectionByGDIFamilyName( - IDWriteFontCollection* fontCollection, const WCHAR* gdiFamilyName); - -} // namespace Util -} // namespace Gfx - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_UTIL_DWRITEHELPERS_H_ +#define RM_GFX_UTIL_DWRITEHELPERS_H_ + +#include + +namespace Gfx { +namespace Util { + +// Maps the GDI family name and italic/bold flags to the DirectWrite family name, weight, style, +// and stretch. +HRESULT GetDWritePropertiesFromGDIProperties( + IDWriteFactory* factory, const WCHAR* gdiFamilyName, const bool gdiBold, const bool gdiItalic, + DWRITE_FONT_WEIGHT& dwriteFontWeight, DWRITE_FONT_STYLE& dwriteFontStyle, + DWRITE_FONT_STRETCH& dwriteFontStretch, WCHAR* dwriteFamilyName, UINT dwriteFamilyNameSize); + +void GetPropertiesFromDWriteFont( + IDWriteFont* dwriteFont, const bool bold, const bool italic, + DWRITE_FONT_WEIGHT* dwriteFontWeight, DWRITE_FONT_STYLE* dwriteFontStyle, + DWRITE_FONT_STRETCH* dwriteFontStretch); + +// Creates a IDWriteFont using the GDI family name instead of the DirectWrite family name. For +// example, 'Segoe UI' and 'Segoe UI Semibold' are separate family names with GDI whereas +// DirectWrite uses the family name 'Segoe UI' for both and differentiates them by the font +// style. +IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* fontFamily); + +HRESULT GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize); + +HRESULT GetFamilyNameFromDWriteFontFamily( + IDWriteFontFamily* fontFamily, WCHAR* buffer, UINT bufferSize); + +bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* familyName); + +IDWriteFont* FindDWriteFontInFontCollectionByGDIFamilyName( + IDWriteFontCollection* fontCollection, const WCHAR* gdiFamilyName); + +} // namespace Util +} // namespace Gfx + #endif \ No newline at end of file diff --git a/Common/Gfx/Util/WICBitmapDIB.cpp b/Common/Gfx/Util/WICBitmapDIB.cpp index b3c8aef9..9c1b6c2e 100644 --- a/Common/Gfx/Util/WICBitmapDIB.cpp +++ b/Common/Gfx/Util/WICBitmapDIB.cpp @@ -1,136 +1,136 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "WICBitmapDIB.h" -#include "WICBitmapLockDIB.h" - -namespace Gfx { -namespace Util { - -WICBitmapDIB::WICBitmapDIB() : - m_DIBSectionBuffer(), - m_DIBSectionBufferPixels(), - m_W(0), - m_H(0) -{ -} - -WICBitmapDIB::~WICBitmapDIB() -{ - if (m_DIBSectionBuffer) - { - DeleteObject(m_DIBSectionBuffer); - m_DIBSectionBufferPixels = nullptr; - } -} - -void WICBitmapDIB::Resize(UINT w, UINT h) -{ - if (m_DIBSectionBuffer) - { - DeleteObject(m_DIBSectionBuffer); - m_DIBSectionBufferPixels = nullptr; - } - - m_W = w; - m_H = h; - - BITMAPV4HEADER bh = {sizeof(BITMAPV4HEADER)}; - bh.bV4Width = (LONG)m_W; - bh.bV4Height = -(LONG)m_H; // Top-down DIB - bh.bV4Planes = 1; - bh.bV4BitCount = 32; - bh.bV4V4Compression = BI_BITFIELDS; - bh.bV4RedMask = 0x00FF0000; - bh.bV4GreenMask = 0x0000FF00; - bh.bV4BlueMask = 0x000000FF; - bh.bV4AlphaMask = 0xFF000000; - - m_DIBSectionBuffer = CreateDIBSection( - nullptr, - (BITMAPINFO*)&bh, - DIB_RGB_COLORS, - (void**)&m_DIBSectionBufferPixels, - nullptr, - 0); - - assert(m_DIBSectionBufferPixels); -} - -IFACEMETHODIMP WICBitmapDIB::QueryInterface(REFIID riid, void** ppvObject) -{ - return E_NOTIMPL; -} - -IFACEMETHODIMP_(ULONG) WICBitmapDIB::AddRef() -{ - return 0; -} - -IFACEMETHODIMP_(ULONG) WICBitmapDIB::Release() -{ - return 0; -} - -IFACEMETHODIMP WICBitmapDIB::GetSize(UINT* puiWidth, UINT* puiHeight) -{ - if (puiWidth) *puiWidth = m_W; - if (puiHeight) *puiHeight = m_H; - return S_OK; -} - -IFACEMETHODIMP WICBitmapDIB::GetPixelFormat(WICPixelFormatGUID* pPixelFormat) -{ - *pPixelFormat = GUID_WICPixelFormat32bppPBGRA; - return S_OK; -} - -IFACEMETHODIMP WICBitmapDIB::GetResolution(double* pDpiX, double* pDpiY) -{ - return E_NOTIMPL; -} - -IFACEMETHODIMP WICBitmapDIB::CopyPalette(IWICPalette* pIPalette) -{ - return E_NOTIMPL; -} - -IFACEMETHODIMP WICBitmapDIB::CopyPixels(const WICRect* prc, UINT cbStride, UINT cbBufferSize, BYTE* pbBuffer) -{ - return E_NOTIMPL; -} - -IFACEMETHODIMP WICBitmapDIB::Lock(const WICRect* prcLock, DWORD flags, IWICBitmapLock** ppILock) -{ - if (ppILock) *ppILock = (IWICBitmapLock*)new WICBitmapLockDIB(this, prcLock); - return S_OK; -} - -IFACEMETHODIMP WICBitmapDIB::SetPalette(IWICPalette* pIPalette) -{ - return E_NOTIMPL; -} - -IFACEMETHODIMP WICBitmapDIB::SetResolution(double dpiX, double dpiY) -{ - return E_NOTIMPL; -} - -} // namespace Util -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "WICBitmapDIB.h" +#include "WICBitmapLockDIB.h" + +namespace Gfx { +namespace Util { + +WICBitmapDIB::WICBitmapDIB() : + m_DIBSectionBuffer(), + m_DIBSectionBufferPixels(), + m_W(0), + m_H(0) +{ +} + +WICBitmapDIB::~WICBitmapDIB() +{ + if (m_DIBSectionBuffer) + { + DeleteObject(m_DIBSectionBuffer); + m_DIBSectionBufferPixels = nullptr; + } +} + +void WICBitmapDIB::Resize(UINT w, UINT h) +{ + if (m_DIBSectionBuffer) + { + DeleteObject(m_DIBSectionBuffer); + m_DIBSectionBufferPixels = nullptr; + } + + m_W = w; + m_H = h; + + BITMAPV4HEADER bh = {sizeof(BITMAPV4HEADER)}; + bh.bV4Width = (LONG)m_W; + bh.bV4Height = -(LONG)m_H; // Top-down DIB + bh.bV4Planes = 1; + bh.bV4BitCount = 32; + bh.bV4V4Compression = BI_BITFIELDS; + bh.bV4RedMask = 0x00FF0000; + bh.bV4GreenMask = 0x0000FF00; + bh.bV4BlueMask = 0x000000FF; + bh.bV4AlphaMask = 0xFF000000; + + m_DIBSectionBuffer = CreateDIBSection( + nullptr, + (BITMAPINFO*)&bh, + DIB_RGB_COLORS, + (void**)&m_DIBSectionBufferPixels, + nullptr, + 0); + + assert(m_DIBSectionBufferPixels); +} + +IFACEMETHODIMP WICBitmapDIB::QueryInterface(REFIID riid, void** ppvObject) +{ + return E_NOTIMPL; +} + +IFACEMETHODIMP_(ULONG) WICBitmapDIB::AddRef() +{ + return 0; +} + +IFACEMETHODIMP_(ULONG) WICBitmapDIB::Release() +{ + return 0; +} + +IFACEMETHODIMP WICBitmapDIB::GetSize(UINT* puiWidth, UINT* puiHeight) +{ + if (puiWidth) *puiWidth = m_W; + if (puiHeight) *puiHeight = m_H; + return S_OK; +} + +IFACEMETHODIMP WICBitmapDIB::GetPixelFormat(WICPixelFormatGUID* pPixelFormat) +{ + *pPixelFormat = GUID_WICPixelFormat32bppPBGRA; + return S_OK; +} + +IFACEMETHODIMP WICBitmapDIB::GetResolution(double* pDpiX, double* pDpiY) +{ + return E_NOTIMPL; +} + +IFACEMETHODIMP WICBitmapDIB::CopyPalette(IWICPalette* pIPalette) +{ + return E_NOTIMPL; +} + +IFACEMETHODIMP WICBitmapDIB::CopyPixels(const WICRect* prc, UINT cbStride, UINT cbBufferSize, BYTE* pbBuffer) +{ + return E_NOTIMPL; +} + +IFACEMETHODIMP WICBitmapDIB::Lock(const WICRect* prcLock, DWORD flags, IWICBitmapLock** ppILock) +{ + if (ppILock) *ppILock = (IWICBitmapLock*)new WICBitmapLockDIB(this, prcLock); + return S_OK; +} + +IFACEMETHODIMP WICBitmapDIB::SetPalette(IWICPalette* pIPalette) +{ + return E_NOTIMPL; +} + +IFACEMETHODIMP WICBitmapDIB::SetResolution(double dpiX, double dpiY) +{ + return E_NOTIMPL; +} + +} // namespace Util +} // namespace Gfx diff --git a/Common/Gfx/Util/WICBitmapDIB.h b/Common/Gfx/Util/WICBitmapDIB.h index 9cf0aeb3..2d57ac0b 100644 --- a/Common/Gfx/Util/WICBitmapDIB.h +++ b/Common/Gfx/Util/WICBitmapDIB.h @@ -1,76 +1,76 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_GFX_UTIL_WICBITMAPDIB_H_ -#define RM_GFX_UTIL_WICBITMAPDIB_H_ - -#include -#include - -namespace Gfx { -namespace Util { - -// Allows the use of a DIB section (HBITMAP) in Direct2D as a WIC bitmap. It is assumed that this -// class is used only with 32bpp PARGB bitmaps and using a sigle thread. -// -// This class does not follow the COM reference count model. RTTI is used instead. This class -// implements only the bare essentials in order to use a DIB section as a Direct2D render target. -class WICBitmapDIB : public IWICBitmap -{ -public: - WICBitmapDIB(); - ~WICBitmapDIB(); - - WICBitmapDIB(const WICBitmapDIB& other) = delete; - WICBitmapDIB& operator=(WICBitmapDIB other) = delete; - - void Resize(UINT w, UINT h); - - HBITMAP GetHandle() const { return m_DIBSectionBuffer; } - BYTE* GetData() const { return (BYTE*)m_DIBSectionBufferPixels; } - - // IUnknown - IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject); - IFACEMETHOD_(ULONG, AddRef)(); - IFACEMETHOD_(ULONG, Release)(); - - // IWICBitmapSource - IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight); - IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat); - IFACEMETHOD(GetResolution)(double* pDpiX, double* pDpiY); - IFACEMETHOD(CopyPalette)(IWICPalette* pIPalette); - IFACEMETHOD(CopyPixels)(const WICRect* prc, UINT cbStride, UINT cbBufferSize, BYTE* pbBuffer); - - // IWICBitmap - IFACEMETHOD(Lock)(const WICRect* prcLock, DWORD flags, IWICBitmapLock** ppILock); - IFACEMETHOD(SetPalette)(IWICPalette* pIPalette); - IFACEMETHOD(SetResolution)(double dpiX, double dpiY); - -private: - friend class WICBitmapLockDIB; - - HBITMAP m_DIBSectionBuffer; - LPDWORD m_DIBSectionBufferPixels; - UINT m_W; - UINT m_H; -}; - -} // namespace Util -} // namespace Gfx - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_UTIL_WICBITMAPDIB_H_ +#define RM_GFX_UTIL_WICBITMAPDIB_H_ + +#include +#include + +namespace Gfx { +namespace Util { + +// Allows the use of a DIB section (HBITMAP) in Direct2D as a WIC bitmap. It is assumed that this +// class is used only with 32bpp PARGB bitmaps and using a sigle thread. +// +// This class does not follow the COM reference count model. RTTI is used instead. This class +// implements only the bare essentials in order to use a DIB section as a Direct2D render target. +class WICBitmapDIB : public IWICBitmap +{ +public: + WICBitmapDIB(); + ~WICBitmapDIB(); + + WICBitmapDIB(const WICBitmapDIB& other) = delete; + WICBitmapDIB& operator=(WICBitmapDIB other) = delete; + + void Resize(UINT w, UINT h); + + HBITMAP GetHandle() const { return m_DIBSectionBuffer; } + BYTE* GetData() const { return (BYTE*)m_DIBSectionBufferPixels; } + + // IUnknown + IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject); + IFACEMETHOD_(ULONG, AddRef)(); + IFACEMETHOD_(ULONG, Release)(); + + // IWICBitmapSource + IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight); + IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat); + IFACEMETHOD(GetResolution)(double* pDpiX, double* pDpiY); + IFACEMETHOD(CopyPalette)(IWICPalette* pIPalette); + IFACEMETHOD(CopyPixels)(const WICRect* prc, UINT cbStride, UINT cbBufferSize, BYTE* pbBuffer); + + // IWICBitmap + IFACEMETHOD(Lock)(const WICRect* prcLock, DWORD flags, IWICBitmapLock** ppILock); + IFACEMETHOD(SetPalette)(IWICPalette* pIPalette); + IFACEMETHOD(SetResolution)(double dpiX, double dpiY); + +private: + friend class WICBitmapLockDIB; + + HBITMAP m_DIBSectionBuffer; + LPDWORD m_DIBSectionBufferPixels; + UINT m_W; + UINT m_H; +}; + +} // namespace Util +} // namespace Gfx + #endif \ No newline at end of file diff --git a/Common/Gfx/Util/WICBitmapLockDIB.cpp b/Common/Gfx/Util/WICBitmapLockDIB.cpp index 9d551664..b7c7a85a 100644 --- a/Common/Gfx/Util/WICBitmapLockDIB.cpp +++ b/Common/Gfx/Util/WICBitmapLockDIB.cpp @@ -1,91 +1,91 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "WICBitmapLockDIB.h" - -namespace Gfx { -namespace Util { - -WICBitmapLockDIB::WICBitmapLockDIB(WICBitmapDIB* bitmap, const WICRect* lockRect) : - m_Bitmap(bitmap), - m_Rect(lockRect), - m_RefCount(1) -{ -} - -WICBitmapLockDIB::~WICBitmapLockDIB() -{ -} - -IFACEMETHODIMP WICBitmapLockDIB::QueryInterface(REFIID riid, void** ppvObject) -{ - return E_NOTIMPL; -} - -IFACEMETHODIMP_(ULONG) WICBitmapLockDIB::AddRef() -{ - ++m_RefCount; - return m_RefCount; -} - -IFACEMETHODIMP_(ULONG) WICBitmapLockDIB::Release() -{ - --m_RefCount; - if (m_RefCount == 0) - { - delete this; - return 0; - } - - return m_RefCount; -} - -IFACEMETHODIMP WICBitmapLockDIB::GetSize(UINT* puiWidth, UINT* puiHeight) -{ - return m_Bitmap->GetSize(puiWidth, puiHeight); -} - -IFACEMETHODIMP WICBitmapLockDIB::GetStride(UINT* pcbStride) -{ - UINT width = 0; - m_Bitmap->GetSize(&width, nullptr); - - if (pcbStride) *pcbStride = (width * 32 + 31) / 32 * 4; - - return S_OK; -} - -IFACEMETHODIMP WICBitmapLockDIB::GetDataPointer(UINT* pcbBufferSize, BYTE** ppbData) -{ - UINT stride = 0; - GetStride(&stride); - - if (pcbBufferSize) *pcbBufferSize = stride * m_Rect->Height; - if (ppbData) *ppbData = (BYTE*)&m_Bitmap->m_DIBSectionBufferPixels[m_Rect->Y * m_Rect->Width + m_Rect->X]; - - return S_OK; -} - -IFACEMETHODIMP WICBitmapLockDIB::GetPixelFormat(WICPixelFormatGUID* pPixelFormat) -{ - return m_Bitmap->GetPixelFormat(pPixelFormat); -} - -} // namespace Util -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "WICBitmapLockDIB.h" + +namespace Gfx { +namespace Util { + +WICBitmapLockDIB::WICBitmapLockDIB(WICBitmapDIB* bitmap, const WICRect* lockRect) : + m_Bitmap(bitmap), + m_Rect(lockRect), + m_RefCount(1) +{ +} + +WICBitmapLockDIB::~WICBitmapLockDIB() +{ +} + +IFACEMETHODIMP WICBitmapLockDIB::QueryInterface(REFIID riid, void** ppvObject) +{ + return E_NOTIMPL; +} + +IFACEMETHODIMP_(ULONG) WICBitmapLockDIB::AddRef() +{ + ++m_RefCount; + return m_RefCount; +} + +IFACEMETHODIMP_(ULONG) WICBitmapLockDIB::Release() +{ + --m_RefCount; + if (m_RefCount == 0) + { + delete this; + return 0; + } + + return m_RefCount; +} + +IFACEMETHODIMP WICBitmapLockDIB::GetSize(UINT* puiWidth, UINT* puiHeight) +{ + return m_Bitmap->GetSize(puiWidth, puiHeight); +} + +IFACEMETHODIMP WICBitmapLockDIB::GetStride(UINT* pcbStride) +{ + UINT width = 0; + m_Bitmap->GetSize(&width, nullptr); + + if (pcbStride) *pcbStride = (width * 32 + 31) / 32 * 4; + + return S_OK; +} + +IFACEMETHODIMP WICBitmapLockDIB::GetDataPointer(UINT* pcbBufferSize, BYTE** ppbData) +{ + UINT stride = 0; + GetStride(&stride); + + if (pcbBufferSize) *pcbBufferSize = stride * m_Rect->Height; + if (ppbData) *ppbData = (BYTE*)&m_Bitmap->m_DIBSectionBufferPixels[m_Rect->Y * m_Rect->Width + m_Rect->X]; + + return S_OK; +} + +IFACEMETHODIMP WICBitmapLockDIB::GetPixelFormat(WICPixelFormatGUID* pPixelFormat) +{ + return m_Bitmap->GetPixelFormat(pPixelFormat); +} + +} // namespace Util +} // namespace Gfx diff --git a/Common/Gfx/Util/WICBitmapLockDIB.h b/Common/Gfx/Util/WICBitmapLockDIB.h index 5a8789c8..a1b70d80 100644 --- a/Common/Gfx/Util/WICBitmapLockDIB.h +++ b/Common/Gfx/Util/WICBitmapLockDIB.h @@ -1,62 +1,62 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_GFX_UTIL_WICBITMAPLOCKDIB_H_ -#define RM_GFX_UTIL_WICBITMAPLOCKDIB_H_ - -#include -#include -#include "WICBitmapDIB.h" - -namespace Gfx { -namespace Util { - -// Implements the IWICBitmapLock interface for use with WICBitmapDIB. It is assumed that this -// class is used only with 32bpp PARGB bitmaps and using a sigle thread. -class WICBitmapLockDIB : public IWICBitmapLock -{ -public: - WICBitmapLockDIB(WICBitmapDIB* bitmap, const WICRect* lockRect); - virtual ~WICBitmapLockDIB(); - - void Resize(UINT w, UINT h); - - // IUnknown - IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject); - IFACEMETHOD_(ULONG, AddRef)(); - IFACEMETHOD_(ULONG, Release)(); - - // IWICBitmapLock - IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight); - IFACEMETHOD(GetStride)(UINT* pcbStride); - IFACEMETHOD(GetDataPointer)(UINT* pcbBufferSize, BYTE** ppbData); - IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat); - -private: - WICBitmapLockDIB(const WICBitmapLockDIB& other) = delete; - WICBitmapLockDIB& operator=(WICBitmapLockDIB other) = delete; - - WICBitmapDIB* m_Bitmap; - const WICRect* m_Rect; - UINT m_RefCount; -}; - -} // namespace Util -} // namespace Gfx - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_UTIL_WICBITMAPLOCKDIB_H_ +#define RM_GFX_UTIL_WICBITMAPLOCKDIB_H_ + +#include +#include +#include "WICBitmapDIB.h" + +namespace Gfx { +namespace Util { + +// Implements the IWICBitmapLock interface for use with WICBitmapDIB. It is assumed that this +// class is used only with 32bpp PARGB bitmaps and using a sigle thread. +class WICBitmapLockDIB : public IWICBitmapLock +{ +public: + WICBitmapLockDIB(WICBitmapDIB* bitmap, const WICRect* lockRect); + virtual ~WICBitmapLockDIB(); + + void Resize(UINT w, UINT h); + + // IUnknown + IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject); + IFACEMETHOD_(ULONG, AddRef)(); + IFACEMETHOD_(ULONG, Release)(); + + // IWICBitmapLock + IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight); + IFACEMETHOD(GetStride)(UINT* pcbStride); + IFACEMETHOD(GetDataPointer)(UINT* pcbBufferSize, BYTE** ppbData); + IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat); + +private: + WICBitmapLockDIB(const WICBitmapLockDIB& other) = delete; + WICBitmapLockDIB& operator=(WICBitmapLockDIB other) = delete; + + WICBitmapDIB* m_Bitmap; + const WICRect* m_Rect; + UINT m_RefCount; +}; + +} // namespace Util +} // namespace Gfx + #endif \ No newline at end of file diff --git a/Common/Gfx/Util/WICBitmapLockGDIP.cpp b/Common/Gfx/Util/WICBitmapLockGDIP.cpp index adfa2e74..010f2d38 100644 --- a/Common/Gfx/Util/WICBitmapLockGDIP.cpp +++ b/Common/Gfx/Util/WICBitmapLockGDIP.cpp @@ -1,82 +1,82 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "WICBitmapLockGDIP.h" - -namespace Gfx { -namespace Util { - -WICBitmapLockGDIP::WICBitmapLockGDIP() : - m_RefCount(1) -{ -} - -IFACEMETHODIMP WICBitmapLockGDIP::QueryInterface(REFIID riid, void** ppvObject) -{ - return E_NOTIMPL; -} - -IFACEMETHODIMP_(ULONG) WICBitmapLockGDIP::AddRef() -{ - ++m_RefCount; - return m_RefCount; -} - -IFACEMETHODIMP_(ULONG) WICBitmapLockGDIP::Release() -{ - --m_RefCount; - if (m_RefCount == 0) - { - delete this; - return 0; - } - - return m_RefCount; -} - -IFACEMETHODIMP WICBitmapLockGDIP::GetSize(UINT* puiWidth, UINT* puiHeight) -{ - *puiWidth = m_BitmapData.Width; - *puiHeight = m_BitmapData.Height; - return S_OK; -} - -IFACEMETHODIMP WICBitmapLockGDIP::GetStride(UINT* pcbStride) -{ - *pcbStride = m_BitmapData.Stride; - return S_OK; -} - -IFACEMETHODIMP WICBitmapLockGDIP::GetDataPointer(UINT* pcbBufferSize, BYTE** ppbData) -{ - assert(m_BitmapData.PixelFormat == PixelFormat32bppPARGB); - *pcbBufferSize = m_BitmapData.Stride * m_BitmapData.Height; - *ppbData = (BYTE*)m_BitmapData.Scan0; - return S_OK; -} - -IFACEMETHODIMP WICBitmapLockGDIP::GetPixelFormat(WICPixelFormatGUID* pPixelFormat) -{ - assert(m_BitmapData.PixelFormat == PixelFormat32bppPARGB); - *pPixelFormat = GUID_WICPixelFormat32bppPBGRA; - return S_OK; -} - -} // namespace Util -} // namespace Gfx +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "WICBitmapLockGDIP.h" + +namespace Gfx { +namespace Util { + +WICBitmapLockGDIP::WICBitmapLockGDIP() : + m_RefCount(1) +{ +} + +IFACEMETHODIMP WICBitmapLockGDIP::QueryInterface(REFIID riid, void** ppvObject) +{ + return E_NOTIMPL; +} + +IFACEMETHODIMP_(ULONG) WICBitmapLockGDIP::AddRef() +{ + ++m_RefCount; + return m_RefCount; +} + +IFACEMETHODIMP_(ULONG) WICBitmapLockGDIP::Release() +{ + --m_RefCount; + if (m_RefCount == 0) + { + delete this; + return 0; + } + + return m_RefCount; +} + +IFACEMETHODIMP WICBitmapLockGDIP::GetSize(UINT* puiWidth, UINT* puiHeight) +{ + *puiWidth = m_BitmapData.Width; + *puiHeight = m_BitmapData.Height; + return S_OK; +} + +IFACEMETHODIMP WICBitmapLockGDIP::GetStride(UINT* pcbStride) +{ + *pcbStride = m_BitmapData.Stride; + return S_OK; +} + +IFACEMETHODIMP WICBitmapLockGDIP::GetDataPointer(UINT* pcbBufferSize, BYTE** ppbData) +{ + assert(m_BitmapData.PixelFormat == PixelFormat32bppPARGB); + *pcbBufferSize = m_BitmapData.Stride * m_BitmapData.Height; + *ppbData = (BYTE*)m_BitmapData.Scan0; + return S_OK; +} + +IFACEMETHODIMP WICBitmapLockGDIP::GetPixelFormat(WICPixelFormatGUID* pPixelFormat) +{ + assert(m_BitmapData.PixelFormat == PixelFormat32bppPARGB); + *pPixelFormat = GUID_WICPixelFormat32bppPBGRA; + return S_OK; +} + +} // namespace Util +} // namespace Gfx diff --git a/Common/Gfx/Util/WICBitmapLockGDIP.h b/Common/Gfx/Util/WICBitmapLockGDIP.h index 07c64733..500b851b 100644 --- a/Common/Gfx/Util/WICBitmapLockGDIP.h +++ b/Common/Gfx/Util/WICBitmapLockGDIP.h @@ -1,61 +1,61 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_GFX_UTIL_WICBITMAPLOCKGDIP_H_ -#define RM_GFX_UTIL_WICBITMAPLOCKGDIP_H_ - -#include -#include // For Gdiplus.h. -#include -#include - -namespace Gfx { -namespace Util { - -// Allows the creation of a shared ID2D1Bitmap using pixel data in a Gdiplus::Bitmap. It is -// assumed that this class is used only with 32bpp PARGB bitmaps and using a sigle thread. -class WICBitmapLockGDIP : public IWICBitmapLock -{ -public: - WICBitmapLockGDIP(); - - Gdiplus::BitmapData* GetBitmapData() { return &m_BitmapData; } - - // IUnknown - IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject); - IFACEMETHOD_(ULONG, AddRef)(); - IFACEMETHOD_(ULONG, Release)(); - - // IWICBitmapLock - IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight); - IFACEMETHOD(GetStride)(UINT* pcbStride); - IFACEMETHOD(GetDataPointer)(UINT* pcbBufferSize, BYTE** ppbData); - IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat); - -private: - WICBitmapLockGDIP(const WICBitmapLockGDIP& other) = delete; - WICBitmapLockGDIP& operator=(WICBitmapLockGDIP other) = delete; - - Gdiplus::BitmapData m_BitmapData; - UINT m_RefCount; -}; - -} // namespace Util -} // namespace Gfx - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_GFX_UTIL_WICBITMAPLOCKGDIP_H_ +#define RM_GFX_UTIL_WICBITMAPLOCKGDIP_H_ + +#include +#include // For Gdiplus.h. +#include +#include + +namespace Gfx { +namespace Util { + +// Allows the creation of a shared ID2D1Bitmap using pixel data in a Gdiplus::Bitmap. It is +// assumed that this class is used only with 32bpp PARGB bitmaps and using a sigle thread. +class WICBitmapLockGDIP : public IWICBitmapLock +{ +public: + WICBitmapLockGDIP(); + + Gdiplus::BitmapData* GetBitmapData() { return &m_BitmapData; } + + // IUnknown + IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject); + IFACEMETHOD_(ULONG, AddRef)(); + IFACEMETHOD_(ULONG, Release)(); + + // IWICBitmapLock + IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight); + IFACEMETHOD(GetStride)(UINT* pcbStride); + IFACEMETHOD(GetDataPointer)(UINT* pcbBufferSize, BYTE** ppbData); + IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat); + +private: + WICBitmapLockGDIP(const WICBitmapLockGDIP& other) = delete; + WICBitmapLockGDIP& operator=(WICBitmapLockGDIP other) = delete; + + Gdiplus::BitmapData m_BitmapData; + UINT m_RefCount; +}; + +} // namespace Util +} // namespace Gfx + #endif \ No newline at end of file diff --git a/Common/MathParser.cpp b/Common/MathParser.cpp index ae827382..422a7e38 100644 --- a/Common/MathParser.cpp +++ b/Common/MathParser.cpp @@ -1,906 +1,906 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -// Heavily based on ccalc 0.5.1 by Walery Studennikov - -#include "StdAfx.h" -#include "MathParser.h" - -#include - -namespace MathParser { - -static const double M_E = 2.7182818284590452354; -static const double M_PI = 3.14159265358979323846; - -typedef double (*SingleArgFunction)(double arg); -typedef const WCHAR* (*MultiArgFunction)(int paramcnt, double* args, double* result); - -enum class Operator : uint8_t -{ - ShiftLeft, - ShiftRight, - Power, - NotEqual, - GreatorOrEqual, - LessOrEqual, - LogicalAND, - LogicalOR, - OpeningBracket, - Addition, - Subtraction, - Multiplication, - Division, - Modulo, - UNK, - BitwiseXOR, - BitwiseNOT, - BitwiseAND, - BitwiseOR, - Equal, - Greater, - Less, - Conditional, - ConditionalSeparator, - ClosingBracket, - Comma, - SingleArgFunction, - MultiArgFunction, - Invalid // Must be last. -}; - -enum class CharType -{ - Unknown = 0x00, - Letter = 0x01, - Digit = 0x02, - Separator = 0x04, - Symbol = 0x08, - MinusSymbol = 0x10, - Final = 0x7F -}; - -enum class Token -{ - Error, - None, - Final, - Operator, - Number, - Name -}; - -struct Operation -{ - Operator type; - BYTE funcIndex; - char prevTop; -}; - -struct Function -{ - WCHAR* name; - SingleArgFunction proc; - BYTE length; -}; - -static double frac(double x); -static double rad(double deg); -static double sgn(double x); -static double neg(double x); -static const WCHAR* round(int paramcnt, double* args, double* result); - -static Function g_Functions[] = -{ - { L"atan", &atan, 4 }, - { L"cos", &cos, 3 }, - { L"sin", &sin, 3 }, - { L"tan", &tan, 3 }, - { L"abs", &fabs, 3 }, - { L"exp", &exp, 3 }, - { L"ln", &log, 2 }, - { L"log", &log10, 3 }, - { L"sqrt", &sqrt, 4 }, - { L"frac", &frac, 4 }, - { L"trunc", &trunc, 5 }, - { L"floor", &floor, 5 }, - { L"ceil", &ceil, 4 }, - { L"round", (SingleArgFunction)&round, 5 }, - { L"asin", &asin, 4 }, - { L"acos", &acos, 4 }, - { L"rad", &rad, 3 }, - { L"sgn", &sgn, 3 }, - { L"neg", &neg, 3 }, - { L"e", nullptr, 1 }, - { L"pi", nullptr, 2 } -}; - -static const int FUNC_MAX_LEN = 5; -static const int FUNC_ROUND = 13; -static const int FUNC_E = 19; -static const int FUNC_PI = 20; -static const BYTE FUNC_INVALID = UCHAR_MAX; - -static const Operation g_BrOp = { Operator::OpeningBracket, 0, 0}; -static const Operation g_NegOp = { Operator::SingleArgFunction, 18, 0 }; - -static const BYTE g_OpPriorities[(uint8_t)Operator::Invalid] = -{ - 5, // Operator::ShiftLeft - 5, // Operator::ShiftRight - 5, // Operator::Power - 2, // Operator::NotEqual - 2, // Operator::GreatorOrEqual - 2, // Operator::LessOrEqual - 2, // Operator::LogicalAND - 2, // Operator::LogicalOR - 0, // Operator::OpeningBracket - 3, // Operator::Addition - 3, // Operator::Subtraction - 4, // Operator::Multiplication - 4, // Operator::Division - 4, // Operator::Modulo - 4, // Operator::UNK - 5, // Operator::BitwiseXOR - 5, // Operator::BitwiseNOT - 5, // Operator::BitwiseAND - 5, // Operator::BitwiseOR - 2, // Operator::Equal - 2, // Operator::Greater - 2, // Operator::Less - 1, // Operator::Conditional - 2, // Operator::ConditionalSeparator - 0, // Operator::ClosingBracket - 2, // Operator::Comma - 6, // Operator::SingleArgFunction - 6 // Operator::MultiArgFunction -}; - -static CharType GetCharType(WCHAR ch); -static BYTE GetFunctionIndex(const WCHAR* str, BYTE len); -static Operator GetOperator(const WCHAR* str); - -struct Parser -{ - Operation opStack[96]; - double numStack[64]; - char opTop; - char valTop; - int obrDist; - - Parser() : opTop(0), valTop(-1), obrDist(2) { opStack[0].type = Operator::OpeningBracket; } -}; - -static const WCHAR* CalcToObr(Parser& parser); -static const WCHAR* Calc(Parser& parser); - -struct Lexer -{ - const WCHAR* string; - const WCHAR* name; - size_t nameLen; - - Token token; - union - { - Operator oper; // token == Token::Operator - double num; // token == Token::Number - } value; - - CharType charType; - - Lexer(const WCHAR* str) : string(str), name(), nameLen(), value(), token(Token::None), charType(GetCharType(*str)) {} -}; - -static Token GetNextToken(Lexer& lexer); - -const WCHAR* eBrackets = L"Unmatched brackets"; -const WCHAR* eSyntax = L"Syntax error"; -const WCHAR* eInternal = L"Internal error"; -const WCHAR* eExtraOp = L"Extra operation"; -const WCHAR* eInfinity = L"Division by 0"; -const WCHAR* eUnknFunc = L"\"%s\" is unknown"; -const WCHAR* eLogicErr = L"Logical expression error"; -const WCHAR* eInvPrmCnt = L"Invalid function parameter count"; - -const WCHAR* Check(const WCHAR* formula) -{ - int brackets = 0; - - // Brackets Matching - while (*formula) - { - if (*formula == L'(') - { - ++brackets; - } - else if (*formula == L')') - { - --brackets; - } - ++formula; - } - - return (brackets != 0) ? eBrackets : nullptr; -} - -const WCHAR* CheckedParse(const WCHAR* formula, double* result) -{ - const WCHAR* error = Check(formula); - if (!error) - { - error = Parse(formula, result); - } - return error; -} - -const WCHAR* Parse( - const WCHAR* formula, double* result, GetValueFunc getValue, void* getValueContext) -{ - static WCHAR errorBuffer[128]; - - if (!*formula) - { - *result = 0.0; - return nullptr; - } - - Parser parser; - Lexer lexer(formula); - - const WCHAR* error; - for (;;) - { - if ((parser.opTop == _countof(parser.opStack) - 2) || - (parser.valTop == _countof(parser.numStack) - 2)) - { - return eInternal; - } - - Token token = GetNextToken(lexer); - --parser.obrDist; - switch (token) - { - case Token::Error: - return eSyntax; - - case Token::Final: - if ((error = CalcToObr(parser)) != nullptr) - { - return error; - } - else if (parser.opTop != -1 || parser.valTop != 0) - { - return eInternal; - } - else - { - // Done! - *result = parser.numStack[0]; - return nullptr; - } - break; - - case Token::Number: - parser.numStack[++parser.valTop] = lexer.value.num; - break; - - case Token::Operator: - switch (lexer.value.oper) - { - case Operator::OpeningBracket: - { - parser.opStack[++parser.opTop] = g_BrOp; - parser.obrDist = 2; - } - break; - - case Operator::ClosingBracket: - { - if ((error = CalcToObr(parser)) != nullptr) return error; - } - break; - - case Operator::Comma: - { - if ((error = CalcToObr(parser)) != nullptr) return error; - - if (parser.opStack[parser.opTop].type == Operator::MultiArgFunction) - { - parser.opStack[++parser.opTop] = g_BrOp; - parser.obrDist = 2; - } - else - { - return eSyntax; - } - } - break; - - default: - { - Operation op; - op.type = lexer.value.oper; - switch (op.type) - { - case Operator::Addition: - if (parser.obrDist >= 1) - { - // Goto next token - continue; - } - break; - - case Operator::Subtraction: - if (parser.obrDist >= 1) - { - parser.opStack[++parser.opTop] = g_NegOp; - - // Goto next token - continue; - } - break; - - case Operator::Conditional: - case Operator::ConditionalSeparator: - parser.obrDist = 2; - break; - } - - while (g_OpPriorities[(int)op.type] <= g_OpPriorities[(int)parser.opStack[parser.opTop].type]) - { - if ((error = Calc(parser)) != nullptr) return error; - } - parser.opStack[++parser.opTop] = op; - } - break; - } - break; - - case Token::Name: - { - Operation op; - if (lexer.nameLen <= FUNC_MAX_LEN && - ((op.funcIndex = GetFunctionIndex(lexer.name, (BYTE)lexer.nameLen)) != FUNC_INVALID)) - { - switch (op.funcIndex) - { - case FUNC_E: - parser.numStack[++parser.valTop] = M_E; - break; - - case FUNC_PI: - parser.numStack[++parser.valTop] = M_PI; - break; - - case FUNC_ROUND: - op.type = Operator::MultiArgFunction; - op.prevTop = parser.valTop; - parser.opStack[++parser.opTop] = op; - break; - - default: // Internal function - op.type = Operator::SingleArgFunction; - parser.opStack[++parser.opTop] = op; - break; - } - } - else - { - double dblval; - if (getValue && getValue(lexer.name, (int)lexer.nameLen, &dblval, getValueContext)) - { - parser.numStack[++parser.valTop] = dblval; - break; - } - - const std::wstring name(lexer.name, lexer.nameLen); - _snwprintf_s(errorBuffer, _TRUNCATE, eUnknFunc, name.c_str()); - return errorBuffer; - } - break; - } - - default: - return eSyntax; - } - } -} - -static const WCHAR* Calc(Parser& parser) -{ - double res; - Operation op = parser.opStack[parser.opTop--]; - - // Multi-argument function - if (op.type == Operator::Conditional) - { - return nullptr; - } - else if (op.type == Operator::MultiArgFunction) - { - int paramcnt = parser.valTop - op.prevTop; - - parser.valTop = op.prevTop; - const WCHAR* error = (*(MultiArgFunction)g_Functions[op.funcIndex].proc)(paramcnt, &parser.numStack[parser.valTop + 1], &res); - if (error) return error; - - parser.numStack[++parser.valTop] = res; - return nullptr; - } - else if (parser.valTop < 0) - { - return eExtraOp; - } - - // Right arg - double right = parser.numStack[parser.valTop--]; - - // One arg operations - if (op.type == Operator::BitwiseNOT) - { - res = (double)(~((long long)right)); - } - else if (op.type == Operator::SingleArgFunction) - { - res = (*(SingleArgFunction)g_Functions[op.funcIndex].proc)(right); - } - else - { - if (parser.valTop < 0) - { - return eExtraOp; - } - - // Left arg - double left = parser.numStack[parser.valTop--]; - switch (op.type) - { - case Operator::ShiftLeft: - res = (double)((long long)left << (long long)right); - break; - - case Operator::ShiftRight: - res = (double)((long long)left >> (long long)right); - break; - - case Operator::Power: - res = pow(left, right); - break; - - case Operator::NotEqual: - res = left != right; - break; - - case Operator::GreatorOrEqual: - res = left >= right; - break; - - case Operator::LessOrEqual: - res = left <= right; - break; - - case Operator::LogicalAND: - res = left && right; - break; - - case Operator::LogicalOR: - res = left || right; - break; - - case Operator::Addition: - res = left + right; - break; - - case Operator::Subtraction: - res = left - right; - break; - - case Operator::Multiplication: - res = left* right; - break; - - case Operator::Division: - if (right == 0.0) - { - return eInfinity; - } - else - { - res = left / right; - } - break; - - case Operator::Modulo: - res = fmod(left, right); - break; - - case Operator::UNK: - if (left <= 0) - { - res = 0.0; - } - else if (right == 0.0) - { - return eInfinity; - } - else - { - res = ceil(left / right); - } - break; - - case Operator::BitwiseXOR: - res = (double)((long long)left ^ (long long)right); - break; - - case Operator::BitwiseAND: - res = (double)((long long)left & (long long)right); - break; - - case Operator::BitwiseOR: - res = (double)((long long)left | (long long)right); - break; - - case Operator::Equal: - res = left == right; - break; - - case Operator::Greater: - res = left > right; - break; - - case Operator::Less: - res = left < right; - break; - - case Operator::ConditionalSeparator: - { - // Needs three arguments - if (parser.opTop < 0 || parser.opStack[parser.opTop--].type != Operator::Conditional) - { - return eLogicErr; - } - res = parser.numStack[parser.valTop--] ? left : right; - } - break; - - default: - return eInternal; - } - } - - parser.numStack[++parser.valTop] = res; - return nullptr; -} - -static const WCHAR* CalcToObr(Parser& parser) -{ - while (parser.opStack[parser.opTop].type != Operator::OpeningBracket) - { - const WCHAR* error = Calc(parser); - if (error) return error; - } - --parser.opTop; - return nullptr; -} - -Token GetNextToken(Lexer& lexer) -{ - while (lexer.charType == CharType::Separator) - { - lexer.charType = GetCharType(*++lexer.string); - } - - if (lexer.charType == CharType::MinusSymbol) - { - // If the - sign follows a symbol, it is treated as a (negative) number. - lexer.charType = CharType::Symbol; - if (lexer.token == Token::Operator && - lexer.value.oper != Operator::OpeningBracket && // Special case for e.g. (-PI/2), (-(5)-2). - lexer.value.oper != Operator::ClosingBracket) // Special case for e.g. (5)-2. - { - lexer.charType = CharType::Digit; - } - } - - switch (lexer.charType) - { - case CharType::Final: - { - lexer.token = Token::Final; - } - break; - - case CharType::Letter: - { - lexer.token = Token::Name; - lexer.name = lexer.string; - do - { - lexer.charType = GetCharType(*++lexer.string); - } - while (lexer.charType <= CharType::Digit); - lexer.nameLen = lexer.string - lexer.name; - } - break; - - case CharType::Digit: - { - WCHAR* newString; - if (lexer.string[0] == L'0') - { - bool valid = true; - int num = 0; - switch (lexer.string[1]) - { - case L'x': // Hexadecimal - num = wcstol(lexer.string, &newString, 16); - break; - - case L'o': // Octal - num = wcstol(lexer.string + 2, &newString, 8); - break; - - case L'b': // Binary - num = wcstol(lexer.string + 2, &newString, 2); - break; - - default: - valid = false; - break; - } - - if (valid) - { - if (lexer.string != newString) - { - lexer.token = Token::Number; - lexer.value.num = num; - lexer.string = newString; - lexer.charType = GetCharType(*lexer.string); - } - break; - } - } - - // Decimal - double num = wcstod(lexer.string, &newString); - if (lexer.string != newString) - { - lexer.token = Token::Number; - lexer.value.num = num; - lexer.string = newString; - lexer.charType = GetCharType(*lexer.string); - } - } - break; - - case CharType::Symbol: - { - Operator oper = GetOperator(lexer.string); - if (oper != Operator::Invalid) - { - lexer.token = Token::Operator; - lexer.value.oper = oper; - lexer.string += ((int)oper <= (int)Operator::LogicalOR) ? 2 : 1; - lexer.charType = GetCharType(*lexer.string); - } - } - break; - - default: - lexer.token = Token::Error; - break; - } - - return lexer.token; -} - -CharType GetCharType(WCHAR ch) -{ - switch (ch) - { - case L'\0': - return CharType::Final; - - case L' ': - case L'\t': - case L'\n': - return CharType::Separator; - - case L'_': - return CharType::Letter; - - case L'-': - return CharType::MinusSymbol; - - case L'+': - case L'/': - case L'*': - case L'~': - case L'(': - case L')': - case L'<': - case L'>': - case L'%': - case L'$': - case L',': - case L'?': - case L':': - case L'=': - case L'&': - case L'|': - return CharType::Symbol; - } - - if (iswalpha(ch)) return CharType::Letter; - if (iswdigit(ch)) return CharType::Digit; - - return CharType::Unknown; -} - -bool IsDelimiter(WCHAR ch) -{ - CharType type = GetCharType(ch); - return type == CharType::Symbol || type == CharType::Separator; -} - -BYTE GetFunctionIndex(const WCHAR* str, BYTE len) -{ - const int funcCount = sizeof(g_Functions) / sizeof(Function); - for (int i = 0; i < funcCount; ++i) - { - if (g_Functions[i].length == len && - _wcsnicmp(str, g_Functions[i].name, len) == 0) - { - return i; - } - } - - return FUNC_INVALID; -} - -Operator GetOperator(const WCHAR* str) -{ - switch (str[0]) - { - case L'(': - return Operator::OpeningBracket; - - case L'+': - return Operator::Addition; - - case L'-': - return Operator::Subtraction; - - case L'*': - return (str[1] == L'*') ? Operator::Power : Operator::Multiplication; - - case L'/': - return Operator::Division; - - case L'%': - return Operator::Modulo; - - case L'$': - return Operator::UNK; - - case L'^': - return Operator::BitwiseXOR; - - case L'~': - return Operator::BitwiseNOT; - - case L'&': - return (str[1] == L'&') ? Operator::LogicalAND : Operator::BitwiseAND; - - case L'|': - return (str[1] == L'|') ? Operator::LogicalOR : Operator::BitwiseOR; - - case L'=': - return Operator::Equal; - - case L'>': - return (str[1] == L'>') ? Operator::ShiftRight : (str[1] == L'=') ? Operator::GreatorOrEqual : Operator::Greater; - - case L'<': - return (str[1] == L'>') ? Operator::NotEqual : (str[1] == L'<') ? Operator::ShiftLeft : (str[1] == L'=') ? Operator::LessOrEqual : Operator::Less; - - case L'?': - return Operator::Conditional; - - case L':': - return Operator::ConditionalSeparator; - - case L')': - return Operator::ClosingBracket; - - case L',': - return Operator::Comma; - } - - return Operator::Invalid; -} - -// ----------------------------------------------------------------------------------------------- -// Misc -// ----------------------------------------------------------------------------------------------- - -static double frac(double x) -{ - double y; - return modf(x, &y); -} - -static double rad(double deg) -{ - return (deg / 180.0) * M_PI; -} - -static double sgn(double x) -{ - return (x > 0) ? 1 : (x < 0) ? -1 : 0; -} - -static double neg(double x) -{ - return -x; -} - -// "Advanced" round function; second argument - sharpness -static const WCHAR* round(int paramcnt, double* args, double* result) -{ - int sharpness; - if (paramcnt == 1) - { - sharpness = 0; - } - else if (paramcnt == 2) - { - sharpness = (int)args[1]; - } - else - { - return eInvPrmCnt; - } - - double x = args[0]; - double coef; - if (sharpness < 0) - { - coef = 0.1; - sharpness = -sharpness; - } - else - { - coef = 10; - } - - for (int i = 0; i < sharpness; i++) x *= coef; - - x = (x + ((x >= 0) ? 0.5 : -0.5)); - x = (x >= 0.0) ? floor(x) : ceil(x); - - for (int i = 0; i < sharpness; i++) x /= coef; - - *result = x; - return nullptr; -} - -} // namespace MathParser +/* + Copyright (C) 2011 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +// Heavily based on ccalc 0.5.1 by Walery Studennikov + +#include "StdAfx.h" +#include "MathParser.h" + +#include + +namespace MathParser { + +static const double M_E = 2.7182818284590452354; +static const double M_PI = 3.14159265358979323846; + +typedef double (*SingleArgFunction)(double arg); +typedef const WCHAR* (*MultiArgFunction)(int paramcnt, double* args, double* result); + +enum class Operator : uint8_t +{ + ShiftLeft, + ShiftRight, + Power, + NotEqual, + GreatorOrEqual, + LessOrEqual, + LogicalAND, + LogicalOR, + OpeningBracket, + Addition, + Subtraction, + Multiplication, + Division, + Modulo, + UNK, + BitwiseXOR, + BitwiseNOT, + BitwiseAND, + BitwiseOR, + Equal, + Greater, + Less, + Conditional, + ConditionalSeparator, + ClosingBracket, + Comma, + SingleArgFunction, + MultiArgFunction, + Invalid // Must be last. +}; + +enum class CharType +{ + Unknown = 0x00, + Letter = 0x01, + Digit = 0x02, + Separator = 0x04, + Symbol = 0x08, + MinusSymbol = 0x10, + Final = 0x7F +}; + +enum class Token +{ + Error, + None, + Final, + Operator, + Number, + Name +}; + +struct Operation +{ + Operator type; + BYTE funcIndex; + char prevTop; +}; + +struct Function +{ + WCHAR* name; + SingleArgFunction proc; + BYTE length; +}; + +static double frac(double x); +static double rad(double deg); +static double sgn(double x); +static double neg(double x); +static const WCHAR* round(int paramcnt, double* args, double* result); + +static Function g_Functions[] = +{ + { L"atan", &atan, 4 }, + { L"cos", &cos, 3 }, + { L"sin", &sin, 3 }, + { L"tan", &tan, 3 }, + { L"abs", &fabs, 3 }, + { L"exp", &exp, 3 }, + { L"ln", &log, 2 }, + { L"log", &log10, 3 }, + { L"sqrt", &sqrt, 4 }, + { L"frac", &frac, 4 }, + { L"trunc", &trunc, 5 }, + { L"floor", &floor, 5 }, + { L"ceil", &ceil, 4 }, + { L"round", (SingleArgFunction)&round, 5 }, + { L"asin", &asin, 4 }, + { L"acos", &acos, 4 }, + { L"rad", &rad, 3 }, + { L"sgn", &sgn, 3 }, + { L"neg", &neg, 3 }, + { L"e", nullptr, 1 }, + { L"pi", nullptr, 2 } +}; + +static const int FUNC_MAX_LEN = 5; +static const int FUNC_ROUND = 13; +static const int FUNC_E = 19; +static const int FUNC_PI = 20; +static const BYTE FUNC_INVALID = UCHAR_MAX; + +static const Operation g_BrOp = { Operator::OpeningBracket, 0, 0}; +static const Operation g_NegOp = { Operator::SingleArgFunction, 18, 0 }; + +static const BYTE g_OpPriorities[(uint8_t)Operator::Invalid] = +{ + 5, // Operator::ShiftLeft + 5, // Operator::ShiftRight + 5, // Operator::Power + 2, // Operator::NotEqual + 2, // Operator::GreatorOrEqual + 2, // Operator::LessOrEqual + 2, // Operator::LogicalAND + 2, // Operator::LogicalOR + 0, // Operator::OpeningBracket + 3, // Operator::Addition + 3, // Operator::Subtraction + 4, // Operator::Multiplication + 4, // Operator::Division + 4, // Operator::Modulo + 4, // Operator::UNK + 5, // Operator::BitwiseXOR + 5, // Operator::BitwiseNOT + 5, // Operator::BitwiseAND + 5, // Operator::BitwiseOR + 2, // Operator::Equal + 2, // Operator::Greater + 2, // Operator::Less + 1, // Operator::Conditional + 2, // Operator::ConditionalSeparator + 0, // Operator::ClosingBracket + 2, // Operator::Comma + 6, // Operator::SingleArgFunction + 6 // Operator::MultiArgFunction +}; + +static CharType GetCharType(WCHAR ch); +static BYTE GetFunctionIndex(const WCHAR* str, BYTE len); +static Operator GetOperator(const WCHAR* str); + +struct Parser +{ + Operation opStack[96]; + double numStack[64]; + char opTop; + char valTop; + int obrDist; + + Parser() : opTop(0), valTop(-1), obrDist(2) { opStack[0].type = Operator::OpeningBracket; } +}; + +static const WCHAR* CalcToObr(Parser& parser); +static const WCHAR* Calc(Parser& parser); + +struct Lexer +{ + const WCHAR* string; + const WCHAR* name; + size_t nameLen; + + Token token; + union + { + Operator oper; // token == Token::Operator + double num; // token == Token::Number + } value; + + CharType charType; + + Lexer(const WCHAR* str) : string(str), name(), nameLen(), value(), token(Token::None), charType(GetCharType(*str)) {} +}; + +static Token GetNextToken(Lexer& lexer); + +const WCHAR* eBrackets = L"Unmatched brackets"; +const WCHAR* eSyntax = L"Syntax error"; +const WCHAR* eInternal = L"Internal error"; +const WCHAR* eExtraOp = L"Extra operation"; +const WCHAR* eInfinity = L"Division by 0"; +const WCHAR* eUnknFunc = L"\"%s\" is unknown"; +const WCHAR* eLogicErr = L"Logical expression error"; +const WCHAR* eInvPrmCnt = L"Invalid function parameter count"; + +const WCHAR* Check(const WCHAR* formula) +{ + int brackets = 0; + + // Brackets Matching + while (*formula) + { + if (*formula == L'(') + { + ++brackets; + } + else if (*formula == L')') + { + --brackets; + } + ++formula; + } + + return (brackets != 0) ? eBrackets : nullptr; +} + +const WCHAR* CheckedParse(const WCHAR* formula, double* result) +{ + const WCHAR* error = Check(formula); + if (!error) + { + error = Parse(formula, result); + } + return error; +} + +const WCHAR* Parse( + const WCHAR* formula, double* result, GetValueFunc getValue, void* getValueContext) +{ + static WCHAR errorBuffer[128]; + + if (!*formula) + { + *result = 0.0; + return nullptr; + } + + Parser parser; + Lexer lexer(formula); + + const WCHAR* error; + for (;;) + { + if ((parser.opTop == _countof(parser.opStack) - 2) || + (parser.valTop == _countof(parser.numStack) - 2)) + { + return eInternal; + } + + Token token = GetNextToken(lexer); + --parser.obrDist; + switch (token) + { + case Token::Error: + return eSyntax; + + case Token::Final: + if ((error = CalcToObr(parser)) != nullptr) + { + return error; + } + else if (parser.opTop != -1 || parser.valTop != 0) + { + return eInternal; + } + else + { + // Done! + *result = parser.numStack[0]; + return nullptr; + } + break; + + case Token::Number: + parser.numStack[++parser.valTop] = lexer.value.num; + break; + + case Token::Operator: + switch (lexer.value.oper) + { + case Operator::OpeningBracket: + { + parser.opStack[++parser.opTop] = g_BrOp; + parser.obrDist = 2; + } + break; + + case Operator::ClosingBracket: + { + if ((error = CalcToObr(parser)) != nullptr) return error; + } + break; + + case Operator::Comma: + { + if ((error = CalcToObr(parser)) != nullptr) return error; + + if (parser.opStack[parser.opTop].type == Operator::MultiArgFunction) + { + parser.opStack[++parser.opTop] = g_BrOp; + parser.obrDist = 2; + } + else + { + return eSyntax; + } + } + break; + + default: + { + Operation op; + op.type = lexer.value.oper; + switch (op.type) + { + case Operator::Addition: + if (parser.obrDist >= 1) + { + // Goto next token + continue; + } + break; + + case Operator::Subtraction: + if (parser.obrDist >= 1) + { + parser.opStack[++parser.opTop] = g_NegOp; + + // Goto next token + continue; + } + break; + + case Operator::Conditional: + case Operator::ConditionalSeparator: + parser.obrDist = 2; + break; + } + + while (g_OpPriorities[(int)op.type] <= g_OpPriorities[(int)parser.opStack[parser.opTop].type]) + { + if ((error = Calc(parser)) != nullptr) return error; + } + parser.opStack[++parser.opTop] = op; + } + break; + } + break; + + case Token::Name: + { + Operation op; + if (lexer.nameLen <= FUNC_MAX_LEN && + ((op.funcIndex = GetFunctionIndex(lexer.name, (BYTE)lexer.nameLen)) != FUNC_INVALID)) + { + switch (op.funcIndex) + { + case FUNC_E: + parser.numStack[++parser.valTop] = M_E; + break; + + case FUNC_PI: + parser.numStack[++parser.valTop] = M_PI; + break; + + case FUNC_ROUND: + op.type = Operator::MultiArgFunction; + op.prevTop = parser.valTop; + parser.opStack[++parser.opTop] = op; + break; + + default: // Internal function + op.type = Operator::SingleArgFunction; + parser.opStack[++parser.opTop] = op; + break; + } + } + else + { + double dblval; + if (getValue && getValue(lexer.name, (int)lexer.nameLen, &dblval, getValueContext)) + { + parser.numStack[++parser.valTop] = dblval; + break; + } + + const std::wstring name(lexer.name, lexer.nameLen); + _snwprintf_s(errorBuffer, _TRUNCATE, eUnknFunc, name.c_str()); + return errorBuffer; + } + break; + } + + default: + return eSyntax; + } + } +} + +static const WCHAR* Calc(Parser& parser) +{ + double res; + Operation op = parser.opStack[parser.opTop--]; + + // Multi-argument function + if (op.type == Operator::Conditional) + { + return nullptr; + } + else if (op.type == Operator::MultiArgFunction) + { + int paramcnt = parser.valTop - op.prevTop; + + parser.valTop = op.prevTop; + const WCHAR* error = (*(MultiArgFunction)g_Functions[op.funcIndex].proc)(paramcnt, &parser.numStack[parser.valTop + 1], &res); + if (error) return error; + + parser.numStack[++parser.valTop] = res; + return nullptr; + } + else if (parser.valTop < 0) + { + return eExtraOp; + } + + // Right arg + double right = parser.numStack[parser.valTop--]; + + // One arg operations + if (op.type == Operator::BitwiseNOT) + { + res = (double)(~((long long)right)); + } + else if (op.type == Operator::SingleArgFunction) + { + res = (*(SingleArgFunction)g_Functions[op.funcIndex].proc)(right); + } + else + { + if (parser.valTop < 0) + { + return eExtraOp; + } + + // Left arg + double left = parser.numStack[parser.valTop--]; + switch (op.type) + { + case Operator::ShiftLeft: + res = (double)((long long)left << (long long)right); + break; + + case Operator::ShiftRight: + res = (double)((long long)left >> (long long)right); + break; + + case Operator::Power: + res = pow(left, right); + break; + + case Operator::NotEqual: + res = left != right; + break; + + case Operator::GreatorOrEqual: + res = left >= right; + break; + + case Operator::LessOrEqual: + res = left <= right; + break; + + case Operator::LogicalAND: + res = left && right; + break; + + case Operator::LogicalOR: + res = left || right; + break; + + case Operator::Addition: + res = left + right; + break; + + case Operator::Subtraction: + res = left - right; + break; + + case Operator::Multiplication: + res = left* right; + break; + + case Operator::Division: + if (right == 0.0) + { + return eInfinity; + } + else + { + res = left / right; + } + break; + + case Operator::Modulo: + res = fmod(left, right); + break; + + case Operator::UNK: + if (left <= 0) + { + res = 0.0; + } + else if (right == 0.0) + { + return eInfinity; + } + else + { + res = ceil(left / right); + } + break; + + case Operator::BitwiseXOR: + res = (double)((long long)left ^ (long long)right); + break; + + case Operator::BitwiseAND: + res = (double)((long long)left & (long long)right); + break; + + case Operator::BitwiseOR: + res = (double)((long long)left | (long long)right); + break; + + case Operator::Equal: + res = left == right; + break; + + case Operator::Greater: + res = left > right; + break; + + case Operator::Less: + res = left < right; + break; + + case Operator::ConditionalSeparator: + { + // Needs three arguments + if (parser.opTop < 0 || parser.opStack[parser.opTop--].type != Operator::Conditional) + { + return eLogicErr; + } + res = parser.numStack[parser.valTop--] ? left : right; + } + break; + + default: + return eInternal; + } + } + + parser.numStack[++parser.valTop] = res; + return nullptr; +} + +static const WCHAR* CalcToObr(Parser& parser) +{ + while (parser.opStack[parser.opTop].type != Operator::OpeningBracket) + { + const WCHAR* error = Calc(parser); + if (error) return error; + } + --parser.opTop; + return nullptr; +} + +Token GetNextToken(Lexer& lexer) +{ + while (lexer.charType == CharType::Separator) + { + lexer.charType = GetCharType(*++lexer.string); + } + + if (lexer.charType == CharType::MinusSymbol) + { + // If the - sign follows a symbol, it is treated as a (negative) number. + lexer.charType = CharType::Symbol; + if (lexer.token == Token::Operator && + lexer.value.oper != Operator::OpeningBracket && // Special case for e.g. (-PI/2), (-(5)-2). + lexer.value.oper != Operator::ClosingBracket) // Special case for e.g. (5)-2. + { + lexer.charType = CharType::Digit; + } + } + + switch (lexer.charType) + { + case CharType::Final: + { + lexer.token = Token::Final; + } + break; + + case CharType::Letter: + { + lexer.token = Token::Name; + lexer.name = lexer.string; + do + { + lexer.charType = GetCharType(*++lexer.string); + } + while (lexer.charType <= CharType::Digit); + lexer.nameLen = lexer.string - lexer.name; + } + break; + + case CharType::Digit: + { + WCHAR* newString; + if (lexer.string[0] == L'0') + { + bool valid = true; + int num = 0; + switch (lexer.string[1]) + { + case L'x': // Hexadecimal + num = wcstol(lexer.string, &newString, 16); + break; + + case L'o': // Octal + num = wcstol(lexer.string + 2, &newString, 8); + break; + + case L'b': // Binary + num = wcstol(lexer.string + 2, &newString, 2); + break; + + default: + valid = false; + break; + } + + if (valid) + { + if (lexer.string != newString) + { + lexer.token = Token::Number; + lexer.value.num = num; + lexer.string = newString; + lexer.charType = GetCharType(*lexer.string); + } + break; + } + } + + // Decimal + double num = wcstod(lexer.string, &newString); + if (lexer.string != newString) + { + lexer.token = Token::Number; + lexer.value.num = num; + lexer.string = newString; + lexer.charType = GetCharType(*lexer.string); + } + } + break; + + case CharType::Symbol: + { + Operator oper = GetOperator(lexer.string); + if (oper != Operator::Invalid) + { + lexer.token = Token::Operator; + lexer.value.oper = oper; + lexer.string += ((int)oper <= (int)Operator::LogicalOR) ? 2 : 1; + lexer.charType = GetCharType(*lexer.string); + } + } + break; + + default: + lexer.token = Token::Error; + break; + } + + return lexer.token; +} + +CharType GetCharType(WCHAR ch) +{ + switch (ch) + { + case L'\0': + return CharType::Final; + + case L' ': + case L'\t': + case L'\n': + return CharType::Separator; + + case L'_': + return CharType::Letter; + + case L'-': + return CharType::MinusSymbol; + + case L'+': + case L'/': + case L'*': + case L'~': + case L'(': + case L')': + case L'<': + case L'>': + case L'%': + case L'$': + case L',': + case L'?': + case L':': + case L'=': + case L'&': + case L'|': + return CharType::Symbol; + } + + if (iswalpha(ch)) return CharType::Letter; + if (iswdigit(ch)) return CharType::Digit; + + return CharType::Unknown; +} + +bool IsDelimiter(WCHAR ch) +{ + CharType type = GetCharType(ch); + return type == CharType::Symbol || type == CharType::Separator; +} + +BYTE GetFunctionIndex(const WCHAR* str, BYTE len) +{ + const int funcCount = sizeof(g_Functions) / sizeof(Function); + for (int i = 0; i < funcCount; ++i) + { + if (g_Functions[i].length == len && + _wcsnicmp(str, g_Functions[i].name, len) == 0) + { + return i; + } + } + + return FUNC_INVALID; +} + +Operator GetOperator(const WCHAR* str) +{ + switch (str[0]) + { + case L'(': + return Operator::OpeningBracket; + + case L'+': + return Operator::Addition; + + case L'-': + return Operator::Subtraction; + + case L'*': + return (str[1] == L'*') ? Operator::Power : Operator::Multiplication; + + case L'/': + return Operator::Division; + + case L'%': + return Operator::Modulo; + + case L'$': + return Operator::UNK; + + case L'^': + return Operator::BitwiseXOR; + + case L'~': + return Operator::BitwiseNOT; + + case L'&': + return (str[1] == L'&') ? Operator::LogicalAND : Operator::BitwiseAND; + + case L'|': + return (str[1] == L'|') ? Operator::LogicalOR : Operator::BitwiseOR; + + case L'=': + return Operator::Equal; + + case L'>': + return (str[1] == L'>') ? Operator::ShiftRight : (str[1] == L'=') ? Operator::GreatorOrEqual : Operator::Greater; + + case L'<': + return (str[1] == L'>') ? Operator::NotEqual : (str[1] == L'<') ? Operator::ShiftLeft : (str[1] == L'=') ? Operator::LessOrEqual : Operator::Less; + + case L'?': + return Operator::Conditional; + + case L':': + return Operator::ConditionalSeparator; + + case L')': + return Operator::ClosingBracket; + + case L',': + return Operator::Comma; + } + + return Operator::Invalid; +} + +// ----------------------------------------------------------------------------------------------- +// Misc +// ----------------------------------------------------------------------------------------------- + +static double frac(double x) +{ + double y; + return modf(x, &y); +} + +static double rad(double deg) +{ + return (deg / 180.0) * M_PI; +} + +static double sgn(double x) +{ + return (x > 0) ? 1 : (x < 0) ? -1 : 0; +} + +static double neg(double x) +{ + return -x; +} + +// "Advanced" round function; second argument - sharpness +static const WCHAR* round(int paramcnt, double* args, double* result) +{ + int sharpness; + if (paramcnt == 1) + { + sharpness = 0; + } + else if (paramcnt == 2) + { + sharpness = (int)args[1]; + } + else + { + return eInvPrmCnt; + } + + double x = args[0]; + double coef; + if (sharpness < 0) + { + coef = 0.1; + sharpness = -sharpness; + } + else + { + coef = 10; + } + + for (int i = 0; i < sharpness; i++) x *= coef; + + x = (x + ((x >= 0) ? 0.5 : -0.5)); + x = (x >= 0.0) ? floor(x) : ceil(x); + + for (int i = 0; i < sharpness; i++) x /= coef; + + *result = x; + return nullptr; +} + +} // namespace MathParser diff --git a/Common/MathParser.h b/Common/MathParser.h index 8ebf4dd3..0939cb80 100644 --- a/Common/MathParser.h +++ b/Common/MathParser.h @@ -1,39 +1,39 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -// Heavily based on ccalc 0.5.1 by Walery Studennikov - -#ifndef RM_COMMON_MATHPARSER_H_ -#define RM_COMMON_MATHPARSER_H_ - -#include - -namespace MathParser -{ - typedef bool (*GetValueFunc)(const WCHAR* str, int len, double* value, void* context); - - const WCHAR* Check(const WCHAR* formula); - const WCHAR* CheckedParse(const WCHAR* formula, double* result); - const WCHAR* Parse( - const WCHAR* formula, double* result, - GetValueFunc getValue = nullptr, void* getValueContext = nullptr); - - bool IsDelimiter(WCHAR ch); -}; - +/* + Copyright (C) 2011 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +// Heavily based on ccalc 0.5.1 by Walery Studennikov + +#ifndef RM_COMMON_MATHPARSER_H_ +#define RM_COMMON_MATHPARSER_H_ + +#include + +namespace MathParser +{ + typedef bool (*GetValueFunc)(const WCHAR* str, int len, double* value, void* context); + + const WCHAR* Check(const WCHAR* formula); + const WCHAR* CheckedParse(const WCHAR* formula, double* result); + const WCHAR* Parse( + const WCHAR* formula, double* result, + GetValueFunc getValue = nullptr, void* getValueContext = nullptr); + + bool IsDelimiter(WCHAR ch); +}; + #endif \ No newline at end of file diff --git a/Common/MathParser_Test.cpp b/Common/MathParser_Test.cpp index 0ccfea56..82e1e08c 100644 --- a/Common/MathParser_Test.cpp +++ b/Common/MathParser_Test.cpp @@ -1,124 +1,124 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "MathParser.h" -#include "UnitTest.h" - -namespace MathParser { - -TEST_CLASS(Common_MathParser_Test) -{ -public: - void ParseAssert(double expected, const WCHAR* formula) - { - double value = 0.0; - Assert::IsNull(Parse(formula, &value)); - Assert::AreEqual(expected, value); - } - - TEST_METHOD(TestParse) - { - ParseAssert(5.0, L"5"); - ParseAssert(5.0, L" 5 "); - ParseAssert(5.0, L"((((5))))"); - ParseAssert(10.0, L"(5 + 5)"); - ParseAssert(-10.0, L"(-5 - 5)"); - ParseAssert(10.0, L"-(-5-5)"); - ParseAssert(10.0, L"-(-5+-5)"); - ParseAssert(1.0, L"1 && 1"); - ParseAssert(0.0, L"1 && 0"); - ParseAssert(1.0, L"1 || 1"); - ParseAssert(1.0, L"1 || -1"); - ParseAssert(0.0, L"1 < 2 && 2 > 1"); - ParseAssert(1.0, L"(1 < 2) && (2 > 1)"); - ParseAssert(sin(50.0), L"sin(50)"); - ParseAssert(-sin(100.0), L"-sin((25 + 25) * 2)"); - ParseAssert(1.0, L"01"); - ParseAssert(11.0, L"011"); - ParseAssert(3.0, L"0b11"); - ParseAssert(10.0, L"0xA"); - ParseAssert(10.0, L"0o12"); - ParseAssert(2.0, L"1 ? 2 : 3"); - ParseAssert(3.0, L"0 ? 2 : 3"); - ParseAssert(5.0, L"1 ? (2 + 3) : 3"); - ParseAssert(2.0, L"1 ? 2 : 3"); - ParseAssert(4.0, L"1 ? 2 : 0 ? 4 : 5"); - ParseAssert(4.0, L"1 ? 2 : 1 ? 4 : 5"); - ParseAssert(2.0, L"1 ? 2 : (1 ? 4 : 5)"); - ParseAssert(5.0, L"0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:5)))))))))))))))))))))))))))))"); - ParseAssert(1.0, L"trunc(1.5)"); - ParseAssert(-1.0, L"trunc(-1.5)"); - ParseAssert(2.0, L"round(1.555)"); - ParseAssert(1.56, L"round(1.555, 2)"); - - double value; - - Assert::IsNotNull(Parse(L"1 ? 0 ? 4 : 5 : 3", &value)); - Assert::IsNotNull(Parse(L"++1", &value)); - Assert::IsNotNull(Parse(L"((1)", &value)); - Assert::IsNotNull(Parse(L"1 / 0", &value)); - Assert::IsNotNull(Parse(L"1 &&", &value)); - Assert::IsNotNull(Parse(L"a", &value)); - - Assert::IsNull(Parse(L"e", &value)); - Assert::AreEqual(2, (int)value); - - Assert::IsNull(Parse(L"pi", &value)); - Assert::AreEqual(3, (int)value); - - Assert::IsNull(Parse(L"pi", &value, GetValueHelper)); - Assert::AreEqual(3, (int)value); - - Assert::IsNull(Parse(L"a + 5", &value, GetValueHelper)); - Assert::AreEqual(15.0, value); - - Assert::IsNull(Parse(L"bbb", &value, GetValueHelper)); - Assert::AreEqual(20.0, value); - - Assert::IsNull(Parse(L"(ccc_)", &value, GetValueHelper, (void*)1)); - Assert::AreEqual(30.0, value); - } - - static bool GetValueHelper(const WCHAR* str, int len, double* value, void* context) - { - if (wcsncmp(str, L"a", len) == 0) - { - *value = 10.0; - return true; - } - else if (wcsncmp(str, L"bbb", len) == 0) - { - *value = 20.0; - return true; - } - else if (wcsncmp(str, L"ccc_", len) == 0 && context == (void*)1) - { - *value = 30.0; - return true; - } - else if (wcsncmp(str, L"pi", len) == 0) - { - *value = 40.0; - return true; - } - - return false; - } -}; - -} // namespace StringUtil +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "MathParser.h" +#include "UnitTest.h" + +namespace MathParser { + +TEST_CLASS(Common_MathParser_Test) +{ +public: + void ParseAssert(double expected, const WCHAR* formula) + { + double value = 0.0; + Assert::IsNull(Parse(formula, &value)); + Assert::AreEqual(expected, value); + } + + TEST_METHOD(TestParse) + { + ParseAssert(5.0, L"5"); + ParseAssert(5.0, L" 5 "); + ParseAssert(5.0, L"((((5))))"); + ParseAssert(10.0, L"(5 + 5)"); + ParseAssert(-10.0, L"(-5 - 5)"); + ParseAssert(10.0, L"-(-5-5)"); + ParseAssert(10.0, L"-(-5+-5)"); + ParseAssert(1.0, L"1 && 1"); + ParseAssert(0.0, L"1 && 0"); + ParseAssert(1.0, L"1 || 1"); + ParseAssert(1.0, L"1 || -1"); + ParseAssert(0.0, L"1 < 2 && 2 > 1"); + ParseAssert(1.0, L"(1 < 2) && (2 > 1)"); + ParseAssert(sin(50.0), L"sin(50)"); + ParseAssert(-sin(100.0), L"-sin((25 + 25) * 2)"); + ParseAssert(1.0, L"01"); + ParseAssert(11.0, L"011"); + ParseAssert(3.0, L"0b11"); + ParseAssert(10.0, L"0xA"); + ParseAssert(10.0, L"0o12"); + ParseAssert(2.0, L"1 ? 2 : 3"); + ParseAssert(3.0, L"0 ? 2 : 3"); + ParseAssert(5.0, L"1 ? (2 + 3) : 3"); + ParseAssert(2.0, L"1 ? 2 : 3"); + ParseAssert(4.0, L"1 ? 2 : 0 ? 4 : 5"); + ParseAssert(4.0, L"1 ? 2 : 1 ? 4 : 5"); + ParseAssert(2.0, L"1 ? 2 : (1 ? 4 : 5)"); + ParseAssert(5.0, L"0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:5)))))))))))))))))))))))))))))"); + ParseAssert(1.0, L"trunc(1.5)"); + ParseAssert(-1.0, L"trunc(-1.5)"); + ParseAssert(2.0, L"round(1.555)"); + ParseAssert(1.56, L"round(1.555, 2)"); + + double value; + + Assert::IsNotNull(Parse(L"1 ? 0 ? 4 : 5 : 3", &value)); + Assert::IsNotNull(Parse(L"++1", &value)); + Assert::IsNotNull(Parse(L"((1)", &value)); + Assert::IsNotNull(Parse(L"1 / 0", &value)); + Assert::IsNotNull(Parse(L"1 &&", &value)); + Assert::IsNotNull(Parse(L"a", &value)); + + Assert::IsNull(Parse(L"e", &value)); + Assert::AreEqual(2, (int)value); + + Assert::IsNull(Parse(L"pi", &value)); + Assert::AreEqual(3, (int)value); + + Assert::IsNull(Parse(L"pi", &value, GetValueHelper)); + Assert::AreEqual(3, (int)value); + + Assert::IsNull(Parse(L"a + 5", &value, GetValueHelper)); + Assert::AreEqual(15.0, value); + + Assert::IsNull(Parse(L"bbb", &value, GetValueHelper)); + Assert::AreEqual(20.0, value); + + Assert::IsNull(Parse(L"(ccc_)", &value, GetValueHelper, (void*)1)); + Assert::AreEqual(30.0, value); + } + + static bool GetValueHelper(const WCHAR* str, int len, double* value, void* context) + { + if (wcsncmp(str, L"a", len) == 0) + { + *value = 10.0; + return true; + } + else if (wcsncmp(str, L"bbb", len) == 0) + { + *value = 20.0; + return true; + } + else if (wcsncmp(str, L"ccc_", len) == 0 && context == (void*)1) + { + *value = 30.0; + return true; + } + else if (wcsncmp(str, L"pi", len) == 0) + { + *value = 40.0; + return true; + } + + return false; + } +}; + +} // namespace StringUtil diff --git a/Common/MenuTemplate.cpp b/Common/MenuTemplate.cpp index a95059e6..e111863a 100644 --- a/Common/MenuTemplate.cpp +++ b/Common/MenuTemplate.cpp @@ -1,64 +1,64 @@ -/* - Copyright (C) 2012 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MenuTemplate.h" - -HMENU MenuTemplate::CreateMenu(const MenuTemplate* items, UINT itemCount, GetStringFunc getString) -{ - UINT itemIndex = 0; - return CreateSubMenu(items, itemIndex, itemCount, getString); -} - -HMENU MenuTemplate::CreateSubMenu(const MenuTemplate* items, UINT& itemIndex, UINT itemCount, GetStringFunc getString) -{ - HMENU menu = CreatePopupMenu(); - - do - { - const MenuTemplate& item = items[itemIndex]; - ++itemIndex; - - UINT itemFlags = MF_STRING; - UINT_PTR itemId = item.id; - const WCHAR* itemText = item.idText ? getString(item.idText) : nullptr; - - if (item.type == MenuItem_ItemGrayed) - { - itemFlags |= MF_GRAYED; - } - else if (item.type == MenuItem_Separator) - { - itemFlags = MF_SEPARATOR; - } - else if (item.type == MenuItem_SubMenuBegin) - { - itemFlags = MF_POPUP; - itemId = (UINT_PTR)CreateSubMenu(items, itemIndex, itemCount, getString); - } - else if (item.type == MenuItem_SubMenuEnd) - { - return menu; - } - - AppendMenu(menu, itemFlags, itemId, itemText); - } - while (itemIndex < itemCount); - - return menu; -} +/* + Copyright (C) 2012 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MenuTemplate.h" + +HMENU MenuTemplate::CreateMenu(const MenuTemplate* items, UINT itemCount, GetStringFunc getString) +{ + UINT itemIndex = 0; + return CreateSubMenu(items, itemIndex, itemCount, getString); +} + +HMENU MenuTemplate::CreateSubMenu(const MenuTemplate* items, UINT& itemIndex, UINT itemCount, GetStringFunc getString) +{ + HMENU menu = CreatePopupMenu(); + + do + { + const MenuTemplate& item = items[itemIndex]; + ++itemIndex; + + UINT itemFlags = MF_STRING; + UINT_PTR itemId = item.id; + const WCHAR* itemText = item.idText ? getString(item.idText) : nullptr; + + if (item.type == MenuItem_ItemGrayed) + { + itemFlags |= MF_GRAYED; + } + else if (item.type == MenuItem_Separator) + { + itemFlags = MF_SEPARATOR; + } + else if (item.type == MenuItem_SubMenuBegin) + { + itemFlags = MF_POPUP; + itemId = (UINT_PTR)CreateSubMenu(items, itemIndex, itemCount, getString); + } + else if (item.type == MenuItem_SubMenuEnd) + { + return menu; + } + + AppendMenu(menu, itemFlags, itemId, itemText); + } + while (itemIndex < itemCount); + + return menu; +} diff --git a/Common/MenuTemplate.h b/Common/MenuTemplate.h index 6dfc116f..f9d1e6ff 100644 --- a/Common/MenuTemplate.h +++ b/Common/MenuTemplate.h @@ -1,52 +1,52 @@ -/* - Copyright (C) 2012 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_COMMON_MENUTEMPLATE_H_ -#define RM_COMMON_MENUTEMPLATE_H_ - -#include - -struct MenuTemplate -{ - BYTE type; - WORD id; - WORD idText; - - typedef WCHAR* (*GetStringFunc)(UINT id); - - static HMENU CreateMenu(const MenuTemplate* items, UINT itemCount, GetStringFunc getString); - -private: - static HMENU CreateSubMenu(const MenuTemplate* items, UINT& itemIndex, UINT itemCount, GetStringFunc getString); -}; - -enum MenuTemplateItem -{ - MenuItem_Item, - MenuItem_ItemGrayed, - MenuItem_Separator, - MenuItem_SubMenuBegin, - MenuItem_SubMenuEnd -}; - -#define MENU_ITEM(...) { MenuItem_Item, __VA_ARGS__ } -#define MENU_ITEM_GRAYED(...) { MenuItem_ItemGrayed, __VA_ARGS__ } -#define MENU_SEPARATOR() { MenuItem_Separator } -#define MENU_SUBMENU(idText, ...) { MenuItem_SubMenuBegin, 0, idText }, __VA_ARGS__, { MenuItem_SubMenuEnd } - -#endif +/* + Copyright (C) 2012 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_COMMON_MENUTEMPLATE_H_ +#define RM_COMMON_MENUTEMPLATE_H_ + +#include + +struct MenuTemplate +{ + BYTE type; + WORD id; + WORD idText; + + typedef WCHAR* (*GetStringFunc)(UINT id); + + static HMENU CreateMenu(const MenuTemplate* items, UINT itemCount, GetStringFunc getString); + +private: + static HMENU CreateSubMenu(const MenuTemplate* items, UINT& itemIndex, UINT itemCount, GetStringFunc getString); +}; + +enum MenuTemplateItem +{ + MenuItem_Item, + MenuItem_ItemGrayed, + MenuItem_Separator, + MenuItem_SubMenuBegin, + MenuItem_SubMenuEnd +}; + +#define MENU_ITEM(...) { MenuItem_Item, __VA_ARGS__ } +#define MENU_ITEM_GRAYED(...) { MenuItem_ItemGrayed, __VA_ARGS__ } +#define MENU_SEPARATOR() { MenuItem_Separator } +#define MENU_SUBMENU(idText, ...) { MenuItem_SubMenuBegin, 0, idText }, __VA_ARGS__, { MenuItem_SubMenuEnd } + +#endif diff --git a/Common/PathUtil.cpp b/Common/PathUtil.cpp index 7662019b..88cf1776 100644 --- a/Common/PathUtil.cpp +++ b/Common/PathUtil.cpp @@ -1,149 +1,149 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "PathUtil.h" - -namespace PathUtil { - -bool IsSeparator(WCHAR ch) -{ - return ch == L'\\' || ch == L'/'; -} - -bool IsDotOrDotDot(const WCHAR* path) -{ - return path[0] == L'.' && (path[1] == L'\0' || (path[1] == L'.' && path[2] == L'\0')); -} - -bool IsUNC(const std::wstring& path) -{ - return path.length() >= 2 && IsSeparator(path[0]) && IsSeparator(path[1]); -} - -bool IsAbsolute(const std::wstring& path) -{ - return (path.find(L":\\") != std::wstring::npos || - path.find(L":/") != std::wstring::npos || - IsUNC(path)); -} - -void AppendBacklashIfMissing(std::wstring& path) -{ - if (!path.empty() && !IsSeparator(path[path.length() - 1])) - { - path += L'\\'; - } -} - -std::wstring GetFolderFromFilePath(const std::wstring& filePath) -{ - std::wstring::size_type pos = filePath.find_last_of(L"\\/"); - if (pos != std::wstring::npos) - { - return filePath.substr(0, pos + 1); - } - return L".\\"; -} - -/* -** Extracts volume path from program path. -** E.g.: -** "C:\path\" to "C:" -** "\\server\share\" to "\\server\share" -** "\\server\C:\path\" to "\\server\C:" -*/ -std::wstring GetVolume(const std::wstring& path) -{ - std::wstring::size_type pos; - if ((pos = path.find_first_of(L':')) != std::wstring::npos) - { - return path.substr(0, pos + 1); - } - else if (IsUNC(path)) - { - if ((pos = path.find_first_of(L"\\/", 2)) != std::wstring::npos) - { - std::wstring::size_type pos2; - if ((pos2 = path.find_first_of(L"\\/", pos + 1)) != std::wstring::npos || - pos != (path.length() - 1)) - { - pos = pos2; - } - } - - return path.substr(0, pos); - } - - return std::wstring(); -} - -void ExpandEnvironmentVariables(std::wstring& path) -{ - std::wstring::size_type pos; - if ((pos = path.find(L'%')) != std::wstring::npos && - path.find(L'%', pos + 2) != std::wstring::npos) - { - DWORD bufSize = 4096; - WCHAR* buffer = new WCHAR[bufSize]; - - // %APPDATA% is a special case. - pos = path.find(L"%APPDATA%", pos); - if (pos != std::wstring::npos) - { - HRESULT hr = SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, buffer); - if (SUCCEEDED(hr)) - { - size_t len = wcslen(buffer); - do - { - path.replace(pos, 9, buffer, len); - } - while ((pos = path.find(L"%APPDATA%", pos + len)) != std::wstring::npos); - } - } - - if ((pos = path.find(L'%')) != std::wstring::npos && - path.find(L'%', pos + 2) != std::wstring::npos) - { - // Expand the environment variables. - do - { - DWORD ret = ExpandEnvironmentStrings(path.c_str(), buffer, bufSize); - if (ret == 0) // Error - { - break; - } - if (ret <= bufSize) // Fits in the buffer - { - path.assign(buffer, ret - 1); - break; - } - - delete [] buffer; - bufSize = ret; - buffer = new WCHAR[bufSize]; - } - while (true); - } - - delete [] buffer; - } -} - -} // namespace PathUtil +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "PathUtil.h" + +namespace PathUtil { + +bool IsSeparator(WCHAR ch) +{ + return ch == L'\\' || ch == L'/'; +} + +bool IsDotOrDotDot(const WCHAR* path) +{ + return path[0] == L'.' && (path[1] == L'\0' || (path[1] == L'.' && path[2] == L'\0')); +} + +bool IsUNC(const std::wstring& path) +{ + return path.length() >= 2 && IsSeparator(path[0]) && IsSeparator(path[1]); +} + +bool IsAbsolute(const std::wstring& path) +{ + return (path.find(L":\\") != std::wstring::npos || + path.find(L":/") != std::wstring::npos || + IsUNC(path)); +} + +void AppendBacklashIfMissing(std::wstring& path) +{ + if (!path.empty() && !IsSeparator(path[path.length() - 1])) + { + path += L'\\'; + } +} + +std::wstring GetFolderFromFilePath(const std::wstring& filePath) +{ + std::wstring::size_type pos = filePath.find_last_of(L"\\/"); + if (pos != std::wstring::npos) + { + return filePath.substr(0, pos + 1); + } + return L".\\"; +} + +/* +** Extracts volume path from program path. +** E.g.: +** "C:\path\" to "C:" +** "\\server\share\" to "\\server\share" +** "\\server\C:\path\" to "\\server\C:" +*/ +std::wstring GetVolume(const std::wstring& path) +{ + std::wstring::size_type pos; + if ((pos = path.find_first_of(L':')) != std::wstring::npos) + { + return path.substr(0, pos + 1); + } + else if (IsUNC(path)) + { + if ((pos = path.find_first_of(L"\\/", 2)) != std::wstring::npos) + { + std::wstring::size_type pos2; + if ((pos2 = path.find_first_of(L"\\/", pos + 1)) != std::wstring::npos || + pos != (path.length() - 1)) + { + pos = pos2; + } + } + + return path.substr(0, pos); + } + + return std::wstring(); +} + +void ExpandEnvironmentVariables(std::wstring& path) +{ + std::wstring::size_type pos; + if ((pos = path.find(L'%')) != std::wstring::npos && + path.find(L'%', pos + 2) != std::wstring::npos) + { + DWORD bufSize = 4096; + WCHAR* buffer = new WCHAR[bufSize]; + + // %APPDATA% is a special case. + pos = path.find(L"%APPDATA%", pos); + if (pos != std::wstring::npos) + { + HRESULT hr = SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, buffer); + if (SUCCEEDED(hr)) + { + size_t len = wcslen(buffer); + do + { + path.replace(pos, 9, buffer, len); + } + while ((pos = path.find(L"%APPDATA%", pos + len)) != std::wstring::npos); + } + } + + if ((pos = path.find(L'%')) != std::wstring::npos && + path.find(L'%', pos + 2) != std::wstring::npos) + { + // Expand the environment variables. + do + { + DWORD ret = ExpandEnvironmentStrings(path.c_str(), buffer, bufSize); + if (ret == 0) // Error + { + break; + } + if (ret <= bufSize) // Fits in the buffer + { + path.assign(buffer, ret - 1); + break; + } + + delete [] buffer; + bufSize = ret; + buffer = new WCHAR[bufSize]; + } + while (true); + } + + delete [] buffer; + } +} + +} // namespace PathUtil diff --git a/Common/PathUtil.h b/Common/PathUtil.h index 77166889..5f41b223 100644 --- a/Common/PathUtil.h +++ b/Common/PathUtil.h @@ -1,45 +1,45 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_COMMON_PATHUTIL_H_ -#define RM_COMMON_PATHUTIL_H_ - -#include -#include - -namespace PathUtil { - -bool IsSeparator(WCHAR ch); - -bool IsDotOrDotDot(const WCHAR* path); - -bool IsUNC(const std::wstring& path); - -bool IsAbsolute(const std::wstring& path); - -void AppendBacklashIfMissing(std::wstring& path); - -std::wstring GetFolderFromFilePath(const std::wstring& filePath); - -std::wstring GetVolume(const std::wstring& path); - -void ExpandEnvironmentVariables(std::wstring& strPath); - -} // namespace PathUtil - -#endif +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_COMMON_PATHUTIL_H_ +#define RM_COMMON_PATHUTIL_H_ + +#include +#include + +namespace PathUtil { + +bool IsSeparator(WCHAR ch); + +bool IsDotOrDotDot(const WCHAR* path); + +bool IsUNC(const std::wstring& path); + +bool IsAbsolute(const std::wstring& path); + +void AppendBacklashIfMissing(std::wstring& path); + +std::wstring GetFolderFromFilePath(const std::wstring& filePath); + +std::wstring GetVolume(const std::wstring& path); + +void ExpandEnvironmentVariables(std::wstring& strPath); + +} // namespace PathUtil + +#endif diff --git a/Common/PathUtil_Test.cpp b/Common/PathUtil_Test.cpp index f5e51241..26d650ad 100644 --- a/Common/PathUtil_Test.cpp +++ b/Common/PathUtil_Test.cpp @@ -1,106 +1,106 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "PathUtil.h" -#include "UnitTest.h" -#include - -namespace PathUtil { - -TEST_CLASS(Common_PathUtil_Test) -{ -public: - TEST_METHOD(TestIsSeparator) - { - Assert::IsTrue(IsSeparator(L'\\')); - Assert::IsTrue(IsSeparator(L'/')); - Assert::IsFalse(IsSeparator(L'.')); - } - - TEST_METHOD(TestIsDotOrDotDot) - { - Assert::IsTrue(IsDotOrDotDot(L".")); - Assert::IsTrue(IsDotOrDotDot(L"..")); - Assert::IsFalse(IsDotOrDotDot(L"...")); - Assert::IsFalse(IsDotOrDotDot(L"")); - } - - TEST_METHOD(TestIsUNC) - { - Assert::IsTrue(IsUNC(L"\\\\server")); - Assert::IsTrue(IsUNC(L"//server")); - } - - TEST_METHOD(TestIsAbsolute) - { - Assert::IsTrue(IsAbsolute(L"\\\\server")); - Assert::IsTrue(IsAbsolute(L"C:\\test")); - Assert::IsTrue(IsAbsolute(L"C:/test")); - Assert::IsFalse(IsAbsolute(L"C:")); - } - - TEST_METHOD(TestAppendBacklashIfMissing) - { - std::wstring path; - AppendBacklashIfMissing(path); - Assert::IsTrue(path.empty()); - - std::wstring path2 = L"C:\\test"; - AppendBacklashIfMissing(path2); - Assert::IsTrue(path2 == L"C:\\test\\"); - - std::wstring path3 = L"C:\\test\\"; - AppendBacklashIfMissing(path3); - Assert::IsTrue(path3 == L"C:\\test\\"); - } - - TEST_METHOD(TestGetFolderFromFilePath) - { - Assert::IsTrue(GetFolderFromFilePath(L"C:\\test.txt") == L"C:\\"); - } - - TEST_METHOD(TestGetVolume) - { - Assert::IsTrue(GetVolume(L"C:\\test.txt") == L"C:"); - Assert::IsTrue(GetVolume(L"\\\\server\\share\\") == L"\\\\server\\share"); - Assert::IsTrue(GetVolume(L"\\\\server\\C:\\path\\") == L"\\\\server\\C:"); - } - - TEST_METHOD(TestExpandEnvironmentVariables) - { - WCHAR appdataPath[MAX_PATH]; - SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, appdataPath); - - WCHAR windirPath[MAX_PATH]; - ExpandEnvironmentStrings(L"%WINDIR%", windirPath, MAX_PATH); - - std::wstring test = L"%APPDATA%"; - PathUtil::ExpandEnvironmentVariables(test); - Assert::IsTrue(test == appdataPath); - - std::wstring test2 = L"%APPDATA%%WINDIR%"; - PathUtil::ExpandEnvironmentVariables(test2); - Assert::IsTrue(test2 == ((std::wstring)appdataPath + windirPath)); - - std::wstring test3 = L"%APPDATA%%WINDIR%%APPDATA%"; - PathUtil::ExpandEnvironmentVariables(test3); - Assert::IsTrue(test3 == ((std::wstring)appdataPath + windirPath + appdataPath)); - } -}; - -} // namespace PathUtil +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "PathUtil.h" +#include "UnitTest.h" +#include + +namespace PathUtil { + +TEST_CLASS(Common_PathUtil_Test) +{ +public: + TEST_METHOD(TestIsSeparator) + { + Assert::IsTrue(IsSeparator(L'\\')); + Assert::IsTrue(IsSeparator(L'/')); + Assert::IsFalse(IsSeparator(L'.')); + } + + TEST_METHOD(TestIsDotOrDotDot) + { + Assert::IsTrue(IsDotOrDotDot(L".")); + Assert::IsTrue(IsDotOrDotDot(L"..")); + Assert::IsFalse(IsDotOrDotDot(L"...")); + Assert::IsFalse(IsDotOrDotDot(L"")); + } + + TEST_METHOD(TestIsUNC) + { + Assert::IsTrue(IsUNC(L"\\\\server")); + Assert::IsTrue(IsUNC(L"//server")); + } + + TEST_METHOD(TestIsAbsolute) + { + Assert::IsTrue(IsAbsolute(L"\\\\server")); + Assert::IsTrue(IsAbsolute(L"C:\\test")); + Assert::IsTrue(IsAbsolute(L"C:/test")); + Assert::IsFalse(IsAbsolute(L"C:")); + } + + TEST_METHOD(TestAppendBacklashIfMissing) + { + std::wstring path; + AppendBacklashIfMissing(path); + Assert::IsTrue(path.empty()); + + std::wstring path2 = L"C:\\test"; + AppendBacklashIfMissing(path2); + Assert::IsTrue(path2 == L"C:\\test\\"); + + std::wstring path3 = L"C:\\test\\"; + AppendBacklashIfMissing(path3); + Assert::IsTrue(path3 == L"C:\\test\\"); + } + + TEST_METHOD(TestGetFolderFromFilePath) + { + Assert::IsTrue(GetFolderFromFilePath(L"C:\\test.txt") == L"C:\\"); + } + + TEST_METHOD(TestGetVolume) + { + Assert::IsTrue(GetVolume(L"C:\\test.txt") == L"C:"); + Assert::IsTrue(GetVolume(L"\\\\server\\share\\") == L"\\\\server\\share"); + Assert::IsTrue(GetVolume(L"\\\\server\\C:\\path\\") == L"\\\\server\\C:"); + } + + TEST_METHOD(TestExpandEnvironmentVariables) + { + WCHAR appdataPath[MAX_PATH]; + SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, appdataPath); + + WCHAR windirPath[MAX_PATH]; + ExpandEnvironmentStrings(L"%WINDIR%", windirPath, MAX_PATH); + + std::wstring test = L"%APPDATA%"; + PathUtil::ExpandEnvironmentVariables(test); + Assert::IsTrue(test == appdataPath); + + std::wstring test2 = L"%APPDATA%%WINDIR%"; + PathUtil::ExpandEnvironmentVariables(test2); + Assert::IsTrue(test2 == ((std::wstring)appdataPath + windirPath)); + + std::wstring test3 = L"%APPDATA%%WINDIR%%APPDATA%"; + PathUtil::ExpandEnvironmentVariables(test3); + Assert::IsTrue(test3 == ((std::wstring)appdataPath + windirPath + appdataPath)); + } +}; + +} // namespace PathUtil diff --git a/Common/Platform.cpp b/Common/Platform.cpp index 9e933bc3..3d621afd 100644 --- a/Common/Platform.cpp +++ b/Common/Platform.cpp @@ -1,102 +1,102 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Platform.h" - -namespace Platform { - -LPCWSTR GetPlatformName() -{ - const bool isServer = IsWindowsServer(); - - // Note: Place newer versions at the top. - - if (IsWindows8Point1OrGreater()) return isServer ? L"Windows Server 2012 R2" : L"Windows 8.1"; - if (IsWindows8OrGreater()) return isServer ? L"Windows Server 2012" : L"Windows 8"; - if (IsWindows7OrGreater()) return isServer ? L"Windows Server 2008 R2" : L"Windows 7"; - if (IsWindowsVistaOrGreater()) return isServer ? L"Windows Server 2008" : L"Windows Vista"; - if (IsWindowsXPOrGreater()) return isServer ? L"Windows Server 2003" : L"Windows XP"; - - return L"Unknown"; -} - -std::wstring GetPlatformFriendlyName() -{ - std::wstring name; - - WCHAR buffer[256]; - DWORD size = _countof(buffer); - - HKEY hKey; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) - { - if (RegQueryValueEx(hKey, L"ProductName", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS) - { - name += buffer; - name += L' '; - name += Is64BitWindows() ? L"64" : L"32"; - name += L"-bit"; - - size = _countof(buffer); - if (RegQueryValueEx(hKey, L"CurrentBuildNumber", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS || - RegQueryValueEx(hKey, L"CurrentBuild", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS) - { - name += L" (build "; - name += buffer; - name += L')'; - } - - size = _countof(buffer); - if (RegQueryValueEx(hKey, L"CSDVersion", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS) - { - name += L' '; - name += buffer; - } - } - - RegCloseKey(hKey); - } - else - { - name = L"Windows version unknown"; - } - - return name; -} - -/* -** Returns |true| if running on 64-bit Windows. -*/ -bool Is64BitWindows() -{ -#if _WIN64 - return true; -#endif - - auto isWow64Process = (decltype(IsWow64Process)*)GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process"); - if (isWow64Process) - { - BOOL isWow64 = FALSE; - return isWow64Process(GetCurrentProcess(), &isWow64) && isWow64; - } - - return false; -} - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Platform.h" + +namespace Platform { + +LPCWSTR GetPlatformName() +{ + const bool isServer = IsWindowsServer(); + + // Note: Place newer versions at the top. + + if (IsWindows8Point1OrGreater()) return isServer ? L"Windows Server 2012 R2" : L"Windows 8.1"; + if (IsWindows8OrGreater()) return isServer ? L"Windows Server 2012" : L"Windows 8"; + if (IsWindows7OrGreater()) return isServer ? L"Windows Server 2008 R2" : L"Windows 7"; + if (IsWindowsVistaOrGreater()) return isServer ? L"Windows Server 2008" : L"Windows Vista"; + if (IsWindowsXPOrGreater()) return isServer ? L"Windows Server 2003" : L"Windows XP"; + + return L"Unknown"; +} + +std::wstring GetPlatformFriendlyName() +{ + std::wstring name; + + WCHAR buffer[256]; + DWORD size = _countof(buffer); + + HKEY hKey; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) + { + if (RegQueryValueEx(hKey, L"ProductName", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS) + { + name += buffer; + name += L' '; + name += Is64BitWindows() ? L"64" : L"32"; + name += L"-bit"; + + size = _countof(buffer); + if (RegQueryValueEx(hKey, L"CurrentBuildNumber", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS || + RegQueryValueEx(hKey, L"CurrentBuild", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS) + { + name += L" (build "; + name += buffer; + name += L')'; + } + + size = _countof(buffer); + if (RegQueryValueEx(hKey, L"CSDVersion", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS) + { + name += L' '; + name += buffer; + } + } + + RegCloseKey(hKey); + } + else + { + name = L"Windows version unknown"; + } + + return name; +} + +/* +** Returns |true| if running on 64-bit Windows. +*/ +bool Is64BitWindows() +{ +#if _WIN64 + return true; +#endif + + auto isWow64Process = (decltype(IsWow64Process)*)GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process"); + if (isWow64Process) + { + BOOL isWow64 = FALSE; + return isWow64Process(GetCurrentProcess(), &isWow64) && isWow64; + } + + return false; +} + } // namespace Platform \ No newline at end of file diff --git a/Common/Platform.h b/Common/Platform.h index 4298ff0a..94c33dff 100644 --- a/Common/Platform.h +++ b/Common/Platform.h @@ -1,32 +1,32 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_COMMON_PLATFORM_H_ -#define RM_COMMON_PLATFORM_H_ - -#include - -namespace Platform { - -LPCWSTR GetPlatformName(); -std::wstring GetPlatformFriendlyName(); -bool Is64BitWindows(); - -} // namespace Platform - -#endif +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_COMMON_PLATFORM_H_ +#define RM_COMMON_PLATFORM_H_ + +#include + +namespace Platform { + +LPCWSTR GetPlatformName(); +std::wstring GetPlatformFriendlyName(); +bool Is64BitWindows(); + +} // namespace Platform + +#endif diff --git a/Common/RawString.h b/Common/RawString.h index ef3c3f30..1046c126 100644 --- a/Common/RawString.h +++ b/Common/RawString.h @@ -1,92 +1,92 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_COMMON_RAWSTRING_H_ -#define RM_COMMON_RAWSTRING_H_ - -#include - -class RawString -{ -public: - RawString() : - m_String() - { - } - - RawString(const wchar_t* str) : - m_String(str_alloc(str)) - { - } - - RawString(const RawString& rhs) : - m_String(str_alloc(rhs.c_str())) - { - } - - ~RawString() - { - clear(); - } - - RawString& operator=(const wchar_t* rhs) - { - clear(); - m_String = str_alloc(rhs); - return *this; - } - - RawString& operator=(const RawString& rhs) - { - if (&rhs != this) - { - clear(); - m_String = str_alloc(rhs.m_String); - } - return *this; - } - - const wchar_t* c_str() const - { - return m_String ? m_String : L""; - } - - bool empty() const - { - return !m_String || !(*m_String); - } - - void clear() - { - if (m_String) - { - free(m_String); - m_String = nullptr; - } - } - -private: - wchar_t* str_alloc(const wchar_t* str) - { - return str ? _wcsdup(str) : nullptr; - } - - wchar_t* m_String; -}; - -#endif +/* + Copyright (C) 2011 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_COMMON_RAWSTRING_H_ +#define RM_COMMON_RAWSTRING_H_ + +#include + +class RawString +{ +public: + RawString() : + m_String() + { + } + + RawString(const wchar_t* str) : + m_String(str_alloc(str)) + { + } + + RawString(const RawString& rhs) : + m_String(str_alloc(rhs.c_str())) + { + } + + ~RawString() + { + clear(); + } + + RawString& operator=(const wchar_t* rhs) + { + clear(); + m_String = str_alloc(rhs); + return *this; + } + + RawString& operator=(const RawString& rhs) + { + if (&rhs != this) + { + clear(); + m_String = str_alloc(rhs.m_String); + } + return *this; + } + + const wchar_t* c_str() const + { + return m_String ? m_String : L""; + } + + bool empty() const + { + return !m_String || !(*m_String); + } + + void clear() + { + if (m_String) + { + free(m_String); + m_String = nullptr; + } + } + +private: + wchar_t* str_alloc(const wchar_t* str) + { + return str ? _wcsdup(str) : nullptr; + } + + wchar_t* m_String; +}; + +#endif diff --git a/Common/StringUtil.cpp b/Common/StringUtil.cpp index 48961382..89b3af05 100644 --- a/Common/StringUtil.cpp +++ b/Common/StringUtil.cpp @@ -1,95 +1,95 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "StringUtil.h" - -namespace StringUtil { - -std::string Narrow(const WCHAR* str, int strLen, int cp) -{ - std::string narrowStr; - - if (str && *str) - { - if (strLen == -1) - { - strLen = (int)wcslen(str); - } - - int bufLen = WideCharToMultiByte(cp, 0, str, strLen, nullptr, 0, nullptr, nullptr); - if (bufLen > 0) - { - narrowStr.resize(bufLen); - WideCharToMultiByte(cp, 0, str, strLen, &narrowStr[0], bufLen, nullptr, nullptr); - } - } - return narrowStr; -} - -std::wstring Widen(const char* str, int strLen, int cp) -{ - std::wstring wideStr; - - if (str && *str) - { - if (strLen == -1) - { - strLen = (int)strlen(str); - } - - int bufLen = MultiByteToWideChar(cp, 0, str, strLen, nullptr, 0); - if (bufLen > 0) - { - wideStr.resize(bufLen); - MultiByteToWideChar(cp, 0, str, strLen, &wideStr[0], bufLen); - } - } - return wideStr; -} - -/* -** Escapes reserved PCRE regex metacharacters. -*/ -void EscapeRegExp(std::wstring& str) -{ - size_t start = 0; - while ((start = str.find_first_of(L"\\^$|()[{.+*?", start)) != std::wstring::npos) - { - str.insert(start, L"\\"); - start += 2; - } -} - -/* -** Escapes reserved URL characters. -*/ -void EncodeUrl(std::wstring& str) -{ - size_t pos = 0; - while ((pos = str.find_first_of(L" !*'();:@&=+$,/?#[]", pos)) != std::wstring::npos) - { - WCHAR buffer[3]; - _snwprintf_s(buffer, _countof(buffer), L"%.2X", str[pos]); - str[pos] = L'%'; - str.insert(pos + 1, buffer); - pos += 3; - } -} - -} // namespace StringUtil +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "StringUtil.h" + +namespace StringUtil { + +std::string Narrow(const WCHAR* str, int strLen, int cp) +{ + std::string narrowStr; + + if (str && *str) + { + if (strLen == -1) + { + strLen = (int)wcslen(str); + } + + int bufLen = WideCharToMultiByte(cp, 0, str, strLen, nullptr, 0, nullptr, nullptr); + if (bufLen > 0) + { + narrowStr.resize(bufLen); + WideCharToMultiByte(cp, 0, str, strLen, &narrowStr[0], bufLen, nullptr, nullptr); + } + } + return narrowStr; +} + +std::wstring Widen(const char* str, int strLen, int cp) +{ + std::wstring wideStr; + + if (str && *str) + { + if (strLen == -1) + { + strLen = (int)strlen(str); + } + + int bufLen = MultiByteToWideChar(cp, 0, str, strLen, nullptr, 0); + if (bufLen > 0) + { + wideStr.resize(bufLen); + MultiByteToWideChar(cp, 0, str, strLen, &wideStr[0], bufLen); + } + } + return wideStr; +} + +/* +** Escapes reserved PCRE regex metacharacters. +*/ +void EscapeRegExp(std::wstring& str) +{ + size_t start = 0; + while ((start = str.find_first_of(L"\\^$|()[{.+*?", start)) != std::wstring::npos) + { + str.insert(start, L"\\"); + start += 2; + } +} + +/* +** Escapes reserved URL characters. +*/ +void EncodeUrl(std::wstring& str) +{ + size_t pos = 0; + while ((pos = str.find_first_of(L" !*'();:@&=+$,/?#[]", pos)) != std::wstring::npos) + { + WCHAR buffer[3]; + _snwprintf_s(buffer, _countof(buffer), L"%.2X", str[pos]); + str[pos] = L'%'; + str.insert(pos + 1, buffer); + pos += 3; + } +} + +} // namespace StringUtil diff --git a/Common/StringUtil.h b/Common/StringUtil.h index 43608520..cadea6fe 100644 --- a/Common/StringUtil.h +++ b/Common/StringUtil.h @@ -1,79 +1,79 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_COMMON_STRINGUTIL_H_ -#define RM_COMMON_STRINGUTIL_H_ - -#include -#include -#include -#include - -/* -** Helper class for case insensitive find function. -*/ -template -struct Is_Equal -{ - Is_Equal(const std::locale& loc) : locale(loc) { } - bool operator()(CharT ch1, CharT ch2) { return std::toupper(ch1, locale) == std::toupper(ch2, locale); } - -private: - const std::locale& locale; -}; - -namespace StringUtil { - -std::string Narrow(const WCHAR* str, int strLen = -1, int cp = CP_ACP); -inline std::string Narrow(const std::wstring& str, int cp = CP_ACP) { return Narrow(str.c_str(), (int)str.length(), cp); } - -inline std::string NarrowUTF8(const WCHAR* str, int strLen = -1) { return Narrow(str, strLen, CP_UTF8); } -inline std::string NarrowUTF8(const std::wstring& str) { return Narrow(str.c_str(), (int)str.length(), CP_UTF8); } - -std::wstring Widen(const char* str, int strLen = -1, int cp = CP_ACP); -inline std::wstring Widen(const std::string& str, int cp = CP_ACP) { return Widen(str.c_str(), (int)str.length(), cp); } - -inline std::wstring WidenUTF8(const char* str, int strLen = -1) { return Widen(str, strLen, CP_UTF8); } -inline std::wstring WidenUTF8(const std::string& str) { return Widen(str.c_str(), (int)str.length(), CP_UTF8); } - -void EscapeRegExp(std::wstring& str); - -void EncodeUrl(std::wstring& str); - - -/* -** Case insensitive find function for std::string and std::wstring. -** -** Modified from http://stackoverflow.com/questions/3152241/case-insensitive-stdstring-find#3152296 -*/ -template -std::size_t CaseInsensitiveFind(const T& str1, const T& str2, const std::locale& loc = std::locale()) -{ - T::const_iterator iter = std::search(str1.begin(), str1.end(), - str2.begin(), str2.end(), Is_Equal(loc)); - - if (iter != str1.end()) - { - return (iter - str1.begin()); - } - - return -1; // not found -} -} // namespace StringUtil - -#endif +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_COMMON_STRINGUTIL_H_ +#define RM_COMMON_STRINGUTIL_H_ + +#include +#include +#include +#include + +/* +** Helper class for case insensitive find function. +*/ +template +struct Is_Equal +{ + Is_Equal(const std::locale& loc) : locale(loc) { } + bool operator()(CharT ch1, CharT ch2) { return std::toupper(ch1, locale) == std::toupper(ch2, locale); } + +private: + const std::locale& locale; +}; + +namespace StringUtil { + +std::string Narrow(const WCHAR* str, int strLen = -1, int cp = CP_ACP); +inline std::string Narrow(const std::wstring& str, int cp = CP_ACP) { return Narrow(str.c_str(), (int)str.length(), cp); } + +inline std::string NarrowUTF8(const WCHAR* str, int strLen = -1) { return Narrow(str, strLen, CP_UTF8); } +inline std::string NarrowUTF8(const std::wstring& str) { return Narrow(str.c_str(), (int)str.length(), CP_UTF8); } + +std::wstring Widen(const char* str, int strLen = -1, int cp = CP_ACP); +inline std::wstring Widen(const std::string& str, int cp = CP_ACP) { return Widen(str.c_str(), (int)str.length(), cp); } + +inline std::wstring WidenUTF8(const char* str, int strLen = -1) { return Widen(str, strLen, CP_UTF8); } +inline std::wstring WidenUTF8(const std::string& str) { return Widen(str.c_str(), (int)str.length(), CP_UTF8); } + +void EscapeRegExp(std::wstring& str); + +void EncodeUrl(std::wstring& str); + + +/* +** Case insensitive find function for std::string and std::wstring. +** +** Modified from http://stackoverflow.com/questions/3152241/case-insensitive-stdstring-find#3152296 +*/ +template +std::size_t CaseInsensitiveFind(const T& str1, const T& str2, const std::locale& loc = std::locale()) +{ + T::const_iterator iter = std::search(str1.begin(), str1.end(), + str2.begin(), str2.end(), Is_Equal(loc)); + + if (iter != str1.end()) + { + return (iter - str1.begin()); + } + + return -1; // not found +} +} // namespace StringUtil + +#endif diff --git a/Common/StringUtil_Test.cpp b/Common/StringUtil_Test.cpp index db43c998..f034f9b7 100644 --- a/Common/StringUtil_Test.cpp +++ b/Common/StringUtil_Test.cpp @@ -1,58 +1,58 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StringUtil.h" -#include "UnitTest.h" - -namespace StringUtil { - -TEST_CLASS(Common_StringUtil_Test) -{ -public: - TEST_METHOD(TestWiden) - { - Assert::AreEqual(L"test", Widen("test").c_str()); - Assert::AreEqual(L"te", Widen("test", 2).c_str()); - Assert::AreEqual(L"\u0422\u0114st", WidenUTF8("\xd0\xa2\xc4\x94st").c_str()); - Assert::AreEqual(L"\u0422", WidenUTF8("\xd0\xa2\xc4\x94st", 2).c_str()); - } - - TEST_METHOD(TestNarrow) - { - Assert::AreEqual("test", Narrow(L"test").c_str()); - Assert::AreEqual("te", Narrow(L"test", 2).c_str()); - Assert::AreEqual("\xd0\xa2\xc4\x94st", NarrowUTF8(L"\u0422\u0114st").c_str()); - Assert::AreEqual("\xd0\xa2", NarrowUTF8(L"\u0422\u0114st", 1).c_str()); - } - - TEST_METHOD(TestEscapeRegExp) - { - std::wstring str = L"\\^$|(test)[{. ing+*?"; - EscapeRegExp(str); - Assert::AreEqual(L"\\\\\\^\\$\\|\\(test\\)\\[\\{\\. ing\\+\\*\\?", str.c_str()); - } - - TEST_METHOD(TestEncodeUrl) - { - std::wstring str = L" !*'();:@test&=+$,/?#[ing]"; - EncodeUrl(str); - Assert::AreEqual(L"%20%21%2A%27%28%29%3B%3A%40test%26%3D%2B%24%2C%2F%3F%23%5Bing%5D", str.c_str()); - } -}; - -} // namespace StringUtil +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StringUtil.h" +#include "UnitTest.h" + +namespace StringUtil { + +TEST_CLASS(Common_StringUtil_Test) +{ +public: + TEST_METHOD(TestWiden) + { + Assert::AreEqual(L"test", Widen("test").c_str()); + Assert::AreEqual(L"te", Widen("test", 2).c_str()); + Assert::AreEqual(L"\u0422\u0114st", WidenUTF8("\xd0\xa2\xc4\x94st").c_str()); + Assert::AreEqual(L"\u0422", WidenUTF8("\xd0\xa2\xc4\x94st", 2).c_str()); + } + + TEST_METHOD(TestNarrow) + { + Assert::AreEqual("test", Narrow(L"test").c_str()); + Assert::AreEqual("te", Narrow(L"test", 2).c_str()); + Assert::AreEqual("\xd0\xa2\xc4\x94st", NarrowUTF8(L"\u0422\u0114st").c_str()); + Assert::AreEqual("\xd0\xa2", NarrowUTF8(L"\u0422\u0114st", 1).c_str()); + } + + TEST_METHOD(TestEscapeRegExp) + { + std::wstring str = L"\\^$|(test)[{. ing+*?"; + EscapeRegExp(str); + Assert::AreEqual(L"\\\\\\^\\$\\|\\(test\\)\\[\\{\\. ing\\+\\*\\?", str.c_str()); + } + + TEST_METHOD(TestEncodeUrl) + { + std::wstring str = L" !*'();:@test&=+$,/?#[ing]"; + EncodeUrl(str); + Assert::AreEqual(L"%20%21%2A%27%28%29%3B%3A%40test%26%3D%2B%24%2C%2F%3F%23%5Bing%5D", str.c_str()); + } +}; + +} // namespace StringUtil diff --git a/Common/Timer.h b/Common/Timer.h index 3b406d2e..90957651 100644 --- a/Common/Timer.h +++ b/Common/Timer.h @@ -1,56 +1,56 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_COMMON_TIMER_H_ -#define RM_COMMON_TIMER_H_ - -#include - -// Performs timing using the high-resolution performance counter. -class Timer -{ -public: - void Start() - { - QueryPerformanceCounter(&m_Start); - } - - void Stop() - { - QueryPerformanceCounter(&m_Stop); - } - - // Returns the elapsed time in milliseconds. - double GetElapsed() const - { - static LARGE_INTEGER s_Frequency = []() - { - LARGE_INTEGER frequency; - QueryPerformanceFrequency(&frequency); - return frequency; - } (); - - return (m_Stop.QuadPart - m_Start.QuadPart) * 1000.0 / s_Frequency.QuadPart; - } - -private: - LARGE_INTEGER m_Start; - LARGE_INTEGER m_Stop; -}; - -#endif +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_COMMON_TIMER_H_ +#define RM_COMMON_TIMER_H_ + +#include + +// Performs timing using the high-resolution performance counter. +class Timer +{ +public: + void Start() + { + QueryPerformanceCounter(&m_Start); + } + + void Stop() + { + QueryPerformanceCounter(&m_Stop); + } + + // Returns the elapsed time in milliseconds. + double GetElapsed() const + { + static LARGE_INTEGER s_Frequency = []() + { + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + return frequency; + } (); + + return (m_Stop.QuadPart - m_Start.QuadPart) * 1000.0 / s_Frequency.QuadPart; + } + +private: + LARGE_INTEGER m_Start; + LARGE_INTEGER m_Stop; +}; + +#endif diff --git a/Common/UnitTest.h b/Common/UnitTest.h index 808aba87..a1339c4f 100644 --- a/Common/UnitTest.h +++ b/Common/UnitTest.h @@ -1,26 +1,26 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -// VS IntelliSense doesn't seem to work well with the CppUnitTest.h TEST_CLASS macro. This is a -// simpler version, which seems to work fine. -#undef TEST_CLASS -#define TEST_CLASS(className) class className : public TestClass +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +// VS IntelliSense doesn't seem to work well with the CppUnitTest.h TEST_CLASS macro. This is a +// simpler version, which seems to work fine. +#undef TEST_CLASS +#define TEST_CLASS(className) class className : public TestClass diff --git a/Docs/Building.md b/Docs/Building.md index b784bd81..494c26b6 100644 --- a/Docs/Building.md +++ b/Docs/Building.md @@ -1,39 +1,39 @@ -## Building Rainmeter - -### Get the source code - -Use Git to clone the repository: - - git clone https://github.com/rainmeter/rainmeter.git - -Alternatively, download the repository contents as a [ZIP archive](https://github.com/rainmeter/rainmeter/archive/master.zip). - - -### Building with Visual Studio - -Rainmeter can be built using any version of Visual Studio 2013. If you don't already have VS2013, you can download the free "Visual Studio Express 2013 for Windows Desktop" version [here](http://www.visualstudio.com/downloads/download-visual-studio-vs). - -After Visual Studio has been installed and updated, open Rainmeter.sln at the root of the repository to build. - - -### Building the installer - -First, download and install NSIS Unicode (download the Unicode version, not the ANSI version). - -Now you can simply run the Build.bat batch file in the Build folder of your local repository. If you see any "not found" errors, check that the paths in the `set` commands at the top of the file match your environment. To build the release (non-beta) installer, use `Build.bat RELEASE`. - -To digitally sign the installer and the Rainmeter executables, obtain a Windows code signing certificate and create a Certificate.bat file alongside Build.bat with the following contents: - - set CERTFILE=/path/to/PFXcert.p12 - set CERTKEY=certpassword - - -### Building old versions - -The Rainmeter GitHub repository does not contain the full source code history required to build the installer for versions prior to r1249. To obtain the full source from r1 to r1248, use the old Google Code SVN repository located at: - - http://rainmeter.googlecode.com/svn - -The build instructions above are applicable to r1130 - r1248. Build instructions for r27 - r1129 can be found in svn/wiki/. - +## Building Rainmeter + +### Get the source code + +Use Git to clone the repository: + + git clone https://github.com/rainmeter/rainmeter.git + +Alternatively, download the repository contents as a [ZIP archive](https://github.com/rainmeter/rainmeter/archive/master.zip). + + +### Building with Visual Studio + +Rainmeter can be built using any version of Visual Studio 2013. If you don't already have VS2013, you can download the free "Visual Studio Express 2013 for Windows Desktop" version [here](http://www.visualstudio.com/downloads/download-visual-studio-vs). + +After Visual Studio has been installed and updated, open Rainmeter.sln at the root of the repository to build. + + +### Building the installer + +First, download and install NSIS Unicode (download the Unicode version, not the ANSI version). + +Now you can simply run the Build.bat batch file in the Build folder of your local repository. If you see any "not found" errors, check that the paths in the `set` commands at the top of the file match your environment. To build the release (non-beta) installer, use `Build.bat RELEASE`. + +To digitally sign the installer and the Rainmeter executables, obtain a Windows code signing certificate and create a Certificate.bat file alongside Build.bat with the following contents: + + set CERTFILE=/path/to/PFXcert.p12 + set CERTKEY=certpassword + + +### Building old versions + +The Rainmeter GitHub repository does not contain the full source code history required to build the installer for versions prior to r1249. To obtain the full source from r1 to r1248, use the old Google Code SVN repository located at: + + http://rainmeter.googlecode.com/svn + +The build instructions above are applicable to r1130 - r1248. Build instructions for r27 - r1129 can be found in svn/wiki/. + The language files for r963 - r1214 were in a separate repository (svn:externals), which is not available any longer. As a result, the language .dll's for those revisions cannot be built. \ No newline at end of file diff --git a/Docs/UnitTests.md b/Docs/UnitTests.md index a9460eaa..04571c88 100644 --- a/Docs/UnitTests.md +++ b/Docs/UnitTests.md @@ -1,32 +1,32 @@ -Rainmeter uses the [Visual Studio Native Unit Testing framework](http://msdn.microsoft.com/en-us/library/hh598953.aspx) for unit testing. - - -### General notes - -All unit test files should have the `$(ExcludeTests)` property set. The easiest way to ensure this is to manually edit the `ClCompile` entry of the project .vcxproj file. Make sure it looks something like this: - - - $(ExcludeTests) - - -When building within Visual Studio, the macro `$(ExcludeTests)` evaluates to `false` (i.e. the test files are **not** excluded). When building using Build.bat, it evaluates to `true`, and, consequently, the test files are excluded from the build. This is done in order to both reduce the actual build size and remove any kind of dependency on *Microsoft.VisualStudio.TestTools.CppUnitTestFramework.dll* (see below). - - -### Project type specific notes - -* Static library projects: - - Unit testing static library project requires the use of a separate DLL project. The static library project contains the actual code while the DLL project references the static library and includes the testing code. - - See `Common\Common.vcxproj` and `Common\Common_Test.vcxproj` for an example. - -* Dynamic library projects: - - A unit tested dynamic library project should contain both the actual code and the testing code. - - In addition, the `$(DelayLoadTestDLL)` macro should be included in the linker *Delay Loaded Dlls* option. The VS unit testing framework introduces a dependency on *Microsoft.VisualStudio.TestTools.CppUnitTestFramework.dll* for dynamic library projects, which means that omitting the `$(DelayLoadTestDLL)` macro will result in the dynamic library failing to load. - - -### Running tests - -When you build the test project, the tests appear in **Test Explorer**. If Test Explorer is not visible, choose **Test** on the Visual Studio menu, choose **Windows**, and then choose **Test Explorer**. From there, you can run all or a subset of the tests. +Rainmeter uses the [Visual Studio Native Unit Testing framework](http://msdn.microsoft.com/en-us/library/hh598953.aspx) for unit testing. + + +### General notes + +All unit test files should have the `$(ExcludeTests)` property set. The easiest way to ensure this is to manually edit the `ClCompile` entry of the project .vcxproj file. Make sure it looks something like this: + + + $(ExcludeTests) + + +When building within Visual Studio, the macro `$(ExcludeTests)` evaluates to `false` (i.e. the test files are **not** excluded). When building using Build.bat, it evaluates to `true`, and, consequently, the test files are excluded from the build. This is done in order to both reduce the actual build size and remove any kind of dependency on *Microsoft.VisualStudio.TestTools.CppUnitTestFramework.dll* (see below). + + +### Project type specific notes + +* Static library projects: + + Unit testing static library project requires the use of a separate DLL project. The static library project contains the actual code while the DLL project references the static library and includes the testing code. + + See `Common\Common.vcxproj` and `Common\Common_Test.vcxproj` for an example. + +* Dynamic library projects: + + A unit tested dynamic library project should contain both the actual code and the testing code. + + In addition, the `$(DelayLoadTestDLL)` macro should be included in the linker *Delay Loaded Dlls* option. The VS unit testing framework introduces a dependency on *Microsoft.VisualStudio.TestTools.CppUnitTestFramework.dll* for dynamic library projects, which means that omitting the `$(DelayLoadTestDLL)` macro will result in the dynamic library failing to load. + + +### Running tests + +When you build the test project, the tests appear in **Test Explorer**. If Test Explorer is not visible, choose **Test** on the Visual Studio menu, choose **Windows**, and then choose **Test Explorer**. From there, you can run all or a subset of the tests. diff --git a/Installer/Application.cpp b/Installer/Application.cpp index 1c696aca..43abf00d 100644 --- a/Installer/Application.cpp +++ b/Installer/Application.cpp @@ -1,100 +1,100 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Application.h" -#include "DialogInstall.h" -#include "Install.h" -#include "Resource.h" - -bool IsSupportedPlatform(); -bool IsSupportedCPU(); - -int APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR cmdLine, int) -{ - CoInitialize(nullptr); - InitCommonControls(); - - if (*cmdLine) - { - InstallOptions options; - const int scans = swscanf( - cmdLine, L"OPT:%259[^|]|%ld|%hd|%hd|%d", - options.targetPath, - &options.language, - &options.type, - &options.arch, - &options.launchOnLogin); - if (scans == 5) - { - DoInstall(options); - return 0; - } - - return 1; - } - - if (!IsSupportedPlatform()) - { - MessageBox( - nullptr, - L"Windows XP SP2 or higher is required to install Rainmeter.", - L"Rainmeter Setup", MB_OK | MB_ICONERROR); - return (int)InstallStatus::UnsupportedPlatform; - } - - if (!IsSupportedCPU()) - { - MessageBox( - nullptr, - L"A Pentium III or later processor is required to install Rainmeter.", - L"Rainmeter Setup", MB_OK | MB_ICONERROR); - return (int)InstallStatus::UnsupportedPlatform; - } - - CDialogInstall::Create(); - - return 0; -} - -bool IsSupportedPlatform() -{ - OSVERSIONINFOEX osvi = { sizeof(OSVERSIONINFOEX) }; - GetVersionEx((OSVERSIONINFO*)&osvi); - - if (osvi.wProductType != VER_NT_WORKSTATION || - (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)) - { - // 2000 or lower. - return false; - } - - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 && - osvi.wServicePackMajor <= (GetSystemMetrics(SM_SERVERR2) == 0 ? 0 : 1)) - { - // XP SP1 or lower, 2003 SP0. - return FALSE; - } - - return TRUE; -} - -bool IsSupportedCPU() -{ - return IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE) != 0; -} +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Application.h" +#include "DialogInstall.h" +#include "Install.h" +#include "Resource.h" + +bool IsSupportedPlatform(); +bool IsSupportedCPU(); + +int APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR cmdLine, int) +{ + CoInitialize(nullptr); + InitCommonControls(); + + if (*cmdLine) + { + InstallOptions options; + const int scans = swscanf( + cmdLine, L"OPT:%259[^|]|%ld|%hd|%hd|%d", + options.targetPath, + &options.language, + &options.type, + &options.arch, + &options.launchOnLogin); + if (scans == 5) + { + DoInstall(options); + return 0; + } + + return 1; + } + + if (!IsSupportedPlatform()) + { + MessageBox( + nullptr, + L"Windows XP SP2 or higher is required to install Rainmeter.", + L"Rainmeter Setup", MB_OK | MB_ICONERROR); + return (int)InstallStatus::UnsupportedPlatform; + } + + if (!IsSupportedCPU()) + { + MessageBox( + nullptr, + L"A Pentium III or later processor is required to install Rainmeter.", + L"Rainmeter Setup", MB_OK | MB_ICONERROR); + return (int)InstallStatus::UnsupportedPlatform; + } + + CDialogInstall::Create(); + + return 0; +} + +bool IsSupportedPlatform() +{ + OSVERSIONINFOEX osvi = { sizeof(OSVERSIONINFOEX) }; + GetVersionEx((OSVERSIONINFO*)&osvi); + + if (osvi.wProductType != VER_NT_WORKSTATION || + (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)) + { + // 2000 or lower. + return false; + } + + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 && + osvi.wServicePackMajor <= (GetSystemMetrics(SM_SERVERR2) == 0 ? 0 : 1)) + { + // XP SP1 or lower, 2003 SP0. + return FALSE; + } + + return TRUE; +} + +bool IsSupportedCPU() +{ + return IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE) != 0; +} diff --git a/Installer/Application.h b/Installer/Application.h index 571f9742..2cccf154 100644 --- a/Installer/Application.h +++ b/Installer/Application.h @@ -1,32 +1,32 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_INSTALLER_APPLICATION_H_ -#define RM_INSTALLER_APPLICATION_H_ - -enum class InstallStatus -{ - Success, - Error, - UnsupportedPlatform, - VcRedist2010Missing, - VcRedist2012Missing, - DotNetRedistMissing -}; - -#endif +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_INSTALLER_APPLICATION_H_ +#define RM_INSTALLER_APPLICATION_H_ + +enum class InstallStatus +{ + Success, + Error, + UnsupportedPlatform, + VcRedist2010Missing, + VcRedist2012Missing, + DotNetRedistMissing +}; + +#endif diff --git a/Installer/DialogInstall.cpp b/Installer/DialogInstall.cpp index d71bf92b..cc585f81 100644 --- a/Installer/DialogInstall.cpp +++ b/Installer/DialogInstall.cpp @@ -1,494 +1,494 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "DialogInstall.h" -#include "Install.h" -#include "Resource.h" -#include "Util.h" -#include "../Common/ControlTemplate.h" - -#define APPNAME L"Rainmeter" - -const WCHAR* kRegistryInstallKey = L"SOFTWARE\\" APPNAME; - -CDialogInstall* CDialogInstall::c_Dialog = nullptr; - -HICON GetIcon(UINT id, bool large) -{ - typedef HRESULT (WINAPI * FPLOADICONMETRIC)(HINSTANCE hinst, PCWSTR pszName, int lims, HICON* phico); - - HINSTANCE hExe = GetModuleHandle(nullptr); - HINSTANCE hComctl = GetModuleHandle(L"Comctl32"); - if (hComctl) - { - // Try LoadIconMetric for better quality with high DPI - FPLOADICONMETRIC loadIconMetric = (FPLOADICONMETRIC)GetProcAddress(hComctl, "LoadIconMetric"); - if (loadIconMetric) - { - HICON icon; - HRESULT hr = loadIconMetric(hExe, MAKEINTRESOURCE(id), large ? LIM_LARGE : LIM_SMALL, &icon); - if (SUCCEEDED(hr)) - { - return icon; - } - } - } - - return (HICON)LoadImage( - hExe, - MAKEINTRESOURCE(id), - IMAGE_ICON, - GetSystemMetrics(large ? SM_CXICON : SM_CXSMICON), - GetSystemMetrics(large ? SM_CYICON : SM_CYSMICON), - LR_SHARED); -} - -WCHAR* GetString(UINT id) -{ - switch (id) - { - case 1: return L"Install"; - case 2: return L"Rainmeter 3.0.2 beta setup"; - case 3: return L"Click 'Install' to proceed. Rainmeter will launch after setup."; - case 5: return L"Close"; - case 6: return L"Language:"; - case 7: return L"Destination folder:"; - case 9: return L"..."; - case 10: return L"Launch Rainmeter automatically on login"; - case 13: return L"Cancel"; - case 14: return L"C:\\Program Files\\Rainmeter"; - case 15: return L"Standard install (recommended)"; - case 16: return L"Portable install"; - case 17: return L"Installation type:"; - } - return L""; -} - -CDialogInstall::CDialogInstall() : Dialog(), - m_InstallProcess(), - m_InstallProcessWaitThread() -{ -} - -CDialogInstall::~CDialogInstall() -{ -} - -CDialogInstall* CDialogInstall::Create() -{ - c_Dialog = new CDialogInstall(); - - c_Dialog->ShowDialogWindow( - L"Rainmeter Setup", - 0, 0, 350, 210, - DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU, - WS_EX_APPWINDOW | WS_EX_CONTROLPARENT, - nullptr, - false); - - return c_Dialog; -} - -INT_PTR CDialogInstall::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_INITDIALOG: - return OnInitDialog(wParam, lParam); - - case WM_ACTIVATE: - return OnActivate(wParam, lParam); - - case WM_COMMAND: - return OnCommand(wParam, lParam); - - case WM_NOTIFY: - return OnNotify(wParam, lParam); - - case WM_CLOSE: - { - delete this; - } - return TRUE; - } - - return FALSE; -} - -INT_PTR CDialogInstall::OnInitDialog(WPARAM wParam, LPARAM lParam) -{ - static const ControlTemplate::Control s_Controls[] = - { - CT_ICON(Id_HeaderIcon, 0, - 10, 10, 24, 24, - WS_VISIBLE, 0), - - CT_LABEL(Id_HeaderTitleLabel, 2, - 40, 6, 250, 14, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - - CT_LABEL(-1, 3, - 40, 20, 250, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - - CT_BUTTON(Id_InstallButton, 1, - 199, 191, 70, 14, - WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 0), - - CT_BUTTON(Id_CancelButton, 13, - 274, 191, 70, 14, - WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 0), - - CT_TAB(Id_Tab, 0, - -2, 36, 400, 150, - WS_VISIBLE | WS_TABSTOP | TCS_FIXEDWIDTH, 0) // Last for correct tab order. - }; - - CreateControls(s_Controls, _countof(s_Controls), m_Font, GetString); - - m_TabContents.Create(m_Window); - m_TabContents.Activate(); - - SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)GetIcon(IDI_APPICON, false)); - - HWND item = GetControl(Id_HeaderIcon); - Static_SetIcon(item, GetIcon(IDI_APPICON, true)); - - item = GetControl(Id_HeaderTitleLabel); - SendMessage(item, WM_SETFONT, (WPARAM)m_FontBold, 0); - - item = GetControl(Id_InstallButton); - SendMessage(m_Window, WM_NEXTDLGCTL, (WPARAM)item, TRUE); - if (IsWindowsVistaOrGreater() && !Util::IsProcessUserAdmin()) - { - Button_SetElevationRequiredState(item, TRUE); - } - - return TRUE; -} - -INT_PTR CDialogInstall::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case Id_CancelButton: - PostMessage(m_Window, WM_CLOSE, 0, 0); - break; - - case Id_InstallButton: - LaunchInstallProcess(); - break; - - default: - return FALSE; - } - - return TRUE; -} - -INT_PTR CDialogInstall::OnNotify(WPARAM wParam, LPARAM lParam) -{ - return 0; -} - -void CDialogInstall::LaunchInstallProcess() -{ - const bool isProcsesUserAdmin = Util::IsProcessUserAdmin(); - if (!isProcsesUserAdmin && (IsWindowsVistaOrGreater() && !Util::CanProcessUserElevate())) - { - MessageBox( - m_Window, - L"Adminstrative privileges are required to install Rainmeter.\n\nClick OK to close setup.", - L"Rainmeter Setup", MB_OK | MB_ICONERROR); - PostMessage(m_Window, WM_CLOSE, 0, 0); - return; - } - - m_InstallProcessWaitThread = CreateThread( - nullptr, 0, ElevatedProcessWaitThreadProc, nullptr, CREATE_SUSPENDED, nullptr); - if (!m_InstallProcessWaitThread) - { - // TODO. - } - - WCHAR exePath[MAX_PATH]; - GetModuleFileName(nullptr, exePath, _countof(exePath)); - - HWND item = m_TabContents.GetControl(TabContents::Id_LanguageComboBox); - const LCID lcid = (LCID)ComboBox_GetItemData(item, ComboBox_GetCurSel(item)); - - item = m_TabContents.GetControl(TabContents::Id_InstallationTypeComboBox); - const LPARAM typeData = ComboBox_GetItemData(item, ComboBox_GetCurSel(item)); - - WCHAR targetPath[MAX_PATH]; - item = m_TabContents.GetControl(TabContents::Id_DestinationEdit); - Edit_GetText(item, targetPath, _countof(targetPath)); - - item = m_TabContents.GetControl(TabContents::Id_LaunchOnLoginCheckBox); - const int launchOnLogin = Button_GetCheck(item) == BST_CHECKED ? 1 : 0; - - WCHAR params[512]; - wsprintf( - params, L"OPT:%s|%ld|%hd|%hd|%d", - targetPath, lcid, LOWORD(typeData), HIWORD(typeData), launchOnLogin); - - // Launch the installer process and, if needed, request elevation. - SHELLEXECUTEINFO sei = {sizeof(sei)}; - sei.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; - sei.lpVerb = isProcsesUserAdmin ? L"open" : L"runas"; - sei.lpFile = exePath; - sei.lpParameters = params; - sei.hwnd = m_Window; - sei.nShow = SW_NORMAL; - - if (!ShellExecuteEx(&sei) || !sei.hProcess) - { - MessageBox(m_Window, - L"Adminstrative privileges are required to install Rainmeter.\n\nClick OK to close setup.", - L"Rainmeter Setup", MB_OK | MB_ICONERROR); - PostMessage(m_Window, WM_CLOSE, 0, 0); - return; - } - - m_InstallProcess = sei.hProcess; - ResumeThread(m_InstallProcessWaitThread); -} - -DWORD WINAPI CDialogInstall::ElevatedProcessWaitThreadProc(void* param) -{ - WaitForSingleObject(c_Dialog->m_InstallProcess, INFINITE); - - CloseHandle(c_Dialog->m_InstallProcess); - c_Dialog->m_InstallProcess = nullptr; - - CloseHandle(c_Dialog->m_InstallProcessWaitThread); - c_Dialog->m_InstallProcessWaitThread = nullptr; - - PostMessage(c_Dialog->m_Window, WM_CLOSE, 0, 0); - - return 0; -} - -/* -** Constructor. -** -*/ -CDialogInstall::TabContents::TabContents() : Tab() -{ -} - -void CDialogInstall::TabContents::Create(HWND owner) -{ - Tab::CreateTabWindow(10, 50, 380, 135, owner); - - static const ControlTemplate::Control s_Controls[] = - { - CT_LABEL(-1, 6, - 0, 3, 107, 9, - WS_VISIBLE, 0), - - CT_COMBOBOX(Id_LanguageComboBox, 0, - 107, 0, 222, 14, - WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL, 0), - - CT_LABEL(-1, 17, - 0, 21, 107, 9, - WS_VISIBLE, 0), - - CT_COMBOBOX(Id_InstallationTypeComboBox, 0, - 107, 18, 222, 14, - WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL, 0), - - CT_LABEL(-1, 7, - 0, 43, 107, 9, - WS_VISIBLE, 0), - - CT_EDIT(Id_DestinationEdit, 0, - 107, 40, 192, 14, - WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL | ES_READONLY, WS_EX_CLIENTEDGE), - - CT_BUTTON(Id_DestinationBrowseButton, 9, - 303, 40, 25, 14, - WS_VISIBLE | WS_TABSTOP, 0), - - CT_CHECKBOX(Id_LaunchOnLoginCheckBox, 10, - 0, 69, 250, 9, - WS_VISIBLE | WS_TABSTOP, 0), - }; - - CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); - - HWND item = GetControl(Id_LanguageComboBox); - ComboBox_AddString(item, L"English - English (United States)"); - ComboBox_SetCurSel(item, 0); - - PopulateInstallationTypes(); - UpdateDestinationDirectory(); -} - -void CDialogInstall::TabContents::Initialize() -{ -} - -INT_PTR CDialogInstall::TabContents::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return OnCommand(wParam, lParam); - } - - return FALSE; -} - -INT_PTR CDialogInstall::TabContents::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case Id_DestinationBrowseButton: - { - WCHAR buffer[MAX_PATH]; - BROWSEINFO bi = {0}; - bi.hwndOwner = c_Dialog->GetWindow(); - bi.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS; - - PIDLIST_ABSOLUTE pidl = SHBrowseForFolder(&bi); - if (pidl && SHGetPathFromIDList(pidl, buffer)) - { - HWND item = GetControl(Id_DestinationEdit); - Static_SetText(item, buffer); - CoTaskMemFree(pidl); - } - } - break; - - case Id_InstallationTypeComboBox: - { - if (HIWORD(wParam) == CBN_SELCHANGE) - { - UpdateDestinationDirectory(); - } - break; - } - - default: - return FALSE; - } - - return TRUE; -} - -InstallType CDialogInstall::TabContents::GetInstallType() -{ - HWND item = GetControl(TabContents::Id_InstallationTypeComboBox); - const LPARAM typeData = ComboBox_GetItemData(item, ComboBox_GetCurSel(item)); - return (InstallType)LOWORD(typeData); -} - -InstallArch CDialogInstall::TabContents::GetInstallArch() -{ - HWND item = GetControl(TabContents::Id_InstallationTypeComboBox); - const LPARAM typeData = ComboBox_GetItemData(item, ComboBox_GetCurSel(item)); - return (InstallArch)HIWORD(typeData); -} - -void CDialogInstall::TabContents::PopulateInstallationTypes() -{ - HWND item = GetControl(Id_InstallationTypeComboBox); - int index = 0; - if (Util::IsSystem64Bit()) - { - InstallArch existingArch; - const bool alreadyInstalled = IsAlreadyInstalled(existingArch); - if (!alreadyInstalled || existingArch == InstallArch::X64) - { - index = ComboBox_AddString(item, L"Standard 64-bit installation (recommended)"); - ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Standard, InstallArch::X64)); - } - if (!alreadyInstalled || existingArch == InstallArch::X32) - { - index = ComboBox_AddString(item, L"Standard 32-bit installation"); - ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Standard, InstallArch::X32)); - } - index = ComboBox_AddString(item, L"Portable 64-bit installation"); - ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Portable, InstallArch::X64)); - } - else - { - index = ComboBox_AddString(item, L"Standard 32-bit installation (recommended)"); - ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Standard, InstallArch::X32)); - } - index = ComboBox_AddString(item, L"Portable 32-bit installation"); - ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Portable, InstallArch::X32)); - - ComboBox_SetCurSel(item, 0); -} - -void CDialogInstall::TabContents::UpdateDestinationDirectory() -{ - WCHAR buffer[MAX_PATH]; - buffer[0] = L'\0'; - - if (GetInstallType() == InstallType::Standard) - { - const bool hasRegistryKey = Util::GetRegistryString( - HKEY_LOCAL_MACHINE, kRegistryInstallKey, nullptr, buffer, _countof(buffer)); - if (!hasRegistryKey) - { - const WCHAR* installPath = - GetInstallArch() == InstallArch::X32 ? L"%ProgramFiles%\\" APPNAME : L"%ProgramW6432%\\" APPNAME; - ExpandEnvironmentStrings(installPath, buffer, _countof(buffer)); - } - } - else - { - ExpandEnvironmentStrings(L"%SystemDrive%\\" APPNAME, buffer, _countof(buffer)); - } - - HWND item = GetControl(Id_DestinationEdit); - Edit_SetText(item, buffer); -} - -bool CDialogInstall::TabContents::IsAlreadyInstalled(InstallArch& arch) -{ - WCHAR buffer[MAX_PATH]; - const bool hasRegistryKey = Util::GetRegistryString( - HKEY_LOCAL_MACHINE, kRegistryInstallKey, nullptr, buffer, _countof(buffer)); - if (hasRegistryKey) - { - PathAppend(buffer, L"Rainmeter.exe"); - if (PathFileExists(buffer)) - { - // FIXME: This is an ugly way to check if Rainmeter.exe is 32-bit. - HMODULE rainmeterExe = LoadLibrary(buffer); - if (rainmeterExe) - { - arch = InstallArch::X32; - CloseHandle(rainmeterExe); - } - else - { - arch = InstallArch::X64; - } - return true; - } - } - - return false; -} +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "DialogInstall.h" +#include "Install.h" +#include "Resource.h" +#include "Util.h" +#include "../Common/ControlTemplate.h" + +#define APPNAME L"Rainmeter" + +const WCHAR* kRegistryInstallKey = L"SOFTWARE\\" APPNAME; + +CDialogInstall* CDialogInstall::c_Dialog = nullptr; + +HICON GetIcon(UINT id, bool large) +{ + typedef HRESULT (WINAPI * FPLOADICONMETRIC)(HINSTANCE hinst, PCWSTR pszName, int lims, HICON* phico); + + HINSTANCE hExe = GetModuleHandle(nullptr); + HINSTANCE hComctl = GetModuleHandle(L"Comctl32"); + if (hComctl) + { + // Try LoadIconMetric for better quality with high DPI + FPLOADICONMETRIC loadIconMetric = (FPLOADICONMETRIC)GetProcAddress(hComctl, "LoadIconMetric"); + if (loadIconMetric) + { + HICON icon; + HRESULT hr = loadIconMetric(hExe, MAKEINTRESOURCE(id), large ? LIM_LARGE : LIM_SMALL, &icon); + if (SUCCEEDED(hr)) + { + return icon; + } + } + } + + return (HICON)LoadImage( + hExe, + MAKEINTRESOURCE(id), + IMAGE_ICON, + GetSystemMetrics(large ? SM_CXICON : SM_CXSMICON), + GetSystemMetrics(large ? SM_CYICON : SM_CYSMICON), + LR_SHARED); +} + +WCHAR* GetString(UINT id) +{ + switch (id) + { + case 1: return L"Install"; + case 2: return L"Rainmeter 3.0.2 beta setup"; + case 3: return L"Click 'Install' to proceed. Rainmeter will launch after setup."; + case 5: return L"Close"; + case 6: return L"Language:"; + case 7: return L"Destination folder:"; + case 9: return L"..."; + case 10: return L"Launch Rainmeter automatically on login"; + case 13: return L"Cancel"; + case 14: return L"C:\\Program Files\\Rainmeter"; + case 15: return L"Standard install (recommended)"; + case 16: return L"Portable install"; + case 17: return L"Installation type:"; + } + return L""; +} + +CDialogInstall::CDialogInstall() : Dialog(), + m_InstallProcess(), + m_InstallProcessWaitThread() +{ +} + +CDialogInstall::~CDialogInstall() +{ +} + +CDialogInstall* CDialogInstall::Create() +{ + c_Dialog = new CDialogInstall(); + + c_Dialog->ShowDialogWindow( + L"Rainmeter Setup", + 0, 0, 350, 210, + DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU, + WS_EX_APPWINDOW | WS_EX_CONTROLPARENT, + nullptr, + false); + + return c_Dialog; +} + +INT_PTR CDialogInstall::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_INITDIALOG: + return OnInitDialog(wParam, lParam); + + case WM_ACTIVATE: + return OnActivate(wParam, lParam); + + case WM_COMMAND: + return OnCommand(wParam, lParam); + + case WM_NOTIFY: + return OnNotify(wParam, lParam); + + case WM_CLOSE: + { + delete this; + } + return TRUE; + } + + return FALSE; +} + +INT_PTR CDialogInstall::OnInitDialog(WPARAM wParam, LPARAM lParam) +{ + static const ControlTemplate::Control s_Controls[] = + { + CT_ICON(Id_HeaderIcon, 0, + 10, 10, 24, 24, + WS_VISIBLE, 0), + + CT_LABEL(Id_HeaderTitleLabel, 2, + 40, 6, 250, 14, + WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), + + CT_LABEL(-1, 3, + 40, 20, 250, 9, + WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), + + CT_BUTTON(Id_InstallButton, 1, + 199, 191, 70, 14, + WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 0), + + CT_BUTTON(Id_CancelButton, 13, + 274, 191, 70, 14, + WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 0), + + CT_TAB(Id_Tab, 0, + -2, 36, 400, 150, + WS_VISIBLE | WS_TABSTOP | TCS_FIXEDWIDTH, 0) // Last for correct tab order. + }; + + CreateControls(s_Controls, _countof(s_Controls), m_Font, GetString); + + m_TabContents.Create(m_Window); + m_TabContents.Activate(); + + SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)GetIcon(IDI_APPICON, false)); + + HWND item = GetControl(Id_HeaderIcon); + Static_SetIcon(item, GetIcon(IDI_APPICON, true)); + + item = GetControl(Id_HeaderTitleLabel); + SendMessage(item, WM_SETFONT, (WPARAM)m_FontBold, 0); + + item = GetControl(Id_InstallButton); + SendMessage(m_Window, WM_NEXTDLGCTL, (WPARAM)item, TRUE); + if (IsWindowsVistaOrGreater() && !Util::IsProcessUserAdmin()) + { + Button_SetElevationRequiredState(item, TRUE); + } + + return TRUE; +} + +INT_PTR CDialogInstall::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case Id_CancelButton: + PostMessage(m_Window, WM_CLOSE, 0, 0); + break; + + case Id_InstallButton: + LaunchInstallProcess(); + break; + + default: + return FALSE; + } + + return TRUE; +} + +INT_PTR CDialogInstall::OnNotify(WPARAM wParam, LPARAM lParam) +{ + return 0; +} + +void CDialogInstall::LaunchInstallProcess() +{ + const bool isProcsesUserAdmin = Util::IsProcessUserAdmin(); + if (!isProcsesUserAdmin && (IsWindowsVistaOrGreater() && !Util::CanProcessUserElevate())) + { + MessageBox( + m_Window, + L"Adminstrative privileges are required to install Rainmeter.\n\nClick OK to close setup.", + L"Rainmeter Setup", MB_OK | MB_ICONERROR); + PostMessage(m_Window, WM_CLOSE, 0, 0); + return; + } + + m_InstallProcessWaitThread = CreateThread( + nullptr, 0, ElevatedProcessWaitThreadProc, nullptr, CREATE_SUSPENDED, nullptr); + if (!m_InstallProcessWaitThread) + { + // TODO. + } + + WCHAR exePath[MAX_PATH]; + GetModuleFileName(nullptr, exePath, _countof(exePath)); + + HWND item = m_TabContents.GetControl(TabContents::Id_LanguageComboBox); + const LCID lcid = (LCID)ComboBox_GetItemData(item, ComboBox_GetCurSel(item)); + + item = m_TabContents.GetControl(TabContents::Id_InstallationTypeComboBox); + const LPARAM typeData = ComboBox_GetItemData(item, ComboBox_GetCurSel(item)); + + WCHAR targetPath[MAX_PATH]; + item = m_TabContents.GetControl(TabContents::Id_DestinationEdit); + Edit_GetText(item, targetPath, _countof(targetPath)); + + item = m_TabContents.GetControl(TabContents::Id_LaunchOnLoginCheckBox); + const int launchOnLogin = Button_GetCheck(item) == BST_CHECKED ? 1 : 0; + + WCHAR params[512]; + wsprintf( + params, L"OPT:%s|%ld|%hd|%hd|%d", + targetPath, lcid, LOWORD(typeData), HIWORD(typeData), launchOnLogin); + + // Launch the installer process and, if needed, request elevation. + SHELLEXECUTEINFO sei = {sizeof(sei)}; + sei.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; + sei.lpVerb = isProcsesUserAdmin ? L"open" : L"runas"; + sei.lpFile = exePath; + sei.lpParameters = params; + sei.hwnd = m_Window; + sei.nShow = SW_NORMAL; + + if (!ShellExecuteEx(&sei) || !sei.hProcess) + { + MessageBox(m_Window, + L"Adminstrative privileges are required to install Rainmeter.\n\nClick OK to close setup.", + L"Rainmeter Setup", MB_OK | MB_ICONERROR); + PostMessage(m_Window, WM_CLOSE, 0, 0); + return; + } + + m_InstallProcess = sei.hProcess; + ResumeThread(m_InstallProcessWaitThread); +} + +DWORD WINAPI CDialogInstall::ElevatedProcessWaitThreadProc(void* param) +{ + WaitForSingleObject(c_Dialog->m_InstallProcess, INFINITE); + + CloseHandle(c_Dialog->m_InstallProcess); + c_Dialog->m_InstallProcess = nullptr; + + CloseHandle(c_Dialog->m_InstallProcessWaitThread); + c_Dialog->m_InstallProcessWaitThread = nullptr; + + PostMessage(c_Dialog->m_Window, WM_CLOSE, 0, 0); + + return 0; +} + +/* +** Constructor. +** +*/ +CDialogInstall::TabContents::TabContents() : Tab() +{ +} + +void CDialogInstall::TabContents::Create(HWND owner) +{ + Tab::CreateTabWindow(10, 50, 380, 135, owner); + + static const ControlTemplate::Control s_Controls[] = + { + CT_LABEL(-1, 6, + 0, 3, 107, 9, + WS_VISIBLE, 0), + + CT_COMBOBOX(Id_LanguageComboBox, 0, + 107, 0, 222, 14, + WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL, 0), + + CT_LABEL(-1, 17, + 0, 21, 107, 9, + WS_VISIBLE, 0), + + CT_COMBOBOX(Id_InstallationTypeComboBox, 0, + 107, 18, 222, 14, + WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL, 0), + + CT_LABEL(-1, 7, + 0, 43, 107, 9, + WS_VISIBLE, 0), + + CT_EDIT(Id_DestinationEdit, 0, + 107, 40, 192, 14, + WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL | ES_READONLY, WS_EX_CLIENTEDGE), + + CT_BUTTON(Id_DestinationBrowseButton, 9, + 303, 40, 25, 14, + WS_VISIBLE | WS_TABSTOP, 0), + + CT_CHECKBOX(Id_LaunchOnLoginCheckBox, 10, + 0, 69, 250, 9, + WS_VISIBLE | WS_TABSTOP, 0), + }; + + CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); + + HWND item = GetControl(Id_LanguageComboBox); + ComboBox_AddString(item, L"English - English (United States)"); + ComboBox_SetCurSel(item, 0); + + PopulateInstallationTypes(); + UpdateDestinationDirectory(); +} + +void CDialogInstall::TabContents::Initialize() +{ +} + +INT_PTR CDialogInstall::TabContents::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + return OnCommand(wParam, lParam); + } + + return FALSE; +} + +INT_PTR CDialogInstall::TabContents::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case Id_DestinationBrowseButton: + { + WCHAR buffer[MAX_PATH]; + BROWSEINFO bi = {0}; + bi.hwndOwner = c_Dialog->GetWindow(); + bi.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS; + + PIDLIST_ABSOLUTE pidl = SHBrowseForFolder(&bi); + if (pidl && SHGetPathFromIDList(pidl, buffer)) + { + HWND item = GetControl(Id_DestinationEdit); + Static_SetText(item, buffer); + CoTaskMemFree(pidl); + } + } + break; + + case Id_InstallationTypeComboBox: + { + if (HIWORD(wParam) == CBN_SELCHANGE) + { + UpdateDestinationDirectory(); + } + break; + } + + default: + return FALSE; + } + + return TRUE; +} + +InstallType CDialogInstall::TabContents::GetInstallType() +{ + HWND item = GetControl(TabContents::Id_InstallationTypeComboBox); + const LPARAM typeData = ComboBox_GetItemData(item, ComboBox_GetCurSel(item)); + return (InstallType)LOWORD(typeData); +} + +InstallArch CDialogInstall::TabContents::GetInstallArch() +{ + HWND item = GetControl(TabContents::Id_InstallationTypeComboBox); + const LPARAM typeData = ComboBox_GetItemData(item, ComboBox_GetCurSel(item)); + return (InstallArch)HIWORD(typeData); +} + +void CDialogInstall::TabContents::PopulateInstallationTypes() +{ + HWND item = GetControl(Id_InstallationTypeComboBox); + int index = 0; + if (Util::IsSystem64Bit()) + { + InstallArch existingArch; + const bool alreadyInstalled = IsAlreadyInstalled(existingArch); + if (!alreadyInstalled || existingArch == InstallArch::X64) + { + index = ComboBox_AddString(item, L"Standard 64-bit installation (recommended)"); + ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Standard, InstallArch::X64)); + } + if (!alreadyInstalled || existingArch == InstallArch::X32) + { + index = ComboBox_AddString(item, L"Standard 32-bit installation"); + ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Standard, InstallArch::X32)); + } + index = ComboBox_AddString(item, L"Portable 64-bit installation"); + ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Portable, InstallArch::X64)); + } + else + { + index = ComboBox_AddString(item, L"Standard 32-bit installation (recommended)"); + ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Standard, InstallArch::X32)); + } + index = ComboBox_AddString(item, L"Portable 32-bit installation"); + ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Portable, InstallArch::X32)); + + ComboBox_SetCurSel(item, 0); +} + +void CDialogInstall::TabContents::UpdateDestinationDirectory() +{ + WCHAR buffer[MAX_PATH]; + buffer[0] = L'\0'; + + if (GetInstallType() == InstallType::Standard) + { + const bool hasRegistryKey = Util::GetRegistryString( + HKEY_LOCAL_MACHINE, kRegistryInstallKey, nullptr, buffer, _countof(buffer)); + if (!hasRegistryKey) + { + const WCHAR* installPath = + GetInstallArch() == InstallArch::X32 ? L"%ProgramFiles%\\" APPNAME : L"%ProgramW6432%\\" APPNAME; + ExpandEnvironmentStrings(installPath, buffer, _countof(buffer)); + } + } + else + { + ExpandEnvironmentStrings(L"%SystemDrive%\\" APPNAME, buffer, _countof(buffer)); + } + + HWND item = GetControl(Id_DestinationEdit); + Edit_SetText(item, buffer); +} + +bool CDialogInstall::TabContents::IsAlreadyInstalled(InstallArch& arch) +{ + WCHAR buffer[MAX_PATH]; + const bool hasRegistryKey = Util::GetRegistryString( + HKEY_LOCAL_MACHINE, kRegistryInstallKey, nullptr, buffer, _countof(buffer)); + if (hasRegistryKey) + { + PathAppend(buffer, L"Rainmeter.exe"); + if (PathFileExists(buffer)) + { + // FIXME: This is an ugly way to check if Rainmeter.exe is 32-bit. + HMODULE rainmeterExe = LoadLibrary(buffer); + if (rainmeterExe) + { + arch = InstallArch::X32; + CloseHandle(rainmeterExe); + } + else + { + arch = InstallArch::X64; + } + return true; + } + } + + return false; +} diff --git a/Installer/DialogInstall.h b/Installer/DialogInstall.h index a0ce13eb..b58848d6 100644 --- a/Installer/DialogInstall.h +++ b/Installer/DialogInstall.h @@ -1,97 +1,97 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_INSTALLER_DIALOGINSTALL_H_ -#define RM_INSTALLER_DIALOGINSTALL_H_ - -#include "Install.h" -#include "../Common/Dialog.h" - -class CDialogInstall : public Dialog -{ -public: - CDialogInstall(); - virtual ~CDialogInstall(); - - static CDialogInstall* CDialogInstall::Create(); - - static void Open(int tab = 0); - static void Open(const WCHAR* name); - static void ShowAboutLog(); - -protected: - // Layouts tab - class TabContents : public Tab - { - public: - enum Id - { - Id_LanguageComboBox = 100, - Id_InstallationTypeComboBox, - Id_DestinationEdit, - Id_DestinationBrowseButton, - Id_LaunchOnLoginCheckBox - }; - - TabContents(); - - void Create(HWND owner); - virtual void Initialize(); - - InstallType GetInstallType(); - InstallArch GetInstallArch(); - - void PopulateInstallationTypes(); - void UpdateDestinationDirectory(); - - bool IsAlreadyInstalled(InstallArch& arch); - - protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - }; - - static CDialogInstall* c_Dialog; - - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - -private: - enum Id - { - Id_CancelButton = IDCANCEL, - - Id_HeaderIcon = 100, - Id_HeaderTitleLabel, - Id_InstallButton, - Id_Tab - }; - - TabContents m_TabContents; - - HANDLE m_InstallProcess; - HANDLE m_InstallProcessWaitThread; - - void LaunchInstallProcess(); - - static DWORD WINAPI ElevatedProcessWaitThreadProc(void* param); -}; - -#endif +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_INSTALLER_DIALOGINSTALL_H_ +#define RM_INSTALLER_DIALOGINSTALL_H_ + +#include "Install.h" +#include "../Common/Dialog.h" + +class CDialogInstall : public Dialog +{ +public: + CDialogInstall(); + virtual ~CDialogInstall(); + + static CDialogInstall* CDialogInstall::Create(); + + static void Open(int tab = 0); + static void Open(const WCHAR* name); + static void ShowAboutLog(); + +protected: + // Layouts tab + class TabContents : public Tab + { + public: + enum Id + { + Id_LanguageComboBox = 100, + Id_InstallationTypeComboBox, + Id_DestinationEdit, + Id_DestinationBrowseButton, + Id_LaunchOnLoginCheckBox + }; + + TabContents(); + + void Create(HWND owner); + virtual void Initialize(); + + InstallType GetInstallType(); + InstallArch GetInstallArch(); + + void PopulateInstallationTypes(); + void UpdateDestinationDirectory(); + + bool IsAlreadyInstalled(InstallArch& arch); + + protected: + virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + }; + + static CDialogInstall* c_Dialog; + + virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + +private: + enum Id + { + Id_CancelButton = IDCANCEL, + + Id_HeaderIcon = 100, + Id_HeaderTitleLabel, + Id_InstallButton, + Id_Tab + }; + + TabContents m_TabContents; + + HANDLE m_InstallProcess; + HANDLE m_InstallProcessWaitThread; + + void LaunchInstallProcess(); + + static DWORD WINAPI ElevatedProcessWaitThreadProc(void* param); +}; + +#endif diff --git a/Installer/Install.cpp b/Installer/Install.cpp index 64d48d8c..b58c1a59 100644 --- a/Installer/Install.cpp +++ b/Installer/Install.cpp @@ -1,147 +1,147 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Install.h" -#include "Resource.h" - -extern "C" { -#include "lzma/Alloc.h" -#include "lzma/7zFile.h" -#include "lzma/7zVersion.h" -#include "lzma/LzmaDec.h" -#include "lzma/7zCrc.h" -#include "lzma/7z.h" -#include "lzma/7zMemInStream.h" -#include "lzma/7zAlloc.h" -} // extern "C" - -void ExtractPayload(const void* payload, size_t payloadSize, const WCHAR* prefix) -{ - CMemInStream memStream; - MemInStream_Init(&memStream, payload, payloadSize); - - CrcGenerateTable(); - - ISzAlloc alloc = { SzAlloc, SzFree }; - CSzArEx db; - SzArEx_Init(&db); - SRes res = SzArEx_Open(&db, &memStream.s, &alloc, &alloc); - if (res != SZ_OK) - { - SzArEx_Free(&db, &alloc); - return; - } - - WCHAR buffer[MAX_PATH]; - UInt32 blockIndex = 0xFFFFFFFF; - Byte* outBuffer = 0; - size_t outBufferSize = 0; - - for (UInt32 i = 0; i < db.db.NumFiles; i++) - { - size_t offset = 0; - size_t outSizeProcessed = 0; - const CSzFileItem* f = db.db.Files + i; - - SzArEx_GetFileNameUtf16(&db, i, (UInt16*)buffer); - WCHAR* destPath = buffer; - if (wcsncmp(destPath, prefix, 3) == 0 || - wcsncmp(destPath, L"ALL", 3) == 0) - { - // Skip the prefix (X64/X32/ALL) and the path separater. - destPath += 4; - } - else - { - // This file isn't for this arch. - continue; - } - - if (!f->IsDir) - { - res = SzArEx_Extract( - &db, &memStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, - &outSizeProcessed, &alloc, &alloc); - if (res != SZ_OK) - { - break; - } - } - - for (size_t j = 0; destPath[j] != L'\0'; ++j) - { - if (destPath[j] == L'/') - { - destPath[j] = L'\0'; - CreateDirectory(destPath, NULL); - destPath[j] = CHAR_PATH_SEPARATOR; - } - } - - if (f->IsDir) - { - CreateDirectory(destPath, NULL); - continue; - } - - CSzFile outFile; - if (OutFile_OpenW(&outFile, destPath)) - { - res = SZ_ERROR_FAIL; - break; - } - size_t processedSize = outSizeProcessed; - if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || - processedSize != outSizeProcessed) - { - res = SZ_ERROR_FAIL; - break; - } - if (File_Close(&outFile)) - { - res = SZ_ERROR_FAIL; - break; - } - - if (f->AttribDefined) SetFileAttributesW(destPath, f->Attrib); - } - - IAlloc_Free(&alloc, outBuffer); - SzArEx_Free(&db, &alloc); - - if (res == SZ_OK) - { - // Success. - } -} - -void DoInstall(InstallOptions& options) -{ -#ifdef INSTALLER_INCLUDE_PAYLOAD - const auto module = GetModuleHandle(nullptr); - HRSRC payload = FindResource( - module, MAKEINTRESOURCE(IDR_PAYLOAD), MAKEINTRESOURCE(PAYLOAD_RESOURCE_TYPEID)); - const size_t payloadSize = SizeofResource(module, payload); - const void* payloadData = LockResource(LoadResource(module, payload)); - - SetCurrentDirectory(options.targetPath); - ExtractPayload( - payloadData, payloadSize, options.arch == InstallArch::X32 ? L"X32" : L"X64"); -#endif -} +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Install.h" +#include "Resource.h" + +extern "C" { +#include "lzma/Alloc.h" +#include "lzma/7zFile.h" +#include "lzma/7zVersion.h" +#include "lzma/LzmaDec.h" +#include "lzma/7zCrc.h" +#include "lzma/7z.h" +#include "lzma/7zMemInStream.h" +#include "lzma/7zAlloc.h" +} // extern "C" + +void ExtractPayload(const void* payload, size_t payloadSize, const WCHAR* prefix) +{ + CMemInStream memStream; + MemInStream_Init(&memStream, payload, payloadSize); + + CrcGenerateTable(); + + ISzAlloc alloc = { SzAlloc, SzFree }; + CSzArEx db; + SzArEx_Init(&db); + SRes res = SzArEx_Open(&db, &memStream.s, &alloc, &alloc); + if (res != SZ_OK) + { + SzArEx_Free(&db, &alloc); + return; + } + + WCHAR buffer[MAX_PATH]; + UInt32 blockIndex = 0xFFFFFFFF; + Byte* outBuffer = 0; + size_t outBufferSize = 0; + + for (UInt32 i = 0; i < db.db.NumFiles; i++) + { + size_t offset = 0; + size_t outSizeProcessed = 0; + const CSzFileItem* f = db.db.Files + i; + + SzArEx_GetFileNameUtf16(&db, i, (UInt16*)buffer); + WCHAR* destPath = buffer; + if (wcsncmp(destPath, prefix, 3) == 0 || + wcsncmp(destPath, L"ALL", 3) == 0) + { + // Skip the prefix (X64/X32/ALL) and the path separater. + destPath += 4; + } + else + { + // This file isn't for this arch. + continue; + } + + if (!f->IsDir) + { + res = SzArEx_Extract( + &db, &memStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, + &outSizeProcessed, &alloc, &alloc); + if (res != SZ_OK) + { + break; + } + } + + for (size_t j = 0; destPath[j] != L'\0'; ++j) + { + if (destPath[j] == L'/') + { + destPath[j] = L'\0'; + CreateDirectory(destPath, NULL); + destPath[j] = CHAR_PATH_SEPARATOR; + } + } + + if (f->IsDir) + { + CreateDirectory(destPath, NULL); + continue; + } + + CSzFile outFile; + if (OutFile_OpenW(&outFile, destPath)) + { + res = SZ_ERROR_FAIL; + break; + } + size_t processedSize = outSizeProcessed; + if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || + processedSize != outSizeProcessed) + { + res = SZ_ERROR_FAIL; + break; + } + if (File_Close(&outFile)) + { + res = SZ_ERROR_FAIL; + break; + } + + if (f->AttribDefined) SetFileAttributesW(destPath, f->Attrib); + } + + IAlloc_Free(&alloc, outBuffer); + SzArEx_Free(&db, &alloc); + + if (res == SZ_OK) + { + // Success. + } +} + +void DoInstall(InstallOptions& options) +{ +#ifdef INSTALLER_INCLUDE_PAYLOAD + const auto module = GetModuleHandle(nullptr); + HRSRC payload = FindResource( + module, MAKEINTRESOURCE(IDR_PAYLOAD), MAKEINTRESOURCE(PAYLOAD_RESOURCE_TYPEID)); + const size_t payloadSize = SizeofResource(module, payload); + const void* payloadData = LockResource(LoadResource(module, payload)); + + SetCurrentDirectory(options.targetPath); + ExtractPayload( + payloadData, payloadSize, options.arch == InstallArch::X32 ? L"X32" : L"X64"); +#endif +} diff --git a/Installer/Install.h b/Installer/Install.h index 47861d63..3e61f3cb 100644 --- a/Installer/Install.h +++ b/Installer/Install.h @@ -1,45 +1,45 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_INSTALLER_INSTALL_H_ -#define RM_INSTALLER_INSTALL_H_ - -enum InstallType : char -{ - Standard, - Portable -}; - -enum InstallArch : char -{ - X32, - X64 -}; - -struct InstallOptions -{ - WCHAR targetPath[MAX_PATH]; - InstallType type; - InstallArch arch; - LCID language; - BOOL launchOnLogin; -}; - -void DoInstall(InstallOptions& options); - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_INSTALLER_INSTALL_H_ +#define RM_INSTALLER_INSTALL_H_ + +enum InstallType : char +{ + Standard, + Portable +}; + +enum InstallArch : char +{ + X32, + X64 +}; + +struct InstallOptions +{ + WCHAR targetPath[MAX_PATH]; + InstallType type; + InstallArch arch; + LCID language; + BOOL launchOnLogin; +}; + +void DoInstall(InstallOptions& options); + #endif \ No newline at end of file diff --git a/Installer/Installer.rc b/Installer/Installer.rc index 3a0d1b61..135f1d50 100644 --- a/Installer/Installer.rc +++ b/Installer/Installer.rc @@ -1,54 +1,54 @@ -#include -#include "Resource.h" -#include "../Version.h" - -LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT -#pragma code_page(1252) - -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION FILEVER - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", STRFILEVER - VALUE "LegalCopyright", "© 2013 - All authors" - VALUE "OriginalFilename", "Rainmeter-Setup.exe" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} - -// -// Icon -// - -IDI_APPICON ICON "Installer.ico" - -#ifdef INSTALLER_INCLUDE_PAYLOAD -IDR_PAYLOAD PAYLOAD_RESOURCE_TYPEID payload.7z -#endif +#include +#include "Resource.h" +#include "../Version.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT +#pragma code_page(1252) + +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION FILEVER + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", STRFILEVER + VALUE "LegalCopyright", "© 2013 - All authors" + VALUE "OriginalFilename", "Rainmeter-Setup.exe" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} + +// +// Icon +// + +IDI_APPICON ICON "Installer.ico" + +#ifdef INSTALLER_INCLUDE_PAYLOAD +IDR_PAYLOAD PAYLOAD_RESOURCE_TYPEID payload.7z +#endif diff --git a/Installer/Installer.vcxproj b/Installer/Installer.vcxproj index 7df31532..2571b9df 100644 --- a/Installer/Installer.vcxproj +++ b/Installer/Installer.vcxproj @@ -1,83 +1,83 @@ - - - - - {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D} - Application - - - - - - - - - - - - - Windows - Imagehlp.lib;Wininet.lib;Comctl32.lib;Version.lib;UxTheme.lib;shlwapi.lib;%(AdditionalDependencies) - $(WinDDK71Dir)\lib\Crt\i386\msvcrt.lib;$(WinDDK71Dir)\lib\wxp\i386\msvcrt_winxp.obj;%(AdditionalDependencies) - true - - - ..\Application\Application.manifest - - - 4800;4996 - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D} + Application + + + + + + + + + + + + + Windows + Imagehlp.lib;Wininet.lib;Comctl32.lib;Version.lib;UxTheme.lib;shlwapi.lib;%(AdditionalDependencies) + $(WinDDK71Dir)\lib\Crt\i386\msvcrt.lib;$(WinDDK71Dir)\lib\wxp\i386\msvcrt_winxp.obj;%(AdditionalDependencies) + true + + + ..\Application\Application.manifest + + + 4800;4996 + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Installer/Installer.vcxproj.filters b/Installer/Installer.vcxproj.filters index fb80296e..9fa07a01 100644 --- a/Installer/Installer.vcxproj.filters +++ b/Installer/Installer.vcxproj.filters @@ -1,155 +1,155 @@ - - - - - {22670730-eb79-4df9-bed9-27fff1350132} - cpp;c;cxx;rc;def;r;odl;idl;hpj;bat - - - {774a1827-ac91-40b9-ad18-8a3d68983c64} - h;hpp;hxx;hm;inl - - - {a4963a10-e359-400f-86fa-bdce98dd5dc2} - ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe - - - {9588f54f-9188-40b7-b750-260f5f514ee5} - - - {6acda1fa-eb7e-490b-ae49-ed7ff8b2534d} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - Source Files - - - Common - - - Common - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - lzma - - - - - Resource Files - - + + + + + {22670730-eb79-4df9-bed9-27fff1350132} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {774a1827-ac91-40b9-ad18-8a3d68983c64} + h;hpp;hxx;hm;inl + + + {a4963a10-e359-400f-86fa-bdce98dd5dc2} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + {9588f54f-9188-40b7-b750-260f5f514ee5} + + + {6acda1fa-eb7e-490b-ae49-ed7ff8b2534d} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + Source Files + + + Common + + + Common + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + lzma + + + + + Resource Files + + \ No newline at end of file diff --git a/Installer/Resource.h b/Installer/Resource.h index 41578d03..c020e9a3 100644 --- a/Installer/Resource.h +++ b/Installer/Resource.h @@ -1,6 +1,6 @@ -#define IDI_APPICON 101 -#define IDR_PAYLOAD 102 - -#define PAYLOAD_RESOURCE_TYPEID 1000 - -#define IDC_STATIC -1 +#define IDI_APPICON 101 +#define IDR_PAYLOAD 102 + +#define PAYLOAD_RESOURCE_TYPEID 1000 + +#define IDC_STATIC -1 diff --git a/Installer/StdAfx.cpp b/Installer/StdAfx.cpp index 5674c316..a85de943 100644 --- a/Installer/StdAfx.cpp +++ b/Installer/StdAfx.cpp @@ -1,19 +1,19 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" diff --git a/Installer/StdAfx.h b/Installer/StdAfx.h index f0112ea7..96a93202 100644 --- a/Installer/StdAfx.h +++ b/Installer/StdAfx.h @@ -1,36 +1,36 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_INSTALLER_STDAFX_H_ -#define RM_INSTALLER_STDAFX_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_INSTALLER_STDAFX_H_ +#define RM_INSTALLER_STDAFX_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + #endif \ No newline at end of file diff --git a/Installer/Util.cpp b/Installer/Util.cpp index b2728c3d..162cf627 100644 --- a/Installer/Util.cpp +++ b/Installer/Util.cpp @@ -1,281 +1,281 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Util.h" - -namespace Util { - -// -// System functions. -// - -bool IsSystem64Bit() -{ -#ifdef _WIN64 - return true; -#else - BOOL system64 = FALSE; - - typedef BOOL (WINAPI * FPIsWow64Process)(HANDLE hProcess, BOOL* Wow64Process); - auto isWow64Process = (FPIsWow64Process)GetProcAddress( - GetModuleHandle(L"kernel32"), "IsWow64Process"); - if (isWow64Process) - { - isWow64Process(GetCurrentProcess(), &system64); - } - - return system64; -#endif -} - -// -// Process functions. -// - -bool IsProcessUserAdmin() -{ - BOOL runningAsAdmin = FALSE; - - // Allocate and initialize a SID of the administrators group. - PSID adminGroupSid = nullptr; - SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; - if (AllocateAndInitializeSid( - &NtAuthority, - 2, - SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, - 0, 0, 0, 0, 0, 0, - &adminGroupSid)) - { - // Check if the primary access token of the process has the admin group SID. - if (!CheckTokenMembership(nullptr, adminGroupSid, &runningAsAdmin)) - { - runningAsAdmin = TRUE; - } - - FreeSid(adminGroupSid); - adminGroupSid = nullptr; - } - - return runningAsAdmin; -} - -bool CanProcessUserElevate() -{ - OSVERSIONINFO osvi = {sizeof(osvi)}; - GetVersionEx(&osvi); - if (osvi.dwMajorVersion >= 6) - { - // Check if UAC is enabled with Vista and above. - BOOL uacEnabled = FALSE; - - // First try with undocumented CheckElevationEnabled function. - // See: http://blog.airesoft.co.uk/2011/03/uaceen-nothing-yet/ - typedef DWORD (WINAPI * FPCheckElevationEnabled)(BOOL* pResult); - auto checkElevationEnabled = (FPCheckElevationEnabled)GetProcAddress( - GetModuleHandle(L"kernel32"), "CheckElevationEnabled"); - if (checkElevationEnabled && checkElevationEnabled(&uacEnabled) == ERROR_SUCCESS) - { - return uacEnabled; - } - else - { - // Try checking registry. - const WCHAR* subKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"; - DWORD data; - if (GetRegistryDword(HKEY_LOCAL_MACHINE, subKey, L"EnableLUA", &data) && - data != 0) - { - return true; - } - } - } - - return false; -} - -// -// File and directory functions. -// - -bool CopyDirectory(const WCHAR* fromPath, const WCHAR* toPath) -{ - int fromPathLength = wcslen(fromPath); - int toPathLength = wcslen(toPath); - - // SHFileOperation expects double null terminated strings. - WCHAR* from = (WCHAR*)malloc((fromPathLength + 2) * sizeof(WCHAR)); - wcscpy(from, fromPath); - from[fromPathLength + 2] = L'\0'; - - WCHAR* to = (WCHAR*)malloc((toPathLength + 2) * sizeof(WCHAR)); - wcscpy(to, toPath); - to[toPathLength + 2] = L'\0'; - - SHFILEOPSTRUCT fo = - { - nullptr, - FO_COPY, - from, - to, - FOF_SILENT | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR | FOF_NOCONFIRMATION - }; - - BOOL copied = (SHFileOperation(&fo) == 0); - - free(from); - free(to); - - return copied; -} - -bool CreateShortcutFile(const WCHAR* filePath, const WCHAR* targetPath) -{ - IShellLink* psl; - HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl); - if (SUCCEEDED(hr)) - { - IPersistFile* ppf; - hr = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); - if (SUCCEEDED(hr)) - { - psl->SetPath(filePath); - hr = ppf->Save(targetPath, TRUE); - - ppf->Release(); - } - - psl->Release(); - } - - return SUCCEEDED(hr); -} - -bool IsDirectoryWritable() -{ - return TRUE; -} - -// -// Registry functions. -// - -bool GetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD* data) -{ - DWORD type; - DWORD dataSize = sizeof(DWORD); - return (SHGetValue(rootKey, subKey, value, &type, data, &dataSize) == ERROR_SUCCESS && - type == REG_DWORD); -} - -bool GetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, WCHAR* data, DWORD bufferLength) -{ - DWORD type; - DWORD dataSize = bufferLength * sizeof(data[0]); - return (SHGetValue(rootKey, subKey, value, &type, data, &dataSize) == ERROR_SUCCESS && - type == REG_SZ); -} - -bool SetRegistryData(DWORD type, HKEY rootKey, const WCHAR* subKey, const WCHAR* value, BYTE* data, DWORD dataSize) -{ - BOOL result = FALSE; - HKEY regKey; - if (RegCreateKeyEx(rootKey, subKey, 0, 0, 0, KEY_SET_VALUE, nullptr, ®Key, nullptr) == ERROR_SUCCESS) - { - if (RegSetValueEx(regKey, value, 0, type, data, dataSize) == ERROR_SUCCESS) - { - result = TRUE; - } - - RegCloseKey(regKey); - } - - return result; -} - -bool SetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD data) -{ - return SetRegistryData(REG_DWORD, rootKey, subKey, value, (BYTE*)&data, sizeof(DWORD)); -} - -bool SetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, const WCHAR* data) -{ - DWORD dataSize = (wcslen(data) + 1) * sizeof(WCHAR); - return SetRegistryData(REG_SZ, rootKey, subKey, value, (BYTE*)data, dataSize); -} - -// -// Misc. functions. -// - -bool DownloadFile(const WCHAR* url, const WCHAR* file) -{ - bool result = false; - HINTERNET hNet = InternetOpen(L"Mozilla/5.0", INTERNET_OPEN_TYPE_PRECONFIG, nullptr, nullptr, 0); - if (hNet) - { - HANDLE hFile = CreateFile(file, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - if (hFile) - { - HINTERNET hUrl = InternetOpenUrl(hNet, url, nullptr, 0, INTERNET_FLAG_RESYNCHRONIZE, 0); - if (hUrl) - { - const DWORD bufferSize = 8192; - BYTE* buffer = (BYTE*)malloc(bufferSize); - if (buffer) - { - DWORD readSize; - while (InternetReadFile(hUrl, buffer, bufferSize, &readSize)) - { - if (readSize == 0) - { - // All data read. - result = true; - break; - } - - DWORD writeSize; - if (!WriteFile(hFile, buffer, readSize, &writeSize, nullptr) || - readSize != writeSize) - { - break; - } - } - - free(buffer); - } - - InternetCloseHandle(hUrl); - } - - CloseHandle(hFile); - - if (!result) - { - DeleteFile(file); - } - } - - InternetCloseHandle(hNet); - } - - return result; -} - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Util.h" + +namespace Util { + +// +// System functions. +// + +bool IsSystem64Bit() +{ +#ifdef _WIN64 + return true; +#else + BOOL system64 = FALSE; + + typedef BOOL (WINAPI * FPIsWow64Process)(HANDLE hProcess, BOOL* Wow64Process); + auto isWow64Process = (FPIsWow64Process)GetProcAddress( + GetModuleHandle(L"kernel32"), "IsWow64Process"); + if (isWow64Process) + { + isWow64Process(GetCurrentProcess(), &system64); + } + + return system64; +#endif +} + +// +// Process functions. +// + +bool IsProcessUserAdmin() +{ + BOOL runningAsAdmin = FALSE; + + // Allocate and initialize a SID of the administrators group. + PSID adminGroupSid = nullptr; + SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; + if (AllocateAndInitializeSid( + &NtAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &adminGroupSid)) + { + // Check if the primary access token of the process has the admin group SID. + if (!CheckTokenMembership(nullptr, adminGroupSid, &runningAsAdmin)) + { + runningAsAdmin = TRUE; + } + + FreeSid(adminGroupSid); + adminGroupSid = nullptr; + } + + return runningAsAdmin; +} + +bool CanProcessUserElevate() +{ + OSVERSIONINFO osvi = {sizeof(osvi)}; + GetVersionEx(&osvi); + if (osvi.dwMajorVersion >= 6) + { + // Check if UAC is enabled with Vista and above. + BOOL uacEnabled = FALSE; + + // First try with undocumented CheckElevationEnabled function. + // See: http://blog.airesoft.co.uk/2011/03/uaceen-nothing-yet/ + typedef DWORD (WINAPI * FPCheckElevationEnabled)(BOOL* pResult); + auto checkElevationEnabled = (FPCheckElevationEnabled)GetProcAddress( + GetModuleHandle(L"kernel32"), "CheckElevationEnabled"); + if (checkElevationEnabled && checkElevationEnabled(&uacEnabled) == ERROR_SUCCESS) + { + return uacEnabled; + } + else + { + // Try checking registry. + const WCHAR* subKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"; + DWORD data; + if (GetRegistryDword(HKEY_LOCAL_MACHINE, subKey, L"EnableLUA", &data) && + data != 0) + { + return true; + } + } + } + + return false; +} + +// +// File and directory functions. +// + +bool CopyDirectory(const WCHAR* fromPath, const WCHAR* toPath) +{ + int fromPathLength = wcslen(fromPath); + int toPathLength = wcslen(toPath); + + // SHFileOperation expects double null terminated strings. + WCHAR* from = (WCHAR*)malloc((fromPathLength + 2) * sizeof(WCHAR)); + wcscpy(from, fromPath); + from[fromPathLength + 2] = L'\0'; + + WCHAR* to = (WCHAR*)malloc((toPathLength + 2) * sizeof(WCHAR)); + wcscpy(to, toPath); + to[toPathLength + 2] = L'\0'; + + SHFILEOPSTRUCT fo = + { + nullptr, + FO_COPY, + from, + to, + FOF_SILENT | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR | FOF_NOCONFIRMATION + }; + + BOOL copied = (SHFileOperation(&fo) == 0); + + free(from); + free(to); + + return copied; +} + +bool CreateShortcutFile(const WCHAR* filePath, const WCHAR* targetPath) +{ + IShellLink* psl; + HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl); + if (SUCCEEDED(hr)) + { + IPersistFile* ppf; + hr = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); + if (SUCCEEDED(hr)) + { + psl->SetPath(filePath); + hr = ppf->Save(targetPath, TRUE); + + ppf->Release(); + } + + psl->Release(); + } + + return SUCCEEDED(hr); +} + +bool IsDirectoryWritable() +{ + return TRUE; +} + +// +// Registry functions. +// + +bool GetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD* data) +{ + DWORD type; + DWORD dataSize = sizeof(DWORD); + return (SHGetValue(rootKey, subKey, value, &type, data, &dataSize) == ERROR_SUCCESS && + type == REG_DWORD); +} + +bool GetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, WCHAR* data, DWORD bufferLength) +{ + DWORD type; + DWORD dataSize = bufferLength * sizeof(data[0]); + return (SHGetValue(rootKey, subKey, value, &type, data, &dataSize) == ERROR_SUCCESS && + type == REG_SZ); +} + +bool SetRegistryData(DWORD type, HKEY rootKey, const WCHAR* subKey, const WCHAR* value, BYTE* data, DWORD dataSize) +{ + BOOL result = FALSE; + HKEY regKey; + if (RegCreateKeyEx(rootKey, subKey, 0, 0, 0, KEY_SET_VALUE, nullptr, ®Key, nullptr) == ERROR_SUCCESS) + { + if (RegSetValueEx(regKey, value, 0, type, data, dataSize) == ERROR_SUCCESS) + { + result = TRUE; + } + + RegCloseKey(regKey); + } + + return result; +} + +bool SetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD data) +{ + return SetRegistryData(REG_DWORD, rootKey, subKey, value, (BYTE*)&data, sizeof(DWORD)); +} + +bool SetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, const WCHAR* data) +{ + DWORD dataSize = (wcslen(data) + 1) * sizeof(WCHAR); + return SetRegistryData(REG_SZ, rootKey, subKey, value, (BYTE*)data, dataSize); +} + +// +// Misc. functions. +// + +bool DownloadFile(const WCHAR* url, const WCHAR* file) +{ + bool result = false; + HINTERNET hNet = InternetOpen(L"Mozilla/5.0", INTERNET_OPEN_TYPE_PRECONFIG, nullptr, nullptr, 0); + if (hNet) + { + HANDLE hFile = CreateFile(file, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + if (hFile) + { + HINTERNET hUrl = InternetOpenUrl(hNet, url, nullptr, 0, INTERNET_FLAG_RESYNCHRONIZE, 0); + if (hUrl) + { + const DWORD bufferSize = 8192; + BYTE* buffer = (BYTE*)malloc(bufferSize); + if (buffer) + { + DWORD readSize; + while (InternetReadFile(hUrl, buffer, bufferSize, &readSize)) + { + if (readSize == 0) + { + // All data read. + result = true; + break; + } + + DWORD writeSize; + if (!WriteFile(hFile, buffer, readSize, &writeSize, nullptr) || + readSize != writeSize) + { + break; + } + } + + free(buffer); + } + + InternetCloseHandle(hUrl); + } + + CloseHandle(hFile); + + if (!result) + { + DeleteFile(file); + } + } + + InternetCloseHandle(hNet); + } + + return result; +} + } // namespace Util \ No newline at end of file diff --git a/Installer/Util.h b/Installer/Util.h index 9cfbb14b..20fcfc0e 100644 --- a/Installer/Util.h +++ b/Installer/Util.h @@ -1,41 +1,41 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_INSTALLER_UTIL_H_ -#define RM_INSTALLER_UTIL_H_ - -namespace Util { - -bool IsSystem64Bit(); - -bool IsProcessUserAdmin(); -bool CanProcessUserElevate(); - -bool CopyDirectory(const WCHAR* fromPath, const WCHAR* toPath); -bool CreateShortcutFile(const WCHAR* filePath, const WCHAR* targetPath); - -bool GetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD* data); -bool GetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, WCHAR* data, DWORD dataSize); -bool SetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD data); -bool SetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, const WCHAR* data); - -bool DownloadFile(const WCHAR* url, const WCHAR* file); - -} // namespace Util - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_INSTALLER_UTIL_H_ +#define RM_INSTALLER_UTIL_H_ + +namespace Util { + +bool IsSystem64Bit(); + +bool IsProcessUserAdmin(); +bool CanProcessUserElevate(); + +bool CopyDirectory(const WCHAR* fromPath, const WCHAR* toPath); +bool CreateShortcutFile(const WCHAR* filePath, const WCHAR* targetPath); + +bool GetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD* data); +bool GetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, WCHAR* data, DWORD dataSize); +bool SetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD data); +bool SetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, const WCHAR* data); + +bool DownloadFile(const WCHAR* url, const WCHAR* file); + +} // namespace Util + #endif \ No newline at end of file diff --git a/Installer/lzma/7z.h b/Installer/lzma/7z.h index b7edd3ba..01c4cac6 100644 --- a/Installer/lzma/7z.h +++ b/Installer/lzma/7z.h @@ -1,203 +1,203 @@ -/* 7z.h -- 7z interface -2010-03-11 : Igor Pavlov : Public domain */ - -#ifndef __7Z_H -#define __7Z_H - -#include "7zBuf.h" - -EXTERN_C_BEGIN - -#define k7zStartHeaderSize 0x20 -#define k7zSignatureSize 6 -extern Byte k7zSignature[k7zSignatureSize]; -#define k7zMajorVersion 0 - -enum EIdEnum -{ - k7zIdEnd, - k7zIdHeader, - k7zIdArchiveProperties, - k7zIdAdditionalStreamsInfo, - k7zIdMainStreamsInfo, - k7zIdFilesInfo, - k7zIdPackInfo, - k7zIdUnpackInfo, - k7zIdSubStreamsInfo, - k7zIdSize, - k7zIdCRC, - k7zIdFolder, - k7zIdCodersUnpackSize, - k7zIdNumUnpackStream, - k7zIdEmptyStream, - k7zIdEmptyFile, - k7zIdAnti, - k7zIdName, - k7zIdCTime, - k7zIdATime, - k7zIdMTime, - k7zIdWinAttributes, - k7zIdComment, - k7zIdEncodedHeader, - k7zIdStartPos, - k7zIdDummy -}; - -typedef struct -{ - UInt32 NumInStreams; - UInt32 NumOutStreams; - UInt64 MethodID; - CBuf Props; -} CSzCoderInfo; - -void SzCoderInfo_Init(CSzCoderInfo *p); -void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); - -typedef struct -{ - UInt32 InIndex; - UInt32 OutIndex; -} CSzBindPair; - -typedef struct -{ - CSzCoderInfo *Coders; - CSzBindPair *BindPairs; - UInt32 *PackStreams; - UInt64 *UnpackSizes; - UInt32 NumCoders; - UInt32 NumBindPairs; - UInt32 NumPackStreams; - int UnpackCRCDefined; - UInt32 UnpackCRC; - - UInt32 NumUnpackStreams; -} CSzFolder; - -void SzFolder_Init(CSzFolder *p); -UInt64 SzFolder_GetUnpackSize(CSzFolder *p); -int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); -UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); -UInt64 SzFolder_GetUnpackSize(CSzFolder *p); - -SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, - ILookInStream *stream, UInt64 startPos, - Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); - -typedef struct -{ - UInt32 Low; - UInt32 High; -} CNtfsFileTime; - -typedef struct -{ - CNtfsFileTime MTime; - UInt64 Size; - UInt32 Crc; - UInt32 Attrib; - Byte HasStream; - Byte IsDir; - Byte IsAnti; - Byte CrcDefined; - Byte MTimeDefined; - Byte AttribDefined; -} CSzFileItem; - -void SzFile_Init(CSzFileItem *p); - -typedef struct -{ - UInt64 *PackSizes; - Byte *PackCRCsDefined; - UInt32 *PackCRCs; - CSzFolder *Folders; - CSzFileItem *Files; - UInt32 NumPackStreams; - UInt32 NumFolders; - UInt32 NumFiles; -} CSzAr; - -void SzAr_Init(CSzAr *p); -void SzAr_Free(CSzAr *p, ISzAlloc *alloc); - - -/* - SzExtract extracts file from archive - - *outBuffer must be 0 before first call for each new archive. - - Extracting cache: - If you need to decompress more than one file, you can send - these values from previous call: - *blockIndex, - *outBuffer, - *outBufferSize - You can consider "*outBuffer" as cache of solid block. If your archive is solid, - it will increase decompression speed. - - If you use external function, you can declare these 3 cache variables - (blockIndex, outBuffer, outBufferSize) as static in that external function. - - Free *outBuffer and set *outBuffer to 0, if you want to flush cache. -*/ - -typedef struct -{ - CSzAr db; - - UInt64 startPosAfterHeader; - UInt64 dataPos; - - UInt32 *FolderStartPackStreamIndex; - UInt64 *PackStreamStartPositions; - UInt32 *FolderStartFileIndex; - UInt32 *FileIndexToFolderIndexMap; - - size_t *FileNameOffsets; /* in 2-byte steps */ - CBuf FileNames; /* UTF-16-LE */ -} CSzArEx; - -void SzArEx_Init(CSzArEx *p); -void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); -UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); -int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); - -/* -if dest == NULL, the return value specifies the required size of the buffer, - in 16-bit characters, including the null-terminating character. -if dest != NULL, the return value specifies the number of 16-bit characters that - are written to the dest, including the null-terminating character. */ - -size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest); - -SRes SzArEx_Extract( - const CSzArEx *db, - ILookInStream *inStream, - UInt32 fileIndex, /* index of file */ - UInt32 *blockIndex, /* index of solid block */ - Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ - size_t *outBufferSize, /* buffer size for output buffer */ - size_t *offset, /* offset of stream for required file in *outBuffer */ - size_t *outSizeProcessed, /* size of file in *outBuffer */ - ISzAlloc *allocMain, - ISzAlloc *allocTemp); - - -/* -SzArEx_Open Errors: -SZ_ERROR_NO_ARCHIVE -SZ_ERROR_ARCHIVE -SZ_ERROR_UNSUPPORTED -SZ_ERROR_MEM -SZ_ERROR_CRC -SZ_ERROR_INPUT_EOF -SZ_ERROR_FAIL -*/ - -SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); - -EXTERN_C_END - -#endif +/* 7z.h -- 7z interface +2010-03-11 : Igor Pavlov : Public domain */ + +#ifndef __7Z_H +#define __7Z_H + +#include "7zBuf.h" + +EXTERN_C_BEGIN + +#define k7zStartHeaderSize 0x20 +#define k7zSignatureSize 6 +extern Byte k7zSignature[k7zSignatureSize]; +#define k7zMajorVersion 0 + +enum EIdEnum +{ + k7zIdEnd, + k7zIdHeader, + k7zIdArchiveProperties, + k7zIdAdditionalStreamsInfo, + k7zIdMainStreamsInfo, + k7zIdFilesInfo, + k7zIdPackInfo, + k7zIdUnpackInfo, + k7zIdSubStreamsInfo, + k7zIdSize, + k7zIdCRC, + k7zIdFolder, + k7zIdCodersUnpackSize, + k7zIdNumUnpackStream, + k7zIdEmptyStream, + k7zIdEmptyFile, + k7zIdAnti, + k7zIdName, + k7zIdCTime, + k7zIdATime, + k7zIdMTime, + k7zIdWinAttributes, + k7zIdComment, + k7zIdEncodedHeader, + k7zIdStartPos, + k7zIdDummy +}; + +typedef struct +{ + UInt32 NumInStreams; + UInt32 NumOutStreams; + UInt64 MethodID; + CBuf Props; +} CSzCoderInfo; + +void SzCoderInfo_Init(CSzCoderInfo *p); +void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); + +typedef struct +{ + UInt32 InIndex; + UInt32 OutIndex; +} CSzBindPair; + +typedef struct +{ + CSzCoderInfo *Coders; + CSzBindPair *BindPairs; + UInt32 *PackStreams; + UInt64 *UnpackSizes; + UInt32 NumCoders; + UInt32 NumBindPairs; + UInt32 NumPackStreams; + int UnpackCRCDefined; + UInt32 UnpackCRC; + + UInt32 NumUnpackStreams; +} CSzFolder; + +void SzFolder_Init(CSzFolder *p); +UInt64 SzFolder_GetUnpackSize(CSzFolder *p); +int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); +UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); +UInt64 SzFolder_GetUnpackSize(CSzFolder *p); + +SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, + ILookInStream *stream, UInt64 startPos, + Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); + +typedef struct +{ + UInt32 Low; + UInt32 High; +} CNtfsFileTime; + +typedef struct +{ + CNtfsFileTime MTime; + UInt64 Size; + UInt32 Crc; + UInt32 Attrib; + Byte HasStream; + Byte IsDir; + Byte IsAnti; + Byte CrcDefined; + Byte MTimeDefined; + Byte AttribDefined; +} CSzFileItem; + +void SzFile_Init(CSzFileItem *p); + +typedef struct +{ + UInt64 *PackSizes; + Byte *PackCRCsDefined; + UInt32 *PackCRCs; + CSzFolder *Folders; + CSzFileItem *Files; + UInt32 NumPackStreams; + UInt32 NumFolders; + UInt32 NumFiles; +} CSzAr; + +void SzAr_Init(CSzAr *p); +void SzAr_Free(CSzAr *p, ISzAlloc *alloc); + + +/* + SzExtract extracts file from archive + + *outBuffer must be 0 before first call for each new archive. + + Extracting cache: + If you need to decompress more than one file, you can send + these values from previous call: + *blockIndex, + *outBuffer, + *outBufferSize + You can consider "*outBuffer" as cache of solid block. If your archive is solid, + it will increase decompression speed. + + If you use external function, you can declare these 3 cache variables + (blockIndex, outBuffer, outBufferSize) as static in that external function. + + Free *outBuffer and set *outBuffer to 0, if you want to flush cache. +*/ + +typedef struct +{ + CSzAr db; + + UInt64 startPosAfterHeader; + UInt64 dataPos; + + UInt32 *FolderStartPackStreamIndex; + UInt64 *PackStreamStartPositions; + UInt32 *FolderStartFileIndex; + UInt32 *FileIndexToFolderIndexMap; + + size_t *FileNameOffsets; /* in 2-byte steps */ + CBuf FileNames; /* UTF-16-LE */ +} CSzArEx; + +void SzArEx_Init(CSzArEx *p); +void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); +UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); +int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); + +/* +if dest == NULL, the return value specifies the required size of the buffer, + in 16-bit characters, including the null-terminating character. +if dest != NULL, the return value specifies the number of 16-bit characters that + are written to the dest, including the null-terminating character. */ + +size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest); + +SRes SzArEx_Extract( + const CSzArEx *db, + ILookInStream *inStream, + UInt32 fileIndex, /* index of file */ + UInt32 *blockIndex, /* index of solid block */ + Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ + size_t *outBufferSize, /* buffer size for output buffer */ + size_t *offset, /* offset of stream for required file in *outBuffer */ + size_t *outSizeProcessed, /* size of file in *outBuffer */ + ISzAlloc *allocMain, + ISzAlloc *allocTemp); + + +/* +SzArEx_Open Errors: +SZ_ERROR_NO_ARCHIVE +SZ_ERROR_ARCHIVE +SZ_ERROR_UNSUPPORTED +SZ_ERROR_MEM +SZ_ERROR_CRC +SZ_ERROR_INPUT_EOF +SZ_ERROR_FAIL +*/ + +SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); + +EXTERN_C_END + +#endif diff --git a/Installer/lzma/7zAlloc.c b/Installer/lzma/7zAlloc.c index 8874496d..964b28db 100644 --- a/Installer/lzma/7zAlloc.c +++ b/Installer/lzma/7zAlloc.c @@ -1,76 +1,76 @@ -/* 7zAlloc.c -- Allocation functions -2010-10-29 : Igor Pavlov : Public domain */ - -#include "7zAlloc.h" - -/* #define _SZ_ALLOC_DEBUG */ -/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ - -#ifdef _SZ_ALLOC_DEBUG - -#ifdef _WIN32 -#include -#endif - -#include -int g_allocCount = 0; -int g_allocCountTemp = 0; - -#endif - -void *SzAlloc(void *p, size_t size) -{ - p = p; - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); - g_allocCount++; - #endif - return malloc(size); -} - -void SzFree(void *p, void *address) -{ - p = p; - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - { - g_allocCount--; - fprintf(stderr, "\nFree; count = %10d", g_allocCount); - } - #endif - free(address); -} - -void *SzAllocTemp(void *p, size_t size) -{ - p = p; - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); - g_allocCountTemp++; - #ifdef _WIN32 - return HeapAlloc(GetProcessHeap(), 0, size); - #endif - #endif - return malloc(size); -} - -void SzFreeTemp(void *p, void *address) -{ - p = p; - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - { - g_allocCountTemp--; - fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); - } - #ifdef _WIN32 - HeapFree(GetProcessHeap(), 0, address); - return; - #endif - #endif - free(address); -} +/* 7zAlloc.c -- Allocation functions +2010-10-29 : Igor Pavlov : Public domain */ + +#include "7zAlloc.h" + +/* #define _SZ_ALLOC_DEBUG */ +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ + +#ifdef _SZ_ALLOC_DEBUG + +#ifdef _WIN32 +#include +#endif + +#include +int g_allocCount = 0; +int g_allocCountTemp = 0; + +#endif + +void *SzAlloc(void *p, size_t size) +{ + p = p; + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); + g_allocCount++; + #endif + return malloc(size); +} + +void SzFree(void *p, void *address) +{ + p = p; + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + { + g_allocCount--; + fprintf(stderr, "\nFree; count = %10d", g_allocCount); + } + #endif + free(address); +} + +void *SzAllocTemp(void *p, size_t size) +{ + p = p; + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); + g_allocCountTemp++; + #ifdef _WIN32 + return HeapAlloc(GetProcessHeap(), 0, size); + #endif + #endif + return malloc(size); +} + +void SzFreeTemp(void *p, void *address) +{ + p = p; + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + { + g_allocCountTemp--; + fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); + } + #ifdef _WIN32 + HeapFree(GetProcessHeap(), 0, address); + return; + #endif + #endif + free(address); +} diff --git a/Installer/lzma/7zAlloc.h b/Installer/lzma/7zAlloc.h index 860f116a..3344e937 100644 --- a/Installer/lzma/7zAlloc.h +++ b/Installer/lzma/7zAlloc.h @@ -1,15 +1,15 @@ -/* 7zAlloc.h -- Allocation functions -2010-10-29 : Igor Pavlov : Public domain */ - -#ifndef __7Z_ALLOC_H -#define __7Z_ALLOC_H - -#include - -void *SzAlloc(void *p, size_t size); -void SzFree(void *p, void *address); - -void *SzAllocTemp(void *p, size_t size); -void SzFreeTemp(void *p, void *address); - -#endif +/* 7zAlloc.h -- Allocation functions +2010-10-29 : Igor Pavlov : Public domain */ + +#ifndef __7Z_ALLOC_H +#define __7Z_ALLOC_H + +#include + +void *SzAlloc(void *p, size_t size); +void SzFree(void *p, void *address); + +void *SzAllocTemp(void *p, size_t size); +void SzFreeTemp(void *p, void *address); + +#endif diff --git a/Installer/lzma/7zBuf.c b/Installer/lzma/7zBuf.c index a35fa2f9..14e7f4e2 100644 --- a/Installer/lzma/7zBuf.c +++ b/Installer/lzma/7zBuf.c @@ -1,36 +1,36 @@ -/* 7zBuf.c -- Byte Buffer -2008-03-28 -Igor Pavlov -Public domain */ - -#include "7zBuf.h" - -void Buf_Init(CBuf *p) -{ - p->data = 0; - p->size = 0; -} - -int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc) -{ - p->size = 0; - if (size == 0) - { - p->data = 0; - return 1; - } - p->data = (Byte *)alloc->Alloc(alloc, size); - if (p->data != 0) - { - p->size = size; - return 1; - } - return 0; -} - -void Buf_Free(CBuf *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->data); - p->data = 0; - p->size = 0; -} +/* 7zBuf.c -- Byte Buffer +2008-03-28 +Igor Pavlov +Public domain */ + +#include "7zBuf.h" + +void Buf_Init(CBuf *p) +{ + p->data = 0; + p->size = 0; +} + +int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc) +{ + p->size = 0; + if (size == 0) + { + p->data = 0; + return 1; + } + p->data = (Byte *)alloc->Alloc(alloc, size); + if (p->data != 0) + { + p->size = size; + return 1; + } + return 0; +} + +void Buf_Free(CBuf *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->data); + p->data = 0; + p->size = 0; +} diff --git a/Installer/lzma/7zBuf.h b/Installer/lzma/7zBuf.h index 88ff0c2f..e9f2f316 100644 --- a/Installer/lzma/7zBuf.h +++ b/Installer/lzma/7zBuf.h @@ -1,39 +1,39 @@ -/* 7zBuf.h -- Byte Buffer -2009-02-07 : Igor Pavlov : Public domain */ - -#ifndef __7Z_BUF_H -#define __7Z_BUF_H - -#include "Types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct -{ - Byte *data; - size_t size; -} CBuf; - -void Buf_Init(CBuf *p); -int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); -void Buf_Free(CBuf *p, ISzAlloc *alloc); - -typedef struct -{ - Byte *data; - size_t size; - size_t pos; -} CDynBuf; - -void DynBuf_Construct(CDynBuf *p); -void DynBuf_SeekToBeg(CDynBuf *p); -int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); -void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); - -#ifdef __cplusplus -} -#endif - -#endif +/* 7zBuf.h -- Byte Buffer +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __7Z_BUF_H +#define __7Z_BUF_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + Byte *data; + size_t size; +} CBuf; + +void Buf_Init(CBuf *p); +int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); +void Buf_Free(CBuf *p, ISzAlloc *alloc); + +typedef struct +{ + Byte *data; + size_t size; + size_t pos; +} CDynBuf; + +void DynBuf_Construct(CDynBuf *p); +void DynBuf_SeekToBeg(CDynBuf *p); +int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); +void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Installer/lzma/7zCrc.c b/Installer/lzma/7zCrc.c index 5801dabf..a9208496 100644 --- a/Installer/lzma/7zCrc.c +++ b/Installer/lzma/7zCrc.c @@ -1,74 +1,74 @@ -/* 7zCrc.c -- CRC32 calculation -2009-11-23 : Igor Pavlov : Public domain */ - -#include "7zCrc.h" -#include "CpuArch.h" - -#define kCrcPoly 0xEDB88320 - -#ifdef MY_CPU_LE -#define CRC_NUM_TABLES 8 -#else -#define CRC_NUM_TABLES 1 -#endif - -typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); - -static CRC_FUNC g_CrcUpdate; -UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; - -#if CRC_NUM_TABLES == 1 - -#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) - -static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) -{ - const Byte *p = (const Byte *)data; - for (; size > 0; size--, p++) - v = CRC_UPDATE_BYTE_2(v, *p); - return v; -} - -#else - -UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); -UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); - -#endif - -UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) -{ - return g_CrcUpdate(v, data, size, g_CrcTable); -} - -UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) -{ - return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL; -} - -void MY_FAST_CALL CrcGenerateTable() -{ - UInt32 i; - for (i = 0; i < 256; i++) - { - UInt32 r = i; - unsigned j; - for (j = 0; j < 8; j++) - r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); - g_CrcTable[i] = r; - } - #if CRC_NUM_TABLES == 1 - g_CrcUpdate = CrcUpdateT1; - #else - for (; i < 256 * CRC_NUM_TABLES; i++) - { - UInt32 r = g_CrcTable[i - 256]; - g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); - } - g_CrcUpdate = CrcUpdateT4; - #ifdef MY_CPU_X86_OR_AMD64 - if (!CPU_Is_InOrder()) - g_CrcUpdate = CrcUpdateT8; - #endif - #endif -} +/* 7zCrc.c -- CRC32 calculation +2009-11-23 : Igor Pavlov : Public domain */ + +#include "7zCrc.h" +#include "CpuArch.h" + +#define kCrcPoly 0xEDB88320 + +#ifdef MY_CPU_LE +#define CRC_NUM_TABLES 8 +#else +#define CRC_NUM_TABLES 1 +#endif + +typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); + +static CRC_FUNC g_CrcUpdate; +UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; + +#if CRC_NUM_TABLES == 1 + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#else + +UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); +UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); + +#endif + +UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) +{ + return g_CrcUpdate(v, data, size, g_CrcTable); +} + +UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) +{ + return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL; +} + +void MY_FAST_CALL CrcGenerateTable() +{ + UInt32 i; + for (i = 0; i < 256; i++) + { + UInt32 r = i; + unsigned j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); + g_CrcTable[i] = r; + } + #if CRC_NUM_TABLES == 1 + g_CrcUpdate = CrcUpdateT1; + #else + for (; i < 256 * CRC_NUM_TABLES; i++) + { + UInt32 r = g_CrcTable[i - 256]; + g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); + } + g_CrcUpdate = CrcUpdateT4; + #ifdef MY_CPU_X86_OR_AMD64 + if (!CPU_Is_InOrder()) + g_CrcUpdate = CrcUpdateT8; + #endif + #endif +} diff --git a/Installer/lzma/7zCrc.h b/Installer/lzma/7zCrc.h index 4a1ec38c..38e3e5fb 100644 --- a/Installer/lzma/7zCrc.h +++ b/Installer/lzma/7zCrc.h @@ -1,25 +1,25 @@ -/* 7zCrc.h -- CRC32 calculation -2009-11-21 : Igor Pavlov : Public domain */ - -#ifndef __7Z_CRC_H -#define __7Z_CRC_H - -#include "Types.h" - -EXTERN_C_BEGIN - -extern UInt32 g_CrcTable[]; - -/* Call CrcGenerateTable one time before other CRC functions */ -void MY_FAST_CALL CrcGenerateTable(void); - -#define CRC_INIT_VAL 0xFFFFFFFF -#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL) -#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) - -UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); -UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); - -EXTERN_C_END - -#endif +/* 7zCrc.h -- CRC32 calculation +2009-11-21 : Igor Pavlov : Public domain */ + +#ifndef __7Z_CRC_H +#define __7Z_CRC_H + +#include "Types.h" + +EXTERN_C_BEGIN + +extern UInt32 g_CrcTable[]; + +/* Call CrcGenerateTable one time before other CRC functions */ +void MY_FAST_CALL CrcGenerateTable(void); + +#define CRC_INIT_VAL 0xFFFFFFFF +#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL) +#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); +UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); + +EXTERN_C_END + +#endif diff --git a/Installer/lzma/7zCrcOpt.c b/Installer/lzma/7zCrcOpt.c index 6205d716..6c766a20 100644 --- a/Installer/lzma/7zCrcOpt.c +++ b/Installer/lzma/7zCrcOpt.c @@ -1,34 +1,34 @@ -/* 7zCrcOpt.c -- CRC32 calculation : optimized version -2009-11-23 : Igor Pavlov : Public domain */ - -#include "CpuArch.h" - -#ifdef MY_CPU_LE - -#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) - -UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) -{ - const Byte *p = (const Byte *)data; - for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) - v = CRC_UPDATE_BYTE_2(v, *p); - for (; size >= 4; size -= 4, p += 4) - { - v ^= *(const UInt32 *)p; - v = - table[0x300 + (v & 0xFF)] ^ - table[0x200 + ((v >> 8) & 0xFF)] ^ - table[0x100 + ((v >> 16) & 0xFF)] ^ - table[0x000 + ((v >> 24))]; - } - for (; size > 0; size--, p++) - v = CRC_UPDATE_BYTE_2(v, *p); - return v; -} - -UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table) -{ - return CrcUpdateT4(v, data, size, table); -} - -#endif +/* 7zCrcOpt.c -- CRC32 calculation : optimized version +2009-11-23 : Igor Pavlov : Public domain */ + +#include "CpuArch.h" + +#ifdef MY_CPU_LE + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + v ^= *(const UInt32 *)p; + v = + table[0x300 + (v & 0xFF)] ^ + table[0x200 + ((v >> 8) & 0xFF)] ^ + table[0x100 + ((v >> 16) & 0xFF)] ^ + table[0x000 + ((v >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + return CrcUpdateT4(v, data, size, table); +} + +#endif diff --git a/Installer/lzma/7zDec.c b/Installer/lzma/7zDec.c index 73389d03..f0b77457 100644 --- a/Installer/lzma/7zDec.c +++ b/Installer/lzma/7zDec.c @@ -1,481 +1,481 @@ -/* 7zDec.c -- Decoding from 7z folder -2010-11-02 : Igor Pavlov : Public domain */ - -#include - -/* #define _7ZIP_PPMD_SUPPPORT */ - -#include "7z.h" - -#include "Bcj2.h" -#include "Bra.h" -#include "CpuArch.h" -#include "LzmaDec.h" -#ifdef _7ZIP_LZMA2_SUPPPORT -#include "Lzma2Dec.h" -#endif -#ifdef _7ZIP_PPMD_SUPPPORT -#include "Ppmd7.h" -#endif - -#define k_Copy 0 -#define k_LZMA2 0x21 -#define k_LZMA 0x30101 -#define k_BCJ 0x03030103 -#define k_PPC 0x03030205 -#define k_ARM 0x03030501 -#define k_ARMT 0x03030701 -#define k_SPARC 0x03030805 -#define k_BCJ2 0x0303011B - -#ifdef _7ZIP_PPMD_SUPPPORT - -#define k_PPMD 0x30401 - -typedef struct -{ - IByteIn p; - const Byte *cur; - const Byte *end; - const Byte *begin; - UInt64 processed; - Bool extra; - SRes res; - ILookInStream *inStream; -} CByteInToLook; - -static Byte ReadByte(void *pp) -{ - CByteInToLook *p = (CByteInToLook *)pp; - if (p->cur != p->end) - return *p->cur++; - if (p->res == SZ_OK) - { - size_t size = p->cur - p->begin; - p->processed += size; - p->res = p->inStream->Skip(p->inStream, size); - size = (1 << 25); - p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size); - p->cur = p->begin; - p->end = p->begin + size; - if (size != 0) - return *p->cur++;; - } - p->extra = True; - return 0; -} - -static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, - Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) -{ - CPpmd7 ppmd; - CByteInToLook s; - SRes res = SZ_OK; - - s.p.Read = ReadByte; - s.inStream = inStream; - s.begin = s.end = s.cur = NULL; - s.extra = False; - s.res = SZ_OK; - s.processed = 0; - - if (coder->Props.size != 5) - return SZ_ERROR_UNSUPPORTED; - - { - unsigned order = coder->Props.data[0]; - UInt32 memSize = GetUi32(coder->Props.data + 1); - if (order < PPMD7_MIN_ORDER || - order > PPMD7_MAX_ORDER || - memSize < PPMD7_MIN_MEM_SIZE || - memSize > PPMD7_MAX_MEM_SIZE) - return SZ_ERROR_UNSUPPORTED; - Ppmd7_Construct(&ppmd); - if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) - return SZ_ERROR_MEM; - Ppmd7_Init(&ppmd, order); - } - { - CPpmd7z_RangeDec rc; - Ppmd7z_RangeDec_CreateVTable(&rc); - rc.Stream = &s.p; - if (!Ppmd7z_RangeDec_Init(&rc)) - res = SZ_ERROR_DATA; - else if (s.extra) - res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); - else - { - SizeT i; - for (i = 0; i < outSize; i++) - { - int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p); - if (s.extra || sym < 0) - break; - outBuffer[i] = (Byte)sym; - } - if (i != outSize) - res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); - else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) - res = SZ_ERROR_DATA; - } - } - Ppmd7_Free(&ppmd, allocMain); - return res; -} - -#endif - -static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, - Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) -{ - CLzmaDec state; - SRes res = SZ_OK; - - LzmaDec_Construct(&state); - RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); - state.dic = outBuffer; - state.dicBufSize = outSize; - LzmaDec_Init(&state); - - for (;;) - { - Byte *inBuf = NULL; - size_t lookahead = (1 << 18); - if (lookahead > inSize) - lookahead = (size_t)inSize; - res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); - if (res != SZ_OK) - break; - - { - SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; - ELzmaStatus status; - res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); - lookahead -= inProcessed; - inSize -= inProcessed; - if (res != SZ_OK) - break; - if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) - { - if (state.dicBufSize != outSize || lookahead != 0 || - (status != LZMA_STATUS_FINISHED_WITH_MARK && - status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) - res = SZ_ERROR_DATA; - break; - } - res = inStream->Skip((void *)inStream, inProcessed); - if (res != SZ_OK) - break; - } - } - - LzmaDec_FreeProbs(&state, allocMain); - return res; -} - -#ifdef _7ZIP_LZMA2_SUPPPORT - -static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, - Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) -{ - CLzma2Dec state; - SRes res = SZ_OK; - - Lzma2Dec_Construct(&state); - if (coder->Props.size != 1) - return SZ_ERROR_DATA; - RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain)); - state.decoder.dic = outBuffer; - state.decoder.dicBufSize = outSize; - Lzma2Dec_Init(&state); - - for (;;) - { - Byte *inBuf = NULL; - size_t lookahead = (1 << 18); - if (lookahead > inSize) - lookahead = (size_t)inSize; - res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); - if (res != SZ_OK) - break; - - { - SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; - ELzmaStatus status; - res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); - lookahead -= inProcessed; - inSize -= inProcessed; - if (res != SZ_OK) - break; - if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos)) - { - if (state.decoder.dicBufSize != outSize || lookahead != 0 || - (status != LZMA_STATUS_FINISHED_WITH_MARK)) - res = SZ_ERROR_DATA; - break; - } - res = inStream->Skip((void *)inStream, inProcessed); - if (res != SZ_OK) - break; - } - } - - Lzma2Dec_FreeProbs(&state, allocMain); - return res; -} - -#endif - -static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) -{ - while (inSize > 0) - { - void *inBuf; - size_t curSize = (1 << 18); - if (curSize > inSize) - curSize = (size_t)inSize; - RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize)); - if (curSize == 0) - return SZ_ERROR_INPUT_EOF; - memcpy(outBuffer, inBuf, curSize); - outBuffer += curSize; - inSize -= curSize; - RINOK(inStream->Skip((void *)inStream, curSize)); - } - return SZ_OK; -} - -static Bool IS_MAIN_METHOD(UInt32 m) -{ - switch(m) - { - case k_Copy: - case k_LZMA: - #ifdef _7ZIP_LZMA2_SUPPPORT - case k_LZMA2: - #endif - #ifdef _7ZIP_PPMD_SUPPPORT - case k_PPMD: - #endif - return True; - } - return False; -} - -static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) -{ - return - c->NumInStreams == 1 && - c->NumOutStreams == 1 && - c->MethodID <= (UInt32)0xFFFFFFFF && - IS_MAIN_METHOD((UInt32)c->MethodID); -} - -#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1) - -static SRes CheckSupportedFolder(const CSzFolder *f) -{ - if (f->NumCoders < 1 || f->NumCoders > 4) - return SZ_ERROR_UNSUPPORTED; - if (!IS_SUPPORTED_CODER(&f->Coders[0])) - return SZ_ERROR_UNSUPPORTED; - if (f->NumCoders == 1) - { - if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) - return SZ_ERROR_UNSUPPORTED; - return SZ_OK; - } - if (f->NumCoders == 2) - { - CSzCoderInfo *c = &f->Coders[1]; - if (c->MethodID > (UInt32)0xFFFFFFFF || - c->NumInStreams != 1 || - c->NumOutStreams != 1 || - f->NumPackStreams != 1 || - f->PackStreams[0] != 0 || - f->NumBindPairs != 1 || - f->BindPairs[0].InIndex != 1 || - f->BindPairs[0].OutIndex != 0) - return SZ_ERROR_UNSUPPORTED; - switch ((UInt32)c->MethodID) - { - case k_BCJ: - case k_ARM: - break; - default: - return SZ_ERROR_UNSUPPORTED; - } - return SZ_OK; - } - if (f->NumCoders == 4) - { - if (!IS_SUPPORTED_CODER(&f->Coders[1]) || - !IS_SUPPORTED_CODER(&f->Coders[2]) || - !IS_BCJ2(&f->Coders[3])) - return SZ_ERROR_UNSUPPORTED; - if (f->NumPackStreams != 4 || - f->PackStreams[0] != 2 || - f->PackStreams[1] != 6 || - f->PackStreams[2] != 1 || - f->PackStreams[3] != 0 || - f->NumBindPairs != 3 || - f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || - f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || - f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) - return SZ_ERROR_UNSUPPORTED; - return SZ_OK; - } - return SZ_ERROR_UNSUPPORTED; -} - -static UInt64 GetSum(const UInt64 *values, UInt32 index) -{ - UInt64 sum = 0; - UInt32 i; - for (i = 0; i < index; i++) - sum += values[i]; - return sum; -} - -#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; - -static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, - ILookInStream *inStream, UInt64 startPos, - Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, - Byte *tempBuf[]) -{ - UInt32 ci; - SizeT tempSizes[3] = { 0, 0, 0}; - SizeT tempSize3 = 0; - Byte *tempBuf3 = 0; - - RINOK(CheckSupportedFolder(folder)); - - for (ci = 0; ci < folder->NumCoders; ci++) - { - CSzCoderInfo *coder = &folder->Coders[ci]; - - if (IS_MAIN_METHOD((UInt32)coder->MethodID)) - { - UInt32 si = 0; - UInt64 offset; - UInt64 inSize; - Byte *outBufCur = outBuffer; - SizeT outSizeCur = outSize; - if (folder->NumCoders == 4) - { - UInt32 indices[] = { 3, 2, 0 }; - UInt64 unpackSize = folder->UnpackSizes[ci]; - si = indices[ci]; - if (ci < 2) - { - Byte *temp; - outSizeCur = (SizeT)unpackSize; - if (outSizeCur != unpackSize) - return SZ_ERROR_MEM; - temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); - if (temp == 0 && outSizeCur != 0) - return SZ_ERROR_MEM; - outBufCur = tempBuf[1 - ci] = temp; - tempSizes[1 - ci] = outSizeCur; - } - else if (ci == 2) - { - if (unpackSize > outSize) /* check it */ - return SZ_ERROR_PARAM; - tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); - tempSize3 = outSizeCur = (SizeT)unpackSize; - } - else - return SZ_ERROR_UNSUPPORTED; - } - offset = GetSum(packSizes, si); - inSize = packSizes[si]; - RINOK(LookInStream_SeekTo(inStream, startPos + offset)); - - if (coder->MethodID == k_Copy) - { - if (inSize != outSizeCur) /* check it */ - return SZ_ERROR_DATA; - RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); - } - else if (coder->MethodID == k_LZMA) - { - RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); - } - else if (coder->MethodID == k_LZMA2) - { - #ifdef _7ZIP_LZMA2_SUPPPORT - RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); - #else - return SZ_ERROR_UNSUPPORTED; - #endif - } - else - { - #ifdef _7ZIP_PPMD_SUPPPORT - RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); - #else - return SZ_ERROR_UNSUPPORTED; - #endif - } - } - else if (coder->MethodID == k_BCJ2) - { - UInt64 offset = GetSum(packSizes, 1); - UInt64 s3Size = packSizes[1]; - SRes res; - if (ci != 3) - return SZ_ERROR_UNSUPPORTED; - RINOK(LookInStream_SeekTo(inStream, startPos + offset)); - tempSizes[2] = (SizeT)s3Size; - if (tempSizes[2] != s3Size) - return SZ_ERROR_MEM; - tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); - if (tempBuf[2] == 0 && tempSizes[2] != 0) - return SZ_ERROR_MEM; - res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); - RINOK(res) - - res = Bcj2_Decode( - tempBuf3, tempSize3, - tempBuf[0], tempSizes[0], - tempBuf[1], tempSizes[1], - tempBuf[2], tempSizes[2], - outBuffer, outSize); - RINOK(res) - } - else - { - if (ci != 1) - return SZ_ERROR_UNSUPPORTED; - switch(coder->MethodID) - { - case k_BCJ: - { - UInt32 state; - x86_Convert_Init(state); - x86_Convert(outBuffer, outSize, 0, &state, 0); - break; - } - CASE_BRA_CONV(ARM) - default: - return SZ_ERROR_UNSUPPORTED; - } - } - } - return SZ_OK; -} - -SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, - ILookInStream *inStream, UInt64 startPos, - Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) -{ - Byte *tempBuf[3] = { 0, 0, 0}; - int i; - SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos, - outBuffer, (SizeT)outSize, allocMain, tempBuf); - for (i = 0; i < 3; i++) - IAlloc_Free(allocMain, tempBuf[i]); - return res; -} +/* 7zDec.c -- Decoding from 7z folder +2010-11-02 : Igor Pavlov : Public domain */ + +#include + +/* #define _7ZIP_PPMD_SUPPPORT */ + +#include "7z.h" + +#include "Bcj2.h" +#include "Bra.h" +#include "CpuArch.h" +#include "LzmaDec.h" +#ifdef _7ZIP_LZMA2_SUPPPORT +#include "Lzma2Dec.h" +#endif +#ifdef _7ZIP_PPMD_SUPPPORT +#include "Ppmd7.h" +#endif + +#define k_Copy 0 +#define k_LZMA2 0x21 +#define k_LZMA 0x30101 +#define k_BCJ 0x03030103 +#define k_PPC 0x03030205 +#define k_ARM 0x03030501 +#define k_ARMT 0x03030701 +#define k_SPARC 0x03030805 +#define k_BCJ2 0x0303011B + +#ifdef _7ZIP_PPMD_SUPPPORT + +#define k_PPMD 0x30401 + +typedef struct +{ + IByteIn p; + const Byte *cur; + const Byte *end; + const Byte *begin; + UInt64 processed; + Bool extra; + SRes res; + ILookInStream *inStream; +} CByteInToLook; + +static Byte ReadByte(void *pp) +{ + CByteInToLook *p = (CByteInToLook *)pp; + if (p->cur != p->end) + return *p->cur++; + if (p->res == SZ_OK) + { + size_t size = p->cur - p->begin; + p->processed += size; + p->res = p->inStream->Skip(p->inStream, size); + size = (1 << 25); + p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size); + p->cur = p->begin; + p->end = p->begin + size; + if (size != 0) + return *p->cur++;; + } + p->extra = True; + return 0; +} + +static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) +{ + CPpmd7 ppmd; + CByteInToLook s; + SRes res = SZ_OK; + + s.p.Read = ReadByte; + s.inStream = inStream; + s.begin = s.end = s.cur = NULL; + s.extra = False; + s.res = SZ_OK; + s.processed = 0; + + if (coder->Props.size != 5) + return SZ_ERROR_UNSUPPORTED; + + { + unsigned order = coder->Props.data[0]; + UInt32 memSize = GetUi32(coder->Props.data + 1); + if (order < PPMD7_MIN_ORDER || + order > PPMD7_MAX_ORDER || + memSize < PPMD7_MIN_MEM_SIZE || + memSize > PPMD7_MAX_MEM_SIZE) + return SZ_ERROR_UNSUPPORTED; + Ppmd7_Construct(&ppmd); + if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) + return SZ_ERROR_MEM; + Ppmd7_Init(&ppmd, order); + } + { + CPpmd7z_RangeDec rc; + Ppmd7z_RangeDec_CreateVTable(&rc); + rc.Stream = &s.p; + if (!Ppmd7z_RangeDec_Init(&rc)) + res = SZ_ERROR_DATA; + else if (s.extra) + res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); + else + { + SizeT i; + for (i = 0; i < outSize; i++) + { + int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p); + if (s.extra || sym < 0) + break; + outBuffer[i] = (Byte)sym; + } + if (i != outSize) + res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); + else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) + res = SZ_ERROR_DATA; + } + } + Ppmd7_Free(&ppmd, allocMain); + return res; +} + +#endif + +static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) +{ + CLzmaDec state; + SRes res = SZ_OK; + + LzmaDec_Construct(&state); + RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); + state.dic = outBuffer; + state.dicBufSize = outSize; + LzmaDec_Init(&state); + + for (;;) + { + Byte *inBuf = NULL; + size_t lookahead = (1 << 18); + if (lookahead > inSize) + lookahead = (size_t)inSize; + res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); + if (res != SZ_OK) + break; + + { + SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; + ELzmaStatus status; + res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); + lookahead -= inProcessed; + inSize -= inProcessed; + if (res != SZ_OK) + break; + if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) + { + if (state.dicBufSize != outSize || lookahead != 0 || + (status != LZMA_STATUS_FINISHED_WITH_MARK && + status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) + res = SZ_ERROR_DATA; + break; + } + res = inStream->Skip((void *)inStream, inProcessed); + if (res != SZ_OK) + break; + } + } + + LzmaDec_FreeProbs(&state, allocMain); + return res; +} + +#ifdef _7ZIP_LZMA2_SUPPPORT + +static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) +{ + CLzma2Dec state; + SRes res = SZ_OK; + + Lzma2Dec_Construct(&state); + if (coder->Props.size != 1) + return SZ_ERROR_DATA; + RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain)); + state.decoder.dic = outBuffer; + state.decoder.dicBufSize = outSize; + Lzma2Dec_Init(&state); + + for (;;) + { + Byte *inBuf = NULL; + size_t lookahead = (1 << 18); + if (lookahead > inSize) + lookahead = (size_t)inSize; + res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); + if (res != SZ_OK) + break; + + { + SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; + ELzmaStatus status; + res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); + lookahead -= inProcessed; + inSize -= inProcessed; + if (res != SZ_OK) + break; + if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos)) + { + if (state.decoder.dicBufSize != outSize || lookahead != 0 || + (status != LZMA_STATUS_FINISHED_WITH_MARK)) + res = SZ_ERROR_DATA; + break; + } + res = inStream->Skip((void *)inStream, inProcessed); + if (res != SZ_OK) + break; + } + } + + Lzma2Dec_FreeProbs(&state, allocMain); + return res; +} + +#endif + +static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) +{ + while (inSize > 0) + { + void *inBuf; + size_t curSize = (1 << 18); + if (curSize > inSize) + curSize = (size_t)inSize; + RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize)); + if (curSize == 0) + return SZ_ERROR_INPUT_EOF; + memcpy(outBuffer, inBuf, curSize); + outBuffer += curSize; + inSize -= curSize; + RINOK(inStream->Skip((void *)inStream, curSize)); + } + return SZ_OK; +} + +static Bool IS_MAIN_METHOD(UInt32 m) +{ + switch(m) + { + case k_Copy: + case k_LZMA: + #ifdef _7ZIP_LZMA2_SUPPPORT + case k_LZMA2: + #endif + #ifdef _7ZIP_PPMD_SUPPPORT + case k_PPMD: + #endif + return True; + } + return False; +} + +static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) +{ + return + c->NumInStreams == 1 && + c->NumOutStreams == 1 && + c->MethodID <= (UInt32)0xFFFFFFFF && + IS_MAIN_METHOD((UInt32)c->MethodID); +} + +#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1) + +static SRes CheckSupportedFolder(const CSzFolder *f) +{ + if (f->NumCoders < 1 || f->NumCoders > 4) + return SZ_ERROR_UNSUPPORTED; + if (!IS_SUPPORTED_CODER(&f->Coders[0])) + return SZ_ERROR_UNSUPPORTED; + if (f->NumCoders == 1) + { + if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) + return SZ_ERROR_UNSUPPORTED; + return SZ_OK; + } + if (f->NumCoders == 2) + { + CSzCoderInfo *c = &f->Coders[1]; + if (c->MethodID > (UInt32)0xFFFFFFFF || + c->NumInStreams != 1 || + c->NumOutStreams != 1 || + f->NumPackStreams != 1 || + f->PackStreams[0] != 0 || + f->NumBindPairs != 1 || + f->BindPairs[0].InIndex != 1 || + f->BindPairs[0].OutIndex != 0) + return SZ_ERROR_UNSUPPORTED; + switch ((UInt32)c->MethodID) + { + case k_BCJ: + case k_ARM: + break; + default: + return SZ_ERROR_UNSUPPORTED; + } + return SZ_OK; + } + if (f->NumCoders == 4) + { + if (!IS_SUPPORTED_CODER(&f->Coders[1]) || + !IS_SUPPORTED_CODER(&f->Coders[2]) || + !IS_BCJ2(&f->Coders[3])) + return SZ_ERROR_UNSUPPORTED; + if (f->NumPackStreams != 4 || + f->PackStreams[0] != 2 || + f->PackStreams[1] != 6 || + f->PackStreams[2] != 1 || + f->PackStreams[3] != 0 || + f->NumBindPairs != 3 || + f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || + f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || + f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) + return SZ_ERROR_UNSUPPORTED; + return SZ_OK; + } + return SZ_ERROR_UNSUPPORTED; +} + +static UInt64 GetSum(const UInt64 *values, UInt32 index) +{ + UInt64 sum = 0; + UInt32 i; + for (i = 0; i < index; i++) + sum += values[i]; + return sum; +} + +#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; + +static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, + ILookInStream *inStream, UInt64 startPos, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, + Byte *tempBuf[]) +{ + UInt32 ci; + SizeT tempSizes[3] = { 0, 0, 0}; + SizeT tempSize3 = 0; + Byte *tempBuf3 = 0; + + RINOK(CheckSupportedFolder(folder)); + + for (ci = 0; ci < folder->NumCoders; ci++) + { + CSzCoderInfo *coder = &folder->Coders[ci]; + + if (IS_MAIN_METHOD((UInt32)coder->MethodID)) + { + UInt32 si = 0; + UInt64 offset; + UInt64 inSize; + Byte *outBufCur = outBuffer; + SizeT outSizeCur = outSize; + if (folder->NumCoders == 4) + { + UInt32 indices[] = { 3, 2, 0 }; + UInt64 unpackSize = folder->UnpackSizes[ci]; + si = indices[ci]; + if (ci < 2) + { + Byte *temp; + outSizeCur = (SizeT)unpackSize; + if (outSizeCur != unpackSize) + return SZ_ERROR_MEM; + temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); + if (temp == 0 && outSizeCur != 0) + return SZ_ERROR_MEM; + outBufCur = tempBuf[1 - ci] = temp; + tempSizes[1 - ci] = outSizeCur; + } + else if (ci == 2) + { + if (unpackSize > outSize) /* check it */ + return SZ_ERROR_PARAM; + tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); + tempSize3 = outSizeCur = (SizeT)unpackSize; + } + else + return SZ_ERROR_UNSUPPORTED; + } + offset = GetSum(packSizes, si); + inSize = packSizes[si]; + RINOK(LookInStream_SeekTo(inStream, startPos + offset)); + + if (coder->MethodID == k_Copy) + { + if (inSize != outSizeCur) /* check it */ + return SZ_ERROR_DATA; + RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); + } + else if (coder->MethodID == k_LZMA) + { + RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } + else if (coder->MethodID == k_LZMA2) + { + #ifdef _7ZIP_LZMA2_SUPPPORT + RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + #else + return SZ_ERROR_UNSUPPORTED; + #endif + } + else + { + #ifdef _7ZIP_PPMD_SUPPPORT + RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + #else + return SZ_ERROR_UNSUPPORTED; + #endif + } + } + else if (coder->MethodID == k_BCJ2) + { + UInt64 offset = GetSum(packSizes, 1); + UInt64 s3Size = packSizes[1]; + SRes res; + if (ci != 3) + return SZ_ERROR_UNSUPPORTED; + RINOK(LookInStream_SeekTo(inStream, startPos + offset)); + tempSizes[2] = (SizeT)s3Size; + if (tempSizes[2] != s3Size) + return SZ_ERROR_MEM; + tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); + if (tempBuf[2] == 0 && tempSizes[2] != 0) + return SZ_ERROR_MEM; + res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); + RINOK(res) + + res = Bcj2_Decode( + tempBuf3, tempSize3, + tempBuf[0], tempSizes[0], + tempBuf[1], tempSizes[1], + tempBuf[2], tempSizes[2], + outBuffer, outSize); + RINOK(res) + } + else + { + if (ci != 1) + return SZ_ERROR_UNSUPPORTED; + switch(coder->MethodID) + { + case k_BCJ: + { + UInt32 state; + x86_Convert_Init(state); + x86_Convert(outBuffer, outSize, 0, &state, 0); + break; + } + CASE_BRA_CONV(ARM) + default: + return SZ_ERROR_UNSUPPORTED; + } + } + } + return SZ_OK; +} + +SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, + ILookInStream *inStream, UInt64 startPos, + Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) +{ + Byte *tempBuf[3] = { 0, 0, 0}; + int i; + SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos, + outBuffer, (SizeT)outSize, allocMain, tempBuf); + for (i = 0; i < 3; i++) + IAlloc_Free(allocMain, tempBuf[i]); + return res; +} diff --git a/Installer/lzma/7zFile.c b/Installer/lzma/7zFile.c index 7960841c..4270cd51 100644 --- a/Installer/lzma/7zFile.c +++ b/Installer/lzma/7zFile.c @@ -1,288 +1,288 @@ -/* 7zFile.c -- File IO -2009-11-24 : Igor Pavlov : Public domain */ - -#include "7zFile.h" - -#ifndef USE_WINDOWS_FILE - -#ifndef UNDER_CE -#include -#endif - -#else - -/* - ReadFile and WriteFile functions in Windows have BUG: - If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) - from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES - (Insufficient system resources exist to complete the requested service). - Probably in some version of Windows there are problems with other sizes: - for 32 MB (maybe also for 16 MB). - And message can be "Network connection was lost" -*/ - -#define kChunkSizeMax (1 << 22) - -#endif - -void File_Construct(CSzFile *p) -{ - #ifdef USE_WINDOWS_FILE - p->handle = INVALID_HANDLE_VALUE; - #else - p->file = NULL; - #endif -} - -#ifndef _UNICODE - -#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) -static WRes File_Open(CSzFile *p, const char *name, int writeMode) -{ - #ifdef USE_WINDOWS_FILE - p->handle = CreateFileA(name, - writeMode ? GENERIC_WRITE : GENERIC_READ, - FILE_SHARE_READ, NULL, - writeMode ? CREATE_ALWAYS : OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); - #else - p->file = fopen(name, writeMode ? "wb+" : "rb"); - return (p->file != 0) ? 0 : - #ifdef UNDER_CE - 2; /* ENOENT */ - #else - errno; - #endif - #endif -} - -WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } -WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); } -#endif - -#endif - -#ifdef USE_WINDOWS_FILE -static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode) -{ - p->handle = CreateFileW(name, - writeMode ? GENERIC_WRITE : GENERIC_READ, - FILE_SHARE_READ, NULL, - writeMode ? CREATE_ALWAYS : OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); -} -WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); } -WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); } -#endif - -WRes File_Close(CSzFile *p) -{ - #ifdef USE_WINDOWS_FILE - if (p->handle != INVALID_HANDLE_VALUE) - { - if (!CloseHandle(p->handle)) - return GetLastError(); - p->handle = INVALID_HANDLE_VALUE; - } - #else - if (p->file != NULL) - { - int res = fclose(p->file); - if (res != 0) - return res; - p->file = NULL; - } - #endif - return 0; -} - -WRes File_Read(CSzFile *p, void *data, size_t *size) -{ - size_t originalSize = *size; - if (originalSize == 0) - return 0; - - #ifdef USE_WINDOWS_FILE - - *size = 0; - do - { - DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; - DWORD processed = 0; - BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); - data = (void *)((Byte *)data + processed); - originalSize -= processed; - *size += processed; - if (!res) - return GetLastError(); - if (processed == 0) - break; - } - while (originalSize > 0); - return 0; - - #else - - *size = fread(data, 1, originalSize, p->file); - if (*size == originalSize) - return 0; - return ferror(p->file); - - #endif -} - -WRes File_Write(CSzFile *p, const void *data, size_t *size) -{ - size_t originalSize = *size; - if (originalSize == 0) - return 0; - - #ifdef USE_WINDOWS_FILE - - *size = 0; - do - { - DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; - DWORD processed = 0; - BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); - data = (void *)((Byte *)data + processed); - originalSize -= processed; - *size += processed; - if (!res) - return GetLastError(); - if (processed == 0) - break; - } - while (originalSize > 0); - return 0; - - #else - - *size = fwrite(data, 1, originalSize, p->file); - if (*size == originalSize) - return 0; - return ferror(p->file); - - #endif -} - -WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) -{ - #ifdef USE_WINDOWS_FILE - - LARGE_INTEGER value; - DWORD moveMethod; - value.LowPart = (DWORD)*pos; - value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ - switch (origin) - { - case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; - case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; - case SZ_SEEK_END: moveMethod = FILE_END; break; - default: return ERROR_INVALID_PARAMETER; - } - value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod); - if (value.LowPart == 0xFFFFFFFF) - { - WRes res = GetLastError(); - if (res != NO_ERROR) - return res; - } - *pos = ((Int64)value.HighPart << 32) | value.LowPart; - return 0; - - #else - - int moveMethod; - int res; - switch (origin) - { - case SZ_SEEK_SET: moveMethod = SEEK_SET; break; - case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; - case SZ_SEEK_END: moveMethod = SEEK_END; break; - default: return 1; - } - res = fseek(p->file, (long)*pos, moveMethod); - *pos = ftell(p->file); - return res; - - #endif -} - -WRes File_GetLength(CSzFile *p, UInt64 *length) -{ - #ifdef USE_WINDOWS_FILE - - DWORD sizeHigh; - DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); - if (sizeLow == 0xFFFFFFFF) - { - DWORD res = GetLastError(); - if (res != NO_ERROR) - return res; - } - *length = (((UInt64)sizeHigh) << 32) + sizeLow; - return 0; - - #else - - long pos = ftell(p->file); - int res = fseek(p->file, 0, SEEK_END); - *length = ftell(p->file); - fseek(p->file, pos, SEEK_SET); - return res; - - #endif -} - - -/* ---------- FileSeqInStream ---------- */ - -static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size) -{ - CFileSeqInStream *p = (CFileSeqInStream *)pp; - return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; -} - -void FileSeqInStream_CreateVTable(CFileSeqInStream *p) -{ - p->s.Read = FileSeqInStream_Read; -} - - -/* ---------- FileInStream ---------- */ - -static SRes FileInStream_Read(void *pp, void *buf, size_t *size) -{ - CFileInStream *p = (CFileInStream *)pp; - return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; -} - -static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) -{ - CFileInStream *p = (CFileInStream *)pp; - return File_Seek(&p->file, pos, origin); -} - -void FileInStream_CreateVTable(CFileInStream *p) -{ - p->s.Read = FileInStream_Read; - p->s.Seek = FileInStream_Seek; -} - - -/* ---------- FileOutStream ---------- */ - -static size_t FileOutStream_Write(void *pp, const void *data, size_t size) -{ - CFileOutStream *p = (CFileOutStream *)pp; - File_Write(&p->file, data, &size); - return size; -} - -void FileOutStream_CreateVTable(CFileOutStream *p) -{ - p->s.Write = FileOutStream_Write; -} +/* 7zFile.c -- File IO +2009-11-24 : Igor Pavlov : Public domain */ + +#include "7zFile.h" + +#ifndef USE_WINDOWS_FILE + +#ifndef UNDER_CE +#include +#endif + +#else + +/* + ReadFile and WriteFile functions in Windows have BUG: + If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) + from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES + (Insufficient system resources exist to complete the requested service). + Probably in some version of Windows there are problems with other sizes: + for 32 MB (maybe also for 16 MB). + And message can be "Network connection was lost" +*/ + +#define kChunkSizeMax (1 << 22) + +#endif + +void File_Construct(CSzFile *p) +{ + #ifdef USE_WINDOWS_FILE + p->handle = INVALID_HANDLE_VALUE; + #else + p->file = NULL; + #endif +} + +#ifndef _UNICODE + +#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) +static WRes File_Open(CSzFile *p, const char *name, int writeMode) +{ + #ifdef USE_WINDOWS_FILE + p->handle = CreateFileA(name, + writeMode ? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ, NULL, + writeMode ? CREATE_ALWAYS : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); + #else + p->file = fopen(name, writeMode ? "wb+" : "rb"); + return (p->file != 0) ? 0 : + #ifdef UNDER_CE + 2; /* ENOENT */ + #else + errno; + #endif + #endif +} + +WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } +WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); } +#endif + +#endif + +#ifdef USE_WINDOWS_FILE +static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode) +{ + p->handle = CreateFileW(name, + writeMode ? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ, NULL, + writeMode ? CREATE_ALWAYS : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); +} +WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); } +WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); } +#endif + +WRes File_Close(CSzFile *p) +{ + #ifdef USE_WINDOWS_FILE + if (p->handle != INVALID_HANDLE_VALUE) + { + if (!CloseHandle(p->handle)) + return GetLastError(); + p->handle = INVALID_HANDLE_VALUE; + } + #else + if (p->file != NULL) + { + int res = fclose(p->file); + if (res != 0) + return res; + p->file = NULL; + } + #endif + return 0; +} + +WRes File_Read(CSzFile *p, void *data, size_t *size) +{ + size_t originalSize = *size; + if (originalSize == 0) + return 0; + + #ifdef USE_WINDOWS_FILE + + *size = 0; + do + { + DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; + DWORD processed = 0; + BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); + data = (void *)((Byte *)data + processed); + originalSize -= processed; + *size += processed; + if (!res) + return GetLastError(); + if (processed == 0) + break; + } + while (originalSize > 0); + return 0; + + #else + + *size = fread(data, 1, originalSize, p->file); + if (*size == originalSize) + return 0; + return ferror(p->file); + + #endif +} + +WRes File_Write(CSzFile *p, const void *data, size_t *size) +{ + size_t originalSize = *size; + if (originalSize == 0) + return 0; + + #ifdef USE_WINDOWS_FILE + + *size = 0; + do + { + DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; + DWORD processed = 0; + BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); + data = (void *)((Byte *)data + processed); + originalSize -= processed; + *size += processed; + if (!res) + return GetLastError(); + if (processed == 0) + break; + } + while (originalSize > 0); + return 0; + + #else + + *size = fwrite(data, 1, originalSize, p->file); + if (*size == originalSize) + return 0; + return ferror(p->file); + + #endif +} + +WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) +{ + #ifdef USE_WINDOWS_FILE + + LARGE_INTEGER value; + DWORD moveMethod; + value.LowPart = (DWORD)*pos; + value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ + switch (origin) + { + case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; + case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; + case SZ_SEEK_END: moveMethod = FILE_END; break; + default: return ERROR_INVALID_PARAMETER; + } + value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod); + if (value.LowPart == 0xFFFFFFFF) + { + WRes res = GetLastError(); + if (res != NO_ERROR) + return res; + } + *pos = ((Int64)value.HighPart << 32) | value.LowPart; + return 0; + + #else + + int moveMethod; + int res; + switch (origin) + { + case SZ_SEEK_SET: moveMethod = SEEK_SET; break; + case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; + case SZ_SEEK_END: moveMethod = SEEK_END; break; + default: return 1; + } + res = fseek(p->file, (long)*pos, moveMethod); + *pos = ftell(p->file); + return res; + + #endif +} + +WRes File_GetLength(CSzFile *p, UInt64 *length) +{ + #ifdef USE_WINDOWS_FILE + + DWORD sizeHigh; + DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); + if (sizeLow == 0xFFFFFFFF) + { + DWORD res = GetLastError(); + if (res != NO_ERROR) + return res; + } + *length = (((UInt64)sizeHigh) << 32) + sizeLow; + return 0; + + #else + + long pos = ftell(p->file); + int res = fseek(p->file, 0, SEEK_END); + *length = ftell(p->file); + fseek(p->file, pos, SEEK_SET); + return res; + + #endif +} + + +/* ---------- FileSeqInStream ---------- */ + +static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size) +{ + CFileSeqInStream *p = (CFileSeqInStream *)pp; + return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; +} + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p) +{ + p->s.Read = FileSeqInStream_Read; +} + + +/* ---------- FileInStream ---------- */ + +static SRes FileInStream_Read(void *pp, void *buf, size_t *size) +{ + CFileInStream *p = (CFileInStream *)pp; + return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; +} + +static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) +{ + CFileInStream *p = (CFileInStream *)pp; + return File_Seek(&p->file, pos, origin); +} + +void FileInStream_CreateVTable(CFileInStream *p) +{ + p->s.Read = FileInStream_Read; + p->s.Seek = FileInStream_Seek; +} + + +/* ---------- FileOutStream ---------- */ + +static size_t FileOutStream_Write(void *pp, const void *data, size_t size) +{ + CFileOutStream *p = (CFileOutStream *)pp; + File_Write(&p->file, data, &size); + return size; +} + +void FileOutStream_CreateVTable(CFileOutStream *p) +{ + p->s.Write = FileOutStream_Write; +} diff --git a/Installer/lzma/7zFile.h b/Installer/lzma/7zFile.h index 5d857879..84538c03 100644 --- a/Installer/lzma/7zFile.h +++ b/Installer/lzma/7zFile.h @@ -1,83 +1,83 @@ -/* 7zFile.h -- File IO -2009-11-24 : Igor Pavlov : Public domain */ - -#ifndef __7Z_FILE_H -#define __7Z_FILE_H - -#ifdef _WIN32 -#define USE_WINDOWS_FILE -#endif - -#ifdef USE_WINDOWS_FILE -#include -#else -#include -#endif - -#include "Types.h" - -EXTERN_C_BEGIN - -/* ---------- File ---------- */ - -typedef struct -{ - #ifdef USE_WINDOWS_FILE - HANDLE handle; - #else - FILE *file; - #endif -} CSzFile; - -void File_Construct(CSzFile *p); -#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) -WRes InFile_Open(CSzFile *p, const char *name); -WRes OutFile_Open(CSzFile *p, const char *name); -#endif -#ifdef USE_WINDOWS_FILE -WRes InFile_OpenW(CSzFile *p, const WCHAR *name); -WRes OutFile_OpenW(CSzFile *p, const WCHAR *name); -#endif -WRes File_Close(CSzFile *p); - -/* reads max(*size, remain file's size) bytes */ -WRes File_Read(CSzFile *p, void *data, size_t *size); - -/* writes *size bytes */ -WRes File_Write(CSzFile *p, const void *data, size_t *size); - -WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); -WRes File_GetLength(CSzFile *p, UInt64 *length); - - -/* ---------- FileInStream ---------- */ - -typedef struct -{ - ISeqInStream s; - CSzFile file; -} CFileSeqInStream; - -void FileSeqInStream_CreateVTable(CFileSeqInStream *p); - - -typedef struct -{ - ISeekInStream s; - CSzFile file; -} CFileInStream; - -void FileInStream_CreateVTable(CFileInStream *p); - - -typedef struct -{ - ISeqOutStream s; - CSzFile file; -} CFileOutStream; - -void FileOutStream_CreateVTable(CFileOutStream *p); - -EXTERN_C_END - -#endif +/* 7zFile.h -- File IO +2009-11-24 : Igor Pavlov : Public domain */ + +#ifndef __7Z_FILE_H +#define __7Z_FILE_H + +#ifdef _WIN32 +#define USE_WINDOWS_FILE +#endif + +#ifdef USE_WINDOWS_FILE +#include +#else +#include +#endif + +#include "Types.h" + +EXTERN_C_BEGIN + +/* ---------- File ---------- */ + +typedef struct +{ + #ifdef USE_WINDOWS_FILE + HANDLE handle; + #else + FILE *file; + #endif +} CSzFile; + +void File_Construct(CSzFile *p); +#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) +WRes InFile_Open(CSzFile *p, const char *name); +WRes OutFile_Open(CSzFile *p, const char *name); +#endif +#ifdef USE_WINDOWS_FILE +WRes InFile_OpenW(CSzFile *p, const WCHAR *name); +WRes OutFile_OpenW(CSzFile *p, const WCHAR *name); +#endif +WRes File_Close(CSzFile *p); + +/* reads max(*size, remain file's size) bytes */ +WRes File_Read(CSzFile *p, void *data, size_t *size); + +/* writes *size bytes */ +WRes File_Write(CSzFile *p, const void *data, size_t *size); + +WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); +WRes File_GetLength(CSzFile *p, UInt64 *length); + + +/* ---------- FileInStream ---------- */ + +typedef struct +{ + ISeqInStream s; + CSzFile file; +} CFileSeqInStream; + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p); + + +typedef struct +{ + ISeekInStream s; + CSzFile file; +} CFileInStream; + +void FileInStream_CreateVTable(CFileInStream *p); + + +typedef struct +{ + ISeqOutStream s; + CSzFile file; +} CFileOutStream; + +void FileOutStream_CreateVTable(CFileOutStream *p); + +EXTERN_C_END + +#endif diff --git a/Installer/lzma/7zIn.c b/Installer/lzma/7zIn.c index f1a44928..ec93a43f 100644 --- a/Installer/lzma/7zIn.c +++ b/Installer/lzma/7zIn.c @@ -1,1402 +1,1402 @@ -/* 7zIn.c -- 7z Input functions -2010-10-29 : Igor Pavlov : Public domain */ - -#include - -#include "7z.h" -#include "7zCrc.h" -#include "CpuArch.h" - -Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; - -#define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; } - -#define NUM_FOLDER_CODERS_MAX 32 -#define NUM_CODER_STREAMS_MAX 32 - -void SzCoderInfo_Init(CSzCoderInfo *p) -{ - Buf_Init(&p->Props); -} - -void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc) -{ - Buf_Free(&p->Props, alloc); - SzCoderInfo_Init(p); -} - -void SzFolder_Init(CSzFolder *p) -{ - p->Coders = 0; - p->BindPairs = 0; - p->PackStreams = 0; - p->UnpackSizes = 0; - p->NumCoders = 0; - p->NumBindPairs = 0; - p->NumPackStreams = 0; - p->UnpackCRCDefined = 0; - p->UnpackCRC = 0; - p->NumUnpackStreams = 0; -} - -void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) -{ - UInt32 i; - if (p->Coders) - for (i = 0; i < p->NumCoders; i++) - SzCoderInfo_Free(&p->Coders[i], alloc); - IAlloc_Free(alloc, p->Coders); - IAlloc_Free(alloc, p->BindPairs); - IAlloc_Free(alloc, p->PackStreams); - IAlloc_Free(alloc, p->UnpackSizes); - SzFolder_Init(p); -} - -UInt32 SzFolder_GetNumOutStreams(CSzFolder *p) -{ - UInt32 result = 0; - UInt32 i; - for (i = 0; i < p->NumCoders; i++) - result += p->Coders[i].NumOutStreams; - return result; -} - -int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex) -{ - UInt32 i; - for (i = 0; i < p->NumBindPairs; i++) - if (p->BindPairs[i].InIndex == inStreamIndex) - return i; - return -1; -} - - -int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex) -{ - UInt32 i; - for (i = 0; i < p->NumBindPairs; i++) - if (p->BindPairs[i].OutIndex == outStreamIndex) - return i; - return -1; -} - -UInt64 SzFolder_GetUnpackSize(CSzFolder *p) -{ - int i = (int)SzFolder_GetNumOutStreams(p); - if (i == 0) - return 0; - for (i--; i >= 0; i--) - if (SzFolder_FindBindPairForOutStream(p, i) < 0) - return p->UnpackSizes[i]; - /* throw 1; */ - return 0; -} - -void SzFile_Init(CSzFileItem *p) -{ - p->HasStream = 1; - p->IsDir = 0; - p->IsAnti = 0; - p->CrcDefined = 0; - p->MTimeDefined = 0; -} - -void SzAr_Init(CSzAr *p) -{ - p->PackSizes = 0; - p->PackCRCsDefined = 0; - p->PackCRCs = 0; - p->Folders = 0; - p->Files = 0; - p->NumPackStreams = 0; - p->NumFolders = 0; - p->NumFiles = 0; -} - -void SzAr_Free(CSzAr *p, ISzAlloc *alloc) -{ - UInt32 i; - if (p->Folders) - for (i = 0; i < p->NumFolders; i++) - SzFolder_Free(&p->Folders[i], alloc); - - IAlloc_Free(alloc, p->PackSizes); - IAlloc_Free(alloc, p->PackCRCsDefined); - IAlloc_Free(alloc, p->PackCRCs); - IAlloc_Free(alloc, p->Folders); - IAlloc_Free(alloc, p->Files); - SzAr_Init(p); -} - - -void SzArEx_Init(CSzArEx *p) -{ - SzAr_Init(&p->db); - p->FolderStartPackStreamIndex = 0; - p->PackStreamStartPositions = 0; - p->FolderStartFileIndex = 0; - p->FileIndexToFolderIndexMap = 0; - p->FileNameOffsets = 0; - Buf_Init(&p->FileNames); -} - -void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) -{ - IAlloc_Free(alloc, p->FolderStartPackStreamIndex); - IAlloc_Free(alloc, p->PackStreamStartPositions); - IAlloc_Free(alloc, p->FolderStartFileIndex); - IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); - - IAlloc_Free(alloc, p->FileNameOffsets); - Buf_Free(&p->FileNames, alloc); - - SzAr_Free(&p->db, alloc); - SzArEx_Init(p); -} - -/* -UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const -{ - return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; -} - -UInt64 GetFilePackSize(int fileIndex) const -{ - int folderIndex = FileIndexToFolderIndexMap[fileIndex]; - if (folderIndex >= 0) - { - const CSzFolder &folderInfo = Folders[folderIndex]; - if (FolderStartFileIndex[folderIndex] == fileIndex) - return GetFolderFullPackSize(folderIndex); - } - return 0; -} -*/ - -#define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \ - if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; } - -static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc) -{ - UInt32 startPos = 0; - UInt64 startPosSize = 0; - UInt32 i; - UInt32 folderIndex = 0; - UInt32 indexInFolder = 0; - MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc); - for (i = 0; i < p->db.NumFolders; i++) - { - p->FolderStartPackStreamIndex[i] = startPos; - startPos += p->db.Folders[i].NumPackStreams; - } - - MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc); - - for (i = 0; i < p->db.NumPackStreams; i++) - { - p->PackStreamStartPositions[i] = startPosSize; - startPosSize += p->db.PackSizes[i]; - } - - MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc); - MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc); - - for (i = 0; i < p->db.NumFiles; i++) - { - CSzFileItem *file = p->db.Files + i; - int emptyStream = !file->HasStream; - if (emptyStream && indexInFolder == 0) - { - p->FileIndexToFolderIndexMap[i] = (UInt32)-1; - continue; - } - if (indexInFolder == 0) - { - /* - v3.13 incorrectly worked with empty folders - v4.07: Loop for skipping empty folders - */ - for (;;) - { - if (folderIndex >= p->db.NumFolders) - return SZ_ERROR_ARCHIVE; - p->FolderStartFileIndex[folderIndex] = i; - if (p->db.Folders[folderIndex].NumUnpackStreams != 0) - break; - folderIndex++; - } - } - p->FileIndexToFolderIndexMap[i] = folderIndex; - if (emptyStream) - continue; - indexInFolder++; - if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams) - { - folderIndex++; - indexInFolder = 0; - } - } - return SZ_OK; -} - - -UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder) -{ - return p->dataPos + - p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; -} - -int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize) -{ - UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex]; - CSzFolder *folder = p->db.Folders + folderIndex; - UInt64 size = 0; - UInt32 i; - for (i = 0; i < folder->NumPackStreams; i++) - { - UInt64 t = size + p->db.PackSizes[packStreamIndex + i]; - if (t < size) /* check it */ - return SZ_ERROR_FAIL; - size = t; - } - *resSize = size; - return SZ_OK; -} - - -/* -SRes SzReadTime(const CObjectVector &dataVector, - CObjectVector &files, UInt64 type) -{ - CBoolVector boolVector; - RINOK(ReadBoolVector2(files.Size(), boolVector)) - - CStreamSwitch streamSwitch; - RINOK(streamSwitch.Set(this, &dataVector)); - - for (int i = 0; i < files.Size(); i++) - { - CSzFileItem &file = files[i]; - CArchiveFileTime fileTime; - bool defined = boolVector[i]; - if (defined) - { - UInt32 low, high; - RINOK(SzReadUInt32(low)); - RINOK(SzReadUInt32(high)); - fileTime.dwLowDateTime = low; - fileTime.dwHighDateTime = high; - } - switch(type) - { - case k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break; - case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break; - case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break; - } - } - return SZ_OK; -} -*/ - -static int TestSignatureCandidate(Byte *testBytes) -{ - size_t i; - for (i = 0; i < k7zSignatureSize; i++) - if (testBytes[i] != k7zSignature[i]) - return 0; - return 1; -} - -typedef struct _CSzState -{ - Byte *Data; - size_t Size; -}CSzData; - -static SRes SzReadByte(CSzData *sd, Byte *b) -{ - if (sd->Size == 0) - return SZ_ERROR_ARCHIVE; - sd->Size--; - *b = *sd->Data++; - return SZ_OK; -} - -static SRes SzReadBytes(CSzData *sd, Byte *data, size_t size) -{ - size_t i; - for (i = 0; i < size; i++) - { - RINOK(SzReadByte(sd, data + i)); - } - return SZ_OK; -} - -static SRes SzReadUInt32(CSzData *sd, UInt32 *value) -{ - int i; - *value = 0; - for (i = 0; i < 4; i++) - { - Byte b; - RINOK(SzReadByte(sd, &b)); - *value |= ((UInt32)(b) << (8 * i)); - } - return SZ_OK; -} - -static SRes SzReadNumber(CSzData *sd, UInt64 *value) -{ - Byte firstByte; - Byte mask = 0x80; - int i; - RINOK(SzReadByte(sd, &firstByte)); - *value = 0; - for (i = 0; i < 8; i++) - { - Byte b; - if ((firstByte & mask) == 0) - { - UInt64 highPart = firstByte & (mask - 1); - *value += (highPart << (8 * i)); - return SZ_OK; - } - RINOK(SzReadByte(sd, &b)); - *value |= ((UInt64)b << (8 * i)); - mask >>= 1; - } - return SZ_OK; -} - -static SRes SzReadNumber32(CSzData *sd, UInt32 *value) -{ - UInt64 value64; - RINOK(SzReadNumber(sd, &value64)); - if (value64 >= 0x80000000) - return SZ_ERROR_UNSUPPORTED; - if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) - return SZ_ERROR_UNSUPPORTED; - *value = (UInt32)value64; - return SZ_OK; -} - -static SRes SzReadID(CSzData *sd, UInt64 *value) -{ - return SzReadNumber(sd, value); -} - -static SRes SzSkeepDataSize(CSzData *sd, UInt64 size) -{ - if (size > sd->Size) - return SZ_ERROR_ARCHIVE; - sd->Size -= (size_t)size; - sd->Data += (size_t)size; - return SZ_OK; -} - -static SRes SzSkeepData(CSzData *sd) -{ - UInt64 size; - RINOK(SzReadNumber(sd, &size)); - return SzSkeepDataSize(sd, size); -} - -static SRes SzReadArchiveProperties(CSzData *sd) -{ - for (;;) - { - UInt64 type; - RINOK(SzReadID(sd, &type)); - if (type == k7zIdEnd) - break; - SzSkeepData(sd); - } - return SZ_OK; -} - -static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute) -{ - for (;;) - { - UInt64 type; - RINOK(SzReadID(sd, &type)); - if (type == attribute) - return SZ_OK; - if (type == k7zIdEnd) - return SZ_ERROR_ARCHIVE; - RINOK(SzSkeepData(sd)); - } -} - -static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) -{ - Byte b = 0; - Byte mask = 0; - size_t i; - MY_ALLOC(Byte, *v, numItems, alloc); - for (i = 0; i < numItems; i++) - { - if (mask == 0) - { - RINOK(SzReadByte(sd, &b)); - mask = 0x80; - } - (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); - mask >>= 1; - } - return SZ_OK; -} - -static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) -{ - Byte allAreDefined; - size_t i; - RINOK(SzReadByte(sd, &allAreDefined)); - if (allAreDefined == 0) - return SzReadBoolVector(sd, numItems, v, alloc); - MY_ALLOC(Byte, *v, numItems, alloc); - for (i = 0; i < numItems; i++) - (*v)[i] = 1; - return SZ_OK; -} - -static SRes SzReadHashDigests( - CSzData *sd, - size_t numItems, - Byte **digestsDefined, - UInt32 **digests, - ISzAlloc *alloc) -{ - size_t i; - RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc)); - MY_ALLOC(UInt32, *digests, numItems, alloc); - for (i = 0; i < numItems; i++) - if ((*digestsDefined)[i]) - { - RINOK(SzReadUInt32(sd, (*digests) + i)); - } - return SZ_OK; -} - -static SRes SzReadPackInfo( - CSzData *sd, - UInt64 *dataOffset, - UInt32 *numPackStreams, - UInt64 **packSizes, - Byte **packCRCsDefined, - UInt32 **packCRCs, - ISzAlloc *alloc) -{ - UInt32 i; - RINOK(SzReadNumber(sd, dataOffset)); - RINOK(SzReadNumber32(sd, numPackStreams)); - - RINOK(SzWaitAttribute(sd, k7zIdSize)); - - MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc); - - for (i = 0; i < *numPackStreams; i++) - { - RINOK(SzReadNumber(sd, (*packSizes) + i)); - } - - for (;;) - { - UInt64 type; - RINOK(SzReadID(sd, &type)); - if (type == k7zIdEnd) - break; - if (type == k7zIdCRC) - { - RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, alloc)); - continue; - } - RINOK(SzSkeepData(sd)); - } - if (*packCRCsDefined == 0) - { - MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc); - MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc); - for (i = 0; i < *numPackStreams; i++) - { - (*packCRCsDefined)[i] = 0; - (*packCRCs)[i] = 0; - } - } - return SZ_OK; -} - -static SRes SzReadSwitch(CSzData *sd) -{ - Byte external; - RINOK(SzReadByte(sd, &external)); - return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; -} - -static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc) -{ - UInt32 numCoders, numBindPairs, numPackStreams, i; - UInt32 numInStreams = 0, numOutStreams = 0; - - RINOK(SzReadNumber32(sd, &numCoders)); - if (numCoders > NUM_FOLDER_CODERS_MAX) - return SZ_ERROR_UNSUPPORTED; - folder->NumCoders = numCoders; - - MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc); - - for (i = 0; i < numCoders; i++) - SzCoderInfo_Init(folder->Coders + i); - - for (i = 0; i < numCoders; i++) - { - Byte mainByte; - CSzCoderInfo *coder = folder->Coders + i; - { - unsigned idSize, j; - Byte longID[15]; - RINOK(SzReadByte(sd, &mainByte)); - idSize = (unsigned)(mainByte & 0xF); - RINOK(SzReadBytes(sd, longID, idSize)); - if (idSize > sizeof(coder->MethodID)) - return SZ_ERROR_UNSUPPORTED; - coder->MethodID = 0; - for (j = 0; j < idSize; j++) - coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j); - - if ((mainByte & 0x10) != 0) - { - RINOK(SzReadNumber32(sd, &coder->NumInStreams)); - RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); - if (coder->NumInStreams > NUM_CODER_STREAMS_MAX || - coder->NumOutStreams > NUM_CODER_STREAMS_MAX) - return SZ_ERROR_UNSUPPORTED; - } - else - { - coder->NumInStreams = 1; - coder->NumOutStreams = 1; - } - if ((mainByte & 0x20) != 0) - { - UInt64 propertiesSize = 0; - RINOK(SzReadNumber(sd, &propertiesSize)); - if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc)) - return SZ_ERROR_MEM; - RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize)); - } - } - while ((mainByte & 0x80) != 0) - { - RINOK(SzReadByte(sd, &mainByte)); - RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); - if ((mainByte & 0x10) != 0) - { - UInt32 n; - RINOK(SzReadNumber32(sd, &n)); - RINOK(SzReadNumber32(sd, &n)); - } - if ((mainByte & 0x20) != 0) - { - UInt64 propertiesSize = 0; - RINOK(SzReadNumber(sd, &propertiesSize)); - RINOK(SzSkeepDataSize(sd, propertiesSize)); - } - } - numInStreams += coder->NumInStreams; - numOutStreams += coder->NumOutStreams; - } - - if (numOutStreams == 0) - return SZ_ERROR_UNSUPPORTED; - - folder->NumBindPairs = numBindPairs = numOutStreams - 1; - MY_ALLOC(CSzBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); - - for (i = 0; i < numBindPairs; i++) - { - CSzBindPair *bp = folder->BindPairs + i; - RINOK(SzReadNumber32(sd, &bp->InIndex)); - RINOK(SzReadNumber32(sd, &bp->OutIndex)); - } - - if (numInStreams < numBindPairs) - return SZ_ERROR_UNSUPPORTED; - - folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs; - MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc); - - if (numPackStreams == 1) - { - for (i = 0; i < numInStreams ; i++) - if (SzFolder_FindBindPairForInStream(folder, i) < 0) - break; - if (i == numInStreams) - return SZ_ERROR_UNSUPPORTED; - folder->PackStreams[0] = i; - } - else - for (i = 0; i < numPackStreams; i++) - { - RINOK(SzReadNumber32(sd, folder->PackStreams + i)); - } - return SZ_OK; -} - -static SRes SzReadUnpackInfo( - CSzData *sd, - UInt32 *numFolders, - CSzFolder **folders, /* for alloc */ - ISzAlloc *alloc, - ISzAlloc *allocTemp) -{ - UInt32 i; - RINOK(SzWaitAttribute(sd, k7zIdFolder)); - RINOK(SzReadNumber32(sd, numFolders)); - { - RINOK(SzReadSwitch(sd)); - - MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc); - - for (i = 0; i < *numFolders; i++) - SzFolder_Init((*folders) + i); - - for (i = 0; i < *numFolders; i++) - { - RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc)); - } - } - - RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize)); - - for (i = 0; i < *numFolders; i++) - { - UInt32 j; - CSzFolder *folder = (*folders) + i; - UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder); - - MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc); - - for (j = 0; j < numOutStreams; j++) - { - RINOK(SzReadNumber(sd, folder->UnpackSizes + j)); - } - } - - for (;;) - { - UInt64 type; - RINOK(SzReadID(sd, &type)); - if (type == k7zIdEnd) - return SZ_OK; - if (type == k7zIdCRC) - { - SRes res; - Byte *crcsDefined = 0; - UInt32 *crcs = 0; - res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp); - if (res == SZ_OK) - { - for (i = 0; i < *numFolders; i++) - { - CSzFolder *folder = (*folders) + i; - folder->UnpackCRCDefined = crcsDefined[i]; - folder->UnpackCRC = crcs[i]; - } - } - IAlloc_Free(allocTemp, crcs); - IAlloc_Free(allocTemp, crcsDefined); - RINOK(res); - continue; - } - RINOK(SzSkeepData(sd)); - } -} - -static SRes SzReadSubStreamsInfo( - CSzData *sd, - UInt32 numFolders, - CSzFolder *folders, - UInt32 *numUnpackStreams, - UInt64 **unpackSizes, - Byte **digestsDefined, - UInt32 **digests, - ISzAlloc *allocTemp) -{ - UInt64 type = 0; - UInt32 i; - UInt32 si = 0; - UInt32 numDigests = 0; - - for (i = 0; i < numFolders; i++) - folders[i].NumUnpackStreams = 1; - *numUnpackStreams = numFolders; - - for (;;) - { - RINOK(SzReadID(sd, &type)); - if (type == k7zIdNumUnpackStream) - { - *numUnpackStreams = 0; - for (i = 0; i < numFolders; i++) - { - UInt32 numStreams; - RINOK(SzReadNumber32(sd, &numStreams)); - folders[i].NumUnpackStreams = numStreams; - *numUnpackStreams += numStreams; - } - continue; - } - if (type == k7zIdCRC || type == k7zIdSize) - break; - if (type == k7zIdEnd) - break; - RINOK(SzSkeepData(sd)); - } - - if (*numUnpackStreams == 0) - { - *unpackSizes = 0; - *digestsDefined = 0; - *digests = 0; - } - else - { - *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64)); - RINOM(*unpackSizes); - *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte)); - RINOM(*digestsDefined); - *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32)); - RINOM(*digests); - } - - for (i = 0; i < numFolders; i++) - { - /* - v3.13 incorrectly worked with empty folders - v4.07: we check that folder is empty - */ - UInt64 sum = 0; - UInt32 j; - UInt32 numSubstreams = folders[i].NumUnpackStreams; - if (numSubstreams == 0) - continue; - if (type == k7zIdSize) - for (j = 1; j < numSubstreams; j++) - { - UInt64 size; - RINOK(SzReadNumber(sd, &size)); - (*unpackSizes)[si++] = size; - sum += size; - } - (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum; - } - if (type == k7zIdSize) - { - RINOK(SzReadID(sd, &type)); - } - - for (i = 0; i < *numUnpackStreams; i++) - { - (*digestsDefined)[i] = 0; - (*digests)[i] = 0; - } - - - for (i = 0; i < numFolders; i++) - { - UInt32 numSubstreams = folders[i].NumUnpackStreams; - if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) - numDigests += numSubstreams; - } - - - si = 0; - for (;;) - { - if (type == k7zIdCRC) - { - int digestIndex = 0; - Byte *digestsDefined2 = 0; - UInt32 *digests2 = 0; - SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp); - if (res == SZ_OK) - { - for (i = 0; i < numFolders; i++) - { - CSzFolder *folder = folders + i; - UInt32 numSubstreams = folder->NumUnpackStreams; - if (numSubstreams == 1 && folder->UnpackCRCDefined) - { - (*digestsDefined)[si] = 1; - (*digests)[si] = folder->UnpackCRC; - si++; - } - else - { - UInt32 j; - for (j = 0; j < numSubstreams; j++, digestIndex++) - { - (*digestsDefined)[si] = digestsDefined2[digestIndex]; - (*digests)[si] = digests2[digestIndex]; - si++; - } - } - } - } - IAlloc_Free(allocTemp, digestsDefined2); - IAlloc_Free(allocTemp, digests2); - RINOK(res); - } - else if (type == k7zIdEnd) - return SZ_OK; - else - { - RINOK(SzSkeepData(sd)); - } - RINOK(SzReadID(sd, &type)); - } -} - - -static SRes SzReadStreamsInfo( - CSzData *sd, - UInt64 *dataOffset, - CSzAr *p, - UInt32 *numUnpackStreams, - UInt64 **unpackSizes, /* allocTemp */ - Byte **digestsDefined, /* allocTemp */ - UInt32 **digests, /* allocTemp */ - ISzAlloc *alloc, - ISzAlloc *allocTemp) -{ - for (;;) - { - UInt64 type; - RINOK(SzReadID(sd, &type)); - if ((UInt64)(int)type != type) - return SZ_ERROR_UNSUPPORTED; - switch((int)type) - { - case k7zIdEnd: - return SZ_OK; - case k7zIdPackInfo: - { - RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams, - &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc)); - break; - } - case k7zIdUnpackInfo: - { - RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp)); - break; - } - case k7zIdSubStreamsInfo: - { - RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders, - numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp)); - break; - } - default: - return SZ_ERROR_UNSUPPORTED; - } - } -} - -size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest) -{ - size_t len = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; - if (dest != 0) - { - size_t i; - const Byte *src = p->FileNames.data + (p->FileNameOffsets[fileIndex] * 2); - for (i = 0; i < len; i++) - dest[i] = GetUi16(src + i * 2); - } - return len; -} - -static SRes SzReadFileNames(const Byte *p, size_t size, UInt32 numFiles, size_t *sizes) -{ - UInt32 i; - size_t pos = 0; - for (i = 0; i < numFiles; i++) - { - sizes[i] = pos; - for (;;) - { - if (pos >= size) - return SZ_ERROR_ARCHIVE; - if (p[pos * 2] == 0 && p[pos * 2 + 1] == 0) - break; - pos++; - } - pos++; - } - sizes[i] = pos; - return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; -} - -static SRes SzReadHeader2( - CSzArEx *p, /* allocMain */ - CSzData *sd, - UInt64 **unpackSizes, /* allocTemp */ - Byte **digestsDefined, /* allocTemp */ - UInt32 **digests, /* allocTemp */ - Byte **emptyStreamVector, /* allocTemp */ - Byte **emptyFileVector, /* allocTemp */ - Byte **lwtVector, /* allocTemp */ - ISzAlloc *allocMain, - ISzAlloc *allocTemp) -{ - UInt64 type; - UInt32 numUnpackStreams = 0; - UInt32 numFiles = 0; - CSzFileItem *files = 0; - UInt32 numEmptyStreams = 0; - UInt32 i; - - RINOK(SzReadID(sd, &type)); - - if (type == k7zIdArchiveProperties) - { - RINOK(SzReadArchiveProperties(sd)); - RINOK(SzReadID(sd, &type)); - } - - - if (type == k7zIdMainStreamsInfo) - { - RINOK(SzReadStreamsInfo(sd, - &p->dataPos, - &p->db, - &numUnpackStreams, - unpackSizes, - digestsDefined, - digests, allocMain, allocTemp)); - p->dataPos += p->startPosAfterHeader; - RINOK(SzReadID(sd, &type)); - } - - if (type == k7zIdEnd) - return SZ_OK; - if (type != k7zIdFilesInfo) - return SZ_ERROR_ARCHIVE; - - RINOK(SzReadNumber32(sd, &numFiles)); - p->db.NumFiles = numFiles; - - MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain); - - p->db.Files = files; - for (i = 0; i < numFiles; i++) - SzFile_Init(files + i); - - for (;;) - { - UInt64 type; - UInt64 size; - RINOK(SzReadID(sd, &type)); - if (type == k7zIdEnd) - break; - RINOK(SzReadNumber(sd, &size)); - if (size > sd->Size) - return SZ_ERROR_ARCHIVE; - if ((UInt64)(int)type != type) - { - RINOK(SzSkeepDataSize(sd, size)); - } - else - switch((int)type) - { - case k7zIdName: - { - size_t namesSize; - RINOK(SzReadSwitch(sd)); - namesSize = (size_t)size - 1; - if ((namesSize & 1) != 0) - return SZ_ERROR_ARCHIVE; - if (!Buf_Create(&p->FileNames, namesSize, allocMain)) - return SZ_ERROR_MEM; - MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain); - memcpy(p->FileNames.data, sd->Data, namesSize); - RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets)) - RINOK(SzSkeepDataSize(sd, namesSize)); - break; - } - case k7zIdEmptyStream: - { - RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp)); - numEmptyStreams = 0; - for (i = 0; i < numFiles; i++) - if ((*emptyStreamVector)[i]) - numEmptyStreams++; - break; - } - case k7zIdEmptyFile: - { - RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); - break; - } - case k7zIdWinAttributes: - { - RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); - RINOK(SzReadSwitch(sd)); - for (i = 0; i < numFiles; i++) - { - CSzFileItem *f = &files[i]; - Byte defined = (*lwtVector)[i]; - f->AttribDefined = defined; - f->Attrib = 0; - if (defined) - { - RINOK(SzReadUInt32(sd, &f->Attrib)); - } - } - IAlloc_Free(allocTemp, *lwtVector); - *lwtVector = NULL; - break; - } - case k7zIdMTime: - { - RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); - RINOK(SzReadSwitch(sd)); - for (i = 0; i < numFiles; i++) - { - CSzFileItem *f = &files[i]; - Byte defined = (*lwtVector)[i]; - f->MTimeDefined = defined; - f->MTime.Low = f->MTime.High = 0; - if (defined) - { - RINOK(SzReadUInt32(sd, &f->MTime.Low)); - RINOK(SzReadUInt32(sd, &f->MTime.High)); - } - } - IAlloc_Free(allocTemp, *lwtVector); - *lwtVector = NULL; - break; - } - default: - { - RINOK(SzSkeepDataSize(sd, size)); - } - } - } - - { - UInt32 emptyFileIndex = 0; - UInt32 sizeIndex = 0; - for (i = 0; i < numFiles; i++) - { - CSzFileItem *file = files + i; - file->IsAnti = 0; - if (*emptyStreamVector == 0) - file->HasStream = 1; - else - file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); - if (file->HasStream) - { - file->IsDir = 0; - file->Size = (*unpackSizes)[sizeIndex]; - file->Crc = (*digests)[sizeIndex]; - file->CrcDefined = (Byte)(*digestsDefined)[sizeIndex]; - sizeIndex++; - } - else - { - if (*emptyFileVector == 0) - file->IsDir = 1; - else - file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); - emptyFileIndex++; - file->Size = 0; - file->Crc = 0; - file->CrcDefined = 0; - } - } - } - return SzArEx_Fill(p, allocMain); -} - -static SRes SzReadHeader( - CSzArEx *p, - CSzData *sd, - ISzAlloc *allocMain, - ISzAlloc *allocTemp) -{ - UInt64 *unpackSizes = 0; - Byte *digestsDefined = 0; - UInt32 *digests = 0; - Byte *emptyStreamVector = 0; - Byte *emptyFileVector = 0; - Byte *lwtVector = 0; - SRes res = SzReadHeader2(p, sd, - &unpackSizes, &digestsDefined, &digests, - &emptyStreamVector, &emptyFileVector, &lwtVector, - allocMain, allocTemp); - IAlloc_Free(allocTemp, unpackSizes); - IAlloc_Free(allocTemp, digestsDefined); - IAlloc_Free(allocTemp, digests); - IAlloc_Free(allocTemp, emptyStreamVector); - IAlloc_Free(allocTemp, emptyFileVector); - IAlloc_Free(allocTemp, lwtVector); - return res; -} - -static SRes SzReadAndDecodePackedStreams2( - ILookInStream *inStream, - CSzData *sd, - CBuf *outBuffer, - UInt64 baseOffset, - CSzAr *p, - UInt64 **unpackSizes, - Byte **digestsDefined, - UInt32 **digests, - ISzAlloc *allocTemp) -{ - - UInt32 numUnpackStreams = 0; - UInt64 dataStartPos; - CSzFolder *folder; - UInt64 unpackSize; - SRes res; - - RINOK(SzReadStreamsInfo(sd, &dataStartPos, p, - &numUnpackStreams, unpackSizes, digestsDefined, digests, - allocTemp, allocTemp)); - - dataStartPos += baseOffset; - if (p->NumFolders != 1) - return SZ_ERROR_ARCHIVE; - - folder = p->Folders; - unpackSize = SzFolder_GetUnpackSize(folder); - - RINOK(LookInStream_SeekTo(inStream, dataStartPos)); - - if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp)) - return SZ_ERROR_MEM; - - res = SzFolder_Decode(folder, p->PackSizes, - inStream, dataStartPos, - outBuffer->data, (size_t)unpackSize, allocTemp); - RINOK(res); - if (folder->UnpackCRCDefined) - if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC) - return SZ_ERROR_CRC; - return SZ_OK; -} - -static SRes SzReadAndDecodePackedStreams( - ILookInStream *inStream, - CSzData *sd, - CBuf *outBuffer, - UInt64 baseOffset, - ISzAlloc *allocTemp) -{ - CSzAr p; - UInt64 *unpackSizes = 0; - Byte *digestsDefined = 0; - UInt32 *digests = 0; - SRes res; - SzAr_Init(&p); - res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, - &p, &unpackSizes, &digestsDefined, &digests, - allocTemp); - SzAr_Free(&p, allocTemp); - IAlloc_Free(allocTemp, unpackSizes); - IAlloc_Free(allocTemp, digestsDefined); - IAlloc_Free(allocTemp, digests); - return res; -} - -static SRes SzArEx_Open2( - CSzArEx *p, - ILookInStream *inStream, - ISzAlloc *allocMain, - ISzAlloc *allocTemp) -{ - Byte header[k7zStartHeaderSize]; - Int64 startArcPos; - UInt64 nextHeaderOffset, nextHeaderSize; - size_t nextHeaderSizeT; - UInt32 nextHeaderCRC; - CBuf buffer; - SRes res; - - startArcPos = 0; - RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR)); - - RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); - - if (!TestSignatureCandidate(header)) - return SZ_ERROR_NO_ARCHIVE; - if (header[6] != k7zMajorVersion) - return SZ_ERROR_UNSUPPORTED; - - nextHeaderOffset = GetUi64(header + 12); - nextHeaderSize = GetUi64(header + 20); - nextHeaderCRC = GetUi32(header + 28); - - p->startPosAfterHeader = startArcPos + k7zStartHeaderSize; - - if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) - return SZ_ERROR_CRC; - - nextHeaderSizeT = (size_t)nextHeaderSize; - if (nextHeaderSizeT != nextHeaderSize) - return SZ_ERROR_MEM; - if (nextHeaderSizeT == 0) - return SZ_OK; - if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || - nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) - return SZ_ERROR_NO_ARCHIVE; - - { - Int64 pos = 0; - RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); - if ((UInt64)pos < startArcPos + nextHeaderOffset || - (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || - (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) - return SZ_ERROR_INPUT_EOF; - } - - RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset)); - - if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) - return SZ_ERROR_MEM; - - res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT); - if (res == SZ_OK) - { - res = SZ_ERROR_ARCHIVE; - if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC) - { - CSzData sd; - UInt64 type; - sd.Data = buffer.data; - sd.Size = buffer.size; - res = SzReadID(&sd, &type); - if (res == SZ_OK) - { - if (type == k7zIdEncodedHeader) - { - CBuf outBuffer; - Buf_Init(&outBuffer); - res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp); - if (res != SZ_OK) - Buf_Free(&outBuffer, allocTemp); - else - { - Buf_Free(&buffer, allocTemp); - buffer.data = outBuffer.data; - buffer.size = outBuffer.size; - sd.Data = buffer.data; - sd.Size = buffer.size; - res = SzReadID(&sd, &type); - } - } - } - if (res == SZ_OK) - { - if (type == k7zIdHeader) - res = SzReadHeader(p, &sd, allocMain, allocTemp); - else - res = SZ_ERROR_UNSUPPORTED; - } - } - } - Buf_Free(&buffer, allocTemp); - return res; -} - -SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) -{ - SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); - if (res != SZ_OK) - SzArEx_Free(p, allocMain); - return res; -} - -SRes SzArEx_Extract( - const CSzArEx *p, - ILookInStream *inStream, - UInt32 fileIndex, - UInt32 *blockIndex, - Byte **outBuffer, - size_t *outBufferSize, - size_t *offset, - size_t *outSizeProcessed, - ISzAlloc *allocMain, - ISzAlloc *allocTemp) -{ - UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; - SRes res = SZ_OK; - *offset = 0; - *outSizeProcessed = 0; - if (folderIndex == (UInt32)-1) - { - IAlloc_Free(allocMain, *outBuffer); - *blockIndex = folderIndex; - *outBuffer = 0; - *outBufferSize = 0; - return SZ_OK; - } - - if (*outBuffer == 0 || *blockIndex != folderIndex) - { - CSzFolder *folder = p->db.Folders + folderIndex; - UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); - size_t unpackSize = (size_t)unpackSizeSpec; - UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); - - if (unpackSize != unpackSizeSpec) - return SZ_ERROR_MEM; - *blockIndex = folderIndex; - IAlloc_Free(allocMain, *outBuffer); - *outBuffer = 0; - - RINOK(LookInStream_SeekTo(inStream, startOffset)); - - if (res == SZ_OK) - { - *outBufferSize = unpackSize; - if (unpackSize != 0) - { - *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); - if (*outBuffer == 0) - res = SZ_ERROR_MEM; - } - if (res == SZ_OK) - { - res = SzFolder_Decode(folder, - p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], - inStream, startOffset, - *outBuffer, unpackSize, allocTemp); - if (res == SZ_OK) - { - if (folder->UnpackCRCDefined) - { - if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) - res = SZ_ERROR_CRC; - } - } - } - } - } - if (res == SZ_OK) - { - UInt32 i; - CSzFileItem *fileItem = p->db.Files + fileIndex; - *offset = 0; - for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) - *offset += (UInt32)p->db.Files[i].Size; - *outSizeProcessed = (size_t)fileItem->Size; - if (*offset + *outSizeProcessed > *outBufferSize) - return SZ_ERROR_FAIL; - if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc) - res = SZ_ERROR_CRC; - } - return res; -} +/* 7zIn.c -- 7z Input functions +2010-10-29 : Igor Pavlov : Public domain */ + +#include + +#include "7z.h" +#include "7zCrc.h" +#include "CpuArch.h" + +Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; + +#define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; } + +#define NUM_FOLDER_CODERS_MAX 32 +#define NUM_CODER_STREAMS_MAX 32 + +void SzCoderInfo_Init(CSzCoderInfo *p) +{ + Buf_Init(&p->Props); +} + +void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc) +{ + Buf_Free(&p->Props, alloc); + SzCoderInfo_Init(p); +} + +void SzFolder_Init(CSzFolder *p) +{ + p->Coders = 0; + p->BindPairs = 0; + p->PackStreams = 0; + p->UnpackSizes = 0; + p->NumCoders = 0; + p->NumBindPairs = 0; + p->NumPackStreams = 0; + p->UnpackCRCDefined = 0; + p->UnpackCRC = 0; + p->NumUnpackStreams = 0; +} + +void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) +{ + UInt32 i; + if (p->Coders) + for (i = 0; i < p->NumCoders; i++) + SzCoderInfo_Free(&p->Coders[i], alloc); + IAlloc_Free(alloc, p->Coders); + IAlloc_Free(alloc, p->BindPairs); + IAlloc_Free(alloc, p->PackStreams); + IAlloc_Free(alloc, p->UnpackSizes); + SzFolder_Init(p); +} + +UInt32 SzFolder_GetNumOutStreams(CSzFolder *p) +{ + UInt32 result = 0; + UInt32 i; + for (i = 0; i < p->NumCoders; i++) + result += p->Coders[i].NumOutStreams; + return result; +} + +int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex) +{ + UInt32 i; + for (i = 0; i < p->NumBindPairs; i++) + if (p->BindPairs[i].InIndex == inStreamIndex) + return i; + return -1; +} + + +int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex) +{ + UInt32 i; + for (i = 0; i < p->NumBindPairs; i++) + if (p->BindPairs[i].OutIndex == outStreamIndex) + return i; + return -1; +} + +UInt64 SzFolder_GetUnpackSize(CSzFolder *p) +{ + int i = (int)SzFolder_GetNumOutStreams(p); + if (i == 0) + return 0; + for (i--; i >= 0; i--) + if (SzFolder_FindBindPairForOutStream(p, i) < 0) + return p->UnpackSizes[i]; + /* throw 1; */ + return 0; +} + +void SzFile_Init(CSzFileItem *p) +{ + p->HasStream = 1; + p->IsDir = 0; + p->IsAnti = 0; + p->CrcDefined = 0; + p->MTimeDefined = 0; +} + +void SzAr_Init(CSzAr *p) +{ + p->PackSizes = 0; + p->PackCRCsDefined = 0; + p->PackCRCs = 0; + p->Folders = 0; + p->Files = 0; + p->NumPackStreams = 0; + p->NumFolders = 0; + p->NumFiles = 0; +} + +void SzAr_Free(CSzAr *p, ISzAlloc *alloc) +{ + UInt32 i; + if (p->Folders) + for (i = 0; i < p->NumFolders; i++) + SzFolder_Free(&p->Folders[i], alloc); + + IAlloc_Free(alloc, p->PackSizes); + IAlloc_Free(alloc, p->PackCRCsDefined); + IAlloc_Free(alloc, p->PackCRCs); + IAlloc_Free(alloc, p->Folders); + IAlloc_Free(alloc, p->Files); + SzAr_Init(p); +} + + +void SzArEx_Init(CSzArEx *p) +{ + SzAr_Init(&p->db); + p->FolderStartPackStreamIndex = 0; + p->PackStreamStartPositions = 0; + p->FolderStartFileIndex = 0; + p->FileIndexToFolderIndexMap = 0; + p->FileNameOffsets = 0; + Buf_Init(&p->FileNames); +} + +void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) +{ + IAlloc_Free(alloc, p->FolderStartPackStreamIndex); + IAlloc_Free(alloc, p->PackStreamStartPositions); + IAlloc_Free(alloc, p->FolderStartFileIndex); + IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); + + IAlloc_Free(alloc, p->FileNameOffsets); + Buf_Free(&p->FileNames, alloc); + + SzAr_Free(&p->db, alloc); + SzArEx_Init(p); +} + +/* +UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const +{ + return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; +} + +UInt64 GetFilePackSize(int fileIndex) const +{ + int folderIndex = FileIndexToFolderIndexMap[fileIndex]; + if (folderIndex >= 0) + { + const CSzFolder &folderInfo = Folders[folderIndex]; + if (FolderStartFileIndex[folderIndex] == fileIndex) + return GetFolderFullPackSize(folderIndex); + } + return 0; +} +*/ + +#define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \ + if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; } + +static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc) +{ + UInt32 startPos = 0; + UInt64 startPosSize = 0; + UInt32 i; + UInt32 folderIndex = 0; + UInt32 indexInFolder = 0; + MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc); + for (i = 0; i < p->db.NumFolders; i++) + { + p->FolderStartPackStreamIndex[i] = startPos; + startPos += p->db.Folders[i].NumPackStreams; + } + + MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc); + + for (i = 0; i < p->db.NumPackStreams; i++) + { + p->PackStreamStartPositions[i] = startPosSize; + startPosSize += p->db.PackSizes[i]; + } + + MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc); + MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc); + + for (i = 0; i < p->db.NumFiles; i++) + { + CSzFileItem *file = p->db.Files + i; + int emptyStream = !file->HasStream; + if (emptyStream && indexInFolder == 0) + { + p->FileIndexToFolderIndexMap[i] = (UInt32)-1; + continue; + } + if (indexInFolder == 0) + { + /* + v3.13 incorrectly worked with empty folders + v4.07: Loop for skipping empty folders + */ + for (;;) + { + if (folderIndex >= p->db.NumFolders) + return SZ_ERROR_ARCHIVE; + p->FolderStartFileIndex[folderIndex] = i; + if (p->db.Folders[folderIndex].NumUnpackStreams != 0) + break; + folderIndex++; + } + } + p->FileIndexToFolderIndexMap[i] = folderIndex; + if (emptyStream) + continue; + indexInFolder++; + if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams) + { + folderIndex++; + indexInFolder = 0; + } + } + return SZ_OK; +} + + +UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder) +{ + return p->dataPos + + p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; +} + +int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize) +{ + UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex]; + CSzFolder *folder = p->db.Folders + folderIndex; + UInt64 size = 0; + UInt32 i; + for (i = 0; i < folder->NumPackStreams; i++) + { + UInt64 t = size + p->db.PackSizes[packStreamIndex + i]; + if (t < size) /* check it */ + return SZ_ERROR_FAIL; + size = t; + } + *resSize = size; + return SZ_OK; +} + + +/* +SRes SzReadTime(const CObjectVector &dataVector, + CObjectVector &files, UInt64 type) +{ + CBoolVector boolVector; + RINOK(ReadBoolVector2(files.Size(), boolVector)) + + CStreamSwitch streamSwitch; + RINOK(streamSwitch.Set(this, &dataVector)); + + for (int i = 0; i < files.Size(); i++) + { + CSzFileItem &file = files[i]; + CArchiveFileTime fileTime; + bool defined = boolVector[i]; + if (defined) + { + UInt32 low, high; + RINOK(SzReadUInt32(low)); + RINOK(SzReadUInt32(high)); + fileTime.dwLowDateTime = low; + fileTime.dwHighDateTime = high; + } + switch(type) + { + case k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break; + case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break; + case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break; + } + } + return SZ_OK; +} +*/ + +static int TestSignatureCandidate(Byte *testBytes) +{ + size_t i; + for (i = 0; i < k7zSignatureSize; i++) + if (testBytes[i] != k7zSignature[i]) + return 0; + return 1; +} + +typedef struct _CSzState +{ + Byte *Data; + size_t Size; +}CSzData; + +static SRes SzReadByte(CSzData *sd, Byte *b) +{ + if (sd->Size == 0) + return SZ_ERROR_ARCHIVE; + sd->Size--; + *b = *sd->Data++; + return SZ_OK; +} + +static SRes SzReadBytes(CSzData *sd, Byte *data, size_t size) +{ + size_t i; + for (i = 0; i < size; i++) + { + RINOK(SzReadByte(sd, data + i)); + } + return SZ_OK; +} + +static SRes SzReadUInt32(CSzData *sd, UInt32 *value) +{ + int i; + *value = 0; + for (i = 0; i < 4; i++) + { + Byte b; + RINOK(SzReadByte(sd, &b)); + *value |= ((UInt32)(b) << (8 * i)); + } + return SZ_OK; +} + +static SRes SzReadNumber(CSzData *sd, UInt64 *value) +{ + Byte firstByte; + Byte mask = 0x80; + int i; + RINOK(SzReadByte(sd, &firstByte)); + *value = 0; + for (i = 0; i < 8; i++) + { + Byte b; + if ((firstByte & mask) == 0) + { + UInt64 highPart = firstByte & (mask - 1); + *value += (highPart << (8 * i)); + return SZ_OK; + } + RINOK(SzReadByte(sd, &b)); + *value |= ((UInt64)b << (8 * i)); + mask >>= 1; + } + return SZ_OK; +} + +static SRes SzReadNumber32(CSzData *sd, UInt32 *value) +{ + UInt64 value64; + RINOK(SzReadNumber(sd, &value64)); + if (value64 >= 0x80000000) + return SZ_ERROR_UNSUPPORTED; + if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) + return SZ_ERROR_UNSUPPORTED; + *value = (UInt32)value64; + return SZ_OK; +} + +static SRes SzReadID(CSzData *sd, UInt64 *value) +{ + return SzReadNumber(sd, value); +} + +static SRes SzSkeepDataSize(CSzData *sd, UInt64 size) +{ + if (size > sd->Size) + return SZ_ERROR_ARCHIVE; + sd->Size -= (size_t)size; + sd->Data += (size_t)size; + return SZ_OK; +} + +static SRes SzSkeepData(CSzData *sd) +{ + UInt64 size; + RINOK(SzReadNumber(sd, &size)); + return SzSkeepDataSize(sd, size); +} + +static SRes SzReadArchiveProperties(CSzData *sd) +{ + for (;;) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + break; + SzSkeepData(sd); + } + return SZ_OK; +} + +static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute) +{ + for (;;) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == attribute) + return SZ_OK; + if (type == k7zIdEnd) + return SZ_ERROR_ARCHIVE; + RINOK(SzSkeepData(sd)); + } +} + +static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) +{ + Byte b = 0; + Byte mask = 0; + size_t i; + MY_ALLOC(Byte, *v, numItems, alloc); + for (i = 0; i < numItems; i++) + { + if (mask == 0) + { + RINOK(SzReadByte(sd, &b)); + mask = 0x80; + } + (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); + mask >>= 1; + } + return SZ_OK; +} + +static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) +{ + Byte allAreDefined; + size_t i; + RINOK(SzReadByte(sd, &allAreDefined)); + if (allAreDefined == 0) + return SzReadBoolVector(sd, numItems, v, alloc); + MY_ALLOC(Byte, *v, numItems, alloc); + for (i = 0; i < numItems; i++) + (*v)[i] = 1; + return SZ_OK; +} + +static SRes SzReadHashDigests( + CSzData *sd, + size_t numItems, + Byte **digestsDefined, + UInt32 **digests, + ISzAlloc *alloc) +{ + size_t i; + RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc)); + MY_ALLOC(UInt32, *digests, numItems, alloc); + for (i = 0; i < numItems; i++) + if ((*digestsDefined)[i]) + { + RINOK(SzReadUInt32(sd, (*digests) + i)); + } + return SZ_OK; +} + +static SRes SzReadPackInfo( + CSzData *sd, + UInt64 *dataOffset, + UInt32 *numPackStreams, + UInt64 **packSizes, + Byte **packCRCsDefined, + UInt32 **packCRCs, + ISzAlloc *alloc) +{ + UInt32 i; + RINOK(SzReadNumber(sd, dataOffset)); + RINOK(SzReadNumber32(sd, numPackStreams)); + + RINOK(SzWaitAttribute(sd, k7zIdSize)); + + MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc); + + for (i = 0; i < *numPackStreams; i++) + { + RINOK(SzReadNumber(sd, (*packSizes) + i)); + } + + for (;;) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + break; + if (type == k7zIdCRC) + { + RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, alloc)); + continue; + } + RINOK(SzSkeepData(sd)); + } + if (*packCRCsDefined == 0) + { + MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc); + MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc); + for (i = 0; i < *numPackStreams; i++) + { + (*packCRCsDefined)[i] = 0; + (*packCRCs)[i] = 0; + } + } + return SZ_OK; +} + +static SRes SzReadSwitch(CSzData *sd) +{ + Byte external; + RINOK(SzReadByte(sd, &external)); + return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; +} + +static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc) +{ + UInt32 numCoders, numBindPairs, numPackStreams, i; + UInt32 numInStreams = 0, numOutStreams = 0; + + RINOK(SzReadNumber32(sd, &numCoders)); + if (numCoders > NUM_FOLDER_CODERS_MAX) + return SZ_ERROR_UNSUPPORTED; + folder->NumCoders = numCoders; + + MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc); + + for (i = 0; i < numCoders; i++) + SzCoderInfo_Init(folder->Coders + i); + + for (i = 0; i < numCoders; i++) + { + Byte mainByte; + CSzCoderInfo *coder = folder->Coders + i; + { + unsigned idSize, j; + Byte longID[15]; + RINOK(SzReadByte(sd, &mainByte)); + idSize = (unsigned)(mainByte & 0xF); + RINOK(SzReadBytes(sd, longID, idSize)); + if (idSize > sizeof(coder->MethodID)) + return SZ_ERROR_UNSUPPORTED; + coder->MethodID = 0; + for (j = 0; j < idSize; j++) + coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j); + + if ((mainByte & 0x10) != 0) + { + RINOK(SzReadNumber32(sd, &coder->NumInStreams)); + RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); + if (coder->NumInStreams > NUM_CODER_STREAMS_MAX || + coder->NumOutStreams > NUM_CODER_STREAMS_MAX) + return SZ_ERROR_UNSUPPORTED; + } + else + { + coder->NumInStreams = 1; + coder->NumOutStreams = 1; + } + if ((mainByte & 0x20) != 0) + { + UInt64 propertiesSize = 0; + RINOK(SzReadNumber(sd, &propertiesSize)); + if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc)) + return SZ_ERROR_MEM; + RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize)); + } + } + while ((mainByte & 0x80) != 0) + { + RINOK(SzReadByte(sd, &mainByte)); + RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); + if ((mainByte & 0x10) != 0) + { + UInt32 n; + RINOK(SzReadNumber32(sd, &n)); + RINOK(SzReadNumber32(sd, &n)); + } + if ((mainByte & 0x20) != 0) + { + UInt64 propertiesSize = 0; + RINOK(SzReadNumber(sd, &propertiesSize)); + RINOK(SzSkeepDataSize(sd, propertiesSize)); + } + } + numInStreams += coder->NumInStreams; + numOutStreams += coder->NumOutStreams; + } + + if (numOutStreams == 0) + return SZ_ERROR_UNSUPPORTED; + + folder->NumBindPairs = numBindPairs = numOutStreams - 1; + MY_ALLOC(CSzBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); + + for (i = 0; i < numBindPairs; i++) + { + CSzBindPair *bp = folder->BindPairs + i; + RINOK(SzReadNumber32(sd, &bp->InIndex)); + RINOK(SzReadNumber32(sd, &bp->OutIndex)); + } + + if (numInStreams < numBindPairs) + return SZ_ERROR_UNSUPPORTED; + + folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs; + MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc); + + if (numPackStreams == 1) + { + for (i = 0; i < numInStreams ; i++) + if (SzFolder_FindBindPairForInStream(folder, i) < 0) + break; + if (i == numInStreams) + return SZ_ERROR_UNSUPPORTED; + folder->PackStreams[0] = i; + } + else + for (i = 0; i < numPackStreams; i++) + { + RINOK(SzReadNumber32(sd, folder->PackStreams + i)); + } + return SZ_OK; +} + +static SRes SzReadUnpackInfo( + CSzData *sd, + UInt32 *numFolders, + CSzFolder **folders, /* for alloc */ + ISzAlloc *alloc, + ISzAlloc *allocTemp) +{ + UInt32 i; + RINOK(SzWaitAttribute(sd, k7zIdFolder)); + RINOK(SzReadNumber32(sd, numFolders)); + { + RINOK(SzReadSwitch(sd)); + + MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc); + + for (i = 0; i < *numFolders; i++) + SzFolder_Init((*folders) + i); + + for (i = 0; i < *numFolders; i++) + { + RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc)); + } + } + + RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize)); + + for (i = 0; i < *numFolders; i++) + { + UInt32 j; + CSzFolder *folder = (*folders) + i; + UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder); + + MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc); + + for (j = 0; j < numOutStreams; j++) + { + RINOK(SzReadNumber(sd, folder->UnpackSizes + j)); + } + } + + for (;;) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + return SZ_OK; + if (type == k7zIdCRC) + { + SRes res; + Byte *crcsDefined = 0; + UInt32 *crcs = 0; + res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp); + if (res == SZ_OK) + { + for (i = 0; i < *numFolders; i++) + { + CSzFolder *folder = (*folders) + i; + folder->UnpackCRCDefined = crcsDefined[i]; + folder->UnpackCRC = crcs[i]; + } + } + IAlloc_Free(allocTemp, crcs); + IAlloc_Free(allocTemp, crcsDefined); + RINOK(res); + continue; + } + RINOK(SzSkeepData(sd)); + } +} + +static SRes SzReadSubStreamsInfo( + CSzData *sd, + UInt32 numFolders, + CSzFolder *folders, + UInt32 *numUnpackStreams, + UInt64 **unpackSizes, + Byte **digestsDefined, + UInt32 **digests, + ISzAlloc *allocTemp) +{ + UInt64 type = 0; + UInt32 i; + UInt32 si = 0; + UInt32 numDigests = 0; + + for (i = 0; i < numFolders; i++) + folders[i].NumUnpackStreams = 1; + *numUnpackStreams = numFolders; + + for (;;) + { + RINOK(SzReadID(sd, &type)); + if (type == k7zIdNumUnpackStream) + { + *numUnpackStreams = 0; + for (i = 0; i < numFolders; i++) + { + UInt32 numStreams; + RINOK(SzReadNumber32(sd, &numStreams)); + folders[i].NumUnpackStreams = numStreams; + *numUnpackStreams += numStreams; + } + continue; + } + if (type == k7zIdCRC || type == k7zIdSize) + break; + if (type == k7zIdEnd) + break; + RINOK(SzSkeepData(sd)); + } + + if (*numUnpackStreams == 0) + { + *unpackSizes = 0; + *digestsDefined = 0; + *digests = 0; + } + else + { + *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64)); + RINOM(*unpackSizes); + *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte)); + RINOM(*digestsDefined); + *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32)); + RINOM(*digests); + } + + for (i = 0; i < numFolders; i++) + { + /* + v3.13 incorrectly worked with empty folders + v4.07: we check that folder is empty + */ + UInt64 sum = 0; + UInt32 j; + UInt32 numSubstreams = folders[i].NumUnpackStreams; + if (numSubstreams == 0) + continue; + if (type == k7zIdSize) + for (j = 1; j < numSubstreams; j++) + { + UInt64 size; + RINOK(SzReadNumber(sd, &size)); + (*unpackSizes)[si++] = size; + sum += size; + } + (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum; + } + if (type == k7zIdSize) + { + RINOK(SzReadID(sd, &type)); + } + + for (i = 0; i < *numUnpackStreams; i++) + { + (*digestsDefined)[i] = 0; + (*digests)[i] = 0; + } + + + for (i = 0; i < numFolders; i++) + { + UInt32 numSubstreams = folders[i].NumUnpackStreams; + if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) + numDigests += numSubstreams; + } + + + si = 0; + for (;;) + { + if (type == k7zIdCRC) + { + int digestIndex = 0; + Byte *digestsDefined2 = 0; + UInt32 *digests2 = 0; + SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp); + if (res == SZ_OK) + { + for (i = 0; i < numFolders; i++) + { + CSzFolder *folder = folders + i; + UInt32 numSubstreams = folder->NumUnpackStreams; + if (numSubstreams == 1 && folder->UnpackCRCDefined) + { + (*digestsDefined)[si] = 1; + (*digests)[si] = folder->UnpackCRC; + si++; + } + else + { + UInt32 j; + for (j = 0; j < numSubstreams; j++, digestIndex++) + { + (*digestsDefined)[si] = digestsDefined2[digestIndex]; + (*digests)[si] = digests2[digestIndex]; + si++; + } + } + } + } + IAlloc_Free(allocTemp, digestsDefined2); + IAlloc_Free(allocTemp, digests2); + RINOK(res); + } + else if (type == k7zIdEnd) + return SZ_OK; + else + { + RINOK(SzSkeepData(sd)); + } + RINOK(SzReadID(sd, &type)); + } +} + + +static SRes SzReadStreamsInfo( + CSzData *sd, + UInt64 *dataOffset, + CSzAr *p, + UInt32 *numUnpackStreams, + UInt64 **unpackSizes, /* allocTemp */ + Byte **digestsDefined, /* allocTemp */ + UInt32 **digests, /* allocTemp */ + ISzAlloc *alloc, + ISzAlloc *allocTemp) +{ + for (;;) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if ((UInt64)(int)type != type) + return SZ_ERROR_UNSUPPORTED; + switch((int)type) + { + case k7zIdEnd: + return SZ_OK; + case k7zIdPackInfo: + { + RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams, + &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc)); + break; + } + case k7zIdUnpackInfo: + { + RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp)); + break; + } + case k7zIdSubStreamsInfo: + { + RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders, + numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp)); + break; + } + default: + return SZ_ERROR_UNSUPPORTED; + } + } +} + +size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest) +{ + size_t len = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; + if (dest != 0) + { + size_t i; + const Byte *src = p->FileNames.data + (p->FileNameOffsets[fileIndex] * 2); + for (i = 0; i < len; i++) + dest[i] = GetUi16(src + i * 2); + } + return len; +} + +static SRes SzReadFileNames(const Byte *p, size_t size, UInt32 numFiles, size_t *sizes) +{ + UInt32 i; + size_t pos = 0; + for (i = 0; i < numFiles; i++) + { + sizes[i] = pos; + for (;;) + { + if (pos >= size) + return SZ_ERROR_ARCHIVE; + if (p[pos * 2] == 0 && p[pos * 2 + 1] == 0) + break; + pos++; + } + pos++; + } + sizes[i] = pos; + return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; +} + +static SRes SzReadHeader2( + CSzArEx *p, /* allocMain */ + CSzData *sd, + UInt64 **unpackSizes, /* allocTemp */ + Byte **digestsDefined, /* allocTemp */ + UInt32 **digests, /* allocTemp */ + Byte **emptyStreamVector, /* allocTemp */ + Byte **emptyFileVector, /* allocTemp */ + Byte **lwtVector, /* allocTemp */ + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + UInt64 type; + UInt32 numUnpackStreams = 0; + UInt32 numFiles = 0; + CSzFileItem *files = 0; + UInt32 numEmptyStreams = 0; + UInt32 i; + + RINOK(SzReadID(sd, &type)); + + if (type == k7zIdArchiveProperties) + { + RINOK(SzReadArchiveProperties(sd)); + RINOK(SzReadID(sd, &type)); + } + + + if (type == k7zIdMainStreamsInfo) + { + RINOK(SzReadStreamsInfo(sd, + &p->dataPos, + &p->db, + &numUnpackStreams, + unpackSizes, + digestsDefined, + digests, allocMain, allocTemp)); + p->dataPos += p->startPosAfterHeader; + RINOK(SzReadID(sd, &type)); + } + + if (type == k7zIdEnd) + return SZ_OK; + if (type != k7zIdFilesInfo) + return SZ_ERROR_ARCHIVE; + + RINOK(SzReadNumber32(sd, &numFiles)); + p->db.NumFiles = numFiles; + + MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain); + + p->db.Files = files; + for (i = 0; i < numFiles; i++) + SzFile_Init(files + i); + + for (;;) + { + UInt64 type; + UInt64 size; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + break; + RINOK(SzReadNumber(sd, &size)); + if (size > sd->Size) + return SZ_ERROR_ARCHIVE; + if ((UInt64)(int)type != type) + { + RINOK(SzSkeepDataSize(sd, size)); + } + else + switch((int)type) + { + case k7zIdName: + { + size_t namesSize; + RINOK(SzReadSwitch(sd)); + namesSize = (size_t)size - 1; + if ((namesSize & 1) != 0) + return SZ_ERROR_ARCHIVE; + if (!Buf_Create(&p->FileNames, namesSize, allocMain)) + return SZ_ERROR_MEM; + MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain); + memcpy(p->FileNames.data, sd->Data, namesSize); + RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets)) + RINOK(SzSkeepDataSize(sd, namesSize)); + break; + } + case k7zIdEmptyStream: + { + RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp)); + numEmptyStreams = 0; + for (i = 0; i < numFiles; i++) + if ((*emptyStreamVector)[i]) + numEmptyStreams++; + break; + } + case k7zIdEmptyFile: + { + RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); + break; + } + case k7zIdWinAttributes: + { + RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); + RINOK(SzReadSwitch(sd)); + for (i = 0; i < numFiles; i++) + { + CSzFileItem *f = &files[i]; + Byte defined = (*lwtVector)[i]; + f->AttribDefined = defined; + f->Attrib = 0; + if (defined) + { + RINOK(SzReadUInt32(sd, &f->Attrib)); + } + } + IAlloc_Free(allocTemp, *lwtVector); + *lwtVector = NULL; + break; + } + case k7zIdMTime: + { + RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); + RINOK(SzReadSwitch(sd)); + for (i = 0; i < numFiles; i++) + { + CSzFileItem *f = &files[i]; + Byte defined = (*lwtVector)[i]; + f->MTimeDefined = defined; + f->MTime.Low = f->MTime.High = 0; + if (defined) + { + RINOK(SzReadUInt32(sd, &f->MTime.Low)); + RINOK(SzReadUInt32(sd, &f->MTime.High)); + } + } + IAlloc_Free(allocTemp, *lwtVector); + *lwtVector = NULL; + break; + } + default: + { + RINOK(SzSkeepDataSize(sd, size)); + } + } + } + + { + UInt32 emptyFileIndex = 0; + UInt32 sizeIndex = 0; + for (i = 0; i < numFiles; i++) + { + CSzFileItem *file = files + i; + file->IsAnti = 0; + if (*emptyStreamVector == 0) + file->HasStream = 1; + else + file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); + if (file->HasStream) + { + file->IsDir = 0; + file->Size = (*unpackSizes)[sizeIndex]; + file->Crc = (*digests)[sizeIndex]; + file->CrcDefined = (Byte)(*digestsDefined)[sizeIndex]; + sizeIndex++; + } + else + { + if (*emptyFileVector == 0) + file->IsDir = 1; + else + file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); + emptyFileIndex++; + file->Size = 0; + file->Crc = 0; + file->CrcDefined = 0; + } + } + } + return SzArEx_Fill(p, allocMain); +} + +static SRes SzReadHeader( + CSzArEx *p, + CSzData *sd, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + UInt64 *unpackSizes = 0; + Byte *digestsDefined = 0; + UInt32 *digests = 0; + Byte *emptyStreamVector = 0; + Byte *emptyFileVector = 0; + Byte *lwtVector = 0; + SRes res = SzReadHeader2(p, sd, + &unpackSizes, &digestsDefined, &digests, + &emptyStreamVector, &emptyFileVector, &lwtVector, + allocMain, allocTemp); + IAlloc_Free(allocTemp, unpackSizes); + IAlloc_Free(allocTemp, digestsDefined); + IAlloc_Free(allocTemp, digests); + IAlloc_Free(allocTemp, emptyStreamVector); + IAlloc_Free(allocTemp, emptyFileVector); + IAlloc_Free(allocTemp, lwtVector); + return res; +} + +static SRes SzReadAndDecodePackedStreams2( + ILookInStream *inStream, + CSzData *sd, + CBuf *outBuffer, + UInt64 baseOffset, + CSzAr *p, + UInt64 **unpackSizes, + Byte **digestsDefined, + UInt32 **digests, + ISzAlloc *allocTemp) +{ + + UInt32 numUnpackStreams = 0; + UInt64 dataStartPos; + CSzFolder *folder; + UInt64 unpackSize; + SRes res; + + RINOK(SzReadStreamsInfo(sd, &dataStartPos, p, + &numUnpackStreams, unpackSizes, digestsDefined, digests, + allocTemp, allocTemp)); + + dataStartPos += baseOffset; + if (p->NumFolders != 1) + return SZ_ERROR_ARCHIVE; + + folder = p->Folders; + unpackSize = SzFolder_GetUnpackSize(folder); + + RINOK(LookInStream_SeekTo(inStream, dataStartPos)); + + if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp)) + return SZ_ERROR_MEM; + + res = SzFolder_Decode(folder, p->PackSizes, + inStream, dataStartPos, + outBuffer->data, (size_t)unpackSize, allocTemp); + RINOK(res); + if (folder->UnpackCRCDefined) + if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC) + return SZ_ERROR_CRC; + return SZ_OK; +} + +static SRes SzReadAndDecodePackedStreams( + ILookInStream *inStream, + CSzData *sd, + CBuf *outBuffer, + UInt64 baseOffset, + ISzAlloc *allocTemp) +{ + CSzAr p; + UInt64 *unpackSizes = 0; + Byte *digestsDefined = 0; + UInt32 *digests = 0; + SRes res; + SzAr_Init(&p); + res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, + &p, &unpackSizes, &digestsDefined, &digests, + allocTemp); + SzAr_Free(&p, allocTemp); + IAlloc_Free(allocTemp, unpackSizes); + IAlloc_Free(allocTemp, digestsDefined); + IAlloc_Free(allocTemp, digests); + return res; +} + +static SRes SzArEx_Open2( + CSzArEx *p, + ILookInStream *inStream, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + Byte header[k7zStartHeaderSize]; + Int64 startArcPos; + UInt64 nextHeaderOffset, nextHeaderSize; + size_t nextHeaderSizeT; + UInt32 nextHeaderCRC; + CBuf buffer; + SRes res; + + startArcPos = 0; + RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR)); + + RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); + + if (!TestSignatureCandidate(header)) + return SZ_ERROR_NO_ARCHIVE; + if (header[6] != k7zMajorVersion) + return SZ_ERROR_UNSUPPORTED; + + nextHeaderOffset = GetUi64(header + 12); + nextHeaderSize = GetUi64(header + 20); + nextHeaderCRC = GetUi32(header + 28); + + p->startPosAfterHeader = startArcPos + k7zStartHeaderSize; + + if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) + return SZ_ERROR_CRC; + + nextHeaderSizeT = (size_t)nextHeaderSize; + if (nextHeaderSizeT != nextHeaderSize) + return SZ_ERROR_MEM; + if (nextHeaderSizeT == 0) + return SZ_OK; + if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || + nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) + return SZ_ERROR_NO_ARCHIVE; + + { + Int64 pos = 0; + RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); + if ((UInt64)pos < startArcPos + nextHeaderOffset || + (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || + (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) + return SZ_ERROR_INPUT_EOF; + } + + RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset)); + + if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) + return SZ_ERROR_MEM; + + res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT); + if (res == SZ_OK) + { + res = SZ_ERROR_ARCHIVE; + if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC) + { + CSzData sd; + UInt64 type; + sd.Data = buffer.data; + sd.Size = buffer.size; + res = SzReadID(&sd, &type); + if (res == SZ_OK) + { + if (type == k7zIdEncodedHeader) + { + CBuf outBuffer; + Buf_Init(&outBuffer); + res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp); + if (res != SZ_OK) + Buf_Free(&outBuffer, allocTemp); + else + { + Buf_Free(&buffer, allocTemp); + buffer.data = outBuffer.data; + buffer.size = outBuffer.size; + sd.Data = buffer.data; + sd.Size = buffer.size; + res = SzReadID(&sd, &type); + } + } + } + if (res == SZ_OK) + { + if (type == k7zIdHeader) + res = SzReadHeader(p, &sd, allocMain, allocTemp); + else + res = SZ_ERROR_UNSUPPORTED; + } + } + } + Buf_Free(&buffer, allocTemp); + return res; +} + +SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) +{ + SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); + if (res != SZ_OK) + SzArEx_Free(p, allocMain); + return res; +} + +SRes SzArEx_Extract( + const CSzArEx *p, + ILookInStream *inStream, + UInt32 fileIndex, + UInt32 *blockIndex, + Byte **outBuffer, + size_t *outBufferSize, + size_t *offset, + size_t *outSizeProcessed, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; + SRes res = SZ_OK; + *offset = 0; + *outSizeProcessed = 0; + if (folderIndex == (UInt32)-1) + { + IAlloc_Free(allocMain, *outBuffer); + *blockIndex = folderIndex; + *outBuffer = 0; + *outBufferSize = 0; + return SZ_OK; + } + + if (*outBuffer == 0 || *blockIndex != folderIndex) + { + CSzFolder *folder = p->db.Folders + folderIndex; + UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); + size_t unpackSize = (size_t)unpackSizeSpec; + UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); + + if (unpackSize != unpackSizeSpec) + return SZ_ERROR_MEM; + *blockIndex = folderIndex; + IAlloc_Free(allocMain, *outBuffer); + *outBuffer = 0; + + RINOK(LookInStream_SeekTo(inStream, startOffset)); + + if (res == SZ_OK) + { + *outBufferSize = unpackSize; + if (unpackSize != 0) + { + *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); + if (*outBuffer == 0) + res = SZ_ERROR_MEM; + } + if (res == SZ_OK) + { + res = SzFolder_Decode(folder, + p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], + inStream, startOffset, + *outBuffer, unpackSize, allocTemp); + if (res == SZ_OK) + { + if (folder->UnpackCRCDefined) + { + if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) + res = SZ_ERROR_CRC; + } + } + } + } + } + if (res == SZ_OK) + { + UInt32 i; + CSzFileItem *fileItem = p->db.Files + fileIndex; + *offset = 0; + for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) + *offset += (UInt32)p->db.Files[i].Size; + *outSizeProcessed = (size_t)fileItem->Size; + if (*offset + *outSizeProcessed > *outBufferSize) + return SZ_ERROR_FAIL; + if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc) + res = SZ_ERROR_CRC; + } + return res; +} diff --git a/Installer/lzma/7zMemInStream.c b/Installer/lzma/7zMemInStream.c index ba32e601..74758c31 100644 --- a/Installer/lzma/7zMemInStream.c +++ b/Installer/lzma/7zMemInStream.c @@ -1,84 +1,84 @@ -/* 7zMemInStream.c -- Memory input stream -** 2012 - Birunthan Mohanathas -** -** This file is public domain. -*/ - -#include "7zMemInStream.h" - -static SRes MemInStream_Look(void *pp, const void **buf, size_t *size) -{ - CMemInStream *p = (CMemInStream *)pp; - size_t remaining = p->end - p->pos; - if (remaining == 0 && *size > 0) - { - // Restart stream. - p->pos = 0; - remaining = *size; - } - - if (remaining < *size) - { - *size = remaining; - } - - *buf = p->pos; - return SZ_OK; -} - -static SRes MemInStream_Skip(void *pp, size_t offset) -{ - CMemInStream *p = (CMemInStream *)pp; - p->pos += offset; - return SZ_OK; -} - -static SRes MemInStream_Read(void *pp, void *buf, size_t *size) -{ - CMemInStream *p = (CMemInStream *)pp; - size_t remaining = p->end - p->pos; - if (remaining == 0) - { - // End of stream. - *size = 0; - } - else - { - if (remaining > *size) - { - remaining = *size; - } - - memcpy(buf, p->pos, remaining); - p->pos += remaining; - *size = remaining; - } - - return SZ_OK; -} - -static SRes MemInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) -{ - CMemInStream *p = (CMemInStream *)pp; - switch (origin) - { - case SZ_SEEK_SET: p->pos = p->begin + *pos; break; - case SZ_SEEK_CUR: p->pos += *pos; break; - case SZ_SEEK_END: p->pos = p->end - *pos; break; - default: return 1; - } - - *pos = p->pos - p->begin; - return SZ_OK; -} - -void MemInStream_Init(CMemInStream *p, const void *begin, size_t length) -{ - p->begin = p->pos = (Byte *)begin; - p->end = p->begin + length; - - p->s.Look = MemInStream_Look; - p->s.Skip = MemInStream_Skip; - p->s.Read = MemInStream_Read; - p->s.Seek = MemInStream_Seek; -} +/* 7zMemInStream.c -- Memory input stream +** 2012 - Birunthan Mohanathas +** +** This file is public domain. +*/ + +#include "7zMemInStream.h" + +static SRes MemInStream_Look(void *pp, const void **buf, size_t *size) +{ + CMemInStream *p = (CMemInStream *)pp; + size_t remaining = p->end - p->pos; + if (remaining == 0 && *size > 0) + { + // Restart stream. + p->pos = 0; + remaining = *size; + } + + if (remaining < *size) + { + *size = remaining; + } + + *buf = p->pos; + return SZ_OK; +} + +static SRes MemInStream_Skip(void *pp, size_t offset) +{ + CMemInStream *p = (CMemInStream *)pp; + p->pos += offset; + return SZ_OK; +} + +static SRes MemInStream_Read(void *pp, void *buf, size_t *size) +{ + CMemInStream *p = (CMemInStream *)pp; + size_t remaining = p->end - p->pos; + if (remaining == 0) + { + // End of stream. + *size = 0; + } + else + { + if (remaining > *size) + { + remaining = *size; + } + + memcpy(buf, p->pos, remaining); + p->pos += remaining; + *size = remaining; + } + + return SZ_OK; +} + +static SRes MemInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) +{ + CMemInStream *p = (CMemInStream *)pp; + switch (origin) + { + case SZ_SEEK_SET: p->pos = p->begin + *pos; break; + case SZ_SEEK_CUR: p->pos += *pos; break; + case SZ_SEEK_END: p->pos = p->end - *pos; break; + default: return 1; + } + + *pos = p->pos - p->begin; + return SZ_OK; +} + +void MemInStream_Init(CMemInStream *p, const void *begin, size_t length) +{ + p->begin = p->pos = (Byte *)begin; + p->end = p->begin + length; + + p->s.Look = MemInStream_Look; + p->s.Skip = MemInStream_Skip; + p->s.Read = MemInStream_Read; + p->s.Seek = MemInStream_Seek; +} diff --git a/Installer/lzma/7zMemInStream.h b/Installer/lzma/7zMemInStream.h index 182b4cd4..f11ad0e6 100644 --- a/Installer/lzma/7zMemInStream.h +++ b/Installer/lzma/7zMemInStream.h @@ -1,26 +1,26 @@ -/* 7zMemInStream.h -- Memory input stream -** 2012 - Birunthan Mohanathas -** -** This file is public domain. -*/ - -#ifndef __7Z_MEMINSTREAM_H -#define __7Z_MEMINSTREAM_H - -#include "Types.h" - -EXTERN_C_BEGIN - -typedef struct -{ - ILookInStream s; - const Byte *begin; - const Byte *pos; - const Byte *end; -} CMemInStream; - -void MemInStream_Init(CMemInStream *p, const void *begin, size_t length); - -EXTERN_C_END - -#endif +/* 7zMemInStream.h -- Memory input stream +** 2012 - Birunthan Mohanathas +** +** This file is public domain. +*/ + +#ifndef __7Z_MEMINSTREAM_H +#define __7Z_MEMINSTREAM_H + +#include "Types.h" + +EXTERN_C_BEGIN + +typedef struct +{ + ILookInStream s; + const Byte *begin; + const Byte *pos; + const Byte *end; +} CMemInStream; + +void MemInStream_Init(CMemInStream *p, const void *begin, size_t length); + +EXTERN_C_END + +#endif diff --git a/Installer/lzma/7zStream.c b/Installer/lzma/7zStream.c index f0959fb0..0ebb7b5f 100644 --- a/Installer/lzma/7zStream.c +++ b/Installer/lzma/7zStream.c @@ -1,169 +1,169 @@ -/* 7zStream.c -- 7z Stream functions -2010-03-11 : Igor Pavlov : Public domain */ - -#include - -#include "Types.h" - -SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) -{ - while (size != 0) - { - size_t processed = size; - RINOK(stream->Read(stream, buf, &processed)); - if (processed == 0) - return errorType; - buf = (void *)((Byte *)buf + processed); - size -= processed; - } - return SZ_OK; -} - -SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size) -{ - return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); -} - -SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) -{ - size_t processed = 1; - RINOK(stream->Read(stream, buf, &processed)); - return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; -} - -SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) -{ - Int64 t = offset; - return stream->Seek(stream, &t, SZ_SEEK_SET); -} - -SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) -{ - const void *lookBuf; - if (*size == 0) - return SZ_OK; - RINOK(stream->Look(stream, &lookBuf, size)); - memcpy(buf, lookBuf, *size); - return stream->Skip(stream, *size); -} - -SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) -{ - while (size != 0) - { - size_t processed = size; - RINOK(stream->Read(stream, buf, &processed)); - if (processed == 0) - return errorType; - buf = (void *)((Byte *)buf + processed); - size -= processed; - } - return SZ_OK; -} - -SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) -{ - return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); -} - -static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size) -{ - SRes res = SZ_OK; - CLookToRead *p = (CLookToRead *)pp; - size_t size2 = p->size - p->pos; - if (size2 == 0 && *size > 0) - { - p->pos = 0; - size2 = LookToRead_BUF_SIZE; - res = p->realStream->Read(p->realStream, p->buf, &size2); - p->size = size2; - } - if (size2 < *size) - *size = size2; - *buf = p->buf + p->pos; - return res; -} - -static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size) -{ - SRes res = SZ_OK; - CLookToRead *p = (CLookToRead *)pp; - size_t size2 = p->size - p->pos; - if (size2 == 0 && *size > 0) - { - p->pos = 0; - if (*size > LookToRead_BUF_SIZE) - *size = LookToRead_BUF_SIZE; - res = p->realStream->Read(p->realStream, p->buf, size); - size2 = p->size = *size; - } - if (size2 < *size) - *size = size2; - *buf = p->buf + p->pos; - return res; -} - -static SRes LookToRead_Skip(void *pp, size_t offset) -{ - CLookToRead *p = (CLookToRead *)pp; - p->pos += offset; - return SZ_OK; -} - -static SRes LookToRead_Read(void *pp, void *buf, size_t *size) -{ - CLookToRead *p = (CLookToRead *)pp; - size_t rem = p->size - p->pos; - if (rem == 0) - return p->realStream->Read(p->realStream, buf, size); - if (rem > *size) - rem = *size; - memcpy(buf, p->buf + p->pos, rem); - p->pos += rem; - *size = rem; - return SZ_OK; -} - -static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin) -{ - CLookToRead *p = (CLookToRead *)pp; - p->pos = p->size = 0; - return p->realStream->Seek(p->realStream, pos, origin); -} - -void LookToRead_CreateVTable(CLookToRead *p, int lookahead) -{ - p->s.Look = lookahead ? - LookToRead_Look_Lookahead : - LookToRead_Look_Exact; - p->s.Skip = LookToRead_Skip; - p->s.Read = LookToRead_Read; - p->s.Seek = LookToRead_Seek; -} - -void LookToRead_Init(CLookToRead *p) -{ - p->pos = p->size = 0; -} - -static SRes SecToLook_Read(void *pp, void *buf, size_t *size) -{ - CSecToLook *p = (CSecToLook *)pp; - return LookInStream_LookRead(p->realStream, buf, size); -} - -void SecToLook_CreateVTable(CSecToLook *p) -{ - p->s.Read = SecToLook_Read; -} - -static SRes SecToRead_Read(void *pp, void *buf, size_t *size) -{ - CSecToRead *p = (CSecToRead *)pp; - return p->realStream->Read(p->realStream, buf, size); -} - -void SecToRead_CreateVTable(CSecToRead *p) -{ - p->s.Read = SecToRead_Read; -} +/* 7zStream.c -- 7z Stream functions +2010-03-11 : Igor Pavlov : Public domain */ + +#include + +#include "Types.h" + +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) +{ + while (size != 0) + { + size_t processed = size; + RINOK(stream->Read(stream, buf, &processed)); + if (processed == 0) + return errorType; + buf = (void *)((Byte *)buf + processed); + size -= processed; + } + return SZ_OK; +} + +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size) +{ + return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); +} + +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) +{ + size_t processed = 1; + RINOK(stream->Read(stream, buf, &processed)); + return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; +} + +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) +{ + Int64 t = offset; + return stream->Seek(stream, &t, SZ_SEEK_SET); +} + +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) +{ + const void *lookBuf; + if (*size == 0) + return SZ_OK; + RINOK(stream->Look(stream, &lookBuf, size)); + memcpy(buf, lookBuf, *size); + return stream->Skip(stream, *size); +} + +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) +{ + while (size != 0) + { + size_t processed = size; + RINOK(stream->Read(stream, buf, &processed)); + if (processed == 0) + return errorType; + buf = (void *)((Byte *)buf + processed); + size -= processed; + } + return SZ_OK; +} + +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) +{ + return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); +} + +static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size) +{ + SRes res = SZ_OK; + CLookToRead *p = (CLookToRead *)pp; + size_t size2 = p->size - p->pos; + if (size2 == 0 && *size > 0) + { + p->pos = 0; + size2 = LookToRead_BUF_SIZE; + res = p->realStream->Read(p->realStream, p->buf, &size2); + p->size = size2; + } + if (size2 < *size) + *size = size2; + *buf = p->buf + p->pos; + return res; +} + +static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size) +{ + SRes res = SZ_OK; + CLookToRead *p = (CLookToRead *)pp; + size_t size2 = p->size - p->pos; + if (size2 == 0 && *size > 0) + { + p->pos = 0; + if (*size > LookToRead_BUF_SIZE) + *size = LookToRead_BUF_SIZE; + res = p->realStream->Read(p->realStream, p->buf, size); + size2 = p->size = *size; + } + if (size2 < *size) + *size = size2; + *buf = p->buf + p->pos; + return res; +} + +static SRes LookToRead_Skip(void *pp, size_t offset) +{ + CLookToRead *p = (CLookToRead *)pp; + p->pos += offset; + return SZ_OK; +} + +static SRes LookToRead_Read(void *pp, void *buf, size_t *size) +{ + CLookToRead *p = (CLookToRead *)pp; + size_t rem = p->size - p->pos; + if (rem == 0) + return p->realStream->Read(p->realStream, buf, size); + if (rem > *size) + rem = *size; + memcpy(buf, p->buf + p->pos, rem); + p->pos += rem; + *size = rem; + return SZ_OK; +} + +static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin) +{ + CLookToRead *p = (CLookToRead *)pp; + p->pos = p->size = 0; + return p->realStream->Seek(p->realStream, pos, origin); +} + +void LookToRead_CreateVTable(CLookToRead *p, int lookahead) +{ + p->s.Look = lookahead ? + LookToRead_Look_Lookahead : + LookToRead_Look_Exact; + p->s.Skip = LookToRead_Skip; + p->s.Read = LookToRead_Read; + p->s.Seek = LookToRead_Seek; +} + +void LookToRead_Init(CLookToRead *p) +{ + p->pos = p->size = 0; +} + +static SRes SecToLook_Read(void *pp, void *buf, size_t *size) +{ + CSecToLook *p = (CSecToLook *)pp; + return LookInStream_LookRead(p->realStream, buf, size); +} + +void SecToLook_CreateVTable(CSecToLook *p) +{ + p->s.Read = SecToLook_Read; +} + +static SRes SecToRead_Read(void *pp, void *buf, size_t *size) +{ + CSecToRead *p = (CSecToRead *)pp; + return p->realStream->Read(p->realStream, buf, size); +} + +void SecToRead_CreateVTable(CSecToRead *p) +{ + p->s.Read = SecToRead_Read; +} diff --git a/Installer/lzma/7zVersion.h b/Installer/lzma/7zVersion.h index d4ac470e..9d99c5df 100644 --- a/Installer/lzma/7zVersion.h +++ b/Installer/lzma/7zVersion.h @@ -1,7 +1,7 @@ -#define MY_VER_MAJOR 9 -#define MY_VER_MINOR 20 -#define MY_VER_BUILD 0 -#define MY_VERSION "9.20" -#define MY_DATE "2010-11-18" -#define MY_COPYRIGHT ": Igor Pavlov : Public domain" -#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE +#define MY_VER_MAJOR 9 +#define MY_VER_MINOR 20 +#define MY_VER_BUILD 0 +#define MY_VERSION "9.20" +#define MY_DATE "2010-11-18" +#define MY_COPYRIGHT ": Igor Pavlov : Public domain" +#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE diff --git a/Installer/lzma/Alloc.c b/Installer/lzma/Alloc.c index bb24a772..358a7b52 100644 --- a/Installer/lzma/Alloc.c +++ b/Installer/lzma/Alloc.c @@ -1,127 +1,127 @@ -/* Alloc.c -- Memory allocation functions -2008-09-24 -Igor Pavlov -Public domain */ - -#ifdef _WIN32 -#include -#endif -#include - -#include "Alloc.h" - -/* #define _SZ_ALLOC_DEBUG */ - -/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ -#ifdef _SZ_ALLOC_DEBUG -#include -int g_allocCount = 0; -int g_allocCountMid = 0; -int g_allocCountBig = 0; -#endif - -void *MyAlloc(size_t size) -{ - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - { - void *p = malloc(size); - fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); - return p; - } - #else - return malloc(size); - #endif -} - -void MyFree(void *address) -{ - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); - #endif - free(address); -} - -#ifdef _WIN32 - -void *MidAlloc(size_t size) -{ - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); - #endif - return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); -} - -void MidFree(void *address) -{ - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); - #endif - if (address == 0) - return; - VirtualFree(address, 0, MEM_RELEASE); -} - -#ifndef MEM_LARGE_PAGES -#undef _7ZIP_LARGE_PAGES -#endif - -#ifdef _7ZIP_LARGE_PAGES -SIZE_T g_LargePageSize = 0; -typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); -#endif - -void SetLargePageSize() -{ - #ifdef _7ZIP_LARGE_PAGES - SIZE_T size = 0; - GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) - GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); - if (largePageMinimum == 0) - return; - size = largePageMinimum(); - if (size == 0 || (size & (size - 1)) != 0) - return; - g_LargePageSize = size; - #endif -} - - -void *BigAlloc(size_t size) -{ - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); - #endif - - #ifdef _7ZIP_LARGE_PAGES - if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) - { - void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), - MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); - if (res != 0) - return res; - } - #endif - return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); -} - -void BigFree(void *address) -{ - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); - #endif - - if (address == 0) - return; - VirtualFree(address, 0, MEM_RELEASE); -} - -#endif +/* Alloc.c -- Memory allocation functions +2008-09-24 +Igor Pavlov +Public domain */ + +#ifdef _WIN32 +#include +#endif +#include + +#include "Alloc.h" + +/* #define _SZ_ALLOC_DEBUG */ + +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ +#ifdef _SZ_ALLOC_DEBUG +#include +int g_allocCount = 0; +int g_allocCountMid = 0; +int g_allocCountBig = 0; +#endif + +void *MyAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + { + void *p = malloc(size); + fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); + return p; + } + #else + return malloc(size); + #endif +} + +void MyFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); + #endif + free(address); +} + +#ifdef _WIN32 + +void *MidAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); + #endif + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void MidFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); + #endif + if (address == 0) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#ifndef MEM_LARGE_PAGES +#undef _7ZIP_LARGE_PAGES +#endif + +#ifdef _7ZIP_LARGE_PAGES +SIZE_T g_LargePageSize = 0; +typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); +#endif + +void SetLargePageSize() +{ + #ifdef _7ZIP_LARGE_PAGES + SIZE_T size = 0; + GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); + if (largePageMinimum == 0) + return; + size = largePageMinimum(); + if (size == 0 || (size & (size - 1)) != 0) + return; + g_LargePageSize = size; + #endif +} + + +void *BigAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); + #endif + + #ifdef _7ZIP_LARGE_PAGES + if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) + { + void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), + MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); + if (res != 0) + return res; + } + #endif + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void BigFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); + #endif + + if (address == 0) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#endif diff --git a/Installer/lzma/Alloc.h b/Installer/lzma/Alloc.h index 6b3f0347..b8e41436 100644 --- a/Installer/lzma/Alloc.h +++ b/Installer/lzma/Alloc.h @@ -1,38 +1,38 @@ -/* Alloc.h -- Memory allocation functions -2009-02-07 : Igor Pavlov : Public domain */ - -#ifndef __COMMON_ALLOC_H -#define __COMMON_ALLOC_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -void *MyAlloc(size_t size); -void MyFree(void *address); - -#ifdef _WIN32 - -void SetLargePageSize(); - -void *MidAlloc(size_t size); -void MidFree(void *address); -void *BigAlloc(size_t size); -void BigFree(void *address); - -#else - -#define MidAlloc(size) MyAlloc(size) -#define MidFree(address) MyFree(address) -#define BigAlloc(size) MyAlloc(size) -#define BigFree(address) MyFree(address) - -#endif - -#ifdef __cplusplus -} -#endif - -#endif +/* Alloc.h -- Memory allocation functions +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __COMMON_ALLOC_H +#define __COMMON_ALLOC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void *MyAlloc(size_t size); +void MyFree(void *address); + +#ifdef _WIN32 + +void SetLargePageSize(); + +void *MidAlloc(size_t size); +void MidFree(void *address); +void *BigAlloc(size_t size); +void BigFree(void *address); + +#else + +#define MidAlloc(size) MyAlloc(size) +#define MidFree(address) MyFree(address) +#define BigAlloc(size) MyAlloc(size) +#define BigFree(address) MyFree(address) + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Installer/lzma/Bcj2.c b/Installer/lzma/Bcj2.c index 474bdd45..20199ce5 100644 --- a/Installer/lzma/Bcj2.c +++ b/Installer/lzma/Bcj2.c @@ -1,132 +1,132 @@ -/* Bcj2.c -- Converter for x86 code (BCJ2) -2008-10-04 : Igor Pavlov : Public domain */ - -#include "Bcj2.h" - -#ifdef _LZMA_PROB32 -#define CProb UInt32 -#else -#define CProb UInt16 -#endif - -#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) -#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) - -#define kNumTopBits 24 -#define kTopValue ((UInt32)1 << kNumTopBits) - -#define kNumBitModelTotalBits 11 -#define kBitModelTotal (1 << kNumBitModelTotalBits) -#define kNumMoveBits 5 - -#define RC_READ_BYTE (*buffer++) -#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } -#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ - { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }} - -#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; } - -#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) -#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; -#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; - -int Bcj2_Decode( - const Byte *buf0, SizeT size0, - const Byte *buf1, SizeT size1, - const Byte *buf2, SizeT size2, - const Byte *buf3, SizeT size3, - Byte *outBuf, SizeT outSize) -{ - CProb p[256 + 2]; - SizeT inPos = 0, outPos = 0; - - const Byte *buffer, *bufferLim; - UInt32 range, code; - Byte prevByte = 0; - - unsigned int i; - for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) - p[i] = kBitModelTotal >> 1; - - buffer = buf3; - bufferLim = buffer + size3; - RC_INIT2 - - if (outSize == 0) - return SZ_OK; - - for (;;) - { - Byte b; - CProb *prob; - UInt32 bound; - UInt32 ttt; - - SizeT limit = size0 - inPos; - if (outSize - outPos < limit) - limit = outSize - outPos; - while (limit != 0) - { - Byte b = buf0[inPos]; - outBuf[outPos++] = b; - if (IsJ(prevByte, b)) - break; - inPos++; - prevByte = b; - limit--; - } - - if (limit == 0 || outPos == outSize) - break; - - b = buf0[inPos++]; - - if (b == 0xE8) - prob = p + prevByte; - else if (b == 0xE9) - prob = p + 256; - else - prob = p + 257; - - IF_BIT_0(prob) - { - UPDATE_0(prob) - prevByte = b; - } - else - { - UInt32 dest; - const Byte *v; - UPDATE_1(prob) - if (b == 0xE8) - { - v = buf1; - if (size1 < 4) - return SZ_ERROR_DATA; - buf1 += 4; - size1 -= 4; - } - else - { - v = buf2; - if (size2 < 4) - return SZ_ERROR_DATA; - buf2 += 4; - size2 -= 4; - } - dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | - ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); - outBuf[outPos++] = (Byte)dest; - if (outPos == outSize) - break; - outBuf[outPos++] = (Byte)(dest >> 8); - if (outPos == outSize) - break; - outBuf[outPos++] = (Byte)(dest >> 16); - if (outPos == outSize) - break; - outBuf[outPos++] = prevByte = (Byte)(dest >> 24); - } - } - return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA; -} +/* Bcj2.c -- Converter for x86 code (BCJ2) +2008-10-04 : Igor Pavlov : Public domain */ + +#include "Bcj2.h" + +#ifdef _LZMA_PROB32 +#define CProb UInt32 +#else +#define CProb UInt16 +#endif + +#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) +#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_READ_BYTE (*buffer++) +#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } +#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ + { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }} + +#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; } + +#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; + +int Bcj2_Decode( + const Byte *buf0, SizeT size0, + const Byte *buf1, SizeT size1, + const Byte *buf2, SizeT size2, + const Byte *buf3, SizeT size3, + Byte *outBuf, SizeT outSize) +{ + CProb p[256 + 2]; + SizeT inPos = 0, outPos = 0; + + const Byte *buffer, *bufferLim; + UInt32 range, code; + Byte prevByte = 0; + + unsigned int i; + for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) + p[i] = kBitModelTotal >> 1; + + buffer = buf3; + bufferLim = buffer + size3; + RC_INIT2 + + if (outSize == 0) + return SZ_OK; + + for (;;) + { + Byte b; + CProb *prob; + UInt32 bound; + UInt32 ttt; + + SizeT limit = size0 - inPos; + if (outSize - outPos < limit) + limit = outSize - outPos; + while (limit != 0) + { + Byte b = buf0[inPos]; + outBuf[outPos++] = b; + if (IsJ(prevByte, b)) + break; + inPos++; + prevByte = b; + limit--; + } + + if (limit == 0 || outPos == outSize) + break; + + b = buf0[inPos++]; + + if (b == 0xE8) + prob = p + prevByte; + else if (b == 0xE9) + prob = p + 256; + else + prob = p + 257; + + IF_BIT_0(prob) + { + UPDATE_0(prob) + prevByte = b; + } + else + { + UInt32 dest; + const Byte *v; + UPDATE_1(prob) + if (b == 0xE8) + { + v = buf1; + if (size1 < 4) + return SZ_ERROR_DATA; + buf1 += 4; + size1 -= 4; + } + else + { + v = buf2; + if (size2 < 4) + return SZ_ERROR_DATA; + buf2 += 4; + size2 -= 4; + } + dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | + ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); + outBuf[outPos++] = (Byte)dest; + if (outPos == outSize) + break; + outBuf[outPos++] = (Byte)(dest >> 8); + if (outPos == outSize) + break; + outBuf[outPos++] = (Byte)(dest >> 16); + if (outPos == outSize) + break; + outBuf[outPos++] = prevByte = (Byte)(dest >> 24); + } + } + return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA; +} diff --git a/Installer/lzma/Bcj2.h b/Installer/lzma/Bcj2.h index d9d857bc..dbc05414 100644 --- a/Installer/lzma/Bcj2.h +++ b/Installer/lzma/Bcj2.h @@ -1,38 +1,38 @@ -/* Bcj2.h -- Converter for x86 code (BCJ2) -2009-02-07 : Igor Pavlov : Public domain */ - -#ifndef __BCJ2_H -#define __BCJ2_H - -#include "Types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* -Conditions: - outSize <= FullOutputSize, - where FullOutputSize is full size of output stream of x86_2 filter. - -If buf0 overlaps outBuf, there are two required conditions: - 1) (buf0 >= outBuf) - 2) (buf0 + size0 >= outBuf + FullOutputSize). - -Returns: - SZ_OK - SZ_ERROR_DATA - Data error -*/ - -int Bcj2_Decode( - const Byte *buf0, SizeT size0, - const Byte *buf1, SizeT size1, - const Byte *buf2, SizeT size2, - const Byte *buf3, SizeT size3, - Byte *outBuf, SizeT outSize); - -#ifdef __cplusplus -} -#endif - -#endif +/* Bcj2.h -- Converter for x86 code (BCJ2) +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __BCJ2_H +#define __BCJ2_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* +Conditions: + outSize <= FullOutputSize, + where FullOutputSize is full size of output stream of x86_2 filter. + +If buf0 overlaps outBuf, there are two required conditions: + 1) (buf0 >= outBuf) + 2) (buf0 + size0 >= outBuf + FullOutputSize). + +Returns: + SZ_OK + SZ_ERROR_DATA - Data error +*/ + +int Bcj2_Decode( + const Byte *buf0, SizeT size0, + const Byte *buf1, SizeT size1, + const Byte *buf2, SizeT size2, + const Byte *buf3, SizeT size3, + Byte *outBuf, SizeT outSize); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Installer/lzma/Bra.c b/Installer/lzma/Bra.c index 2a0f147b..2e47b141 100644 --- a/Installer/lzma/Bra.c +++ b/Installer/lzma/Bra.c @@ -1,133 +1,133 @@ -/* Bra.c -- Converters for RISC code -2010-04-16 : Igor Pavlov : Public domain */ - -#include "Bra.h" - -SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) -{ - SizeT i; - if (size < 4) - return 0; - size -= 4; - ip += 8; - for (i = 0; i <= size; i += 4) - { - if (data[i + 3] == 0xEB) - { - UInt32 dest; - UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]); - src <<= 2; - if (encoding) - dest = ip + (UInt32)i + src; - else - dest = src - (ip + (UInt32)i); - dest >>= 2; - data[i + 2] = (Byte)(dest >> 16); - data[i + 1] = (Byte)(dest >> 8); - data[i + 0] = (Byte)dest; - } - } - return i; -} - -SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) -{ - SizeT i; - if (size < 4) - return 0; - size -= 4; - ip += 4; - for (i = 0; i <= size; i += 2) - { - if ((data[i + 1] & 0xF8) == 0xF0 && - (data[i + 3] & 0xF8) == 0xF8) - { - UInt32 dest; - UInt32 src = - (((UInt32)data[i + 1] & 0x7) << 19) | - ((UInt32)data[i + 0] << 11) | - (((UInt32)data[i + 3] & 0x7) << 8) | - (data[i + 2]); - - src <<= 1; - if (encoding) - dest = ip + (UInt32)i + src; - else - dest = src - (ip + (UInt32)i); - dest >>= 1; - - data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); - data[i + 0] = (Byte)(dest >> 11); - data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); - data[i + 2] = (Byte)dest; - i += 2; - } - } - return i; -} - -SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) -{ - SizeT i; - if (size < 4) - return 0; - size -= 4; - for (i = 0; i <= size; i += 4) - { - if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1) - { - UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) | - ((UInt32)data[i + 1] << 16) | - ((UInt32)data[i + 2] << 8) | - ((UInt32)data[i + 3] & (~3)); - - UInt32 dest; - if (encoding) - dest = ip + (UInt32)i + src; - else - dest = src - (ip + (UInt32)i); - data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); - data[i + 1] = (Byte)(dest >> 16); - data[i + 2] = (Byte)(dest >> 8); - data[i + 3] &= 0x3; - data[i + 3] |= dest; - } - } - return i; -} - -SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) -{ - UInt32 i; - if (size < 4) - return 0; - size -= 4; - for (i = 0; i <= size; i += 4) - { - if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) || - (data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0)) - { - UInt32 src = - ((UInt32)data[i + 0] << 24) | - ((UInt32)data[i + 1] << 16) | - ((UInt32)data[i + 2] << 8) | - ((UInt32)data[i + 3]); - UInt32 dest; - - src <<= 2; - if (encoding) - dest = ip + i + src; - else - dest = src - (ip + i); - dest >>= 2; - - dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; - - data[i + 0] = (Byte)(dest >> 24); - data[i + 1] = (Byte)(dest >> 16); - data[i + 2] = (Byte)(dest >> 8); - data[i + 3] = (Byte)dest; - } - } - return i; -} +/* Bra.c -- Converters for RISC code +2010-04-16 : Igor Pavlov : Public domain */ + +#include "Bra.h" + +SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 4) + return 0; + size -= 4; + ip += 8; + for (i = 0; i <= size; i += 4) + { + if (data[i + 3] == 0xEB) + { + UInt32 dest; + UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]); + src <<= 2; + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + dest >>= 2; + data[i + 2] = (Byte)(dest >> 16); + data[i + 1] = (Byte)(dest >> 8); + data[i + 0] = (Byte)dest; + } + } + return i; +} + +SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 4) + return 0; + size -= 4; + ip += 4; + for (i = 0; i <= size; i += 2) + { + if ((data[i + 1] & 0xF8) == 0xF0 && + (data[i + 3] & 0xF8) == 0xF8) + { + UInt32 dest; + UInt32 src = + (((UInt32)data[i + 1] & 0x7) << 19) | + ((UInt32)data[i + 0] << 11) | + (((UInt32)data[i + 3] & 0x7) << 8) | + (data[i + 2]); + + src <<= 1; + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + dest >>= 1; + + data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); + data[i + 0] = (Byte)(dest >> 11); + data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); + data[i + 2] = (Byte)dest; + i += 2; + } + } + return i; +} + +SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 4) + return 0; + size -= 4; + for (i = 0; i <= size; i += 4) + { + if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1) + { + UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) | + ((UInt32)data[i + 1] << 16) | + ((UInt32)data[i + 2] << 8) | + ((UInt32)data[i + 3] & (~3)); + + UInt32 dest; + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); + data[i + 1] = (Byte)(dest >> 16); + data[i + 2] = (Byte)(dest >> 8); + data[i + 3] &= 0x3; + data[i + 3] |= dest; + } + } + return i; +} + +SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + UInt32 i; + if (size < 4) + return 0; + size -= 4; + for (i = 0; i <= size; i += 4) + { + if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) || + (data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0)) + { + UInt32 src = + ((UInt32)data[i + 0] << 24) | + ((UInt32)data[i + 1] << 16) | + ((UInt32)data[i + 2] << 8) | + ((UInt32)data[i + 3]); + UInt32 dest; + + src <<= 2; + if (encoding) + dest = ip + i + src; + else + dest = src - (ip + i); + dest >>= 2; + + dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; + + data[i + 0] = (Byte)(dest >> 24); + data[i + 1] = (Byte)(dest >> 16); + data[i + 2] = (Byte)(dest >> 8); + data[i + 3] = (Byte)dest; + } + } + return i; +} diff --git a/Installer/lzma/Bra.h b/Installer/lzma/Bra.h index 9c91e332..5748c1c0 100644 --- a/Installer/lzma/Bra.h +++ b/Installer/lzma/Bra.h @@ -1,68 +1,68 @@ -/* Bra.h -- Branch converters for executables -2009-02-07 : Igor Pavlov : Public domain */ - -#ifndef __BRA_H -#define __BRA_H - -#include "Types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* -These functions convert relative addresses to absolute addresses -in CALL instructions to increase the compression ratio. - - In: - data - data buffer - size - size of data - ip - current virtual Instruction Pinter (IP) value - state - state variable for x86 converter - encoding - 0 (for decoding), 1 (for encoding) - - Out: - state - state variable for x86 converter - - Returns: - The number of processed bytes. If you call these functions with multiple calls, - you must start next call with first byte after block of processed bytes. - - Type Endian Alignment LookAhead - - x86 little 1 4 - ARMT little 2 2 - ARM little 4 0 - PPC big 4 0 - SPARC big 4 0 - IA64 little 16 0 - - size must be >= Alignment + LookAhead, if it's not last block. - If (size < Alignment + LookAhead), converter returns 0. - - Example: - - UInt32 ip = 0; - for () - { - ; size must be >= Alignment + LookAhead, if it's not last block - SizeT processed = Convert(data, size, ip, 1); - data += processed; - size -= processed; - ip += processed; - } -*/ - -#define x86_Convert_Init(state) { state = 0; } -SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); -SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); - -#ifdef __cplusplus -} -#endif - -#endif +/* Bra.h -- Branch converters for executables +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __BRA_H +#define __BRA_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* +These functions convert relative addresses to absolute addresses +in CALL instructions to increase the compression ratio. + + In: + data - data buffer + size - size of data + ip - current virtual Instruction Pinter (IP) value + state - state variable for x86 converter + encoding - 0 (for decoding), 1 (for encoding) + + Out: + state - state variable for x86 converter + + Returns: + The number of processed bytes. If you call these functions with multiple calls, + you must start next call with first byte after block of processed bytes. + + Type Endian Alignment LookAhead + + x86 little 1 4 + ARMT little 2 2 + ARM little 4 0 + PPC big 4 0 + SPARC big 4 0 + IA64 little 16 0 + + size must be >= Alignment + LookAhead, if it's not last block. + If (size < Alignment + LookAhead), converter returns 0. + + Example: + + UInt32 ip = 0; + for () + { + ; size must be >= Alignment + LookAhead, if it's not last block + SizeT processed = Convert(data, size, ip, 1); + data += processed; + size -= processed; + ip += processed; + } +*/ + +#define x86_Convert_Init(state) { state = 0; } +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); +SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Installer/lzma/Bra86.c b/Installer/lzma/Bra86.c index 93566cb2..1ee0e709 100644 --- a/Installer/lzma/Bra86.c +++ b/Installer/lzma/Bra86.c @@ -1,85 +1,85 @@ -/* Bra86.c -- Converter for x86 code (BCJ) -2008-10-04 : Igor Pavlov : Public domain */ - -#include "Bra.h" - -#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) - -const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; -const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; - -SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) -{ - SizeT bufferPos = 0, prevPosT; - UInt32 prevMask = *state & 0x7; - if (size < 5) - return 0; - ip += 5; - prevPosT = (SizeT)0 - 1; - - for (;;) - { - Byte *p = data + bufferPos; - Byte *limit = data + size - 4; - for (; p < limit; p++) - if ((*p & 0xFE) == 0xE8) - break; - bufferPos = (SizeT)(p - data); - if (p >= limit) - break; - prevPosT = bufferPos - prevPosT; - if (prevPosT > 3) - prevMask = 0; - else - { - prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; - if (prevMask != 0) - { - Byte b = p[4 - kMaskToBitNumber[prevMask]]; - if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) - { - prevPosT = bufferPos; - prevMask = ((prevMask << 1) & 0x7) | 1; - bufferPos++; - continue; - } - } - } - prevPosT = bufferPos; - - if (Test86MSByte(p[4])) - { - UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); - UInt32 dest; - for (;;) - { - Byte b; - int index; - if (encoding) - dest = (ip + (UInt32)bufferPos) + src; - else - dest = src - (ip + (UInt32)bufferPos); - if (prevMask == 0) - break; - index = kMaskToBitNumber[prevMask] * 8; - b = (Byte)(dest >> (24 - index)); - if (!Test86MSByte(b)) - break; - src = dest ^ ((1 << (32 - index)) - 1); - } - p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); - p[3] = (Byte)(dest >> 16); - p[2] = (Byte)(dest >> 8); - p[1] = (Byte)dest; - bufferPos += 5; - } - else - { - prevMask = ((prevMask << 1) & 0x7) | 1; - bufferPos++; - } - } - prevPosT = bufferPos - prevPosT; - *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); - return bufferPos; -} +/* Bra86.c -- Converter for x86 code (BCJ) +2008-10-04 : Igor Pavlov : Public domain */ + +#include "Bra.h" + +#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) + +const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; +const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; + +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) +{ + SizeT bufferPos = 0, prevPosT; + UInt32 prevMask = *state & 0x7; + if (size < 5) + return 0; + ip += 5; + prevPosT = (SizeT)0 - 1; + + for (;;) + { + Byte *p = data + bufferPos; + Byte *limit = data + size - 4; + for (; p < limit; p++) + if ((*p & 0xFE) == 0xE8) + break; + bufferPos = (SizeT)(p - data); + if (p >= limit) + break; + prevPosT = bufferPos - prevPosT; + if (prevPosT > 3) + prevMask = 0; + else + { + prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; + if (prevMask != 0) + { + Byte b = p[4 - kMaskToBitNumber[prevMask]]; + if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) + { + prevPosT = bufferPos; + prevMask = ((prevMask << 1) & 0x7) | 1; + bufferPos++; + continue; + } + } + } + prevPosT = bufferPos; + + if (Test86MSByte(p[4])) + { + UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); + UInt32 dest; + for (;;) + { + Byte b; + int index; + if (encoding) + dest = (ip + (UInt32)bufferPos) + src; + else + dest = src - (ip + (UInt32)bufferPos); + if (prevMask == 0) + break; + index = kMaskToBitNumber[prevMask] * 8; + b = (Byte)(dest >> (24 - index)); + if (!Test86MSByte(b)) + break; + src = dest ^ ((1 << (32 - index)) - 1); + } + p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); + p[3] = (Byte)(dest >> 16); + p[2] = (Byte)(dest >> 8); + p[1] = (Byte)dest; + bufferPos += 5; + } + else + { + prevMask = ((prevMask << 1) & 0x7) | 1; + bufferPos++; + } + } + prevPosT = bufferPos - prevPosT; + *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); + return bufferPos; +} diff --git a/Installer/lzma/CpuArch.c b/Installer/lzma/CpuArch.c index 36e7680d..260cc1f4 100644 --- a/Installer/lzma/CpuArch.c +++ b/Installer/lzma/CpuArch.c @@ -1,168 +1,168 @@ -/* CpuArch.c -- CPU specific code -2010-10-26: Igor Pavlov : Public domain */ - -#include "CpuArch.h" - -#ifdef MY_CPU_X86_OR_AMD64 - -#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) -#define USE_ASM -#endif - -#if defined(USE_ASM) && !defined(MY_CPU_AMD64) -static UInt32 CheckFlag(UInt32 flag) -{ - #ifdef _MSC_VER - __asm pushfd; - __asm pop EAX; - __asm mov EDX, EAX; - __asm xor EAX, flag; - __asm push EAX; - __asm popfd; - __asm pushfd; - __asm pop EAX; - __asm xor EAX, EDX; - __asm push EDX; - __asm popfd; - __asm and flag, EAX; - #else - __asm__ __volatile__ ( - "pushf\n\t" - "pop %%EAX\n\t" - "movl %%EAX,%%EDX\n\t" - "xorl %0,%%EAX\n\t" - "push %%EAX\n\t" - "popf\n\t" - "pushf\n\t" - "pop %%EAX\n\t" - "xorl %%EDX,%%EAX\n\t" - "push %%EDX\n\t" - "popf\n\t" - "andl %%EAX, %0\n\t": - "=c" (flag) : "c" (flag)); - #endif - return flag; -} -#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False; -#else -#define CHECK_CPUID_IS_SUPPORTED -#endif - -static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) -{ - #ifdef USE_ASM - - #ifdef _MSC_VER - - UInt32 a2, b2, c2, d2; - __asm xor EBX, EBX; - __asm xor ECX, ECX; - __asm xor EDX, EDX; - __asm mov EAX, function; - __asm cpuid; - __asm mov a2, EAX; - __asm mov b2, EBX; - __asm mov c2, ECX; - __asm mov d2, EDX; - - *a = a2; - *b = b2; - *c = c2; - *d = d2; - - #else - - __asm__ __volatile__ ( - "cpuid" - : "=a" (*a) , - "=b" (*b) , - "=c" (*c) , - "=d" (*d) - : "0" (function)) ; - - #endif - - #else - - int CPUInfo[4]; - __cpuid(CPUInfo, function); - *a = CPUInfo[0]; - *b = CPUInfo[1]; - *c = CPUInfo[2]; - *d = CPUInfo[3]; - - #endif -} - -Bool x86cpuid_CheckAndRead(Cx86cpuid *p) -{ - CHECK_CPUID_IS_SUPPORTED - MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); - MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); - return True; -} - -static UInt32 kVendors[][3] = -{ - { 0x756E6547, 0x49656E69, 0x6C65746E}, - { 0x68747541, 0x69746E65, 0x444D4163}, - { 0x746E6543, 0x48727561, 0x736C7561} -}; - -int x86cpuid_GetFirm(const Cx86cpuid *p) -{ - unsigned i; - for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) - { - const UInt32 *v = kVendors[i]; - if (v[0] == p->vendor[0] && - v[1] == p->vendor[1] && - v[2] == p->vendor[2]) - return (int)i; - } - return -1; -} - -Bool CPU_Is_InOrder() -{ - Cx86cpuid p; - int firm; - UInt32 family, model; - if (!x86cpuid_CheckAndRead(&p)) - return True; - family = x86cpuid_GetFamily(&p); - model = x86cpuid_GetModel(&p); - firm = x86cpuid_GetFirm(&p); - switch (firm) - { - case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C)); - case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); - case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); - } - return True; -} - -#if !defined(MY_CPU_AMD64) && defined(_WIN32) -static Bool CPU_Sys_Is_SSE_Supported() -{ - OSVERSIONINFO vi; - vi.dwOSVersionInfoSize = sizeof(vi); - if (!GetVersionEx(&vi)) - return False; - return (vi.dwMajorVersion >= 5); -} -#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; -#else -#define CHECK_SYS_SSE_SUPPORT -#endif - -Bool CPU_Is_Aes_Supported() -{ - Cx86cpuid p; - CHECK_SYS_SSE_SUPPORT - if (!x86cpuid_CheckAndRead(&p)) - return False; - return (p.c >> 25) & 1; -} - -#endif +/* CpuArch.c -- CPU specific code +2010-10-26: Igor Pavlov : Public domain */ + +#include "CpuArch.h" + +#ifdef MY_CPU_X86_OR_AMD64 + +#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) +#define USE_ASM +#endif + +#if defined(USE_ASM) && !defined(MY_CPU_AMD64) +static UInt32 CheckFlag(UInt32 flag) +{ + #ifdef _MSC_VER + __asm pushfd; + __asm pop EAX; + __asm mov EDX, EAX; + __asm xor EAX, flag; + __asm push EAX; + __asm popfd; + __asm pushfd; + __asm pop EAX; + __asm xor EAX, EDX; + __asm push EDX; + __asm popfd; + __asm and flag, EAX; + #else + __asm__ __volatile__ ( + "pushf\n\t" + "pop %%EAX\n\t" + "movl %%EAX,%%EDX\n\t" + "xorl %0,%%EAX\n\t" + "push %%EAX\n\t" + "popf\n\t" + "pushf\n\t" + "pop %%EAX\n\t" + "xorl %%EDX,%%EAX\n\t" + "push %%EDX\n\t" + "popf\n\t" + "andl %%EAX, %0\n\t": + "=c" (flag) : "c" (flag)); + #endif + return flag; +} +#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False; +#else +#define CHECK_CPUID_IS_SUPPORTED +#endif + +static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) +{ + #ifdef USE_ASM + + #ifdef _MSC_VER + + UInt32 a2, b2, c2, d2; + __asm xor EBX, EBX; + __asm xor ECX, ECX; + __asm xor EDX, EDX; + __asm mov EAX, function; + __asm cpuid; + __asm mov a2, EAX; + __asm mov b2, EBX; + __asm mov c2, ECX; + __asm mov d2, EDX; + + *a = a2; + *b = b2; + *c = c2; + *d = d2; + + #else + + __asm__ __volatile__ ( + "cpuid" + : "=a" (*a) , + "=b" (*b) , + "=c" (*c) , + "=d" (*d) + : "0" (function)) ; + + #endif + + #else + + int CPUInfo[4]; + __cpuid(CPUInfo, function); + *a = CPUInfo[0]; + *b = CPUInfo[1]; + *c = CPUInfo[2]; + *d = CPUInfo[3]; + + #endif +} + +Bool x86cpuid_CheckAndRead(Cx86cpuid *p) +{ + CHECK_CPUID_IS_SUPPORTED + MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); + MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); + return True; +} + +static UInt32 kVendors[][3] = +{ + { 0x756E6547, 0x49656E69, 0x6C65746E}, + { 0x68747541, 0x69746E65, 0x444D4163}, + { 0x746E6543, 0x48727561, 0x736C7561} +}; + +int x86cpuid_GetFirm(const Cx86cpuid *p) +{ + unsigned i; + for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) + { + const UInt32 *v = kVendors[i]; + if (v[0] == p->vendor[0] && + v[1] == p->vendor[1] && + v[2] == p->vendor[2]) + return (int)i; + } + return -1; +} + +Bool CPU_Is_InOrder() +{ + Cx86cpuid p; + int firm; + UInt32 family, model; + if (!x86cpuid_CheckAndRead(&p)) + return True; + family = x86cpuid_GetFamily(&p); + model = x86cpuid_GetModel(&p); + firm = x86cpuid_GetFirm(&p); + switch (firm) + { + case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C)); + case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); + case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); + } + return True; +} + +#if !defined(MY_CPU_AMD64) && defined(_WIN32) +static Bool CPU_Sys_Is_SSE_Supported() +{ + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (!GetVersionEx(&vi)) + return False; + return (vi.dwMajorVersion >= 5); +} +#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; +#else +#define CHECK_SYS_SSE_SUPPORT +#endif + +Bool CPU_Is_Aes_Supported() +{ + Cx86cpuid p; + CHECK_SYS_SSE_SUPPORT + if (!x86cpuid_CheckAndRead(&p)) + return False; + return (p.c >> 25) & 1; +} + +#endif diff --git a/Installer/lzma/CpuArch.h b/Installer/lzma/CpuArch.h index 0a709bb2..01930c7e 100644 --- a/Installer/lzma/CpuArch.h +++ b/Installer/lzma/CpuArch.h @@ -1,155 +1,155 @@ -/* CpuArch.h -- CPU specific code -2010-10-26: Igor Pavlov : Public domain */ - -#ifndef __CPU_ARCH_H -#define __CPU_ARCH_H - -#include "Types.h" - -EXTERN_C_BEGIN - -/* -MY_CPU_LE means that CPU is LITTLE ENDIAN. -If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN). - -MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. -If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform. -*/ - -#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) -#define MY_CPU_AMD64 -#endif - -#if defined(MY_CPU_AMD64) || defined(_M_IA64) -#define MY_CPU_64BIT -#endif - -#if defined(_M_IX86) || defined(__i386__) -#define MY_CPU_X86 -#endif - -#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) -#define MY_CPU_X86_OR_AMD64 -#endif - -#if defined(MY_CPU_X86) || defined(_M_ARM) -#define MY_CPU_32BIT -#endif - -#if defined(_WIN32) && defined(_M_ARM) -#define MY_CPU_ARM_LE -#endif - -#if defined(_WIN32) && defined(_M_IA64) -#define MY_CPU_IA64_LE -#endif - -#if defined(MY_CPU_X86_OR_AMD64) -#define MY_CPU_LE_UNALIGN -#endif - -#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__) -#define MY_CPU_LE -#endif - -#if defined(__BIG_ENDIAN__) -#define MY_CPU_BE -#endif - -#if defined(MY_CPU_LE) && defined(MY_CPU_BE) -Stop_Compiling_Bad_Endian -#endif - -#ifdef MY_CPU_LE_UNALIGN - -#define GetUi16(p) (*(const UInt16 *)(p)) -#define GetUi32(p) (*(const UInt32 *)(p)) -#define GetUi64(p) (*(const UInt64 *)(p)) -#define SetUi16(p, d) *(UInt16 *)(p) = (d); -#define SetUi32(p, d) *(UInt32 *)(p) = (d); -#define SetUi64(p, d) *(UInt64 *)(p) = (d); - -#else - -#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) - -#define GetUi32(p) ( \ - ((const Byte *)(p))[0] | \ - ((UInt32)((const Byte *)(p))[1] << 8) | \ - ((UInt32)((const Byte *)(p))[2] << 16) | \ - ((UInt32)((const Byte *)(p))[3] << 24)) - -#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) - -#define SetUi16(p, d) { UInt32 _x_ = (d); \ - ((Byte *)(p))[0] = (Byte)_x_; \ - ((Byte *)(p))[1] = (Byte)(_x_ >> 8); } - -#define SetUi32(p, d) { UInt32 _x_ = (d); \ - ((Byte *)(p))[0] = (Byte)_x_; \ - ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ - ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ - ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } - -#define SetUi64(p, d) { UInt64 _x64_ = (d); \ - SetUi32(p, (UInt32)_x64_); \ - SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); } - -#endif - -#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) - -#pragma intrinsic(_byteswap_ulong) -#pragma intrinsic(_byteswap_uint64) -#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) -#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) - -#else - -#define GetBe32(p) ( \ - ((UInt32)((const Byte *)(p))[0] << 24) | \ - ((UInt32)((const Byte *)(p))[1] << 16) | \ - ((UInt32)((const Byte *)(p))[2] << 8) | \ - ((const Byte *)(p))[3] ) - -#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) - -#endif - -#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) - - -#ifdef MY_CPU_X86_OR_AMD64 - -typedef struct -{ - UInt32 maxFunc; - UInt32 vendor[3]; - UInt32 ver; - UInt32 b; - UInt32 c; - UInt32 d; -} Cx86cpuid; - -enum -{ - CPU_FIRM_INTEL, - CPU_FIRM_AMD, - CPU_FIRM_VIA -}; - -Bool x86cpuid_CheckAndRead(Cx86cpuid *p); -int x86cpuid_GetFirm(const Cx86cpuid *p); - -#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F) -#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F) -#define x86cpuid_GetStepping(p) ((p)->ver & 0xF) - -Bool CPU_Is_InOrder(); -Bool CPU_Is_Aes_Supported(); - -#endif - -EXTERN_C_END - -#endif +/* CpuArch.h -- CPU specific code +2010-10-26: Igor Pavlov : Public domain */ + +#ifndef __CPU_ARCH_H +#define __CPU_ARCH_H + +#include "Types.h" + +EXTERN_C_BEGIN + +/* +MY_CPU_LE means that CPU is LITTLE ENDIAN. +If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN). + +MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. +If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform. +*/ + +#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) +#define MY_CPU_AMD64 +#endif + +#if defined(MY_CPU_AMD64) || defined(_M_IA64) +#define MY_CPU_64BIT +#endif + +#if defined(_M_IX86) || defined(__i386__) +#define MY_CPU_X86 +#endif + +#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) +#define MY_CPU_X86_OR_AMD64 +#endif + +#if defined(MY_CPU_X86) || defined(_M_ARM) +#define MY_CPU_32BIT +#endif + +#if defined(_WIN32) && defined(_M_ARM) +#define MY_CPU_ARM_LE +#endif + +#if defined(_WIN32) && defined(_M_IA64) +#define MY_CPU_IA64_LE +#endif + +#if defined(MY_CPU_X86_OR_AMD64) +#define MY_CPU_LE_UNALIGN +#endif + +#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__) +#define MY_CPU_LE +#endif + +#if defined(__BIG_ENDIAN__) +#define MY_CPU_BE +#endif + +#if defined(MY_CPU_LE) && defined(MY_CPU_BE) +Stop_Compiling_Bad_Endian +#endif + +#ifdef MY_CPU_LE_UNALIGN + +#define GetUi16(p) (*(const UInt16 *)(p)) +#define GetUi32(p) (*(const UInt32 *)(p)) +#define GetUi64(p) (*(const UInt64 *)(p)) +#define SetUi16(p, d) *(UInt16 *)(p) = (d); +#define SetUi32(p, d) *(UInt32 *)(p) = (d); +#define SetUi64(p, d) *(UInt64 *)(p) = (d); + +#else + +#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) + +#define GetUi32(p) ( \ + ((const Byte *)(p))[0] | \ + ((UInt32)((const Byte *)(p))[1] << 8) | \ + ((UInt32)((const Byte *)(p))[2] << 16) | \ + ((UInt32)((const Byte *)(p))[3] << 24)) + +#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) + +#define SetUi16(p, d) { UInt32 _x_ = (d); \ + ((Byte *)(p))[0] = (Byte)_x_; \ + ((Byte *)(p))[1] = (Byte)(_x_ >> 8); } + +#define SetUi32(p, d) { UInt32 _x_ = (d); \ + ((Byte *)(p))[0] = (Byte)_x_; \ + ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ + ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ + ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } + +#define SetUi64(p, d) { UInt64 _x64_ = (d); \ + SetUi32(p, (UInt32)_x64_); \ + SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); } + +#endif + +#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) + +#pragma intrinsic(_byteswap_ulong) +#pragma intrinsic(_byteswap_uint64) +#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) +#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) + +#else + +#define GetBe32(p) ( \ + ((UInt32)((const Byte *)(p))[0] << 24) | \ + ((UInt32)((const Byte *)(p))[1] << 16) | \ + ((UInt32)((const Byte *)(p))[2] << 8) | \ + ((const Byte *)(p))[3] ) + +#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) + +#endif + +#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) + + +#ifdef MY_CPU_X86_OR_AMD64 + +typedef struct +{ + UInt32 maxFunc; + UInt32 vendor[3]; + UInt32 ver; + UInt32 b; + UInt32 c; + UInt32 d; +} Cx86cpuid; + +enum +{ + CPU_FIRM_INTEL, + CPU_FIRM_AMD, + CPU_FIRM_VIA +}; + +Bool x86cpuid_CheckAndRead(Cx86cpuid *p); +int x86cpuid_GetFirm(const Cx86cpuid *p); + +#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F) +#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F) +#define x86cpuid_GetStepping(p) ((p)->ver & 0xF) + +Bool CPU_Is_InOrder(); +Bool CPU_Is_Aes_Supported(); + +#endif + +EXTERN_C_END + +#endif diff --git a/Installer/lzma/LzmaDec.c b/Installer/lzma/LzmaDec.c index 4fdc11d4..2036761b 100644 --- a/Installer/lzma/LzmaDec.c +++ b/Installer/lzma/LzmaDec.c @@ -1,999 +1,999 @@ -/* LzmaDec.c -- LZMA Decoder -2009-09-20 : Igor Pavlov : Public domain */ - -#include "LzmaDec.h" - -#include - -#define kNumTopBits 24 -#define kTopValue ((UInt32)1 << kNumTopBits) - -#define kNumBitModelTotalBits 11 -#define kBitModelTotal (1 << kNumBitModelTotalBits) -#define kNumMoveBits 5 - -#define RC_INIT_SIZE 5 - -#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } - -#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) -#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); -#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); -#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ - { UPDATE_0(p); i = (i + i); A0; } else \ - { UPDATE_1(p); i = (i + i) + 1; A1; } -#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) - -#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } -#define TREE_DECODE(probs, limit, i) \ - { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } - -/* #define _LZMA_SIZE_OPT */ - -#ifdef _LZMA_SIZE_OPT -#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) -#else -#define TREE_6_DECODE(probs, i) \ - { i = 1; \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - i -= 0x40; } -#endif - -#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } - -#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) -#define UPDATE_0_CHECK range = bound; -#define UPDATE_1_CHECK range -= bound; code -= bound; -#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ - { UPDATE_0_CHECK; i = (i + i); A0; } else \ - { UPDATE_1_CHECK; i = (i + i) + 1; A1; } -#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) -#define TREE_DECODE_CHECK(probs, limit, i) \ - { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } - - -#define kNumPosBitsMax 4 -#define kNumPosStatesMax (1 << kNumPosBitsMax) - -#define kLenNumLowBits 3 -#define kLenNumLowSymbols (1 << kLenNumLowBits) -#define kLenNumMidBits 3 -#define kLenNumMidSymbols (1 << kLenNumMidBits) -#define kLenNumHighBits 8 -#define kLenNumHighSymbols (1 << kLenNumHighBits) - -#define LenChoice 0 -#define LenChoice2 (LenChoice + 1) -#define LenLow (LenChoice2 + 1) -#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) -#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) -#define kNumLenProbs (LenHigh + kLenNumHighSymbols) - - -#define kNumStates 12 -#define kNumLitStates 7 - -#define kStartPosModelIndex 4 -#define kEndPosModelIndex 14 -#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) - -#define kNumPosSlotBits 6 -#define kNumLenToPosStates 4 - -#define kNumAlignBits 4 -#define kAlignTableSize (1 << kNumAlignBits) - -#define kMatchMinLen 2 -#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) - -#define IsMatch 0 -#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) -#define IsRepG0 (IsRep + kNumStates) -#define IsRepG1 (IsRepG0 + kNumStates) -#define IsRepG2 (IsRepG1 + kNumStates) -#define IsRep0Long (IsRepG2 + kNumStates) -#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) -#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) -#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) -#define LenCoder (Align + kAlignTableSize) -#define RepLenCoder (LenCoder + kNumLenProbs) -#define Literal (RepLenCoder + kNumLenProbs) - -#define LZMA_BASE_SIZE 1846 -#define LZMA_LIT_SIZE 768 - -#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) - -#if Literal != LZMA_BASE_SIZE -StopCompilingDueBUG -#endif - -#define LZMA_DIC_MIN (1 << 12) - -/* First LZMA-symbol is always decoded. -And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization -Out: - Result: - SZ_OK - OK - SZ_ERROR_DATA - Error - p->remainLen: - < kMatchSpecLenStart : normal remain - = kMatchSpecLenStart : finished - = kMatchSpecLenStart + 1 : Flush marker - = kMatchSpecLenStart + 2 : State Init Marker -*/ - -static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) -{ - CLzmaProb *probs = p->probs; - - unsigned state = p->state; - UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; - unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; - unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; - unsigned lc = p->prop.lc; - - Byte *dic = p->dic; - SizeT dicBufSize = p->dicBufSize; - SizeT dicPos = p->dicPos; - - UInt32 processedPos = p->processedPos; - UInt32 checkDicSize = p->checkDicSize; - unsigned len = 0; - - const Byte *buf = p->buf; - UInt32 range = p->range; - UInt32 code = p->code; - - do - { - CLzmaProb *prob; - UInt32 bound; - unsigned ttt; - unsigned posState = processedPos & pbMask; - - prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; - IF_BIT_0(prob) - { - unsigned symbol; - UPDATE_0(prob); - prob = probs + Literal; - if (checkDicSize != 0 || processedPos != 0) - prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + - (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); - - if (state < kNumLitStates) - { - state -= (state < 4) ? state : 3; - symbol = 1; - do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); - } - else - { - unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; - unsigned offs = 0x100; - state -= (state < 10) ? 3 : 6; - symbol = 1; - do - { - unsigned bit; - CLzmaProb *probLit; - matchByte <<= 1; - bit = (matchByte & offs); - probLit = prob + offs + bit + symbol; - GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) - } - while (symbol < 0x100); - } - dic[dicPos++] = (Byte)symbol; - processedPos++; - continue; - } - else - { - UPDATE_1(prob); - prob = probs + IsRep + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - state += kNumStates; - prob = probs + LenCoder; - } - else - { - UPDATE_1(prob); - if (checkDicSize == 0 && processedPos == 0) - return SZ_ERROR_DATA; - prob = probs + IsRepG0 + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; - IF_BIT_0(prob) - { - UPDATE_0(prob); - dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; - dicPos++; - processedPos++; - state = state < kNumLitStates ? 9 : 11; - continue; - } - UPDATE_1(prob); - } - else - { - UInt32 distance; - UPDATE_1(prob); - prob = probs + IsRepG1 + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - distance = rep1; - } - else - { - UPDATE_1(prob); - prob = probs + IsRepG2 + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - distance = rep2; - } - else - { - UPDATE_1(prob); - distance = rep3; - rep3 = rep2; - } - rep2 = rep1; - } - rep1 = rep0; - rep0 = distance; - } - state = state < kNumLitStates ? 8 : 11; - prob = probs + RepLenCoder; - } - { - unsigned limit, offset; - CLzmaProb *probLen = prob + LenChoice; - IF_BIT_0(probLen) - { - UPDATE_0(probLen); - probLen = prob + LenLow + (posState << kLenNumLowBits); - offset = 0; - limit = (1 << kLenNumLowBits); - } - else - { - UPDATE_1(probLen); - probLen = prob + LenChoice2; - IF_BIT_0(probLen) - { - UPDATE_0(probLen); - probLen = prob + LenMid + (posState << kLenNumMidBits); - offset = kLenNumLowSymbols; - limit = (1 << kLenNumMidBits); - } - else - { - UPDATE_1(probLen); - probLen = prob + LenHigh; - offset = kLenNumLowSymbols + kLenNumMidSymbols; - limit = (1 << kLenNumHighBits); - } - } - TREE_DECODE(probLen, limit, len); - len += offset; - } - - if (state >= kNumStates) - { - UInt32 distance; - prob = probs + PosSlot + - ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); - TREE_6_DECODE(prob, distance); - if (distance >= kStartPosModelIndex) - { - unsigned posSlot = (unsigned)distance; - int numDirectBits = (int)(((distance >> 1) - 1)); - distance = (2 | (distance & 1)); - if (posSlot < kEndPosModelIndex) - { - distance <<= numDirectBits; - prob = probs + SpecPos + distance - posSlot - 1; - { - UInt32 mask = 1; - unsigned i = 1; - do - { - GET_BIT2(prob + i, i, ; , distance |= mask); - mask <<= 1; - } - while (--numDirectBits != 0); - } - } - else - { - numDirectBits -= kNumAlignBits; - do - { - NORMALIZE - range >>= 1; - - { - UInt32 t; - code -= range; - t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ - distance = (distance << 1) + (t + 1); - code += range & t; - } - /* - distance <<= 1; - if (code >= range) - { - code -= range; - distance |= 1; - } - */ - } - while (--numDirectBits != 0); - prob = probs + Align; - distance <<= kNumAlignBits; - { - unsigned i = 1; - GET_BIT2(prob + i, i, ; , distance |= 1); - GET_BIT2(prob + i, i, ; , distance |= 2); - GET_BIT2(prob + i, i, ; , distance |= 4); - GET_BIT2(prob + i, i, ; , distance |= 8); - } - if (distance == (UInt32)0xFFFFFFFF) - { - len += kMatchSpecLenStart; - state -= kNumStates; - break; - } - } - } - rep3 = rep2; - rep2 = rep1; - rep1 = rep0; - rep0 = distance + 1; - if (checkDicSize == 0) - { - if (distance >= processedPos) - return SZ_ERROR_DATA; - } - else if (distance >= checkDicSize) - return SZ_ERROR_DATA; - state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; - } - - len += kMatchMinLen; - - if (limit == dicPos) - return SZ_ERROR_DATA; - { - SizeT rem = limit - dicPos; - unsigned curLen = ((rem < len) ? (unsigned)rem : len); - SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); - - processedPos += curLen; - - len -= curLen; - if (pos + curLen <= dicBufSize) - { - Byte *dest = dic + dicPos; - ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; - const Byte *lim = dest + curLen; - dicPos += curLen; - do - *(dest) = (Byte)*(dest + src); - while (++dest != lim); - } - else - { - do - { - dic[dicPos++] = dic[pos]; - if (++pos == dicBufSize) - pos = 0; - } - while (--curLen != 0); - } - } - } - } - while (dicPos < limit && buf < bufLimit); - NORMALIZE; - p->buf = buf; - p->range = range; - p->code = code; - p->remainLen = len; - p->dicPos = dicPos; - p->processedPos = processedPos; - p->reps[0] = rep0; - p->reps[1] = rep1; - p->reps[2] = rep2; - p->reps[3] = rep3; - p->state = state; - - return SZ_OK; -} - -static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) -{ - if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) - { - Byte *dic = p->dic; - SizeT dicPos = p->dicPos; - SizeT dicBufSize = p->dicBufSize; - unsigned len = p->remainLen; - UInt32 rep0 = p->reps[0]; - if (limit - dicPos < len) - len = (unsigned)(limit - dicPos); - - if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) - p->checkDicSize = p->prop.dicSize; - - p->processedPos += len; - p->remainLen -= len; - while (len-- != 0) - { - dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; - dicPos++; - } - p->dicPos = dicPos; - } -} - -static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) -{ - do - { - SizeT limit2 = limit; - if (p->checkDicSize == 0) - { - UInt32 rem = p->prop.dicSize - p->processedPos; - if (limit - p->dicPos > rem) - limit2 = p->dicPos + rem; - } - RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); - if (p->processedPos >= p->prop.dicSize) - p->checkDicSize = p->prop.dicSize; - LzmaDec_WriteRem(p, limit); - } - while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); - - if (p->remainLen > kMatchSpecLenStart) - { - p->remainLen = kMatchSpecLenStart; - } - return 0; -} - -typedef enum -{ - DUMMY_ERROR, /* unexpected end of input stream */ - DUMMY_LIT, - DUMMY_MATCH, - DUMMY_REP -} ELzmaDummy; - -static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) -{ - UInt32 range = p->range; - UInt32 code = p->code; - const Byte *bufLimit = buf + inSize; - CLzmaProb *probs = p->probs; - unsigned state = p->state; - ELzmaDummy res; - - { - CLzmaProb *prob; - UInt32 bound; - unsigned ttt; - unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); - - prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK - - /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ - - prob = probs + Literal; - if (p->checkDicSize != 0 || p->processedPos != 0) - prob += (LZMA_LIT_SIZE * - ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + - (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); - - if (state < kNumLitStates) - { - unsigned symbol = 1; - do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); - } - else - { - unsigned matchByte = p->dic[p->dicPos - p->reps[0] + - ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; - unsigned offs = 0x100; - unsigned symbol = 1; - do - { - unsigned bit; - CLzmaProb *probLit; - matchByte <<= 1; - bit = (matchByte & offs); - probLit = prob + offs + bit + symbol; - GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) - } - while (symbol < 0x100); - } - res = DUMMY_LIT; - } - else - { - unsigned len; - UPDATE_1_CHECK; - - prob = probs + IsRep + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - state = 0; - prob = probs + LenCoder; - res = DUMMY_MATCH; - } - else - { - UPDATE_1_CHECK; - res = DUMMY_REP; - prob = probs + IsRepG0 + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - NORMALIZE_CHECK; - return DUMMY_REP; - } - else - { - UPDATE_1_CHECK; - } - } - else - { - UPDATE_1_CHECK; - prob = probs + IsRepG1 + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - } - else - { - UPDATE_1_CHECK; - prob = probs + IsRepG2 + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - } - else - { - UPDATE_1_CHECK; - } - } - } - state = kNumStates; - prob = probs + RepLenCoder; - } - { - unsigned limit, offset; - CLzmaProb *probLen = prob + LenChoice; - IF_BIT_0_CHECK(probLen) - { - UPDATE_0_CHECK; - probLen = prob + LenLow + (posState << kLenNumLowBits); - offset = 0; - limit = 1 << kLenNumLowBits; - } - else - { - UPDATE_1_CHECK; - probLen = prob + LenChoice2; - IF_BIT_0_CHECK(probLen) - { - UPDATE_0_CHECK; - probLen = prob + LenMid + (posState << kLenNumMidBits); - offset = kLenNumLowSymbols; - limit = 1 << kLenNumMidBits; - } - else - { - UPDATE_1_CHECK; - probLen = prob + LenHigh; - offset = kLenNumLowSymbols + kLenNumMidSymbols; - limit = 1 << kLenNumHighBits; - } - } - TREE_DECODE_CHECK(probLen, limit, len); - len += offset; - } - - if (state < 4) - { - unsigned posSlot; - prob = probs + PosSlot + - ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << - kNumPosSlotBits); - TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); - if (posSlot >= kStartPosModelIndex) - { - int numDirectBits = ((posSlot >> 1) - 1); - - /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ - - if (posSlot < kEndPosModelIndex) - { - prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; - } - else - { - numDirectBits -= kNumAlignBits; - do - { - NORMALIZE_CHECK - range >>= 1; - code -= range & (((code - range) >> 31) - 1); - /* if (code >= range) code -= range; */ - } - while (--numDirectBits != 0); - prob = probs + Align; - numDirectBits = kNumAlignBits; - } - { - unsigned i = 1; - do - { - GET_BIT_CHECK(prob + i, i); - } - while (--numDirectBits != 0); - } - } - } - } - } - NORMALIZE_CHECK; - return res; -} - - -static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) -{ - p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); - p->range = 0xFFFFFFFF; - p->needFlush = 0; -} - -void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) -{ - p->needFlush = 1; - p->remainLen = 0; - p->tempBufSize = 0; - - if (initDic) - { - p->processedPos = 0; - p->checkDicSize = 0; - p->needInitState = 1; - } - if (initState) - p->needInitState = 1; -} - -void LzmaDec_Init(CLzmaDec *p) -{ - p->dicPos = 0; - LzmaDec_InitDicAndState(p, True, True); -} - -static void LzmaDec_InitStateReal(CLzmaDec *p) -{ - UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); - UInt32 i; - CLzmaProb *probs = p->probs; - for (i = 0; i < numProbs; i++) - probs[i] = kBitModelTotal >> 1; - p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; - p->state = 0; - p->needInitState = 0; -} - -SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, - ELzmaFinishMode finishMode, ELzmaStatus *status) -{ - SizeT inSize = *srcLen; - (*srcLen) = 0; - LzmaDec_WriteRem(p, dicLimit); - - *status = LZMA_STATUS_NOT_SPECIFIED; - - while (p->remainLen != kMatchSpecLenStart) - { - int checkEndMarkNow; - - if (p->needFlush != 0) - { - for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) - p->tempBuf[p->tempBufSize++] = *src++; - if (p->tempBufSize < RC_INIT_SIZE) - { - *status = LZMA_STATUS_NEEDS_MORE_INPUT; - return SZ_OK; - } - if (p->tempBuf[0] != 0) - return SZ_ERROR_DATA; - - LzmaDec_InitRc(p, p->tempBuf); - p->tempBufSize = 0; - } - - checkEndMarkNow = 0; - if (p->dicPos >= dicLimit) - { - if (p->remainLen == 0 && p->code == 0) - { - *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; - return SZ_OK; - } - if (finishMode == LZMA_FINISH_ANY) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_OK; - } - if (p->remainLen != 0) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; - } - checkEndMarkNow = 1; - } - - if (p->needInitState) - LzmaDec_InitStateReal(p); - - if (p->tempBufSize == 0) - { - SizeT processed; - const Byte *bufLimit; - if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) - { - int dummyRes = LzmaDec_TryDummy(p, src, inSize); - if (dummyRes == DUMMY_ERROR) - { - memcpy(p->tempBuf, src, inSize); - p->tempBufSize = (unsigned)inSize; - (*srcLen) += inSize; - *status = LZMA_STATUS_NEEDS_MORE_INPUT; - return SZ_OK; - } - if (checkEndMarkNow && dummyRes != DUMMY_MATCH) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; - } - bufLimit = src; - } - else - bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; - p->buf = src; - if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) - return SZ_ERROR_DATA; - processed = (SizeT)(p->buf - src); - (*srcLen) += processed; - src += processed; - inSize -= processed; - } - else - { - unsigned rem = p->tempBufSize, lookAhead = 0; - while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) - p->tempBuf[rem++] = src[lookAhead++]; - p->tempBufSize = rem; - if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) - { - int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); - if (dummyRes == DUMMY_ERROR) - { - (*srcLen) += lookAhead; - *status = LZMA_STATUS_NEEDS_MORE_INPUT; - return SZ_OK; - } - if (checkEndMarkNow && dummyRes != DUMMY_MATCH) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; - } - } - p->buf = p->tempBuf; - if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) - return SZ_ERROR_DATA; - lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); - (*srcLen) += lookAhead; - src += lookAhead; - inSize -= lookAhead; - p->tempBufSize = 0; - } - } - if (p->code == 0) - *status = LZMA_STATUS_FINISHED_WITH_MARK; - return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; -} - -SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) -{ - SizeT outSize = *destLen; - SizeT inSize = *srcLen; - *srcLen = *destLen = 0; - for (;;) - { - SizeT inSizeCur = inSize, outSizeCur, dicPos; - ELzmaFinishMode curFinishMode; - SRes res; - if (p->dicPos == p->dicBufSize) - p->dicPos = 0; - dicPos = p->dicPos; - if (outSize > p->dicBufSize - dicPos) - { - outSizeCur = p->dicBufSize; - curFinishMode = LZMA_FINISH_ANY; - } - else - { - outSizeCur = dicPos + outSize; - curFinishMode = finishMode; - } - - res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); - src += inSizeCur; - inSize -= inSizeCur; - *srcLen += inSizeCur; - outSizeCur = p->dicPos - dicPos; - memcpy(dest, p->dic + dicPos, outSizeCur); - dest += outSizeCur; - outSize -= outSizeCur; - *destLen += outSizeCur; - if (res != 0) - return res; - if (outSizeCur == 0 || outSize == 0) - return SZ_OK; - } -} - -void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->probs); - p->probs = 0; -} - -static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->dic); - p->dic = 0; -} - -void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) -{ - LzmaDec_FreeProbs(p, alloc); - LzmaDec_FreeDict(p, alloc); -} - -SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) -{ - UInt32 dicSize; - Byte d; - - if (size < LZMA_PROPS_SIZE) - return SZ_ERROR_UNSUPPORTED; - else - dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); - - if (dicSize < LZMA_DIC_MIN) - dicSize = LZMA_DIC_MIN; - p->dicSize = dicSize; - - d = data[0]; - if (d >= (9 * 5 * 5)) - return SZ_ERROR_UNSUPPORTED; - - p->lc = d % 9; - d /= 9; - p->pb = d / 5; - p->lp = d % 5; - - return SZ_OK; -} - -static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) -{ - UInt32 numProbs = LzmaProps_GetNumProbs(propNew); - if (p->probs == 0 || numProbs != p->numProbs) - { - LzmaDec_FreeProbs(p, alloc); - p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); - p->numProbs = numProbs; - if (p->probs == 0) - return SZ_ERROR_MEM; - } - return SZ_OK; -} - -SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) -{ - CLzmaProps propNew; - RINOK(LzmaProps_Decode(&propNew, props, propsSize)); - RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); - p->prop = propNew; - return SZ_OK; -} - -SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) -{ - CLzmaProps propNew; - SizeT dicBufSize; - RINOK(LzmaProps_Decode(&propNew, props, propsSize)); - RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); - dicBufSize = propNew.dicSize; - if (p->dic == 0 || dicBufSize != p->dicBufSize) - { - LzmaDec_FreeDict(p, alloc); - p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); - if (p->dic == 0) - { - LzmaDec_FreeProbs(p, alloc); - return SZ_ERROR_MEM; - } - } - p->dicBufSize = dicBufSize; - p->prop = propNew; - return SZ_OK; -} - -SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, - const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, - ELzmaStatus *status, ISzAlloc *alloc) -{ - CLzmaDec p; - SRes res; - SizeT inSize = *srcLen; - SizeT outSize = *destLen; - *srcLen = *destLen = 0; - if (inSize < RC_INIT_SIZE) - return SZ_ERROR_INPUT_EOF; - - LzmaDec_Construct(&p); - res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); - if (res != 0) - return res; - p.dic = dest; - p.dicBufSize = outSize; - - LzmaDec_Init(&p); - - *srcLen = inSize; - res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); - - if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) - res = SZ_ERROR_INPUT_EOF; - - (*destLen) = p.dicPos; - LzmaDec_FreeProbs(&p, alloc); - return res; -} +/* LzmaDec.c -- LZMA Decoder +2009-09-20 : Igor Pavlov : Public domain */ + +#include "LzmaDec.h" + +#include + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_INIT_SIZE 5 + +#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); +#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ + { UPDATE_0(p); i = (i + i); A0; } else \ + { UPDATE_1(p); i = (i + i) + 1; A1; } +#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) + +#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } +#define TREE_DECODE(probs, limit, i) \ + { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } + +/* #define _LZMA_SIZE_OPT */ + +#ifdef _LZMA_SIZE_OPT +#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) +#else +#define TREE_6_DECODE(probs, i) \ + { i = 1; \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + i -= 0x40; } +#endif + +#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0_CHECK range = bound; +#define UPDATE_1_CHECK range -= bound; code -= bound; +#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ + { UPDATE_0_CHECK; i = (i + i); A0; } else \ + { UPDATE_1_CHECK; i = (i + i) + 1; A1; } +#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) +#define TREE_DECODE_CHECK(probs, limit, i) \ + { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 +#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +#define LZMA_DIC_MIN (1 << 12) + +/* First LZMA-symbol is always decoded. +And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization +Out: + Result: + SZ_OK - OK + SZ_ERROR_DATA - Error + p->remainLen: + < kMatchSpecLenStart : normal remain + = kMatchSpecLenStart : finished + = kMatchSpecLenStart + 1 : Flush marker + = kMatchSpecLenStart + 2 : State Init Marker +*/ + +static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + CLzmaProb *probs = p->probs; + + unsigned state = p->state; + UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; + unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; + unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; + unsigned lc = p->prop.lc; + + Byte *dic = p->dic; + SizeT dicBufSize = p->dicBufSize; + SizeT dicPos = p->dicPos; + + UInt32 processedPos = p->processedPos; + UInt32 checkDicSize = p->checkDicSize; + unsigned len = 0; + + const Byte *buf = p->buf; + UInt32 range = p->range; + UInt32 code = p->code; + + do + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = processedPos & pbMask; + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + unsigned symbol; + UPDATE_0(prob); + prob = probs + Literal; + if (checkDicSize != 0 || processedPos != 0) + prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); + + if (state < kNumLitStates) + { + state -= (state < 4) ? state : 3; + symbol = 1; + do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + unsigned offs = 0x100; + state -= (state < 10) ? 3 : 6; + symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + dic[dicPos++] = (Byte)symbol; + processedPos++; + continue; + } + else + { + UPDATE_1(prob); + prob = probs + IsRep + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + state += kNumStates; + prob = probs + LenCoder; + } + else + { + UPDATE_1(prob); + if (checkDicSize == 0 && processedPos == 0) + return SZ_ERROR_DATA; + prob = probs + IsRepG0 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + UPDATE_0(prob); + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + processedPos++; + state = state < kNumLitStates ? 9 : 11; + continue; + } + UPDATE_1(prob); + } + else + { + UInt32 distance; + UPDATE_1(prob); + prob = probs + IsRepG1 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep1; + } + else + { + UPDATE_1(prob); + prob = probs + IsRepG2 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep2; + } + else + { + UPDATE_1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit = (1 << kLenNumLowBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenChoice2; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit = (1 << kLenNumMidBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit = (1 << kLenNumHighBits); + } + } + TREE_DECODE(probLen, limit, len); + len += offset; + } + + if (state >= kNumStates) + { + UInt32 distance; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); + TREE_6_DECODE(prob, distance); + if (distance >= kStartPosModelIndex) + { + unsigned posSlot = (unsigned)distance; + int numDirectBits = (int)(((distance >> 1) - 1)); + distance = (2 | (distance & 1)); + if (posSlot < kEndPosModelIndex) + { + distance <<= numDirectBits; + prob = probs + SpecPos + distance - posSlot - 1; + { + UInt32 mask = 1; + unsigned i = 1; + do + { + GET_BIT2(prob + i, i, ; , distance |= mask); + mask <<= 1; + } + while (--numDirectBits != 0); + } + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE + range >>= 1; + + { + UInt32 t; + code -= range; + t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ + distance = (distance << 1) + (t + 1); + code += range & t; + } + /* + distance <<= 1; + if (code >= range) + { + code -= range; + distance |= 1; + } + */ + } + while (--numDirectBits != 0); + prob = probs + Align; + distance <<= kNumAlignBits; + { + unsigned i = 1; + GET_BIT2(prob + i, i, ; , distance |= 1); + GET_BIT2(prob + i, i, ; , distance |= 2); + GET_BIT2(prob + i, i, ; , distance |= 4); + GET_BIT2(prob + i, i, ; , distance |= 8); + } + if (distance == (UInt32)0xFFFFFFFF) + { + len += kMatchSpecLenStart; + state -= kNumStates; + break; + } + } + } + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance + 1; + if (checkDicSize == 0) + { + if (distance >= processedPos) + return SZ_ERROR_DATA; + } + else if (distance >= checkDicSize) + return SZ_ERROR_DATA; + state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + } + + len += kMatchMinLen; + + if (limit == dicPos) + return SZ_ERROR_DATA; + { + SizeT rem = limit - dicPos; + unsigned curLen = ((rem < len) ? (unsigned)rem : len); + SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); + + processedPos += curLen; + + len -= curLen; + if (pos + curLen <= dicBufSize) + { + Byte *dest = dic + dicPos; + ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; + const Byte *lim = dest + curLen; + dicPos += curLen; + do + *(dest) = (Byte)*(dest + src); + while (++dest != lim); + } + else + { + do + { + dic[dicPos++] = dic[pos]; + if (++pos == dicBufSize) + pos = 0; + } + while (--curLen != 0); + } + } + } + } + while (dicPos < limit && buf < bufLimit); + NORMALIZE; + p->buf = buf; + p->range = range; + p->code = code; + p->remainLen = len; + p->dicPos = dicPos; + p->processedPos = processedPos; + p->reps[0] = rep0; + p->reps[1] = rep1; + p->reps[2] = rep2; + p->reps[3] = rep3; + p->state = state; + + return SZ_OK; +} + +static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) +{ + if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) + { + Byte *dic = p->dic; + SizeT dicPos = p->dicPos; + SizeT dicBufSize = p->dicBufSize; + unsigned len = p->remainLen; + UInt32 rep0 = p->reps[0]; + if (limit - dicPos < len) + len = (unsigned)(limit - dicPos); + + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) + p->checkDicSize = p->prop.dicSize; + + p->processedPos += len; + p->remainLen -= len; + while (len-- != 0) + { + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + } + p->dicPos = dicPos; + } +} + +static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + do + { + SizeT limit2 = limit; + if (p->checkDicSize == 0) + { + UInt32 rem = p->prop.dicSize - p->processedPos; + if (limit - p->dicPos > rem) + limit2 = p->dicPos + rem; + } + RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); + if (p->processedPos >= p->prop.dicSize) + p->checkDicSize = p->prop.dicSize; + LzmaDec_WriteRem(p, limit); + } + while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); + + if (p->remainLen > kMatchSpecLenStart) + { + p->remainLen = kMatchSpecLenStart; + } + return 0; +} + +typedef enum +{ + DUMMY_ERROR, /* unexpected end of input stream */ + DUMMY_LIT, + DUMMY_MATCH, + DUMMY_REP +} ELzmaDummy; + +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) +{ + UInt32 range = p->range; + UInt32 code = p->code; + const Byte *bufLimit = buf + inSize; + CLzmaProb *probs = p->probs; + unsigned state = p->state; + ELzmaDummy res; + + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK + + /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ + + prob = probs + Literal; + if (p->checkDicSize != 0 || p->processedPos != 0) + prob += (LZMA_LIT_SIZE * + ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); + + if (state < kNumLitStates) + { + unsigned symbol = 1; + do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[p->dicPos - p->reps[0] + + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; + unsigned offs = 0x100; + unsigned symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + res = DUMMY_LIT; + } + else + { + unsigned len; + UPDATE_1_CHECK; + + prob = probs + IsRep + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + state = 0; + prob = probs + LenCoder; + res = DUMMY_MATCH; + } + else + { + UPDATE_1_CHECK; + res = DUMMY_REP; + prob = probs + IsRepG0 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + NORMALIZE_CHECK; + return DUMMY_REP; + } + else + { + UPDATE_1_CHECK; + } + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG1 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG2 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + } + } + } + state = kNumStates; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit = 1 << kLenNumLowBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenChoice2; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit = 1 << kLenNumMidBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit = 1 << kLenNumHighBits; + } + } + TREE_DECODE_CHECK(probLen, limit, len); + len += offset; + } + + if (state < 4) + { + unsigned posSlot; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + + /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ + + if (posSlot < kEndPosModelIndex) + { + prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE_CHECK + range >>= 1; + code -= range & (((code - range) >> 31) - 1); + /* if (code >= range) code -= range; */ + } + while (--numDirectBits != 0); + prob = probs + Align; + numDirectBits = kNumAlignBits; + } + { + unsigned i = 1; + do + { + GET_BIT_CHECK(prob + i, i); + } + while (--numDirectBits != 0); + } + } + } + } + } + NORMALIZE_CHECK; + return res; +} + + +static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) +{ + p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); + p->range = 0xFFFFFFFF; + p->needFlush = 0; +} + +void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +{ + p->needFlush = 1; + p->remainLen = 0; + p->tempBufSize = 0; + + if (initDic) + { + p->processedPos = 0; + p->checkDicSize = 0; + p->needInitState = 1; + } + if (initState) + p->needInitState = 1; +} + +void LzmaDec_Init(CLzmaDec *p) +{ + p->dicPos = 0; + LzmaDec_InitDicAndState(p, True, True); +} + +static void LzmaDec_InitStateReal(CLzmaDec *p) +{ + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); + UInt32 i; + CLzmaProb *probs = p->probs; + for (i = 0; i < numProbs; i++) + probs[i] = kBitModelTotal >> 1; + p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; + p->state = 0; + p->needInitState = 0; +} + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, + ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + (*srcLen) = 0; + LzmaDec_WriteRem(p, dicLimit); + + *status = LZMA_STATUS_NOT_SPECIFIED; + + while (p->remainLen != kMatchSpecLenStart) + { + int checkEndMarkNow; + + if (p->needFlush != 0) + { + for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) + p->tempBuf[p->tempBufSize++] = *src++; + if (p->tempBufSize < RC_INIT_SIZE) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (p->tempBuf[0] != 0) + return SZ_ERROR_DATA; + + LzmaDec_InitRc(p, p->tempBuf); + p->tempBufSize = 0; + } + + checkEndMarkNow = 0; + if (p->dicPos >= dicLimit) + { + if (p->remainLen == 0 && p->code == 0) + { + *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; + return SZ_OK; + } + if (finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + if (p->remainLen != 0) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + checkEndMarkNow = 1; + } + + if (p->needInitState) + LzmaDec_InitStateReal(p); + + if (p->tempBufSize == 0) + { + SizeT processed; + const Byte *bufLimit; + if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, src, inSize); + if (dummyRes == DUMMY_ERROR) + { + memcpy(p->tempBuf, src, inSize); + p->tempBufSize = (unsigned)inSize; + (*srcLen) += inSize; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + bufLimit = src; + } + else + bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; + p->buf = src; + if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) + return SZ_ERROR_DATA; + processed = (SizeT)(p->buf - src); + (*srcLen) += processed; + src += processed; + inSize -= processed; + } + else + { + unsigned rem = p->tempBufSize, lookAhead = 0; + while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) + p->tempBuf[rem++] = src[lookAhead++]; + p->tempBufSize = rem; + if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); + if (dummyRes == DUMMY_ERROR) + { + (*srcLen) += lookAhead; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + } + p->buf = p->tempBuf; + if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) + return SZ_ERROR_DATA; + lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); + (*srcLen) += lookAhead; + src += lookAhead; + inSize -= lookAhead; + p->tempBufSize = 0; + } + } + if (p->code == 0) + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; +} + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen; + SizeT inSize = *srcLen; + *srcLen = *destLen = 0; + for (;;) + { + SizeT inSizeCur = inSize, outSizeCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + if (p->dicPos == p->dicBufSize) + p->dicPos = 0; + dicPos = p->dicPos; + if (outSize > p->dicBufSize - dicPos) + { + outSizeCur = p->dicBufSize; + curFinishMode = LZMA_FINISH_ANY; + } + else + { + outSizeCur = dicPos + outSize; + curFinishMode = finishMode; + } + + res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); + src += inSizeCur; + inSize -= inSizeCur; + *srcLen += inSizeCur; + outSizeCur = p->dicPos - dicPos; + memcpy(dest, p->dic + dicPos, outSizeCur); + dest += outSizeCur; + outSize -= outSizeCur; + *destLen += outSizeCur; + if (res != 0) + return res; + if (outSizeCur == 0 || outSize == 0) + return SZ_OK; + } +} + +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->probs); + p->probs = 0; +} + +static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->dic); + p->dic = 0; +} + +void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) +{ + LzmaDec_FreeProbs(p, alloc); + LzmaDec_FreeDict(p, alloc); +} + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) +{ + UInt32 dicSize; + Byte d; + + if (size < LZMA_PROPS_SIZE) + return SZ_ERROR_UNSUPPORTED; + else + dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); + + if (dicSize < LZMA_DIC_MIN) + dicSize = LZMA_DIC_MIN; + p->dicSize = dicSize; + + d = data[0]; + if (d >= (9 * 5 * 5)) + return SZ_ERROR_UNSUPPORTED; + + p->lc = d % 9; + d /= 9; + p->pb = d / 5; + p->lp = d % 5; + + return SZ_OK; +} + +static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) +{ + UInt32 numProbs = LzmaProps_GetNumProbs(propNew); + if (p->probs == 0 || numProbs != p->numProbs) + { + LzmaDec_FreeProbs(p, alloc); + p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); + p->numProbs = numProbs; + if (p->probs == 0) + return SZ_ERROR_MEM; + } + return SZ_OK; +} + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + SizeT dicBufSize; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + dicBufSize = propNew.dicSize; + if (p->dic == 0 || dicBufSize != p->dicBufSize) + { + LzmaDec_FreeDict(p, alloc); + p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); + if (p->dic == 0) + { + LzmaDec_FreeProbs(p, alloc); + return SZ_ERROR_MEM; + } + } + p->dicBufSize = dicBufSize; + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc) +{ + CLzmaDec p; + SRes res; + SizeT inSize = *srcLen; + SizeT outSize = *destLen; + *srcLen = *destLen = 0; + if (inSize < RC_INIT_SIZE) + return SZ_ERROR_INPUT_EOF; + + LzmaDec_Construct(&p); + res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); + if (res != 0) + return res; + p.dic = dest; + p.dicBufSize = outSize; + + LzmaDec_Init(&p); + + *srcLen = inSize; + res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + + (*destLen) = p.dicPos; + LzmaDec_FreeProbs(&p, alloc); + return res; +} diff --git a/Installer/lzma/LzmaDec.h b/Installer/lzma/LzmaDec.h index 6741a644..bf7f084b 100644 --- a/Installer/lzma/LzmaDec.h +++ b/Installer/lzma/LzmaDec.h @@ -1,231 +1,231 @@ -/* LzmaDec.h -- LZMA Decoder -2009-02-07 : Igor Pavlov : Public domain */ - -#ifndef __LZMA_DEC_H -#define __LZMA_DEC_H - -#include "Types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* #define _LZMA_PROB32 */ -/* _LZMA_PROB32 can increase the speed on some CPUs, - but memory usage for CLzmaDec::probs will be doubled in that case */ - -#ifdef _LZMA_PROB32 -#define CLzmaProb UInt32 -#else -#define CLzmaProb UInt16 -#endif - - -/* ---------- LZMA Properties ---------- */ - -#define LZMA_PROPS_SIZE 5 - -typedef struct _CLzmaProps -{ - unsigned lc, lp, pb; - UInt32 dicSize; -} CLzmaProps; - -/* LzmaProps_Decode - decodes properties -Returns: - SZ_OK - SZ_ERROR_UNSUPPORTED - Unsupported properties -*/ - -SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); - - -/* ---------- LZMA Decoder state ---------- */ - -/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. - Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ - -#define LZMA_REQUIRED_INPUT_MAX 20 - -typedef struct -{ - CLzmaProps prop; - CLzmaProb *probs; - Byte *dic; - const Byte *buf; - UInt32 range, code; - SizeT dicPos; - SizeT dicBufSize; - UInt32 processedPos; - UInt32 checkDicSize; - unsigned state; - UInt32 reps[4]; - unsigned remainLen; - int needFlush; - int needInitState; - UInt32 numProbs; - unsigned tempBufSize; - Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; -} CLzmaDec; - -#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } - -void LzmaDec_Init(CLzmaDec *p); - -/* There are two types of LZMA streams: - 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. - 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ - -typedef enum -{ - LZMA_FINISH_ANY, /* finish at any point */ - LZMA_FINISH_END /* block must be finished at the end */ -} ELzmaFinishMode; - -/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! - - You must use LZMA_FINISH_END, when you know that current output buffer - covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. - - If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, - and output value of destLen will be less than output buffer size limit. - You can check status result also. - - You can use multiple checks to test data integrity after full decompression: - 1) Check Result and "status" variable. - 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. - 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. - You must use correct finish mode in that case. */ - -typedef enum -{ - LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ - LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ - LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ - LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ -} ELzmaStatus; - -/* ELzmaStatus is used only as output value for function call */ - - -/* ---------- Interfaces ---------- */ - -/* There are 3 levels of interfaces: - 1) Dictionary Interface - 2) Buffer Interface - 3) One Call Interface - You can select any of these interfaces, but don't mix functions from different - groups for same object. */ - - -/* There are two variants to allocate state for Dictionary Interface: - 1) LzmaDec_Allocate / LzmaDec_Free - 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs - You can use variant 2, if you set dictionary buffer manually. - For Buffer Interface you must always use variant 1. - -LzmaDec_Allocate* can return: - SZ_OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_UNSUPPORTED - Unsupported properties -*/ - -SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); -void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); - -SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); -void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); - -/* ---------- Dictionary Interface ---------- */ - -/* You can use it, if you want to eliminate the overhead for data copying from - dictionary to some other external buffer. - You must work with CLzmaDec variables directly in this interface. - - STEPS: - LzmaDec_Constr() - LzmaDec_Allocate() - for (each new stream) - { - LzmaDec_Init() - while (it needs more decompression) - { - LzmaDec_DecodeToDic() - use data from CLzmaDec::dic and update CLzmaDec::dicPos - } - } - LzmaDec_Free() -*/ - -/* LzmaDec_DecodeToDic - - The decoding to internal dictionary buffer (CLzmaDec::dic). - You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! - -finishMode: - It has meaning only if the decoding reaches output limit (dicLimit). - LZMA_FINISH_ANY - Decode just dicLimit bytes. - LZMA_FINISH_END - Stream must be finished after dicLimit. - -Returns: - SZ_OK - status: - LZMA_STATUS_FINISHED_WITH_MARK - LZMA_STATUS_NOT_FINISHED - LZMA_STATUS_NEEDS_MORE_INPUT - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK - SZ_ERROR_DATA - Data error -*/ - -SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); - - -/* ---------- Buffer Interface ---------- */ - -/* It's zlib-like interface. - See LzmaDec_DecodeToDic description for information about STEPS and return results, - but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need - to work with CLzmaDec variables manually. - -finishMode: - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). -*/ - -SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); - - -/* ---------- One Call Interface ---------- */ - -/* LzmaDecode - -finishMode: - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). - -Returns: - SZ_OK - status: - LZMA_STATUS_FINISHED_WITH_MARK - LZMA_STATUS_NOT_FINISHED - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK - SZ_ERROR_DATA - Data error - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_UNSUPPORTED - Unsupported properties - SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). -*/ - -SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, - const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, - ELzmaStatus *status, ISzAlloc *alloc); - -#ifdef __cplusplus -} -#endif - -#endif +/* LzmaDec.h -- LZMA Decoder +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __LZMA_DEC_H +#define __LZMA_DEC_H + +#include "Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* #define _LZMA_PROB32 */ +/* _LZMA_PROB32 can increase the speed on some CPUs, + but memory usage for CLzmaDec::probs will be doubled in that case */ + +#ifdef _LZMA_PROB32 +#define CLzmaProb UInt32 +#else +#define CLzmaProb UInt16 +#endif + + +/* ---------- LZMA Properties ---------- */ + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaProps +{ + unsigned lc, lp, pb; + UInt32 dicSize; +} CLzmaProps; + +/* LzmaProps_Decode - decodes properties +Returns: + SZ_OK + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); + + +/* ---------- LZMA Decoder state ---------- */ + +/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. + Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ + +#define LZMA_REQUIRED_INPUT_MAX 20 + +typedef struct +{ + CLzmaProps prop; + CLzmaProb *probs; + Byte *dic; + const Byte *buf; + UInt32 range, code; + SizeT dicPos; + SizeT dicBufSize; + UInt32 processedPos; + UInt32 checkDicSize; + unsigned state; + UInt32 reps[4]; + unsigned remainLen; + int needFlush; + int needInitState; + UInt32 numProbs; + unsigned tempBufSize; + Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; +} CLzmaDec; + +#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } + +void LzmaDec_Init(CLzmaDec *p); + +/* There are two types of LZMA streams: + 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. + 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ + +typedef enum +{ + LZMA_FINISH_ANY, /* finish at any point */ + LZMA_FINISH_END /* block must be finished at the end */ +} ELzmaFinishMode; + +/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! + + You must use LZMA_FINISH_END, when you know that current output buffer + covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. + + If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, + and output value of destLen will be less than output buffer size limit. + You can check status result also. + + You can use multiple checks to test data integrity after full decompression: + 1) Check Result and "status" variable. + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. + You must use correct finish mode in that case. */ + +typedef enum +{ + LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ + LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ + LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ + LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ +} ELzmaStatus; + +/* ELzmaStatus is used only as output value for function call */ + + +/* ---------- Interfaces ---------- */ + +/* There are 3 levels of interfaces: + 1) Dictionary Interface + 2) Buffer Interface + 3) One Call Interface + You can select any of these interfaces, but don't mix functions from different + groups for same object. */ + + +/* There are two variants to allocate state for Dictionary Interface: + 1) LzmaDec_Allocate / LzmaDec_Free + 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs + You can use variant 2, if you set dictionary buffer manually. + For Buffer Interface you must always use variant 1. + +LzmaDec_Allocate* can return: + SZ_OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); + +SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); +void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); + +/* ---------- Dictionary Interface ---------- */ + +/* You can use it, if you want to eliminate the overhead for data copying from + dictionary to some other external buffer. + You must work with CLzmaDec variables directly in this interface. + + STEPS: + LzmaDec_Constr() + LzmaDec_Allocate() + for (each new stream) + { + LzmaDec_Init() + while (it needs more decompression) + { + LzmaDec_DecodeToDic() + use data from CLzmaDec::dic and update CLzmaDec::dicPos + } + } + LzmaDec_Free() +*/ + +/* LzmaDec_DecodeToDic + + The decoding to internal dictionary buffer (CLzmaDec::dic). + You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! + +finishMode: + It has meaning only if the decoding reaches output limit (dicLimit). + LZMA_FINISH_ANY - Decode just dicLimit bytes. + LZMA_FINISH_END - Stream must be finished after dicLimit. + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error +*/ + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- Buffer Interface ---------- */ + +/* It's zlib-like interface. + See LzmaDec_DecodeToDic description for information about STEPS and return results, + but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need + to work with CLzmaDec variables manually. + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). +*/ + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- One Call Interface ---------- */ + +/* LzmaDecode + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +*/ + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Installer/lzma/Types.h b/Installer/lzma/Types.h index f193ce2f..7732c240 100644 --- a/Installer/lzma/Types.h +++ b/Installer/lzma/Types.h @@ -1,254 +1,254 @@ -/* Types.h -- Basic types -2010-10-09 : Igor Pavlov : Public domain */ - -#ifndef __7Z_TYPES_H -#define __7Z_TYPES_H - -#include - -#ifdef _WIN32 -#include -#endif - -#ifndef EXTERN_C_BEGIN -#ifdef __cplusplus -#define EXTERN_C_BEGIN extern "C" { -#define EXTERN_C_END } -#else -#define EXTERN_C_BEGIN -#define EXTERN_C_END -#endif -#endif - -EXTERN_C_BEGIN - -#define SZ_OK 0 - -#define SZ_ERROR_DATA 1 -#define SZ_ERROR_MEM 2 -#define SZ_ERROR_CRC 3 -#define SZ_ERROR_UNSUPPORTED 4 -#define SZ_ERROR_PARAM 5 -#define SZ_ERROR_INPUT_EOF 6 -#define SZ_ERROR_OUTPUT_EOF 7 -#define SZ_ERROR_READ 8 -#define SZ_ERROR_WRITE 9 -#define SZ_ERROR_PROGRESS 10 -#define SZ_ERROR_FAIL 11 -#define SZ_ERROR_THREAD 12 - -#define SZ_ERROR_ARCHIVE 16 -#define SZ_ERROR_NO_ARCHIVE 17 - -typedef int SRes; - -#ifdef _WIN32 -typedef DWORD WRes; -#else -typedef int WRes; -#endif - -#ifndef RINOK -#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } -#endif - -typedef unsigned char Byte; -typedef short Int16; -typedef unsigned short UInt16; - -#ifdef _LZMA_UINT32_IS_ULONG -typedef long Int32; -typedef unsigned long UInt32; -#else -typedef int Int32; -typedef unsigned int UInt32; -#endif - -#ifdef _SZ_NO_INT_64 - -/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. - NOTES: Some code will work incorrectly in that case! */ - -typedef long Int64; -typedef unsigned long UInt64; - -#else - -#if defined(_MSC_VER) || defined(__BORLANDC__) -typedef __int64 Int64; -typedef unsigned __int64 UInt64; -#define UINT64_CONST(n) n -#else -typedef long long int Int64; -typedef unsigned long long int UInt64; -#define UINT64_CONST(n) n ## ULL -#endif - -#endif - -#ifdef _LZMA_NO_SYSTEM_SIZE_T -typedef UInt32 SizeT; -#else -typedef size_t SizeT; -#endif - -typedef int Bool; -#define True 1 -#define False 0 - - -#ifdef _WIN32 -#define MY_STD_CALL __stdcall -#else -#define MY_STD_CALL -#endif - -#ifdef _MSC_VER - -#if _MSC_VER >= 1300 -#define MY_NO_INLINE __declspec(noinline) -#else -#define MY_NO_INLINE -#endif - -#define MY_CDECL __cdecl -#define MY_FAST_CALL __fastcall - -#else - -#define MY_CDECL -#define MY_FAST_CALL - -#endif - - -/* The following interfaces use first parameter as pointer to structure */ - -typedef struct -{ - Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */ -} IByteIn; - -typedef struct -{ - void (*Write)(void *p, Byte b); -} IByteOut; - -typedef struct -{ - SRes (*Read)(void *p, void *buf, size_t *size); - /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. - (output(*size) < input(*size)) is allowed */ -} ISeqInStream; - -/* it can return SZ_ERROR_INPUT_EOF */ -SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); -SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); -SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); - -typedef struct -{ - size_t (*Write)(void *p, const void *buf, size_t size); - /* Returns: result - the number of actually written bytes. - (result < size) means error */ -} ISeqOutStream; - -typedef enum -{ - SZ_SEEK_SET = 0, - SZ_SEEK_CUR = 1, - SZ_SEEK_END = 2 -} ESzSeek; - -typedef struct -{ - SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ - SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); -} ISeekInStream; - -typedef struct -{ - SRes (*Look)(void *p, const void **buf, size_t *size); - /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. - (output(*size) > input(*size)) is not allowed - (output(*size) < input(*size)) is allowed */ - SRes (*Skip)(void *p, size_t offset); - /* offset must be <= output(*size) of Look */ - - SRes (*Read)(void *p, void *buf, size_t *size); - /* reads directly (without buffer). It's same as ISeqInStream::Read */ - SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); -} ILookInStream; - -SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); -SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); - -/* reads via ILookInStream::Read */ -SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); -SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); - -#define LookToRead_BUF_SIZE (1 << 14) - -typedef struct -{ - ILookInStream s; - ISeekInStream *realStream; - size_t pos; - size_t size; - Byte buf[LookToRead_BUF_SIZE]; -} CLookToRead; - -void LookToRead_CreateVTable(CLookToRead *p, int lookahead); -void LookToRead_Init(CLookToRead *p); - -typedef struct -{ - ISeqInStream s; - ILookInStream *realStream; -} CSecToLook; - -void SecToLook_CreateVTable(CSecToLook *p); - -typedef struct -{ - ISeqInStream s; - ILookInStream *realStream; -} CSecToRead; - -void SecToRead_CreateVTable(CSecToRead *p); - -typedef struct -{ - SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); - /* Returns: result. (result != SZ_OK) means break. - Value (UInt64)(Int64)-1 for size means unknown value. */ -} ICompressProgress; - -typedef struct -{ - void *(*Alloc)(void *p, size_t size); - void (*Free)(void *p, void *address); /* address can be 0 */ -} ISzAlloc; - -#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) -#define IAlloc_Free(p, a) (p)->Free((p), a) - -#ifdef _WIN32 - -#define CHAR_PATH_SEPARATOR '\\' -#define WCHAR_PATH_SEPARATOR L'\\' -#define STRING_PATH_SEPARATOR "\\" -#define WSTRING_PATH_SEPARATOR L"\\" - -#else - -#define CHAR_PATH_SEPARATOR '/' -#define WCHAR_PATH_SEPARATOR L'/' -#define STRING_PATH_SEPARATOR "/" -#define WSTRING_PATH_SEPARATOR L"/" - -#endif - -EXTERN_C_END - -#endif +/* Types.h -- Basic types +2010-10-09 : Igor Pavlov : Public domain */ + +#ifndef __7Z_TYPES_H +#define __7Z_TYPES_H + +#include + +#ifdef _WIN32 +#include +#endif + +#ifndef EXTERN_C_BEGIN +#ifdef __cplusplus +#define EXTERN_C_BEGIN extern "C" { +#define EXTERN_C_END } +#else +#define EXTERN_C_BEGIN +#define EXTERN_C_END +#endif +#endif + +EXTERN_C_BEGIN + +#define SZ_OK 0 + +#define SZ_ERROR_DATA 1 +#define SZ_ERROR_MEM 2 +#define SZ_ERROR_CRC 3 +#define SZ_ERROR_UNSUPPORTED 4 +#define SZ_ERROR_PARAM 5 +#define SZ_ERROR_INPUT_EOF 6 +#define SZ_ERROR_OUTPUT_EOF 7 +#define SZ_ERROR_READ 8 +#define SZ_ERROR_WRITE 9 +#define SZ_ERROR_PROGRESS 10 +#define SZ_ERROR_FAIL 11 +#define SZ_ERROR_THREAD 12 + +#define SZ_ERROR_ARCHIVE 16 +#define SZ_ERROR_NO_ARCHIVE 17 + +typedef int SRes; + +#ifdef _WIN32 +typedef DWORD WRes; +#else +typedef int WRes; +#endif + +#ifndef RINOK +#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +#endif + +typedef unsigned char Byte; +typedef short Int16; +typedef unsigned short UInt16; + +#ifdef _LZMA_UINT32_IS_ULONG +typedef long Int32; +typedef unsigned long UInt32; +#else +typedef int Int32; +typedef unsigned int UInt32; +#endif + +#ifdef _SZ_NO_INT_64 + +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. + NOTES: Some code will work incorrectly in that case! */ + +typedef long Int64; +typedef unsigned long UInt64; + +#else + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#define UINT64_CONST(n) n +#else +typedef long long int Int64; +typedef unsigned long long int UInt64; +#define UINT64_CONST(n) n ## ULL +#endif + +#endif + +#ifdef _LZMA_NO_SYSTEM_SIZE_T +typedef UInt32 SizeT; +#else +typedef size_t SizeT; +#endif + +typedef int Bool; +#define True 1 +#define False 0 + + +#ifdef _WIN32 +#define MY_STD_CALL __stdcall +#else +#define MY_STD_CALL +#endif + +#ifdef _MSC_VER + +#if _MSC_VER >= 1300 +#define MY_NO_INLINE __declspec(noinline) +#else +#define MY_NO_INLINE +#endif + +#define MY_CDECL __cdecl +#define MY_FAST_CALL __fastcall + +#else + +#define MY_CDECL +#define MY_FAST_CALL + +#endif + + +/* The following interfaces use first parameter as pointer to structure */ + +typedef struct +{ + Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */ +} IByteIn; + +typedef struct +{ + void (*Write)(void *p, Byte b); +} IByteOut; + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) < input(*size)) is allowed */ +} ISeqInStream; + +/* it can return SZ_ERROR_INPUT_EOF */ +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); + +typedef struct +{ + size_t (*Write)(void *p, const void *buf, size_t size); + /* Returns: result - the number of actually written bytes. + (result < size) means error */ +} ISeqOutStream; + +typedef enum +{ + SZ_SEEK_SET = 0, + SZ_SEEK_CUR = 1, + SZ_SEEK_END = 2 +} ESzSeek; + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ISeekInStream; + +typedef struct +{ + SRes (*Look)(void *p, const void **buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) > input(*size)) is not allowed + (output(*size) < input(*size)) is allowed */ + SRes (*Skip)(void *p, size_t offset); + /* offset must be <= output(*size) of Look */ + + SRes (*Read)(void *p, void *buf, size_t *size); + /* reads directly (without buffer). It's same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ILookInStream; + +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); + +/* reads via ILookInStream::Read */ +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); + +#define LookToRead_BUF_SIZE (1 << 14) + +typedef struct +{ + ILookInStream s; + ISeekInStream *realStream; + size_t pos; + size_t size; + Byte buf[LookToRead_BUF_SIZE]; +} CLookToRead; + +void LookToRead_CreateVTable(CLookToRead *p, int lookahead); +void LookToRead_Init(CLookToRead *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToLook; + +void SecToLook_CreateVTable(CSecToLook *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToRead; + +void SecToRead_CreateVTable(CSecToRead *p); + +typedef struct +{ + SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); + /* Returns: result. (result != SZ_OK) means break. + Value (UInt64)(Int64)-1 for size means unknown value. */ +} ICompressProgress; + +typedef struct +{ + void *(*Alloc)(void *p, size_t size); + void (*Free)(void *p, void *address); /* address can be 0 */ +} ISzAlloc; + +#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) +#define IAlloc_Free(p, a) (p)->Free((p), a) + +#ifdef _WIN32 + +#define CHAR_PATH_SEPARATOR '\\' +#define WCHAR_PATH_SEPARATOR L'\\' +#define STRING_PATH_SEPARATOR "\\" +#define WSTRING_PATH_SEPARATOR L"\\" + +#else + +#define CHAR_PATH_SEPARATOR '/' +#define WCHAR_PATH_SEPARATOR L'/' +#define STRING_PATH_SEPARATOR "/" +#define WSTRING_PATH_SEPARATOR L"/" + +#endif + +EXTERN_C_END + +#endif diff --git a/LICENSE b/LICENSE index 89e08fb0..d159169d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,339 +1,339 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/Language/Arabic.nsh b/Language/Arabic.nsh index 23976800..d40eb2c2 100644 --- a/Language/Arabic.nsh +++ b/Language/Arabic.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "هذه النسخة ${VER} لا تدعم ويندوز 2000 لتشغيل البرنامج على ويندوز 2000 قم بتنزيل الإصدار رقم 2.0 من البرنامج." -${LangFileString} WINXPS2ERROR "هذه النسخة ${VER} تتطلب الحزمة الخدمية الثانية لويندوز إكس بي أو أعلى. الرجاء تحديثها." -${LangFileString} WIN2003SP1ERROR "هذه النسخة ${VER} تتطلب الحزمة الخدمية الثانية لويندوز 2003 أو أعلى. الرجاء تحديثها." -${LangFileString} ADMINERROR "صلاحيات إدارية مطلوبة." -${LangFileString} LOGONERROR "خدمة تسجيل الدخول لا تعمل." -${LangFileString} UACERROR "غير قادر على التنشيط." -${LangFileString} WRITEERROR "يجب تثبيت النسخة المحمولة في مكان ذو وصول كامل للقراءة و الكتابة .$\nإذا أرت تثبيت البرنامج في '$0', ارجع و اختر تثبيت قياسي.$\n$\nأو اختر مكان آخر ذو وصول كامل للقراءة و الكتابة." -${LangFileString} VCINSTERROR "Visual C++ $instArc فشل التثبيت مع رمز الخطأ $0.$\n$\nقد تحتاج تنزيل حزمة فيجوال سي بلس بلس $instArc يدوياً من http://rainmeter.net/redist$\n$\nاضغط موافق للخروج." -${LangFileString} DOTNETINSTERROR ".NET $instArc فشل التثبيت مع رمز الخطأ $0.$\n$\nقد تحتاج تنزيل حزمة the .NET $instArc يدوياً من http://rainmeter.net/redist$\n$\nاضغط موافق للخروج." -${LangFileString} RAINMETERCLOSEERROR "فشل إغلاق البرنامج.$\n$\nالرجاء إغلاق البرنامج يدوياً و المحاولة مرة أخرى." -${LangFileString} SETTINGSFILEERROR "ملف الإعدادات موجود في مجلد التثبيت. الإبقاء عليه هناك قد يسبب مشاكل عند استخدام البرنامج من أكثر من مستخدم أو مستخدم ذو صلاحيات محدودة .$\n$\nهل تريد نقل الملف إلى مجلد بيانات البرنامج؟" -${LangFileString} SETTINGSMOVEERROR "لا يمكن نقل الملف '$INSTDIR\Rainmeter.ini' إلى '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "اختر لغة المثبت." -${LangFileString} INSTALLOPTIONS "خيارات التثبيت" -${LangFileString} INSTALLOPTIONSDESC "اختيار خيارات التثبيت الإضافية" -${LangFileString} STANDARDINST "تثبيت قياسي (مستحسن)" -${LangFileString} STANDARDINSTDESC "تثبيت البرنامج و تنزيل المكتبات المطلوبة." -${LangFileString} PORTABLEINST "تثبيت محمول" -${LangFileString} PORTABLEINSTDESC "لا تختر هذا إلا إذا كنت تعرف ماذا تفعل. لن يتم عمل اختصارات .rmskin و لن يتم تسجيل امتداد الأنماط. و قد تحتاج إلى تنزيل المكتبات التالية تلقائياً Visual C++ و .NET 2.0." -${LangFileString} AUTOSTARTUP "تشغيل البرنامج عند بدء التشغيل" -${LangFileString} ADDITIONALOPTIONS "خيارات إضافية" -${LangFileString} INSTALL64BIT "تثبيت نسخة 64-بت" -${LangFileString} SENDINFORMATION "إرسال معلومات حول الكمبيوتر" -${LangFileString} SENDINFORMATIONDESC "إصدار ويندوز و اللغة و قدرات المكونات المادية الخاصة بجهازك سيتم إرسال تقرير بها مرة واحدة أثناء التثبيت لتحسين البرنامج. لن يتم إرسال معلومات شخصية" -${LangFileString} UNSTALLOPTIONS "خيارات إلغاء التثبيت" -${LangFileString} UNSTALLOPTIONSDESC "تحديد أي خيارات إضافية" -${LangFileString} UNSTALLRAINMETER "إزالة Rainmeter" -${LangFileString} UNSTALLSETTINGS "إزالة كل الإعدادات و الملفات الشخصية بشكل كامل" +${LangFileString} WIN2KERROR "هذه النسخة ${VER} لا تدعم ويندوز 2000 لتشغيل البرنامج على ويندوز 2000 قم بتنزيل الإصدار رقم 2.0 من البرنامج." +${LangFileString} WINXPS2ERROR "هذه النسخة ${VER} تتطلب الحزمة الخدمية الثانية لويندوز إكس بي أو أعلى. الرجاء تحديثها." +${LangFileString} WIN2003SP1ERROR "هذه النسخة ${VER} تتطلب الحزمة الخدمية الثانية لويندوز 2003 أو أعلى. الرجاء تحديثها." +${LangFileString} ADMINERROR "صلاحيات إدارية مطلوبة." +${LangFileString} LOGONERROR "خدمة تسجيل الدخول لا تعمل." +${LangFileString} UACERROR "غير قادر على التنشيط." +${LangFileString} WRITEERROR "يجب تثبيت النسخة المحمولة في مكان ذو وصول كامل للقراءة و الكتابة .$\nإذا أرت تثبيت البرنامج في '$0', ارجع و اختر تثبيت قياسي.$\n$\nأو اختر مكان آخر ذو وصول كامل للقراءة و الكتابة." +${LangFileString} VCINSTERROR "Visual C++ $instArc فشل التثبيت مع رمز الخطأ $0.$\n$\nقد تحتاج تنزيل حزمة فيجوال سي بلس بلس $instArc يدوياً من http://rainmeter.net/redist$\n$\nاضغط موافق للخروج." +${LangFileString} DOTNETINSTERROR ".NET $instArc فشل التثبيت مع رمز الخطأ $0.$\n$\nقد تحتاج تنزيل حزمة the .NET $instArc يدوياً من http://rainmeter.net/redist$\n$\nاضغط موافق للخروج." +${LangFileString} RAINMETERCLOSEERROR "فشل إغلاق البرنامج.$\n$\nالرجاء إغلاق البرنامج يدوياً و المحاولة مرة أخرى." +${LangFileString} SETTINGSFILEERROR "ملف الإعدادات موجود في مجلد التثبيت. الإبقاء عليه هناك قد يسبب مشاكل عند استخدام البرنامج من أكثر من مستخدم أو مستخدم ذو صلاحيات محدودة .$\n$\nهل تريد نقل الملف إلى مجلد بيانات البرنامج؟" +${LangFileString} SETTINGSMOVEERROR "لا يمكن نقل الملف '$INSTDIR\Rainmeter.ini' إلى '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "اختر لغة المثبت." +${LangFileString} INSTALLOPTIONS "خيارات التثبيت" +${LangFileString} INSTALLOPTIONSDESC "اختيار خيارات التثبيت الإضافية" +${LangFileString} STANDARDINST "تثبيت قياسي (مستحسن)" +${LangFileString} STANDARDINSTDESC "تثبيت البرنامج و تنزيل المكتبات المطلوبة." +${LangFileString} PORTABLEINST "تثبيت محمول" +${LangFileString} PORTABLEINSTDESC "لا تختر هذا إلا إذا كنت تعرف ماذا تفعل. لن يتم عمل اختصارات .rmskin و لن يتم تسجيل امتداد الأنماط. و قد تحتاج إلى تنزيل المكتبات التالية تلقائياً Visual C++ و .NET 2.0." +${LangFileString} AUTOSTARTUP "تشغيل البرنامج عند بدء التشغيل" +${LangFileString} ADDITIONALOPTIONS "خيارات إضافية" +${LangFileString} INSTALL64BIT "تثبيت نسخة 64-بت" +${LangFileString} SENDINFORMATION "إرسال معلومات حول الكمبيوتر" +${LangFileString} SENDINFORMATIONDESC "إصدار ويندوز و اللغة و قدرات المكونات المادية الخاصة بجهازك سيتم إرسال تقرير بها مرة واحدة أثناء التثبيت لتحسين البرنامج. لن يتم إرسال معلومات شخصية" +${LangFileString} UNSTALLOPTIONS "خيارات إلغاء التثبيت" +${LangFileString} UNSTALLOPTIONSDESC "تحديد أي خيارات إضافية" +${LangFileString} UNSTALLRAINMETER "إزالة Rainmeter" +${LangFileString} UNSTALLSETTINGS "إزالة كل الإعدادات و الملفات الشخصية بشكل كامل" ${LangFileString} UNSTALLSETTINGSDESC "(تضمين الأنماط ، السمات ، الإضافات ، إعدادات التسجيل و عناصر قائمة ابدأ)" \ No newline at end of file diff --git a/Language/Bulgarian.nsh b/Language/Bulgarian.nsh index fe1876bd..81851164 100644 --- a/Language/Bulgarian.nsh +++ b/Language/Bulgarian.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} не поддържа Windows 2000. За да използвате Rainmeter под Windows 2000, свалете по-старата Rainmeter 2.0 версия." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} изисква Windows XP SP2 или по-висока версия. Моля, обновете до най-новия сервизен пакет и опитайте отново." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} изисква Windows 2003 SP1 или по-висока версия. Моля, обновете до най-новия сервизен пакет и опитайте отново." -${LangFileString} ADMINERROR "Нужни са административни права." -${LangFileString} LOGONERROR "Услугата Logon service не е стартирана." -${LangFileString} UACERROR "Unable to elevate." -${LangFileString} WRITEERROR "Портативната инсталация на Rainmeter може да се осъществи само в папка с пълни права за четене и писане (като нормален потребител).$\nАко искате да инсталирате Rainmeter в '$0', се върнете обратно и изберете 'Стандартна инсталация'.$\n$\nВ противен случай посочете папка с пълен достъп (писане/четене)." -${LangFileString} VCINSTERROR "Visual C++ $instArc инсталацията е неуспешна с код за грешка $0.$\n$\nПрепоръчваме ви да свалите ръчно Visual C++ $instArc пакета от http://rainmeter.net/redist$\n$\nНатиснете OK за да излезете." -${LangFileString} DOTNETINSTERROR ".NET $instArc инсталацията е неуспешна с код за грешка $0.$\n$\nПрепоръчваме ви да свалите ръчно .NET $instArc пакета от http://rainmeter.net/redist$\n$\nНатиснете OK за да излезете." -${LangFileString} RAINMETERCLOSEERROR "Rainmeter не може да бъде затворен.$\n$\nМоля, затворете Rainmeter ръчно и опитайте отново." -${LangFileString} SETTINGSFILEERROR "Файла с опциите (Rainmeter.ini) се намира в инсталационната папка. Възможно е да възникнат проблеми при използване на програмата от повече от един потребител или от някого с ограничени права.$\n$\nИскате ли да преместите файла в потребителската папка за данни?" -${LangFileString} SETTINGSMOVEERROR "Файла '$INSTDIR\Rainmeter.ini' не може да бъде преместен в '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Посочете език на инсталатора." -${LangFileString} INSTALLOPTIONS "Опции за инсталацията" -${LangFileString} INSTALLOPTIONSDESC "Посочете опции за инсталацията" -${LangFileString} STANDARDINST "Стандартна инсталация (препоръчително)" -${LangFileString} STANDARDINSTDESC "Инсталирай Rainmeter и свали нужните библиотеки." -${LangFileString} PORTABLEINST "Портативна инсталация" -${LangFileString} PORTABLEINSTDESC "Не използвайте тази опция ако не знаете какво означава. Няма да бъдат създадени връзки в Старт менюто, нито асоциации за .rmskin разширенията. Възможно е библиотеките на Visual C++ и .NET 2.0 да трябва да се инсталират ръчно." -${LangFileString} AUTOSTARTUP "Стартирай Rainmeter с Windows" -${LangFileString} ADDITIONALOPTIONS "Допълнителни опции" -${LangFileString} INSTALL64BIT "64-битова" -${LangFileString} SENDINFORMATION "Send information about your computer" -${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." -${LangFileString} UNSTALLOPTIONS "Опции за деинсталация" -${LangFileString} UNSTALLOPTIONSDESC "Посочете допълнителни опции" -${LangFileString} UNSTALLRAINMETER "Деинсталирай Rainmeter" -${LangFileString} UNSTALLSETTINGS "Премахни всички персонални настройки и файлове" +${LangFileString} WIN2KERROR "Rainmeter ${VER} не поддържа Windows 2000. За да използвате Rainmeter под Windows 2000, свалете по-старата Rainmeter 2.0 версия." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} изисква Windows XP SP2 или по-висока версия. Моля, обновете до най-новия сервизен пакет и опитайте отново." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} изисква Windows 2003 SP1 или по-висока версия. Моля, обновете до най-новия сервизен пакет и опитайте отново." +${LangFileString} ADMINERROR "Нужни са административни права." +${LangFileString} LOGONERROR "Услугата Logon service не е стартирана." +${LangFileString} UACERROR "Unable to elevate." +${LangFileString} WRITEERROR "Портативната инсталация на Rainmeter може да се осъществи само в папка с пълни права за четене и писане (като нормален потребител).$\nАко искате да инсталирате Rainmeter в '$0', се върнете обратно и изберете 'Стандартна инсталация'.$\n$\nВ противен случай посочете папка с пълен достъп (писане/четене)." +${LangFileString} VCINSTERROR "Visual C++ $instArc инсталацията е неуспешна с код за грешка $0.$\n$\nПрепоръчваме ви да свалите ръчно Visual C++ $instArc пакета от http://rainmeter.net/redist$\n$\nНатиснете OK за да излезете." +${LangFileString} DOTNETINSTERROR ".NET $instArc инсталацията е неуспешна с код за грешка $0.$\n$\nПрепоръчваме ви да свалите ръчно .NET $instArc пакета от http://rainmeter.net/redist$\n$\nНатиснете OK за да излезете." +${LangFileString} RAINMETERCLOSEERROR "Rainmeter не може да бъде затворен.$\n$\nМоля, затворете Rainmeter ръчно и опитайте отново." +${LangFileString} SETTINGSFILEERROR "Файла с опциите (Rainmeter.ini) се намира в инсталационната папка. Възможно е да възникнат проблеми при използване на програмата от повече от един потребител или от някого с ограничени права.$\n$\nИскате ли да преместите файла в потребителската папка за данни?" +${LangFileString} SETTINGSMOVEERROR "Файла '$INSTDIR\Rainmeter.ini' не може да бъде преместен в '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Посочете език на инсталатора." +${LangFileString} INSTALLOPTIONS "Опции за инсталацията" +${LangFileString} INSTALLOPTIONSDESC "Посочете опции за инсталацията" +${LangFileString} STANDARDINST "Стандартна инсталация (препоръчително)" +${LangFileString} STANDARDINSTDESC "Инсталирай Rainmeter и свали нужните библиотеки." +${LangFileString} PORTABLEINST "Портативна инсталация" +${LangFileString} PORTABLEINSTDESC "Не използвайте тази опция ако не знаете какво означава. Няма да бъдат създадени връзки в Старт менюто, нито асоциации за .rmskin разширенията. Възможно е библиотеките на Visual C++ и .NET 2.0 да трябва да се инсталират ръчно." +${LangFileString} AUTOSTARTUP "Стартирай Rainmeter с Windows" +${LangFileString} ADDITIONALOPTIONS "Допълнителни опции" +${LangFileString} INSTALL64BIT "64-битова" +${LangFileString} SENDINFORMATION "Send information about your computer" +${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." +${LangFileString} UNSTALLOPTIONS "Опции за деинсталация" +${LangFileString} UNSTALLOPTIONSDESC "Посочете допълнителни опции" +${LangFileString} UNSTALLRAINMETER "Деинсталирай Rainmeter" +${LangFileString} UNSTALLSETTINGS "Премахни всички персонални настройки и файлове" ${LangFileString} UNSTALLSETTINGSDESC "(включително кофи, теми, добавки, опции в регистрите и връзки в Старт менюто)" \ No newline at end of file diff --git a/Language/ChineseSimplified.nsh b/Language/ChineseSimplified.nsh index 7f24b655..e9606740 100644 --- a/Language/ChineseSimplified.nsh +++ b/Language/ChineseSimplified.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} 不支持Windows 2000。 如果要在Windows 2000上运行Rainmeter,请下载Rainmeter 2.0或更早版本。" -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} 支持Windows XP SP2或更高版本。 请升级到最新的服务包,然后再试一次。" -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} 支持Windows 2003 SP1或更高版本。 请升级到最新的服务包,然后再试一次。" -${LangFileString} ADMINERROR "需要管理员权限。" -${LangFileString} LOGONERROR "Logon 服务未运行。" -${LangFileString} UACERROR "无法创建。" -${LangFileString} WRITEERROR "便携式Rainmeter必须安装在一个普通用户具有完全读写权限的位置。$\n如果你要将Rainmeter安装在'$0', 请返回并选择'标准安装'.$\n$\n 否则,请选择一个普通用户具有完全读写权限的位置。" -${LangFileString} VCINSTERROR "Visual C++ $instArc 安装失败 错误代码 $0。$\n$\n 你可能需要手动从http://rainmeter.net/redist下载Visual C++ $instArc 组件安装包 $\n$\n点击确认退出。" -${LangFileString} DOTNETINSTERROR ".NET $instArc 安装失败 错误代码 $0。$\n$\n 你可能需要手动从http://rainmeter.net/redist下载.NET $instArc 组件安装包 $\n$\n点击确认退出。" -${LangFileString} RAINMETERCLOSEERROR "无法关闭Rainmeter.$\n$\n请手动关闭Rainmeter后再试。" -${LangFileString} SETTINGSFILEERROR "配置文件(Rainmeter.ini)位于安装文件夹内. 如果该文件被多个用户在共同使用,将它移动到此处可能会导致错误.$\n$\n你确定要将该文件移动到application data文件夹吗?" -${LangFileString} SETTINGSMOVEERROR "无法将文件'$INSTDIR\Rainmeter.ini' 移动到 '$APPDATA\Rainmeter\Rainmeter.ini'。" -${LangFileString} SELECTLANGUAGE "请选择安装语言。" -${LangFileString} INSTALLOPTIONS "安装选项" -${LangFileString} INSTALLOPTIONSDESC "选择其它安装选项" -${LangFileString} STANDARDINST "标准安装(推荐)" -${LangFileString} STANDARDINSTDESC "安装Rainmeter并下载所需的运行库。" -${LangFileString} PORTABLEINST "便携式安装" -${LangFileString} PORTABLEINSTDESC "如果你不了解该项,请不要选择。便携式安装不会创建快捷方式、也不会与rmskin文件关联。您可能还需要手动下载安装Visual C++和.NET 2.0运行库。" -${LangFileString} AUTOSTARTUP "开机运行Rainmeter" -${LangFileString} ADDITIONALOPTIONS "附加选项" -${LangFileString} INSTALL64BIT "安装 64 位版本" -${LangFileString} SENDINFORMATION "发送计算机信息" -${LangFileString} SENDINFORMATIONDESC "Rainmeter 安装程序会在安装过程中将您的 Windows 版本,语言以及硬件性能等信息反馈给我们,以帮助我们更好的改善 Rainmeter。不会发送您的个人信息。" -${LangFileString} UNSTALLOPTIONS "卸载选项" -${LangFileString} UNSTALLOPTIONSDESC "选择所有附加项" -${LangFileString} UNSTALLRAINMETER "卸载 Rainmeter" -${LangFileString} UNSTALLSETTINGS "完全移除所有个人设置和文件" +${LangFileString} WIN2KERROR "Rainmeter ${VER} 不支持Windows 2000。 如果要在Windows 2000上运行Rainmeter,请下载Rainmeter 2.0或更早版本。" +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} 支持Windows XP SP2或更高版本。 请升级到最新的服务包,然后再试一次。" +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} 支持Windows 2003 SP1或更高版本。 请升级到最新的服务包,然后再试一次。" +${LangFileString} ADMINERROR "需要管理员权限。" +${LangFileString} LOGONERROR "Logon 服务未运行。" +${LangFileString} UACERROR "无法创建。" +${LangFileString} WRITEERROR "便携式Rainmeter必须安装在一个普通用户具有完全读写权限的位置。$\n如果你要将Rainmeter安装在'$0', 请返回并选择'标准安装'.$\n$\n 否则,请选择一个普通用户具有完全读写权限的位置。" +${LangFileString} VCINSTERROR "Visual C++ $instArc 安装失败 错误代码 $0。$\n$\n 你可能需要手动从http://rainmeter.net/redist下载Visual C++ $instArc 组件安装包 $\n$\n点击确认退出。" +${LangFileString} DOTNETINSTERROR ".NET $instArc 安装失败 错误代码 $0。$\n$\n 你可能需要手动从http://rainmeter.net/redist下载.NET $instArc 组件安装包 $\n$\n点击确认退出。" +${LangFileString} RAINMETERCLOSEERROR "无法关闭Rainmeter.$\n$\n请手动关闭Rainmeter后再试。" +${LangFileString} SETTINGSFILEERROR "配置文件(Rainmeter.ini)位于安装文件夹内. 如果该文件被多个用户在共同使用,将它移动到此处可能会导致错误.$\n$\n你确定要将该文件移动到application data文件夹吗?" +${LangFileString} SETTINGSMOVEERROR "无法将文件'$INSTDIR\Rainmeter.ini' 移动到 '$APPDATA\Rainmeter\Rainmeter.ini'。" +${LangFileString} SELECTLANGUAGE "请选择安装语言。" +${LangFileString} INSTALLOPTIONS "安装选项" +${LangFileString} INSTALLOPTIONSDESC "选择其它安装选项" +${LangFileString} STANDARDINST "标准安装(推荐)" +${LangFileString} STANDARDINSTDESC "安装Rainmeter并下载所需的运行库。" +${LangFileString} PORTABLEINST "便携式安装" +${LangFileString} PORTABLEINSTDESC "如果你不了解该项,请不要选择。便携式安装不会创建快捷方式、也不会与rmskin文件关联。您可能还需要手动下载安装Visual C++和.NET 2.0运行库。" +${LangFileString} AUTOSTARTUP "开机运行Rainmeter" +${LangFileString} ADDITIONALOPTIONS "附加选项" +${LangFileString} INSTALL64BIT "安装 64 位版本" +${LangFileString} SENDINFORMATION "发送计算机信息" +${LangFileString} SENDINFORMATIONDESC "Rainmeter 安装程序会在安装过程中将您的 Windows 版本,语言以及硬件性能等信息反馈给我们,以帮助我们更好的改善 Rainmeter。不会发送您的个人信息。" +${LangFileString} UNSTALLOPTIONS "卸载选项" +${LangFileString} UNSTALLOPTIONSDESC "选择所有附加项" +${LangFileString} UNSTALLRAINMETER "卸载 Rainmeter" +${LangFileString} UNSTALLSETTINGS "完全移除所有个人设置和文件" ${LangFileString} UNSTALLSETTINGSDESC "(包括皮肤,主题,插件,注册表设置以及开始菜单项)" \ No newline at end of file diff --git a/Language/ChineseTraditional.nsh b/Language/ChineseTraditional.nsh index 06eecf29..7fa5ca1a 100644 --- a/Language/ChineseTraditional.nsh +++ b/Language/ChineseTraditional.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} 不支援 Windows 2000。如果要在 Windows 2000 上執行 Rainmeter,請下載 Rainmeter 2.0 或更早版本。" -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} 需要 Windows XP SP2 或更高版本。請升級到最新的 Service Pack,然後再試一次。" -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} 需要 Windows 2003 SP1 或更高版本。請升級到最新的 Service Pack,然後再試一次。" -${LangFileString} ADMINERROR "需要管理員權限。" -${LangFileString} LOGONERROR "Logon 服務未執行。" -${LangFileString} UACERROR "無法建立。" -${LangFileString} WRITEERROR "便攜式 Rainmeter 必須安裝在一個普通使用者具有完全存取權限的位置。$\n如果你要將 Rainmeter 安裝在'$0', 請返回並選擇'標準安裝'。$\n$\n 否則,請選擇一個普通使用者具有完全存取權限的位置。" -${LangFileString} VCINSTERROR "Visual C++ $instArc 安裝失敗 錯誤代碼 $0。$\n$\n 你可能需要手動從 http://rainmeter.net/redist 下載 Visual C++ $instArc 組件庫 $\n$\n點擊確認離開。" -${LangFileString} DOTNETINSTERROR ".NET $instArc 安裝失敗 錯誤代碼 $0。$\n$\n 你可能需要手動從 http://rainmeter.net/redist 下載 .NET $instArc 組件庫 $\n$\n點擊確認離開。" -${LangFileString} RAINMETERCLOSEERROR "無法關閉 Rainmeter。$\n$\n請手動關閉Rainmeter後再試。" -${LangFileString} SETTINGSFILEERROR "設定檔案(Rainmeter.ini)位於安裝資料夾內。如果該檔案被多個使用者共同使用,將它移動到此處可能會導致錯誤。$\n$\n你確定要將該檔案移動到 application data 資料夾嗎?" -${LangFileString} SETTINGSMOVEERROR "無法將檔案'$INSTDIR\Rainmeter.ini' 移動到 '$APPDATA\Rainmeter\Rainmeter.ini'。" -${LangFileString} SELECTLANGUAGE "請選擇安裝語言。" -${LangFileString} INSTALLOPTIONS "安裝選項" -${LangFileString} INSTALLOPTIONSDESC "選擇其它安裝選項" -${LangFileString} STANDARDINST "標準安裝(建議)" -${LangFileString} STANDARDINSTDESC "安裝 Rainmeter 並下載所需的組件庫。" -${LangFileString} PORTABLEINST "便攜式安裝" -${LangFileString} PORTABLEINSTDESC "如果你不了解該選項,請不要選擇。便攜式安裝不會建立快捷方式、也不會與 rmskin 檔案關聯。你可能還需要手動下載安裝 Visual C++ 和 .NET 2.0 組件庫。" -${LangFileString} AUTOSTARTUP "開機時執行 Rainmeter" -${LangFileString} ADDITIONALOPTIONS "附加選項" -${LangFileString} INSTALL64BIT "安裝 64 位元版本" -${LangFileString} SENDINFORMATION "傳送電腦資訊" -${LangFileString} SENDINFORMATIONDESC "Rainmeter 安裝程式會在安裝過程中將你的 Windows 版本、語言以及硬體效能等資訊回報給我們,以幫助我們改善 Rainmeter 變得更好。資訊回報不會傳送你的任何個人資訊。" -${LangFileString} UNSTALLOPTIONS "移除選項" -${LangFileString} UNSTALLOPTIONSDESC "選擇所有附加選項" -${LangFileString} UNSTALLRAINMETER "移除 Rainmeter" -${LangFileString} UNSTALLSETTINGS "完全移除所有個人設定和檔案" +${LangFileString} WIN2KERROR "Rainmeter ${VER} 不支援 Windows 2000。如果要在 Windows 2000 上執行 Rainmeter,請下載 Rainmeter 2.0 或更早版本。" +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} 需要 Windows XP SP2 或更高版本。請升級到最新的 Service Pack,然後再試一次。" +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} 需要 Windows 2003 SP1 或更高版本。請升級到最新的 Service Pack,然後再試一次。" +${LangFileString} ADMINERROR "需要管理員權限。" +${LangFileString} LOGONERROR "Logon 服務未執行。" +${LangFileString} UACERROR "無法建立。" +${LangFileString} WRITEERROR "便攜式 Rainmeter 必須安裝在一個普通使用者具有完全存取權限的位置。$\n如果你要將 Rainmeter 安裝在'$0', 請返回並選擇'標準安裝'。$\n$\n 否則,請選擇一個普通使用者具有完全存取權限的位置。" +${LangFileString} VCINSTERROR "Visual C++ $instArc 安裝失敗 錯誤代碼 $0。$\n$\n 你可能需要手動從 http://rainmeter.net/redist 下載 Visual C++ $instArc 組件庫 $\n$\n點擊確認離開。" +${LangFileString} DOTNETINSTERROR ".NET $instArc 安裝失敗 錯誤代碼 $0。$\n$\n 你可能需要手動從 http://rainmeter.net/redist 下載 .NET $instArc 組件庫 $\n$\n點擊確認離開。" +${LangFileString} RAINMETERCLOSEERROR "無法關閉 Rainmeter。$\n$\n請手動關閉Rainmeter後再試。" +${LangFileString} SETTINGSFILEERROR "設定檔案(Rainmeter.ini)位於安裝資料夾內。如果該檔案被多個使用者共同使用,將它移動到此處可能會導致錯誤。$\n$\n你確定要將該檔案移動到 application data 資料夾嗎?" +${LangFileString} SETTINGSMOVEERROR "無法將檔案'$INSTDIR\Rainmeter.ini' 移動到 '$APPDATA\Rainmeter\Rainmeter.ini'。" +${LangFileString} SELECTLANGUAGE "請選擇安裝語言。" +${LangFileString} INSTALLOPTIONS "安裝選項" +${LangFileString} INSTALLOPTIONSDESC "選擇其它安裝選項" +${LangFileString} STANDARDINST "標準安裝(建議)" +${LangFileString} STANDARDINSTDESC "安裝 Rainmeter 並下載所需的組件庫。" +${LangFileString} PORTABLEINST "便攜式安裝" +${LangFileString} PORTABLEINSTDESC "如果你不了解該選項,請不要選擇。便攜式安裝不會建立快捷方式、也不會與 rmskin 檔案關聯。你可能還需要手動下載安裝 Visual C++ 和 .NET 2.0 組件庫。" +${LangFileString} AUTOSTARTUP "開機時執行 Rainmeter" +${LangFileString} ADDITIONALOPTIONS "附加選項" +${LangFileString} INSTALL64BIT "安裝 64 位元版本" +${LangFileString} SENDINFORMATION "傳送電腦資訊" +${LangFileString} SENDINFORMATIONDESC "Rainmeter 安裝程式會在安裝過程中將你的 Windows 版本、語言以及硬體效能等資訊回報給我們,以幫助我們改善 Rainmeter 變得更好。資訊回報不會傳送你的任何個人資訊。" +${LangFileString} UNSTALLOPTIONS "移除選項" +${LangFileString} UNSTALLOPTIONSDESC "選擇所有附加選項" +${LangFileString} UNSTALLRAINMETER "移除 Rainmeter" +${LangFileString} UNSTALLSETTINGS "完全移除所有個人設定和檔案" ${LangFileString} UNSTALLSETTINGSDESC "(包括面板,主題,插件,登錄值設定以及開始選單項目)" \ No newline at end of file diff --git a/Language/Croatian.nsh b/Language/Croatian.nsh index d09e1afd..558b0bfc 100644 --- a/Language/Croatian.nsh +++ b/Language/Croatian.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} ne podržava Windowse 2000. Za korištenje Rainmetera na Windowsima 2000, skinite stariju verziju, Rainmeter 2.0." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} zahtjeva Windowse XP SP2 ili više. Molimo vas nadogradite na najnoviji service pack i pokušajte ponovo." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} zahtjeva Windows 2003 SP1 ili više. Molimo vas nadogradite na najnoviji service pack i pokušajte ponovo." -${LangFileString} ADMINERROR "Potrebne su adminstrativne ovlasti." -${LangFileString} LOGONERROR "Logon servis nije pokrenut." -${LangFileString} UACERROR "Nije moguće uzdići prava." -${LangFileString} WRITEERROR "Prijenosni Rainmeter mora biti instaliran u lokaciju s punim pravima čitanja i pisanja (kao običan korisnik).$\nUkoliko želite instalirati Rainmeter u '$0', vratite se i izaberite 'Standardna instalacija'.$\n$\nInače, nađite drugu lokaciju s punim pravima čitanja i pisanja." -${LangFileString} VCINSTERROR "Visual C++ $instArc instalacija nije uspjela s kodom greške $0.$\n$\nPokušajte ručno skinuti Visual C++ $instArc redistributable package sa http://rainmeter.net/redist$\n$\nKliknite OK za izlaz." -${LangFileString} DOTNETINSTERROR ".NET $instArc instalacija nije uspjela s kodom greške $0.$\n$\nPokušajte skinuti .NET $instArc redistributable package ručno sa http://rainmeter.net/redist$\n$\nPritisnite OK za izlaz." -${LangFileString} RAINMETERCLOSEERROR "Gašenje Rainmetera nije uspjelo.$\n$\nMolimo vas ručno ugasite Rainmeter i pokušajte ponovo." -${LangFileString} SETTINGSFILEERROR "Datoteka s postavkama (Rainmeter.ini) nalazi se u instalacijskom direktoriju. Ukoliko ju ostavite tamo, može prouzročiti probleme ako aplikaciju koristi više korisnika ili bilo tko sa ograničenim pravima pristupa.$\n$\nŽelite li premjestiti datoteku u podatkovni direktorij aplikacije?" -${LangFileString} SETTINGSMOVEERROR "Nije moguće premjestiti '$INSTDIR\Rainmeter.ini' u '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Molimo vas izaberite jezik instalacijske procedure." -${LangFileString} INSTALLOPTIONS "Instalacijske opcije" -${LangFileString} INSTALLOPTIONSDESC "Izaberite dodatne instalacijske opcije" -${LangFileString} STANDARDINST "Standardna instalacija (preporučeno)" -${LangFileString} STANDARDINSTDESC "Instalira Rainmeter i skida potrebne biblioteke." -${LangFileString} PORTABLEINST "Prijenosna instalacija" -${LangFileString} PORTABLEINSTDESC "Nemojte izabrati ovu opciju osim ako točno znate što radite. Prečice neće biti kreirane i .rmskin ekstenzija neće biti registrirana. Možda će biti potrebno ručno instalirati Visual C++ i .NET 2.0 biblioteke." -${LangFileString} AUTOSTARTUP "Pokreni Rainmeter na pokretanje računala" -${LangFileString} ADDITIONALOPTIONS "Dodatne opcije" -${LangFileString} INSTALL64BIT "Instaliraj 64-bitnu verziju" -${LangFileString} SENDINFORMATION "Send information about your computer" -${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." -${LangFileString} UNSTALLOPTIONS "Deinstalacijske mogućnosti" -${LangFileString} UNSTALLOPTIONSDESC "Izaberite dodatne mogućnosti" -${LangFileString} UNSTALLRAINMETER "Deinstaliraj Rainmeter" -${LangFileString} UNSTALLSETTINGS "U potpunosti izbriši sve osobne postavke i datoteke." -${LangFileString} UNSTALLSETTINGSDESC "(uključujući skinove, teme, dodatke, registry postavke i stavke u start meniju.)" +${LangFileString} WIN2KERROR "Rainmeter ${VER} ne podržava Windowse 2000. Za korištenje Rainmetera na Windowsima 2000, skinite stariju verziju, Rainmeter 2.0." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} zahtjeva Windowse XP SP2 ili više. Molimo vas nadogradite na najnoviji service pack i pokušajte ponovo." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} zahtjeva Windows 2003 SP1 ili više. Molimo vas nadogradite na najnoviji service pack i pokušajte ponovo." +${LangFileString} ADMINERROR "Potrebne su adminstrativne ovlasti." +${LangFileString} LOGONERROR "Logon servis nije pokrenut." +${LangFileString} UACERROR "Nije moguće uzdići prava." +${LangFileString} WRITEERROR "Prijenosni Rainmeter mora biti instaliran u lokaciju s punim pravima čitanja i pisanja (kao običan korisnik).$\nUkoliko želite instalirati Rainmeter u '$0', vratite se i izaberite 'Standardna instalacija'.$\n$\nInače, nađite drugu lokaciju s punim pravima čitanja i pisanja." +${LangFileString} VCINSTERROR "Visual C++ $instArc instalacija nije uspjela s kodom greške $0.$\n$\nPokušajte ručno skinuti Visual C++ $instArc redistributable package sa http://rainmeter.net/redist$\n$\nKliknite OK za izlaz." +${LangFileString} DOTNETINSTERROR ".NET $instArc instalacija nije uspjela s kodom greške $0.$\n$\nPokušajte skinuti .NET $instArc redistributable package ručno sa http://rainmeter.net/redist$\n$\nPritisnite OK za izlaz." +${LangFileString} RAINMETERCLOSEERROR "Gašenje Rainmetera nije uspjelo.$\n$\nMolimo vas ručno ugasite Rainmeter i pokušajte ponovo." +${LangFileString} SETTINGSFILEERROR "Datoteka s postavkama (Rainmeter.ini) nalazi se u instalacijskom direktoriju. Ukoliko ju ostavite tamo, može prouzročiti probleme ako aplikaciju koristi više korisnika ili bilo tko sa ograničenim pravima pristupa.$\n$\nŽelite li premjestiti datoteku u podatkovni direktorij aplikacije?" +${LangFileString} SETTINGSMOVEERROR "Nije moguće premjestiti '$INSTDIR\Rainmeter.ini' u '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Molimo vas izaberite jezik instalacijske procedure." +${LangFileString} INSTALLOPTIONS "Instalacijske opcije" +${LangFileString} INSTALLOPTIONSDESC "Izaberite dodatne instalacijske opcije" +${LangFileString} STANDARDINST "Standardna instalacija (preporučeno)" +${LangFileString} STANDARDINSTDESC "Instalira Rainmeter i skida potrebne biblioteke." +${LangFileString} PORTABLEINST "Prijenosna instalacija" +${LangFileString} PORTABLEINSTDESC "Nemojte izabrati ovu opciju osim ako točno znate što radite. Prečice neće biti kreirane i .rmskin ekstenzija neće biti registrirana. Možda će biti potrebno ručno instalirati Visual C++ i .NET 2.0 biblioteke." +${LangFileString} AUTOSTARTUP "Pokreni Rainmeter na pokretanje računala" +${LangFileString} ADDITIONALOPTIONS "Dodatne opcije" +${LangFileString} INSTALL64BIT "Instaliraj 64-bitnu verziju" +${LangFileString} SENDINFORMATION "Send information about your computer" +${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." +${LangFileString} UNSTALLOPTIONS "Deinstalacijske mogućnosti" +${LangFileString} UNSTALLOPTIONSDESC "Izaberite dodatne mogućnosti" +${LangFileString} UNSTALLRAINMETER "Deinstaliraj Rainmeter" +${LangFileString} UNSTALLSETTINGS "U potpunosti izbriši sve osobne postavke i datoteke." +${LangFileString} UNSTALLSETTINGSDESC "(uključujući skinove, teme, dodatke, registry postavke i stavke u start meniju.)" diff --git a/Language/Czech.nsh b/Language/Czech.nsh index 23581828..dd484eaf 100644 --- a/Language/Czech.nsh +++ b/Language/Czech.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} nepodporuje Windows 2000. Pro použití Rainmeteru ve Windows 2000 stáhněte starší verzi Rainmeter 2.0." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} vyžaduje Windows XP SP2 nebo vyšší. Prosím upgradujte na nejnovější verzi service packu a zkuste to znovu." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} vyžaduje Windows 2003 SP1 nebo vyšší. Prosím upgradujte na nejnovější verzi service packu a zkuste to znovu." -${LangFileString} ADMINERROR "Požadována administrátorská práva." -${LangFileString} LOGONERROR "Služba přihlášení není spuštěna." -${LangFileString} UACERROR "Nelze povýšit." -${LangFileString} WRITEERROR "Přenosný Rainmeter musí být instalován do umístění s plným oprávněním čtení i zápisu (jako běžný uživatel).$\nPokud chcete instalovat Rainmeter do '$0', jděte zpět a vyberte 'Standardní instalace'.$\n$\nPřípadně vyberte jiné umístění s plným oprávněním čtení i zápisu." -${LangFileString} VCINSTERROR "Instalace Visual C++ $instArc selhala s chybovým kódem $0.$\n$\nMůžete zkusit stáhnout Visual C++ $instArc redistributable package ručně z http://rainmeter.net/redist$\n$\nStiskněte OK pro ukončení." -${LangFileString} DOTNETINSTERROR "Instalace .NET $instArc selhala s chybovým kódem $0.$\n$\nMůžete zkusit stáhnout .NET $instArc redistributable package ručně z http://rainmeter.net/redist$\n$\nStiskněte OK pro ukončení." -${LangFileString} RAINMETERCLOSEERROR "Ukončení Rainmeteru selhalo.$\n$\nProsím ukončete Rainmeter ručně a zkuste to znovu." -${LangFileString} SETTINGSFILEERROR "Soubor nastavení (Rainmeter.ini) je umístěn v instalační složce. Může to způsobit problémy, bude-li aplikace používána více uživateli nebo uživateli s omezeným oprávněním.$\n$\nChcete přesunout soubor do složky data aplikací?" -${LangFileString} SETTINGSMOVEERROR "Nelze přesunout soubor '$INSTDIR\Rainmeter.ini' do '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE " " -${LangFileString} INSTALLOPTIONS "Možnosti instalace" -${LangFileString} INSTALLOPTIONSDESC "Vyberte další možnosti instalace" -${LangFileString} STANDARDINST "Standardní instalace (doporučeno)" -${LangFileString} STANDARDINSTDESC "Instalace Rainmeteru a stažení požadovaných knihoven." -${LangFileString} PORTABLEINST "Přenosná instalace" -${LangFileString} PORTABLEINSTDESC "Nevybírejte tuto možnost, pokud nevíte, co děláte. Zástupci nebudou vytvořeny a přípona .rmskin nebude registrována. Visual C++ a .NET 2.0 bude možná potřeba nainstalovat ručně." -${LangFileString} AUTOSTARTUP "Spustit Rainmeter při startu" -${LangFileString} ADDITIONALOPTIONS "Další možnosti" -${LangFileString} INSTALL64BIT "Instalovat 64-bitovou verzi" -${LangFileString} SENDINFORMATION "Odeslat informace o počítači" -${LangFileString} SENDINFORMATIONDESC "Pro zlepšení programu Rainmeter budou v průběhu instalace odeslány informace o jazyku a verzi systému Windows a informace o hardwarových schopnostech vašeho počítače. Osobní údaje nebudou odeslány." -${LangFileString} UNSTALLOPTIONS "Možnosti odinstalace" -${LangFileString} UNSTALLOPTIONSDESC "Vyberte další možnosti" -${LangFileString} UNSTALLRAINMETER "Odinstalovat Rainmeter" -${LangFileString} UNSTALLSETTINGS "Úplně odebrat všechny soubory a osobní nastavení" +${LangFileString} WIN2KERROR "Rainmeter ${VER} nepodporuje Windows 2000. Pro použití Rainmeteru ve Windows 2000 stáhněte starší verzi Rainmeter 2.0." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} vyžaduje Windows XP SP2 nebo vyšší. Prosím upgradujte na nejnovější verzi service packu a zkuste to znovu." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} vyžaduje Windows 2003 SP1 nebo vyšší. Prosím upgradujte na nejnovější verzi service packu a zkuste to znovu." +${LangFileString} ADMINERROR "Požadována administrátorská práva." +${LangFileString} LOGONERROR "Služba přihlášení není spuštěna." +${LangFileString} UACERROR "Nelze povýšit." +${LangFileString} WRITEERROR "Přenosný Rainmeter musí být instalován do umístění s plným oprávněním čtení i zápisu (jako běžný uživatel).$\nPokud chcete instalovat Rainmeter do '$0', jděte zpět a vyberte 'Standardní instalace'.$\n$\nPřípadně vyberte jiné umístění s plným oprávněním čtení i zápisu." +${LangFileString} VCINSTERROR "Instalace Visual C++ $instArc selhala s chybovým kódem $0.$\n$\nMůžete zkusit stáhnout Visual C++ $instArc redistributable package ručně z http://rainmeter.net/redist$\n$\nStiskněte OK pro ukončení." +${LangFileString} DOTNETINSTERROR "Instalace .NET $instArc selhala s chybovým kódem $0.$\n$\nMůžete zkusit stáhnout .NET $instArc redistributable package ručně z http://rainmeter.net/redist$\n$\nStiskněte OK pro ukončení." +${LangFileString} RAINMETERCLOSEERROR "Ukončení Rainmeteru selhalo.$\n$\nProsím ukončete Rainmeter ručně a zkuste to znovu." +${LangFileString} SETTINGSFILEERROR "Soubor nastavení (Rainmeter.ini) je umístěn v instalační složce. Může to způsobit problémy, bude-li aplikace používána více uživateli nebo uživateli s omezeným oprávněním.$\n$\nChcete přesunout soubor do složky data aplikací?" +${LangFileString} SETTINGSMOVEERROR "Nelze přesunout soubor '$INSTDIR\Rainmeter.ini' do '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE " " +${LangFileString} INSTALLOPTIONS "Možnosti instalace" +${LangFileString} INSTALLOPTIONSDESC "Vyberte další možnosti instalace" +${LangFileString} STANDARDINST "Standardní instalace (doporučeno)" +${LangFileString} STANDARDINSTDESC "Instalace Rainmeteru a stažení požadovaných knihoven." +${LangFileString} PORTABLEINST "Přenosná instalace" +${LangFileString} PORTABLEINSTDESC "Nevybírejte tuto možnost, pokud nevíte, co děláte. Zástupci nebudou vytvořeny a přípona .rmskin nebude registrována. Visual C++ a .NET 2.0 bude možná potřeba nainstalovat ručně." +${LangFileString} AUTOSTARTUP "Spustit Rainmeter při startu" +${LangFileString} ADDITIONALOPTIONS "Další možnosti" +${LangFileString} INSTALL64BIT "Instalovat 64-bitovou verzi" +${LangFileString} SENDINFORMATION "Odeslat informace o počítači" +${LangFileString} SENDINFORMATIONDESC "Pro zlepšení programu Rainmeter budou v průběhu instalace odeslány informace o jazyku a verzi systému Windows a informace o hardwarových schopnostech vašeho počítače. Osobní údaje nebudou odeslány." +${LangFileString} UNSTALLOPTIONS "Možnosti odinstalace" +${LangFileString} UNSTALLOPTIONSDESC "Vyberte další možnosti" +${LangFileString} UNSTALLRAINMETER "Odinstalovat Rainmeter" +${LangFileString} UNSTALLSETTINGS "Úplně odebrat všechny soubory a osobní nastavení" ${LangFileString} UNSTALLSETTINGSDESC "(včetně skinů, témat, doplňků, nastavení registrů a položek nabídky Start)" \ No newline at end of file diff --git a/Language/Danish.nsh b/Language/Danish.nsh index 30847b86..d6347c71 100644 --- a/Language/Danish.nsh +++ b/Language/Danish.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} understøtter ikke Windows 2000. For at bruge Rainmeter på Windows 2000 skal du hente den ældre Rainmeter 2.0 version." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} kræver Windows XP SP2 eller nyere. Opdater venligst til den seneste service pack og prøv igen." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} kræver Windows 2003 SP1 eller senere. Opdater venligst til den seneste service pack og prøv igen." -${LangFileString} ADMINERROR "Adminstrative rettigheder påkrævet." -${LangFileString} LOGONERROR "Logon service kører ikke." -${LangFileString} UACERROR "Kunne ikke elevere rettigheder." -${LangFileString} WRITEERROR "Portabel Rainmeter skal installeres til en placering med fulde læse/skriverettigheder (som normal bruger).$\nHvis du ønsker at installere Rainmeter i '$0', gå tilbage og vælg 'Standard installation'.$\n$\nEller vælg en anden placering med fulde læse/skriverettigheder." -${LangFileString} VCINSTERROR "Visual C++ $instArc installation slog fejl med fejlkode $0.$\n$\nDu kan prøve at hente og installere Visual C++ $instArc gendistribueringspakken manuelt fra http://rainmeter.net/redist$\n$\nTryk OK for at afslutte." -${LangFileString} DOTNETINSTERROR ".NET $instArc installation slog fejl med fejlkode $0.$\n$\nDu kan prøve at hente og installere .NET $instArc gendistribueringspakken manuelt fra http://rainmeter.net/redist$\n$\nTryk OK for at afslutte." -${LangFileString} RAINMETERCLOSEERROR "Kunne ikke lukke Rainmeter.$\n$\nLuk venligst Rainmeter manuelt og prøv igen." -${LangFileString} SETTINGSFILEERROR "Indstillings-filen (Rainmeter.ini) ligger i installationsmappen. At have den der kan give problemer hvis programmet bruges af flere brugere eller af brugere med begrænsede brugerrettigheder.$\n$\nØnsker du at flytte filen til programdatamappen?" -${LangFileString} SETTINGSMOVEERROR "Kunne ikke flytte filen '$INSTDIR\Rainmeter.ini' til '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Vælg installationssprog." -${LangFileString} INSTALLOPTIONS "Installationsindstillinger" -${LangFileString} INSTALLOPTIONSDESC "Vælg yderligere installationsindstillinger" -${LangFileString} STANDARDINST "Standard installation (anbefales)" -${LangFileString} STANDARDINSTDESC "Installerer Rainmeter og henter manglende biblioteker." -${LangFileString} PORTABLEINST "Portabel installation" -${LangFileString} PORTABLEINSTDESC "Vælg ikke dette med mindre du ved hvad du laver. Der oprettes ingen genveje og .rmskin-filtypen vil ikke blive associeret. Visual C++ og .NET 2.0 bibliotekerne skal muligvis installeres manuelt." -${LangFileString} AUTOSTARTUP "Start Rainmeter ved opstart" -${LangFileString} ADDITIONALOPTIONS "Yderligere indstillinger" -${LangFileString} INSTALL64BIT "Installer 64-bit version" -${LangFileString} SENDINFORMATION "Send oplysninger om din computer" -${LangFileString} SENDINFORMATIONDESC "Din computers Windows-version, sprog og hardwarefaciliteter bliver sendt én gang under installationen for at forbedre Rainmeter. Ingen personlige oplysninger sendes." -${LangFileString} UNSTALLOPTIONS "Afinstallationsindstillinger" -${LangFileString} UNSTALLOPTIONSDESC "Vælg yderligere indstillinger" -${LangFileString} UNSTALLRAINMETER "Afinstaller Rainmeter" -${LangFileString} UNSTALLSETTINGS "Fjern fuldstændigt alle personlige indstillinger og filer" +${LangFileString} WIN2KERROR "Rainmeter ${VER} understøtter ikke Windows 2000. For at bruge Rainmeter på Windows 2000 skal du hente den ældre Rainmeter 2.0 version." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} kræver Windows XP SP2 eller nyere. Opdater venligst til den seneste service pack og prøv igen." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} kræver Windows 2003 SP1 eller senere. Opdater venligst til den seneste service pack og prøv igen." +${LangFileString} ADMINERROR "Adminstrative rettigheder påkrævet." +${LangFileString} LOGONERROR "Logon service kører ikke." +${LangFileString} UACERROR "Kunne ikke elevere rettigheder." +${LangFileString} WRITEERROR "Portabel Rainmeter skal installeres til en placering med fulde læse/skriverettigheder (som normal bruger).$\nHvis du ønsker at installere Rainmeter i '$0', gå tilbage og vælg 'Standard installation'.$\n$\nEller vælg en anden placering med fulde læse/skriverettigheder." +${LangFileString} VCINSTERROR "Visual C++ $instArc installation slog fejl med fejlkode $0.$\n$\nDu kan prøve at hente og installere Visual C++ $instArc gendistribueringspakken manuelt fra http://rainmeter.net/redist$\n$\nTryk OK for at afslutte." +${LangFileString} DOTNETINSTERROR ".NET $instArc installation slog fejl med fejlkode $0.$\n$\nDu kan prøve at hente og installere .NET $instArc gendistribueringspakken manuelt fra http://rainmeter.net/redist$\n$\nTryk OK for at afslutte." +${LangFileString} RAINMETERCLOSEERROR "Kunne ikke lukke Rainmeter.$\n$\nLuk venligst Rainmeter manuelt og prøv igen." +${LangFileString} SETTINGSFILEERROR "Indstillings-filen (Rainmeter.ini) ligger i installationsmappen. At have den der kan give problemer hvis programmet bruges af flere brugere eller af brugere med begrænsede brugerrettigheder.$\n$\nØnsker du at flytte filen til programdatamappen?" +${LangFileString} SETTINGSMOVEERROR "Kunne ikke flytte filen '$INSTDIR\Rainmeter.ini' til '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Vælg installationssprog." +${LangFileString} INSTALLOPTIONS "Installationsindstillinger" +${LangFileString} INSTALLOPTIONSDESC "Vælg yderligere installationsindstillinger" +${LangFileString} STANDARDINST "Standard installation (anbefales)" +${LangFileString} STANDARDINSTDESC "Installerer Rainmeter og henter manglende biblioteker." +${LangFileString} PORTABLEINST "Portabel installation" +${LangFileString} PORTABLEINSTDESC "Vælg ikke dette med mindre du ved hvad du laver. Der oprettes ingen genveje og .rmskin-filtypen vil ikke blive associeret. Visual C++ og .NET 2.0 bibliotekerne skal muligvis installeres manuelt." +${LangFileString} AUTOSTARTUP "Start Rainmeter ved opstart" +${LangFileString} ADDITIONALOPTIONS "Yderligere indstillinger" +${LangFileString} INSTALL64BIT "Installer 64-bit version" +${LangFileString} SENDINFORMATION "Send oplysninger om din computer" +${LangFileString} SENDINFORMATIONDESC "Din computers Windows-version, sprog og hardwarefaciliteter bliver sendt én gang under installationen for at forbedre Rainmeter. Ingen personlige oplysninger sendes." +${LangFileString} UNSTALLOPTIONS "Afinstallationsindstillinger" +${LangFileString} UNSTALLOPTIONSDESC "Vælg yderligere indstillinger" +${LangFileString} UNSTALLRAINMETER "Afinstaller Rainmeter" +${LangFileString} UNSTALLSETTINGS "Fjern fuldstændigt alle personlige indstillinger og filer" ${LangFileString} UNSTALLSETTINGSDESC "(inkluderer skind, temaer, tilføjelser, registreringsdatabase-indstillinger, og Start menu-elementer)" \ No newline at end of file diff --git a/Language/Dutch.nsh b/Language/Dutch.nsh index d936483f..04dc7f2d 100644 --- a/Language/Dutch.nsh +++ b/Language/Dutch.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} ondersteund Windows 2000 niet. Download de oudere Rainmeter 2.0 versie, om Rainmeter te gebruiken op Windows 2000." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} Vereist Windows XP SP2 of hoger. Upgrade naar de meest recente servicepack en probeer opnieuw." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} Vereist Windows 2003 SP1 of hoger. Upgrade naar de meest recente servicepack en probeer opnieuw." -${LangFileString} ADMINERROR "Beheerdersrechten vereist." -${LangFileString} LOGONERROR "Logon-service wordt niet uitgevoerd." -${LangFileString} UACERROR "Met benodigde bevoegdheden uitvoeren is niet mogelijk." -${LangFileString} WRITEERROR "Draagbare Rainmeter moet worden geïnstalleerd op een locatie met volledige lees- en schrijftoegang (als normale gebruiker).$\nAls u Rainmeter wilt installeren op '$0', ga terug en selecteer 'Standaardinstallatie'.$\n$\nOf blader naar een andere locatie met volledige lees- en schrijftoegang." -${LangFileString} VCINSTERROR "Visual C++ $instArc installatie mislukt met foutcode $0.$\n$\nU kunt proberen Visual C++ $instArc herdistribueerbaar pakket handmatig te downloaden van http://rainmeter.net/redist$\n$\nDruk op OK om te sluiten." -${LangFileString} DOTNETINSTERROR ".NET $instArc installatie mislukt met foutcode $0.$\n$\nU kunt proberen .NET $instArc herdistribueerbaar pakket handmatig te downloaden van http://rainmeter.net/redist$\n$\nDruk op OK om te sluiten." -${LangFileString} RAINMETERCLOSEERROR "Kan Rainmeter niet sluiten.$\n$\nSluit Rainmeter handmatig en probeer opnieuw." -${LangFileString} SETTINGSFILEERROR "Het instellingenbestand (Rainmeter.ini) is gevonden in de installatiemap. Het op die locatie houden, kan problemen veroorzaken indien de toepassing door meerdere gebruikers of door iemand met beperkte gebruikersprivileges wordt gebruikt.$\n$\nWilt u het bestand naar de toepassingsgegevensmap verplaatsen?" -${LangFileString} SETTINGSMOVEERROR "Kan het bestand '$INSTDIR\Rainmeter.ini' niet verplaatsen naar '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Selecteer alstublieft de installatie taal." -${LangFileString} INSTALLOPTIONS "Installatieopties" -${LangFileString} INSTALLOPTIONSDESC "Extra installatieopties selecteren" -${LangFileString} STANDARDINST "Standaardinstallatie (aanbevolen)" -${LangFileString} STANDARDINSTDESC "Installeert Rainmeter en downloadt vereiste bibliotheken." -${LangFileString} PORTABLEINST "Draagbare installatie" -${LangFileString} PORTABLEINSTDESC "Niet selecteren tenzij u weet wat u doet. Snelkoppelingen zullen niet worden gemaakt en de .rmskin extensie zal niet geregistreerd worden. Mogelijk moeten de Visual C++ en .NET 2.0 bibliotheken handmatig geïnstalleerd worden." -${LangFileString} AUTOSTARTUP "Start Rainmeter bij opstarten" -${LangFileString} ADDITIONALOPTIONS "Extra Opties" -${LangFileString} INSTALL64BIT "64-bit versie installeren" -${LangFileString} SENDINFORMATION "Verzend informatie over de computer" -${LangFileString} SENDINFORMATIONDESC "Uw computers window versie, taal en hardware capaciteiten worden eenmalig gerapporteerd tijdens de installatie om Rainmeter te verbeteren. Geen enkele persoonlijke informatie wordt verzonden." -${LangFileString} UNSTALLOPTIONS "Verwijder opties" -${LangFileString} UNSTALLOPTIONSDESC "Extra opties selecteren" -${LangFileString} UNSTALLRAINMETER "Rainmeter installatie ongedaan maken" -${LangFileString} UNSTALLSETTINGS "Alle persoonlijke instellingen en bestanden geheel verwijderen" +${LangFileString} WIN2KERROR "Rainmeter ${VER} ondersteund Windows 2000 niet. Download de oudere Rainmeter 2.0 versie, om Rainmeter te gebruiken op Windows 2000." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} Vereist Windows XP SP2 of hoger. Upgrade naar de meest recente servicepack en probeer opnieuw." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} Vereist Windows 2003 SP1 of hoger. Upgrade naar de meest recente servicepack en probeer opnieuw." +${LangFileString} ADMINERROR "Beheerdersrechten vereist." +${LangFileString} LOGONERROR "Logon-service wordt niet uitgevoerd." +${LangFileString} UACERROR "Met benodigde bevoegdheden uitvoeren is niet mogelijk." +${LangFileString} WRITEERROR "Draagbare Rainmeter moet worden geïnstalleerd op een locatie met volledige lees- en schrijftoegang (als normale gebruiker).$\nAls u Rainmeter wilt installeren op '$0', ga terug en selecteer 'Standaardinstallatie'.$\n$\nOf blader naar een andere locatie met volledige lees- en schrijftoegang." +${LangFileString} VCINSTERROR "Visual C++ $instArc installatie mislukt met foutcode $0.$\n$\nU kunt proberen Visual C++ $instArc herdistribueerbaar pakket handmatig te downloaden van http://rainmeter.net/redist$\n$\nDruk op OK om te sluiten." +${LangFileString} DOTNETINSTERROR ".NET $instArc installatie mislukt met foutcode $0.$\n$\nU kunt proberen .NET $instArc herdistribueerbaar pakket handmatig te downloaden van http://rainmeter.net/redist$\n$\nDruk op OK om te sluiten." +${LangFileString} RAINMETERCLOSEERROR "Kan Rainmeter niet sluiten.$\n$\nSluit Rainmeter handmatig en probeer opnieuw." +${LangFileString} SETTINGSFILEERROR "Het instellingenbestand (Rainmeter.ini) is gevonden in de installatiemap. Het op die locatie houden, kan problemen veroorzaken indien de toepassing door meerdere gebruikers of door iemand met beperkte gebruikersprivileges wordt gebruikt.$\n$\nWilt u het bestand naar de toepassingsgegevensmap verplaatsen?" +${LangFileString} SETTINGSMOVEERROR "Kan het bestand '$INSTDIR\Rainmeter.ini' niet verplaatsen naar '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Selecteer alstublieft de installatie taal." +${LangFileString} INSTALLOPTIONS "Installatieopties" +${LangFileString} INSTALLOPTIONSDESC "Extra installatieopties selecteren" +${LangFileString} STANDARDINST "Standaardinstallatie (aanbevolen)" +${LangFileString} STANDARDINSTDESC "Installeert Rainmeter en downloadt vereiste bibliotheken." +${LangFileString} PORTABLEINST "Draagbare installatie" +${LangFileString} PORTABLEINSTDESC "Niet selecteren tenzij u weet wat u doet. Snelkoppelingen zullen niet worden gemaakt en de .rmskin extensie zal niet geregistreerd worden. Mogelijk moeten de Visual C++ en .NET 2.0 bibliotheken handmatig geïnstalleerd worden." +${LangFileString} AUTOSTARTUP "Start Rainmeter bij opstarten" +${LangFileString} ADDITIONALOPTIONS "Extra Opties" +${LangFileString} INSTALL64BIT "64-bit versie installeren" +${LangFileString} SENDINFORMATION "Verzend informatie over de computer" +${LangFileString} SENDINFORMATIONDESC "Uw computers window versie, taal en hardware capaciteiten worden eenmalig gerapporteerd tijdens de installatie om Rainmeter te verbeteren. Geen enkele persoonlijke informatie wordt verzonden." +${LangFileString} UNSTALLOPTIONS "Verwijder opties" +${LangFileString} UNSTALLOPTIONSDESC "Extra opties selecteren" +${LangFileString} UNSTALLRAINMETER "Rainmeter installatie ongedaan maken" +${LangFileString} UNSTALLSETTINGS "Alle persoonlijke instellingen en bestanden geheel verwijderen" ${LangFileString} UNSTALLSETTINGSDESC "(inclusief weergaven, thema's, plug-ins, registerinstellingen en menu Start items)" \ No newline at end of file diff --git a/Language/English.nsh b/Language/English.nsh index ae56ca39..d60d2957 100644 --- a/Language/English.nsh +++ b/Language/English.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} does not support Windows 2000. To use Rainmeter on Windows 2000, download the older Rainmeter 2.0 version." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} requires Windows XP SP2 or higher. Please upgrade to the latest service pack and try again." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} requires Windows 2003 SP1 or higher. Please upgrade to the latest service pack and try again." -${LangFileString} ADMINERROR "Adminstrative rights required." -${LangFileString} LOGONERROR "Logon service not running." -${LangFileString} UACERROR "Unable to elevate." -${LangFileString} WRITEERROR "Portable Rainmeter must be installed into a location with full read and write access (as normal user).$\nIf you want to install Rainmeter into '$0', go back and select 'Standard installation'.$\n$\nOtherwise, browse for another location with full read and write access." -${LangFileString} VCINSTERROR "Visual C++ $instArc install failed with error code $0.$\n$\nYou might want to try downloading the Visual C++ $instArc redistributable package manually from http://rainmeter.net/redist$\n$\nPress OK to exit." -${LangFileString} DOTNETINSTERROR ".NET $instArc install failed with error code $0.$\n$\nYou might want to try downloading the .NET $instArc redistributable package manually from http://rainmeter.net/redist$\n$\nPress OK to exit." -${LangFileString} RAINMETERCLOSEERROR "Failed to close Rainmeter.$\n$\nPlease close Rainmeter manually and try again." -${LangFileString} SETTINGSFILEERROR "The settings file (Rainmeter.ini) is located in the installation folder. Keeping it there can cause problems if the application is used by multiple users or by anyone with restricted user privileges.$\n$\nDo you want to move the file to the application data folder?" -${LangFileString} SETTINGSMOVEERROR "Unable to move the file '$INSTDIR\Rainmeter.ini' to '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE " " -${LangFileString} INSTALLOPTIONS "Install Options" -${LangFileString} INSTALLOPTIONSDESC "Select additional install options" -${LangFileString} STANDARDINST "Standard installation (recommended)" -${LangFileString} STANDARDINSTDESC "Installs Rainmeter and downloads required libraries." -${LangFileString} PORTABLEINST "Portable installation" -${LangFileString} PORTABLEINSTDESC "Do not select this unless you know what you're doing. Shortcuts will not be created and the .rmskin extension will not be registered. The Visual C++ and .NET 2.0 libraries may need to be manually installed." -${LangFileString} AUTOSTARTUP "Launch Rainmeter on startup" -${LangFileString} ADDITIONALOPTIONS "Additional Options" -${LangFileString} INSTALL64BIT "Install 64-bit version" -${LangFileString} SENDINFORMATION "Send information about your computer" -${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." -${LangFileString} UNSTALLOPTIONS "Uninstall options" -${LangFileString} UNSTALLOPTIONSDESC "Select any additional options" -${LangFileString} UNSTALLRAINMETER "Uninstall Rainmeter" -${LangFileString} UNSTALLSETTINGS "Completely remove all personal settings and files" +${LangFileString} WIN2KERROR "Rainmeter ${VER} does not support Windows 2000. To use Rainmeter on Windows 2000, download the older Rainmeter 2.0 version." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} requires Windows XP SP2 or higher. Please upgrade to the latest service pack and try again." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} requires Windows 2003 SP1 or higher. Please upgrade to the latest service pack and try again." +${LangFileString} ADMINERROR "Adminstrative rights required." +${LangFileString} LOGONERROR "Logon service not running." +${LangFileString} UACERROR "Unable to elevate." +${LangFileString} WRITEERROR "Portable Rainmeter must be installed into a location with full read and write access (as normal user).$\nIf you want to install Rainmeter into '$0', go back and select 'Standard installation'.$\n$\nOtherwise, browse for another location with full read and write access." +${LangFileString} VCINSTERROR "Visual C++ $instArc install failed with error code $0.$\n$\nYou might want to try downloading the Visual C++ $instArc redistributable package manually from http://rainmeter.net/redist$\n$\nPress OK to exit." +${LangFileString} DOTNETINSTERROR ".NET $instArc install failed with error code $0.$\n$\nYou might want to try downloading the .NET $instArc redistributable package manually from http://rainmeter.net/redist$\n$\nPress OK to exit." +${LangFileString} RAINMETERCLOSEERROR "Failed to close Rainmeter.$\n$\nPlease close Rainmeter manually and try again." +${LangFileString} SETTINGSFILEERROR "The settings file (Rainmeter.ini) is located in the installation folder. Keeping it there can cause problems if the application is used by multiple users or by anyone with restricted user privileges.$\n$\nDo you want to move the file to the application data folder?" +${LangFileString} SETTINGSMOVEERROR "Unable to move the file '$INSTDIR\Rainmeter.ini' to '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE " " +${LangFileString} INSTALLOPTIONS "Install Options" +${LangFileString} INSTALLOPTIONSDESC "Select additional install options" +${LangFileString} STANDARDINST "Standard installation (recommended)" +${LangFileString} STANDARDINSTDESC "Installs Rainmeter and downloads required libraries." +${LangFileString} PORTABLEINST "Portable installation" +${LangFileString} PORTABLEINSTDESC "Do not select this unless you know what you're doing. Shortcuts will not be created and the .rmskin extension will not be registered. The Visual C++ and .NET 2.0 libraries may need to be manually installed." +${LangFileString} AUTOSTARTUP "Launch Rainmeter on startup" +${LangFileString} ADDITIONALOPTIONS "Additional Options" +${LangFileString} INSTALL64BIT "Install 64-bit version" +${LangFileString} SENDINFORMATION "Send information about your computer" +${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." +${LangFileString} UNSTALLOPTIONS "Uninstall options" +${LangFileString} UNSTALLOPTIONSDESC "Select any additional options" +${LangFileString} UNSTALLRAINMETER "Uninstall Rainmeter" +${LangFileString} UNSTALLSETTINGS "Completely remove all personal settings and files" ${LangFileString} UNSTALLSETTINGSDESC "(including skins, themes, addons, registry settings, and Start menu items)" \ No newline at end of file diff --git a/Language/Finnish.nsh b/Language/Finnish.nsh index 69474ca9..465d7171 100644 --- a/Language/Finnish.nsh +++ b/Language/Finnish.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} ei enää tue Windows 2000:tta. Ole hyvä ja lataa vanhempi Rainmeter 2.0 versio." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} tarvitsee Windows XP SP2:n tai uudemman. Ole hyvä ja päivitä Windows uusimpaan Service Pack -päivityspakettiin ja yritä sen jälkeen uudelleen." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} tarvitsee Windows 2003 SP1:n tai uudemman. Ole hyvä ja päivitä Windows uusimpaan Service Pack -päivityspakettiin ja yritä sen jälkeen uudelleen." -${LangFileString} ADMINERROR "Tarvitaan järjestelmänvalvojan oikeudet." -${LangFileString} LOGONERROR "Kirjautumispalvelu ei ole käynnissä." -${LangFileString} UACERROR "UAC korottaminen epäonnistui." -${LangFileString} WRITEERROR "Siirrettävä Rainmeter on asennettava sijaintiin johon on sekä kirjoitus- että lukuoikeudet (normaalikäyttäjänä).$\nJos haluat asentaa ohjelman Rainmeter kohteeseen '$0', palaa takaisin ja valitse 'Normaali asennus'.$\n$\nMuussa tapauksessa valitse sijainti johon on täydet luku- ja kirjoitusoikeudet." -${LangFileString} VCINSTERROR "Kirjaston Visual C++ $instArc asennus epäonnistui virhekoodilla $0.$\n$\nKoita ladata Visual C++ $instArc uudelleenjaeltava paketti käsin osoitteesta http://rainmeter.net/redist$\n$\nPaina OK poistuaksesi." -${LangFileString} DOTNETINSTERROR "Kirjaston .NET $instArc asennus epäonnistui virhekoodilla $0.$\n$\nKoita ladata .NET $instArc uudelleenjaeltava paketti käsin osoitteesta http://rainmeter.net/redist$\n$\nPaina OK poistuaksesi." -${LangFileString} RAINMETERCLOSEERROR "Rainmeter:n sulkeminen epäonnistui.$\n$\nSulje Rainmeter käsin ja yritä uudelleen." -${LangFileString} SETTINGSFILEERROR "Asetustiedosto (Rainmeter.ini) on havaittu sijaitsevan asennuskansiossa. Tämä saattaa tuottaa ongelmia mikäli ohjelmaa käyttävät useat käyttäjät tai sitä käytetään rajoitetuin oikeuksin.$\n$\nTahdotko siirtää tiedoston 'application data' kansioon?" -${LangFileString} SETTINGSMOVEERROR "Tiedostoa '$INSTDIR\Rainmeter.ini' ei voitu siirtää kohteeseen '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Valitse asennuskieli." -${LangFileString} INSTALLOPTIONS "Asennusvaihtoehdot" -${LangFileString} INSTALLOPTIONSDESC "Valitse asennuksen lisäasetukset" -${LangFileString} STANDARDINST "Oletusasennus (suositeltu)" -${LangFileString} STANDARDINSTDESC "Asentaa Rainmeter ohjelman ja lataa tarvittavat kirjastot." -${LangFileString} PORTABLEINST "Siirrettävä asennus" -${LangFileString} PORTABLEINSTDESC "Jätä tämä valitsematta ellet ole varma toimistasi. Pikakuvakkeita ei luoda eikä .rmskin tiedostopäätettä rekisteröidä. Saatat joutua asentamaan Visual C++ ja .NET 2.0 -kirjastot käsin." -${LangFileString} AUTOSTARTUP "Aloita Rainmeter käynnistyksessä" -${LangFileString} ADDITIONALOPTIONS "Lisäasetukset" -${LangFileString} INSTALL64BIT "Asenna 64-bittinen versio" -${LangFileString} SENDINFORMATION "Lähetä tietoja tietokoneestasi" -${LangFileString} SENDINFORMATIONDESC "Tietokoneesi Windows version ja kielen sekä laitteiston ominaisuudet raportoidaan kerran asennuksen aikana Rainmeterin parantamiseksi. Henkilökohtaisia tietoja ei lähetetä." -${LangFileString} UNSTALLOPTIONS "Poista asetukset" -${LangFileString} UNSTALLOPTIONSDESC "Valitse lisäasetukset" -${LangFileString} UNSTALLRAINMETER "Poista Rainmeter" -${LangFileString} UNSTALLSETTINGS "Poista kaikki tekemäsi asetukset ja tiedostot" -${LangFileString} UNSTALLSETTINGSDESC "(mukaanlukien olemukset, teemat, liitännäiset, rekisteriasetukset ja Käynnistä-valikon kohdat)" +${LangFileString} WIN2KERROR "Rainmeter ${VER} ei enää tue Windows 2000:tta. Ole hyvä ja lataa vanhempi Rainmeter 2.0 versio." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} tarvitsee Windows XP SP2:n tai uudemman. Ole hyvä ja päivitä Windows uusimpaan Service Pack -päivityspakettiin ja yritä sen jälkeen uudelleen." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} tarvitsee Windows 2003 SP1:n tai uudemman. Ole hyvä ja päivitä Windows uusimpaan Service Pack -päivityspakettiin ja yritä sen jälkeen uudelleen." +${LangFileString} ADMINERROR "Tarvitaan järjestelmänvalvojan oikeudet." +${LangFileString} LOGONERROR "Kirjautumispalvelu ei ole käynnissä." +${LangFileString} UACERROR "UAC korottaminen epäonnistui." +${LangFileString} WRITEERROR "Siirrettävä Rainmeter on asennettava sijaintiin johon on sekä kirjoitus- että lukuoikeudet (normaalikäyttäjänä).$\nJos haluat asentaa ohjelman Rainmeter kohteeseen '$0', palaa takaisin ja valitse 'Normaali asennus'.$\n$\nMuussa tapauksessa valitse sijainti johon on täydet luku- ja kirjoitusoikeudet." +${LangFileString} VCINSTERROR "Kirjaston Visual C++ $instArc asennus epäonnistui virhekoodilla $0.$\n$\nKoita ladata Visual C++ $instArc uudelleenjaeltava paketti käsin osoitteesta http://rainmeter.net/redist$\n$\nPaina OK poistuaksesi." +${LangFileString} DOTNETINSTERROR "Kirjaston .NET $instArc asennus epäonnistui virhekoodilla $0.$\n$\nKoita ladata .NET $instArc uudelleenjaeltava paketti käsin osoitteesta http://rainmeter.net/redist$\n$\nPaina OK poistuaksesi." +${LangFileString} RAINMETERCLOSEERROR "Rainmeter:n sulkeminen epäonnistui.$\n$\nSulje Rainmeter käsin ja yritä uudelleen." +${LangFileString} SETTINGSFILEERROR "Asetustiedosto (Rainmeter.ini) on havaittu sijaitsevan asennuskansiossa. Tämä saattaa tuottaa ongelmia mikäli ohjelmaa käyttävät useat käyttäjät tai sitä käytetään rajoitetuin oikeuksin.$\n$\nTahdotko siirtää tiedoston 'application data' kansioon?" +${LangFileString} SETTINGSMOVEERROR "Tiedostoa '$INSTDIR\Rainmeter.ini' ei voitu siirtää kohteeseen '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Valitse asennuskieli." +${LangFileString} INSTALLOPTIONS "Asennusvaihtoehdot" +${LangFileString} INSTALLOPTIONSDESC "Valitse asennuksen lisäasetukset" +${LangFileString} STANDARDINST "Oletusasennus (suositeltu)" +${LangFileString} STANDARDINSTDESC "Asentaa Rainmeter ohjelman ja lataa tarvittavat kirjastot." +${LangFileString} PORTABLEINST "Siirrettävä asennus" +${LangFileString} PORTABLEINSTDESC "Jätä tämä valitsematta ellet ole varma toimistasi. Pikakuvakkeita ei luoda eikä .rmskin tiedostopäätettä rekisteröidä. Saatat joutua asentamaan Visual C++ ja .NET 2.0 -kirjastot käsin." +${LangFileString} AUTOSTARTUP "Aloita Rainmeter käynnistyksessä" +${LangFileString} ADDITIONALOPTIONS "Lisäasetukset" +${LangFileString} INSTALL64BIT "Asenna 64-bittinen versio" +${LangFileString} SENDINFORMATION "Lähetä tietoja tietokoneestasi" +${LangFileString} SENDINFORMATIONDESC "Tietokoneesi Windows version ja kielen sekä laitteiston ominaisuudet raportoidaan kerran asennuksen aikana Rainmeterin parantamiseksi. Henkilökohtaisia tietoja ei lähetetä." +${LangFileString} UNSTALLOPTIONS "Poista asetukset" +${LangFileString} UNSTALLOPTIONSDESC "Valitse lisäasetukset" +${LangFileString} UNSTALLRAINMETER "Poista Rainmeter" +${LangFileString} UNSTALLSETTINGS "Poista kaikki tekemäsi asetukset ja tiedostot" +${LangFileString} UNSTALLSETTINGSDESC "(mukaanlukien olemukset, teemat, liitännäiset, rekisteriasetukset ja Käynnistä-valikon kohdat)" diff --git a/Language/French.nsh b/Language/French.nsh index a84dcc77..6c3c13f9 100644 --- a/Language/French.nsh +++ b/Language/French.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} ne supporte pas Windows 2000. Veuillez télécharger une version antérieure à Rainmeter 2.0." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} requiert Windows XP SP2 ou ultérieur. Veuillez installer le dernier service pack et réessayer." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} requiert Windows 2003 SP1 ou ultérieur. Veuillez installer le dernier service pack et réessayer." -${LangFileString} ADMINERROR "Droits administratifs requis." -${LangFileString} LOGONERROR "Le service Logon n'est pas démarré." -${LangFileString} UACERROR "Impossible d'élever les privilèges." -${LangFileString} WRITEERROR "Rainmeter version portable doit être installé dans un dossier à accès total(en tant qu'utilisateur normal).$\nSi vous voulez installer Rainmeter dans le dossier '$0', faites Précédent et sélectionnez 'Installation normale'.$\n$\nSinon, parcourez un autre emplacement avec un accès total." -${LangFileString} VCINSTERROR "Visual C++ $instArc l'installation a échoué avec le code d'erreur $0.$\n$\nVous pourriez essayer de télécharger le progiciel redistribuable Visual C++ $instArc manuellement à http://rainmeter.net/redist$\n$\nOK pour quitter." -${LangFileString} DOTNETINSTERROR ".NET $instArc l'installation a échoué avec le code d'erreur $0.$\n$\nVous pourriez essayer de télécharger le progiciel redistribuable .NET $instArc manuellement à http://rainmeter.net/redist$\n$\nOK pour quitter." -${LangFileString} RAINMETERCLOSEERROR "La fermeture de Rainmeter a échoué.$\n$\nVeuillez fermer Rainmeter manuellement et réessayer." -${LangFileString} SETTINGSFILEERROR "Le fichier de configuration (Rainmeter.ini) est localisé dans le dossier d'installation. Le conserver ici peut causer des problèmes si l'application est utilisée par plusieurs utilisateurs ou par quelqu'un ayant des privilèges d'utilisateur restreint.$\n$\nVoulez-vous déplacer le fichier dans le dossier application data ?" -${LangFileString} SETTINGSMOVEERROR "Impossible de déplacer le fichier '$INSTDIR\Rainmeter.ini' dans '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "S'il vous plait, sélectionnez la langue d'installation." -${LangFileString} INSTALLOPTIONS "Options d'installation" -${LangFileString} INSTALLOPTIONSDESC "Sélectionner des options d'installation additionnelles" -${LangFileString} STANDARDINST "Installation normale (recommandé)" -${LangFileString} STANDARDINSTDESC "Installer Rainmeter et télécharger les librairies requises." -${LangFileString} PORTABLEINST "Installation portable" -${LangFileString} PORTABLEINSTDESC "Ne sélectionnez pas ceci à moins que vous sachiez ce que vous faites. Le raccourci ne sera pas créé et les fichiers .rmskin ne seront pas enregistrés . Visual C++ et .NET 2.0 devront être installés manuellement." -${LangFileString} AUTOSTARTUP "Démarrer automatiquement avec Windows" -${LangFileString} ADDITIONALOPTIONS "Options additionnelles" -${LangFileString} INSTALL64BIT "Installer la version 64-bits" -${LangFileString} SENDINFORMATION "Envoyer des informations à propos de l'ordinateur" -${LangFileString} SENDINFORMATIONDESC "La version de Windows, le langage, ainsi que les informations sur le matériel de votre ordinateur seront envoyées durant l'installation pour améliorer Rainmeter. Aucune information personnelle ne sera envoyée." -${LangFileString} UNSTALLOPTIONS "Options de désinstallation" -${LangFileString} UNSTALLOPTIONSDESC "Sélectionner une option additionnelle" -${LangFileString} UNSTALLRAINMETER "Désinstaller Rainmeter" -${LangFileString} UNSTALLSETTINGS "Supprimer tous les paramètres personnels et les fichiers" +${LangFileString} WIN2KERROR "Rainmeter ${VER} ne supporte pas Windows 2000. Veuillez télécharger une version antérieure à Rainmeter 2.0." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} requiert Windows XP SP2 ou ultérieur. Veuillez installer le dernier service pack et réessayer." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} requiert Windows 2003 SP1 ou ultérieur. Veuillez installer le dernier service pack et réessayer." +${LangFileString} ADMINERROR "Droits administratifs requis." +${LangFileString} LOGONERROR "Le service Logon n'est pas démarré." +${LangFileString} UACERROR "Impossible d'élever les privilèges." +${LangFileString} WRITEERROR "Rainmeter version portable doit être installé dans un dossier à accès total(en tant qu'utilisateur normal).$\nSi vous voulez installer Rainmeter dans le dossier '$0', faites Précédent et sélectionnez 'Installation normale'.$\n$\nSinon, parcourez un autre emplacement avec un accès total." +${LangFileString} VCINSTERROR "Visual C++ $instArc l'installation a échoué avec le code d'erreur $0.$\n$\nVous pourriez essayer de télécharger le progiciel redistribuable Visual C++ $instArc manuellement à http://rainmeter.net/redist$\n$\nOK pour quitter." +${LangFileString} DOTNETINSTERROR ".NET $instArc l'installation a échoué avec le code d'erreur $0.$\n$\nVous pourriez essayer de télécharger le progiciel redistribuable .NET $instArc manuellement à http://rainmeter.net/redist$\n$\nOK pour quitter." +${LangFileString} RAINMETERCLOSEERROR "La fermeture de Rainmeter a échoué.$\n$\nVeuillez fermer Rainmeter manuellement et réessayer." +${LangFileString} SETTINGSFILEERROR "Le fichier de configuration (Rainmeter.ini) est localisé dans le dossier d'installation. Le conserver ici peut causer des problèmes si l'application est utilisée par plusieurs utilisateurs ou par quelqu'un ayant des privilèges d'utilisateur restreint.$\n$\nVoulez-vous déplacer le fichier dans le dossier application data ?" +${LangFileString} SETTINGSMOVEERROR "Impossible de déplacer le fichier '$INSTDIR\Rainmeter.ini' dans '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "S'il vous plait, sélectionnez la langue d'installation." +${LangFileString} INSTALLOPTIONS "Options d'installation" +${LangFileString} INSTALLOPTIONSDESC "Sélectionner des options d'installation additionnelles" +${LangFileString} STANDARDINST "Installation normale (recommandé)" +${LangFileString} STANDARDINSTDESC "Installer Rainmeter et télécharger les librairies requises." +${LangFileString} PORTABLEINST "Installation portable" +${LangFileString} PORTABLEINSTDESC "Ne sélectionnez pas ceci à moins que vous sachiez ce que vous faites. Le raccourci ne sera pas créé et les fichiers .rmskin ne seront pas enregistrés . Visual C++ et .NET 2.0 devront être installés manuellement." +${LangFileString} AUTOSTARTUP "Démarrer automatiquement avec Windows" +${LangFileString} ADDITIONALOPTIONS "Options additionnelles" +${LangFileString} INSTALL64BIT "Installer la version 64-bits" +${LangFileString} SENDINFORMATION "Envoyer des informations à propos de l'ordinateur" +${LangFileString} SENDINFORMATIONDESC "La version de Windows, le langage, ainsi que les informations sur le matériel de votre ordinateur seront envoyées durant l'installation pour améliorer Rainmeter. Aucune information personnelle ne sera envoyée." +${LangFileString} UNSTALLOPTIONS "Options de désinstallation" +${LangFileString} UNSTALLOPTIONSDESC "Sélectionner une option additionnelle" +${LangFileString} UNSTALLRAINMETER "Désinstaller Rainmeter" +${LangFileString} UNSTALLSETTINGS "Supprimer tous les paramètres personnels et les fichiers" ${LangFileString} UNSTALLSETTINGSDESC "(y compris les skins, les thèmes, les addons, les paramètres de registre et les éléments du menu Démarrer)" \ No newline at end of file diff --git a/Language/German.nsh b/Language/German.nsh index eb0b767f..ca37b080 100644 --- a/Language/German.nsh +++ b/Language/German.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} unterstützt nicht Windows 2000. Um Rainmeter unter Windows 2000 zu verwenden, laden Sie die ältere Rainmeter Version 2.0 herunter." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} benötigt Windows XP SP2 oder höher. Bitte das letzte Servicepack einspielen und neu versuchen." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} benötigt Windows 2003 SP1 oder höher. Bitte das letzte Servicepack einspielen und neu versuchen." -${LangFileString} ADMINERROR "Benötigt Adminstratorrechte." -${LangFileString} LOGONERROR "Logon Service läuft nicht." -${LangFileString} UACERROR "Ausführen mit erweiterten Rechten fehlgeschlagen." -${LangFileString} WRITEERROR "Die portable Rainmeter-Version muss in einen Ordner mit vollem Lese- und Schreibzugriff intalliert werden (als normaler Benutzer).$\nFalls Sie Rainmeter in '$0' installieren wollen, gehen Sie zurück und wählen 'Standardinstallation'.$\n$\nAndernfalls, suchen Sie einen anderen Ordner auf den Sie vollen Lese- und Schreibzugriff haben." -${LangFileString} VCINSTERROR "Visual C++ $instArc Installation fehlgeschlagen mit Fehlercode $0.$\n$\nSie können versuchen das Visual C++ $instArc redistributable Paket manuell von http://rainmeter.net/redist zu laden$\n$\nZum Schließen drücken Sie OK." -${LangFileString} DOTNETINSTERROR ".NET $instArc Installation fehlgeschlagen mit Fehlercode $0.$\n$\nSie können versuchen das .NET $instArc redistributable Paket manuell von http://rainmeter.net/redist zu laden$\n$\nZum Schließen drücken Sie OK." -${LangFileString} RAINMETERCLOSEERROR "Schließen von Rainmeter fehlgeschlagen.$\n$\nBitte Rainmeter manuell schließen und neu versuchen." -${LangFileString} SETTINGSFILEERROR "Die Einstellungsdatei (Rainmeter.ini) befindet sich im Installationsordner. Verbleib in diesem Ordner führt zu Problemen, falls die Anwendung von mehreren Benutzern oder von einem Benutzer mit eingeschränkten Rechten verwendet wird.$\n$\nWollen Sie die Datei in den Anwendungsdatenordner verschieben?" -${LangFileString} SETTINGSMOVEERROR "Datei '$INSTDIR\Rainmeter.ini' kann nicht nach '$APPDATA\Rainmeter\Rainmeter.ini' verschoben werden." -${LangFileString} SELECTLANGUAGE "Bitte wählen Sie eine Sprache aus." -${LangFileString} INSTALLOPTIONS "Installationsoptionen" -${LangFileString} INSTALLOPTIONSDESC "Zusätzliche Installationsoptionen auswählen" -${LangFileString} STANDARDINST "Standardinstallation (empfohlen)" -${LangFileString} STANDARDINSTDESC "Installiert Rainmeter und lädt benötigte Bibliotheken nach." -${LangFileString} PORTABLEINST "Portable Installation" -${LangFileString} PORTABLEINSTDESC "Nicht auswählen, es sei denn, Sie wissen was Sie tun. Verknüpfungen werden nicht angelegt und die .rmskin Erweiterung wird nicht registriert. Die Visual C++ und .NET 2.0 Bibliotheken müssen ggf. manuell installiert werden." -${LangFileString} AUTOSTARTUP "Rainmeter mit Windows starten" -${LangFileString} ADDITIONALOPTIONS "Zusätzliche Optionen" -${LangFileString} INSTALL64BIT "64-Bit-Version installieren" -${LangFileString} SENDINFORMATION "Send information about your computer" -${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." -${LangFileString} UNSTALLOPTIONS "Deinstallationsoptionen" -${LangFileString} UNSTALLOPTIONSDESC "Zusätzliche Optionen auswählen" -${LangFileString} UNSTALLRAINMETER "Rainmeter deinstallieren" -${LangFileString} UNSTALLSETTINGS "Alle persönlichen Einstellungen und Dateien löschen" +${LangFileString} WIN2KERROR "Rainmeter ${VER} unterstützt nicht Windows 2000. Um Rainmeter unter Windows 2000 zu verwenden, laden Sie die ältere Rainmeter Version 2.0 herunter." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} benötigt Windows XP SP2 oder höher. Bitte das letzte Servicepack einspielen und neu versuchen." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} benötigt Windows 2003 SP1 oder höher. Bitte das letzte Servicepack einspielen und neu versuchen." +${LangFileString} ADMINERROR "Benötigt Adminstratorrechte." +${LangFileString} LOGONERROR "Logon Service läuft nicht." +${LangFileString} UACERROR "Ausführen mit erweiterten Rechten fehlgeschlagen." +${LangFileString} WRITEERROR "Die portable Rainmeter-Version muss in einen Ordner mit vollem Lese- und Schreibzugriff intalliert werden (als normaler Benutzer).$\nFalls Sie Rainmeter in '$0' installieren wollen, gehen Sie zurück und wählen 'Standardinstallation'.$\n$\nAndernfalls, suchen Sie einen anderen Ordner auf den Sie vollen Lese- und Schreibzugriff haben." +${LangFileString} VCINSTERROR "Visual C++ $instArc Installation fehlgeschlagen mit Fehlercode $0.$\n$\nSie können versuchen das Visual C++ $instArc redistributable Paket manuell von http://rainmeter.net/redist zu laden$\n$\nZum Schließen drücken Sie OK." +${LangFileString} DOTNETINSTERROR ".NET $instArc Installation fehlgeschlagen mit Fehlercode $0.$\n$\nSie können versuchen das .NET $instArc redistributable Paket manuell von http://rainmeter.net/redist zu laden$\n$\nZum Schließen drücken Sie OK." +${LangFileString} RAINMETERCLOSEERROR "Schließen von Rainmeter fehlgeschlagen.$\n$\nBitte Rainmeter manuell schließen und neu versuchen." +${LangFileString} SETTINGSFILEERROR "Die Einstellungsdatei (Rainmeter.ini) befindet sich im Installationsordner. Verbleib in diesem Ordner führt zu Problemen, falls die Anwendung von mehreren Benutzern oder von einem Benutzer mit eingeschränkten Rechten verwendet wird.$\n$\nWollen Sie die Datei in den Anwendungsdatenordner verschieben?" +${LangFileString} SETTINGSMOVEERROR "Datei '$INSTDIR\Rainmeter.ini' kann nicht nach '$APPDATA\Rainmeter\Rainmeter.ini' verschoben werden." +${LangFileString} SELECTLANGUAGE "Bitte wählen Sie eine Sprache aus." +${LangFileString} INSTALLOPTIONS "Installationsoptionen" +${LangFileString} INSTALLOPTIONSDESC "Zusätzliche Installationsoptionen auswählen" +${LangFileString} STANDARDINST "Standardinstallation (empfohlen)" +${LangFileString} STANDARDINSTDESC "Installiert Rainmeter und lädt benötigte Bibliotheken nach." +${LangFileString} PORTABLEINST "Portable Installation" +${LangFileString} PORTABLEINSTDESC "Nicht auswählen, es sei denn, Sie wissen was Sie tun. Verknüpfungen werden nicht angelegt und die .rmskin Erweiterung wird nicht registriert. Die Visual C++ und .NET 2.0 Bibliotheken müssen ggf. manuell installiert werden." +${LangFileString} AUTOSTARTUP "Rainmeter mit Windows starten" +${LangFileString} ADDITIONALOPTIONS "Zusätzliche Optionen" +${LangFileString} INSTALL64BIT "64-Bit-Version installieren" +${LangFileString} SENDINFORMATION "Send information about your computer" +${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." +${LangFileString} UNSTALLOPTIONS "Deinstallationsoptionen" +${LangFileString} UNSTALLOPTIONSDESC "Zusätzliche Optionen auswählen" +${LangFileString} UNSTALLRAINMETER "Rainmeter deinstallieren" +${LangFileString} UNSTALLSETTINGS "Alle persönlichen Einstellungen und Dateien löschen" ${LangFileString} UNSTALLSETTINGSDESC "(einschließlich Skins, Themes, Addons, Einträge in der Registry und Einträge im Startmenü)" \ No newline at end of file diff --git a/Language/Greek.nsh b/Language/Greek.nsh index 5bb3ac74..a1f8a23e 100644 --- a/Language/Greek.nsh +++ b/Language/Greek.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Το Rainmeter ${VER} δεν υποστηρίζει Windows 2000. Για να χρησιμοποιήσετε το Rainmeter στα Windows 2000, κατεβάστε την έκδοση 2.0 του Rainmeter." -${LangFileString} WINXPS2ERROR "Το Rainmeter ${VER} απαιτεί Windows XP SP2 ή υψηλότερο. Παρακαλώ αναβαθμίστε στην τελευταία έκδοση του service pack των Windows και δοκιμάστε ξανά." -${LangFileString} WIN2003SP1ERROR "Το Rainmeter ${VER} απαιτεί Windows 2003 SP1 ή υψηλότερο. Παρακαλώ αναβαθμίστε στην τελευταία έκδοση του service pack των Windows και δοκιμάστε ξανά." -${LangFileString} ADMINERROR "Χρειάζονται δικαιώματα διαχειριστή." -${LangFileString} LOGONERROR "Η υπηρεσία Logon δεν λειτουργεί." -${LangFileString} UACERROR "Λάθος UAC. Αδύνατον να συνεχίσει." -${LangFileString} WRITEERROR "Η έκδοση Portable Rainmeter πρέπει να εγκατασταθεί σε μέσο με πλήρη δικαιώματα read/write (σαν απλός χρήστης).$\nΑν θέλετε να εγκαταστήσετε το Rainmeter στο '$0', πηγαίνετε πίσω και διαλέξτε 'Standard installation'.$\n$\nή, διαλέξτε άλλο μέσο με πλήρη δικαιώματα read/write." -${LangFileString} VCINSTERROR "Visual C++ $instArc η εγκατάσταση απέτυχε με κωδικό λάθους $0.$\n$\nΊσως να πρέπει να κατεβάσετε τη Visual C++ $instArc redistributable package χειροκίνητα από τη διεύθυνση http://rainmeter.net/redist$\n$\nΠατήστε OK για έξοδο." -${LangFileString} DOTNETINSTERROR ".NET $instArc η εγκατάσταση απέτυχε με κωδικό λάθους $0.$\n$\nΊσως να πρέπει να κατεβάσετε τη .NET $instArc redistributable package χειροκίνητα από τη διεύθυνση http://rainmeter.net/redist$\n$\nΠατήστε OK για έξοδο." -${LangFileString} RAINMETERCLOSEERROR "Απέτυχε το κλείσιμο του Rainmeter.$\n$\nΠαρακαλώ κλείστε το Rainmeter χειροκίνητα και δοκιμάστε ξανά." -${LangFileString} SETTINGSFILEERROR "Το αρχείο ρυθμίσεων (Rainmeter.ini) βρίσκεται στο φάκελο εγκατάστασης. Κρατώντας το εκεί μπορεί να δημιουργήσει προβλήματα αν η εφαρμογή χρησιμοποιείται από πολλούς χρήστες ή οποιονδήποτε με περιορισμένα προνόμια.$\n$\nΘέλετε να μετακινήσετε το αρχείο στο φάκελο δεδομένων της εφαρμογής;" -${LangFileString} SETTINGSMOVEERROR "Αδύνατον να μετακινηθεί το αρχείο '$INSTDIR\Rainmeter.ini' στο '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Επιλέξτε τη γλώσσα εγκατάστασης." -${LangFileString} INSTALLOPTIONS "Επιλογές εγκτάστασης." -${LangFileString} INSTALLOPTIONSDESC "Επιλέξτε επιπλέον επιλογές εγκατάστασης." -${LangFileString} STANDARDINST "Κανονική εγκατάσταση (συνιστάται)" -${LangFileString} STANDARDINSTDESC "Εγκατάσταση του Rainmeter και αυτόματο κατέβασμα των απαιτούμενων βιβλιοθηκών." -${LangFileString} PORTABLEINST "Εγκατάσταση Portable έκδοσης." -${LangFileString} PORTABLEINSTDESC "Μην το επιλέγετε αν δεν ξέρετε τί κάνει. Δεν θα δημιουργηθούν συντομεύσεις και η προέκταση .rmskin δεν θα εγγραφεί στο μητρώο. Οι βιβλιοθήκες Visual C++ και .NET 2.0 ίσως να χρειαστεί να εγκατασταθούν χειροκίνητα." -${LangFileString} AUTOSTARTUP "Εκκίνηση του Rainmeter κατά την εκκίνηση του υπολογιστή." -${LangFileString} ADDITIONALOPTIONS "Επιπλέον επιλογές." -${LangFileString} INSTALL64BIT "Εγκαταστήστε την 64-bit έκδοση" -${LangFileString} SENDINFORMATION "Αποστείλετε πληροφορίες σχετικά με τον υπολογιστή" -${LangFileString} SENDINFORMATIONDESC "Η έκδοση Windows του υπολογιστή σας, η γλώσσα και οι δυνατότητες του hardware θα γνωστοποιηθούν στο Rainmeter μία μόνο φορά κατά την εγκατάσταση του, για την βελτίωση της ανάπτυξης του. Καμία προσωπική πληροφορία δεν θα αποσταλεί." -${LangFileString} UNSTALLOPTIONS "Επιλογές απεγκατάστασης." -${LangFileString} UNSTALLOPTIONSDESC "Επιλέξτε επιπλέον επιλογές." -${LangFileString} UNSTALLRAINMETER "Απεγκατάσταση του Rainmeter" -${LangFileString} UNSTALLSETTINGS "Διαγραφή όλων των προσωπικών ρυθμίσεων και αρχείων." +${LangFileString} WIN2KERROR "Το Rainmeter ${VER} δεν υποστηρίζει Windows 2000. Για να χρησιμοποιήσετε το Rainmeter στα Windows 2000, κατεβάστε την έκδοση 2.0 του Rainmeter." +${LangFileString} WINXPS2ERROR "Το Rainmeter ${VER} απαιτεί Windows XP SP2 ή υψηλότερο. Παρακαλώ αναβαθμίστε στην τελευταία έκδοση του service pack των Windows και δοκιμάστε ξανά." +${LangFileString} WIN2003SP1ERROR "Το Rainmeter ${VER} απαιτεί Windows 2003 SP1 ή υψηλότερο. Παρακαλώ αναβαθμίστε στην τελευταία έκδοση του service pack των Windows και δοκιμάστε ξανά." +${LangFileString} ADMINERROR "Χρειάζονται δικαιώματα διαχειριστή." +${LangFileString} LOGONERROR "Η υπηρεσία Logon δεν λειτουργεί." +${LangFileString} UACERROR "Λάθος UAC. Αδύνατον να συνεχίσει." +${LangFileString} WRITEERROR "Η έκδοση Portable Rainmeter πρέπει να εγκατασταθεί σε μέσο με πλήρη δικαιώματα read/write (σαν απλός χρήστης).$\nΑν θέλετε να εγκαταστήσετε το Rainmeter στο '$0', πηγαίνετε πίσω και διαλέξτε 'Standard installation'.$\n$\nή, διαλέξτε άλλο μέσο με πλήρη δικαιώματα read/write." +${LangFileString} VCINSTERROR "Visual C++ $instArc η εγκατάσταση απέτυχε με κωδικό λάθους $0.$\n$\nΊσως να πρέπει να κατεβάσετε τη Visual C++ $instArc redistributable package χειροκίνητα από τη διεύθυνση http://rainmeter.net/redist$\n$\nΠατήστε OK για έξοδο." +${LangFileString} DOTNETINSTERROR ".NET $instArc η εγκατάσταση απέτυχε με κωδικό λάθους $0.$\n$\nΊσως να πρέπει να κατεβάσετε τη .NET $instArc redistributable package χειροκίνητα από τη διεύθυνση http://rainmeter.net/redist$\n$\nΠατήστε OK για έξοδο." +${LangFileString} RAINMETERCLOSEERROR "Απέτυχε το κλείσιμο του Rainmeter.$\n$\nΠαρακαλώ κλείστε το Rainmeter χειροκίνητα και δοκιμάστε ξανά." +${LangFileString} SETTINGSFILEERROR "Το αρχείο ρυθμίσεων (Rainmeter.ini) βρίσκεται στο φάκελο εγκατάστασης. Κρατώντας το εκεί μπορεί να δημιουργήσει προβλήματα αν η εφαρμογή χρησιμοποιείται από πολλούς χρήστες ή οποιονδήποτε με περιορισμένα προνόμια.$\n$\nΘέλετε να μετακινήσετε το αρχείο στο φάκελο δεδομένων της εφαρμογής;" +${LangFileString} SETTINGSMOVEERROR "Αδύνατον να μετακινηθεί το αρχείο '$INSTDIR\Rainmeter.ini' στο '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Επιλέξτε τη γλώσσα εγκατάστασης." +${LangFileString} INSTALLOPTIONS "Επιλογές εγκτάστασης." +${LangFileString} INSTALLOPTIONSDESC "Επιλέξτε επιπλέον επιλογές εγκατάστασης." +${LangFileString} STANDARDINST "Κανονική εγκατάσταση (συνιστάται)" +${LangFileString} STANDARDINSTDESC "Εγκατάσταση του Rainmeter και αυτόματο κατέβασμα των απαιτούμενων βιβλιοθηκών." +${LangFileString} PORTABLEINST "Εγκατάσταση Portable έκδοσης." +${LangFileString} PORTABLEINSTDESC "Μην το επιλέγετε αν δεν ξέρετε τί κάνει. Δεν θα δημιουργηθούν συντομεύσεις και η προέκταση .rmskin δεν θα εγγραφεί στο μητρώο. Οι βιβλιοθήκες Visual C++ και .NET 2.0 ίσως να χρειαστεί να εγκατασταθούν χειροκίνητα." +${LangFileString} AUTOSTARTUP "Εκκίνηση του Rainmeter κατά την εκκίνηση του υπολογιστή." +${LangFileString} ADDITIONALOPTIONS "Επιπλέον επιλογές." +${LangFileString} INSTALL64BIT "Εγκαταστήστε την 64-bit έκδοση" +${LangFileString} SENDINFORMATION "Αποστείλετε πληροφορίες σχετικά με τον υπολογιστή" +${LangFileString} SENDINFORMATIONDESC "Η έκδοση Windows του υπολογιστή σας, η γλώσσα και οι δυνατότητες του hardware θα γνωστοποιηθούν στο Rainmeter μία μόνο φορά κατά την εγκατάσταση του, για την βελτίωση της ανάπτυξης του. Καμία προσωπική πληροφορία δεν θα αποσταλεί." +${LangFileString} UNSTALLOPTIONS "Επιλογές απεγκατάστασης." +${LangFileString} UNSTALLOPTIONSDESC "Επιλέξτε επιπλέον επιλογές." +${LangFileString} UNSTALLRAINMETER "Απεγκατάσταση του Rainmeter" +${LangFileString} UNSTALLSETTINGS "Διαγραφή όλων των προσωπικών ρυθμίσεων και αρχείων." ${LangFileString} UNSTALLSETTINGSDESC "(συμπεριλαμβανομένων skins, themes, addons, ρυθμίσεων registry, και στοιχεία του μενού Έναρξη.)" \ No newline at end of file diff --git a/Language/Hebrew.nsh b/Language/Hebrew.nsh index d455f454..fcee27f0 100644 --- a/Language/Hebrew.nsh +++ b/Language/Hebrew.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "ריינמטר ${VER} אינו תומך בחלונות 2000. כדי להשתמש בריינמטר בחלונות 2000, הורד את הגירסא הישנה ריינמטר 2.0." -${LangFileString} WINXPS2ERROR "לריינמטר ${VER} נדרשת גירסאת חלונות XP SP2 או גירסא חדשה יותר. אנא שדרג לגירסאת חבילת השירות החדשה ביותר ונסה שוב." -${LangFileString} WIN2003SP1ERROR "לריינמטר ${VER} נדרשת גירסאת חלונות 2003 SP1 או גירסא חדשה יותר. אנא שדרג לגירסאת חבילת השירות החדשה ביותר ונסה שוב." -${LangFileString} ADMINERROR "נדרשות הרשאות ניהוליות." -${LangFileString} LOGONERROR "שירות החיבור אינו מופעל." -${LangFileString} UACERROR "אינו מצליח לעלות." -${LangFileString} WRITEERROR "הגירסא הניידת של ריינמטר חייבת להיות מותקנת במיקום עם הרשאות קריאה וכתיבה (כמשתמש רגיל).$\nIf אם תרצה להתקין את ריינמטר ב- '$0', חזור אחורה ובחר 'התקנה רגילה'.$\n$\nאחרת, בחר מיקום אחר בעת הרשאות קריאה וכתיבה מלאות." -${LangFileString} VCINSTERROR "Visual C++ $instArc נכשל בהתקנה עם קוד שגיאה $0.$\n$\n תצטרך להוריד את חבילת Visual C++ $instArc redistributable ידנית מ- http://rainmeter.net/redist$\n$\n לחץ OK כדי לצאת." -${LangFileString} DOTNETINSTERROR ".NET $instArc נכשל בהתקנה עם קוד שגיאה $0.$\n$\nתצטרך להוריד את חבילת .NET $instArc ידנית מ- from http://rainmeter.net/redist$\n$\nלחץ OK כדי לצאת." -${LangFileString} RAINMETERCLOSEERROR "נכשל בסגירת ריינמטר.$\n$\nאנא סגור את ריינמטר ידנית ונסה שוב." -${LangFileString} SETTINGSFILEERROR "קובץ ההגדרות (Rainmeter.ini) ממוקם בתקיית ההתקנה. השארתו שם עלולה לגרום בעיות במידה ומשתמש אחד או יותר בעלי הרשאות מוגבלות.$\n$\n האם תרצה להזיז את הקובץ לתקיית מידע היישום?" -${LangFileString} SETTINGSMOVEERROR "לא ניתן להזיז את הקובץ '$INSTDIR\Rainmeter.ini' ל- '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "אנא בחר את שפת ההתקנה." -${LangFileString} INSTALLOPTIONS "אפשרויות התקנה" -${LangFileString} INSTALLOPTIONSDESC "בחר באפשרויות התקנה נוספות" -${LangFileString} STANDARDINST "התקנה רגילה (מומלץ)" -${LangFileString} STANDARDINSTDESC "התקן את ריינמטר למחשבך והורד את הסיפריות הדרושות אוטומטית." -${LangFileString} PORTABLEINST "התקנה ניידת" -${LangFileString} PORTABLEINSTDESC "אין לבחור באפשרות זו אלא אם הינך יודע מה אתה עושה. לא יווצרו קיצורי דרך ושיוך קובץ .rmskin לא יתבצע. תצטרך להתקין ידנית את סיפריות Visual C++ ו .NET 2.0." -${LangFileString} AUTOSTARTUP "הפעל את ריינמטר אוטומטית עם עליית חלונות" -${LangFileString} ADDITIONALOPTIONS "אפשרויות נוספות" -${LangFileString} INSTALL64BIT "התקן גירסאת 64 סיביות" -${LangFileString} SENDINFORMATION "שלח מידע אודות המחשב" -${LangFileString} SENDINFORMATIONDESC "גירסאת חלונות, השפה ויכולות החומרה ידווחו פעם אחת בזמן ההתקנה כדי לאפשר שיפור של ריינמטר. לא ישלח מידע אישי." -${LangFileString} UNSTALLOPTIONS "אפשרויות הסרה" -${LangFileString} UNSTALLOPTIONSDESC "בחר אפשרויות נוספות" -${LangFileString} UNSTALLRAINMETER "הסר את ריינמטר" -${LangFileString} UNSTALLSETTINGS "הסר לחלוטין את כל ההגדרות והקבצים האישיים" +${LangFileString} WIN2KERROR "ריינמטר ${VER} אינו תומך בחלונות 2000. כדי להשתמש בריינמטר בחלונות 2000, הורד את הגירסא הישנה ריינמטר 2.0." +${LangFileString} WINXPS2ERROR "לריינמטר ${VER} נדרשת גירסאת חלונות XP SP2 או גירסא חדשה יותר. אנא שדרג לגירסאת חבילת השירות החדשה ביותר ונסה שוב." +${LangFileString} WIN2003SP1ERROR "לריינמטר ${VER} נדרשת גירסאת חלונות 2003 SP1 או גירסא חדשה יותר. אנא שדרג לגירסאת חבילת השירות החדשה ביותר ונסה שוב." +${LangFileString} ADMINERROR "נדרשות הרשאות ניהוליות." +${LangFileString} LOGONERROR "שירות החיבור אינו מופעל." +${LangFileString} UACERROR "אינו מצליח לעלות." +${LangFileString} WRITEERROR "הגירסא הניידת של ריינמטר חייבת להיות מותקנת במיקום עם הרשאות קריאה וכתיבה (כמשתמש רגיל).$\nIf אם תרצה להתקין את ריינמטר ב- '$0', חזור אחורה ובחר 'התקנה רגילה'.$\n$\nאחרת, בחר מיקום אחר בעת הרשאות קריאה וכתיבה מלאות." +${LangFileString} VCINSTERROR "Visual C++ $instArc נכשל בהתקנה עם קוד שגיאה $0.$\n$\n תצטרך להוריד את חבילת Visual C++ $instArc redistributable ידנית מ- http://rainmeter.net/redist$\n$\n לחץ OK כדי לצאת." +${LangFileString} DOTNETINSTERROR ".NET $instArc נכשל בהתקנה עם קוד שגיאה $0.$\n$\nתצטרך להוריד את חבילת .NET $instArc ידנית מ- from http://rainmeter.net/redist$\n$\nלחץ OK כדי לצאת." +${LangFileString} RAINMETERCLOSEERROR "נכשל בסגירת ריינמטר.$\n$\nאנא סגור את ריינמטר ידנית ונסה שוב." +${LangFileString} SETTINGSFILEERROR "קובץ ההגדרות (Rainmeter.ini) ממוקם בתקיית ההתקנה. השארתו שם עלולה לגרום בעיות במידה ומשתמש אחד או יותר בעלי הרשאות מוגבלות.$\n$\n האם תרצה להזיז את הקובץ לתקיית מידע היישום?" +${LangFileString} SETTINGSMOVEERROR "לא ניתן להזיז את הקובץ '$INSTDIR\Rainmeter.ini' ל- '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "אנא בחר את שפת ההתקנה." +${LangFileString} INSTALLOPTIONS "אפשרויות התקנה" +${LangFileString} INSTALLOPTIONSDESC "בחר באפשרויות התקנה נוספות" +${LangFileString} STANDARDINST "התקנה רגילה (מומלץ)" +${LangFileString} STANDARDINSTDESC "התקן את ריינמטר למחשבך והורד את הסיפריות הדרושות אוטומטית." +${LangFileString} PORTABLEINST "התקנה ניידת" +${LangFileString} PORTABLEINSTDESC "אין לבחור באפשרות זו אלא אם הינך יודע מה אתה עושה. לא יווצרו קיצורי דרך ושיוך קובץ .rmskin לא יתבצע. תצטרך להתקין ידנית את סיפריות Visual C++ ו .NET 2.0." +${LangFileString} AUTOSTARTUP "הפעל את ריינמטר אוטומטית עם עליית חלונות" +${LangFileString} ADDITIONALOPTIONS "אפשרויות נוספות" +${LangFileString} INSTALL64BIT "התקן גירסאת 64 סיביות" +${LangFileString} SENDINFORMATION "שלח מידע אודות המחשב" +${LangFileString} SENDINFORMATIONDESC "גירסאת חלונות, השפה ויכולות החומרה ידווחו פעם אחת בזמן ההתקנה כדי לאפשר שיפור של ריינמטר. לא ישלח מידע אישי." +${LangFileString} UNSTALLOPTIONS "אפשרויות הסרה" +${LangFileString} UNSTALLOPTIONSDESC "בחר אפשרויות נוספות" +${LangFileString} UNSTALLRAINMETER "הסר את ריינמטר" +${LangFileString} UNSTALLSETTINGS "הסר לחלוטין את כל ההגדרות והקבצים האישיים" ${LangFileString} UNSTALLSETTINGSDESC "(כולל מעטפות, ערכות נושא, תוספים, הגדרות מערכת הרישום, ופריטי תפריט ההתחלה)" \ No newline at end of file diff --git a/Language/Hungarian.nsh b/Language/Hungarian.nsh index 34aeb4f6..59a72f6d 100644 --- a/Language/Hungarian.nsh +++ b/Language/Hungarian.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "A Rainmeter ${VER} nem támogatja a Windows 2000 operációs rendszert. A program használatához töltsd le a korábbi Rainmeter 2.0 verziót." -${LangFileString} WINXPS2ERROR "A Rainmeter ${VER} telepítéséhez Windows XP SP2 vagy újabb operációs rendszer szükséges. Kérlek frissítsd a legújabb szervíz csomagra és próbáld újra." -${LangFileString} WIN2003SP1ERROR "A Rainmeter ${VER} telepítéséhez Windows 2003 SP1 vagy újabb operációs rendszer szükséges. Kérlek frissítsd a legújabb szervíz csomagra és próbáld újra." -${LangFileString} ADMINERROR "Rendszergazdai engedély szükséges" -${LangFileString} LOGONERROR "A bejelentkezési szolgáltatás nem fut." -${LangFileString} UACERROR "Jogosultságemelés nem lehetséges" -${LangFileString} WRITEERROR "A Rainmeter hordozható verzióját teljes írási és olvasási hozzáféréssel rendelkező helyre kell telepíteni (normál felhasználóként).$\nHa a Rainmetert a(z) '$0' mappába szeretnéd telepíteni, akkor lépj vissza és válaszd a 'Szabványos telepítés'-t.$\n$\nEgyébként válassz egy másik helyet teljes írási és olvasási hozzáféréssel. " -${LangFileString} VCINSTERROR "A Visual C++ $instArc telepítése sikertelen, hibakód: $0$\n$\nPróbáld meg a Visual C++ $instArc terjeszthető csomag manuális letöltését a http://rainmeter.net/redist webhelyről.$\n$\nKattints az OK-ra a kilépéshez." -${LangFileString} DOTNETINSTERROR ".NET $instArc telepítése sikertelen, hibakód: $0$\n$\nPróbáld meg a .NET $instArc terjeszthető csomag manuális letöltését a http://rainmeter.net/redist webhelyről.$\n$\nKattints az OK-ra a kilépéshez." -${LangFileString} RAINMETERCLOSEERROR "A Rainmeter bezárása sikertelen volt.$\n$\nKérlek zárd be a Rainmetert manuálisan, majd próbáld újra." -${LangFileString} SETTINGSFILEERROR "A beállításfájl (Rainmeter.ini) a telepítési mappában található. Ha ott marad, az problémát okozhat, ha az alkalmazást többen használják a programot, vagy valaki akinek korlátozott jogosultsága van.$\n$\nÁthelyezed a fájlt az application data mappába?" -${LangFileString} SETTINGSMOVEERROR "Nem sikerült áthelyezni a '$INSTDIR\Rainmeter.ini' fájlt a(z) '$APPDATA\Rainmeter\Rainmeter.ini' helyre." -${LangFileString} SELECTLANGUAGE " " -${LangFileString} INSTALLOPTIONS "Telepítési beállítások" -${LangFileString} INSTALLOPTIONSDESC "További telepítési beállítások kiválasztása" -${LangFileString} STANDARDINST "Szabványos telepítés (ajánlott)" -${LangFileString} STANDARDINSTDESC "Telepíti a Rainmetert és letölti a szükséges csomagokat." -${LangFileString} PORTABLEINST "Hordozható telepítés" -${LangFileString} PORTABLEINSTDESC "Ne válaszd ki, csak ha tudod mit csinálsz. Nem lesznek létrehozva parancsikonok és az .rmskin kiterjesztés nem lesz társítva. A Visual C++ és a .NET 2.0 csomagok manuális telepítésére is szükség lehet." -${LangFileString} AUTOSTARTUP "Rainmeter indítása a Windowssal" -${LangFileString} ADDITIONALOPTIONS "További beállítások" -${LangFileString} INSTALL64BIT "64 bites verzió telepítése" -${LangFileString} SENDINFORMATION "Információ küldése a számítógépről" -${LangFileString} SENDINFORMATIONDESC "A számítógéped Windows verziója, nyelve és hardver felépítését feldolgozzuk a telepítés során, a Rainmeter fejlesztése céljából. Semmilyen személyes információ nem kerül elküldésre." -${LangFileString} UNSTALLOPTIONS "Eltávolítási beállítások" -${LangFileString} UNSTALLOPTIONSDESC "További beállítások kiválasztása" -${LangFileString} UNSTALLRAINMETER "Rainmeter eltávolítása" -${LangFileString} UNSTALLSETTINGS "Személyes beállítások és fájlok végleges törlése" +${LangFileString} WIN2KERROR "A Rainmeter ${VER} nem támogatja a Windows 2000 operációs rendszert. A program használatához töltsd le a korábbi Rainmeter 2.0 verziót." +${LangFileString} WINXPS2ERROR "A Rainmeter ${VER} telepítéséhez Windows XP SP2 vagy újabb operációs rendszer szükséges. Kérlek frissítsd a legújabb szervíz csomagra és próbáld újra." +${LangFileString} WIN2003SP1ERROR "A Rainmeter ${VER} telepítéséhez Windows 2003 SP1 vagy újabb operációs rendszer szükséges. Kérlek frissítsd a legújabb szervíz csomagra és próbáld újra." +${LangFileString} ADMINERROR "Rendszergazdai engedély szükséges" +${LangFileString} LOGONERROR "A bejelentkezési szolgáltatás nem fut." +${LangFileString} UACERROR "Jogosultságemelés nem lehetséges" +${LangFileString} WRITEERROR "A Rainmeter hordozható verzióját teljes írási és olvasási hozzáféréssel rendelkező helyre kell telepíteni (normál felhasználóként).$\nHa a Rainmetert a(z) '$0' mappába szeretnéd telepíteni, akkor lépj vissza és válaszd a 'Szabványos telepítés'-t.$\n$\nEgyébként válassz egy másik helyet teljes írási és olvasási hozzáféréssel. " +${LangFileString} VCINSTERROR "A Visual C++ $instArc telepítése sikertelen, hibakód: $0$\n$\nPróbáld meg a Visual C++ $instArc terjeszthető csomag manuális letöltését a http://rainmeter.net/redist webhelyről.$\n$\nKattints az OK-ra a kilépéshez." +${LangFileString} DOTNETINSTERROR ".NET $instArc telepítése sikertelen, hibakód: $0$\n$\nPróbáld meg a .NET $instArc terjeszthető csomag manuális letöltését a http://rainmeter.net/redist webhelyről.$\n$\nKattints az OK-ra a kilépéshez." +${LangFileString} RAINMETERCLOSEERROR "A Rainmeter bezárása sikertelen volt.$\n$\nKérlek zárd be a Rainmetert manuálisan, majd próbáld újra." +${LangFileString} SETTINGSFILEERROR "A beállításfájl (Rainmeter.ini) a telepítési mappában található. Ha ott marad, az problémát okozhat, ha az alkalmazást többen használják a programot, vagy valaki akinek korlátozott jogosultsága van.$\n$\nÁthelyezed a fájlt az application data mappába?" +${LangFileString} SETTINGSMOVEERROR "Nem sikerült áthelyezni a '$INSTDIR\Rainmeter.ini' fájlt a(z) '$APPDATA\Rainmeter\Rainmeter.ini' helyre." +${LangFileString} SELECTLANGUAGE " " +${LangFileString} INSTALLOPTIONS "Telepítési beállítások" +${LangFileString} INSTALLOPTIONSDESC "További telepítési beállítások kiválasztása" +${LangFileString} STANDARDINST "Szabványos telepítés (ajánlott)" +${LangFileString} STANDARDINSTDESC "Telepíti a Rainmetert és letölti a szükséges csomagokat." +${LangFileString} PORTABLEINST "Hordozható telepítés" +${LangFileString} PORTABLEINSTDESC "Ne válaszd ki, csak ha tudod mit csinálsz. Nem lesznek létrehozva parancsikonok és az .rmskin kiterjesztés nem lesz társítva. A Visual C++ és a .NET 2.0 csomagok manuális telepítésére is szükség lehet." +${LangFileString} AUTOSTARTUP "Rainmeter indítása a Windowssal" +${LangFileString} ADDITIONALOPTIONS "További beállítások" +${LangFileString} INSTALL64BIT "64 bites verzió telepítése" +${LangFileString} SENDINFORMATION "Információ küldése a számítógépről" +${LangFileString} SENDINFORMATIONDESC "A számítógéped Windows verziója, nyelve és hardver felépítését feldolgozzuk a telepítés során, a Rainmeter fejlesztése céljából. Semmilyen személyes információ nem kerül elküldésre." +${LangFileString} UNSTALLOPTIONS "Eltávolítási beállítások" +${LangFileString} UNSTALLOPTIONSDESC "További beállítások kiválasztása" +${LangFileString} UNSTALLRAINMETER "Rainmeter eltávolítása" +${LangFileString} UNSTALLSETTINGS "Személyes beállítások és fájlok végleges törlése" ${LangFileString} UNSTALLSETTINGSDESC "(beleértve a felületeket, témákat, bővítményeket, registry beállításokat, és a Start menü elemeket.)" \ No newline at end of file diff --git a/Language/Indonesian.nsh b/Language/Indonesian.nsh index e7ea0ff1..79389524 100644 --- a/Language/Indonesian.nsh +++ b/Language/Indonesian.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} tidak mendukung Windows 2000. Untuk menggunakan pada Windows 2000, unduh Rainmeter 2.0 versi lama." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} membutuhkan Windows XP SP2 atau lebih tinggi. Mohon naikan ke service pack terbaru dan coba lagi." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} membutuhkan Windows 2003 SP1 atau lebih tinggi. Mohon naikan ke service pack terbaru dan coba lagi." -${LangFileString} ADMINERROR "Adminstrative rights dibutuhkan." -${LangFileString} LOGONERROR "Logon service tidak berjalan." -${LangFileString} UACERROR "Tak dapat meningkatkan." -${LangFileString} WRITEERROR "Portable Rainmeter harus di instal pada lokasi dengan full read and write access (as normal user).$\njika Anda mau menginstal Rainmeter pada '$0', kembali dan pilih 'Standard installation'.$\n$\nAtau, cari lokasi lain dengan full read and write access." -${LangFileString} VCINSTERROR "Visual C++ $instArc instal gagal dengan kode galat $0.$\n$\nAnda mungkin mau coba unduh secara manual paket Visual C++ $instArc redistributable dari http://rainmeter.net/redist$\n$\nTekan OK untuk keluar." -${LangFileString} DOTNETINSTERROR ".NET $instArc instal gagal dengan kode galat $0.$\n$\nAnda mungkin mau coba unduh secara manual paket Visual .Net $instArc redistributable dari http://rainmeter.net/redist$\n$\nTekan OK untuk keluar." -${LangFileString} RAINMETERCLOSEERROR "Failed to close Rainmeter.$\n$\nPlease close Rainmeter manually and try again." -${LangFileString} SETTINGSFILEERROR "Berkas pengaturan-pengaturan (Rainmeter.ini) berada di bilah instalasi. Membiarkan disitu bisa menyebabkan masalah-masalah jika aplikasi digunakan oleh multiple users atau oleh seseorang dengan restricted user privileges.$\n$\nApakah Anda mau memindahkan berkas ke bilah data applikasi?" -${LangFileString} SETTINGSMOVEERROR "Tak dapat memindahkan berkas '$INSTDIR\Rainmeter.ini' ke '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Silahkan pilih bahasa instalasian." -${LangFileString} INSTALLOPTIONS "Opsi Instal" -${LangFileString} INSTALLOPTIONSDESC "Pilih opsi-opsi instal tambahan" -${LangFileString} STANDARDINST "Instalasi tandar (dianjurkan)" -${LangFileString} STANDARDINSTDESC "Instal Rainmeter dan unduh pustaka yang dibutuhkan." -${LangFileString} PORTABLEINST "Instalasi portabel" -${LangFileString} PORTABLEINSTDESC "Jangan pilih ini kecuali Anda tahu yang sedang Anda lakukan. Shortcuts takan dibuat dan .rmskin extension takan di-registered. Pustaka Visual C++ dan .NET 2.0 mungkin harus di instal secara manual." -${LangFileString} AUTOSTARTUP "Jalankan Rainmeter saat startup" -${LangFileString} ADDITIONALOPTIONS "Opsi-opsi tambahan" -${LangFileString} INSTALL64BIT "64-bit" -${LangFileString} SENDINFORMATION "Send information about your computer" -${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." -${LangFileString} UNSTALLOPTIONS "Opsi-opsi penidakpasangan" -${LangFileString} UNSTALLOPTIONSDESC "Pilih opsi-opsi tambahan lainnya" -${LangFileString} UNSTALLRAINMETER "Penidakpasang Rainmeter" -${LangFileString} UNSTALLSETTINGS "Singkirkan semua pengaturan-pengaturan dan berkas-berkas pribadi secara menyeluruh" +${LangFileString} WIN2KERROR "Rainmeter ${VER} tidak mendukung Windows 2000. Untuk menggunakan pada Windows 2000, unduh Rainmeter 2.0 versi lama." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} membutuhkan Windows XP SP2 atau lebih tinggi. Mohon naikan ke service pack terbaru dan coba lagi." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} membutuhkan Windows 2003 SP1 atau lebih tinggi. Mohon naikan ke service pack terbaru dan coba lagi." +${LangFileString} ADMINERROR "Adminstrative rights dibutuhkan." +${LangFileString} LOGONERROR "Logon service tidak berjalan." +${LangFileString} UACERROR "Tak dapat meningkatkan." +${LangFileString} WRITEERROR "Portable Rainmeter harus di instal pada lokasi dengan full read and write access (as normal user).$\njika Anda mau menginstal Rainmeter pada '$0', kembali dan pilih 'Standard installation'.$\n$\nAtau, cari lokasi lain dengan full read and write access." +${LangFileString} VCINSTERROR "Visual C++ $instArc instal gagal dengan kode galat $0.$\n$\nAnda mungkin mau coba unduh secara manual paket Visual C++ $instArc redistributable dari http://rainmeter.net/redist$\n$\nTekan OK untuk keluar." +${LangFileString} DOTNETINSTERROR ".NET $instArc instal gagal dengan kode galat $0.$\n$\nAnda mungkin mau coba unduh secara manual paket Visual .Net $instArc redistributable dari http://rainmeter.net/redist$\n$\nTekan OK untuk keluar." +${LangFileString} RAINMETERCLOSEERROR "Failed to close Rainmeter.$\n$\nPlease close Rainmeter manually and try again." +${LangFileString} SETTINGSFILEERROR "Berkas pengaturan-pengaturan (Rainmeter.ini) berada di bilah instalasi. Membiarkan disitu bisa menyebabkan masalah-masalah jika aplikasi digunakan oleh multiple users atau oleh seseorang dengan restricted user privileges.$\n$\nApakah Anda mau memindahkan berkas ke bilah data applikasi?" +${LangFileString} SETTINGSMOVEERROR "Tak dapat memindahkan berkas '$INSTDIR\Rainmeter.ini' ke '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Silahkan pilih bahasa instalasian." +${LangFileString} INSTALLOPTIONS "Opsi Instal" +${LangFileString} INSTALLOPTIONSDESC "Pilih opsi-opsi instal tambahan" +${LangFileString} STANDARDINST "Instalasi tandar (dianjurkan)" +${LangFileString} STANDARDINSTDESC "Instal Rainmeter dan unduh pustaka yang dibutuhkan." +${LangFileString} PORTABLEINST "Instalasi portabel" +${LangFileString} PORTABLEINSTDESC "Jangan pilih ini kecuali Anda tahu yang sedang Anda lakukan. Shortcuts takan dibuat dan .rmskin extension takan di-registered. Pustaka Visual C++ dan .NET 2.0 mungkin harus di instal secara manual." +${LangFileString} AUTOSTARTUP "Jalankan Rainmeter saat startup" +${LangFileString} ADDITIONALOPTIONS "Opsi-opsi tambahan" +${LangFileString} INSTALL64BIT "64-bit" +${LangFileString} SENDINFORMATION "Send information about your computer" +${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." +${LangFileString} UNSTALLOPTIONS "Opsi-opsi penidakpasangan" +${LangFileString} UNSTALLOPTIONSDESC "Pilih opsi-opsi tambahan lainnya" +${LangFileString} UNSTALLRAINMETER "Penidakpasang Rainmeter" +${LangFileString} UNSTALLSETTINGS "Singkirkan semua pengaturan-pengaturan dan berkas-berkas pribadi secara menyeluruh" ${LangFileString} UNSTALLSETTINGSDESC "(termasuk skin-skin, tema-tema, addon-addon, pengaturan registry, dan item-item Start menu )" \ No newline at end of file diff --git a/Language/Italian.nsh b/Language/Italian.nsh index 3b9e20ea..2a784eb1 100644 --- a/Language/Italian.nsh +++ b/Language/Italian.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} non supporta Windows 2000. Per usare Rainmeter su Windows 2000, scaricare la versione obsoleta di Rainmeter 2.0" -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} necessita Windows XP SP2 o superiore. Aggiornare all'ultimo Service Pack e riprovare." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} necessita Windows 2003 SP1 o superiore. Aggiornare all'ultimo Service Pack e riprovare." -${LangFileString} ADMINERROR "Richiesti diritti d'amministratore." -${LangFileString} LOGONERROR "Servizio di login non disponibile." -${LangFileString} UACERROR "Impossibile alzare i privilegi." -${LangFileString} WRITEERROR "Rainmeter portable deve essere installato in una cartella con pieno accesso di lettura e scrittura (come utente normale).$\nISe vuoi installare Rainmeter in '$0', torna indietro e seleziona 'Installazione standard'.$\n$\nAltrimenti, cerca un'altra cartella con pieno accesso di lettura e scrittura." -${LangFileString} VCINSTERROR "Visual C++ $instArc installazione fallita, codice errore $0.$\n$\nPuoi scaricare Visual C++ $instArc redistributable manualmente da http://rainmeter.net/redist$\n$\nPremi OK per uscire." -${LangFileString} DOTNETINSTERROR ".NET $instArc installazione fallita, codice errore $0.$\n$\nPuoi scaricare .NET $instArc redistributable manualmente da http://rainmeter.net/redist$\n$\nPremi OK per uscire." -${LangFileString} RAINMETERCLOSEERROR "Chiusura di Rainmeter non riuscita.$\n$\nChiudere Rainmeter manualmente e riprovare." -${LangFileString} SETTINGSFILEERROR "Il file di impostazioni (Rainmeter.ini) si trova nella cartella d'installazione. Tenendolo lì potrebbero esserci problemi se l'applicazione è utilizzata da diversi utenti o da un utente con privilegi limitati.$\n$\nVuoi spostare il file nella cartella Dati Applicazioni?" -${LangFileString} SETTINGSMOVEERROR "Impossibile muovere il file '$INSTDIR\Rainmeter.ini' in '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Selezionare la lingua di installazione." -${LangFileString} INSTALLOPTIONS "Opzioni di installazione" -${LangFileString} INSTALLOPTIONSDESC "Selezionare le opzioni aggiuntive di installazione" -${LangFileString} STANDARDINST "Installazione standard (raccomandato)" -${LangFileString} STANDARDINSTDESC "Installa Rainmeter e scarica le librerie richieste." -${LangFileString} PORTABLEINST "Installazione portable" -${LangFileString} PORTABLEINSTDESC "Non selezionare a meno che non sai quel che stai facendo. I collegamenti non saranno creati e l'estensione .rmskin non sarà registrata. Le librerie Visual C++ e .NET 2.0 potrebbero dover essere installate manualmente." -${LangFileString} AUTOSTARTUP "Lancia Rainmeter all'avvio" -${LangFileString} ADDITIONALOPTIONS "Opzioni aggiuntive" -${LangFileString} INSTALL64BIT "Installa la versione 64-bit" -${LangFileString} SENDINFORMATION "Send information about your computer" -${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." -${LangFileString} UNSTALLOPTIONS "Opzioni di disinstallazione" -${LangFileString} UNSTALLOPTIONSDESC "Selezionare opzioni aggiuntive" -${LangFileString} UNSTALLRAINMETER "Disinstalla Rainmeter" -${LangFileString} UNSTALLSETTINGS "Rimuovere completamente tutti i file e le impostazioni personali" +${LangFileString} WIN2KERROR "Rainmeter ${VER} non supporta Windows 2000. Per usare Rainmeter su Windows 2000, scaricare la versione obsoleta di Rainmeter 2.0" +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} necessita Windows XP SP2 o superiore. Aggiornare all'ultimo Service Pack e riprovare." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} necessita Windows 2003 SP1 o superiore. Aggiornare all'ultimo Service Pack e riprovare." +${LangFileString} ADMINERROR "Richiesti diritti d'amministratore." +${LangFileString} LOGONERROR "Servizio di login non disponibile." +${LangFileString} UACERROR "Impossibile alzare i privilegi." +${LangFileString} WRITEERROR "Rainmeter portable deve essere installato in una cartella con pieno accesso di lettura e scrittura (come utente normale).$\nISe vuoi installare Rainmeter in '$0', torna indietro e seleziona 'Installazione standard'.$\n$\nAltrimenti, cerca un'altra cartella con pieno accesso di lettura e scrittura." +${LangFileString} VCINSTERROR "Visual C++ $instArc installazione fallita, codice errore $0.$\n$\nPuoi scaricare Visual C++ $instArc redistributable manualmente da http://rainmeter.net/redist$\n$\nPremi OK per uscire." +${LangFileString} DOTNETINSTERROR ".NET $instArc installazione fallita, codice errore $0.$\n$\nPuoi scaricare .NET $instArc redistributable manualmente da http://rainmeter.net/redist$\n$\nPremi OK per uscire." +${LangFileString} RAINMETERCLOSEERROR "Chiusura di Rainmeter non riuscita.$\n$\nChiudere Rainmeter manualmente e riprovare." +${LangFileString} SETTINGSFILEERROR "Il file di impostazioni (Rainmeter.ini) si trova nella cartella d'installazione. Tenendolo lì potrebbero esserci problemi se l'applicazione è utilizzata da diversi utenti o da un utente con privilegi limitati.$\n$\nVuoi spostare il file nella cartella Dati Applicazioni?" +${LangFileString} SETTINGSMOVEERROR "Impossibile muovere il file '$INSTDIR\Rainmeter.ini' in '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Selezionare la lingua di installazione." +${LangFileString} INSTALLOPTIONS "Opzioni di installazione" +${LangFileString} INSTALLOPTIONSDESC "Selezionare le opzioni aggiuntive di installazione" +${LangFileString} STANDARDINST "Installazione standard (raccomandato)" +${LangFileString} STANDARDINSTDESC "Installa Rainmeter e scarica le librerie richieste." +${LangFileString} PORTABLEINST "Installazione portable" +${LangFileString} PORTABLEINSTDESC "Non selezionare a meno che non sai quel che stai facendo. I collegamenti non saranno creati e l'estensione .rmskin non sarà registrata. Le librerie Visual C++ e .NET 2.0 potrebbero dover essere installate manualmente." +${LangFileString} AUTOSTARTUP "Lancia Rainmeter all'avvio" +${LangFileString} ADDITIONALOPTIONS "Opzioni aggiuntive" +${LangFileString} INSTALL64BIT "Installa la versione 64-bit" +${LangFileString} SENDINFORMATION "Send information about your computer" +${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." +${LangFileString} UNSTALLOPTIONS "Opzioni di disinstallazione" +${LangFileString} UNSTALLOPTIONSDESC "Selezionare opzioni aggiuntive" +${LangFileString} UNSTALLRAINMETER "Disinstalla Rainmeter" +${LangFileString} UNSTALLSETTINGS "Rimuovere completamente tutti i file e le impostazioni personali" ${LangFileString} UNSTALLSETTINGSDESC "(includendo skin, temi, addon, impostazioni di registro e voci del menù Start)" \ No newline at end of file diff --git a/Language/Japanese.nsh b/Language/Japanese.nsh index d2d841fa..e7d158bf 100644 --- a/Language/Japanese.nsh +++ b/Language/Japanese.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} は Windows 2000 に対応していません。Rainmeter を Windows 2000 で使用するには、バージョン 2.0 以前の Rainmeter をダウンロードしてください。" -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} を動作させるには、Windows XP SP2 以降である必要があります。最新の ServicePack を適用後にもう一度お試しください。" -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} を動作させるには、Windows 2003 SP1 以降である必要があります。最新の ServicePack を適用後にもう一度お試しください。" -${LangFileString} ADMINERROR "管理者権限が必要です。" -${LangFileString} LOGONERROR "ログオンサービスが起動していません。" -${LangFileString} UACERROR "権限の昇格に失敗しました。" -${LangFileString} WRITEERROR "ポータブル版 Rainmeter をインストールするには、標準ユーザーとしての完全なファイルの読み書き権限を必要とします。$\nRainmeter を '$0' へインストールするには、前に戻り、[標準インストール] を選択してください。$\n$\nまたは、完全なファイルの読み書き権限のある別の場所を選択してください。" -${LangFileString} VCINSTERROR "Visual C++ $instArc のインストールに失敗しました。(エラー$0)$\n$\n必要であれば、Visual C++ $instArc ランタイムを http://rainmeter.net/redist からダウンロードすることができます。$\n$\n[OK] を押すと終了します。" -${LangFileString} DOTNETINSTERROR ".NET $instArc のインストールに失敗しました。(エラー$0)$\n$\n必要であれば、.NET $instArc ランタイムを http://rainmeter.net/redist からダウンロードすることができます。$\n$\n[OK] を押すと終了します。" -${LangFileString} RAINMETERCLOSEERROR "Rainmeter の終了に失敗しました。$\n$\nRainmeter を手動で終了した後にもう一度お試しください。" -${LangFileString} SETTINGSFILEERROR "設定ファイル (Rainmeter.ini) の保存先がインストールフォルダーに指定されています。そのままにした場合、複数のユーザーや制限ユーザーがアプリケーションを実行した際に問題を引き起こす可能性があります。$\n$\nこのファイルをアプリケーションデータフォルダーに移動してもよろしいですか?" -${LangFileString} SETTINGSMOVEERROR "'$INSTDIR\Rainmeter.ini' から '$APPDATA\Rainmeter\Rainmeter.ini' へのファイルの移動に失敗しました。" -${LangFileString} SELECTLANGUAGE "インストール時に使用する言語を選択してください。" -${LangFileString} INSTALLOPTIONS "インストールの設定" -${LangFileString} INSTALLOPTIONSDESC "追加のインストールの設定を選択" -${LangFileString} STANDARDINST "標準インストール (推奨)" -${LangFileString} STANDARDINSTDESC "Rainmeter のインストールと必要なライブラリのダウンロードが行われます。" -${LangFileString} PORTABLEINST "ポータブル版のインストール" -${LangFileString} PORTABLEINSTDESC "この項目を理解している場合のみこちらを選択してください。ショートカットの作成や .rmskin ファイルの関連付けは一切行われません。Visual C++ 及び、.NET 2.0 ライブラリを手動でインストールする必要があるかもしれません。" -${LangFileString} AUTOSTARTUP "Windows の起動時に Rainmeter を起動する" -${LangFileString} ADDITIONALOPTIONS "追加の設定" -${LangFileString} INSTALL64BIT "64 ビット版をインストール" -${LangFileString} SENDINFORMATION "コンピューターに関する情報を送信する" -${LangFileString} SENDINFORMATIONDESC "Rainmeter の改善のため、インストール時に Windows のバージョン、言語、ハードウェアの機能に関する情報を送信します。個人情報は収集されません。" -${LangFileString} UNSTALLOPTIONS "アンインストールの設定" -${LangFileString} UNSTALLOPTIONSDESC "追加の設定を選択" -${LangFileString} UNSTALLRAINMETER "Rainmeter をアンインストール" -${LangFileString} UNSTALLSETTINGS "すべての個人の設定とファイルは完全に削除されます。" -${LangFileString} UNSTALLSETTINGSDESC "(スキン、テーマ、レジストリの設定、スタートメニューの項目を含む)" +${LangFileString} WIN2KERROR "Rainmeter ${VER} は Windows 2000 に対応していません。Rainmeter を Windows 2000 で使用するには、バージョン 2.0 以前の Rainmeter をダウンロードしてください。" +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} を動作させるには、Windows XP SP2 以降である必要があります。最新の ServicePack を適用後にもう一度お試しください。" +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} を動作させるには、Windows 2003 SP1 以降である必要があります。最新の ServicePack を適用後にもう一度お試しください。" +${LangFileString} ADMINERROR "管理者権限が必要です。" +${LangFileString} LOGONERROR "ログオンサービスが起動していません。" +${LangFileString} UACERROR "権限の昇格に失敗しました。" +${LangFileString} WRITEERROR "ポータブル版 Rainmeter をインストールするには、標準ユーザーとしての完全なファイルの読み書き権限を必要とします。$\nRainmeter を '$0' へインストールするには、前に戻り、[標準インストール] を選択してください。$\n$\nまたは、完全なファイルの読み書き権限のある別の場所を選択してください。" +${LangFileString} VCINSTERROR "Visual C++ $instArc のインストールに失敗しました。(エラー$0)$\n$\n必要であれば、Visual C++ $instArc ランタイムを http://rainmeter.net/redist からダウンロードすることができます。$\n$\n[OK] を押すと終了します。" +${LangFileString} DOTNETINSTERROR ".NET $instArc のインストールに失敗しました。(エラー$0)$\n$\n必要であれば、.NET $instArc ランタイムを http://rainmeter.net/redist からダウンロードすることができます。$\n$\n[OK] を押すと終了します。" +${LangFileString} RAINMETERCLOSEERROR "Rainmeter の終了に失敗しました。$\n$\nRainmeter を手動で終了した後にもう一度お試しください。" +${LangFileString} SETTINGSFILEERROR "設定ファイル (Rainmeter.ini) の保存先がインストールフォルダーに指定されています。そのままにした場合、複数のユーザーや制限ユーザーがアプリケーションを実行した際に問題を引き起こす可能性があります。$\n$\nこのファイルをアプリケーションデータフォルダーに移動してもよろしいですか?" +${LangFileString} SETTINGSMOVEERROR "'$INSTDIR\Rainmeter.ini' から '$APPDATA\Rainmeter\Rainmeter.ini' へのファイルの移動に失敗しました。" +${LangFileString} SELECTLANGUAGE "インストール時に使用する言語を選択してください。" +${LangFileString} INSTALLOPTIONS "インストールの設定" +${LangFileString} INSTALLOPTIONSDESC "追加のインストールの設定を選択" +${LangFileString} STANDARDINST "標準インストール (推奨)" +${LangFileString} STANDARDINSTDESC "Rainmeter のインストールと必要なライブラリのダウンロードが行われます。" +${LangFileString} PORTABLEINST "ポータブル版のインストール" +${LangFileString} PORTABLEINSTDESC "この項目を理解している場合のみこちらを選択してください。ショートカットの作成や .rmskin ファイルの関連付けは一切行われません。Visual C++ 及び、.NET 2.0 ライブラリを手動でインストールする必要があるかもしれません。" +${LangFileString} AUTOSTARTUP "Windows の起動時に Rainmeter を起動する" +${LangFileString} ADDITIONALOPTIONS "追加の設定" +${LangFileString} INSTALL64BIT "64 ビット版をインストール" +${LangFileString} SENDINFORMATION "コンピューターに関する情報を送信する" +${LangFileString} SENDINFORMATIONDESC "Rainmeter の改善のため、インストール時に Windows のバージョン、言語、ハードウェアの機能に関する情報を送信します。個人情報は収集されません。" +${LangFileString} UNSTALLOPTIONS "アンインストールの設定" +${LangFileString} UNSTALLOPTIONSDESC "追加の設定を選択" +${LangFileString} UNSTALLRAINMETER "Rainmeter をアンインストール" +${LangFileString} UNSTALLSETTINGS "すべての個人の設定とファイルは完全に削除されます。" +${LangFileString} UNSTALLSETTINGSDESC "(スキン、テーマ、レジストリの設定、スタートメニューの項目を含む)" diff --git a/Language/Korean.nsh b/Language/Korean.nsh index 9a29024c..5ce02203 100644 --- a/Language/Korean.nsh +++ b/Language/Korean.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "레인미터 ${VER}은 Windows 2000을 지원하지 않습니다. 레인미터를 Windows 2000에서 사용하려면, 레인미터 2.0 이전 버전을 다운로드 하세요." -${LangFileString} WINXPS2ERROR "레인미터 ${VER}은 Windows XP 서비스팩2 이상이 필요합니다. 최신 서비스팩으로 업그레이드 후 다시 시도해 주세요." -${LangFileString} WIN2003SP1ERROR "레인미터 ${VER}은 Windows 2003 서비스팩1 이상이 필요합니다. 최신 서비스팩으로 업그레이드 후 다시 시도해 주세요." -${LangFileString} ADMINERROR "관리자 권한이 필요합니다." -${LangFileString} LOGONERROR "로그온 서비스가 실행 중이 아닙니다." -${LangFileString} UACERROR "권한 상승 실패." -${LangFileString} WRITEERROR "포터블 레인미터는 반드시 (일반 사용자로) 완전한 읽기 및 쓰기 권한을 가진 위치에 설치되야 합니다.$\nIf 레인미터를 '$0'에 설치하려면 이전으로 가서 '일반 설치'를 선택하세요.$\n$\n또는 완전한 읽기 및 쓰기 권한을 가진 다른 위치를 선택하세요." -${LangFileString} VCINSTERROR "Visual C++ $instArc 설치가 오류 코드 $0로 실패하였습니다.$\n$\nhttp://rainmeter.net/redist에서 직접 Visual C++ $instArc 재배포 가능 패키지를 다운로드하세요.$\n$\nOK를 누르면 종료됩니다." -${LangFileString} DOTNETINSTERROR ".NET $instArc 설치가 오류 코드 $0로 실패하였습니다.$\n$\nhttp://rainmeter.net/redist에서 직접 .NET $instArc 재배포 가능 패키지를 다운로드하세요.$\n$\nPress OK to exit." -${LangFileString} RAINMETERCLOSEERROR "레인미터 종료 실패.$\n$\n레인미터를 직접 종료한 후 다시 시도해 주세요." -${LangFileString} SETTINGSFILEERROR "설정 파일(Rainmeter.ini)는 레인미터가 설치된 폴더에 있습니다. 응용 프로그램을 여러 사용자 혹은 제한된 권한의 사용자가 사용할 경우 설정을 유지하는데 문제가 생길 수 있습니다.$\n$\n이 파일을 응용 프로그램 데이터 폴더로 옮기시겠습니까?" -${LangFileString} SETTINGSMOVEERROR "'$INSTDIR\Rainmeter.ini' 파일을 '$APPDATA\Rainmeter\Rainmeter.ini'로 이동할 수 없습습니다." -${LangFileString} SELECTLANGUAGE "설치 언어를 선택하세요." -${LangFileString} INSTALLOPTIONS "설치 옵션" -${LangFileString} INSTALLOPTIONSDESC "추가 설치 옵션을 선택하세요" -${LangFileString} STANDARDINST "일반 설치 (권장)" -${LangFileString} STANDARDINSTDESC "레인미터를 설치하고 필요한 라이브러리들을 다운로드 합니다." -${LangFileString} PORTABLEINST "포터블 설치" -${LangFileString} PORTABLEINSTDESC "이 항목을 알지 못한다면 선택하지 마십시오. 바로 가기가 설치되지 않고 .rmskin 파일 연결이 되지 않습니다. Visual C++과 .NET 2.0 라이브러리를 수동으로 설치해야 할 수도 있습니다." -${LangFileString} AUTOSTARTUP "Windows를 시작 시 레인미터 실행" -${LangFileString} ADDITIONALOPTIONS "추가 옵션" -${LangFileString} INSTALL64BIT "64비트 버전 설치" -${LangFileString} SENDINFORMATION "컴퓨터 정보 보내기" -${LangFileString} SENDINFORMATIONDESC "레인미터를 향상시키기 위해 사용자 컴퓨터의 윈도우 버전, 언어, 그리고 하드웨어 호환성이 설치 중 단 한번 보고됩니다. 개인 정보는 보내지 않습니다." -${LangFileString} UNSTALLOPTIONS "제거 옵션" -${LangFileString} UNSTALLOPTIONSDESC "다른 추가 옵션을 선택하세요" -${LangFileString} UNSTALLRAINMETER "레인미터 제거" -${LangFileString} UNSTALLSETTINGS "모든 개인 설정 및 파일 제거" +${LangFileString} WIN2KERROR "레인미터 ${VER}은 Windows 2000을 지원하지 않습니다. 레인미터를 Windows 2000에서 사용하려면, 레인미터 2.0 이전 버전을 다운로드 하세요." +${LangFileString} WINXPS2ERROR "레인미터 ${VER}은 Windows XP 서비스팩2 이상이 필요합니다. 최신 서비스팩으로 업그레이드 후 다시 시도해 주세요." +${LangFileString} WIN2003SP1ERROR "레인미터 ${VER}은 Windows 2003 서비스팩1 이상이 필요합니다. 최신 서비스팩으로 업그레이드 후 다시 시도해 주세요." +${LangFileString} ADMINERROR "관리자 권한이 필요합니다." +${LangFileString} LOGONERROR "로그온 서비스가 실행 중이 아닙니다." +${LangFileString} UACERROR "권한 상승 실패." +${LangFileString} WRITEERROR "포터블 레인미터는 반드시 (일반 사용자로) 완전한 읽기 및 쓰기 권한을 가진 위치에 설치되야 합니다.$\nIf 레인미터를 '$0'에 설치하려면 이전으로 가서 '일반 설치'를 선택하세요.$\n$\n또는 완전한 읽기 및 쓰기 권한을 가진 다른 위치를 선택하세요." +${LangFileString} VCINSTERROR "Visual C++ $instArc 설치가 오류 코드 $0로 실패하였습니다.$\n$\nhttp://rainmeter.net/redist에서 직접 Visual C++ $instArc 재배포 가능 패키지를 다운로드하세요.$\n$\nOK를 누르면 종료됩니다." +${LangFileString} DOTNETINSTERROR ".NET $instArc 설치가 오류 코드 $0로 실패하였습니다.$\n$\nhttp://rainmeter.net/redist에서 직접 .NET $instArc 재배포 가능 패키지를 다운로드하세요.$\n$\nPress OK to exit." +${LangFileString} RAINMETERCLOSEERROR "레인미터 종료 실패.$\n$\n레인미터를 직접 종료한 후 다시 시도해 주세요." +${LangFileString} SETTINGSFILEERROR "설정 파일(Rainmeter.ini)는 레인미터가 설치된 폴더에 있습니다. 응용 프로그램을 여러 사용자 혹은 제한된 권한의 사용자가 사용할 경우 설정을 유지하는데 문제가 생길 수 있습니다.$\n$\n이 파일을 응용 프로그램 데이터 폴더로 옮기시겠습니까?" +${LangFileString} SETTINGSMOVEERROR "'$INSTDIR\Rainmeter.ini' 파일을 '$APPDATA\Rainmeter\Rainmeter.ini'로 이동할 수 없습습니다." +${LangFileString} SELECTLANGUAGE "설치 언어를 선택하세요." +${LangFileString} INSTALLOPTIONS "설치 옵션" +${LangFileString} INSTALLOPTIONSDESC "추가 설치 옵션을 선택하세요" +${LangFileString} STANDARDINST "일반 설치 (권장)" +${LangFileString} STANDARDINSTDESC "레인미터를 설치하고 필요한 라이브러리들을 다운로드 합니다." +${LangFileString} PORTABLEINST "포터블 설치" +${LangFileString} PORTABLEINSTDESC "이 항목을 알지 못한다면 선택하지 마십시오. 바로 가기가 설치되지 않고 .rmskin 파일 연결이 되지 않습니다. Visual C++과 .NET 2.0 라이브러리를 수동으로 설치해야 할 수도 있습니다." +${LangFileString} AUTOSTARTUP "Windows를 시작 시 레인미터 실행" +${LangFileString} ADDITIONALOPTIONS "추가 옵션" +${LangFileString} INSTALL64BIT "64비트 버전 설치" +${LangFileString} SENDINFORMATION "컴퓨터 정보 보내기" +${LangFileString} SENDINFORMATIONDESC "레인미터를 향상시키기 위해 사용자 컴퓨터의 윈도우 버전, 언어, 그리고 하드웨어 호환성이 설치 중 단 한번 보고됩니다. 개인 정보는 보내지 않습니다." +${LangFileString} UNSTALLOPTIONS "제거 옵션" +${LangFileString} UNSTALLOPTIONSDESC "다른 추가 옵션을 선택하세요" +${LangFileString} UNSTALLRAINMETER "레인미터 제거" +${LangFileString} UNSTALLSETTINGS "모든 개인 설정 및 파일 제거" ${LangFileString} UNSTALLSETTINGSDESC "(스킨, 테마, 애드온, 레지스트리 설정, 시작 메뉴 항목 포함)" \ No newline at end of file diff --git a/Language/Language.rc b/Language/Language.rc index 2c767bba..1d9d0813 100644 --- a/Language/Language.rc +++ b/Language/Language.rc @@ -1,2 +1,2 @@ -#include "English.h" -#include "Resource.rc" +#include "English.h" +#include "Resource.rc" diff --git a/Language/Language.vcxproj b/Language/Language.vcxproj index 24986b2b..4dc4a5f7 100644 --- a/Language/Language.vcxproj +++ b/Language/Language.vcxproj @@ -1,43 +1,43 @@ - - - - - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A} - DynamicLibrary - 1033 - - - - - - - - - - - - $(OutDir)Languages\ - - - - true - - - Default - true - - - _UNICODE;UNICODE;%(PreprocessorDefinitions) - true - - - - - - true - - - - - + + + + + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A} + DynamicLibrary + 1033 + + + + + + + + + + + + $(OutDir)Languages\ + + + + true + + + Default + true + + + _UNICODE;UNICODE;%(PreprocessorDefinitions) + true + + + + + + true + + + + + \ No newline at end of file diff --git a/Language/Language.vcxproj.filters b/Language/Language.vcxproj.filters index a5e7646f..b0480503 100644 --- a/Language/Language.vcxproj.filters +++ b/Language/Language.vcxproj.filters @@ -1,25 +1,25 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Resource Files - - - Resource Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + \ No newline at end of file diff --git a/Language/Latvian.nsh b/Language/Latvian.nsh index 39e33dbe..c9f002b6 100644 --- a/Language/Latvian.nsh +++ b/Language/Latvian.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter programa ${VER} neatbalsta Windows 2000. Lai izmantotu Rainmeter uz Windows 2000 platformas, lejuplādējiet vecāku Rainmeter 2.0 programas versiju." -${LangFileString} WINXPS2ERROR "Rainmeter programai ${VER} nepieciešams Windows XP Servisa paka 2 (SP2) vai augstāks. Lūdzu uzlabojiet uz jaunāku servisa paku un mēģiniet vēlreiz." -${LangFileString} WIN2003SP1ERROR "Rainmeter programai ${VER} nepieciešams Windows 2003 Servisa paka 1 (SP1) vai augstāks. Lūdzu uzlabojiet uz jaunāku servisa paku un mēģiniet vēlreiz." -${LangFileString} ADMINERROR "Nepieciešamas administratora tiesības." -${LangFileString} LOGONERROR "'Logon service' nav ieslēgts." -${LangFileString} UACERROR "Nevar paaugstināt." -${LangFileString} WRITEERROR "Mobīlai Rainmeter programai jābūt instalētai mapē ar pilnīgu piekļuvi (kā parastam lietotājam).$\nJa jūs vēlaties instalēt Rainmeter programu mapē '$0', tad ejat atpakaļ un izvēlaties 'Standarta instalāciju'.$\n$\nVai arī, definējiet citu mapi ar pilnīgu piekļuvi." -${LangFileString} VCINSTERROR "Visual C++ $instArc instalēšana neizdevās anr kļūdas kodu $0.$\n$\nJums vajag lejuplādēt Visual C++ $instArc redistributable package manuāli no http://rainmeter.net/redist$\n$\nNospiediet OK lai izietu." -${LangFileString} DOTNETINSTERROR ".NET $instArc instalēšana neizdevās ar kļūdas kodu $0.$\n$\nJums vajag lejuplādēt .NET $instArc redistributable package manuāli no http://rainmeter.net/redist$\n$\nNospiediet OK lai izietu." -${LangFileString} RAINMETERCLOSEERROR "Neizdevās aizvērt Rainmeter.$\n$\nLūdzu aizveriet Rainmeter programu manuāli un mēģiniet vēlreiz." -${LangFileString} SETTINGSFILEERROR "Uzstādījumu fails (Rainmeter.ini) atrodas instalācijas mapē. Faila atstāšana tur, var radīt problēmas, ja programu izmanto vairāki lietotāji vai jebkurš ar ierobežotām lietotāja privilēģijām.$\n$\nVai jūs vēlaties pārvietot failu uz programas datu mapi?" -${LangFileString} SETTINGSMOVEERROR "Nevar pārvietot failu '$INSTDIR\Rainmeter.ini' uz '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Lūdzu izvēlieties instalēšanas valodu." -${LangFileString} INSTALLOPTIONS "Instalēšanas opcijas" -${LangFileString} INSTALLOPTIONSDESC "Izvēlieties papildus instalēšanas opcijas" -${LangFileString} STANDARDINST "Standarta instalācija (rekomendējam)" -${LangFileString} STANDARDINSTDESC "Instalē programu Rainmeter un lejuplādē nepieciešamos failus." -${LangFileString} PORTABLEINST "Mobīlā instalēcija" -${LangFileString} PORTABLEINSTDESC "Neizvēlieties šo, ja jūs nezinat ko jūs darat. Īsceļi netiks izveidoti un .rmskin extension netiks reģistrēts. Visual C++ un .NET 2.0 faili nepieciešams instalēt manuāli." -${LangFileString} AUTOSTARTUP "Palaist Rainmeter līdz ar sistēmas ieslēgšanu" -${LangFileString} ADDITIONALOPTIONS "Papildu opcijas" -${LangFileString} INSTALL64BIT "64-bit" -${LangFileString} SENDINFORMATION "Send information about your computer" -${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." -${LangFileString} UNSTALLOPTIONS "Atinstalēšanas opcijas" -${LangFileString} UNSTALLOPTIONSDESC "Izvēlieties jebkuras papildu opcijas" -${LangFileString} UNSTALLRAINMETER "Atinstalēt Rainmeter programu" -${LangFileString} UNSTALLSETTINGS "Izdzēst pilnībā visus personiskus uzstādijumus un failus" +${LangFileString} WIN2KERROR "Rainmeter programa ${VER} neatbalsta Windows 2000. Lai izmantotu Rainmeter uz Windows 2000 platformas, lejuplādējiet vecāku Rainmeter 2.0 programas versiju." +${LangFileString} WINXPS2ERROR "Rainmeter programai ${VER} nepieciešams Windows XP Servisa paka 2 (SP2) vai augstāks. Lūdzu uzlabojiet uz jaunāku servisa paku un mēģiniet vēlreiz." +${LangFileString} WIN2003SP1ERROR "Rainmeter programai ${VER} nepieciešams Windows 2003 Servisa paka 1 (SP1) vai augstāks. Lūdzu uzlabojiet uz jaunāku servisa paku un mēģiniet vēlreiz." +${LangFileString} ADMINERROR "Nepieciešamas administratora tiesības." +${LangFileString} LOGONERROR "'Logon service' nav ieslēgts." +${LangFileString} UACERROR "Nevar paaugstināt." +${LangFileString} WRITEERROR "Mobīlai Rainmeter programai jābūt instalētai mapē ar pilnīgu piekļuvi (kā parastam lietotājam).$\nJa jūs vēlaties instalēt Rainmeter programu mapē '$0', tad ejat atpakaļ un izvēlaties 'Standarta instalāciju'.$\n$\nVai arī, definējiet citu mapi ar pilnīgu piekļuvi." +${LangFileString} VCINSTERROR "Visual C++ $instArc instalēšana neizdevās anr kļūdas kodu $0.$\n$\nJums vajag lejuplādēt Visual C++ $instArc redistributable package manuāli no http://rainmeter.net/redist$\n$\nNospiediet OK lai izietu." +${LangFileString} DOTNETINSTERROR ".NET $instArc instalēšana neizdevās ar kļūdas kodu $0.$\n$\nJums vajag lejuplādēt .NET $instArc redistributable package manuāli no http://rainmeter.net/redist$\n$\nNospiediet OK lai izietu." +${LangFileString} RAINMETERCLOSEERROR "Neizdevās aizvērt Rainmeter.$\n$\nLūdzu aizveriet Rainmeter programu manuāli un mēģiniet vēlreiz." +${LangFileString} SETTINGSFILEERROR "Uzstādījumu fails (Rainmeter.ini) atrodas instalācijas mapē. Faila atstāšana tur, var radīt problēmas, ja programu izmanto vairāki lietotāji vai jebkurš ar ierobežotām lietotāja privilēģijām.$\n$\nVai jūs vēlaties pārvietot failu uz programas datu mapi?" +${LangFileString} SETTINGSMOVEERROR "Nevar pārvietot failu '$INSTDIR\Rainmeter.ini' uz '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Lūdzu izvēlieties instalēšanas valodu." +${LangFileString} INSTALLOPTIONS "Instalēšanas opcijas" +${LangFileString} INSTALLOPTIONSDESC "Izvēlieties papildus instalēšanas opcijas" +${LangFileString} STANDARDINST "Standarta instalācija (rekomendējam)" +${LangFileString} STANDARDINSTDESC "Instalē programu Rainmeter un lejuplādē nepieciešamos failus." +${LangFileString} PORTABLEINST "Mobīlā instalēcija" +${LangFileString} PORTABLEINSTDESC "Neizvēlieties šo, ja jūs nezinat ko jūs darat. Īsceļi netiks izveidoti un .rmskin extension netiks reģistrēts. Visual C++ un .NET 2.0 faili nepieciešams instalēt manuāli." +${LangFileString} AUTOSTARTUP "Palaist Rainmeter līdz ar sistēmas ieslēgšanu" +${LangFileString} ADDITIONALOPTIONS "Papildu opcijas" +${LangFileString} INSTALL64BIT "64-bit" +${LangFileString} SENDINFORMATION "Send information about your computer" +${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." +${LangFileString} UNSTALLOPTIONS "Atinstalēšanas opcijas" +${LangFileString} UNSTALLOPTIONSDESC "Izvēlieties jebkuras papildu opcijas" +${LangFileString} UNSTALLRAINMETER "Atinstalēt Rainmeter programu" +${LangFileString} UNSTALLSETTINGS "Izdzēst pilnībā visus personiskus uzstādijumus un failus" ${LangFileString} UNSTALLSETTINGSDESC "(ieskaitot ierīces, tēmas, paplašinājumus, reģistra uzstādijumus, un Start izvēlnes īsceļus)" \ No newline at end of file diff --git a/Language/List b/Language/List index f0936fa8..2735da05 100644 --- a/Language/List +++ b/Language/List @@ -1,32 +1,32 @@ -Arabic,Arabic,1025 -Bulgarian,Bulgarian,1026 -ChineseSimplified,SimpChinese,2052 -ChineseTraditional,TradChinese,1028 -Czech,Czech,1029 -Danish,Danish,1030 -Dutch,Dutch,1043 -English,English,1033 -Finnish,Finnish,1035 -French,French,1036 -German,German,1031 -Greek,Greek,1032 -Hebrew,Hebrew,1037 -Hungarian,Hungarian,1038 -Indonesian,Indonesian,1057 -Italian,Italian,1040 -Japanese,Japanese,1041 -Korean,Korean,1042 -NorwegianBokmal,Norwegian,1044 -Polish,Polish,1045 -PortugueseBrazil,PortugueseBR,1046 -PortuguesePortugal,Portuguese,2070 -Romanian,Romanian,1048 -Russian,Russian,1049 -SerbianCyrillic,Serbian,3098 -SerbianLatin,SerbianLatin,2074 -Slovak,Slovak,1051 -SpanishModern,SpanishInternational,3082 -Swedish,Swedish,1053 -Turkish,Turkish,1055 -Ukrainian,Ukrainian,1058 +Arabic,Arabic,1025 +Bulgarian,Bulgarian,1026 +ChineseSimplified,SimpChinese,2052 +ChineseTraditional,TradChinese,1028 +Czech,Czech,1029 +Danish,Danish,1030 +Dutch,Dutch,1043 +English,English,1033 +Finnish,Finnish,1035 +French,French,1036 +German,German,1031 +Greek,Greek,1032 +Hebrew,Hebrew,1037 +Hungarian,Hungarian,1038 +Indonesian,Indonesian,1057 +Italian,Italian,1040 +Japanese,Japanese,1041 +Korean,Korean,1042 +NorwegianBokmal,Norwegian,1044 +Polish,Polish,1045 +PortugueseBrazil,PortugueseBR,1046 +PortuguesePortugal,Portuguese,2070 +Romanian,Romanian,1048 +Russian,Russian,1049 +SerbianCyrillic,Serbian,3098 +SerbianLatin,SerbianLatin,2074 +Slovak,Slovak,1051 +SpanishModern,SpanishInternational,3082 +Swedish,Swedish,1053 +Turkish,Turkish,1055 +Ukrainian,Ukrainian,1058 Vietnamese,Vietnamese,1066 \ No newline at end of file diff --git a/Language/Lithuanian.nsh b/Language/Lithuanian.nsh index 931c1670..77f66942 100644 --- a/Language/Lithuanian.nsh +++ b/Language/Lithuanian.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "'Rainmeter' ${VER} nepalaiko 'Windows 2000'. Norėdami naudoti 'Rainmeter' 'Windows 2000' systemoje, atsisiųskite senesnę ''Rainmeter'' 2.0 versija." -${LangFileString} WINXPS2ERROR "'Rainmeter' ${VER} reikia 'Windows XP SP2' arba naujesnės. Prašome įdiegti naujausią pakeitimų paketą ir bandyti dar kartą." -${LangFileString} WIN2003SP1ERROR "'Rainmeter' ${VER} reikia 'Windows 2003 SP1' arba naujesnės. Prašome įdiegti naujausią pakeitimų paketą ir bandyti dar kartą." -${LangFileString} ADMINERROR "Turite turėti administratoriaus teises." -${LangFileString} LOGONERROR "Registravimosi tarnyba neveikia." -${LangFileString} UACERROR "Nepavyko sukelti teisių." -${LangFileString} WRITEERROR "Kilnojamas 'Rainmeter' privalo būti įdiegtas į vietą su pilna skaitymo ir rašymo prieiga (normaliam vartotojui).$\nJei norite įdiegti 'Rainmeter' į '$0', grįžkite ir pasirinkite 'Standartinis įdiegimas'.$\n$\nPriešingu atveju, paieškokite kitą vietą su pilna skaitymo ir rašymo prieiga." -${LangFileString} VCINSTERROR "'Visual C++' $instArc diegimas buvo nesėkmingas, klaidos kodas $0.$\n$\nGalbūt norėsite atsisiųsti Visual C++ $instArc platinimo paketą rankiniu būdu šiuo adresu http://rainmeter.net/redist$\n$\nPaspauskite Gerai, kad išeitumėte." -${LangFileString} DOTNETINSTERROR "'.NET' $instArc diegimas buvo nesėkmingas, klaidos kodas $0.$\n$\nGalbūt norėsite atsisiųsti '.NET' $instArc platinimo paketą rankiniu būdu šiuo adresu http://rainmeter.net/redist$\n$\nPaspauskite Gerai, kad išeitumėte." -${LangFileString} RAINMETERCLOSEERROR "Nepavyko uždaryti 'Rainmeter'.$\n$\nPrašome rankiniu būdu uždaryti 'Rainmeter' ir bandyti dar kartą įdiegti." -${LangFileString} SETTINGSFILEERROR "Parametrų failas ('Rainmeter'.ini) yra diegimo aplanke. Palikus jį ten, gali kelti problemų, jei programa yra naudojasi keleta vartotojų arba nors vienas vartotojas su apribotomis teisėmis.$\n$\nAr norite perkelti failą į Programų duomenų aplanką?" -${LangFileString} SETTINGSMOVEERROR "Nepavyko perkelti failą iš '$INSTDIR\Rainmeter.ini' į '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Prašome pasirinkti diegimo kalbą." -${LangFileString} INSTALLOPTIONS "Diegimo Parinktis" -${LangFileString} INSTALLOPTIONSDESC "Pasirinkite papildomas diegimo parinktis" -${LangFileString} STANDARDINST "Standartinis įdiegimas (rekomenduojama)" -${LangFileString} STANDARDINSTDESC "Įdiegia 'Rainmeter' ir atsisiunčia reikalingas bibliotekas." -${LangFileString} PORTABLEINST "Įdiegti kilnojamą" -${LangFileString} PORTABLEINSTDESC "Nežymėkite, nebent žinote ką darote. Nebus sukurtos nuorodos ir .rmskin failo išplėtimas nebus registruotas. 'Visual C++' ir '.NET 2.0' bibliotekas gali tekti įdiegti rankiniu būdu." -${LangFileString} AUTOSTARTUP "Įkelti 'Rainmeter' paleidus operacinę sistemą" -${LangFileString} ADDITIONALOPTIONS "Papildomi parametrai" -${LangFileString} INSTALL64BIT "Įdiegti 64 bitų versiją" -${LangFileString} SENDINFORMATION "Siųsti informaciją apie kompiuterį" -${LangFileString} SENDINFORMATIONDESC "Kokia jūsų kompiuterio Windows versija, kalba, bei apie įrangos pajėgumus informacija bus išsiųsta tik diegimo metu ir bus naudojama Rainmeter tobulinimui. Jokia asmeninė informacija nebus išsiųsta." -${LangFileString} UNSTALLOPTIONS "Pašalinimo parametrai" -${LangFileString} UNSTALLOPTIONSDESC "Pasirinkite bet kokius papildomus parametrus" -${LangFileString} UNSTALLRAINMETER "Pašalinti 'Rainmeter'" -${LangFileString} UNSTALLSETTINGS "Visiškai pašalinkite visus asmeninius parametrus ir failus" +${LangFileString} WIN2KERROR "'Rainmeter' ${VER} nepalaiko 'Windows 2000'. Norėdami naudoti 'Rainmeter' 'Windows 2000' systemoje, atsisiųskite senesnę ''Rainmeter'' 2.0 versija." +${LangFileString} WINXPS2ERROR "'Rainmeter' ${VER} reikia 'Windows XP SP2' arba naujesnės. Prašome įdiegti naujausią pakeitimų paketą ir bandyti dar kartą." +${LangFileString} WIN2003SP1ERROR "'Rainmeter' ${VER} reikia 'Windows 2003 SP1' arba naujesnės. Prašome įdiegti naujausią pakeitimų paketą ir bandyti dar kartą." +${LangFileString} ADMINERROR "Turite turėti administratoriaus teises." +${LangFileString} LOGONERROR "Registravimosi tarnyba neveikia." +${LangFileString} UACERROR "Nepavyko sukelti teisių." +${LangFileString} WRITEERROR "Kilnojamas 'Rainmeter' privalo būti įdiegtas į vietą su pilna skaitymo ir rašymo prieiga (normaliam vartotojui).$\nJei norite įdiegti 'Rainmeter' į '$0', grįžkite ir pasirinkite 'Standartinis įdiegimas'.$\n$\nPriešingu atveju, paieškokite kitą vietą su pilna skaitymo ir rašymo prieiga." +${LangFileString} VCINSTERROR "'Visual C++' $instArc diegimas buvo nesėkmingas, klaidos kodas $0.$\n$\nGalbūt norėsite atsisiųsti Visual C++ $instArc platinimo paketą rankiniu būdu šiuo adresu http://rainmeter.net/redist$\n$\nPaspauskite Gerai, kad išeitumėte." +${LangFileString} DOTNETINSTERROR "'.NET' $instArc diegimas buvo nesėkmingas, klaidos kodas $0.$\n$\nGalbūt norėsite atsisiųsti '.NET' $instArc platinimo paketą rankiniu būdu šiuo adresu http://rainmeter.net/redist$\n$\nPaspauskite Gerai, kad išeitumėte." +${LangFileString} RAINMETERCLOSEERROR "Nepavyko uždaryti 'Rainmeter'.$\n$\nPrašome rankiniu būdu uždaryti 'Rainmeter' ir bandyti dar kartą įdiegti." +${LangFileString} SETTINGSFILEERROR "Parametrų failas ('Rainmeter'.ini) yra diegimo aplanke. Palikus jį ten, gali kelti problemų, jei programa yra naudojasi keleta vartotojų arba nors vienas vartotojas su apribotomis teisėmis.$\n$\nAr norite perkelti failą į Programų duomenų aplanką?" +${LangFileString} SETTINGSMOVEERROR "Nepavyko perkelti failą iš '$INSTDIR\Rainmeter.ini' į '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Prašome pasirinkti diegimo kalbą." +${LangFileString} INSTALLOPTIONS "Diegimo Parinktis" +${LangFileString} INSTALLOPTIONSDESC "Pasirinkite papildomas diegimo parinktis" +${LangFileString} STANDARDINST "Standartinis įdiegimas (rekomenduojama)" +${LangFileString} STANDARDINSTDESC "Įdiegia 'Rainmeter' ir atsisiunčia reikalingas bibliotekas." +${LangFileString} PORTABLEINST "Įdiegti kilnojamą" +${LangFileString} PORTABLEINSTDESC "Nežymėkite, nebent žinote ką darote. Nebus sukurtos nuorodos ir .rmskin failo išplėtimas nebus registruotas. 'Visual C++' ir '.NET 2.0' bibliotekas gali tekti įdiegti rankiniu būdu." +${LangFileString} AUTOSTARTUP "Įkelti 'Rainmeter' paleidus operacinę sistemą" +${LangFileString} ADDITIONALOPTIONS "Papildomi parametrai" +${LangFileString} INSTALL64BIT "Įdiegti 64 bitų versiją" +${LangFileString} SENDINFORMATION "Siųsti informaciją apie kompiuterį" +${LangFileString} SENDINFORMATIONDESC "Kokia jūsų kompiuterio Windows versija, kalba, bei apie įrangos pajėgumus informacija bus išsiųsta tik diegimo metu ir bus naudojama Rainmeter tobulinimui. Jokia asmeninė informacija nebus išsiųsta." +${LangFileString} UNSTALLOPTIONS "Pašalinimo parametrai" +${LangFileString} UNSTALLOPTIONSDESC "Pasirinkite bet kokius papildomus parametrus" +${LangFileString} UNSTALLRAINMETER "Pašalinti 'Rainmeter'" +${LangFileString} UNSTALLSETTINGS "Visiškai pašalinkite visus asmeninius parametrus ir failus" ${LangFileString} UNSTALLSETTINGSDESC "(įskaitant išvaizdas, temos, priedai, registro nustatymus, ir nuorodas iš pagrindinio meniu)" \ No newline at end of file diff --git a/Language/NorwegianBokmal.nsh b/Language/NorwegianBokmal.nsh index 4f302e57..05d7c17f 100644 --- a/Language/NorwegianBokmal.nsh +++ b/Language/NorwegianBokmal.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} støtter ikke Windows 2000. For å benytte Rainmeter på Windows 2000, last ned den eldre versjonen, Rainmeter 2.0." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} krever Windows XP SP2 eller nyere. Vennligst oppdater til siste service pakke og prøv igjen." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} krever Windows 2003 SP1 eller nyere. Vennligst oppdater til siste service pakke og prøv igjen." -${LangFileString} ADMINERROR "Administratortilgang kreves." -${LangFileString} LOGONERROR "Påloggingstjenesten kjører ikke." -${LangFileString} UACERROR "Kunne ikke heve." -${LangFileString} WRITEERROR "Portabel Rainmeter må installeres på en lokasjon med full lese- og skrivetilgang (som en normal bruker).$\nHvis du vil installere Rainmeter til '$0', gå tilbake og velg 'Standard installasjon'.$\n$\nEllers bla til en annen lokasjon med lese- og skrivetilgang." -${LangFileString} VCINSTERROR "Kunne ikke installere Visual C++ $instArc (feilkode $0).$\n$\nDu kan forsøke å laste ned Visual C++ $instArc redistributable package manuelt fra http://rainmeter.net/redist$\n$\nKlikk OK for å avslutte." -${LangFileString} DOTNETINSTERROR "Kunne ikke installere .NET $instArc (feilkode $0).$\n$\nDu kan forsøke å laste ned .NET $instArc redistributable package manuelt fra http://rainmeter.net/redist$\n$\nKlikk OK for å avslutte." -${LangFileString} RAINMETERCLOSEERROR "Kunne ikke avslutte Rainmeter.$\n$\nVennligst avslutt Rainmeter manuelt og prøv igjen." -${LangFileString} SETTINGSFILEERROR "Konfigurasjonsfilen (Rainmeter.ini) er lokalisert i installasjonsmappen. Å beholde filen der kan føre til problemer hvis programmet benyttes av flere brukere eller brukere med begrensede rettigheter.$\n$\nØnsker du å flytte filen til mappen for brukerdata?" -${LangFileString} SETTINGSMOVEERROR "Kunne ikke flytte filen '$INSTDIR\Rainmeter.ini' til '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Velg språk for installasjonsveilederen." -${LangFileString} INSTALLOPTIONS "Innstillinger" -${LangFileString} INSTALLOPTIONSDESC "Velg flere innstillinger" -${LangFileString} STANDARDINST "Standard installasjon (anbefalt)" -${LangFileString} STANDARDINSTDESC "Installerer Rainmeter og laster ned påkrevde biblioteker." -${LangFileString} PORTABLEINST "Portabel installasjon" -${LangFileString} PORTABLEINSTDESC "Ikke velg denne dersom du ikke er helt sikker på hva du gjør. Snarveier blir ikke opprettet og filtypen .rmskin blir ikke registrert. Visual C++ og .NET 2.0 bibliotek må installeres manuelt." -${LangFileString} AUTOSTARTUP "Kjør Rainmeter ved oppstart" -${LangFileString} ADDITIONALOPTIONS "Flere innstillinger" -${LangFileString} INSTALL64BIT "Installer 64-bit versjon" -${LangFileString} SENDINFORMATION "Send informasjon om din datamaskin" -${LangFileString} SENDINFORMATIONDESC "Din datamaskins Windows-versjon, språk og maskinvarefunksjoner vil sendes kun én gang, under installasjon, for å bidra til å forbedre Rainmeter. Ingen personlig informasjon vil bli sendt." -${LangFileString} UNSTALLOPTIONS "Innstillinger for avinstallering" -${LangFileString} UNSTALLOPTIONSDESC "Velg flere innstillinger" -${LangFileString} UNSTALLRAINMETER "Avinstaller Rainmeter" -${LangFileString} UNSTALLSETTINGS "Fjern alle personlige innstillinger og filer" +${LangFileString} WIN2KERROR "Rainmeter ${VER} støtter ikke Windows 2000. For å benytte Rainmeter på Windows 2000, last ned den eldre versjonen, Rainmeter 2.0." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} krever Windows XP SP2 eller nyere. Vennligst oppdater til siste service pakke og prøv igjen." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} krever Windows 2003 SP1 eller nyere. Vennligst oppdater til siste service pakke og prøv igjen." +${LangFileString} ADMINERROR "Administratortilgang kreves." +${LangFileString} LOGONERROR "Påloggingstjenesten kjører ikke." +${LangFileString} UACERROR "Kunne ikke heve." +${LangFileString} WRITEERROR "Portabel Rainmeter må installeres på en lokasjon med full lese- og skrivetilgang (som en normal bruker).$\nHvis du vil installere Rainmeter til '$0', gå tilbake og velg 'Standard installasjon'.$\n$\nEllers bla til en annen lokasjon med lese- og skrivetilgang." +${LangFileString} VCINSTERROR "Kunne ikke installere Visual C++ $instArc (feilkode $0).$\n$\nDu kan forsøke å laste ned Visual C++ $instArc redistributable package manuelt fra http://rainmeter.net/redist$\n$\nKlikk OK for å avslutte." +${LangFileString} DOTNETINSTERROR "Kunne ikke installere .NET $instArc (feilkode $0).$\n$\nDu kan forsøke å laste ned .NET $instArc redistributable package manuelt fra http://rainmeter.net/redist$\n$\nKlikk OK for å avslutte." +${LangFileString} RAINMETERCLOSEERROR "Kunne ikke avslutte Rainmeter.$\n$\nVennligst avslutt Rainmeter manuelt og prøv igjen." +${LangFileString} SETTINGSFILEERROR "Konfigurasjonsfilen (Rainmeter.ini) er lokalisert i installasjonsmappen. Å beholde filen der kan føre til problemer hvis programmet benyttes av flere brukere eller brukere med begrensede rettigheter.$\n$\nØnsker du å flytte filen til mappen for brukerdata?" +${LangFileString} SETTINGSMOVEERROR "Kunne ikke flytte filen '$INSTDIR\Rainmeter.ini' til '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Velg språk for installasjonsveilederen." +${LangFileString} INSTALLOPTIONS "Innstillinger" +${LangFileString} INSTALLOPTIONSDESC "Velg flere innstillinger" +${LangFileString} STANDARDINST "Standard installasjon (anbefalt)" +${LangFileString} STANDARDINSTDESC "Installerer Rainmeter og laster ned påkrevde biblioteker." +${LangFileString} PORTABLEINST "Portabel installasjon" +${LangFileString} PORTABLEINSTDESC "Ikke velg denne dersom du ikke er helt sikker på hva du gjør. Snarveier blir ikke opprettet og filtypen .rmskin blir ikke registrert. Visual C++ og .NET 2.0 bibliotek må installeres manuelt." +${LangFileString} AUTOSTARTUP "Kjør Rainmeter ved oppstart" +${LangFileString} ADDITIONALOPTIONS "Flere innstillinger" +${LangFileString} INSTALL64BIT "Installer 64-bit versjon" +${LangFileString} SENDINFORMATION "Send informasjon om din datamaskin" +${LangFileString} SENDINFORMATIONDESC "Din datamaskins Windows-versjon, språk og maskinvarefunksjoner vil sendes kun én gang, under installasjon, for å bidra til å forbedre Rainmeter. Ingen personlig informasjon vil bli sendt." +${LangFileString} UNSTALLOPTIONS "Innstillinger for avinstallering" +${LangFileString} UNSTALLOPTIONSDESC "Velg flere innstillinger" +${LangFileString} UNSTALLRAINMETER "Avinstaller Rainmeter" +${LangFileString} UNSTALLSETTINGS "Fjern alle personlige innstillinger og filer" ${LangFileString} UNSTALLSETTINGSDESC "(inkludert skins, temaer, tillegg, registerinnstillinger, og Startmenyvalg)" \ No newline at end of file diff --git a/Language/Polish.nsh b/Language/Polish.nsh index ee2ff1c6..cd595a52 100644 --- a/Language/Polish.nsh +++ b/Language/Polish.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} nie wspiera Windows 2000. W celu użycia na Windows 2000, pobierz starszą wersję Rainmeter 2.0." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} wymaga wersji Windows XP SP2 lub wyższej. Pobierz ostatnią wersję pakietu aktualizującego i spróbuj ponownie." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} wymaga wersji Windows 2003 SP1 lub wyższej. Pobierz ostatnią wersję pakietu aktualizującego i spróbuj ponownie." -${LangFileString} ADMINERROR "Potrzebne uprawnienia administratora." -${LangFileString} LOGONERROR "Usługa logowania nie uruchomiona." -${LangFileString} UACERROR "Nie można podnieść." -${LangFileString} WRITEERROR "Przenośny Rainmeter musi być zainstalowany w lokalizacji z pełnymi uprawnieniami do odczytu i zapisu (jako zwykły użytkownik).$\nJeżeli chcesz zapisać Rainmeter w '$0', wróć i wybierz 'Instalacja standardowa'.$\n$\nW przeciwnym wypadku, wybierz inną lokalizację z pełnymi uprawnieniami do odczytu i zapisu." -${LangFileString} VCINSTERROR "Instalacja Visual C++ $instArc nieudana. Kod błędu $0.$\n$\nMożesz spróbować pobrać pakiet Visual C++ $instArc ręcznie z http://rainmeter.net/redist$\n$\nNaciśnij OK żeby wyjść." -${LangFileString} DOTNETINSTERROR "Instalacja .NET $instArc nieudana. Kod błędu $0.$\n$\nMożesz spróbować pobrać pakiet .NET $instArc ręcznie z http://rainmeter.net/redist$\n$\nNaciśnij OK żeby wyjść." -${LangFileString} RAINMETERCLOSEERROR "Nie udało się zamknąć Rainmeter.$\n$\nZamknij Rainmeter ręcznie i spróbuj ponownie." -${LangFileString} SETTINGSFILEERROR "Plik konfiguracyjny (Rainmeter.ini) jest umieszczony w folderze instalacyjnym. Trzymanie go w tej lokalizacji może powodować problemy jeżeli z aplikacji korzysta wielu użytkowników lub gdy któryś z nich ma ograniczone uprawnienia.$\n$\nCzy chcesz przenieść plik do folderu danych aplikacji?" -${LangFileString} SETTINGSMOVEERROR "Nie można przenieść pliku '$INSTDIR\Rainmeter.ini' do '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Proszę wybrać język instalacji." -${LangFileString} INSTALLOPTIONS "Opcje instalacji" -${LangFileString} INSTALLOPTIONSDESC "Wybierz dodatkowe opcje instalacji" -${LangFileString} STANDARDINST "Standardowa instalacja (zalecane)" -${LangFileString} STANDARDINSTDESC "Instaluje Rainmeter i pobiera wymagane biblioteki." -${LangFileString} PORTABLEINST "Instalacja przenośna" -${LangFileString} PORTABLEINSTDESC "Nie zaznaczaj tego jeżeli nie wiesz co robisz. Skróty nie zostaną utworzone a rozszerzenie .rmskin nie będzie zarejestrowane. Może być konieczne ręczne zainstalowanie bibliotek Visual C++ oraz .NET 2.0." -${LangFileString} AUTOSTARTUP "Automatycznie uruchamiaj Rainmeter wraz z Windows" -${LangFileString} ADDITIONALOPTIONS "Dodatkowe opcje" -${LangFileString} INSTALL64BIT "64-bit" -${LangFileString} SENDINFORMATION "Wyślij informację na temat swojego komputera" -${LangFileString} SENDINFORMATIONDESC "Wersja Windows w Twoim komputerze, język oraz możliwości sprzętowe będą zaraportowane jednorazowo podczas instalacji dla ulepszenia działania programu Rainmeter. Żadne informacje osobiste nie będą wysyłane na serwer." -${LangFileString} UNSTALLOPTIONS "Opcje odinstalowania" -${LangFileString} UNSTALLOPTIONSDESC "Wybierz dodatkowe opcje" -${LangFileString} UNSTALLRAINMETER "Odinstaluj Rainmeter" -${LangFileString} UNSTALLSETTINGS "Całkowicie usuń wszystkie osobiste ustawienia i pliki" +${LangFileString} WIN2KERROR "Rainmeter ${VER} nie wspiera Windows 2000. W celu użycia na Windows 2000, pobierz starszą wersję Rainmeter 2.0." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} wymaga wersji Windows XP SP2 lub wyższej. Pobierz ostatnią wersję pakietu aktualizującego i spróbuj ponownie." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} wymaga wersji Windows 2003 SP1 lub wyższej. Pobierz ostatnią wersję pakietu aktualizującego i spróbuj ponownie." +${LangFileString} ADMINERROR "Potrzebne uprawnienia administratora." +${LangFileString} LOGONERROR "Usługa logowania nie uruchomiona." +${LangFileString} UACERROR "Nie można podnieść." +${LangFileString} WRITEERROR "Przenośny Rainmeter musi być zainstalowany w lokalizacji z pełnymi uprawnieniami do odczytu i zapisu (jako zwykły użytkownik).$\nJeżeli chcesz zapisać Rainmeter w '$0', wróć i wybierz 'Instalacja standardowa'.$\n$\nW przeciwnym wypadku, wybierz inną lokalizację z pełnymi uprawnieniami do odczytu i zapisu." +${LangFileString} VCINSTERROR "Instalacja Visual C++ $instArc nieudana. Kod błędu $0.$\n$\nMożesz spróbować pobrać pakiet Visual C++ $instArc ręcznie z http://rainmeter.net/redist$\n$\nNaciśnij OK żeby wyjść." +${LangFileString} DOTNETINSTERROR "Instalacja .NET $instArc nieudana. Kod błędu $0.$\n$\nMożesz spróbować pobrać pakiet .NET $instArc ręcznie z http://rainmeter.net/redist$\n$\nNaciśnij OK żeby wyjść." +${LangFileString} RAINMETERCLOSEERROR "Nie udało się zamknąć Rainmeter.$\n$\nZamknij Rainmeter ręcznie i spróbuj ponownie." +${LangFileString} SETTINGSFILEERROR "Plik konfiguracyjny (Rainmeter.ini) jest umieszczony w folderze instalacyjnym. Trzymanie go w tej lokalizacji może powodować problemy jeżeli z aplikacji korzysta wielu użytkowników lub gdy któryś z nich ma ograniczone uprawnienia.$\n$\nCzy chcesz przenieść plik do folderu danych aplikacji?" +${LangFileString} SETTINGSMOVEERROR "Nie można przenieść pliku '$INSTDIR\Rainmeter.ini' do '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Proszę wybrać język instalacji." +${LangFileString} INSTALLOPTIONS "Opcje instalacji" +${LangFileString} INSTALLOPTIONSDESC "Wybierz dodatkowe opcje instalacji" +${LangFileString} STANDARDINST "Standardowa instalacja (zalecane)" +${LangFileString} STANDARDINSTDESC "Instaluje Rainmeter i pobiera wymagane biblioteki." +${LangFileString} PORTABLEINST "Instalacja przenośna" +${LangFileString} PORTABLEINSTDESC "Nie zaznaczaj tego jeżeli nie wiesz co robisz. Skróty nie zostaną utworzone a rozszerzenie .rmskin nie będzie zarejestrowane. Może być konieczne ręczne zainstalowanie bibliotek Visual C++ oraz .NET 2.0." +${LangFileString} AUTOSTARTUP "Automatycznie uruchamiaj Rainmeter wraz z Windows" +${LangFileString} ADDITIONALOPTIONS "Dodatkowe opcje" +${LangFileString} INSTALL64BIT "64-bit" +${LangFileString} SENDINFORMATION "Wyślij informację na temat swojego komputera" +${LangFileString} SENDINFORMATIONDESC "Wersja Windows w Twoim komputerze, język oraz możliwości sprzętowe będą zaraportowane jednorazowo podczas instalacji dla ulepszenia działania programu Rainmeter. Żadne informacje osobiste nie będą wysyłane na serwer." +${LangFileString} UNSTALLOPTIONS "Opcje odinstalowania" +${LangFileString} UNSTALLOPTIONSDESC "Wybierz dodatkowe opcje" +${LangFileString} UNSTALLRAINMETER "Odinstaluj Rainmeter" +${LangFileString} UNSTALLSETTINGS "Całkowicie usuń wszystkie osobiste ustawienia i pliki" ${LangFileString} UNSTALLSETTINGSDESC "(wraz ze skórkami, tematami, dodatkami, ustawieniami rejestru i wpisami menu Start)" \ No newline at end of file diff --git a/Language/PortugueseBrazil.nsh b/Language/PortugueseBrazil.nsh index 3546c7f1..66b1463d 100644 --- a/Language/PortugueseBrazil.nsh +++ b/Language/PortugueseBrazil.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} não suporta Windows 2000. Para usar o Rainmeter no seu computador, faça download da versão mais antiga do Rainmeter 2.0." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} requer Windows XP SP2 ou mais recente. Por favor atualize o Service Pack mais recente e tente novamente." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} requer Windows 2003 SP1 ou mais recente. Por favor atualize o Service Pack e tente novamente." -${LangFileString} ADMINERROR "Direitos administrativos são necessários." -${LangFileString} LOGONERROR "Serviço de login não está sendo executado." -${LangFileString} UACERROR "Não foi possível elevar." -${LangFileString} WRITEERROR "Rainmeter Portable deve ser instalado em um local com total acesso a criação e edição de arquivos (como usuário comum). $\nSe você deseja instalar o Rainmeter em '$0', volte e selecione 'Instalação Padrão'. $\n$\nOu procure outro local com total acesso a criação e edição de arquivos." -${LangFileString} VCINSTERROR "Visual C++$instArc falha na instalação, código de erro $0.$\n$\nVocê pode desejar baixar o Visual C++ $instArc manualmente em http://rainmeter.net/redist$\n$\nPressione OK para sair." -${LangFileString} DOTNETINSTERROR ".NET $instArc falha na instalação, código de erro $0.$\n$\nVocê pode desejar baixar o .NET $instArc manualmente em http://rainmeter.net/redist$\n$\nPressione OK para sair." -${LangFileString} RAINMETERCLOSEERROR "Falha ao encerrar o Rainmeter. $\n$\nPor favor, feche o Rainmeter manualmente e tente novamente." -${LangFileString} SETTINGSFILEERROR "O arquivo de configurações (Rainmeter.ini) está localizado na pasta de instalação. Mantê-lo nesta pasta pode causar problemas se o aplicativo for usado por vários usuários ou por algum usuário com privilégios restritos.$\n$\nVocê deseja mover o arquivo para a pasta de dados do aplicativo?" -${LangFileString} SETTINGSMOVEERROR "Não foi possível mover o arquivo '$INSTDIR\Rainmeter.ini' para '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Por favor, selecione o idioma do instalador." -${LangFileString} INSTALLOPTIONS "Opções de Instalação" -${LangFileString} INSTALLOPTIONSDESC "Selecione opções de instalação adcionais" -${LangFileString} STANDARDINST "Instalação padrão (recomendável)" -${LangFileString} STANDARDINSTDESC "Instala o Rainmeter e baixa bibliotecas necessárias." -${LangFileString} PORTABLEINST "Instalação Portable" -${LangFileString} PORTABLEINSTDESC "Não selecione se não souber o que está fazendo. Atalhos não serão criados e a extensão .rmskin não será registrada. As bibliotecas Visual C++ e .NET 2.0 provavelmente terão de ser instaladas manualmente." -${LangFileString} AUTOSTARTUP "Iniciar com o Windows" -${LangFileString} ADDITIONALOPTIONS "Opções Adicionais" -${LangFileString} INSTALL64BIT "Instalar versão 64-bits" -${LangFileString} SENDINFORMATION "Enviar informações sobre o computador" -${LangFileString} SENDINFORMATIONDESC "A versão instalada do Windows, idioma e capacidades de hardware serão enviadas uma única vez durante a instalação, para melhorar o Rainmeter. Nenhuma informação pessoal será enviada." -${LangFileString} UNSTALLOPTIONS "Opções de desinstalação" -${LangFileString} UNSTALLOPTIONSDESC "Selecione opções adcionais" -${LangFileString} UNSTALLRAINMETER "Desistalar o Rainmeter" -${LangFileString} UNSTALLSETTINGS "Remover completamente arquivos e configurações pessoais" +${LangFileString} WIN2KERROR "Rainmeter ${VER} não suporta Windows 2000. Para usar o Rainmeter no seu computador, faça download da versão mais antiga do Rainmeter 2.0." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} requer Windows XP SP2 ou mais recente. Por favor atualize o Service Pack mais recente e tente novamente." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} requer Windows 2003 SP1 ou mais recente. Por favor atualize o Service Pack e tente novamente." +${LangFileString} ADMINERROR "Direitos administrativos são necessários." +${LangFileString} LOGONERROR "Serviço de login não está sendo executado." +${LangFileString} UACERROR "Não foi possível elevar." +${LangFileString} WRITEERROR "Rainmeter Portable deve ser instalado em um local com total acesso a criação e edição de arquivos (como usuário comum). $\nSe você deseja instalar o Rainmeter em '$0', volte e selecione 'Instalação Padrão'. $\n$\nOu procure outro local com total acesso a criação e edição de arquivos." +${LangFileString} VCINSTERROR "Visual C++$instArc falha na instalação, código de erro $0.$\n$\nVocê pode desejar baixar o Visual C++ $instArc manualmente em http://rainmeter.net/redist$\n$\nPressione OK para sair." +${LangFileString} DOTNETINSTERROR ".NET $instArc falha na instalação, código de erro $0.$\n$\nVocê pode desejar baixar o .NET $instArc manualmente em http://rainmeter.net/redist$\n$\nPressione OK para sair." +${LangFileString} RAINMETERCLOSEERROR "Falha ao encerrar o Rainmeter. $\n$\nPor favor, feche o Rainmeter manualmente e tente novamente." +${LangFileString} SETTINGSFILEERROR "O arquivo de configurações (Rainmeter.ini) está localizado na pasta de instalação. Mantê-lo nesta pasta pode causar problemas se o aplicativo for usado por vários usuários ou por algum usuário com privilégios restritos.$\n$\nVocê deseja mover o arquivo para a pasta de dados do aplicativo?" +${LangFileString} SETTINGSMOVEERROR "Não foi possível mover o arquivo '$INSTDIR\Rainmeter.ini' para '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Por favor, selecione o idioma do instalador." +${LangFileString} INSTALLOPTIONS "Opções de Instalação" +${LangFileString} INSTALLOPTIONSDESC "Selecione opções de instalação adcionais" +${LangFileString} STANDARDINST "Instalação padrão (recomendável)" +${LangFileString} STANDARDINSTDESC "Instala o Rainmeter e baixa bibliotecas necessárias." +${LangFileString} PORTABLEINST "Instalação Portable" +${LangFileString} PORTABLEINSTDESC "Não selecione se não souber o que está fazendo. Atalhos não serão criados e a extensão .rmskin não será registrada. As bibliotecas Visual C++ e .NET 2.0 provavelmente terão de ser instaladas manualmente." +${LangFileString} AUTOSTARTUP "Iniciar com o Windows" +${LangFileString} ADDITIONALOPTIONS "Opções Adicionais" +${LangFileString} INSTALL64BIT "Instalar versão 64-bits" +${LangFileString} SENDINFORMATION "Enviar informações sobre o computador" +${LangFileString} SENDINFORMATIONDESC "A versão instalada do Windows, idioma e capacidades de hardware serão enviadas uma única vez durante a instalação, para melhorar o Rainmeter. Nenhuma informação pessoal será enviada." +${LangFileString} UNSTALLOPTIONS "Opções de desinstalação" +${LangFileString} UNSTALLOPTIONSDESC "Selecione opções adcionais" +${LangFileString} UNSTALLRAINMETER "Desistalar o Rainmeter" +${LangFileString} UNSTALLSETTINGS "Remover completamente arquivos e configurações pessoais" ${LangFileString} UNSTALLSETTINGSDESC "(incluindo skins, temas, addons, opções de registro, e itens do menu Iniciar)" \ No newline at end of file diff --git a/Language/PortuguesePortugal.nsh b/Language/PortuguesePortugal.nsh index 40c54755..31981726 100644 --- a/Language/PortuguesePortugal.nsh +++ b/Language/PortuguesePortugal.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} não suporta o Windows 2000. Para usar o Rainmeter no Windows 2000, faz download do Rainmeter 2.0." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} requer o Windows XP SP2 ou melhor. Por favor atualiza para o último Service Pack e tenta outra vez." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} requer o Windows 2003 SP1 ou melhor. Por favor atualiza para o último Service Pack e tenta outra vez." -${LangFileString} ADMINERROR "Direitos de administração necessários." -${LangFileString} LOGONERROR "O serviço de inicio de sessão não está a ser executado." -${LangFileString} UACERROR "Falha a obter direitos de instalação." -${LangFileString} WRITEERROR "A versão portátil do Rainmeter tem de ser instalada num local com direitos completos de escrita e leitura sem necessidade de direitos de administrador.$\nSe instalaste o Rainmeter em em '$0', volta atrás e seleciona 'Instalação Normal'.$\n$\nCaso contrário, escolhe outro local que respeite o direitos requeridos." -${LangFileString} VCINSTERROR "A instalação do Visual C++ $instArc falhou com o código de erro $0.$\n$\nÉ melhor fazer download manualmente do Visual C++ $instArc em http://rainmeter.net/redist$\n$\nPressiona ok para sair." -${LangFileString} DOTNETINSTERROR "A instalação do .NET $instArc falhou com o código de erro $0.$\n$\nÉ melhor fazer download manualmente do .NET $instArc em http://rainmeter.net/redist$\n$\nPressiona ok para sair." -${LangFileString} RAINMETERCLOSEERROR "Não foi possível fechar o Rainmeter.$\n$\nPor favor, fecha o Rainmeter manualmente e tenta outra vez." -${LangFileString} SETTINGSFILEERROR "O ficheiro de configurações (Rainmeter.ini) está localizado no local de instalação. Mantê-lo lá pode causar problemas se a aplicação for usada por múltiplos utilizadores ou por alguém com privilégios de utilizador restritos.$\n$\nQueres mover o ficheiro para a pasta application data?" -${LangFileString} SETTINGSMOVEERROR "Não foi possível mover o ficheiro '$INSTDIR\Rainmeter.ini' para '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Seleciona a linguagem a ser utilizada na instalação." -${LangFileString} INSTALLOPTIONS "Opções de instalação" -${LangFileString} INSTALLOPTIONSDESC "Seleciona opções adicionais de instalação" -${LangFileString} STANDARDINST "Instalação normal (recomendado)" -${LangFileString} STANDARDINSTDESC "Instala o Rainmeter e faz download das bases de dados necessárias." -${LangFileString} PORTABLEINST "Instalação portátil" -${LangFileString} PORTABLEINSTDESC "Não seleciones isto a não ser que saibas o que estás a fazer. Os atalhos não serão criados e a extensão .rmskin não vai será registada. As bases de dados Visual C++ e .NET 2.0 terão de ser manualmente instaladas." -${LangFileString} AUTOSTARTUP "Ligar o Rainmeter ao ligar o computador" -${LangFileString} ADDITIONALOPTIONS "Opções adicionais" -${LangFileString} INSTALL64BIT "Instalar versão 64-bits" -${LangFileString} SENDINFORMATION "Enviar informações sobre este computador" -${LangFileString} SENDINFORMATIONDESC "A versão do Windows do seu computador e as capacidades do seu hardware serão enviadas uma vez durante a instalação do para melhorar o Rainmeter. Nenhuma informação pessoal será enviada." -${LangFileString} UNSTALLOPTIONS "Opções de desinstalação" -${LangFileString} UNSTALLOPTIONSDESC "Selecionar opções adicionais" -${LangFileString} UNSTALLRAINMETER "Desinstalar Rainmeter" -${LangFileString} UNSTALLSETTINGS "Remover completamente todas a configurações e ficheiros" +${LangFileString} WIN2KERROR "Rainmeter ${VER} não suporta o Windows 2000. Para usar o Rainmeter no Windows 2000, faz download do Rainmeter 2.0." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} requer o Windows XP SP2 ou melhor. Por favor atualiza para o último Service Pack e tenta outra vez." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} requer o Windows 2003 SP1 ou melhor. Por favor atualiza para o último Service Pack e tenta outra vez." +${LangFileString} ADMINERROR "Direitos de administração necessários." +${LangFileString} LOGONERROR "O serviço de inicio de sessão não está a ser executado." +${LangFileString} UACERROR "Falha a obter direitos de instalação." +${LangFileString} WRITEERROR "A versão portátil do Rainmeter tem de ser instalada num local com direitos completos de escrita e leitura sem necessidade de direitos de administrador.$\nSe instalaste o Rainmeter em em '$0', volta atrás e seleciona 'Instalação Normal'.$\n$\nCaso contrário, escolhe outro local que respeite o direitos requeridos." +${LangFileString} VCINSTERROR "A instalação do Visual C++ $instArc falhou com o código de erro $0.$\n$\nÉ melhor fazer download manualmente do Visual C++ $instArc em http://rainmeter.net/redist$\n$\nPressiona ok para sair." +${LangFileString} DOTNETINSTERROR "A instalação do .NET $instArc falhou com o código de erro $0.$\n$\nÉ melhor fazer download manualmente do .NET $instArc em http://rainmeter.net/redist$\n$\nPressiona ok para sair." +${LangFileString} RAINMETERCLOSEERROR "Não foi possível fechar o Rainmeter.$\n$\nPor favor, fecha o Rainmeter manualmente e tenta outra vez." +${LangFileString} SETTINGSFILEERROR "O ficheiro de configurações (Rainmeter.ini) está localizado no local de instalação. Mantê-lo lá pode causar problemas se a aplicação for usada por múltiplos utilizadores ou por alguém com privilégios de utilizador restritos.$\n$\nQueres mover o ficheiro para a pasta application data?" +${LangFileString} SETTINGSMOVEERROR "Não foi possível mover o ficheiro '$INSTDIR\Rainmeter.ini' para '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Seleciona a linguagem a ser utilizada na instalação." +${LangFileString} INSTALLOPTIONS "Opções de instalação" +${LangFileString} INSTALLOPTIONSDESC "Seleciona opções adicionais de instalação" +${LangFileString} STANDARDINST "Instalação normal (recomendado)" +${LangFileString} STANDARDINSTDESC "Instala o Rainmeter e faz download das bases de dados necessárias." +${LangFileString} PORTABLEINST "Instalação portátil" +${LangFileString} PORTABLEINSTDESC "Não seleciones isto a não ser que saibas o que estás a fazer. Os atalhos não serão criados e a extensão .rmskin não vai será registada. As bases de dados Visual C++ e .NET 2.0 terão de ser manualmente instaladas." +${LangFileString} AUTOSTARTUP "Ligar o Rainmeter ao ligar o computador" +${LangFileString} ADDITIONALOPTIONS "Opções adicionais" +${LangFileString} INSTALL64BIT "Instalar versão 64-bits" +${LangFileString} SENDINFORMATION "Enviar informações sobre este computador" +${LangFileString} SENDINFORMATIONDESC "A versão do Windows do seu computador e as capacidades do seu hardware serão enviadas uma vez durante a instalação do para melhorar o Rainmeter. Nenhuma informação pessoal será enviada." +${LangFileString} UNSTALLOPTIONS "Opções de desinstalação" +${LangFileString} UNSTALLOPTIONSDESC "Selecionar opções adicionais" +${LangFileString} UNSTALLRAINMETER "Desinstalar Rainmeter" +${LangFileString} UNSTALLSETTINGS "Remover completamente todas a configurações e ficheiros" ${LangFileString} UNSTALLSETTINGSDESC "(incluíndo skins, temas, addons, opções do registo e ficheiros do Menu Iniciar)" \ No newline at end of file diff --git a/Language/Resource.rc b/Language/Resource.rc index 2221fad8..b28c0761 100644 --- a/Language/Resource.rc +++ b/Language/Resource.rc @@ -1,173 +1,173 @@ -#include -#include "../Library/resource.h" -#include "../Version.h" - -#ifdef LANGUAGE_RTL -#define DIALOG_EXSTYLE_FLAGS WS_EX_APPWINDOW | WS_EX_CONTROLPARENT | WS_EX_LAYOUTRTL -#define STR_ISRTL "1" -#else -#define DIALOG_EXSTYLE_FLAGS WS_EX_APPWINDOW | WS_EX_CONTROLPARENT -#define STR_ISRTL "0" -#endif - - -#define MAKESTRING2(num) #num -#define MAKESTRING(num) MAKESTRING2(num) - -#define STR_NUM_BUTTONWIDTH MAKESTRING(NUM_BUTTONWIDTH) -#define STR_NUM_LABELWIDTH MAKESTRING(NUM_LABELWIDTH) - -LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE -{ - ID_STR_NUM_BUTTONWIDTH, STR_NUM_BUTTONWIDTH - ID_STR_NUM_LABELWIDTH, STR_NUM_LABELWIDTH - ID_STR_ISRTL, STR_ISRTL - ID_STR_UPDATEAVAILABLE, STR_UPDATEAVAILABLE - ID_STR_MANAGE, STR_MANAGE - ID_STR_ABOUT, STR_ABOUT - ID_STR_HELP, STR_HELP - ID_STR_SKINS, STR_SKINS - ID_STR_NOSKINS, STR_NOSKINS - ID_STR_OPENFOLDER, STR_OPENFOLDER - ID_STR_DISABLEDRAGGING, STR_DISABLEDRAGGING - ID_STR_THEMES, STR_THEMES - ID_STR_NOTHEMES, STR_NOTHEMES - ID_STR_EDITSETTINGS, STR_EDITSETTINGS - ID_STR_REFRESHALL, STR_REFRESHALL - ID_STR_LOGGING, STR_LOGGING - ID_STR_SHOWLOGFILE, STR_SHOWLOGFILE - ID_STR_STARTLOGGING, STR_STARTLOGGING - ID_STR_STOPLOGGING, STR_STOPLOGGING - ID_STR_DELETELOGFILE, STR_DELETELOGFILE - ID_STR_DEBUGMODE, STR_DEBUGMODE - ID_STR_EXIT, STR_EXIT - ID_STR_VARIANTS, STR_VARIANTS - ID_STR_SETTINGS, STR_SETTINGS - ID_STR_POSITION, STR_POSITION - ID_STR_DISPLAYMONITOR, STR_DISPLAYMONITOR - ID_STR_USEDEFAULTMONITOR, STR_USEDEFAULTMONITOR - ID_STR_VIRTUALSCREEN, STR_VIRTUALSCREEN - ID_STR_AUTOSELECTMONITOR, STR_AUTOSELECTMONITOR - ID_STR_STAYTOPMOST, STR_STAYTOPMOST - ID_STR_TOPMOST, STR_TOPMOST - ID_STR_NORMAL, STR_NORMAL - ID_STR_BOTTOM, STR_BOTTOM - ID_STR_ONDESKTOP, STR_ONDESKTOP - ID_STR_FROMRIGHT, STR_FROMRIGHT - ID_STR_FROMBOTTOM, STR_FROMBOTTOM - ID_STR_XASPERCENTAGE, STR_XASPERCENTAGE - ID_STR_YASPERCENTAGE, STR_YASPERCENTAGE - ID_STR_TRANSPARENCY, STR_TRANSPARENCY - ID_STR_0PERCENT, "0%" - ID_STR_10PERCENT, "10%" - ID_STR_20PERCENT, "20%" - ID_STR_30PERCENT, "30%" - ID_STR_40PERCENT, "40%" - ID_STR_50PERCENT, "50%" - ID_STR_60PERCENT, "60%" - ID_STR_70PERCENT, "70%" - ID_STR_80PERCENT, "80%" - ID_STR_90PERCENT, "90%" - ID_STR_FADEIN, STR_FADEIN - ID_STR_FADEOUT, STR_FADEOUT - ID_STR_HIDEONMOUSEOVER, STR_HIDEONMOUSEOVER - ID_STR_DRAGGABLE, STR_DRAGGABLE - ID_STR_SAVEPOSITION, STR_SAVEPOSITION - ID_STR_SNAPTOEDGES, STR_SNAPTOEDGES - ID_STR_CLICKTHROUGH, STR_CLICKTHROUGH - ID_STR_KEEPONSCREEN, STR_KEEPONSCREEN - ID_STR_MANAGESKIN, STR_MANAGESKIN - ID_STR_EDITSKIN, STR_EDITSKIN - ID_STR_REFRESHSKIN, STR_REFRESHSKIN - ID_STR_UNLOADSKIN, STR_UNLOADSKIN - ID_STR_CLOSE, STR_CLOSE - ID_STR_ABOUTRAINMETER, STR_ABOUTRAINMETER - ID_STR_LOG, STR_LOG - ID_STR_MEASURES, STR_MEASURES - ID_STR_VARIABLES, STR_VARIABLES - ID_STR_PLUGINS, STR_PLUGINS - ID_STR_VERSION, STR_VERSION - ID_STR_TYPE, STR_TYPE - ID_STR_TIME, STR_TIME - ID_STR_MESSAGE, STR_MESSAGE - ID_STR_NAME, STR_NAME - ID_STR_RANGE, STR_RANGE - ID_STR_VALUE, STR_VALUE - ID_STR_AUTHOR, STR_AUTHOR - ID_STR_ERROR, STR_ERROR - ID_STR_WARNING, STR_WARNING - ID_STR_NOTICE, STR_NOTICE - ID_STR_DEBUG, STR_DEBUG - ID_STR_GETLATESTVERSION, STR_GETLATESTVERSION - ID_STR_COPYRIGHTNOTICE, STR_COPYRIGHTNOTICE - ID_STR_COPYTOCLIPBOARD, STR_COPYTOCLIPBOARD - ID_STR_MANAGERAINMETER, STR_MANAGERAINMETER - ID_STR_ACTIVESKINS, STR_ACTIVESKINS - ID_STR_EXPAND, STR_EXPAND - ID_STR_COLLAPSE, STR_COLLAPSE - ID_STR_OPENLOG, STR_OPENLOG - ID_STR_LOAD, STR_LOAD - ID_STR_UNLOAD, STR_UNLOAD - ID_STR_REFRESH, STR_REFRESH - ID_STR_EDIT, STR_EDIT - ID_STR_AUTHORSC, STR_AUTHORSC - ID_STR_VERSIONSC, STR_VERSIONSC - ID_STR_LICENSESC, STR_LICENSESC - ID_STR_INFORMATIONSC, STR_INFORMATIONSC - ID_STR_ADDMETADATA, STR_ADDMETADATA - ID_STR_COORDINATESSC, STR_COORDINATESSC - ID_STR_POSITIONSC, STR_POSITIONSC - ID_STR_LOADORDERSC, STR_LOADORDERSC - ID_STR_TRANSPARENCYSC, STR_TRANSPARENCYSC - ID_STR_ONHOVERSC, STR_ONHOVERSC - ID_STR_DONOTHING, STR_DONOTHING - ID_STR_HIDE, STR_HIDE - ID_STR_SAVENEWTHEME, STR_SAVENEWTHEME - ID_STR_THEMEDESCRIPTION, STR_THEMEDESCRIPTION - ID_STR_SAVEASEMPTYTHEME, STR_SAVEASEMPTYTHEME - ID_STR_EXCLUDEUNUSEDSKINS, STR_EXCLUDEUNUSEDSKINS - ID_STR_INCLUDEWALLPAPER, STR_INCLUDEWALLPAPER - ID_STR_NAMESC, STR_NAMESC - ID_STR_SAVE, STR_SAVE - ID_STR_SAVEDTHEMES, STR_SAVEDTHEMES - ID_STR_DELETE, STR_DELETE -// ID_STR_BACKUP, STR_BACKUP -// ID_STR_BACKUPDESCRIPTION, STR_BACKUPDESCRIPTION -// ID_STR_BACKUPE, STR_BACKUPE - ID_STR_LANGUAGESC, STR_LANGUAGESC - ID_STR_GENERAL, STR_GENERAL - ID_STR_CHECKFORUPDATES, STR_CHECKFORUPDATES - ID_STR_RESETSTATISTICS, STR_RESETSTATISTICS - ID_STR_LOGTOFILE, STR_LOGTOFILE - ID_STR_SETTINGSNOTWRITABLE, STR_SETTINGSNOTWRITABLE - ID_STR_SETTINGSMOVEFILE, STR_SETTINGSMOVEFILE - ID_STR_SETTINGSREADONLY, STR_SETTINGSREADONLY - ID_STR_THEMEALREADYEXISTS, STR_THEMEALREADYEXISTS - ID_STR_THEMESAVEFAIL, STR_THEMESAVEFAIL - ID_STR_THEMEDELETE, STR_THEMEDELETE - ID_STR_LOGFILECREATEFAIL, STR_LOGFILECREATEFAIL - ID_STR_LOGFILEDELETE, STR_LOGFILEDELETE - ID_STR_NOAVAILABLESKINS, STR_NOAVAILABLESKINS - ID_STR_UNABLETOACTIVATESKIN, STR_UNABLETOACTIVATESKIN - ID_STR_UNABLETOREFRESHSKIN, STR_UNABLETOREFRESHSKIN - ID_STR_NEWVERSIONREQUIRED, STR_NEWVERSIONREQUIRED - ID_STR_NOMETERSINSKIN, STR_NOMETERSINSKIN - ID_STR_INCLUDEINFINITELOOP, STR_INCLUDEINFINITELOOP - ID_STR_WELCOME, STR_WELCOME - ID_STR_CLICKTOMANAGE, STR_CLICKTOMANAGE - ID_STR_CLICKTODOWNLOAD, STR_CLICKTODOWNLOAD - ID_STR_CREATERMSKINPACKAGE, STR_CREATERMSKIN - ID_STR_EDITORSC, STR_EDITORSC - ID_STR_ELLIPSIS, "..." - ID_STR_SHOWNOTIFICATIONAREAICON, STR_SHOWNOTIFAREAICON - ID_STR_SOURCE, STR_SOURCE - ID_STR_USED2D, STR_USED2D - ID_STR_CLEAR, STR_CLEAR -} +#include +#include "../Library/resource.h" +#include "../Version.h" + +#ifdef LANGUAGE_RTL +#define DIALOG_EXSTYLE_FLAGS WS_EX_APPWINDOW | WS_EX_CONTROLPARENT | WS_EX_LAYOUTRTL +#define STR_ISRTL "1" +#else +#define DIALOG_EXSTYLE_FLAGS WS_EX_APPWINDOW | WS_EX_CONTROLPARENT +#define STR_ISRTL "0" +#endif + + +#define MAKESTRING2(num) #num +#define MAKESTRING(num) MAKESTRING2(num) + +#define STR_NUM_BUTTONWIDTH MAKESTRING(NUM_BUTTONWIDTH) +#define STR_NUM_LABELWIDTH MAKESTRING(NUM_LABELWIDTH) + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +{ + ID_STR_NUM_BUTTONWIDTH, STR_NUM_BUTTONWIDTH + ID_STR_NUM_LABELWIDTH, STR_NUM_LABELWIDTH + ID_STR_ISRTL, STR_ISRTL + ID_STR_UPDATEAVAILABLE, STR_UPDATEAVAILABLE + ID_STR_MANAGE, STR_MANAGE + ID_STR_ABOUT, STR_ABOUT + ID_STR_HELP, STR_HELP + ID_STR_SKINS, STR_SKINS + ID_STR_NOSKINS, STR_NOSKINS + ID_STR_OPENFOLDER, STR_OPENFOLDER + ID_STR_DISABLEDRAGGING, STR_DISABLEDRAGGING + ID_STR_THEMES, STR_THEMES + ID_STR_NOTHEMES, STR_NOTHEMES + ID_STR_EDITSETTINGS, STR_EDITSETTINGS + ID_STR_REFRESHALL, STR_REFRESHALL + ID_STR_LOGGING, STR_LOGGING + ID_STR_SHOWLOGFILE, STR_SHOWLOGFILE + ID_STR_STARTLOGGING, STR_STARTLOGGING + ID_STR_STOPLOGGING, STR_STOPLOGGING + ID_STR_DELETELOGFILE, STR_DELETELOGFILE + ID_STR_DEBUGMODE, STR_DEBUGMODE + ID_STR_EXIT, STR_EXIT + ID_STR_VARIANTS, STR_VARIANTS + ID_STR_SETTINGS, STR_SETTINGS + ID_STR_POSITION, STR_POSITION + ID_STR_DISPLAYMONITOR, STR_DISPLAYMONITOR + ID_STR_USEDEFAULTMONITOR, STR_USEDEFAULTMONITOR + ID_STR_VIRTUALSCREEN, STR_VIRTUALSCREEN + ID_STR_AUTOSELECTMONITOR, STR_AUTOSELECTMONITOR + ID_STR_STAYTOPMOST, STR_STAYTOPMOST + ID_STR_TOPMOST, STR_TOPMOST + ID_STR_NORMAL, STR_NORMAL + ID_STR_BOTTOM, STR_BOTTOM + ID_STR_ONDESKTOP, STR_ONDESKTOP + ID_STR_FROMRIGHT, STR_FROMRIGHT + ID_STR_FROMBOTTOM, STR_FROMBOTTOM + ID_STR_XASPERCENTAGE, STR_XASPERCENTAGE + ID_STR_YASPERCENTAGE, STR_YASPERCENTAGE + ID_STR_TRANSPARENCY, STR_TRANSPARENCY + ID_STR_0PERCENT, "0%" + ID_STR_10PERCENT, "10%" + ID_STR_20PERCENT, "20%" + ID_STR_30PERCENT, "30%" + ID_STR_40PERCENT, "40%" + ID_STR_50PERCENT, "50%" + ID_STR_60PERCENT, "60%" + ID_STR_70PERCENT, "70%" + ID_STR_80PERCENT, "80%" + ID_STR_90PERCENT, "90%" + ID_STR_FADEIN, STR_FADEIN + ID_STR_FADEOUT, STR_FADEOUT + ID_STR_HIDEONMOUSEOVER, STR_HIDEONMOUSEOVER + ID_STR_DRAGGABLE, STR_DRAGGABLE + ID_STR_SAVEPOSITION, STR_SAVEPOSITION + ID_STR_SNAPTOEDGES, STR_SNAPTOEDGES + ID_STR_CLICKTHROUGH, STR_CLICKTHROUGH + ID_STR_KEEPONSCREEN, STR_KEEPONSCREEN + ID_STR_MANAGESKIN, STR_MANAGESKIN + ID_STR_EDITSKIN, STR_EDITSKIN + ID_STR_REFRESHSKIN, STR_REFRESHSKIN + ID_STR_UNLOADSKIN, STR_UNLOADSKIN + ID_STR_CLOSE, STR_CLOSE + ID_STR_ABOUTRAINMETER, STR_ABOUTRAINMETER + ID_STR_LOG, STR_LOG + ID_STR_MEASURES, STR_MEASURES + ID_STR_VARIABLES, STR_VARIABLES + ID_STR_PLUGINS, STR_PLUGINS + ID_STR_VERSION, STR_VERSION + ID_STR_TYPE, STR_TYPE + ID_STR_TIME, STR_TIME + ID_STR_MESSAGE, STR_MESSAGE + ID_STR_NAME, STR_NAME + ID_STR_RANGE, STR_RANGE + ID_STR_VALUE, STR_VALUE + ID_STR_AUTHOR, STR_AUTHOR + ID_STR_ERROR, STR_ERROR + ID_STR_WARNING, STR_WARNING + ID_STR_NOTICE, STR_NOTICE + ID_STR_DEBUG, STR_DEBUG + ID_STR_GETLATESTVERSION, STR_GETLATESTVERSION + ID_STR_COPYRIGHTNOTICE, STR_COPYRIGHTNOTICE + ID_STR_COPYTOCLIPBOARD, STR_COPYTOCLIPBOARD + ID_STR_MANAGERAINMETER, STR_MANAGERAINMETER + ID_STR_ACTIVESKINS, STR_ACTIVESKINS + ID_STR_EXPAND, STR_EXPAND + ID_STR_COLLAPSE, STR_COLLAPSE + ID_STR_OPENLOG, STR_OPENLOG + ID_STR_LOAD, STR_LOAD + ID_STR_UNLOAD, STR_UNLOAD + ID_STR_REFRESH, STR_REFRESH + ID_STR_EDIT, STR_EDIT + ID_STR_AUTHORSC, STR_AUTHORSC + ID_STR_VERSIONSC, STR_VERSIONSC + ID_STR_LICENSESC, STR_LICENSESC + ID_STR_INFORMATIONSC, STR_INFORMATIONSC + ID_STR_ADDMETADATA, STR_ADDMETADATA + ID_STR_COORDINATESSC, STR_COORDINATESSC + ID_STR_POSITIONSC, STR_POSITIONSC + ID_STR_LOADORDERSC, STR_LOADORDERSC + ID_STR_TRANSPARENCYSC, STR_TRANSPARENCYSC + ID_STR_ONHOVERSC, STR_ONHOVERSC + ID_STR_DONOTHING, STR_DONOTHING + ID_STR_HIDE, STR_HIDE + ID_STR_SAVENEWTHEME, STR_SAVENEWTHEME + ID_STR_THEMEDESCRIPTION, STR_THEMEDESCRIPTION + ID_STR_SAVEASEMPTYTHEME, STR_SAVEASEMPTYTHEME + ID_STR_EXCLUDEUNUSEDSKINS, STR_EXCLUDEUNUSEDSKINS + ID_STR_INCLUDEWALLPAPER, STR_INCLUDEWALLPAPER + ID_STR_NAMESC, STR_NAMESC + ID_STR_SAVE, STR_SAVE + ID_STR_SAVEDTHEMES, STR_SAVEDTHEMES + ID_STR_DELETE, STR_DELETE +// ID_STR_BACKUP, STR_BACKUP +// ID_STR_BACKUPDESCRIPTION, STR_BACKUPDESCRIPTION +// ID_STR_BACKUPE, STR_BACKUPE + ID_STR_LANGUAGESC, STR_LANGUAGESC + ID_STR_GENERAL, STR_GENERAL + ID_STR_CHECKFORUPDATES, STR_CHECKFORUPDATES + ID_STR_RESETSTATISTICS, STR_RESETSTATISTICS + ID_STR_LOGTOFILE, STR_LOGTOFILE + ID_STR_SETTINGSNOTWRITABLE, STR_SETTINGSNOTWRITABLE + ID_STR_SETTINGSMOVEFILE, STR_SETTINGSMOVEFILE + ID_STR_SETTINGSREADONLY, STR_SETTINGSREADONLY + ID_STR_THEMEALREADYEXISTS, STR_THEMEALREADYEXISTS + ID_STR_THEMESAVEFAIL, STR_THEMESAVEFAIL + ID_STR_THEMEDELETE, STR_THEMEDELETE + ID_STR_LOGFILECREATEFAIL, STR_LOGFILECREATEFAIL + ID_STR_LOGFILEDELETE, STR_LOGFILEDELETE + ID_STR_NOAVAILABLESKINS, STR_NOAVAILABLESKINS + ID_STR_UNABLETOACTIVATESKIN, STR_UNABLETOACTIVATESKIN + ID_STR_UNABLETOREFRESHSKIN, STR_UNABLETOREFRESHSKIN + ID_STR_NEWVERSIONREQUIRED, STR_NEWVERSIONREQUIRED + ID_STR_NOMETERSINSKIN, STR_NOMETERSINSKIN + ID_STR_INCLUDEINFINITELOOP, STR_INCLUDEINFINITELOOP + ID_STR_WELCOME, STR_WELCOME + ID_STR_CLICKTOMANAGE, STR_CLICKTOMANAGE + ID_STR_CLICKTODOWNLOAD, STR_CLICKTODOWNLOAD + ID_STR_CREATERMSKINPACKAGE, STR_CREATERMSKIN + ID_STR_EDITORSC, STR_EDITORSC + ID_STR_ELLIPSIS, "..." + ID_STR_SHOWNOTIFICATIONAREAICON, STR_SHOWNOTIFAREAICON + ID_STR_SOURCE, STR_SOURCE + ID_STR_USED2D, STR_USED2D + ID_STR_CLEAR, STR_CLEAR +} diff --git a/Language/Romanian.nsh b/Language/Romanian.nsh index f10ef8f8..107a65d4 100644 --- a/Language/Romanian.nsh +++ b/Language/Romanian.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} nu suportă Windows 2000. Pentru a utiliza Rainmeter în Windows 2000, descărcaţi versiunea Rainmeter 2.0." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} solicită Windows XP SP2 sau mai nou. Vă rugăm să actualizaţi service pack-ul, apoi să încercaţi din nou." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} solicită Windows 2003 SP1 sau mai nou. Vă rugăm să actualizaţi service pack-ul, apoi să încercaţi din nou." -${LangFileString} ADMINERROR "Se solicită drepturi de administrator." -${LangFileString} LOGONERROR "Serviciul logon nu este pornit." -${LangFileString} UACERROR "Imposibilă ridicarea." -${LangFileString} WRITEERROR "Versiunea portabilă a Rainmeter trebuie instalată (ca utilizator normal) într-o locaţie cu acces de citire şi scriere.$\nDacă doriţi instalarea Rainmeter în '$0', selectaţi 'Instalare standard'.$\n$\nAltfel selectaţi o locaţie la care aveţi acces pentru citire şi scriere." -${LangFileString} VCINSTERROR "Instalarea Visual C++ $instArc a eşuat din cauza erorii $0.$\n$\nPuteţi încerca descărcarea manuală a pachetului Visual C++ $instArc de la adresa http://rainmeter.net/redist$\n$\nApăsaţi OK pentru ieşire." -${LangFileString} DOTNETINSTERROR "Instalarea .NET $instArc a eşuat din cauza erorii $0.$\n$\nPuteţi încerca descărcarea manuală a pachetului .NET $instArc de la adresa http://rainmeter.net/redist$\n$\nApăsaţi OK pentru ieşire." -${LangFileString} RAINMETERCLOSEERROR "Eroare la închiderea Rainmeter.$\n$\nVă rugăm închideţi programul manual, apoi încercaţi din nou." -${LangFileString} SETTINGSFILEERROR "Fişierul de setări (Rainmeter.ini) se găseşte în folderul de instalare. Păstrându-l acolo, există posibilitatea unor erori dacă programul este folosit de mai mulţi utilizatori sau de către un utilizator standard.$\n$\nDoriţi mutarea fişierului în folderul application data?" -${LangFileString} SETTINGSMOVEERROR "Imposibilă mutarea fişierului '$INSTDIR\Rainmeter.ini' la '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Vă rugăm selectaţi limba pachetului de instalare." -${LangFileString} INSTALLOPTIONS "Opţiuni de instalare" -${LangFileString} INSTALLOPTIONSDESC "Selectaţi opţiunile adiţionale de instalare" -${LangFileString} STANDARDINST "Instalare standard (recomandat)" -${LangFileString} STANDARDINSTDESC "Instalarea Rainmeter şi descărcarea pachetelor necesare." -${LangFileString} PORTABLEINST "Instalare portabilă" -${LangFileString} PORTABLEINSTDESC "Nu selectaţi această opţiune până nu sunteţi sigur de ceea ce faceţi. Comenzile rapide nu vor fi create şi extensia .rmskin nu va fi înregistrată. Poate fi necesară instalarea manuală a Visual C++ şi .NET 2.0." -${LangFileString} AUTOSTARTUP "Lansare Rainmeter după pornire" -${LangFileString} ADDITIONALOPTIONS "Opţiuni adiţionale" -${LangFileString} INSTALL64BIT "Instalare versiune pe 64 biţi" -${LangFileString} SENDINFORMATION "Trimitere informaţii legate de computer" -${LangFileString} SENDINFORMATIONDESC "Pentru îmbunătăţirea Rainmeter, în timpul instalării vor fi trimise informaţii legate de versiunea Windows, limbă şi hardware. Nu vor fi trimise informaţii personale." -${LangFileString} UNSTALLOPTIONS "Opţiuni dezinstalare" -${LangFileString} UNSTALLOPTIONSDESC "Selectaţi opţiunile adiţionale" -${LangFileString} UNSTALLRAINMETER "Dezinstalare Rainmeter" -${LangFileString} UNSTALLSETTINGS "Eliminare completă a setărilor personale şi fişierelor" +${LangFileString} WIN2KERROR "Rainmeter ${VER} nu suportă Windows 2000. Pentru a utiliza Rainmeter în Windows 2000, descărcaţi versiunea Rainmeter 2.0." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} solicită Windows XP SP2 sau mai nou. Vă rugăm să actualizaţi service pack-ul, apoi să încercaţi din nou." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} solicită Windows 2003 SP1 sau mai nou. Vă rugăm să actualizaţi service pack-ul, apoi să încercaţi din nou." +${LangFileString} ADMINERROR "Se solicită drepturi de administrator." +${LangFileString} LOGONERROR "Serviciul logon nu este pornit." +${LangFileString} UACERROR "Imposibilă ridicarea." +${LangFileString} WRITEERROR "Versiunea portabilă a Rainmeter trebuie instalată (ca utilizator normal) într-o locaţie cu acces de citire şi scriere.$\nDacă doriţi instalarea Rainmeter în '$0', selectaţi 'Instalare standard'.$\n$\nAltfel selectaţi o locaţie la care aveţi acces pentru citire şi scriere." +${LangFileString} VCINSTERROR "Instalarea Visual C++ $instArc a eşuat din cauza erorii $0.$\n$\nPuteţi încerca descărcarea manuală a pachetului Visual C++ $instArc de la adresa http://rainmeter.net/redist$\n$\nApăsaţi OK pentru ieşire." +${LangFileString} DOTNETINSTERROR "Instalarea .NET $instArc a eşuat din cauza erorii $0.$\n$\nPuteţi încerca descărcarea manuală a pachetului .NET $instArc de la adresa http://rainmeter.net/redist$\n$\nApăsaţi OK pentru ieşire." +${LangFileString} RAINMETERCLOSEERROR "Eroare la închiderea Rainmeter.$\n$\nVă rugăm închideţi programul manual, apoi încercaţi din nou." +${LangFileString} SETTINGSFILEERROR "Fişierul de setări (Rainmeter.ini) se găseşte în folderul de instalare. Păstrându-l acolo, există posibilitatea unor erori dacă programul este folosit de mai mulţi utilizatori sau de către un utilizator standard.$\n$\nDoriţi mutarea fişierului în folderul application data?" +${LangFileString} SETTINGSMOVEERROR "Imposibilă mutarea fişierului '$INSTDIR\Rainmeter.ini' la '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Vă rugăm selectaţi limba pachetului de instalare." +${LangFileString} INSTALLOPTIONS "Opţiuni de instalare" +${LangFileString} INSTALLOPTIONSDESC "Selectaţi opţiunile adiţionale de instalare" +${LangFileString} STANDARDINST "Instalare standard (recomandat)" +${LangFileString} STANDARDINSTDESC "Instalarea Rainmeter şi descărcarea pachetelor necesare." +${LangFileString} PORTABLEINST "Instalare portabilă" +${LangFileString} PORTABLEINSTDESC "Nu selectaţi această opţiune până nu sunteţi sigur de ceea ce faceţi. Comenzile rapide nu vor fi create şi extensia .rmskin nu va fi înregistrată. Poate fi necesară instalarea manuală a Visual C++ şi .NET 2.0." +${LangFileString} AUTOSTARTUP "Lansare Rainmeter după pornire" +${LangFileString} ADDITIONALOPTIONS "Opţiuni adiţionale" +${LangFileString} INSTALL64BIT "Instalare versiune pe 64 biţi" +${LangFileString} SENDINFORMATION "Trimitere informaţii legate de computer" +${LangFileString} SENDINFORMATIONDESC "Pentru îmbunătăţirea Rainmeter, în timpul instalării vor fi trimise informaţii legate de versiunea Windows, limbă şi hardware. Nu vor fi trimise informaţii personale." +${LangFileString} UNSTALLOPTIONS "Opţiuni dezinstalare" +${LangFileString} UNSTALLOPTIONSDESC "Selectaţi opţiunile adiţionale" +${LangFileString} UNSTALLRAINMETER "Dezinstalare Rainmeter" +${LangFileString} UNSTALLSETTINGS "Eliminare completă a setărilor personale şi fişierelor" ${LangFileString} UNSTALLSETTINGSDESC "(incluzând gadgeturi, teme, suplimentare, setările registrului şi elementele meniului Start)" \ No newline at end of file diff --git a/Language/Russian.nsh b/Language/Russian.nsh index 3634a786..b8cdfb10 100644 --- a/Language/Russian.nsh +++ b/Language/Russian.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} не поддерживает Windows 2000. Чтобы использовать Rainmeter на Windows 2000, скачайте позднюю версию Rainmeter 2.0." -${LangFileString} WINXPS2ERROR "Для Rainmeter ${VER} требуется Windows XP SP2 или выше. Пожалуйста обновитесь до самого последнего SP и попробуйте снова." -${LangFileString} WIN2003SP1ERROR "Для Rainmeter ${VER} требуется Windows 2003 SP1 или выше. Пожалуйста обновитесь до самого последнего SP и попробуйте снова." -${LangFileString} ADMINERROR "Требуются права Администратора." -${LangFileString} LOGONERROR "Служба входа в систему не запущена." -${LangFileString} UACERROR "Не удается повысить." -${LangFileString} WRITEERROR "Портативный Rainmeter должен быть установлен в директории с полным доступом для чтения и записи (как обычный пользователь).$\nЕсли вы хотите установить Rainmeter в '$0', вернитесь назад и выберите «Стандартная Установка».$\n$\nВ противном случае укажите другое расположение с полным доступом для чтения и записи." -${LangFileString} VCINSTERROR "Visual C++ $instArc установка завершилась с кодом ошибки $0.$\n$\nВы можете попробовать загрузить Visual C++ $instArc распространяемый пакет вручную из http://rainmeter.net/redist$\n$\nНажмите кнопку OK для выхода." -${LangFileString} DOTNETINSTERROR ".NET $instArc установка завершилась с кодом ошибки $0.$\n$\nВы можете попробовать загрузить .NET $instArc распространяемый пакет вручную из http://rainmeter.net/redist$\n$\nНажмите кнопку OK для выхода." -${LangFileString} RAINMETERCLOSEERROR "Не удалось закрыть Rainmeter.$\n$\nПожалуйста закройте Rainmeter вручную и повторите попытку." -${LangFileString} SETTINGSFILEERROR "Файл настроек (Rainmeter.ini) расположен в папке установки. Нахождение его там может вызвать проблемы, если приложение используется несколькими пользователями или кем-либо с привилегиями пользователя с ограниченными правами.$\n$\nХотите переместить файл в папку для данных приложения?" -${LangFileString} SETTINGSMOVEERROR "Не удается переместить файл '$INSTDIR\Rainmeter.ini' в '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Пожалуйста выберете язык установщика." -${LangFileString} INSTALLOPTIONS "Настройки Установки" -${LangFileString} INSTALLOPTIONSDESC "Выберите дополнительные параметры установки" -${LangFileString} STANDARDINST "Стандартная установка (рекомендуется)" -${LangFileString} STANDARDINSTDESC "Установить Rainmeter и загрузить необходимые библиотеки." -${LangFileString} PORTABLEINST "Портативная установка" -${LangFileString} PORTABLEINSTDESC "Не выбирайте это, если вы не знаете, что вы делаете. Ярлыки не создадуться и .rmskin расширение будет не зарегистрировано. Может потребоваться вручную установить sVisual C++ и .NET 2.0 библиотеки." -${LangFileString} AUTOSTARTUP "Запускать Rainmeter при старте системы" -${LangFileString} ADDITIONALOPTIONS "Дополнительные настройки" -${LangFileString} INSTALL64BIT "Установить 64-разрядную версию" -${LangFileString} SENDINFORMATION "Отправить информацию о компьютере" -${LangFileString} SENDINFORMATIONDESC "Версия Windows, язык а также возможности оборудования, будут отправлены единажды во время установки для улучшения Rainmeter. Никакие личные данные не будут отправлены." -${LangFileString} UNSTALLOPTIONS "Настройки Удаления" -${LangFileString} UNSTALLOPTIONSDESC "Выберите любые дополнительные опции" -${LangFileString} UNSTALLRAINMETER "Удалить Rainmeter" -${LangFileString} UNSTALLSETTINGS "Полностью удалить все личные настройки и файлы" -${LangFileString} UNSTALLSETTINGSDESC "(включая скины, темы, аддоны, параметры реестра и элементы меню Пуск)" +${LangFileString} WIN2KERROR "Rainmeter ${VER} не поддерживает Windows 2000. Чтобы использовать Rainmeter на Windows 2000, скачайте позднюю версию Rainmeter 2.0." +${LangFileString} WINXPS2ERROR "Для Rainmeter ${VER} требуется Windows XP SP2 или выше. Пожалуйста обновитесь до самого последнего SP и попробуйте снова." +${LangFileString} WIN2003SP1ERROR "Для Rainmeter ${VER} требуется Windows 2003 SP1 или выше. Пожалуйста обновитесь до самого последнего SP и попробуйте снова." +${LangFileString} ADMINERROR "Требуются права Администратора." +${LangFileString} LOGONERROR "Служба входа в систему не запущена." +${LangFileString} UACERROR "Не удается повысить." +${LangFileString} WRITEERROR "Портативный Rainmeter должен быть установлен в директории с полным доступом для чтения и записи (как обычный пользователь).$\nЕсли вы хотите установить Rainmeter в '$0', вернитесь назад и выберите «Стандартная Установка».$\n$\nВ противном случае укажите другое расположение с полным доступом для чтения и записи." +${LangFileString} VCINSTERROR "Visual C++ $instArc установка завершилась с кодом ошибки $0.$\n$\nВы можете попробовать загрузить Visual C++ $instArc распространяемый пакет вручную из http://rainmeter.net/redist$\n$\nНажмите кнопку OK для выхода." +${LangFileString} DOTNETINSTERROR ".NET $instArc установка завершилась с кодом ошибки $0.$\n$\nВы можете попробовать загрузить .NET $instArc распространяемый пакет вручную из http://rainmeter.net/redist$\n$\nНажмите кнопку OK для выхода." +${LangFileString} RAINMETERCLOSEERROR "Не удалось закрыть Rainmeter.$\n$\nПожалуйста закройте Rainmeter вручную и повторите попытку." +${LangFileString} SETTINGSFILEERROR "Файл настроек (Rainmeter.ini) расположен в папке установки. Нахождение его там может вызвать проблемы, если приложение используется несколькими пользователями или кем-либо с привилегиями пользователя с ограниченными правами.$\n$\nХотите переместить файл в папку для данных приложения?" +${LangFileString} SETTINGSMOVEERROR "Не удается переместить файл '$INSTDIR\Rainmeter.ini' в '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Пожалуйста выберете язык установщика." +${LangFileString} INSTALLOPTIONS "Настройки Установки" +${LangFileString} INSTALLOPTIONSDESC "Выберите дополнительные параметры установки" +${LangFileString} STANDARDINST "Стандартная установка (рекомендуется)" +${LangFileString} STANDARDINSTDESC "Установить Rainmeter и загрузить необходимые библиотеки." +${LangFileString} PORTABLEINST "Портативная установка" +${LangFileString} PORTABLEINSTDESC "Не выбирайте это, если вы не знаете, что вы делаете. Ярлыки не создадуться и .rmskin расширение будет не зарегистрировано. Может потребоваться вручную установить sVisual C++ и .NET 2.0 библиотеки." +${LangFileString} AUTOSTARTUP "Запускать Rainmeter при старте системы" +${LangFileString} ADDITIONALOPTIONS "Дополнительные настройки" +${LangFileString} INSTALL64BIT "Установить 64-разрядную версию" +${LangFileString} SENDINFORMATION "Отправить информацию о компьютере" +${LangFileString} SENDINFORMATIONDESC "Версия Windows, язык а также возможности оборудования, будут отправлены единажды во время установки для улучшения Rainmeter. Никакие личные данные не будут отправлены." +${LangFileString} UNSTALLOPTIONS "Настройки Удаления" +${LangFileString} UNSTALLOPTIONSDESC "Выберите любые дополнительные опции" +${LangFileString} UNSTALLRAINMETER "Удалить Rainmeter" +${LangFileString} UNSTALLSETTINGS "Полностью удалить все личные настройки и файлы" +${LangFileString} UNSTALLSETTINGSDESC "(включая скины, темы, аддоны, параметры реестра и элементы меню Пуск)" diff --git a/Language/SerbianCyrillic.nsh b/Language/SerbianCyrillic.nsh index 84ff0328..bd5f2b98 100644 --- a/Language/SerbianCyrillic.nsh +++ b/Language/SerbianCyrillic.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} не подржава Windows 2000. Да бисте користили Rainmeter на Windows-у 2000, преузмите старију верзију (2.0) Rainmeter-а." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} захтева Windows XP SP2 или новији. Надоградите последњи сервисни пакет и покушајте поново." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} захтева Windows 2003 SP1 или новији. Надоградите последњи сервисни пакет и покушајте поново." -${LangFileString} ADMINERROR "Потребна су администраторска права." -${LangFileString} LOGONERROR "Услуга пријављивања није покренута." -${LangFileString} UACERROR "Покретање није могуће." -${LangFileString} WRITEERROR "Преносива верзија Rainmeter-а мора да буде инсталирана на локацију са пуним правима читања и писања (за стандардног корисника).$\nАко желите да инсталирате Rainmeter у '$0', вратите се и изаберите 'Стандардна инсталација'.$\n$\nУ супротном, изаберите другу локацију за коју је дозвољено писање и читање." -${LangFileString} VCINSTERROR "Инсталација Visual C++ $instArc није успела. Кôд грешке: $0.$\n$\nПробајте да ручно преузмете пакет Visual C++ $instArc redistributable са адресе http://rainmeter.net/redist$\n$\nКликните 'У реду' за излазак." -${LangFileString} DOTNETINSTERROR "Инсталација .NET $instArc није успела. Кôд грешке: $0.$\n$\nПробајте да ручно преузмете пакет .NET $instArc redistributable са адресе http://rainmeter.net/redist$\n$\nКликните 'У реду' за излазак." -${LangFileString} RAINMETERCLOSEERROR "Затварање Rainmeter-а није успело.$\n$\nЗатворите Rainmeter ручно и покушајте поново." -${LangFileString} SETTINGSFILEERROR "Датотека са подешавањима (Rainmeter.ini) се налази у инсталационој фасцикли. То може довести до проблема ако апликацију користи више корисника или корисник са ограниченим правима.$\n$\nДа ли желите да преместите датотеку у фасциклу за податке апликације?" -${LangFileString} SETTINGSMOVEERROR "Премештање датотеке '$INSTDIR\Rainmeter.ini' на локацију '$APPDATA\Rainmeter\Rainmeter.ini' није могуће." -${LangFileString} SELECTLANGUAGE "Одаберите језик инсталације." -${LangFileString} INSTALLOPTIONS "Опције инсталације" -${LangFileString} INSTALLOPTIONSDESC "Одаберите додатне опције инсталације" -${LangFileString} STANDARDINST "Стандардна инсталација (препоручује се)" -${LangFileString} STANDARDINSTDESC "Rainmeter ће се инсталирати и преузеће се потребне библиотеке." -${LangFileString} PORTABLEINST "Преносива инсталација" -${LangFileString} PORTABLEINSTDESC "Одаберите ову опцију само ако знате шта радите. Пречице неће бити направљене и тип датотеке .rmskin неће бити регистрован. Можда ће бити потребно да ручно инсталирате библиотеке Visual C++ и .NET 2.0." -${LangFileString} AUTOSTARTUP "Покрени Rainmeter заједно са системом" -${LangFileString} ADDITIONALOPTIONS "Додатне опције" -${LangFileString} INSTALL64BIT "Инсталирај 64-битну верзију" -${LangFileString} SENDINFORMATION "Пошаљи информације о рачунару" -${LangFileString} SENDINFORMATIONDESC "Следеће информације о рачунару ће бити послати током инсталације, а у циљу побољшања Rainmeter-а: верзија Windows-а, језик и могућности хардвера. Лични подаци неће бити послати." -${LangFileString} UNSTALLOPTIONS "Опције деинсталације" -${LangFileString} UNSTALLOPTIONSDESC "Одаберите додатне опције" -${LangFileString} UNSTALLRAINMETER "Деинсталирај Rainmeter" -${LangFileString} UNSTALLSETTINGS "Потпуно уклони сва лична подешавања и датотеке" +${LangFileString} WIN2KERROR "Rainmeter ${VER} не подржава Windows 2000. Да бисте користили Rainmeter на Windows-у 2000, преузмите старију верзију (2.0) Rainmeter-а." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} захтева Windows XP SP2 или новији. Надоградите последњи сервисни пакет и покушајте поново." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} захтева Windows 2003 SP1 или новији. Надоградите последњи сервисни пакет и покушајте поново." +${LangFileString} ADMINERROR "Потребна су администраторска права." +${LangFileString} LOGONERROR "Услуга пријављивања није покренута." +${LangFileString} UACERROR "Покретање није могуће." +${LangFileString} WRITEERROR "Преносива верзија Rainmeter-а мора да буде инсталирана на локацију са пуним правима читања и писања (за стандардног корисника).$\nАко желите да инсталирате Rainmeter у '$0', вратите се и изаберите 'Стандардна инсталација'.$\n$\nУ супротном, изаберите другу локацију за коју је дозвољено писање и читање." +${LangFileString} VCINSTERROR "Инсталација Visual C++ $instArc није успела. Кôд грешке: $0.$\n$\nПробајте да ручно преузмете пакет Visual C++ $instArc redistributable са адресе http://rainmeter.net/redist$\n$\nКликните 'У реду' за излазак." +${LangFileString} DOTNETINSTERROR "Инсталација .NET $instArc није успела. Кôд грешке: $0.$\n$\nПробајте да ручно преузмете пакет .NET $instArc redistributable са адресе http://rainmeter.net/redist$\n$\nКликните 'У реду' за излазак." +${LangFileString} RAINMETERCLOSEERROR "Затварање Rainmeter-а није успело.$\n$\nЗатворите Rainmeter ручно и покушајте поново." +${LangFileString} SETTINGSFILEERROR "Датотека са подешавањима (Rainmeter.ini) се налази у инсталационој фасцикли. То може довести до проблема ако апликацију користи више корисника или корисник са ограниченим правима.$\n$\nДа ли желите да преместите датотеку у фасциклу за податке апликације?" +${LangFileString} SETTINGSMOVEERROR "Премештање датотеке '$INSTDIR\Rainmeter.ini' на локацију '$APPDATA\Rainmeter\Rainmeter.ini' није могуће." +${LangFileString} SELECTLANGUAGE "Одаберите језик инсталације." +${LangFileString} INSTALLOPTIONS "Опције инсталације" +${LangFileString} INSTALLOPTIONSDESC "Одаберите додатне опције инсталације" +${LangFileString} STANDARDINST "Стандардна инсталација (препоручује се)" +${LangFileString} STANDARDINSTDESC "Rainmeter ће се инсталирати и преузеће се потребне библиотеке." +${LangFileString} PORTABLEINST "Преносива инсталација" +${LangFileString} PORTABLEINSTDESC "Одаберите ову опцију само ако знате шта радите. Пречице неће бити направљене и тип датотеке .rmskin неће бити регистрован. Можда ће бити потребно да ручно инсталирате библиотеке Visual C++ и .NET 2.0." +${LangFileString} AUTOSTARTUP "Покрени Rainmeter заједно са системом" +${LangFileString} ADDITIONALOPTIONS "Додатне опције" +${LangFileString} INSTALL64BIT "Инсталирај 64-битну верзију" +${LangFileString} SENDINFORMATION "Пошаљи информације о рачунару" +${LangFileString} SENDINFORMATIONDESC "Следеће информације о рачунару ће бити послати током инсталације, а у циљу побољшања Rainmeter-а: верзија Windows-а, језик и могућности хардвера. Лични подаци неће бити послати." +${LangFileString} UNSTALLOPTIONS "Опције деинсталације" +${LangFileString} UNSTALLOPTIONSDESC "Одаберите додатне опције" +${LangFileString} UNSTALLRAINMETER "Деинсталирај Rainmeter" +${LangFileString} UNSTALLSETTINGS "Потпуно уклони сва лична подешавања и датотеке" ${LangFileString} UNSTALLSETTINGSDESC "(укључујући маске, теме, додатке, подешавања registry базе и ставке менија Старт" \ No newline at end of file diff --git a/Language/SerbianLatin.nsh b/Language/SerbianLatin.nsh index b792e280..428b0c9a 100644 --- a/Language/SerbianLatin.nsh +++ b/Language/SerbianLatin.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} ne podržava Windows 2000. Da biste koristili Rainmeter na Windows-u 2000, preuzmite stariju verziju (2.0) Rainmeter-a." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} zahteva Windows XP SP2 ili noviji. Nadogradite poslednji servisni paket i pokušajte ponovo." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} zahteva Windows 2003 SP1 ili noviji. Nadogradite poslednji servisni paket i pokušajte ponovo." -${LangFileString} ADMINERROR "Potrebna su administratorska prava." -${LangFileString} LOGONERROR "Usluga prijavljivanja nije pokrenuta." -${LangFileString} UACERROR "Pokretanje nije moguće." -${LangFileString} WRITEERROR "Prenosiva verzija Rainmeter-a mora da bude instalirana na lokaciju sa punim pravima čitanja i pisanja (za standardnog korisnika).$\nAko želite da instalirate Rainmeter u '$0', vratite se i izaberite 'Standardna instalacija'.$\n$\nU suprotnom, izaberite drugu lokaciju za koju je dozvoljeno pisanje i čitanje." -${LangFileString} VCINSTERROR "Instalacija Visual C++ $instArc nije uspela. Kôd greške: $0.$\n$\nProbajte da ručno preuzmete paket Visual C++ $instArc redistributable sa adrese http://rainmeter.net/redist$\n$\nKliknite 'U redu' za izlazak." -${LangFileString} DOTNETINSTERROR "Instalacija .NET $instArc nije uspela. Kôd greške: $0.$\n$\nProbajte da ručno preuzmete paket .NET $instArc redistributable sa adrese http://rainmeter.net/redist$\n$\nKliknite 'U redu' za izlazak." -${LangFileString} RAINMETERCLOSEERROR "Zatvaranje Rainmeter-a nije uspelo.$\n$\nZatvorite Rainmeter ručno i pokušajte ponovo." -${LangFileString} SETTINGSFILEERROR "Datoteka sa podešavanjima (Rainmeter.ini) se nalazi u instalacionoj fascikli. To može dovesti do problema ako aplikaciju koristi više korisnika ili korisnik sa ograničenim pravima.$\n$\nDa li želite da premestite datoteku u fasciklu za podatke aplikacije?" -${LangFileString} SETTINGSMOVEERROR "Premeštanje datoteke '$INSTDIR\Rainmeter.ini' na lokaciju '$APPDATA\Rainmeter\Rainmeter.ini' nije moguće." -${LangFileString} SELECTLANGUAGE "Odaberite jezik instalacije." -${LangFileString} INSTALLOPTIONS "Opcije instalacije" -${LangFileString} INSTALLOPTIONSDESC "Odaberite dodatne opcije instalacije" -${LangFileString} STANDARDINST "Standardna instalacija (preporučuje se)" -${LangFileString} STANDARDINSTDESC "Rainmeter će se instalirati i preuzeće se potrebne biblioteke." -${LangFileString} PORTABLEINST "Prenosiva instalacija" -${LangFileString} PORTABLEINSTDESC "Odaberite ovu opciju samo ako znate šta radite. Prečice neće biti napravljene i tip datoteke .rmskin neće biti registrovan. Možda će biti potrebno da ručno instalirate biblioteke Visual C++ i .NET 2.0." -${LangFileString} AUTOSTARTUP "Pokreni Rainmeter zajedno sa sistemom" -${LangFileString} ADDITIONALOPTIONS "Dodatne opcije" -${LangFileString} INSTALL64BIT "Instaliraj 64-bitnu verziju" -${LangFileString} SENDINFORMATION "Pošalji informacije o računaru" -${LangFileString} SENDINFORMATIONDESC "Sledeće informacije o računaru će biti poslate tokom instalacije, a u cilju poboljšanja Rainmetera: verzija Windowsa, jezik i mogućnosti hardvera. Lični podaci neće biti poslati." -${LangFileString} UNSTALLOPTIONS "Opcije deinstalacije" -${LangFileString} UNSTALLOPTIONSDESC "Odaberite dodatne opcije" -${LangFileString} UNSTALLRAINMETER "Deinstaliraj Rainmeter" -${LangFileString} UNSTALLSETTINGS "Potpuno ukloni sva lična podešavanja i datoteke" +${LangFileString} WIN2KERROR "Rainmeter ${VER} ne podržava Windows 2000. Da biste koristili Rainmeter na Windows-u 2000, preuzmite stariju verziju (2.0) Rainmeter-a." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} zahteva Windows XP SP2 ili noviji. Nadogradite poslednji servisni paket i pokušajte ponovo." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} zahteva Windows 2003 SP1 ili noviji. Nadogradite poslednji servisni paket i pokušajte ponovo." +${LangFileString} ADMINERROR "Potrebna su administratorska prava." +${LangFileString} LOGONERROR "Usluga prijavljivanja nije pokrenuta." +${LangFileString} UACERROR "Pokretanje nije moguće." +${LangFileString} WRITEERROR "Prenosiva verzija Rainmeter-a mora da bude instalirana na lokaciju sa punim pravima čitanja i pisanja (za standardnog korisnika).$\nAko želite da instalirate Rainmeter u '$0', vratite se i izaberite 'Standardna instalacija'.$\n$\nU suprotnom, izaberite drugu lokaciju za koju je dozvoljeno pisanje i čitanje." +${LangFileString} VCINSTERROR "Instalacija Visual C++ $instArc nije uspela. Kôd greške: $0.$\n$\nProbajte da ručno preuzmete paket Visual C++ $instArc redistributable sa adrese http://rainmeter.net/redist$\n$\nKliknite 'U redu' za izlazak." +${LangFileString} DOTNETINSTERROR "Instalacija .NET $instArc nije uspela. Kôd greške: $0.$\n$\nProbajte da ručno preuzmete paket .NET $instArc redistributable sa adrese http://rainmeter.net/redist$\n$\nKliknite 'U redu' za izlazak." +${LangFileString} RAINMETERCLOSEERROR "Zatvaranje Rainmeter-a nije uspelo.$\n$\nZatvorite Rainmeter ručno i pokušajte ponovo." +${LangFileString} SETTINGSFILEERROR "Datoteka sa podešavanjima (Rainmeter.ini) se nalazi u instalacionoj fascikli. To može dovesti do problema ako aplikaciju koristi više korisnika ili korisnik sa ograničenim pravima.$\n$\nDa li želite da premestite datoteku u fasciklu za podatke aplikacije?" +${LangFileString} SETTINGSMOVEERROR "Premeštanje datoteke '$INSTDIR\Rainmeter.ini' na lokaciju '$APPDATA\Rainmeter\Rainmeter.ini' nije moguće." +${LangFileString} SELECTLANGUAGE "Odaberite jezik instalacije." +${LangFileString} INSTALLOPTIONS "Opcije instalacije" +${LangFileString} INSTALLOPTIONSDESC "Odaberite dodatne opcije instalacije" +${LangFileString} STANDARDINST "Standardna instalacija (preporučuje se)" +${LangFileString} STANDARDINSTDESC "Rainmeter će se instalirati i preuzeće se potrebne biblioteke." +${LangFileString} PORTABLEINST "Prenosiva instalacija" +${LangFileString} PORTABLEINSTDESC "Odaberite ovu opciju samo ako znate šta radite. Prečice neće biti napravljene i tip datoteke .rmskin neće biti registrovan. Možda će biti potrebno da ručno instalirate biblioteke Visual C++ i .NET 2.0." +${LangFileString} AUTOSTARTUP "Pokreni Rainmeter zajedno sa sistemom" +${LangFileString} ADDITIONALOPTIONS "Dodatne opcije" +${LangFileString} INSTALL64BIT "Instaliraj 64-bitnu verziju" +${LangFileString} SENDINFORMATION "Pošalji informacije o računaru" +${LangFileString} SENDINFORMATIONDESC "Sledeće informacije o računaru će biti poslate tokom instalacije, a u cilju poboljšanja Rainmetera: verzija Windowsa, jezik i mogućnosti hardvera. Lični podaci neće biti poslati." +${LangFileString} UNSTALLOPTIONS "Opcije deinstalacije" +${LangFileString} UNSTALLOPTIONSDESC "Odaberite dodatne opcije" +${LangFileString} UNSTALLRAINMETER "Deinstaliraj Rainmeter" +${LangFileString} UNSTALLSETTINGS "Potpuno ukloni sva lična podešavanja i datoteke" ${LangFileString} UNSTALLSETTINGSDESC "(uključujući maske, teme, dodatke, podešavanja registry baze i stavke menija Start)" \ No newline at end of file diff --git a/Language/Slovak.nsh b/Language/Slovak.nsh index ff521e75..8598100c 100644 --- a/Language/Slovak.nsh +++ b/Language/Slovak.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} nepodporuje systém Windows 2000. Na používanie programu Rainmeter v systéme Windows 2000 si stiahnite staršiu verziu programu Rainmeter 2.0." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} požaduje systém Windows XP SP2 alebo vyšší. Prosím, zaktualizujte systém na najnovší service pack a skúste znova." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} požaduje systém Windows 2003 SP1 alebo vyšší. Prosím, zaktualizujte systém na najnovší service pack a skúste znova." -${LangFileString} ADMINERROR "Požadované práva administrátora." -${LangFileString} LOGONERROR "Služba prihlasovania nie je aktívna." -${LangFileString} UACERROR "Zakázaný prístup." -${LangFileString} WRITEERROR "Portable Rainmeter musí byť nainštalovaný do priečinka s plnou podporou čítania a zápisu (ako normálny používateľ).$\nAk chcete nainštalovať Rainmeter do '$0', choďte späť a zadajte 'Štandardná inštalácia'.$\n$\nAlebo zadajte iný priečinok s plnou podporou čítania a zápisu." -${LangFileString} VCINSTERROR "Visual C++ $instArc inštalácia zlyhala s chybovým kódom $0.$\n$\nSkúste stiahnuť Visual C++ $instArc redistributable package manuálne z http://rainmeter.net/redist$\n$\nStlačte OK pre ukončenie." -${LangFileString} DOTNETINSTERROR ".NET $instArc inštalácia zlyhala s chybovým kódom $0.$\n$\nSkúste stiahnuť .NET $instArc redistributable package manuálne z http://rainmeter.net/redist$\n$\nStlačte OK pre ukončenie." -${LangFileString} RAINMETERCLOSEERROR "Nemožno ukončiť Rainmeter.$\n$\nProsím zatvorte Rainmeter manuálne a skúste znova." -${LangFileString} SETTINGSFILEERROR "Súbor nastavení (Rainmeter.ini) je uložený v inštalačnom priečinku. Ak tam bude ponechaný, môžu nastať problémy pri používaní aplikácie viacerými používateľmi alebo kýmkoľvek s obmedzenými právami.$\n$\nPrajete si presunúť súbor nastavení do priečinka application data?" -${LangFileString} SETTINGSMOVEERROR "Nemožno presunúť súbor '$INSTDIR\Rainmeter.ini' do '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Prosím zvoľte jazyk inštalácie." -${LangFileString} INSTALLOPTIONS "Možnosti inštalácie" -${LangFileString} INSTALLOPTIONSDESC "Zvoliť ďalšie možnosti inštalácie" -${LangFileString} STANDARDINST "Štandardná inštalácia (doporučené)" -${LangFileString} STANDARDINSTDESC "Nainštaluje Rainmeter do Vášho počítača a stiahne požadované knižnice." -${LangFileString} PORTABLEINST "Portable inštalácia" -${LangFileString} PORTABLEINSTDESC "Nevyberajte túto možnosť pokiaľ neviete, čo robíte. Nebudú vytvorené odkazy a rozšírenie .rmskin nebude zaregistrované. Knižnice Visual C++ a .NET 2.0 bude možno potrebné nainštalovať manuálne." -${LangFileString} AUTOSTARTUP "Spustiť Rainmeter pri štarte Windowsu" -${LangFileString} ADDITIONALOPTIONS "Ďalšie možnosti" -${LangFileString} INSTALL64BIT "Inštalovať 64-bitovú verziu" -${LangFileString} SENDINFORMATION "Odoslať informácie o počítači" -${LangFileString} SENDINFORMATIONDESC "Vaša verzia Windowsu, jazykové rozhranie a hardvérové možnosti budú odoslané jeden krát počas inštalácie na zlepšenie programu Rainmeter. Nebudú odoslané žiadne súkromné informácie." -${LangFileString} UNSTALLOPTIONS "Možnosti odinštalácie" -${LangFileString} UNSTALLOPTIONSDESC "Zvoľte ďalšie možnosti" -${LangFileString} UNSTALLRAINMETER "Odinštalovať Rainmeter" -${LangFileString} UNSTALLSETTINGS "Odstrániť všetky osobné nastavenia a súbory." +${LangFileString} WIN2KERROR "Rainmeter ${VER} nepodporuje systém Windows 2000. Na používanie programu Rainmeter v systéme Windows 2000 si stiahnite staršiu verziu programu Rainmeter 2.0." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} požaduje systém Windows XP SP2 alebo vyšší. Prosím, zaktualizujte systém na najnovší service pack a skúste znova." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} požaduje systém Windows 2003 SP1 alebo vyšší. Prosím, zaktualizujte systém na najnovší service pack a skúste znova." +${LangFileString} ADMINERROR "Požadované práva administrátora." +${LangFileString} LOGONERROR "Služba prihlasovania nie je aktívna." +${LangFileString} UACERROR "Zakázaný prístup." +${LangFileString} WRITEERROR "Portable Rainmeter musí byť nainštalovaný do priečinka s plnou podporou čítania a zápisu (ako normálny používateľ).$\nAk chcete nainštalovať Rainmeter do '$0', choďte späť a zadajte 'Štandardná inštalácia'.$\n$\nAlebo zadajte iný priečinok s plnou podporou čítania a zápisu." +${LangFileString} VCINSTERROR "Visual C++ $instArc inštalácia zlyhala s chybovým kódom $0.$\n$\nSkúste stiahnuť Visual C++ $instArc redistributable package manuálne z http://rainmeter.net/redist$\n$\nStlačte OK pre ukončenie." +${LangFileString} DOTNETINSTERROR ".NET $instArc inštalácia zlyhala s chybovým kódom $0.$\n$\nSkúste stiahnuť .NET $instArc redistributable package manuálne z http://rainmeter.net/redist$\n$\nStlačte OK pre ukončenie." +${LangFileString} RAINMETERCLOSEERROR "Nemožno ukončiť Rainmeter.$\n$\nProsím zatvorte Rainmeter manuálne a skúste znova." +${LangFileString} SETTINGSFILEERROR "Súbor nastavení (Rainmeter.ini) je uložený v inštalačnom priečinku. Ak tam bude ponechaný, môžu nastať problémy pri používaní aplikácie viacerými používateľmi alebo kýmkoľvek s obmedzenými právami.$\n$\nPrajete si presunúť súbor nastavení do priečinka application data?" +${LangFileString} SETTINGSMOVEERROR "Nemožno presunúť súbor '$INSTDIR\Rainmeter.ini' do '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Prosím zvoľte jazyk inštalácie." +${LangFileString} INSTALLOPTIONS "Možnosti inštalácie" +${LangFileString} INSTALLOPTIONSDESC "Zvoliť ďalšie možnosti inštalácie" +${LangFileString} STANDARDINST "Štandardná inštalácia (doporučené)" +${LangFileString} STANDARDINSTDESC "Nainštaluje Rainmeter do Vášho počítača a stiahne požadované knižnice." +${LangFileString} PORTABLEINST "Portable inštalácia" +${LangFileString} PORTABLEINSTDESC "Nevyberajte túto možnosť pokiaľ neviete, čo robíte. Nebudú vytvorené odkazy a rozšírenie .rmskin nebude zaregistrované. Knižnice Visual C++ a .NET 2.0 bude možno potrebné nainštalovať manuálne." +${LangFileString} AUTOSTARTUP "Spustiť Rainmeter pri štarte Windowsu" +${LangFileString} ADDITIONALOPTIONS "Ďalšie možnosti" +${LangFileString} INSTALL64BIT "Inštalovať 64-bitovú verziu" +${LangFileString} SENDINFORMATION "Odoslať informácie o počítači" +${LangFileString} SENDINFORMATIONDESC "Vaša verzia Windowsu, jazykové rozhranie a hardvérové možnosti budú odoslané jeden krát počas inštalácie na zlepšenie programu Rainmeter. Nebudú odoslané žiadne súkromné informácie." +${LangFileString} UNSTALLOPTIONS "Možnosti odinštalácie" +${LangFileString} UNSTALLOPTIONSDESC "Zvoľte ďalšie možnosti" +${LangFileString} UNSTALLRAINMETER "Odinštalovať Rainmeter" +${LangFileString} UNSTALLSETTINGS "Odstrániť všetky osobné nastavenia a súbory." ${LangFileString} UNSTALLSETTINGSDESC "(vrátane skinov, tém, addonov, nastavení registrov a položiek v menu Štart)" \ No newline at end of file diff --git a/Language/Slovenian.nsh b/Language/Slovenian.nsh index 397585a1..e3460c3e 100644 --- a/Language/Slovenian.nsh +++ b/Language/Slovenian.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} ne podpira Windows 2000. Za uporabo Rainmeter na Windows 2000, prenesite starejšo Rainmeter 2.0 verzijo." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} potrebuje Windows XP SP2 ali novejše. Prosim posodobite na novejši servisni paket in poskusite ponovno." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} potrebuje Windows 2003 SP1 oali novejše. Prosim posodobite na novejši servisni paket in poskusite ponovno." -${LangFileString} ADMINERROR "Potrebne so Administratorske pravice." -${LangFileString} LOGONERROR "Prijavna storitev ne deluje." -${LangFileString} UACERROR "Ne morem dvigniti." -${LangFileString} WRITEERROR "Prenosni Rainmeter mora biti nameščen v lokacijo s popolnoma omogočenim branjem in pisanjem (kot normalni uporabnik).$\nČe želite naložiti Rainmeter v '$0', pojdite nazaj in izberite 'Standardna namestitev'.$\n$\nDrugače pa prebrskajte za drugo lokacijo s popolnoma omogočenim branjem in pisanjem." -${LangFileString} VCINSTERROR "Visual C++ $instArc napaka namestitve koda $0.$\n$\nMorda boste želeli poskusiti naložiti Visual C++ $instArc redistributable package ročno iz http://rainmeter.net/redist$\n$\nPritisnite OK za izhod." -${LangFileString} DOTNETINSTERROR ".NET $instArc napaka namestitve koda $0.$\n$\nMorda boste želeli poskusiti prenesti .NET $instArc redistributable package ročno iz http://rainmeter.net/redist$\n$\nPritisnite OK za izhod." -${LangFileString} RAINMETERCLOSEERROR "Ni mogoče zapreti Rainmeter.$\n$\nProsim zaprite Rainmeter ročno in poskusite ponovno." -${LangFileString} SETTINGSFILEERROR "Nastavitvena datoteka (Rainmeter.ini) se nahaja v namestitveni mapi. Če ga imate tam lahko povzroči težave, če se prijavlja več uporabnikov ali kdorkoli z omejenimi pravicami uporabnikov.$\n$\nŽelite premakniti datoteko v programsko mapo?" -${LangFileString} SETTINGSMOVEERROR "Nemogoče premakniti datoteko '$INSTDIR\Rainmeter.ini' v '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE " " -${LangFileString} INSTALLOPTIONS "Namestitvene možnosti" -${LangFileString} INSTALLOPTIONSDESC "Izberite dodatne možnosti namestitvene" -${LangFileString} STANDARDINST "Standardna namestitev (priporočeno)" -${LangFileString} STANDARDINSTDESC "Namestite Rainmeter in prenesite potrebne knjižnice." -${LangFileString} PORTABLEINST "Prenosna namestitev" -${LangFileString} PORTABLEINSTDESC "Ne izberite tega, razen če veste kaj delate. Bližnjica ne bo ustvarjena in .rmskin končnica ne bo registrirana. Visual C++ in .NET 2.0 knjižnice bodo morale biti ročno naložene." -${LangFileString} AUTOSTARTUP "Vklop Rainmeter pri zagonu" -${LangFileString} ADDITIONALOPTIONS "Dodatne možnosti" -${LangFileString} INSTALL64BIT "Namestite 64-bit verzijo" -${LangFileString} SENDINFORMATION "Pošljite informacije o vašem računalniku" -${LangFileString} SENDINFORMATIONDESC "Vaša Windows verzija na računalniku, jezik in zmogljivosti strojne opreme bodo poslane ob namestitvi za izbolšanje Rainmeter-ja. Osebne informacije ne bodo poslane." -${LangFileString} UNSTALLOPTIONS "Možnosti odstranitve" -${LangFileString} UNSTALLOPTIONSDESC "Izberite dodatne možnosti" -${LangFileString} UNSTALLRAINMETER "Odstranitev Rainmeter-ja" -${LangFileString} UNSTALLSETTINGS "Popolnoma odstranite vse osebne nastavitve in datoteke" +${LangFileString} WIN2KERROR "Rainmeter ${VER} ne podpira Windows 2000. Za uporabo Rainmeter na Windows 2000, prenesite starejšo Rainmeter 2.0 verzijo." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} potrebuje Windows XP SP2 ali novejše. Prosim posodobite na novejši servisni paket in poskusite ponovno." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} potrebuje Windows 2003 SP1 oali novejše. Prosim posodobite na novejši servisni paket in poskusite ponovno." +${LangFileString} ADMINERROR "Potrebne so Administratorske pravice." +${LangFileString} LOGONERROR "Prijavna storitev ne deluje." +${LangFileString} UACERROR "Ne morem dvigniti." +${LangFileString} WRITEERROR "Prenosni Rainmeter mora biti nameščen v lokacijo s popolnoma omogočenim branjem in pisanjem (kot normalni uporabnik).$\nČe želite naložiti Rainmeter v '$0', pojdite nazaj in izberite 'Standardna namestitev'.$\n$\nDrugače pa prebrskajte za drugo lokacijo s popolnoma omogočenim branjem in pisanjem." +${LangFileString} VCINSTERROR "Visual C++ $instArc napaka namestitve koda $0.$\n$\nMorda boste želeli poskusiti naložiti Visual C++ $instArc redistributable package ročno iz http://rainmeter.net/redist$\n$\nPritisnite OK za izhod." +${LangFileString} DOTNETINSTERROR ".NET $instArc napaka namestitve koda $0.$\n$\nMorda boste želeli poskusiti prenesti .NET $instArc redistributable package ročno iz http://rainmeter.net/redist$\n$\nPritisnite OK za izhod." +${LangFileString} RAINMETERCLOSEERROR "Ni mogoče zapreti Rainmeter.$\n$\nProsim zaprite Rainmeter ročno in poskusite ponovno." +${LangFileString} SETTINGSFILEERROR "Nastavitvena datoteka (Rainmeter.ini) se nahaja v namestitveni mapi. Če ga imate tam lahko povzroči težave, če se prijavlja več uporabnikov ali kdorkoli z omejenimi pravicami uporabnikov.$\n$\nŽelite premakniti datoteko v programsko mapo?" +${LangFileString} SETTINGSMOVEERROR "Nemogoče premakniti datoteko '$INSTDIR\Rainmeter.ini' v '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE " " +${LangFileString} INSTALLOPTIONS "Namestitvene možnosti" +${LangFileString} INSTALLOPTIONSDESC "Izberite dodatne možnosti namestitvene" +${LangFileString} STANDARDINST "Standardna namestitev (priporočeno)" +${LangFileString} STANDARDINSTDESC "Namestite Rainmeter in prenesite potrebne knjižnice." +${LangFileString} PORTABLEINST "Prenosna namestitev" +${LangFileString} PORTABLEINSTDESC "Ne izberite tega, razen če veste kaj delate. Bližnjica ne bo ustvarjena in .rmskin končnica ne bo registrirana. Visual C++ in .NET 2.0 knjižnice bodo morale biti ročno naložene." +${LangFileString} AUTOSTARTUP "Vklop Rainmeter pri zagonu" +${LangFileString} ADDITIONALOPTIONS "Dodatne možnosti" +${LangFileString} INSTALL64BIT "Namestite 64-bit verzijo" +${LangFileString} SENDINFORMATION "Pošljite informacije o vašem računalniku" +${LangFileString} SENDINFORMATIONDESC "Vaša Windows verzija na računalniku, jezik in zmogljivosti strojne opreme bodo poslane ob namestitvi za izbolšanje Rainmeter-ja. Osebne informacije ne bodo poslane." +${LangFileString} UNSTALLOPTIONS "Možnosti odstranitve" +${LangFileString} UNSTALLOPTIONSDESC "Izberite dodatne možnosti" +${LangFileString} UNSTALLRAINMETER "Odstranitev Rainmeter-ja" +${LangFileString} UNSTALLSETTINGS "Popolnoma odstranite vse osebne nastavitve in datoteke" ${LangFileString} UNSTALLSETTINGSDESC "(vključeno s datotekami, temami, dodatki, nastavitvami registra, in predmetov Start menija)" \ No newline at end of file diff --git a/Language/SpanishModern.nsh b/Language/SpanishModern.nsh index 0d0ee418..3793e85b 100644 --- a/Language/SpanishModern.nsh +++ b/Language/SpanishModern.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} no esta sorportado en 2000. Para usar Rainmeter en Windows 2000, descargue la versión 2.0 de Rainmeter." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} requiere Windows XP SP2 o superior. Por favor actualice al último service pack e intentelo de nuevo." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} requiere Windows 2003 SP1 o superior. Por favor actualiza al último service pack e intentalo de nuevo." -${LangFileString} ADMINERROR "Derechos de administrador requeridos." -${LangFileString} LOGONERROR "El servicio de inicio de sesión no se esta ejecutando." -${LangFileString} UACERROR "No es posible elevar." -${LangFileString} WRITEERROR "La carpeta de instalación de Rainmeter Portable debe tener acceso completo de lectura y escritura (como usuario normal).$\nSi desea instalar Rainmeter en '$0', vuelva atrás y seleccione 'Instalación Estandar'.$\n$\nEn caso contrario, cambie la ubicación o los permisos en la carpeta." -${LangFileString} VCINSTERROR "Visual C++ $instArc La instalación ha fallado, código de error: $0.$\n$\nQuizás debería intentar descargar Visual C++ $instArc paquete redistribuible manualmente desde http://rainmeter.net/redist$\n$\nPulse OK para salir." -${LangFileString} DOTNETINSTERROR ".NET $instArc La instalación ha fallado, código de error: $0.$\n$\nQuizás debería intentar descargar el .NET $instArc paquete redistribuible manualmente desde http://rainmeter.net/redist$\n$\nPulse OK para salir." -${LangFileString} RAINMETERCLOSEERROR "No se pudo cerrar Rainmeter.$\n$\nPor favor cierre Rainmeter manualmente e intentelo de nuevo." -${LangFileString} SETTINGSFILEERROR "El archivo de ajustes (Rainmeter.ini) se encuentra en la carpeta de instalación. Mantenerlo ahí puede causar problemas si la aplicación es usada por múltiples usuarios.$\n$\nQuiere mover el archivo a la carpeta Datos de Programa?" -${LangFileString} SETTINGSMOVEERROR "No se puede mover el archivo '$INSTDIR\Rainmeter.ini' a '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Por favor seleccione el idioma de la instalación." -${LangFileString} INSTALLOPTIONS "Opciones de instalación" -${LangFileString} INSTALLOPTIONSDESC "Seleccione opciones adicionales de instalación" -${LangFileString} STANDARDINST "Instalación estandar (recomendado)" -${LangFileString} STANDARDINSTDESC "Instala Rainmeter y descarga las librerias necesarias." -${LangFileString} PORTABLEINST "Instalación Portable" -${LangFileString} PORTABLEINSTDESC "No seleccione esto a menos que sepa lo que está haciendo. Los accesos directos no se crearán y la extensión .rmskin no será registrada. Las librerias Visual C++ y .NET 2.0 puede que necesiten ser instaladas manualmente." -${LangFileString} AUTOSTARTUP "Ejecuta Rainmeter al iniciar windows" -${LangFileString} ADDITIONALOPTIONS "Opciones Adicionales" -${LangFileString} INSTALL64BIT "Instalar version 64 bits" -${LangFileString} SENDINFORMATION "Send information about your computer" -${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." -${LangFileString} UNSTALLOPTIONS "Desinstalar opciones" -${LangFileString} UNSTALLOPTIONSDESC "Selecciona cualquier otra opción adicional" -${LangFileString} UNSTALLRAINMETER "Desinstalar Rainmeter" -${LangFileString} UNSTALLSETTINGS "Elimina por completo todos los ajustes y archivos personales" +${LangFileString} WIN2KERROR "Rainmeter ${VER} no esta sorportado en 2000. Para usar Rainmeter en Windows 2000, descargue la versión 2.0 de Rainmeter." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} requiere Windows XP SP2 o superior. Por favor actualice al último service pack e intentelo de nuevo." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} requiere Windows 2003 SP1 o superior. Por favor actualiza al último service pack e intentalo de nuevo." +${LangFileString} ADMINERROR "Derechos de administrador requeridos." +${LangFileString} LOGONERROR "El servicio de inicio de sesión no se esta ejecutando." +${LangFileString} UACERROR "No es posible elevar." +${LangFileString} WRITEERROR "La carpeta de instalación de Rainmeter Portable debe tener acceso completo de lectura y escritura (como usuario normal).$\nSi desea instalar Rainmeter en '$0', vuelva atrás y seleccione 'Instalación Estandar'.$\n$\nEn caso contrario, cambie la ubicación o los permisos en la carpeta." +${LangFileString} VCINSTERROR "Visual C++ $instArc La instalación ha fallado, código de error: $0.$\n$\nQuizás debería intentar descargar Visual C++ $instArc paquete redistribuible manualmente desde http://rainmeter.net/redist$\n$\nPulse OK para salir." +${LangFileString} DOTNETINSTERROR ".NET $instArc La instalación ha fallado, código de error: $0.$\n$\nQuizás debería intentar descargar el .NET $instArc paquete redistribuible manualmente desde http://rainmeter.net/redist$\n$\nPulse OK para salir." +${LangFileString} RAINMETERCLOSEERROR "No se pudo cerrar Rainmeter.$\n$\nPor favor cierre Rainmeter manualmente e intentelo de nuevo." +${LangFileString} SETTINGSFILEERROR "El archivo de ajustes (Rainmeter.ini) se encuentra en la carpeta de instalación. Mantenerlo ahí puede causar problemas si la aplicación es usada por múltiples usuarios.$\n$\nQuiere mover el archivo a la carpeta Datos de Programa?" +${LangFileString} SETTINGSMOVEERROR "No se puede mover el archivo '$INSTDIR\Rainmeter.ini' a '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Por favor seleccione el idioma de la instalación." +${LangFileString} INSTALLOPTIONS "Opciones de instalación" +${LangFileString} INSTALLOPTIONSDESC "Seleccione opciones adicionales de instalación" +${LangFileString} STANDARDINST "Instalación estandar (recomendado)" +${LangFileString} STANDARDINSTDESC "Instala Rainmeter y descarga las librerias necesarias." +${LangFileString} PORTABLEINST "Instalación Portable" +${LangFileString} PORTABLEINSTDESC "No seleccione esto a menos que sepa lo que está haciendo. Los accesos directos no se crearán y la extensión .rmskin no será registrada. Las librerias Visual C++ y .NET 2.0 puede que necesiten ser instaladas manualmente." +${LangFileString} AUTOSTARTUP "Ejecuta Rainmeter al iniciar windows" +${LangFileString} ADDITIONALOPTIONS "Opciones Adicionales" +${LangFileString} INSTALL64BIT "Instalar version 64 bits" +${LangFileString} SENDINFORMATION "Send information about your computer" +${LangFileString} SENDINFORMATIONDESC "Your computer's Windows version, language, and hardware capabilities will be reported once during installation to improve Rainmeter. No personal information will be sent." +${LangFileString} UNSTALLOPTIONS "Desinstalar opciones" +${LangFileString} UNSTALLOPTIONSDESC "Selecciona cualquier otra opción adicional" +${LangFileString} UNSTALLRAINMETER "Desinstalar Rainmeter" +${LangFileString} UNSTALLSETTINGS "Elimina por completo todos los ajustes y archivos personales" ${LangFileString} UNSTALLSETTINGSDESC "(incluyendo pieles, temas, extensiones, configuración del registro, y elementos del menú Inicio)" \ No newline at end of file diff --git a/Language/Swedish.nsh b/Language/Swedish.nsh index 0cfd009a..fb523969 100644 --- a/Language/Swedish.nsh +++ b/Language/Swedish.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} fungerar inte på Windows 2000. För att använda Rainmeter på Windows 2000, ladda ner den äldre Rainmeter-versionen 2.0." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} kräver Windows XP SP2 eller senare. Uppgradera till senaste Service Pack och försök igen." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} kräver Windows 2003 SP1 eller senare. Uppgradera till senaste Service Pack och försök igen." -${LangFileString} ADMINERROR "Administrativa rättigheter krävs." -${LangFileString} LOGONERROR "Logon-tjänsten körs ej." -${LangFileString} UACERROR "Kan inte höja UAC-nivån." -${LangFileString} WRITEERROR "Portabel Rainmeter måste installeras på en plats med fullständiga läs- och skrivrättigheter (som vanlig användare).$\nOm du vill installera Rainmeter i '$0', gå tillbaka och välj 'Standardinstallation'.$\n$\nVälj annars en annan plats med fullständiga läs- och skrivrättigheter." -${LangFileString} VCINSTERROR "Installationen av Visual C++ $instArc misslyckades med felkod $0.$\n$\nDu kanske vill prova att ladda ner Visual C++ $instArc distributionspaketet manuellt från http://rainmeter.net/redist$\n$\nTryck OK för att avsluta." -${LangFileString} DOTNETINSTERROR ".NET $instArc installationen misslyckades med felkod $0.$\n$\nDu kanske vill prova att ladda ner .NET $instArc distributionspaketet manuellt från http://rainmeter.net/redist$\n$\nTryck OK för att avsluta." -${LangFileString} RAINMETERCLOSEERROR "Kunde inte stänga Rainmeter.$\n$\nStäng Rainmeter manuellt och försök igen." -${LangFileString} SETTINGSFILEERROR "Inställningsfilen (Rainmeter.ini) ligger i installationsmappen. Att behålla den där kan orsaka problem om datorn används av fler användare eller av någon med begränsade användarrättigheter.$\n$\nVill du flytta filen till mappen Programdata?" -${LangFileString} SETTINGSMOVEERROR "Kan inte flytta filen '$INSTDIR\Rainmeter.ini' till '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Välj installationsspråk." -${LangFileString} INSTALLOPTIONS "Installationsalternativ" -${LangFileString} INSTALLOPTIONSDESC "Välj ytterligare installationsalternativ" -${LangFileString} STANDARDINST "Standardinstallation (rekommenderas)" -${LangFileString} STANDARDINSTDESC "Installerar Rainmeter och hämtar nödvändiga bibliotek." -${LangFileString} PORTABLEINST "Portabel installation" -${LangFileString} PORTABLEINSTDESC "Välj inte detta om du inte vet vad du gör. Genvägar kommer inte att skapas och .rmskin kommer inte att registeras. Visual C++ och .NET 2.0 biblioteken kan behövas att installeras separat." -${LangFileString} AUTOSTARTUP "Starta Rainmeter vid systemstart" -${LangFileString} ADDITIONALOPTIONS "Fler alternativ" -${LangFileString} INSTALL64BIT "Installera 64-bitars version" -${LangFileString} SENDINFORMATION "Skicka Datorns information" -${LangFileString} SENDINFORMATIONDESC "Din Dators Windows version, språk samt hårdvara kapacitet kommer att skickas under installation för att förbättra Rainmeter. Ingen personlig information kommer skickas." -${LangFileString} UNSTALLOPTIONS "Avinstallations-alternativ" -${LangFileString} UNSTALLOPTIONSDESC "Välj andra alternativ" -${LangFileString} UNSTALLRAINMETER "Avinstallera Rainmeter" -${LangFileString} UNSTALLSETTINGS "Ta bort alla personliga inställningar och filer" +${LangFileString} WIN2KERROR "Rainmeter ${VER} fungerar inte på Windows 2000. För att använda Rainmeter på Windows 2000, ladda ner den äldre Rainmeter-versionen 2.0." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} kräver Windows XP SP2 eller senare. Uppgradera till senaste Service Pack och försök igen." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} kräver Windows 2003 SP1 eller senare. Uppgradera till senaste Service Pack och försök igen." +${LangFileString} ADMINERROR "Administrativa rättigheter krävs." +${LangFileString} LOGONERROR "Logon-tjänsten körs ej." +${LangFileString} UACERROR "Kan inte höja UAC-nivån." +${LangFileString} WRITEERROR "Portabel Rainmeter måste installeras på en plats med fullständiga läs- och skrivrättigheter (som vanlig användare).$\nOm du vill installera Rainmeter i '$0', gå tillbaka och välj 'Standardinstallation'.$\n$\nVälj annars en annan plats med fullständiga läs- och skrivrättigheter." +${LangFileString} VCINSTERROR "Installationen av Visual C++ $instArc misslyckades med felkod $0.$\n$\nDu kanske vill prova att ladda ner Visual C++ $instArc distributionspaketet manuellt från http://rainmeter.net/redist$\n$\nTryck OK för att avsluta." +${LangFileString} DOTNETINSTERROR ".NET $instArc installationen misslyckades med felkod $0.$\n$\nDu kanske vill prova att ladda ner .NET $instArc distributionspaketet manuellt från http://rainmeter.net/redist$\n$\nTryck OK för att avsluta." +${LangFileString} RAINMETERCLOSEERROR "Kunde inte stänga Rainmeter.$\n$\nStäng Rainmeter manuellt och försök igen." +${LangFileString} SETTINGSFILEERROR "Inställningsfilen (Rainmeter.ini) ligger i installationsmappen. Att behålla den där kan orsaka problem om datorn används av fler användare eller av någon med begränsade användarrättigheter.$\n$\nVill du flytta filen till mappen Programdata?" +${LangFileString} SETTINGSMOVEERROR "Kan inte flytta filen '$INSTDIR\Rainmeter.ini' till '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Välj installationsspråk." +${LangFileString} INSTALLOPTIONS "Installationsalternativ" +${LangFileString} INSTALLOPTIONSDESC "Välj ytterligare installationsalternativ" +${LangFileString} STANDARDINST "Standardinstallation (rekommenderas)" +${LangFileString} STANDARDINSTDESC "Installerar Rainmeter och hämtar nödvändiga bibliotek." +${LangFileString} PORTABLEINST "Portabel installation" +${LangFileString} PORTABLEINSTDESC "Välj inte detta om du inte vet vad du gör. Genvägar kommer inte att skapas och .rmskin kommer inte att registeras. Visual C++ och .NET 2.0 biblioteken kan behövas att installeras separat." +${LangFileString} AUTOSTARTUP "Starta Rainmeter vid systemstart" +${LangFileString} ADDITIONALOPTIONS "Fler alternativ" +${LangFileString} INSTALL64BIT "Installera 64-bitars version" +${LangFileString} SENDINFORMATION "Skicka Datorns information" +${LangFileString} SENDINFORMATIONDESC "Din Dators Windows version, språk samt hårdvara kapacitet kommer att skickas under installation för att förbättra Rainmeter. Ingen personlig information kommer skickas." +${LangFileString} UNSTALLOPTIONS "Avinstallations-alternativ" +${LangFileString} UNSTALLOPTIONSDESC "Välj andra alternativ" +${LangFileString} UNSTALLRAINMETER "Avinstallera Rainmeter" +${LangFileString} UNSTALLSETTINGS "Ta bort alla personliga inställningar och filer" ${LangFileString} UNSTALLSETTINGSDESC "(inklusive skinn, teman, addons, registerinställningar och Start-menyobjekt)" \ No newline at end of file diff --git a/Language/Turkish.nsh b/Language/Turkish.nsh index 9621082e..c709be5d 100644 --- a/Language/Turkish.nsh +++ b/Language/Turkish.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} Windows 2000 üzerinde çalışmaz. Rainmeter'i Windows 2000 üzerinde kullanmak için, Rainmeter 2.0 sürümünü indirin." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} Windows XP SP2 veya daha sonraki sürümlerini gerektirir. Lütfen son sürüme güncelleyip tekrar deneyin." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} Windows 2003 SP1 veya daha sonraki sürümlerini gerektirir. Lütfen son sürüme güncelleyip tekrar deneyin." -${LangFileString} ADMINERROR "Yönetici hakları gerektirir." -${LangFileString} LOGONERROR "Giriş servisi çalışmıyor." -${LangFileString} UACERROR "Yükseltilemiyor." -${LangFileString} WRITEERROR "Taşınabilir Rainmeter, (normal kullanıcı olarak) tam yazma ve okuma haklarının olduğu bir dizine kurulmalıdır.$\nEğer Rainmeter'ı '$0' dizinine kurmak istiyorsanız, geri dönüp 'Standart kurulum'u seçin.$\n$\nAksi hallerde tam yazma ve okuma hakları olan bir dizin seçin." -${LangFileString} VCINSTERROR "Visual C++ $instArc kurulumu $0 hata kodu ile sonlandı.$\n$\nVisual C++ $instArc dağıtım paketini http://rainmeter.net/redist adresinden kendiniz indirmek isteyebilirsiniz.$\n$\nÇıkmak için Tamam tuşuna basın." -${LangFileString} DOTNETINSTERROR ".NET $instArc kurulumu $0 hata kodu ile sonlandı.$\n$\nVisual C++ $instArc dağıtım paketini http://rainmeter.net/redist adresinden kendiniz indirmek isteyebilirsiniz.$\n$\nÇıkmak için Tamam tuşuna basın." -${LangFileString} RAINMETERCLOSEERROR "Rainmeter kapatılamadı.$\n$\nLütfen Rainmeter'i elle kapatıp yeniden deneyiniz." -${LangFileString} SETTINGSFILEERROR "Kurulum dosyası (Rainmeter.ini) kurulum dizinindedir. Bu dizinde kalması farklı veya yetkisi olmayan kullanıcılar tarafından kullanıldığında sorun yaratabilir.$\n$\nDosyayı uygulama veri dizinine kopyalamak ister misiniz?" -${LangFileString} SETTINGSMOVEERROR "'$INSTDIR\Rainmeter.ini' dosyası '$APPDATA\Rainmeter\Rainmeter.ini' dizinine kopyalanamadı." -${LangFileString} SELECTLANGUAGE "Lütfen kurulum dilini seçiniz." -${LangFileString} INSTALLOPTIONS "Kurulum Seçenekleri" -${LangFileString} INSTALLOPTIONSDESC "Ek kurulum seçeneklerini seçin" -${LangFileString} STANDARDINST "Standart Kurulum (Önerilen)" -${LangFileString} STANDARDINSTDESC "Rainmeter'i kurar ve gerekli kütüphaneleri indirir." -${LangFileString} PORTABLEINST "Taşınabilir Kurulum" -${LangFileString} PORTABLEINSTDESC "Eğer ne yaptığınızı tam olarak bilmiyorsanız bunu seçmeyin. Kısayollar yaratılmayacak ve .rmskin uzantısı kayıt anahtarına eklenmeyecek. Visual C++ ve .NET 2.0 kütüphanelerinin elle yüklenmesi gerekebilir." -${LangFileString} AUTOSTARTUP "Rainmeter'ı başlangıçta çalıştır" -${LangFileString} ADDITIONALOPTIONS "Ek Seçenekler" -${LangFileString} INSTALL64BIT "64-bit sürümü kur" -${LangFileString} SENDINFORMATION "Bilgisayar hakkındaki bilgileri gönder" -${LangFileString} SENDINFORMATIONDESC "Bilgisayarınızın Windows sürümü, dili ve donanım kapasitesi Rainmeter'ı geliştirmek için kurulum esnasında bir kez rapor edilecektir. Herhangi bir kişisel bilgi gönderilmeyecektir." -${LangFileString} UNSTALLOPTIONS "Kaldırma seçenekleri" -${LangFileString} UNSTALLOPTIONSDESC "Herhangi bir ek seçeneği seçin" -${LangFileString} UNSTALLRAINMETER "Rainmeter'ı kaldır" -${LangFileString} UNSTALLSETTINGS "Tüm kişisel ayar ve dosyaları tamamen kaldır" +${LangFileString} WIN2KERROR "Rainmeter ${VER} Windows 2000 üzerinde çalışmaz. Rainmeter'i Windows 2000 üzerinde kullanmak için, Rainmeter 2.0 sürümünü indirin." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} Windows XP SP2 veya daha sonraki sürümlerini gerektirir. Lütfen son sürüme güncelleyip tekrar deneyin." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} Windows 2003 SP1 veya daha sonraki sürümlerini gerektirir. Lütfen son sürüme güncelleyip tekrar deneyin." +${LangFileString} ADMINERROR "Yönetici hakları gerektirir." +${LangFileString} LOGONERROR "Giriş servisi çalışmıyor." +${LangFileString} UACERROR "Yükseltilemiyor." +${LangFileString} WRITEERROR "Taşınabilir Rainmeter, (normal kullanıcı olarak) tam yazma ve okuma haklarının olduğu bir dizine kurulmalıdır.$\nEğer Rainmeter'ı '$0' dizinine kurmak istiyorsanız, geri dönüp 'Standart kurulum'u seçin.$\n$\nAksi hallerde tam yazma ve okuma hakları olan bir dizin seçin." +${LangFileString} VCINSTERROR "Visual C++ $instArc kurulumu $0 hata kodu ile sonlandı.$\n$\nVisual C++ $instArc dağıtım paketini http://rainmeter.net/redist adresinden kendiniz indirmek isteyebilirsiniz.$\n$\nÇıkmak için Tamam tuşuna basın." +${LangFileString} DOTNETINSTERROR ".NET $instArc kurulumu $0 hata kodu ile sonlandı.$\n$\nVisual C++ $instArc dağıtım paketini http://rainmeter.net/redist adresinden kendiniz indirmek isteyebilirsiniz.$\n$\nÇıkmak için Tamam tuşuna basın." +${LangFileString} RAINMETERCLOSEERROR "Rainmeter kapatılamadı.$\n$\nLütfen Rainmeter'i elle kapatıp yeniden deneyiniz." +${LangFileString} SETTINGSFILEERROR "Kurulum dosyası (Rainmeter.ini) kurulum dizinindedir. Bu dizinde kalması farklı veya yetkisi olmayan kullanıcılar tarafından kullanıldığında sorun yaratabilir.$\n$\nDosyayı uygulama veri dizinine kopyalamak ister misiniz?" +${LangFileString} SETTINGSMOVEERROR "'$INSTDIR\Rainmeter.ini' dosyası '$APPDATA\Rainmeter\Rainmeter.ini' dizinine kopyalanamadı." +${LangFileString} SELECTLANGUAGE "Lütfen kurulum dilini seçiniz." +${LangFileString} INSTALLOPTIONS "Kurulum Seçenekleri" +${LangFileString} INSTALLOPTIONSDESC "Ek kurulum seçeneklerini seçin" +${LangFileString} STANDARDINST "Standart Kurulum (Önerilen)" +${LangFileString} STANDARDINSTDESC "Rainmeter'i kurar ve gerekli kütüphaneleri indirir." +${LangFileString} PORTABLEINST "Taşınabilir Kurulum" +${LangFileString} PORTABLEINSTDESC "Eğer ne yaptığınızı tam olarak bilmiyorsanız bunu seçmeyin. Kısayollar yaratılmayacak ve .rmskin uzantısı kayıt anahtarına eklenmeyecek. Visual C++ ve .NET 2.0 kütüphanelerinin elle yüklenmesi gerekebilir." +${LangFileString} AUTOSTARTUP "Rainmeter'ı başlangıçta çalıştır" +${LangFileString} ADDITIONALOPTIONS "Ek Seçenekler" +${LangFileString} INSTALL64BIT "64-bit sürümü kur" +${LangFileString} SENDINFORMATION "Bilgisayar hakkındaki bilgileri gönder" +${LangFileString} SENDINFORMATIONDESC "Bilgisayarınızın Windows sürümü, dili ve donanım kapasitesi Rainmeter'ı geliştirmek için kurulum esnasında bir kez rapor edilecektir. Herhangi bir kişisel bilgi gönderilmeyecektir." +${LangFileString} UNSTALLOPTIONS "Kaldırma seçenekleri" +${LangFileString} UNSTALLOPTIONSDESC "Herhangi bir ek seçeneği seçin" +${LangFileString} UNSTALLRAINMETER "Rainmeter'ı kaldır" +${LangFileString} UNSTALLSETTINGS "Tüm kişisel ayar ve dosyaları tamamen kaldır" ${LangFileString} UNSTALLSETTINGSDESC "(Kabuklar, temalar, eklentiler, kayıt ayarları ve başlangıç menüsü maddelerini içerir)" \ No newline at end of file diff --git a/Language/Ukrainian.nsh b/Language/Ukrainian.nsh index 038bd7d4..2c684f94 100644 --- a/Language/Ukrainian.nsh +++ b/Language/Ukrainian.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} не підтримує Windows 2000. Щоб використовувати Rainmeter на Windows 2000, закачайте пізню версію Rainmeter 2.0." -${LangFileString} WINXPS2ERROR "Для Rainmeter ${VER} потрібно Windows XP SP2 або вище. Будь ласка оновіть до самого останнього SP і спробуйте знову." -${LangFileString} WIN2003SP1ERROR "Для Rainmeter ${VER} потрібно Windows 2003 SP1 або вище. Будь ласка оновіть до самого останнього SP і спробуйте знову." -${LangFileString} ADMINERROR "Потрібні права Адміністратора." -${LangFileString} LOGONERROR "Служба входу в систему не запущена." -${LangFileString} UACERROR "Не вдається підвищити." -${LangFileString} WRITEERROR "Портативний Rainmeter повинен бути встановлений в директорії з повним доступом для читання і запису (як звичайний користувач).$\nЯкщо ви хочете встановити Rainmeter в '$0', поверніться назад і оберіть «Стандартна Установка».$\n$\nВ іншому випадку вкажіть інше розташування з повним доступом для читання і запису." -${LangFileString} VCINSTERROR "Visual C++ $instArc установка завершилася з кодом помилки $0.$\n$\nВи можете спробувати завантажити Visual C++ $instArc розповсюджуваний пакет вручну з http://rainmeter.net/redist$\n$\nНатисніть кнопку OK для виходу. " -${LangFileString} DOTNETINSTERROR ".NET $instArc установка завершилася з кодом помилки $0.$\n$\nВы можете спробувати завантажити .NET $instArc розповсюджуваний пакет вручну з http://rainmeter.net/redist$\n$\nНатисніть кнопку OK для виходу. " -${LangFileString} RAINMETERCLOSEERROR "Не вдалося закрити Rainmeter.$\n$\nБудь ласка закрийте Rainmeter вручну і повторіть спробу." -${LangFileString} SETTINGSFILEERROR "Файл налаштувань (Rainmeter.ini) розташований в папці установки. Знаходження його там може викликати проблеми, якщо програма використовується декількома користувачами або будь-ким з привілеями користувача з обмеженими правами. $\n$\nБажаєте перемістити файл в папку для даних програми?" -${LangFileString} SETTINGSMOVEERROR "Не вдається перемістити файл '$INSTDIR\Rainmeter.ini' в '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Будь ласка, виберіть мову установки." -${LangFileString} INSTALLOPTIONS "Параметри Установки" -${LangFileString} INSTALLOPTIONSDESC "Виберіть додаткові параметри установки" -${LangFileString} STANDARDINST "Стандартна установка (рекомендується)" -${LangFileString} STANDARDINSTDESC "Встановити Rainmeter і завантажити необхідні бібліотеки." -${LangFileString} PORTABLEINST "Портативна установка" -${LangFileString} PORTABLEINSTDESC "Не вибирайте це, якщо ви не знаєте, що ви робите. Ярлики не будуть створені і. rmskin розширення буде не зареєстровано. Може знадобитися вручну встановити Visual C++ і .NET 2.0 бібліотеки." -${LangFileString} AUTOSTARTUP "Запускати Rainmeter при старті системи" -${LangFileString} ADDITIONALOPTIONS "Додаткові налаштування" -${LangFileString} INSTALL64BIT "Встановити 64-розрядну версію" -${LangFileString} SENDINFORMATION "Відправити інформацію про комп'ютер" -${LangFileString} SENDINFORMATIONDESC "Версія Windows, мова а також можливості обладнання, будуть відправлені одноразово під час установки для поліпшення Rainmeter. Ніякі особисті дані не будуть відправлені." -${LangFileString} UNSTALLOPTIONS "Настройки Видалення" -${LangFileString} UNSTALLOPTIONSDESC "Виберіть будь-які додаткові опції" -${LangFileString} UNSTALLRAINMETER "Видалити Rainmeter" -${LangFileString} UNSTALLSETTINGS "Повністю видалити всі особисті настройки та файли" +${LangFileString} WIN2KERROR "Rainmeter ${VER} не підтримує Windows 2000. Щоб використовувати Rainmeter на Windows 2000, закачайте пізню версію Rainmeter 2.0." +${LangFileString} WINXPS2ERROR "Для Rainmeter ${VER} потрібно Windows XP SP2 або вище. Будь ласка оновіть до самого останнього SP і спробуйте знову." +${LangFileString} WIN2003SP1ERROR "Для Rainmeter ${VER} потрібно Windows 2003 SP1 або вище. Будь ласка оновіть до самого останнього SP і спробуйте знову." +${LangFileString} ADMINERROR "Потрібні права Адміністратора." +${LangFileString} LOGONERROR "Служба входу в систему не запущена." +${LangFileString} UACERROR "Не вдається підвищити." +${LangFileString} WRITEERROR "Портативний Rainmeter повинен бути встановлений в директорії з повним доступом для читання і запису (як звичайний користувач).$\nЯкщо ви хочете встановити Rainmeter в '$0', поверніться назад і оберіть «Стандартна Установка».$\n$\nВ іншому випадку вкажіть інше розташування з повним доступом для читання і запису." +${LangFileString} VCINSTERROR "Visual C++ $instArc установка завершилася з кодом помилки $0.$\n$\nВи можете спробувати завантажити Visual C++ $instArc розповсюджуваний пакет вручну з http://rainmeter.net/redist$\n$\nНатисніть кнопку OK для виходу. " +${LangFileString} DOTNETINSTERROR ".NET $instArc установка завершилася з кодом помилки $0.$\n$\nВы можете спробувати завантажити .NET $instArc розповсюджуваний пакет вручну з http://rainmeter.net/redist$\n$\nНатисніть кнопку OK для виходу. " +${LangFileString} RAINMETERCLOSEERROR "Не вдалося закрити Rainmeter.$\n$\nБудь ласка закрийте Rainmeter вручну і повторіть спробу." +${LangFileString} SETTINGSFILEERROR "Файл налаштувань (Rainmeter.ini) розташований в папці установки. Знаходження його там може викликати проблеми, якщо програма використовується декількома користувачами або будь-ким з привілеями користувача з обмеженими правами. $\n$\nБажаєте перемістити файл в папку для даних програми?" +${LangFileString} SETTINGSMOVEERROR "Не вдається перемістити файл '$INSTDIR\Rainmeter.ini' в '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Будь ласка, виберіть мову установки." +${LangFileString} INSTALLOPTIONS "Параметри Установки" +${LangFileString} INSTALLOPTIONSDESC "Виберіть додаткові параметри установки" +${LangFileString} STANDARDINST "Стандартна установка (рекомендується)" +${LangFileString} STANDARDINSTDESC "Встановити Rainmeter і завантажити необхідні бібліотеки." +${LangFileString} PORTABLEINST "Портативна установка" +${LangFileString} PORTABLEINSTDESC "Не вибирайте це, якщо ви не знаєте, що ви робите. Ярлики не будуть створені і. rmskin розширення буде не зареєстровано. Може знадобитися вручну встановити Visual C++ і .NET 2.0 бібліотеки." +${LangFileString} AUTOSTARTUP "Запускати Rainmeter при старті системи" +${LangFileString} ADDITIONALOPTIONS "Додаткові налаштування" +${LangFileString} INSTALL64BIT "Встановити 64-розрядну версію" +${LangFileString} SENDINFORMATION "Відправити інформацію про комп'ютер" +${LangFileString} SENDINFORMATIONDESC "Версія Windows, мова а також можливості обладнання, будуть відправлені одноразово під час установки для поліпшення Rainmeter. Ніякі особисті дані не будуть відправлені." +${LangFileString} UNSTALLOPTIONS "Настройки Видалення" +${LangFileString} UNSTALLOPTIONSDESC "Виберіть будь-які додаткові опції" +${LangFileString} UNSTALLRAINMETER "Видалити Rainmeter" +${LangFileString} UNSTALLSETTINGS "Повністю видалити всі особисті настройки та файли" ${LangFileString} UNSTALLSETTINGSDESC "(включаючи скіни, теми, аддони, параметри реєстру та елементи меню Пуск)" \ No newline at end of file diff --git a/Language/Vietnamese.nsh b/Language/Vietnamese.nsh index 1312c3db..d21a9e1f 100644 --- a/Language/Vietnamese.nsh +++ b/Language/Vietnamese.nsh @@ -1,29 +1,29 @@ -${LangFileString} WIN2KERROR "Rainmeter ${VER} không hỗ trợ Windows 2000. Để sử dụng Rainmeter trên Windows 2000, tải bản cũ hơn phiên bản Rainmeter 2.0." -${LangFileString} WINXPS2ERROR "Rainmeter ${VER} yêu cầu Windows XP SP2 hoặc hơn. Vui lòng nâng cấp lên gói mới nhất và thử lại." -${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} yêu cầu Windows 2003 SP1 hoặc hơn. Vui lòng nâng cấp lên gói mới nhất và thử lại." -${LangFileString} ADMINERROR "Yêu cầu quyền Admin." -${LangFileString} LOGONERROR "Truy cập hệ thống không hoạt động." -${LangFileString} UACERROR "Không thể nâng cấp." -${LangFileString} WRITEERROR "Portable Rainmeter phải được cài đặt tại địa chỉ có thể đọc và viết được (tức là sử dụng bình thường).$\nNếu bạn muốn cài đặt Rainmeter tại '$0', quay lại và chọn 'Cài đặt thông thường'.$\n$\nCòn không, tìm một địa chỉ nào đó có thể đọc và viết được." -${LangFileString} VCINSTERROR "Visual C++ $instArc đã cài đặt thất bại error code $0.$\n$\nBạn có muốn thử tải bằng tay Visual C++ $instArc đã được đóng gói phân phối từ http://rainmeter.net/redist$\n$\nẤn OK để thoát." -${LangFileString} DOTNETINSTERROR ".NET $instArc đã cài đặt thất bại error code $0.$\n$\nBạn có muốn thử tải bằng tay .NET $instArc đã được đóng gói phân phối từ http://rainmeter.net/redist$\n$\nẤn OK để thoát." -${LangFileString} RAINMETERCLOSEERROR "Thất bại khi đóng Rainmeter.$\n$\nVui lòng đóng Rainmeter bằng tay và thử lại." -${LangFileString} SETTINGSFILEERROR "File cấu hình (Rainmeter.ini) đã có ở trong thư mục cài đặt. Giữ nó ở đây có thể gây vấn đề nếu ứng dụng được sử dụng bởi nhiều người hoặc bất kỳ ai với quyền sử dụng bị hạn chế.$\n$\nBạn có muốn chuyển file vào thư mục dữ liệu của ứng dụng?" -${LangFileString} SETTINGSMOVEERROR "Không thể di chuyển file '$INSTDIR\Rainmeter.ini' đến '$APPDATA\Rainmeter\Rainmeter.ini'." -${LangFileString} SELECTLANGUAGE "Vui lòng lựa chọn ngôn ngữ cài đặt." -${LangFileString} INSTALLOPTIONS "Tùy chọn cài đặt" -${LangFileString} INSTALLOPTIONSDESC "Chọn bổ sung tùy chọn cài đặt" -${LangFileString} STANDARDINST "Cài đặt thông thường (khuyến nghị)" -${LangFileString} STANDARDINSTDESC "Cài đặt Rainmeter và tải về dữ liệu được yêu cầu." -${LangFileString} PORTABLEINST "Bản cài đặt Portable" -${LangFileString} PORTABLEINSTDESC "Không chọn nếu như bạn không biết mình đang làm gì. Sẽ không có shortcut nào được tạo và phần đuôi .rmskin sẽ không được nhận diện. Thư viện Visual C++ và .NET 2.0 sẽ phải tự cài bằng tay." -${LangFileString} AUTOSTARTUP "Chạy Rainmeter cùng window" -${LangFileString} ADDITIONALOPTIONS "Lựa chọn bổ sung" -${LangFileString} INSTALL64BIT "Cài đặt phiên bản 64 bit" -${LangFileString} SENDINFORMATION "Gửi đi thông tin của máy tính" -${LangFileString} SENDINFORMATIONDESC "Phiên bản của Window, ngôn ngữ, và hiệu năng phần cứng sẽ được gửi đi một lần trong quá trình cài đặt để giúp Rainmeter hoàn thiện hơn. Sẽ không có bất kỳ thông tin cá nhân nào bị gửi đi." -${LangFileString} UNSTALLOPTIONS "Tùy chọn gỡ cài đặt" -${LangFileString} UNSTALLOPTIONSDESC "Chọn và thêm các lựa chọn bổ sung" -${LangFileString} UNSTALLRAINMETER "Gỡ cài đặt Rainmeter" -${LangFileString} UNSTALLSETTINGS "Gỡ bỏ hoàn toàn các tùy chọn cá nhân và các tệp tin" +${LangFileString} WIN2KERROR "Rainmeter ${VER} không hỗ trợ Windows 2000. Để sử dụng Rainmeter trên Windows 2000, tải bản cũ hơn phiên bản Rainmeter 2.0." +${LangFileString} WINXPS2ERROR "Rainmeter ${VER} yêu cầu Windows XP SP2 hoặc hơn. Vui lòng nâng cấp lên gói mới nhất và thử lại." +${LangFileString} WIN2003SP1ERROR "Rainmeter ${VER} yêu cầu Windows 2003 SP1 hoặc hơn. Vui lòng nâng cấp lên gói mới nhất và thử lại." +${LangFileString} ADMINERROR "Yêu cầu quyền Admin." +${LangFileString} LOGONERROR "Truy cập hệ thống không hoạt động." +${LangFileString} UACERROR "Không thể nâng cấp." +${LangFileString} WRITEERROR "Portable Rainmeter phải được cài đặt tại địa chỉ có thể đọc và viết được (tức là sử dụng bình thường).$\nNếu bạn muốn cài đặt Rainmeter tại '$0', quay lại và chọn 'Cài đặt thông thường'.$\n$\nCòn không, tìm một địa chỉ nào đó có thể đọc và viết được." +${LangFileString} VCINSTERROR "Visual C++ $instArc đã cài đặt thất bại error code $0.$\n$\nBạn có muốn thử tải bằng tay Visual C++ $instArc đã được đóng gói phân phối từ http://rainmeter.net/redist$\n$\nẤn OK để thoát." +${LangFileString} DOTNETINSTERROR ".NET $instArc đã cài đặt thất bại error code $0.$\n$\nBạn có muốn thử tải bằng tay .NET $instArc đã được đóng gói phân phối từ http://rainmeter.net/redist$\n$\nẤn OK để thoát." +${LangFileString} RAINMETERCLOSEERROR "Thất bại khi đóng Rainmeter.$\n$\nVui lòng đóng Rainmeter bằng tay và thử lại." +${LangFileString} SETTINGSFILEERROR "File cấu hình (Rainmeter.ini) đã có ở trong thư mục cài đặt. Giữ nó ở đây có thể gây vấn đề nếu ứng dụng được sử dụng bởi nhiều người hoặc bất kỳ ai với quyền sử dụng bị hạn chế.$\n$\nBạn có muốn chuyển file vào thư mục dữ liệu của ứng dụng?" +${LangFileString} SETTINGSMOVEERROR "Không thể di chuyển file '$INSTDIR\Rainmeter.ini' đến '$APPDATA\Rainmeter\Rainmeter.ini'." +${LangFileString} SELECTLANGUAGE "Vui lòng lựa chọn ngôn ngữ cài đặt." +${LangFileString} INSTALLOPTIONS "Tùy chọn cài đặt" +${LangFileString} INSTALLOPTIONSDESC "Chọn bổ sung tùy chọn cài đặt" +${LangFileString} STANDARDINST "Cài đặt thông thường (khuyến nghị)" +${LangFileString} STANDARDINSTDESC "Cài đặt Rainmeter và tải về dữ liệu được yêu cầu." +${LangFileString} PORTABLEINST "Bản cài đặt Portable" +${LangFileString} PORTABLEINSTDESC "Không chọn nếu như bạn không biết mình đang làm gì. Sẽ không có shortcut nào được tạo và phần đuôi .rmskin sẽ không được nhận diện. Thư viện Visual C++ và .NET 2.0 sẽ phải tự cài bằng tay." +${LangFileString} AUTOSTARTUP "Chạy Rainmeter cùng window" +${LangFileString} ADDITIONALOPTIONS "Lựa chọn bổ sung" +${LangFileString} INSTALL64BIT "Cài đặt phiên bản 64 bit" +${LangFileString} SENDINFORMATION "Gửi đi thông tin của máy tính" +${LangFileString} SENDINFORMATIONDESC "Phiên bản của Window, ngôn ngữ, và hiệu năng phần cứng sẽ được gửi đi một lần trong quá trình cài đặt để giúp Rainmeter hoàn thiện hơn. Sẽ không có bất kỳ thông tin cá nhân nào bị gửi đi." +${LangFileString} UNSTALLOPTIONS "Tùy chọn gỡ cài đặt" +${LangFileString} UNSTALLOPTIONSDESC "Chọn và thêm các lựa chọn bổ sung" +${LangFileString} UNSTALLRAINMETER "Gỡ cài đặt Rainmeter" +${LangFileString} UNSTALLSETTINGS "Gỡ bỏ hoàn toàn các tùy chọn cá nhân và các tệp tin" ${LangFileString} UNSTALLSETTINGSDESC "(bao gồm skin, chủ đề, trình cắm, cấu hình, và thư mục trong Start menu)" \ No newline at end of file diff --git a/Library/CommandHandler.cpp b/Library/CommandHandler.cpp index 285945a4..389fa69d 100644 --- a/Library/CommandHandler.cpp +++ b/Library/CommandHandler.cpp @@ -1,950 +1,950 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../Common/PathUtil.h" -#include "CommandHandler.h" -#include "ConfigParser.h" -#include "DialogAbout.h" -#include "DialogManage.h" -#include "Measure.h" -#include "Logger.h" -#include "Rainmeter.h" -#include "System.h" -#include "TrayWindow.h" -#include "resource.h" - -namespace { - -typedef void (* BangHandlerFunc)(std::vector& args, MeterWindow* skin); - -struct BangInfo -{ - Bang bang; - WCHAR* name; - uint8_t argCount; -}; - -struct CustomBangInfo -{ - Bang bang; - WCHAR* name; - BangHandlerFunc handlerFunc; -}; - -// Bangs that are to be handled with DoBang(). -const BangInfo s_Bangs[] = -{ - { Bang::Refresh, L"Refresh", 0 }, - { Bang::Redraw, L"Redraw", 0 }, - { Bang::Update, L"Update", 0 }, - { Bang::Hide, L"Hide", 0 }, - { Bang::Show, L"Show", 0 }, - { Bang::Toggle, L"Toggle", 0 }, - { Bang::HideFade, L"HideFade", 0 }, - { Bang::ShowFade, L"ShowFade", 0 }, - { Bang::ToggleFade, L"ToggleFade", 0 }, - { Bang::HideMeter, L"HideMeter", 1 }, - { Bang::ShowMeter, L"ShowMeter", 1 }, - { Bang::ToggleMeter, L"ToggleMeter", 1 }, - { Bang::MoveMeter, L"MoveMeter", 3 }, - { Bang::UpdateMeter, L"UpdateMeter", 1 }, - { Bang::DisableMeasure, L"DisableMeasure", 1 }, - { Bang::EnableMeasure, L"EnableMeasure", 1 }, - { Bang::ToggleMeasure, L"ToggleMeasure", 1 }, - { Bang::PauseMeasure, L"PauseMeasure", 1 }, - { Bang::UnpauseMeasure, L"UnpauseMeasure", 1 }, - { Bang::TogglePauseMeasure, L"TogglePauseMeasure", 1 }, - { Bang::UpdateMeasure, L"UpdateMeasure", 1 }, - { Bang::CommandMeasure, L"CommandMeasure", 2 }, - { Bang::PluginBang, L"PluginBang", 1 }, - { Bang::ShowBlur, L"ShowBlur", 0 }, - { Bang::HideBlur, L"HideBlur", 0 }, - { Bang::ToggleBlur, L"ToggleBlur", 0 }, - { Bang::AddBlur, L"AddBlur", 1 }, - { Bang::RemoveBlur, L"RemoveBlur", 1 }, - { Bang::Move, L"Move", 2 }, - { Bang::ZPos, L"ZPos", 1 }, - { Bang::ZPos, L"ChangeZPos", 1 }, // For backwards compatibility. - { Bang::ChangeZPos, L"ChangeZPos", 1 }, - { Bang::ClickThrough, L"ClickThrough", 1 }, - { Bang::Draggable, L"Draggable", 1 }, - { Bang::SnapEdges, L"SnapEdges", 1 }, - { Bang::KeepOnScreen, L"KeepOnScreen", 1 }, - { Bang::SetTransparency, L"SetTransparency", 1 }, - { Bang::SetVariable, L"SetVariable", 2 }, - { Bang::SetOption, L"SetOption", 3 }, - { Bang::SetOptionGroup, L"SetOptionGroup", 3 }, - { Bang::HideMeterGroup, L"HideMeterGroup", 1 }, - { Bang::ShowMeterGroup, L"ShowMeterGroup", 1 }, - { Bang::ToggleMeterGroup, L"ToggleMeterGroup", 1 }, - { Bang::UpdateMeterGroup, L"UpdateMeterGroup", 1 }, - { Bang::DisableMeasureGroup, L"DisableMeasureGroup", 1 }, - { Bang::EnableMeasureGroup, L"EnableMeasureGroup", 1 }, - { Bang::ToggleMeasureGroup, L"ToggleMeasureGroup", 1 }, - { Bang::PauseMeasureGroup, L"PauseMeasureGroup", 1 }, - { Bang::UnpauseMeasureGroup, L"UnpauseMeasureGroup", 1 }, - { Bang::TogglePauseMeasureGroup, L"TogglePauseMeasureGroup", 1 }, - { Bang::UpdateMeasureGroup, L"UpdateMeasureGroup", 1 }, - { Bang::SkinCustomMenu, L"SkinCustomMenu", 0 } -}; - -// Bangs that are to be handled with DoGroupBang(). -// TODO: Better handling of Bang-id -const BangInfo s_GroupBangs[] = -{ - { Bang::Refresh, L"RefreshGroup", 0 }, - { Bang::Update, L"UpdateGroup", 0 }, - { Bang::Redraw, L"RedrawGroup", 0 }, - { Bang::Hide, L"HideGroup", 0 }, - { Bang::Show, L"ShowGroup", 0 }, - { Bang::Toggle, L"ToggleGroup", 0 }, - { Bang::HideFade, L"HideFadeGroup", 0 }, - { Bang::ShowFade, L"ShowFadeGroup", 0 }, - { Bang::ToggleFade, L"ToggleFadeGroup", 0 }, - { Bang::ZPos, L"ZPosGroup", 1 }, - { Bang::ClickThrough, L"ClickThroughGroup", 1 }, - { Bang::Draggable, L"DraggableGroup", 1 }, - { Bang::SnapEdges, L"SnapEdgesGroup", 1 }, - { Bang::KeepOnScreen, L"KeepOnScreenGroup", 1 }, - { Bang::SetTransparency, L"SetTransparencyGroup", 1 }, - { Bang::SetVariable, L"SetVariableGroup", 2 } -}; - -// Bangs that are to be handled using a custom handler function. -const CustomBangInfo s_CustomBangs[] = -{ - { Bang::ActivateConfig, L"ActivateConfig", CommandHandler::DoActivateSkinBang }, - { Bang::DeactivateConfig, L"DeactivateConfig", CommandHandler::DoDeactivateSkinBang }, - { Bang::ToggleConfig, L"ToggleConfig", CommandHandler::DoToggleSkinBang }, - { Bang::DeactivateConfigGroup, L"DeactivateConfigGroup", CommandHandler::DoDeactivateSkinGroupBang }, - { Bang::WriteKeyValue, L"WriteKeyValue", CommandHandler::DoWriteKeyValueBang }, - { Bang::LoadLayout, L"LoadLayout", CommandHandler::DoLoadLayoutBang }, - { Bang::SetClip, L"SetClip", CommandHandler::DoSetClipBang }, - { Bang::SetWallpaper, L"SetWallpaper", CommandHandler::DoSetWallpaperBang }, - { Bang::About, L"About", CommandHandler::DoAboutBang }, - { Bang::Manage, L"Manage", CommandHandler::DoManageBang }, - { Bang::SkinMenu, L"SkinMenu", CommandHandler::DoSkinMenuBang }, - { Bang::TrayMenu, L"TrayMenu", CommandHandler::DoTrayMenuBang }, - { Bang::ResetStats, L"ResetStats", CommandHandler::DoResetStatsBang }, - { Bang::Log, L"Log", CommandHandler::DoLogBang }, - { Bang::RefreshApp, L"RefreshApp", CommandHandler::DoRefreshApp }, - { Bang::Quit, L"Quit", CommandHandler::DoQuitBang }, - { Bang::LsBoxHook, L"LsBoxHook", CommandHandler::DoLsBoxHookBang } -}; - -void DoBang(const BangInfo& bangInfo, std::vector& args, MeterWindow* skin) -{ - const size_t argsCount = args.size(); - if (argsCount >= bangInfo.argCount) - { - if (argsCount == bangInfo.argCount && skin) - { - skin->DoBang(bangInfo.bang, args); - } - else - { - // Use the specified window instead of skin parameter. - if (argsCount > bangInfo.argCount) - { - const std::wstring& folderPath = args[bangInfo.argCount]; - if (!folderPath.empty() && (folderPath.length() != 1 || folderPath[0] != L'*')) - { - MeterWindow* meterWindow = Rainmeter::GetInstance().GetMeterWindow(folderPath); - if (meterWindow) - { - meterWindow->DoBang(bangInfo.bang, args); - } - else - { - LogErrorF(skin, L"!%s: Skin \"%s\" not found", bangInfo.name, folderPath.c_str()); - } - return; - } - } - - // No skin defined -> apply to all. - for (const auto& ip : Rainmeter::GetInstance().GetAllMeterWindows()) - { - ip.second->DoBang(bangInfo.bang, args); - } - } - } - else - { - // For backwards compatibility. - if (bangInfo.bang == Bang::CommandMeasure && argsCount >= 1) - { - std::wstring& firstArg = args[0]; - std::wstring::size_type pos = firstArg.find_first_of(L' '); - if (pos != std::wstring::npos) - { - std::wstring newArg = firstArg.substr(0, pos); - firstArg.erase(0, pos + 1); - args.insert(args.begin(), newArg); - - LogWarningF(skin, L"!%s: Two parameters required, only one given", bangInfo.name); - DoBang(bangInfo, args, skin); - return; - } - } - - LogErrorF(skin, L"!%s: Incorrect number of arguments", bangInfo.name); - } -} - -void DoGroupBang(const BangInfo& bangInfo, std::vector& args, MeterWindow* skin) -{ - if (args.size() > bangInfo.argCount) - { - std::multimap windows; - Rainmeter::GetInstance().GetMeterWindowsByLoadOrder(windows, args[bangInfo.argCount]); - - // Remove extra parameters (including group). - args.resize(bangInfo.argCount); - - for (const auto& ip : windows) - { - DoBang(bangInfo, args, ip.second); - } - } - else - { - LogErrorF(skin, L"!%s: Incorrect number of arguments", bangInfo.name); - } -} - -} // namespace - -/* -** Parses and executes the given command. -** -*/ -void CommandHandler::ExecuteCommand(const WCHAR* command, MeterWindow* skin, bool multi) -{ - if (command[0] == L'!') // Bang - { - ++command; // Skip "!" - - if (_wcsnicmp(L"Execute", command, 7) == 0) - { - command += 7; - command = wcschr(command, L'['); - if (!command) return; - } - else - { - if (_wcsnicmp(command, L"Rainmeter", 9) == 0) - { - // Skip "Rainmeter" for backwards compatibility - command += 9; - } - - std::wstring bang; - std::vector args; - - // Find the first space - const WCHAR* pos = wcschr(command, L' '); - if (pos) - { - bang.assign(command, 0, pos - command); - args = ParseString(pos + 1, skin ? &skin->GetParser() : nullptr); - } - else - { - bang = command; - } - - ExecuteBang(bang.c_str(), args, skin); - return; - } - } - - if (multi && command[0] == L'[') // Multi-bang - { - std::wstring bangs = command; - std::wstring::size_type start = std::wstring::npos; - int count = 0; - for (size_t i = 0, isize = bangs.size(); i < isize; ++i) - { - if (bangs[i] == L'[') - { - if (count == 0) - { - start = i; - } - ++count; - } - else if (bangs[i] == L']') - { - --count; - - if (count == 0 && start != std::wstring::npos) - { - // Change ] to nullptr - bangs[i] = L'\0'; - - // Skip whitespace - start = bangs.find_first_not_of(L" \t\r\n", start + 1, 4); - - ExecuteCommand(bangs.c_str() + start, skin, false); - } - } - else if (bangs[i] == L'"' && isize > (i + 2) && bangs[i + 1] == L'"' && bangs[i + 2] == L'"') - { - i += 3; - - std::wstring::size_type pos = bangs.find(L"\"\"\"", i); - if (pos != std::wstring::npos) - { - i = pos + 2; // Skip "", loop will skip last " - } - } - } - } - else - { - // Check for built-ins - if (_wcsnicmp(L"PLAY", command, 4) == 0) - { - if (command[4] == L' ' || // PLAY - _wcsnicmp(L"LOOP ", &command[4], 5) == 0) // PLAYLOOP - { - command += 4; // Skip PLAY - - DWORD flags = SND_FILENAME | SND_ASYNC; - - if (command[0] != L' ') - { - flags |= SND_LOOP | SND_NODEFAULT; - command += 4; // Skip LOOP - } - - ++command; // Skip the space - if (command[0] != L'\0') - { - std::wstring sound = command; - - // Strip the quotes - std::wstring::size_type len = sound.length(); - if (len >= 2 && sound[0] == L'"' && sound[len - 1] == L'"') - { - len -= 2; - sound.assign(sound, 1, len); - } - - if (skin) - { - skin->GetParser().ReplaceMeasures(sound); - skin->MakePathAbsolute(sound); - } - - PlaySound(sound.c_str(), nullptr, flags); - } - return; - } - else if (_wcsnicmp(L"STOP", &command[4], 4) == 0) // PLAYSTOP - { - PlaySound(nullptr, nullptr, SND_PURGE); - return; - } - } - - // Run command - std::wstring tmpSz = command; - if (skin) - { - skin->GetParser().ReplaceMeasures(tmpSz); - } - RunCommand(tmpSz); - } -} - -/* -** Runs the given bang. -** -*/ -void CommandHandler::ExecuteBang(const WCHAR* name, std::vector& args, MeterWindow* skin) -{ - for (const auto& bangInfo : s_Bangs) - { - if (_wcsicmp(bangInfo.name, name) == 0) - { - DoBang(bangInfo, args, skin); - return; - } - } - - for (const auto& bangInfo : s_GroupBangs) - { - if (_wcsicmp(bangInfo.name, name) == 0) - { - DoGroupBang(bangInfo, args, skin); - return; - } - } - - for (const auto& bangInfo : s_CustomBangs) - { - if (_wcsicmp(bangInfo.name, name) == 0) - { - bangInfo.handlerFunc(args, skin); - return; - } - } - - LogErrorF(skin, L"Invalid bang: !%s", name); -} - -/* -** Parses and runs the given command. -** -*/ -void CommandHandler::RunCommand(std::wstring command) -{ - std::wstring args; - - size_t notwhite = command.find_first_not_of(L" \t\r\n"); - command.erase(0, notwhite); - - size_t quotePos = command.find(L'"'); - if (quotePos == 0) - { - size_t quotePos2 = command.find(L'"', quotePos + 1); - if (quotePos2 != std::wstring::npos) - { - args.assign(command, quotePos2 + 1, command.length() - (quotePos2 + 1)); - command.assign(command, quotePos + 1, quotePos2 - quotePos - 1); - } - else - { - command.erase(0, 1); - } - } - else - { - size_t spacePos = command.find(L' '); - if (spacePos != std::wstring::npos) - { - args.assign(command, spacePos + 1, command.length() - (spacePos + 1)); - command.erase(spacePos); - } - } - - if (!command.empty()) - { - RunFile(command.c_str(), args.c_str()); - } -} - -/* -** Runs a file with the given arguments. -** -*/ -void CommandHandler::RunFile(const WCHAR* file, const WCHAR* args) -{ - SHELLEXECUTEINFO si = {sizeof(SHELLEXECUTEINFO)}; - si.lpVerb = L"open"; - si.lpFile = file; - si.nShow = SW_SHOWNORMAL; - - DWORD type = GetFileAttributes(si.lpFile); - if (type & FILE_ATTRIBUTE_DIRECTORY && type != 0xFFFFFFFF) - { - ShellExecute(si.hwnd, si.lpVerb, si.lpFile, nullptr, nullptr, si.nShow); - } - else - { - std::wstring dir = PathUtil::GetFolderFromFilePath(file); - si.lpDirectory = dir.c_str(); - si.lpParameters = args; - si.fMask = SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI; - ShellExecuteEx(&si); - } -} - -/* -** Splits strings into parts. -** -*/ -std::vector CommandHandler::ParseString(LPCTSTR str, ConfigParser* parser) -{ - std::vector result; - - if (str) - { - std::wstring arg = str; - - // Split the argument between first space. - // Or if string is in quotes, the after the second quote. - - auto addResult = [&](std::wstring& string, bool stripQuotes) - { - if (stripQuotes) - { - size_t pos = 0; - do - { - pos = string.find(L'"', pos); - if (pos != std::wstring::npos) - { - string.erase(pos, 1); - } - } - while (pos != std::wstring::npos); - } - - if (parser) - { - parser->ReplaceMeasures(string); - } - - result.push_back(string); - }; - - size_t pos; - std::wstring newStr; - while ((pos = arg.find_first_not_of(L' ')) != std::wstring::npos) - { - size_t extra = 1; - if (arg[pos] == L'"') - { - if (arg.size() > (pos + 2) && - arg[pos + 1] == L'"' && arg[pos + 2] == L'"') - { - // Eat found quotes and finding ending """ - arg.erase(0, pos + 3); - - extra = 4; - if ((pos = arg.find(L"\"\"\" ")) == std::wstring::npos) - { - extra = 3; - pos = arg.rfind(L"\"\"\""); // search backward - } - } - else - { - // Eat found quote and find ending quote - arg.erase(0, pos + 1); - pos = arg.find_first_of(L'"'); - } - } - else - { - if (pos > 0) - { - // Eat everything until non-space (and non-quote) char - arg.erase(0, pos); - } - - // Find the second quote - pos = arg.find_first_of(L' '); - } - - if (pos != std::wstring::npos) - { - newStr.assign(arg, 0, pos); - arg.erase(0, pos + extra); - - addResult(newStr, extra == 1); - } - else // quote or space not found - { - addResult(arg, extra == 1); - arg.clear(); - break; - } - } - - if (!arg.empty() && result.empty()) - { - addResult(arg, true); - } - } - - return result; -} - -void CommandHandler::DoActivateSkinBang(std::vector& args, MeterWindow* skin) -{ - if (args.size() == 1) - { - if (Rainmeter::GetInstance().ActivateSkin(args[0])) return; - } - else if (args.size() > 1) - { - if (Rainmeter::GetInstance().ActivateSkin(args[0], args[1])) return; - } - - LogErrorF(skin, L"!ActivateConfig: Invalid parameters"); -} - -void CommandHandler::DoDeactivateSkinBang(std::vector& args, MeterWindow* skin) -{ - if (!args.empty()) - { - skin = Rainmeter::GetInstance().GetMeterWindow(args[0]); - if (!skin) - { - LogWarningF(L"!DeactivateConfig: \"%s\" not active", args[0].c_str()); - return; - } - } - - if (skin) - { - Rainmeter::GetInstance().DeactivateSkin(skin, -1); - } - else - { - LogError(L"!DeactivateConfig: Invalid parameters"); - } -} - -void CommandHandler::DoToggleSkinBang(std::vector& args, MeterWindow* skin) -{ - if (args.size() >= 2) - { - MeterWindow* meterWindow = Rainmeter::GetInstance().GetMeterWindow(args[0]); - if (meterWindow) - { - Rainmeter::GetInstance().DeactivateSkin(meterWindow, -1); - return; - } - - // If the skin wasn't active, activate it. - DoActivateSkinBang(args, nullptr); - } - else - { - LogErrorF(skin, L"!ToggleConfig: Invalid parameters"); - } -} - -void CommandHandler::DoDeactivateSkinGroupBang(std::vector& args, MeterWindow* skin) -{ - if (!args.empty()) - { - std::multimap windows; - Rainmeter::GetInstance().GetMeterWindowsByLoadOrder(windows, args[0]); - for (const auto& ip : windows) - { - Rainmeter::GetInstance().DeactivateSkin(ip.second, -1); - } - } - else - { - LogErrorF(skin, L"!DeactivateConfigGroup: Invalid parameters"); - } -} - -void CommandHandler::DoLoadLayoutBang(std::vector& args, MeterWindow* skin) -{ - if (args.size() == 1) - { - if (skin) - { - // Delay to avoid loading theme in the middle of an update. - std::wstring command = L"!LoadLayout \""; - command += args[0]; - command += L'"'; - Rainmeter::GetInstance().DelayedExecuteCommand(command.c_str()); - } - else - { - // Not called from a skin (or called with delay). - Rainmeter::GetInstance().LoadLayout(args[0]); - } - } -} - -void CommandHandler::DoSetClipBang(std::vector& args, MeterWindow* skin) -{ - if (!args.empty()) - { - System::SetClipboardText(args[0]); - } - else - { - LogErrorF(skin, L"!SetClip: Invalid parameter"); - } -} - -void CommandHandler::DoSetWallpaperBang(std::vector& args, MeterWindow* skin) -{ - const size_t argsSize = args.size(); - if (argsSize >= 1 && argsSize <= 2) - { - std::wstring& file = args[0]; - const std::wstring& style = (argsSize == 2) ? args[1] : L""; - - if (skin) - { - skin->MakePathAbsolute(file); - } - - System::SetWallpaper(file, style); - } - else - { - LogErrorF(skin, L"!SetWallpaper: Invalid parameters"); - } -} - -void CommandHandler::DoAboutBang(std::vector& args, MeterWindow* meterWindow) -{ - DialogAbout::Open(args.empty() ? L"" : args[0].c_str()); -} - -void CommandHandler::DoManageBang(std::vector& args, MeterWindow* meterWindow) -{ - const size_t argsSize = args.size(); - if (argsSize >= 2 && argsSize <= 3) - { - DialogManage::Open(args[0].c_str(), - args[1].c_str(), - (argsSize == 3) ? args[2].c_str() : L""); - } - else if (argsSize <= 1) - { - DialogManage::Open(args.empty() ? L"" : args[0].c_str()); - } - else - { - LogErrorF(meterWindow, L"!Manage: Invalid parameters"); - } -} - -void CommandHandler::DoSkinMenuBang(std::vector& args, MeterWindow* skin) -{ - if (!args.empty()) - { - skin = Rainmeter::GetInstance().GetMeterWindow(args[0]); - if (!skin) - { - LogWarningF(L"!SkinMenu: \"%s\" not active", args[0].c_str()); - return; - } - } - - if (skin) - { - POINT pos = System::GetCursorPosition(); - Rainmeter::GetInstance().ShowContextMenu(pos, skin); - } - else - { - LogError(L"!SkinMenu: Invalid parameter"); - } -} - -void CommandHandler::DoTrayMenuBang(std::vector& args, MeterWindow* skin) -{ - POINT pos = System::GetCursorPosition(); - Rainmeter::GetInstance().ShowContextMenu(pos, nullptr); -} - -void CommandHandler::DoResetStatsBang(std::vector& args, MeterWindow* meterWindow) -{ - Rainmeter::GetInstance().ResetStats(); -} - -void CommandHandler::DoWriteKeyValueBang(std::vector& args, MeterWindow* skin) -{ - if (args.size() == 3 && skin) - { - // Add the skin file path to the args - args.push_back(skin->GetFilePath()); - } - else if (args.size() < 4) - { - LogErrorF(skin, L"!WriteKeyValue: Invalid parameters"); - return; - } - - std::wstring& strIniFile = args[3]; - if (skin) - { - skin->MakePathAbsolute(strIniFile); - } - - const WCHAR* iniFile = strIniFile.c_str(); - - if (strIniFile.find(L"..\\") != std::wstring::npos || strIniFile.find(L"../") != std::wstring::npos) - { - LogErrorF(skin, L"!WriteKeyValue: Illegal path: %s", iniFile); - return; - } - - if (_wcsnicmp(iniFile, Rainmeter::GetInstance().m_SkinPath.c_str(), Rainmeter::GetInstance().m_SkinPath.size()) != 0 && - _wcsnicmp(iniFile, Rainmeter::GetInstance().m_SettingsPath.c_str(), Rainmeter::GetInstance().m_SettingsPath.size()) != 0) - { - LogErrorF(skin, L"!WriteKeyValue: Illegal path: %s", iniFile); - return; - } - - // Verify whether the file exists. - if (_waccess(iniFile, 0) == -1) - { - LogErrorF(skin, L"!WriteKeyValue: File not found: %s", iniFile); - return; - } - - // Verify whether the file is read-only. - DWORD attr = GetFileAttributes(iniFile); - if (attr == -1 || (attr & FILE_ATTRIBUTE_READONLY)) - { - LogWarningF(skin, L"!WriteKeyValue: File is read-only: %s", iniFile); - return; - } - - // Avoid "IniFileMapping" - System::UpdateIniFileMappingList(); - std::wstring strIniWrite = System::GetTemporaryFile(strIniFile); - if (strIniWrite.size() == 1 && strIniWrite[0] == L'?') // error occurred - { - return; - } - - bool temporary = !strIniWrite.empty(); - - if (temporary) - { - if (Rainmeter::GetInstance().GetDebug()) - { - LogDebugF(skin, L"!WriteKeyValue: Writing to: %s (Temp: %s)", iniFile, strIniWrite.c_str()); - } - } - else - { - if (Rainmeter::GetInstance().GetDebug()) - { - LogDebugF(skin, L"!WriteKeyValue: Writing to: %s", iniFile); - } - strIniWrite = strIniFile; - } - - const WCHAR* iniWrite = strIniWrite.c_str(); - const WCHAR* section = args[0].c_str(); - const WCHAR* key = args[1].c_str(); - const std::wstring& strValue = args[2]; - - bool formula = false; - BOOL write = 0; - - if (skin) - { - double value; - formula = skin->GetParser().ParseFormula(strValue, &value); - if (formula) - { - WCHAR buffer[256]; - int len = _snwprintf_s(buffer, _TRUNCATE, L"%.5f", value); - Measure::RemoveTrailingZero(buffer, len); - - write = WritePrivateProfileString(section, key, buffer, iniWrite); - } - } - - if (!formula) - { - write = WritePrivateProfileString(section, key, strValue.c_str(), iniWrite); - } - - if (temporary) - { - if (write != 0) - { - WritePrivateProfileString(nullptr, nullptr, nullptr, iniWrite); // FLUSH - - // Copy the file back. - if (!System::CopyFiles(strIniWrite, strIniFile)) - { - LogErrorF(skin, L"!WriteKeyValue: Failed to copy temporary file to original filepath: %s (Temp: %s)", iniFile, iniWrite); - } - } - else // failed - { - LogErrorF(skin, L"!WriteKeyValue: Failed to write to: %s (Temp: %s)", iniFile, iniWrite); - } - - // Remove the temporary file. - System::RemoveFile(strIniWrite); - } - else - { - if (write == 0) // failed - { - LogErrorF(skin, L"!WriteKeyValue: Failed to write to: %s", iniFile); - } - } -} - -void CommandHandler::DoLogBang(std::vector& args, MeterWindow* skin) -{ - if (!args.empty()) - { - Logger::Level level = Logger::Level::Notice; - if (args.size() > 1) - { - const WCHAR* type = args[1].c_str(); - if (_wcsicmp(type, L"ERROR") == 0) - { - level = Logger::Level::Error; - } - else if (_wcsicmp(type, L"WARNING") == 0) - { - level = Logger::Level::Warning; - } - else if (_wcsicmp(type, L"DEBUG") == 0) - { - level = Logger::Level::Debug; - } - else if (_wcsicmp(type, L"NOTICE") != 0) - { - LogErrorF(skin, L"!Log: Invalid type"); - return; - } - } - - std::wstring source; - if (skin) - { - source = skin->GetSkinPath(); - } - - GetLogger().Log(level, source.c_str(), args[0].c_str()); - } -} - -void CommandHandler::DoRefreshApp(std::vector& args, MeterWindow* meterWindow) -{ - // Refresh needs to be delayed since it crashes if done during Update(). - PostMessage(Rainmeter::GetInstance().m_Window, WM_RAINMETER_DELAYED_REFRESH_ALL, 0, 0); -} - -void CommandHandler::DoQuitBang(std::vector& args, MeterWindow* meterWindow) -{ - // Quit needs to be delayed since it crashes if done during Update(). - PostMessage(Rainmeter::GetInstance().GetTrayWindow()->GetWindow(), WM_COMMAND, MAKEWPARAM(IDM_QUIT, 0), 0); -} - -void CommandHandler::DoLsBoxHookBang(std::vector& args, MeterWindow* meterWindow) -{ - // Deprecated. -} +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../Common/PathUtil.h" +#include "CommandHandler.h" +#include "ConfigParser.h" +#include "DialogAbout.h" +#include "DialogManage.h" +#include "Measure.h" +#include "Logger.h" +#include "Rainmeter.h" +#include "System.h" +#include "TrayWindow.h" +#include "resource.h" + +namespace { + +typedef void (* BangHandlerFunc)(std::vector& args, MeterWindow* skin); + +struct BangInfo +{ + Bang bang; + WCHAR* name; + uint8_t argCount; +}; + +struct CustomBangInfo +{ + Bang bang; + WCHAR* name; + BangHandlerFunc handlerFunc; +}; + +// Bangs that are to be handled with DoBang(). +const BangInfo s_Bangs[] = +{ + { Bang::Refresh, L"Refresh", 0 }, + { Bang::Redraw, L"Redraw", 0 }, + { Bang::Update, L"Update", 0 }, + { Bang::Hide, L"Hide", 0 }, + { Bang::Show, L"Show", 0 }, + { Bang::Toggle, L"Toggle", 0 }, + { Bang::HideFade, L"HideFade", 0 }, + { Bang::ShowFade, L"ShowFade", 0 }, + { Bang::ToggleFade, L"ToggleFade", 0 }, + { Bang::HideMeter, L"HideMeter", 1 }, + { Bang::ShowMeter, L"ShowMeter", 1 }, + { Bang::ToggleMeter, L"ToggleMeter", 1 }, + { Bang::MoveMeter, L"MoveMeter", 3 }, + { Bang::UpdateMeter, L"UpdateMeter", 1 }, + { Bang::DisableMeasure, L"DisableMeasure", 1 }, + { Bang::EnableMeasure, L"EnableMeasure", 1 }, + { Bang::ToggleMeasure, L"ToggleMeasure", 1 }, + { Bang::PauseMeasure, L"PauseMeasure", 1 }, + { Bang::UnpauseMeasure, L"UnpauseMeasure", 1 }, + { Bang::TogglePauseMeasure, L"TogglePauseMeasure", 1 }, + { Bang::UpdateMeasure, L"UpdateMeasure", 1 }, + { Bang::CommandMeasure, L"CommandMeasure", 2 }, + { Bang::PluginBang, L"PluginBang", 1 }, + { Bang::ShowBlur, L"ShowBlur", 0 }, + { Bang::HideBlur, L"HideBlur", 0 }, + { Bang::ToggleBlur, L"ToggleBlur", 0 }, + { Bang::AddBlur, L"AddBlur", 1 }, + { Bang::RemoveBlur, L"RemoveBlur", 1 }, + { Bang::Move, L"Move", 2 }, + { Bang::ZPos, L"ZPos", 1 }, + { Bang::ZPos, L"ChangeZPos", 1 }, // For backwards compatibility. + { Bang::ChangeZPos, L"ChangeZPos", 1 }, + { Bang::ClickThrough, L"ClickThrough", 1 }, + { Bang::Draggable, L"Draggable", 1 }, + { Bang::SnapEdges, L"SnapEdges", 1 }, + { Bang::KeepOnScreen, L"KeepOnScreen", 1 }, + { Bang::SetTransparency, L"SetTransparency", 1 }, + { Bang::SetVariable, L"SetVariable", 2 }, + { Bang::SetOption, L"SetOption", 3 }, + { Bang::SetOptionGroup, L"SetOptionGroup", 3 }, + { Bang::HideMeterGroup, L"HideMeterGroup", 1 }, + { Bang::ShowMeterGroup, L"ShowMeterGroup", 1 }, + { Bang::ToggleMeterGroup, L"ToggleMeterGroup", 1 }, + { Bang::UpdateMeterGroup, L"UpdateMeterGroup", 1 }, + { Bang::DisableMeasureGroup, L"DisableMeasureGroup", 1 }, + { Bang::EnableMeasureGroup, L"EnableMeasureGroup", 1 }, + { Bang::ToggleMeasureGroup, L"ToggleMeasureGroup", 1 }, + { Bang::PauseMeasureGroup, L"PauseMeasureGroup", 1 }, + { Bang::UnpauseMeasureGroup, L"UnpauseMeasureGroup", 1 }, + { Bang::TogglePauseMeasureGroup, L"TogglePauseMeasureGroup", 1 }, + { Bang::UpdateMeasureGroup, L"UpdateMeasureGroup", 1 }, + { Bang::SkinCustomMenu, L"SkinCustomMenu", 0 } +}; + +// Bangs that are to be handled with DoGroupBang(). +// TODO: Better handling of Bang-id +const BangInfo s_GroupBangs[] = +{ + { Bang::Refresh, L"RefreshGroup", 0 }, + { Bang::Update, L"UpdateGroup", 0 }, + { Bang::Redraw, L"RedrawGroup", 0 }, + { Bang::Hide, L"HideGroup", 0 }, + { Bang::Show, L"ShowGroup", 0 }, + { Bang::Toggle, L"ToggleGroup", 0 }, + { Bang::HideFade, L"HideFadeGroup", 0 }, + { Bang::ShowFade, L"ShowFadeGroup", 0 }, + { Bang::ToggleFade, L"ToggleFadeGroup", 0 }, + { Bang::ZPos, L"ZPosGroup", 1 }, + { Bang::ClickThrough, L"ClickThroughGroup", 1 }, + { Bang::Draggable, L"DraggableGroup", 1 }, + { Bang::SnapEdges, L"SnapEdgesGroup", 1 }, + { Bang::KeepOnScreen, L"KeepOnScreenGroup", 1 }, + { Bang::SetTransparency, L"SetTransparencyGroup", 1 }, + { Bang::SetVariable, L"SetVariableGroup", 2 } +}; + +// Bangs that are to be handled using a custom handler function. +const CustomBangInfo s_CustomBangs[] = +{ + { Bang::ActivateConfig, L"ActivateConfig", CommandHandler::DoActivateSkinBang }, + { Bang::DeactivateConfig, L"DeactivateConfig", CommandHandler::DoDeactivateSkinBang }, + { Bang::ToggleConfig, L"ToggleConfig", CommandHandler::DoToggleSkinBang }, + { Bang::DeactivateConfigGroup, L"DeactivateConfigGroup", CommandHandler::DoDeactivateSkinGroupBang }, + { Bang::WriteKeyValue, L"WriteKeyValue", CommandHandler::DoWriteKeyValueBang }, + { Bang::LoadLayout, L"LoadLayout", CommandHandler::DoLoadLayoutBang }, + { Bang::SetClip, L"SetClip", CommandHandler::DoSetClipBang }, + { Bang::SetWallpaper, L"SetWallpaper", CommandHandler::DoSetWallpaperBang }, + { Bang::About, L"About", CommandHandler::DoAboutBang }, + { Bang::Manage, L"Manage", CommandHandler::DoManageBang }, + { Bang::SkinMenu, L"SkinMenu", CommandHandler::DoSkinMenuBang }, + { Bang::TrayMenu, L"TrayMenu", CommandHandler::DoTrayMenuBang }, + { Bang::ResetStats, L"ResetStats", CommandHandler::DoResetStatsBang }, + { Bang::Log, L"Log", CommandHandler::DoLogBang }, + { Bang::RefreshApp, L"RefreshApp", CommandHandler::DoRefreshApp }, + { Bang::Quit, L"Quit", CommandHandler::DoQuitBang }, + { Bang::LsBoxHook, L"LsBoxHook", CommandHandler::DoLsBoxHookBang } +}; + +void DoBang(const BangInfo& bangInfo, std::vector& args, MeterWindow* skin) +{ + const size_t argsCount = args.size(); + if (argsCount >= bangInfo.argCount) + { + if (argsCount == bangInfo.argCount && skin) + { + skin->DoBang(bangInfo.bang, args); + } + else + { + // Use the specified window instead of skin parameter. + if (argsCount > bangInfo.argCount) + { + const std::wstring& folderPath = args[bangInfo.argCount]; + if (!folderPath.empty() && (folderPath.length() != 1 || folderPath[0] != L'*')) + { + MeterWindow* meterWindow = Rainmeter::GetInstance().GetMeterWindow(folderPath); + if (meterWindow) + { + meterWindow->DoBang(bangInfo.bang, args); + } + else + { + LogErrorF(skin, L"!%s: Skin \"%s\" not found", bangInfo.name, folderPath.c_str()); + } + return; + } + } + + // No skin defined -> apply to all. + for (const auto& ip : Rainmeter::GetInstance().GetAllMeterWindows()) + { + ip.second->DoBang(bangInfo.bang, args); + } + } + } + else + { + // For backwards compatibility. + if (bangInfo.bang == Bang::CommandMeasure && argsCount >= 1) + { + std::wstring& firstArg = args[0]; + std::wstring::size_type pos = firstArg.find_first_of(L' '); + if (pos != std::wstring::npos) + { + std::wstring newArg = firstArg.substr(0, pos); + firstArg.erase(0, pos + 1); + args.insert(args.begin(), newArg); + + LogWarningF(skin, L"!%s: Two parameters required, only one given", bangInfo.name); + DoBang(bangInfo, args, skin); + return; + } + } + + LogErrorF(skin, L"!%s: Incorrect number of arguments", bangInfo.name); + } +} + +void DoGroupBang(const BangInfo& bangInfo, std::vector& args, MeterWindow* skin) +{ + if (args.size() > bangInfo.argCount) + { + std::multimap windows; + Rainmeter::GetInstance().GetMeterWindowsByLoadOrder(windows, args[bangInfo.argCount]); + + // Remove extra parameters (including group). + args.resize(bangInfo.argCount); + + for (const auto& ip : windows) + { + DoBang(bangInfo, args, ip.second); + } + } + else + { + LogErrorF(skin, L"!%s: Incorrect number of arguments", bangInfo.name); + } +} + +} // namespace + +/* +** Parses and executes the given command. +** +*/ +void CommandHandler::ExecuteCommand(const WCHAR* command, MeterWindow* skin, bool multi) +{ + if (command[0] == L'!') // Bang + { + ++command; // Skip "!" + + if (_wcsnicmp(L"Execute", command, 7) == 0) + { + command += 7; + command = wcschr(command, L'['); + if (!command) return; + } + else + { + if (_wcsnicmp(command, L"Rainmeter", 9) == 0) + { + // Skip "Rainmeter" for backwards compatibility + command += 9; + } + + std::wstring bang; + std::vector args; + + // Find the first space + const WCHAR* pos = wcschr(command, L' '); + if (pos) + { + bang.assign(command, 0, pos - command); + args = ParseString(pos + 1, skin ? &skin->GetParser() : nullptr); + } + else + { + bang = command; + } + + ExecuteBang(bang.c_str(), args, skin); + return; + } + } + + if (multi && command[0] == L'[') // Multi-bang + { + std::wstring bangs = command; + std::wstring::size_type start = std::wstring::npos; + int count = 0; + for (size_t i = 0, isize = bangs.size(); i < isize; ++i) + { + if (bangs[i] == L'[') + { + if (count == 0) + { + start = i; + } + ++count; + } + else if (bangs[i] == L']') + { + --count; + + if (count == 0 && start != std::wstring::npos) + { + // Change ] to nullptr + bangs[i] = L'\0'; + + // Skip whitespace + start = bangs.find_first_not_of(L" \t\r\n", start + 1, 4); + + ExecuteCommand(bangs.c_str() + start, skin, false); + } + } + else if (bangs[i] == L'"' && isize > (i + 2) && bangs[i + 1] == L'"' && bangs[i + 2] == L'"') + { + i += 3; + + std::wstring::size_type pos = bangs.find(L"\"\"\"", i); + if (pos != std::wstring::npos) + { + i = pos + 2; // Skip "", loop will skip last " + } + } + } + } + else + { + // Check for built-ins + if (_wcsnicmp(L"PLAY", command, 4) == 0) + { + if (command[4] == L' ' || // PLAY + _wcsnicmp(L"LOOP ", &command[4], 5) == 0) // PLAYLOOP + { + command += 4; // Skip PLAY + + DWORD flags = SND_FILENAME | SND_ASYNC; + + if (command[0] != L' ') + { + flags |= SND_LOOP | SND_NODEFAULT; + command += 4; // Skip LOOP + } + + ++command; // Skip the space + if (command[0] != L'\0') + { + std::wstring sound = command; + + // Strip the quotes + std::wstring::size_type len = sound.length(); + if (len >= 2 && sound[0] == L'"' && sound[len - 1] == L'"') + { + len -= 2; + sound.assign(sound, 1, len); + } + + if (skin) + { + skin->GetParser().ReplaceMeasures(sound); + skin->MakePathAbsolute(sound); + } + + PlaySound(sound.c_str(), nullptr, flags); + } + return; + } + else if (_wcsnicmp(L"STOP", &command[4], 4) == 0) // PLAYSTOP + { + PlaySound(nullptr, nullptr, SND_PURGE); + return; + } + } + + // Run command + std::wstring tmpSz = command; + if (skin) + { + skin->GetParser().ReplaceMeasures(tmpSz); + } + RunCommand(tmpSz); + } +} + +/* +** Runs the given bang. +** +*/ +void CommandHandler::ExecuteBang(const WCHAR* name, std::vector& args, MeterWindow* skin) +{ + for (const auto& bangInfo : s_Bangs) + { + if (_wcsicmp(bangInfo.name, name) == 0) + { + DoBang(bangInfo, args, skin); + return; + } + } + + for (const auto& bangInfo : s_GroupBangs) + { + if (_wcsicmp(bangInfo.name, name) == 0) + { + DoGroupBang(bangInfo, args, skin); + return; + } + } + + for (const auto& bangInfo : s_CustomBangs) + { + if (_wcsicmp(bangInfo.name, name) == 0) + { + bangInfo.handlerFunc(args, skin); + return; + } + } + + LogErrorF(skin, L"Invalid bang: !%s", name); +} + +/* +** Parses and runs the given command. +** +*/ +void CommandHandler::RunCommand(std::wstring command) +{ + std::wstring args; + + size_t notwhite = command.find_first_not_of(L" \t\r\n"); + command.erase(0, notwhite); + + size_t quotePos = command.find(L'"'); + if (quotePos == 0) + { + size_t quotePos2 = command.find(L'"', quotePos + 1); + if (quotePos2 != std::wstring::npos) + { + args.assign(command, quotePos2 + 1, command.length() - (quotePos2 + 1)); + command.assign(command, quotePos + 1, quotePos2 - quotePos - 1); + } + else + { + command.erase(0, 1); + } + } + else + { + size_t spacePos = command.find(L' '); + if (spacePos != std::wstring::npos) + { + args.assign(command, spacePos + 1, command.length() - (spacePos + 1)); + command.erase(spacePos); + } + } + + if (!command.empty()) + { + RunFile(command.c_str(), args.c_str()); + } +} + +/* +** Runs a file with the given arguments. +** +*/ +void CommandHandler::RunFile(const WCHAR* file, const WCHAR* args) +{ + SHELLEXECUTEINFO si = {sizeof(SHELLEXECUTEINFO)}; + si.lpVerb = L"open"; + si.lpFile = file; + si.nShow = SW_SHOWNORMAL; + + DWORD type = GetFileAttributes(si.lpFile); + if (type & FILE_ATTRIBUTE_DIRECTORY && type != 0xFFFFFFFF) + { + ShellExecute(si.hwnd, si.lpVerb, si.lpFile, nullptr, nullptr, si.nShow); + } + else + { + std::wstring dir = PathUtil::GetFolderFromFilePath(file); + si.lpDirectory = dir.c_str(); + si.lpParameters = args; + si.fMask = SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI; + ShellExecuteEx(&si); + } +} + +/* +** Splits strings into parts. +** +*/ +std::vector CommandHandler::ParseString(LPCTSTR str, ConfigParser* parser) +{ + std::vector result; + + if (str) + { + std::wstring arg = str; + + // Split the argument between first space. + // Or if string is in quotes, the after the second quote. + + auto addResult = [&](std::wstring& string, bool stripQuotes) + { + if (stripQuotes) + { + size_t pos = 0; + do + { + pos = string.find(L'"', pos); + if (pos != std::wstring::npos) + { + string.erase(pos, 1); + } + } + while (pos != std::wstring::npos); + } + + if (parser) + { + parser->ReplaceMeasures(string); + } + + result.push_back(string); + }; + + size_t pos; + std::wstring newStr; + while ((pos = arg.find_first_not_of(L' ')) != std::wstring::npos) + { + size_t extra = 1; + if (arg[pos] == L'"') + { + if (arg.size() > (pos + 2) && + arg[pos + 1] == L'"' && arg[pos + 2] == L'"') + { + // Eat found quotes and finding ending """ + arg.erase(0, pos + 3); + + extra = 4; + if ((pos = arg.find(L"\"\"\" ")) == std::wstring::npos) + { + extra = 3; + pos = arg.rfind(L"\"\"\""); // search backward + } + } + else + { + // Eat found quote and find ending quote + arg.erase(0, pos + 1); + pos = arg.find_first_of(L'"'); + } + } + else + { + if (pos > 0) + { + // Eat everything until non-space (and non-quote) char + arg.erase(0, pos); + } + + // Find the second quote + pos = arg.find_first_of(L' '); + } + + if (pos != std::wstring::npos) + { + newStr.assign(arg, 0, pos); + arg.erase(0, pos + extra); + + addResult(newStr, extra == 1); + } + else // quote or space not found + { + addResult(arg, extra == 1); + arg.clear(); + break; + } + } + + if (!arg.empty() && result.empty()) + { + addResult(arg, true); + } + } + + return result; +} + +void CommandHandler::DoActivateSkinBang(std::vector& args, MeterWindow* skin) +{ + if (args.size() == 1) + { + if (Rainmeter::GetInstance().ActivateSkin(args[0])) return; + } + else if (args.size() > 1) + { + if (Rainmeter::GetInstance().ActivateSkin(args[0], args[1])) return; + } + + LogErrorF(skin, L"!ActivateConfig: Invalid parameters"); +} + +void CommandHandler::DoDeactivateSkinBang(std::vector& args, MeterWindow* skin) +{ + if (!args.empty()) + { + skin = Rainmeter::GetInstance().GetMeterWindow(args[0]); + if (!skin) + { + LogWarningF(L"!DeactivateConfig: \"%s\" not active", args[0].c_str()); + return; + } + } + + if (skin) + { + Rainmeter::GetInstance().DeactivateSkin(skin, -1); + } + else + { + LogError(L"!DeactivateConfig: Invalid parameters"); + } +} + +void CommandHandler::DoToggleSkinBang(std::vector& args, MeterWindow* skin) +{ + if (args.size() >= 2) + { + MeterWindow* meterWindow = Rainmeter::GetInstance().GetMeterWindow(args[0]); + if (meterWindow) + { + Rainmeter::GetInstance().DeactivateSkin(meterWindow, -1); + return; + } + + // If the skin wasn't active, activate it. + DoActivateSkinBang(args, nullptr); + } + else + { + LogErrorF(skin, L"!ToggleConfig: Invalid parameters"); + } +} + +void CommandHandler::DoDeactivateSkinGroupBang(std::vector& args, MeterWindow* skin) +{ + if (!args.empty()) + { + std::multimap windows; + Rainmeter::GetInstance().GetMeterWindowsByLoadOrder(windows, args[0]); + for (const auto& ip : windows) + { + Rainmeter::GetInstance().DeactivateSkin(ip.second, -1); + } + } + else + { + LogErrorF(skin, L"!DeactivateConfigGroup: Invalid parameters"); + } +} + +void CommandHandler::DoLoadLayoutBang(std::vector& args, MeterWindow* skin) +{ + if (args.size() == 1) + { + if (skin) + { + // Delay to avoid loading theme in the middle of an update. + std::wstring command = L"!LoadLayout \""; + command += args[0]; + command += L'"'; + Rainmeter::GetInstance().DelayedExecuteCommand(command.c_str()); + } + else + { + // Not called from a skin (or called with delay). + Rainmeter::GetInstance().LoadLayout(args[0]); + } + } +} + +void CommandHandler::DoSetClipBang(std::vector& args, MeterWindow* skin) +{ + if (!args.empty()) + { + System::SetClipboardText(args[0]); + } + else + { + LogErrorF(skin, L"!SetClip: Invalid parameter"); + } +} + +void CommandHandler::DoSetWallpaperBang(std::vector& args, MeterWindow* skin) +{ + const size_t argsSize = args.size(); + if (argsSize >= 1 && argsSize <= 2) + { + std::wstring& file = args[0]; + const std::wstring& style = (argsSize == 2) ? args[1] : L""; + + if (skin) + { + skin->MakePathAbsolute(file); + } + + System::SetWallpaper(file, style); + } + else + { + LogErrorF(skin, L"!SetWallpaper: Invalid parameters"); + } +} + +void CommandHandler::DoAboutBang(std::vector& args, MeterWindow* meterWindow) +{ + DialogAbout::Open(args.empty() ? L"" : args[0].c_str()); +} + +void CommandHandler::DoManageBang(std::vector& args, MeterWindow* meterWindow) +{ + const size_t argsSize = args.size(); + if (argsSize >= 2 && argsSize <= 3) + { + DialogManage::Open(args[0].c_str(), + args[1].c_str(), + (argsSize == 3) ? args[2].c_str() : L""); + } + else if (argsSize <= 1) + { + DialogManage::Open(args.empty() ? L"" : args[0].c_str()); + } + else + { + LogErrorF(meterWindow, L"!Manage: Invalid parameters"); + } +} + +void CommandHandler::DoSkinMenuBang(std::vector& args, MeterWindow* skin) +{ + if (!args.empty()) + { + skin = Rainmeter::GetInstance().GetMeterWindow(args[0]); + if (!skin) + { + LogWarningF(L"!SkinMenu: \"%s\" not active", args[0].c_str()); + return; + } + } + + if (skin) + { + POINT pos = System::GetCursorPosition(); + Rainmeter::GetInstance().ShowContextMenu(pos, skin); + } + else + { + LogError(L"!SkinMenu: Invalid parameter"); + } +} + +void CommandHandler::DoTrayMenuBang(std::vector& args, MeterWindow* skin) +{ + POINT pos = System::GetCursorPosition(); + Rainmeter::GetInstance().ShowContextMenu(pos, nullptr); +} + +void CommandHandler::DoResetStatsBang(std::vector& args, MeterWindow* meterWindow) +{ + Rainmeter::GetInstance().ResetStats(); +} + +void CommandHandler::DoWriteKeyValueBang(std::vector& args, MeterWindow* skin) +{ + if (args.size() == 3 && skin) + { + // Add the skin file path to the args + args.push_back(skin->GetFilePath()); + } + else if (args.size() < 4) + { + LogErrorF(skin, L"!WriteKeyValue: Invalid parameters"); + return; + } + + std::wstring& strIniFile = args[3]; + if (skin) + { + skin->MakePathAbsolute(strIniFile); + } + + const WCHAR* iniFile = strIniFile.c_str(); + + if (strIniFile.find(L"..\\") != std::wstring::npos || strIniFile.find(L"../") != std::wstring::npos) + { + LogErrorF(skin, L"!WriteKeyValue: Illegal path: %s", iniFile); + return; + } + + if (_wcsnicmp(iniFile, Rainmeter::GetInstance().m_SkinPath.c_str(), Rainmeter::GetInstance().m_SkinPath.size()) != 0 && + _wcsnicmp(iniFile, Rainmeter::GetInstance().m_SettingsPath.c_str(), Rainmeter::GetInstance().m_SettingsPath.size()) != 0) + { + LogErrorF(skin, L"!WriteKeyValue: Illegal path: %s", iniFile); + return; + } + + // Verify whether the file exists. + if (_waccess(iniFile, 0) == -1) + { + LogErrorF(skin, L"!WriteKeyValue: File not found: %s", iniFile); + return; + } + + // Verify whether the file is read-only. + DWORD attr = GetFileAttributes(iniFile); + if (attr == -1 || (attr & FILE_ATTRIBUTE_READONLY)) + { + LogWarningF(skin, L"!WriteKeyValue: File is read-only: %s", iniFile); + return; + } + + // Avoid "IniFileMapping" + System::UpdateIniFileMappingList(); + std::wstring strIniWrite = System::GetTemporaryFile(strIniFile); + if (strIniWrite.size() == 1 && strIniWrite[0] == L'?') // error occurred + { + return; + } + + bool temporary = !strIniWrite.empty(); + + if (temporary) + { + if (Rainmeter::GetInstance().GetDebug()) + { + LogDebugF(skin, L"!WriteKeyValue: Writing to: %s (Temp: %s)", iniFile, strIniWrite.c_str()); + } + } + else + { + if (Rainmeter::GetInstance().GetDebug()) + { + LogDebugF(skin, L"!WriteKeyValue: Writing to: %s", iniFile); + } + strIniWrite = strIniFile; + } + + const WCHAR* iniWrite = strIniWrite.c_str(); + const WCHAR* section = args[0].c_str(); + const WCHAR* key = args[1].c_str(); + const std::wstring& strValue = args[2]; + + bool formula = false; + BOOL write = 0; + + if (skin) + { + double value; + formula = skin->GetParser().ParseFormula(strValue, &value); + if (formula) + { + WCHAR buffer[256]; + int len = _snwprintf_s(buffer, _TRUNCATE, L"%.5f", value); + Measure::RemoveTrailingZero(buffer, len); + + write = WritePrivateProfileString(section, key, buffer, iniWrite); + } + } + + if (!formula) + { + write = WritePrivateProfileString(section, key, strValue.c_str(), iniWrite); + } + + if (temporary) + { + if (write != 0) + { + WritePrivateProfileString(nullptr, nullptr, nullptr, iniWrite); // FLUSH + + // Copy the file back. + if (!System::CopyFiles(strIniWrite, strIniFile)) + { + LogErrorF(skin, L"!WriteKeyValue: Failed to copy temporary file to original filepath: %s (Temp: %s)", iniFile, iniWrite); + } + } + else // failed + { + LogErrorF(skin, L"!WriteKeyValue: Failed to write to: %s (Temp: %s)", iniFile, iniWrite); + } + + // Remove the temporary file. + System::RemoveFile(strIniWrite); + } + else + { + if (write == 0) // failed + { + LogErrorF(skin, L"!WriteKeyValue: Failed to write to: %s", iniFile); + } + } +} + +void CommandHandler::DoLogBang(std::vector& args, MeterWindow* skin) +{ + if (!args.empty()) + { + Logger::Level level = Logger::Level::Notice; + if (args.size() > 1) + { + const WCHAR* type = args[1].c_str(); + if (_wcsicmp(type, L"ERROR") == 0) + { + level = Logger::Level::Error; + } + else if (_wcsicmp(type, L"WARNING") == 0) + { + level = Logger::Level::Warning; + } + else if (_wcsicmp(type, L"DEBUG") == 0) + { + level = Logger::Level::Debug; + } + else if (_wcsicmp(type, L"NOTICE") != 0) + { + LogErrorF(skin, L"!Log: Invalid type"); + return; + } + } + + std::wstring source; + if (skin) + { + source = skin->GetSkinPath(); + } + + GetLogger().Log(level, source.c_str(), args[0].c_str()); + } +} + +void CommandHandler::DoRefreshApp(std::vector& args, MeterWindow* meterWindow) +{ + // Refresh needs to be delayed since it crashes if done during Update(). + PostMessage(Rainmeter::GetInstance().m_Window, WM_RAINMETER_DELAYED_REFRESH_ALL, 0, 0); +} + +void CommandHandler::DoQuitBang(std::vector& args, MeterWindow* meterWindow) +{ + // Quit needs to be delayed since it crashes if done during Update(). + PostMessage(Rainmeter::GetInstance().GetTrayWindow()->GetWindow(), WM_COMMAND, MAKEWPARAM(IDM_QUIT, 0), 0); +} + +void CommandHandler::DoLsBoxHookBang(std::vector& args, MeterWindow* meterWindow) +{ + // Deprecated. +} diff --git a/Library/CommandHandler.h b/Library/CommandHandler.h index 92138fbb..ab5b2e95 100644 --- a/Library/CommandHandler.h +++ b/Library/CommandHandler.h @@ -1,148 +1,148 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_LIBRARY_COMMANDHANDLER_H_ -#define RM_LIBRARY_COMMANDHANDLER_H_ - -#include -#include -#include - -class ConfigParser; -class MeterWindow; - -enum class Bang -{ - Refresh, - RefreshApp, - Redraw, - Update, - Hide, - Show, - Toggle, - HideFade, - ShowFade, - ToggleFade, - HideMeter, - ShowMeter, - ToggleMeter, - MoveMeter, - UpdateMeter, - DisableMeasure, - EnableMeasure, - ToggleMeasure, - PauseMeasure, - UnpauseMeasure, - TogglePauseMeasure, - UpdateMeasure, - CommandMeasure, - PluginBang, - ShowBlur, - HideBlur, - ToggleBlur, - AddBlur, - RemoveBlur, - ActivateConfig, - DeactivateConfig, - ToggleConfig, - Move, - ZPos, - ChangeZPos, - ClickThrough, - Draggable, - SnapEdges, - KeepOnScreen, - SetTransparency, - SetVariable, - SetOption, - RefreshGroup, - UpdateGroup, - RedrawGroup, - HideGroup, - ShowGroup, - ToggleGroup, - HideFadeGroup, - ShowFadeGroup, - ToggleFadeGroup, - HideMeterGroup, - ShowMeterGroup, - ToggleMeterGroup, - UpdateMeterGroup, - DisableMeasureGroup, - EnableMeasureGroup, - ToggleMeasureGroup, - PauseMeasureGroup, - UnpauseMeasureGroup, - TogglePauseMeasureGroup, - UpdateMeasureGroup, - DeactivateConfigGroup, - ZPosGroup, - ClickThroughGroup, - DraggableGroup, - SnapEdgesGroup, - KeepOnScreenGroup, - SetTransparencyGroup, - SetVariableGroup, - SetOptionGroup, - WriteKeyValue, - LoadLayout, - SetClip, - SetWallpaper, - About, - Manage, - SkinMenu, - SkinCustomMenu, - TrayMenu, - ResetStats, - Log, - Quit, - LsBoxHook -}; - -// Parses and executes commands and bangs. -class CommandHandler -{ -public: - void ExecuteCommand(const WCHAR* command, MeterWindow* skin, bool multi = true); - void ExecuteBang(const WCHAR* name, std::vector& args, MeterWindow* skin); - - static void RunCommand(std::wstring command); - static void RunFile(const WCHAR* file, const WCHAR* args = nullptr); - - static std::vector ParseString(const WCHAR* str, ConfigParser* parser = nullptr); - - static void DoActivateSkinBang(std::vector& args, MeterWindow* skin); - static void DoDeactivateSkinBang(std::vector& args, MeterWindow* skin); - static void DoToggleSkinBang(std::vector& args, MeterWindow* skin); - static void DoDeactivateSkinGroupBang(std::vector& args, MeterWindow* skin); - static void DoLoadLayoutBang(std::vector& args, MeterWindow* meterWindow); - static void DoSetClipBang(std::vector& args, MeterWindow* skin); - static void DoSetWallpaperBang(std::vector& args, MeterWindow* meterWindow); - static void DoAboutBang(std::vector& args, MeterWindow* meterWindow); - static void DoManageBang(std::vector& args, MeterWindow* meterWindow); - static void DoSkinMenuBang(std::vector& args, MeterWindow* meterWindow); - static void DoTrayMenuBang(std::vector& args, MeterWindow* meterWindow); - static void DoResetStatsBang(std::vector& args, MeterWindow* meterWindow); - static void DoWriteKeyValueBang(std::vector& args, MeterWindow* meterWindow); - static void DoLogBang(std::vector& args, MeterWindow* meterWindow); - static void DoRefreshApp(std::vector& args, MeterWindow* skin); - static void DoQuitBang(std::vector& args, MeterWindow* meterWindow); - static void DoLsBoxHookBang(std::vector& args, MeterWindow* meterWindow); -}; - -#endif +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_LIBRARY_COMMANDHANDLER_H_ +#define RM_LIBRARY_COMMANDHANDLER_H_ + +#include +#include +#include + +class ConfigParser; +class MeterWindow; + +enum class Bang +{ + Refresh, + RefreshApp, + Redraw, + Update, + Hide, + Show, + Toggle, + HideFade, + ShowFade, + ToggleFade, + HideMeter, + ShowMeter, + ToggleMeter, + MoveMeter, + UpdateMeter, + DisableMeasure, + EnableMeasure, + ToggleMeasure, + PauseMeasure, + UnpauseMeasure, + TogglePauseMeasure, + UpdateMeasure, + CommandMeasure, + PluginBang, + ShowBlur, + HideBlur, + ToggleBlur, + AddBlur, + RemoveBlur, + ActivateConfig, + DeactivateConfig, + ToggleConfig, + Move, + ZPos, + ChangeZPos, + ClickThrough, + Draggable, + SnapEdges, + KeepOnScreen, + SetTransparency, + SetVariable, + SetOption, + RefreshGroup, + UpdateGroup, + RedrawGroup, + HideGroup, + ShowGroup, + ToggleGroup, + HideFadeGroup, + ShowFadeGroup, + ToggleFadeGroup, + HideMeterGroup, + ShowMeterGroup, + ToggleMeterGroup, + UpdateMeterGroup, + DisableMeasureGroup, + EnableMeasureGroup, + ToggleMeasureGroup, + PauseMeasureGroup, + UnpauseMeasureGroup, + TogglePauseMeasureGroup, + UpdateMeasureGroup, + DeactivateConfigGroup, + ZPosGroup, + ClickThroughGroup, + DraggableGroup, + SnapEdgesGroup, + KeepOnScreenGroup, + SetTransparencyGroup, + SetVariableGroup, + SetOptionGroup, + WriteKeyValue, + LoadLayout, + SetClip, + SetWallpaper, + About, + Manage, + SkinMenu, + SkinCustomMenu, + TrayMenu, + ResetStats, + Log, + Quit, + LsBoxHook +}; + +// Parses and executes commands and bangs. +class CommandHandler +{ +public: + void ExecuteCommand(const WCHAR* command, MeterWindow* skin, bool multi = true); + void ExecuteBang(const WCHAR* name, std::vector& args, MeterWindow* skin); + + static void RunCommand(std::wstring command); + static void RunFile(const WCHAR* file, const WCHAR* args = nullptr); + + static std::vector ParseString(const WCHAR* str, ConfigParser* parser = nullptr); + + static void DoActivateSkinBang(std::vector& args, MeterWindow* skin); + static void DoDeactivateSkinBang(std::vector& args, MeterWindow* skin); + static void DoToggleSkinBang(std::vector& args, MeterWindow* skin); + static void DoDeactivateSkinGroupBang(std::vector& args, MeterWindow* skin); + static void DoLoadLayoutBang(std::vector& args, MeterWindow* meterWindow); + static void DoSetClipBang(std::vector& args, MeterWindow* skin); + static void DoSetWallpaperBang(std::vector& args, MeterWindow* meterWindow); + static void DoAboutBang(std::vector& args, MeterWindow* meterWindow); + static void DoManageBang(std::vector& args, MeterWindow* meterWindow); + static void DoSkinMenuBang(std::vector& args, MeterWindow* meterWindow); + static void DoTrayMenuBang(std::vector& args, MeterWindow* meterWindow); + static void DoResetStatsBang(std::vector& args, MeterWindow* meterWindow); + static void DoWriteKeyValueBang(std::vector& args, MeterWindow* meterWindow); + static void DoLogBang(std::vector& args, MeterWindow* meterWindow); + static void DoRefreshApp(std::vector& args, MeterWindow* skin); + static void DoQuitBang(std::vector& args, MeterWindow* meterWindow); + static void DoLsBoxHookBang(std::vector& args, MeterWindow* meterWindow); +}; + +#endif diff --git a/Library/ConfigParser.cpp b/Library/ConfigParser.cpp index 86da5631..b2122a4d 100644 --- a/Library/ConfigParser.cpp +++ b/Library/ConfigParser.cpp @@ -1,1586 +1,1586 @@ -/* - Copyright (C) 2004 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../Common/MathParser.h" -#include "../Common/PathUtil.h" -#include "ConfigParser.h" -#include "Litestep.h" -#include "Rainmeter.h" -#include "System.h" -#include "Measure.h" -#include "Meter.h" -#include "resource.h" - -using namespace Gdiplus; - -std::unordered_map ConfigParser::c_MonitorVariables; - -/* -** The constructor -** -*/ -ConfigParser::ConfigParser() : - m_LastReplaced(false), - m_LastDefaultUsed(false), - m_LastValueDefined(false), - m_CurrentSection(), - m_MeterWindow() -{ -} - -/* -** The destructor -** -*/ -ConfigParser::~ConfigParser() -{ -} - -void ConfigParser::Initialize(const std::wstring& filename, MeterWindow* meterWindow, LPCTSTR skinSection, const std::wstring* resourcePath) -{ - m_MeterWindow = meterWindow; - - m_Measures.clear(); - m_Sections.clear(); - m_Values.clear(); - m_BuiltInVariables.clear(); - m_Variables.clear(); - - m_StyleTemplate.clear(); - m_LastReplaced = false; - m_LastDefaultUsed = false; - m_LastValueDefined = false; - - m_CurrentSection = nullptr; - m_SectionInsertPos = m_Sections.end(); - - // Set the built-in variables. Do this before the ini file is read so that the paths can be used with @include - SetBuiltInVariables(filename, resourcePath, meterWindow); - ResetMonitorVariables(meterWindow); - - System::UpdateIniFileMappingList(); - - ReadIniFile(filename, skinSection); - ReadVariables(); - - // Clear and minimize - m_FoundSections.clear(); - m_ListVariables.clear(); - m_SectionInsertPos = m_Sections.end(); -} - -void ConfigParser::SetBuiltInVariables(const std::wstring& filename, const std::wstring* resourcePath, MeterWindow* meterWindow) -{ - auto insertVariable = [&](const WCHAR* name, std::wstring value) - { - return m_BuiltInVariables.insert(std::make_pair(name, value)); - }; - - insertVariable(L"PROGRAMPATH", Rainmeter::GetInstance().GetPath()); - insertVariable(L"PROGRAMDRIVE", Rainmeter::GetInstance().GetDrive()); - insertVariable(L"SETTINGSPATH", Rainmeter::GetInstance().GetSettingsPath()); - insertVariable(L"SKINSPATH", Rainmeter::GetInstance().GetSkinPath()); - insertVariable(L"PLUGINSPATH", Rainmeter::GetInstance().GetPluginPath()); - insertVariable(L"CURRENTPATH", PathUtil::GetFolderFromFilePath(filename)); - insertVariable(L"ADDONSPATH", Rainmeter::GetInstance().GetAddonPath()); - - if (meterWindow) - { - insertVariable(L"CURRENTFILE", meterWindow->GetFileName()); - insertVariable(L"CURRENTCONFIG", meterWindow->GetFolderPath()); - insertVariable(L"ROOTCONFIG", meterWindow->GetRootName()); - insertVariable(L"ROOTCONFIGPATH", meterWindow->GetRootPath()); - } - - insertVariable(L"CRLF", L"\n"); - - m_CurrentSection = &(insertVariable(L"CURRENTSECTION", L"").first->second); // shortcut - - if (resourcePath) - { - SetVariable(L"@", *resourcePath); - } -} - -/* -** Sets all user-defined variables. -** -*/ -void ConfigParser::ReadVariables() -{ - std::list::const_iterator iter = m_ListVariables.begin(); - for ( ; iter != m_ListVariables.end(); ++iter) - { - SetVariable((*iter), ReadString(L"Variables", (*iter).c_str(), L"", false)); - } -} - -void ConfigParser::SetVariable(std::wstring strVariable, const std::wstring& strValue) -{ - StrToUpperC(strVariable); - m_Variables[strVariable] = strValue; -} - -void ConfigParser::SetBuiltInVariable(const std::wstring& strVariable, const std::wstring& strValue) -{ - m_BuiltInVariables[strVariable] = strValue; -} - -/* -** Gets a value for the variable. Returns nullptr if not found. -** -*/ -const std::wstring* ConfigParser::GetVariable(const std::wstring& strVariable) -{ - const std::wstring strTmp = StrToUpper(strVariable); - - // #1: Built-in variables - std::unordered_map::const_iterator iter = m_BuiltInVariables.find(strTmp); - if (iter != m_BuiltInVariables.end()) - { - return &(*iter).second; - } - - // #2: Monitor variables - iter = c_MonitorVariables.find(strTmp); - if (iter != c_MonitorVariables.end()) - { - return &(*iter).second; - } - - // #3: User-defined variables - iter = m_Variables.find(strTmp); - if (iter != m_Variables.end()) - { - return &(*iter).second; - } - - return nullptr; -} - -/* -** Gets the value of a section variable. Returns true if strValue is set. -** The selector is stripped from strVariable. -** -*/ -bool ConfigParser::GetSectionVariable(std::wstring& strVariable, std::wstring& strValue) -{ - size_t colonPos = strVariable.find_last_of(L':'); - if (colonPos == std::wstring::npos) - { - return false; - } - - const std::wstring selector = strVariable.substr(colonPos + 1); - const WCHAR* selectorSz = selector.c_str(); - strVariable.resize(colonPos); - - bool isKeySelector = (!selector.empty() && iswalpha(selectorSz[0])); - - if (isKeySelector) - { - // [Meter:X], [Meter:Y], [Meter:W], [Meter:H] - Meter* meter = m_MeterWindow->GetMeter(strVariable); - if (meter) - { - WCHAR buffer[32]; - if (_wcsicmp(selectorSz, L"X") == 0) - { - _itow_s(meter->GetX(), buffer, 10); - } - else if (_wcsicmp(selectorSz, L"Y") == 0) - { - _itow_s(meter->GetY(), buffer, 10); - } - else if (_wcsicmp(selectorSz, L"W") == 0) - { - _itow_s(meter->GetW(), buffer, 10); - } - else if (_wcsicmp(selectorSz, L"H") == 0) - { - _itow_s(meter->GetH(), buffer, 10); - } - else - { - return false; - } - - strValue = buffer; - return true; - } - } - - // Number: [Measure:], [Measure:dec] - // Percentual: [Measure:%], [Measure:%, dec] - // Scale: [Measure:/scale], [Measure:/scale, dec] - // Max/Min: [Measure:MaxValue], [Measure:MaxValue:/scale, dec] ('%' cannot be used) - // EscapeRegExp: [Measure:EscapeRegExp] (Escapes regular expression syntax, used for 'IfMatch') - enum class ValueType - { - Raw, - Percentual, - Max, - Min, - EscapeRegExp, - EncodeUrl - } valueType = ValueType::Raw; - - if (isKeySelector) - { - if (_wcsicmp(selectorSz, L"MaxValue") == 0) - { - valueType = ValueType::Max; - } - else if (_wcsicmp(selectorSz, L"MinValue") == 0) - { - valueType = ValueType::Min; - } - else if (_wcsicmp(selectorSz, L"EscapeRegExp") == 0) - { - valueType = ValueType::EscapeRegExp; - } - else if (_wcsicmp(selectorSz, L"EncodeUrl") == 0) - { - valueType = ValueType::EncodeUrl; - } - else - { - return false; - } - - selectorSz = L""; - } - else - { - colonPos = strVariable.find_last_of(L':'); - if (colonPos != std::wstring::npos) - { - do - { - const WCHAR* keySelectorSz = strVariable.c_str() + colonPos + 1; - - if (_wcsicmp(keySelectorSz, L"MaxValue") == 0) - { - valueType = ValueType::Max; - } - else if (_wcsicmp(keySelectorSz, L"MinValue") == 0) - { - valueType = ValueType::Min; - } - else - { - // Section name contains ':' ? - break; - } - - strVariable.resize(colonPos); - } - while (0); - } - } - - Measure* measure = m_MeterWindow->GetMeasure(strVariable); - if (measure) - { - if (valueType == ValueType::EscapeRegExp) - { - strValue = measure->GetStringValue(); - StringUtil::EscapeRegExp(strValue); - return true; - } - else if (valueType == ValueType::EncodeUrl) - { - strValue = measure->GetStringValue(); - StringUtil::EncodeUrl(strValue); - return true; - } - - int scale = 1; - - const WCHAR* decimalsSz = wcschr(selectorSz, L','); - if (decimalsSz) - { - ++decimalsSz; - } - - if (*selectorSz == L'%') // Percentual - { - if (valueType == ValueType::Max || valueType == ValueType::Min) - { - // '%' cannot be used with Max/Min values. - return false; - } - - valueType = ValueType::Percentual; - } - else if (*selectorSz == L'/') // Scale - { - errno = 0; - scale = _wtoi(selectorSz + 1); - if (errno == EINVAL || scale == 0) - { - // Invalid scale value. - return false; - } - } - else - { - if (decimalsSz) - { - return false; - } - - decimalsSz = selectorSz; - } - - const double value = - (valueType == ValueType::Percentual) ? measure->GetRelativeValue() * 100.0 : - (valueType == ValueType::Max) ? measure->GetMaxValue() / scale : - (valueType == ValueType::Min) ? measure->GetMinValue() / scale : - measure->GetValue() / scale; - int decimals = 10; - if (decimalsSz) - { - while (iswspace(*decimalsSz)) ++decimalsSz; - - if (*decimalsSz) - { - decimals = _wtoi(decimalsSz); - decimals = max(0, decimals); - decimals = min(32, decimals); - } - else - { - decimalsSz = nullptr; - } - } - - WCHAR format[32]; - WCHAR buffer[128]; - _snwprintf_s(format, _TRUNCATE, L"%%.%if", decimals); - int bufferLen = _snwprintf_s(buffer, _TRUNCATE, format, value); - - if (!decimalsSz) - { - // Remove trailing zeros if decimal count was not specified. - measure->RemoveTrailingZero(buffer, bufferLen); - bufferLen = (int)wcslen(buffer); - } - - strValue.assign(buffer, bufferLen); - return true; - } - - return false; -} - -void ConfigParser::ResetMonitorVariables(MeterWindow* meterWindow) -{ - // Set the SCREENAREA/WORKAREA variables - if (c_MonitorVariables.empty()) - { - SetMultiMonitorVariables(true); - } - - // Set the SCREENAREA/WORKAREA variables for present monitor - SetAutoSelectedMonitorVariables(meterWindow); -} - -/* -** Sets new values for the SCREENAREA/WORKAREA variables. -** -*/ -void ConfigParser::SetMultiMonitorVariables(bool reset) -{ - auto setMonitorVariable = [&](const WCHAR* variable, const WCHAR* value) - { - c_MonitorVariables[variable] = value; - }; - - if (!reset && c_MonitorVariables.empty()) - { - reset = true; // Set all variables - } - - const size_t numOfMonitors = System::GetMonitorCount(); // intentional - const MultiMonitorInfo& monitorsInfo = System::GetMultiMonitorInfo(); - const std::vector& monitors = monitorsInfo.monitors; - - WCHAR buffer[32]; - const RECT workArea = monitors[monitorsInfo.primary - 1].work; - const RECT scrArea = monitors[monitorsInfo.primary - 1].screen; - - _itow_s(workArea.left, buffer, 10); - setMonitorVariable(L"WORKAREAX", buffer); - setMonitorVariable(L"PWORKAREAX", buffer); - _itow_s(workArea.top, buffer, 10); - setMonitorVariable(L"WORKAREAY", buffer); - setMonitorVariable(L"PWORKAREAY", buffer); - _itow_s(workArea.right - workArea.left, buffer, 10); - setMonitorVariable(L"WORKAREAWIDTH", buffer); - setMonitorVariable(L"PWORKAREAWIDTH", buffer); - _itow_s(workArea.bottom - workArea.top, buffer, 10); - setMonitorVariable(L"WORKAREAHEIGHT", buffer); - setMonitorVariable(L"PWORKAREAHEIGHT", buffer); - - if (reset) - { - _itow_s(scrArea.left, buffer, 10); - setMonitorVariable(L"SCREENAREAX", buffer); - setMonitorVariable(L"PSCREENAREAX", buffer); - _itow_s(scrArea.top, buffer, 10); - setMonitorVariable(L"SCREENAREAY", buffer); - setMonitorVariable(L"PSCREENAREAY", buffer); - _itow_s(scrArea.right - scrArea.left, buffer, 10); - setMonitorVariable(L"SCREENAREAWIDTH", buffer); - setMonitorVariable(L"PSCREENAREAWIDTH", buffer); - _itow_s(scrArea.bottom - scrArea.top, buffer, 10); - setMonitorVariable(L"SCREENAREAHEIGHT", buffer); - setMonitorVariable(L"PSCREENAREAHEIGHT", buffer); - - _itow_s(monitorsInfo.vsL, buffer, 10); - setMonitorVariable(L"VSCREENAREAX", buffer); - _itow_s(monitorsInfo.vsT, buffer, 10); - setMonitorVariable(L"VSCREENAREAY", buffer); - _itow_s(monitorsInfo.vsW, buffer, 10); - setMonitorVariable(L"VSCREENAREAWIDTH", buffer); - _itow_s(monitorsInfo.vsH, buffer, 10); - setMonitorVariable(L"VSCREENAREAHEIGHT", buffer); - } - - int i = 1; - for (auto iter = monitors.cbegin(); iter != monitors.cend(); ++iter, ++i) - { - WCHAR buffer2[64]; - - const RECT work = ((*iter).active) ? (*iter).work : workArea; - - _itow_s(work.left, buffer, 10); - _snwprintf_s(buffer2, _TRUNCATE, L"WORKAREAX@%i", i); - setMonitorVariable(buffer2, buffer); - _itow_s(work.top, buffer, 10); - _snwprintf_s(buffer2, _TRUNCATE, L"WORKAREAY@%i", i); - setMonitorVariable(buffer2, buffer); - _itow_s(work.right - work.left, buffer, 10); - _snwprintf_s(buffer2, _TRUNCATE, L"WORKAREAWIDTH@%i", i); - setMonitorVariable(buffer2, buffer); - _itow_s(work.bottom - work.top, buffer, 10); - _snwprintf_s(buffer2, _TRUNCATE, L"WORKAREAHEIGHT@%i", i); - setMonitorVariable(buffer2, buffer); - - if (reset) - { - const RECT screen = ((*iter).active) ? (*iter).screen : scrArea; - - _itow_s(screen.left, buffer, 10); - _snwprintf_s(buffer2, _TRUNCATE, L"SCREENAREAX@%i", i); - setMonitorVariable(buffer2, buffer); - _itow_s(screen.top, buffer, 10); - _snwprintf_s(buffer2, _TRUNCATE, L"SCREENAREAY@%i", i); - setMonitorVariable(buffer2, buffer); - _itow_s(screen.right - screen.left, buffer, 10); - _snwprintf_s(buffer2, _TRUNCATE, L"SCREENAREAWIDTH@%i", i); - setMonitorVariable(buffer2, buffer); - _itow_s(screen.bottom - screen.top, buffer, 10); - _snwprintf_s(buffer2, _TRUNCATE, L"SCREENAREAHEIGHT@%i", i); - setMonitorVariable(buffer2, buffer); - } - } -} - -/* -** Sets new SCREENAREA/WORKAREA variables for present monitor. -** -*/ -void ConfigParser::SetAutoSelectedMonitorVariables(MeterWindow* meterWindow) -{ - if (meterWindow) - { - const int numOfMonitors = (int)System::GetMonitorCount(); - const MultiMonitorInfo& monitorsInfo = System::GetMultiMonitorInfo(); - const std::vector& monitors = monitorsInfo.monitors; - - WCHAR buffer[32]; - int w1, w2, s1, s2; - int screenIndex; - - // Set X / WIDTH - screenIndex = monitorsInfo.primary; - if (meterWindow->GetXScreenDefined()) - { - int i = meterWindow->GetXScreen(); - if (i >= 0 && (i == 0 || i <= numOfMonitors && monitors[i - 1].active)) - { - screenIndex = i; - } - } - - if (screenIndex == 0) - { - s1 = w1 = monitorsInfo.vsL; - s2 = w2 = monitorsInfo.vsW; - } - else - { - w1 = monitors[screenIndex - 1].work.left; - w2 = monitors[screenIndex - 1].work.right - monitors[screenIndex - 1].work.left; - s1 = monitors[screenIndex - 1].screen.left; - s2 = monitors[screenIndex - 1].screen.right - monitors[screenIndex - 1].screen.left; - } - - _itow_s(w1, buffer, 10); - SetBuiltInVariable(L"WORKAREAX", buffer); - _itow_s(w2, buffer, 10); - SetBuiltInVariable(L"WORKAREAWIDTH", buffer); - _itow_s(s1, buffer, 10); - SetBuiltInVariable(L"SCREENAREAX", buffer); - _itow_s(s2, buffer, 10); - SetBuiltInVariable(L"SCREENAREAWIDTH", buffer); - - // Set Y / HEIGHT - screenIndex = monitorsInfo.primary; - if (meterWindow->GetYScreenDefined()) - { - int i = meterWindow->GetYScreen(); - if (i >= 0 && (i == 0 || i <= numOfMonitors && monitors[i - 1].active)) - { - screenIndex = i; - } - } - - if (screenIndex == 0) - { - s1 = w1 = monitorsInfo.vsL; - s2 = w2 = monitorsInfo.vsW; - } - else - { - w1 = monitors[screenIndex - 1].work.top; - w2 = monitors[screenIndex - 1].work.bottom - monitors[screenIndex - 1].work.top; - s1 = monitors[screenIndex - 1].screen.top; - s2 = monitors[screenIndex - 1].screen.bottom - monitors[screenIndex - 1].screen.top; - } - - _itow_s(w1, buffer, 10); - SetBuiltInVariable(L"WORKAREAY", buffer); - _itow_s(w2, buffer, 10); - SetBuiltInVariable(L"WORKAREAHEIGHT", buffer); - _itow_s(s1, buffer, 10); - SetBuiltInVariable(L"SCREENAREAY", buffer); - _itow_s(s2, buffer, 10); - SetBuiltInVariable(L"SCREENAREAHEIGHT", buffer); - } -} - -/* -** Replaces environment and internal variables in the given string. -** -*/ -bool ConfigParser::ReplaceVariables(std::wstring& result) -{ - bool replaced = false; - - PathUtil::ExpandEnvironmentVariables(result); - - if (c_MonitorVariables.empty()) - { - SetMultiMonitorVariables(true); - } - - // Check for variables (#VAR#) - size_t start = 0, end; - bool loop = true; - - do - { - start = result.find(L'#', start); - if (start != std::wstring::npos) - { - size_t si = start + 1; - end = result.find(L'#', si); - if (end != std::wstring::npos) - { - size_t ei = end - 1; - if (si != ei && result[si] == L'*' && result[ei] == L'*') - { - result.erase(ei, 1); - result.erase(si, 1); - start = ei; - } - else - { - std::wstring strVariable = result.substr(si, end - si); - const std::wstring* value = GetVariable(strVariable); - if (value) - { - // Variable found, replace it with the value - result.replace(start, end - start + 1, *value); - start += (*value).length(); - replaced = true; - } - else - { - start = end; - } - } - } - else - { - loop = false; - } - } - else - { - loop = false; - } - } - while (loop); - - return replaced; -} - -/* -** Replaces measures in the given string. -** -*/ -bool ConfigParser::ReplaceMeasures(std::wstring& result) -{ - bool replaced = false; - - size_t start = 0; - while ((start = result.find(L'[', start)) != std::wstring::npos) - { - size_t si = start + 1; - size_t end = result.find(L']', si); - if (end == std::wstring::npos) - { - break; - } - - size_t next = result.find(L'[', si); - if (next == std::wstring::npos || end < next) - { - size_t ei = end - 1; - if (si != ei && result[si] == L'*' && result[ei] == L'*') - { - result.erase(ei, 1); - result.erase(si, 1); - start = ei; - } - else - { - std::wstring var = result.substr(si, end - si); - - Measure* measure = GetMeasure(var); - if (measure) - { - const WCHAR* value = measure->GetStringOrFormattedValue(AUTOSCALE_OFF, 1, -1, false); - size_t valueLen = wcslen(value); - - // Measure found, replace it with the value - result.replace(start, end - start + 1, value, valueLen); - start += valueLen; - replaced = true; - } - else - { - std::wstring value; - if (GetSectionVariable(var, value)) - { - // Replace section variable with the value. - result.replace(start, end - start + 1, value); - start += value.length(); - replaced = true; - } - else - { - start = end; - } - } - } - } - else - { - start = next; - } - } - - return replaced; -} - -const std::wstring& ConfigParser::ReadString(LPCTSTR section, LPCTSTR key, LPCTSTR defValue, bool bReplaceMeasures) -{ - static std::wstring result; - - // Clear last status - m_LastReplaced = false; - m_LastDefaultUsed = false; - m_LastValueDefined = false; - - const std::wstring strSection = section; - const std::wstring strKey = key; - const std::wstring strDefault = defValue; - - const std::wstring& strValue = GetValue(strSection, strKey, strDefault); - if (&strValue == &strDefault) - { - bool foundStyleValue = false; - - // If the template is defined read the value from there. - std::vector::const_reverse_iterator iter = m_StyleTemplate.rbegin(); - for ( ; iter != m_StyleTemplate.rend(); ++iter) - { - const std::wstring& strStyleValue = GetValue((*iter), strKey, strDefault); - - //LogDebugF(L"StyleTemplate: [%s] %s (from [%s]) : strDefault=%s (0x%p), strStyleValue=%s (0x%p)", - // section, key, (*iter).c_str(), strDefault.c_str(), &strDefault, strStyleValue.c_str(), &strStyleValue); - - if (&strStyleValue != &strDefault) - { - result = strStyleValue; - foundStyleValue = true; - break; - } - } - - if (!foundStyleValue) - { - result = strDefault; - m_LastDefaultUsed = true; - return result; - } - } - else - { - result = strValue; - } - - if (!result.empty()) - { - m_LastValueDefined = true; - - if (result.size() >= 3) - { - if (result.find(L'#') != std::wstring::npos) - { - m_CurrentSection->assign(strSection); // Set temporarily - - if (ReplaceVariables(result)) - { - m_LastReplaced = true; - } - - m_CurrentSection->clear(); // Reset - } - else - { - PathUtil::ExpandEnvironmentVariables(result); - } - - if (bReplaceMeasures && ReplaceMeasures(result)) - { - m_LastReplaced = true; - } - } - } - - return result; -} - -bool ConfigParser::IsKeyDefined(LPCTSTR section, LPCTSTR key) -{ - ReadString(section, key, L"", false); - return !m_LastDefaultUsed; -} - -bool ConfigParser::IsValueDefined(LPCTSTR section, LPCTSTR key) -{ - ReadString(section, key, L"", false); - return m_LastValueDefined; -} - -void ConfigParser::AddMeasure(Measure* pMeasure) -{ - if (pMeasure) - { - m_Measures[StrToUpper(pMeasure->GetOriginalName())] = pMeasure; - } -} - -Measure* ConfigParser::GetMeasure(const std::wstring& name) -{ - std::unordered_map::const_iterator iter = m_Measures.find(StrToUpper(name)); - if (iter != m_Measures.end()) - { - return (*iter).second; - } - - return nullptr; -} - -std::vector ConfigParser::ReadFloats(LPCTSTR section, LPCTSTR key) -{ - std::vector result; - const std::wstring& str = ReadString(section, key, L""); - if (!str.empty()) - { - // Tokenize and parse the floats - const WCHAR delimiter = L';'; - size_t lastPos, pos = 0; - do - { - lastPos = str.find_first_not_of(delimiter, pos); - if (lastPos == std::wstring::npos) break; - - pos = str.find_first_of(delimiter, lastPos + 1); - - result.push_back((Gdiplus::REAL)ParseDouble(str.substr(lastPos, pos - lastPos).c_str(), 0.0)); // (pos != std::wstring::npos) ? pos - lastPos : pos - if (pos == std::wstring::npos) break; - - ++pos; - } - while (true); - } - return result; -} - -int ConfigParser::ReadInt(LPCTSTR section, LPCTSTR key, int defValue) -{ - const std::wstring& result = ReadString(section, key, L""); - - if (!m_LastDefaultUsed) - { - const WCHAR* string = result.c_str(); - if (*string == L'(') - { - double dblValue; - const WCHAR* errMsg = MathParser::CheckedParse(string, &dblValue); - if (!errMsg) - { - return (int)dblValue; - } - - LogErrorF(m_MeterWindow, L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section); - } - else if (*string) - { - errno = 0; - int intValue = wcstol(string, nullptr, 10); - if (errno != ERANGE) - { - return intValue; - } - } - } - - return defValue; -} - -uint32_t ConfigParser::ReadUInt(LPCTSTR section, LPCTSTR key, uint32_t defValue) -{ - const std::wstring& result = ReadString(section, key, L""); - - if (!m_LastDefaultUsed) - { - const WCHAR* string = result.c_str(); - if (*string == L'(') - { - double dblValue; - const WCHAR* errMsg = MathParser::CheckedParse(string, &dblValue); - if (!errMsg) - { - return (uint32_t)dblValue; - } - - LogErrorF(m_MeterWindow, L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section); - } - else if (*string) - { - errno = 0; - uint32_t uintValue = wcstoul(string, nullptr, 10); - if (errno != ERANGE) - { - return uintValue; - } - } - } - - return defValue; -} - -uint64_t ConfigParser::ReadUInt64(LPCTSTR section, LPCTSTR key, uint64_t defValue) -{ - const std::wstring& result = ReadString(section, key, L""); - - if (!m_LastDefaultUsed) - { - const WCHAR* string = result.c_str(); - if (*string == L'(') - { - double dblValue; - const WCHAR* errMsg = MathParser::CheckedParse(string, &dblValue); - if (!errMsg) - { - return (uint64_t)dblValue; - } - - LogErrorF(m_MeterWindow, L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section); - } - else if (*string) - { - errno = 0; - uint64_t uint64Value = _wcstoui64(string, nullptr, 10); - if (errno != ERANGE) - { - return uint64Value; - } - } - } - - return defValue; -} - -double ConfigParser::ReadFloat(LPCTSTR section, LPCTSTR key, double defValue) -{ - const std::wstring& result = ReadString(section, key, L""); - - if (!m_LastDefaultUsed) - { - double value; - const WCHAR* string = result.c_str(); - if (*string == L'(') - { - const WCHAR* errMsg = MathParser::CheckedParse(string, &value); - if (!errMsg) - { - return value; - } - - LogErrorF(m_MeterWindow, L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section); - } - else if (*string) - { - errno = 0; - value = wcstod(string, nullptr); - if (errno != ERANGE) - { - return value; - } - } - } - - return defValue; -} - -// Returns true if the formula was read successfully, false for failure. -bool ConfigParser::ParseFormula(const std::wstring& formula, double* resultValue) -{ - // Formulas must be surrounded by parenthesis - if (!formula.empty() && formula[0] == L'(' && formula[formula.size() - 1] == L')') - { - const WCHAR* string = formula.c_str(); - const WCHAR* errMsg = MathParser::CheckedParse(string, resultValue); - if (errMsg != nullptr) - { - LogErrorF(m_MeterWindow, L"Formula: %s: %s", errMsg, string); - return false; - } - - return true; - } - - return false; -} - -ARGB ConfigParser::ReadColor(LPCTSTR section, LPCTSTR key, ARGB defValue) -{ - const std::wstring& result = ReadString(section, key, L""); - - return (m_LastDefaultUsed) ? defValue : ParseColor(result.c_str()); -} - -Rect ConfigParser::ReadRect(LPCTSTR section, LPCTSTR key, const Rect& defValue) -{ - const std::wstring& result = ReadString(section, key, L""); - - return (m_LastDefaultUsed) ? defValue : ParseRect(result.c_str()); -} - -RECT ConfigParser::ReadRECT(LPCTSTR section, LPCTSTR key, const RECT& defValue) -{ - const std::wstring& result = ReadString(section, key, L""); - - RECT r; - if (m_LastDefaultUsed) - { - r = defValue; - } - else - { - r = ParseRECT(result.c_str()); - } - return r; -} - -/* -** Splits the string from the delimiters. -** Now trims empty element in vector and white-space in each string. -** -** Modified from http://www.digitalpeer.com/id/simple -*/ -std::vector ConfigParser::Tokenize(const std::wstring& str, const std::wstring& delimiters) -{ - std::vector tokens; - - size_t lastPos, pos = 0; - do - { - lastPos = str.find_first_not_of(delimiters, pos); - if (lastPos == std::wstring::npos) break; - - pos = str.find_first_of(delimiters, lastPos + 1); - std::wstring token = str.substr(lastPos, pos - lastPos); // len = (pos != std::wstring::npos) ? pos - lastPos : pos - - size_t pos2 = token.find_first_not_of(L" \t\r\n"); - if (pos2 != std::wstring::npos) - { - size_t lastPos2 = token.find_last_not_of(L" \t\r\n"); - if (pos2 != 0 || lastPos2 != (token.size() - 1)) - { - // Trim white-space - token.assign(token, pos2, lastPos2 - pos2 + 1); - } - tokens.push_back(token); - } - - if (pos == std::wstring::npos) break; - ++pos; - } - while (true); - - return tokens; -} - -/* -** Helper method that parses the floating-point value from the given string. -** If the given string is invalid format or causes overflow/underflow, returns given default value. -** -*/ -double ConfigParser::ParseDouble(LPCTSTR string, double defValue) -{ - assert(string); - - double value; - if (*string == L'(') - { - const WCHAR* errMsg = MathParser::CheckedParse(string, &value); - if (!errMsg) - { - return value; - } - - LogErrorF(L"Formula: %s: %s", errMsg, string); - } - else if (*string) - { - errno = 0; - double value = wcstod(string, nullptr); - if (errno != ERANGE) - { - return value; - } - } - - return defValue; -} - -/* -** Helper method that parses the integer value from the given string. -** If the given string is invalid format or causes overflow/underflow, returns given default value. -** -*/ -int ConfigParser::ParseInt(LPCTSTR string, int defValue) -{ - assert(string); - - if (*string == L'(') - { - double dblValue; - const WCHAR* errMsg = MathParser::CheckedParse(string, &dblValue); - if (!errMsg) - { - return (int)dblValue; - } - - LogErrorF(L"Formula: %s: %s", errMsg, string); - } - else if (*string) - { - errno = 0; - int intValue = wcstol(string, nullptr, 10); - if (errno != ERANGE) - { - return intValue; - } - } - - return defValue; -} - -/* -** Helper method that parses the unsigned integer value from the given string. -** If the given string is invalid format or causes overflow/underflow, returns given default value. -** -*/ -uint32_t ConfigParser::ParseUInt(LPCTSTR string, uint32_t defValue) -{ - assert(string); - - if (*string == L'(') - { - double dblValue; - const WCHAR* errMsg = MathParser::CheckedParse(string, &dblValue); - if (!errMsg) - { - return (uint32_t)dblValue; - } - - LogErrorF(L"Formula: %s: %s", errMsg, string); - } - else if (*string) - { - errno = 0; - uint32_t uintValue = wcstoul(string, nullptr, 10); - if (errno != ERANGE) - { - return uintValue; - } - } - - return defValue; -} - -/* -** Helper method that parses the 64bit unsigned integer value from the given string. -** If the given string is invalid format or causes overflow/underflow, returns given default value. -** -*/ -uint64_t ConfigParser::ParseUInt64(LPCTSTR string, uint64_t defValue) -{ - assert(string); - - if (*string == L'(') - { - double dblValue; - const WCHAR* errMsg = MathParser::CheckedParse(string, &dblValue); - if (!errMsg) - { - return (uint64_t)dblValue; - } - - LogErrorF(L"Formula: %s: %s", errMsg, string); - } - else if (*string) - { - errno = 0; - uint64_t uint64Value = _wcstoui64(string, nullptr, 10); - if (errno != ERANGE) - { - return uint64Value; - } - } - - return defValue; -} - -/* -** Helper template that parses four comma separated values from the given string. -** -*/ -template -bool ParseInt4(LPCTSTR string, T& v1, T& v2, T& v3, T& v4) -{ - if (wcschr(string, L',')) - { - WCHAR* parseSz = _wcsdup(string); - WCHAR* token; - - token = wcstok(parseSz, L","); - if (token) - { - v1 = ConfigParser::ParseInt(token, 0); - - token = wcstok(nullptr, L","); - if (token) - { - v2 = ConfigParser::ParseInt(token, 0); - - token = wcstok(nullptr, L","); - if (token) - { - v3 = ConfigParser::ParseInt(token, 0); - - token = wcstok(nullptr, L","); - if (token) - { - v4 = ConfigParser::ParseInt(token, 0); - } - } - } - } - free(parseSz); - return true; - } - - return false; -} - -/* -** Helper method that parses the color values from the given string. -** The color can be supplied as three/four comma separated values or as one -** hex-value. -** -*/ -ARGB ConfigParser::ParseColor(LPCTSTR string) -{ - int R = 255, G = 255, B = 255, A = 255; - - if (!ParseInt4(string, R, G, B, A)) - { - if (wcsncmp(string, L"0x", 2) == 0) - { - string += 2; // skip prefix - } - - size_t len = wcslen(string); - if (len >= 8 && !iswspace(string[6])) - { - swscanf(string, L"%02x%02x%02x%02x", &R, &G, &B, &A); - } - else if (len >= 6) - { - swscanf(string, L"%02x%02x%02x", &R, &G, &B); - } - } - - return Color::MakeARGB(A, R, G, B); -} - -/* -** Helper method that parses the Gdiplus::Rect values from the given string. -** The rect can be supplied as four comma separated values (X/Y/Width/Height). -** -*/ -Rect ConfigParser::ParseRect(LPCTSTR string) -{ - Rect r; - ParseInt4(string, r.X, r.Y, r.Width, r.Height); - return r; -} - -/* -** Helper method that parses the RECT values from the given string. -** The rect can be supplied as four comma separated values (left/top/right/bottom). -** -*/ -RECT ConfigParser::ParseRECT(LPCTSTR string) -{ - RECT r = {0}; - ParseInt4(string, r.left, r.top, r.right, r.bottom); - return r; -} - -/* -** Reads the given ini file and fills the m_Values and m_Keys maps. -** -*/ -void ConfigParser::ReadIniFile(const std::wstring& iniFile, LPCTSTR skinSection, int depth) -{ - if (depth > 100) // Is 100 enough to assume the include loop never ends? - { - Rainmeter::GetInstance().ShowMessage(nullptr, GetString(ID_STR_INCLUDEINFINITELOOP), MB_OK | MB_ICONERROR); - return; - } - - // Verify whether the file exists - if (_waccess(iniFile.c_str(), 0) == -1) - { - LogErrorF(m_MeterWindow, L"Unable to read file: %s", iniFile.c_str()); - return; - } - - // Avoid "IniFileMapping" - std::wstring iniRead = System::GetTemporaryFile(iniFile); - bool temporary = (!iniRead.empty() && (iniRead.size() != 1 || iniRead[0] != L'?')); - - if (temporary) - { - if (Rainmeter::GetInstance().GetDebug()) LogDebugF(m_MeterWindow, L"Reading file: %s (Temp: %s)", iniFile.c_str(), iniRead.c_str()); - } - else - { - if (Rainmeter::GetInstance().GetDebug()) LogDebugF(m_MeterWindow, L"Reading file: %s", iniFile.c_str()); - iniRead = iniFile; - } - - // Get all the sections (i.e. different meters) - std::list sections; - std::unordered_set unique; - std::wstring key, value; // buffer - - DWORD itemsSize = MAX_LINE_LENGTH; - WCHAR* items = new WCHAR[itemsSize]; - WCHAR* pos = nullptr; - WCHAR* epos = nullptr; - - if (skinSection == nullptr) - { - // Get all the sections - do - { - items[0] = 0; - DWORD res = GetPrivateProfileSectionNames(items, itemsSize, iniRead.c_str()); - if (res == 0) // File not found - { - delete [] items; - if (temporary) System::RemoveFile(iniRead); - return; - } - if (res < itemsSize - 2) // Fits in the buffer - { - epos = items + res; - break; - } - - delete [] items; - itemsSize *= 2; - items = new WCHAR[itemsSize]; - } - while (true); - - // Read the sections - pos = items; - while (pos < epos) - { - if (*pos) - { - value = pos; // section name - StrToUpperC(key.assign(value)); - if (unique.insert(key).second) - { - if (m_FoundSections.insert(key).second) - { - m_Sections.insert(m_SectionInsertPos, value); - } - sections.push_back(value); - } - pos += value.size() + 1; - } - else // Empty string - { - ++pos; - } - } - } - else - { - // Special case: Read only "Rainmeter" and specified section from "Rainmeter.ini" - const std::wstring strRainmeter = L"Rainmeter"; - const std::wstring strFolder = skinSection; - - sections.push_back(strRainmeter); - sections.push_back(strFolder); - - if (depth == 0) // Add once - { - m_Sections.push_back(strRainmeter); - m_Sections.push_back(strFolder); - } - } - - // Read the keys and values - for (auto it = sections.cbegin(); it != sections.cend(); ++it) - { - unique.clear(); - - const WCHAR* sectionName = (*it).c_str(); - bool isVariables = (_wcsicmp(sectionName, L"Variables") == 0); - bool isMetadata = (skinSection == nullptr && !isVariables && _wcsicmp(sectionName, L"Metadata") == 0); - bool resetInsertPos = true; - - // Read all "key=value" from the section - do - { - items[0] = 0; - DWORD res = GetPrivateProfileSection(sectionName, items, itemsSize, iniRead.c_str()); - if (res < itemsSize - 2) // Fits in the buffer - { - epos = items + res; - break; - } - - delete [] items; - itemsSize *= 2; - items = new WCHAR[itemsSize]; - } - while (true); - - pos = items; - while (pos < epos) - { - if (*pos) - { - size_t len = wcslen(pos); - WCHAR* sep = wmemchr(pos, L'=', len); - if (sep != nullptr && sep != pos) - { - size_t clen = sep - pos; // key's length - - StrToUpperC(key.assign(pos, clen)); - if (unique.insert(key).second) - { - ++sep; - clen = len - (clen + 1); // value's length - - // Trim surrounded quotes from value - if (clen >= 2 && (sep[0] == L'"' || sep[0] == L'\'') && sep[clen - 1] == sep[0]) - { - clen -= 2; - ++sep; - } - - if (wcsncmp(key.c_str(), L"@INCLUDE", 8) == 0) - { - if (clen > 0) - { - value.assign(sep, clen); - ReadVariables(); - ReplaceVariables(value); - if (!PathUtil::IsAbsolute(value)) - { - // Relative to the ini folder - value.insert(0, PathUtil::GetFolderFromFilePath(iniFile)); - } - - if (resetInsertPos) - { - auto jt = it; - if (++jt == sections.end()) // Special case: @include was used in the last section of the current file - { - // Set the insertion place to the last - m_SectionInsertPos = m_Sections.end(); - resetInsertPos = false; - } - else - { - // Find the appropriate insertion place - for (jt = m_Sections.cbegin(); jt != m_Sections.cend(); ++jt) - { - if (_wcsicmp((*jt).c_str(), sectionName) == 0) - { - m_SectionInsertPos = ++jt; - resetInsertPos = false; - break; - } - } - } - } - - ReadIniFile(value, skinSection, depth + 1); - } - } - else - { - if (!isMetadata) // Uncache Metadata's key-value pair in the skin - { - value.assign(sep, clen); - SetValue((*it), key, value); - - if (isVariables) - { - m_ListVariables.push_back(key); - } - } - } - } - } - pos += len + 1; - } - else // Empty string - { - ++pos; - } - } - } - - delete [] items; - if (temporary) System::RemoveFile(iniRead); -} - -/* -** Sets the value for the key under the given section. -** -*/ -void ConfigParser::SetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strValue) -{ - // LogDebugF(L"[%s] %s=%s (size: %i)", strSection.c_str(), strKey.c_str(), strValue.c_str(), (int)m_Values.size()); - - std::wstring strTmp; - strTmp.reserve(strSection.size() + 1 + strKey.size()); - strTmp = strSection; - strTmp += L'~'; - strTmp += strKey; - - m_Values[StrToUpperC(strTmp)] = strValue; -} - -/* -** Deletes the value for the key under the given section. -** -*/ -void ConfigParser::DeleteValue(const std::wstring& strSection, const std::wstring& strKey) -{ - std::wstring strTmp; - strTmp.reserve(strSection.size() + 1 + strKey.size()); - strTmp = strSection; - strTmp += L'~'; - strTmp += strKey; - - std::unordered_map::const_iterator iter = m_Values.find(StrToUpperC(strTmp)); - if (iter != m_Values.end()) - { - m_Values.erase(iter); - } -} - -/* -** Returns the value for the key under the given section. -** -*/ -const std::wstring& ConfigParser::GetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strDefault) -{ - std::wstring strTmp; - strTmp.reserve(strSection.size() + 1 + strKey.size()); - strTmp = strSection; - strTmp += L'~'; - strTmp += strKey; - - std::unordered_map::const_iterator iter = m_Values.find(StrToUpperC(strTmp)); - return (iter != m_Values.end()) ? (*iter).second : strDefault; -} +/* + Copyright (C) 2004 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../Common/MathParser.h" +#include "../Common/PathUtil.h" +#include "ConfigParser.h" +#include "Litestep.h" +#include "Rainmeter.h" +#include "System.h" +#include "Measure.h" +#include "Meter.h" +#include "resource.h" + +using namespace Gdiplus; + +std::unordered_map ConfigParser::c_MonitorVariables; + +/* +** The constructor +** +*/ +ConfigParser::ConfigParser() : + m_LastReplaced(false), + m_LastDefaultUsed(false), + m_LastValueDefined(false), + m_CurrentSection(), + m_MeterWindow() +{ +} + +/* +** The destructor +** +*/ +ConfigParser::~ConfigParser() +{ +} + +void ConfigParser::Initialize(const std::wstring& filename, MeterWindow* meterWindow, LPCTSTR skinSection, const std::wstring* resourcePath) +{ + m_MeterWindow = meterWindow; + + m_Measures.clear(); + m_Sections.clear(); + m_Values.clear(); + m_BuiltInVariables.clear(); + m_Variables.clear(); + + m_StyleTemplate.clear(); + m_LastReplaced = false; + m_LastDefaultUsed = false; + m_LastValueDefined = false; + + m_CurrentSection = nullptr; + m_SectionInsertPos = m_Sections.end(); + + // Set the built-in variables. Do this before the ini file is read so that the paths can be used with @include + SetBuiltInVariables(filename, resourcePath, meterWindow); + ResetMonitorVariables(meterWindow); + + System::UpdateIniFileMappingList(); + + ReadIniFile(filename, skinSection); + ReadVariables(); + + // Clear and minimize + m_FoundSections.clear(); + m_ListVariables.clear(); + m_SectionInsertPos = m_Sections.end(); +} + +void ConfigParser::SetBuiltInVariables(const std::wstring& filename, const std::wstring* resourcePath, MeterWindow* meterWindow) +{ + auto insertVariable = [&](const WCHAR* name, std::wstring value) + { + return m_BuiltInVariables.insert(std::make_pair(name, value)); + }; + + insertVariable(L"PROGRAMPATH", Rainmeter::GetInstance().GetPath()); + insertVariable(L"PROGRAMDRIVE", Rainmeter::GetInstance().GetDrive()); + insertVariable(L"SETTINGSPATH", Rainmeter::GetInstance().GetSettingsPath()); + insertVariable(L"SKINSPATH", Rainmeter::GetInstance().GetSkinPath()); + insertVariable(L"PLUGINSPATH", Rainmeter::GetInstance().GetPluginPath()); + insertVariable(L"CURRENTPATH", PathUtil::GetFolderFromFilePath(filename)); + insertVariable(L"ADDONSPATH", Rainmeter::GetInstance().GetAddonPath()); + + if (meterWindow) + { + insertVariable(L"CURRENTFILE", meterWindow->GetFileName()); + insertVariable(L"CURRENTCONFIG", meterWindow->GetFolderPath()); + insertVariable(L"ROOTCONFIG", meterWindow->GetRootName()); + insertVariable(L"ROOTCONFIGPATH", meterWindow->GetRootPath()); + } + + insertVariable(L"CRLF", L"\n"); + + m_CurrentSection = &(insertVariable(L"CURRENTSECTION", L"").first->second); // shortcut + + if (resourcePath) + { + SetVariable(L"@", *resourcePath); + } +} + +/* +** Sets all user-defined variables. +** +*/ +void ConfigParser::ReadVariables() +{ + std::list::const_iterator iter = m_ListVariables.begin(); + for ( ; iter != m_ListVariables.end(); ++iter) + { + SetVariable((*iter), ReadString(L"Variables", (*iter).c_str(), L"", false)); + } +} + +void ConfigParser::SetVariable(std::wstring strVariable, const std::wstring& strValue) +{ + StrToUpperC(strVariable); + m_Variables[strVariable] = strValue; +} + +void ConfigParser::SetBuiltInVariable(const std::wstring& strVariable, const std::wstring& strValue) +{ + m_BuiltInVariables[strVariable] = strValue; +} + +/* +** Gets a value for the variable. Returns nullptr if not found. +** +*/ +const std::wstring* ConfigParser::GetVariable(const std::wstring& strVariable) +{ + const std::wstring strTmp = StrToUpper(strVariable); + + // #1: Built-in variables + std::unordered_map::const_iterator iter = m_BuiltInVariables.find(strTmp); + if (iter != m_BuiltInVariables.end()) + { + return &(*iter).second; + } + + // #2: Monitor variables + iter = c_MonitorVariables.find(strTmp); + if (iter != c_MonitorVariables.end()) + { + return &(*iter).second; + } + + // #3: User-defined variables + iter = m_Variables.find(strTmp); + if (iter != m_Variables.end()) + { + return &(*iter).second; + } + + return nullptr; +} + +/* +** Gets the value of a section variable. Returns true if strValue is set. +** The selector is stripped from strVariable. +** +*/ +bool ConfigParser::GetSectionVariable(std::wstring& strVariable, std::wstring& strValue) +{ + size_t colonPos = strVariable.find_last_of(L':'); + if (colonPos == std::wstring::npos) + { + return false; + } + + const std::wstring selector = strVariable.substr(colonPos + 1); + const WCHAR* selectorSz = selector.c_str(); + strVariable.resize(colonPos); + + bool isKeySelector = (!selector.empty() && iswalpha(selectorSz[0])); + + if (isKeySelector) + { + // [Meter:X], [Meter:Y], [Meter:W], [Meter:H] + Meter* meter = m_MeterWindow->GetMeter(strVariable); + if (meter) + { + WCHAR buffer[32]; + if (_wcsicmp(selectorSz, L"X") == 0) + { + _itow_s(meter->GetX(), buffer, 10); + } + else if (_wcsicmp(selectorSz, L"Y") == 0) + { + _itow_s(meter->GetY(), buffer, 10); + } + else if (_wcsicmp(selectorSz, L"W") == 0) + { + _itow_s(meter->GetW(), buffer, 10); + } + else if (_wcsicmp(selectorSz, L"H") == 0) + { + _itow_s(meter->GetH(), buffer, 10); + } + else + { + return false; + } + + strValue = buffer; + return true; + } + } + + // Number: [Measure:], [Measure:dec] + // Percentual: [Measure:%], [Measure:%, dec] + // Scale: [Measure:/scale], [Measure:/scale, dec] + // Max/Min: [Measure:MaxValue], [Measure:MaxValue:/scale, dec] ('%' cannot be used) + // EscapeRegExp: [Measure:EscapeRegExp] (Escapes regular expression syntax, used for 'IfMatch') + enum class ValueType + { + Raw, + Percentual, + Max, + Min, + EscapeRegExp, + EncodeUrl + } valueType = ValueType::Raw; + + if (isKeySelector) + { + if (_wcsicmp(selectorSz, L"MaxValue") == 0) + { + valueType = ValueType::Max; + } + else if (_wcsicmp(selectorSz, L"MinValue") == 0) + { + valueType = ValueType::Min; + } + else if (_wcsicmp(selectorSz, L"EscapeRegExp") == 0) + { + valueType = ValueType::EscapeRegExp; + } + else if (_wcsicmp(selectorSz, L"EncodeUrl") == 0) + { + valueType = ValueType::EncodeUrl; + } + else + { + return false; + } + + selectorSz = L""; + } + else + { + colonPos = strVariable.find_last_of(L':'); + if (colonPos != std::wstring::npos) + { + do + { + const WCHAR* keySelectorSz = strVariable.c_str() + colonPos + 1; + + if (_wcsicmp(keySelectorSz, L"MaxValue") == 0) + { + valueType = ValueType::Max; + } + else if (_wcsicmp(keySelectorSz, L"MinValue") == 0) + { + valueType = ValueType::Min; + } + else + { + // Section name contains ':' ? + break; + } + + strVariable.resize(colonPos); + } + while (0); + } + } + + Measure* measure = m_MeterWindow->GetMeasure(strVariable); + if (measure) + { + if (valueType == ValueType::EscapeRegExp) + { + strValue = measure->GetStringValue(); + StringUtil::EscapeRegExp(strValue); + return true; + } + else if (valueType == ValueType::EncodeUrl) + { + strValue = measure->GetStringValue(); + StringUtil::EncodeUrl(strValue); + return true; + } + + int scale = 1; + + const WCHAR* decimalsSz = wcschr(selectorSz, L','); + if (decimalsSz) + { + ++decimalsSz; + } + + if (*selectorSz == L'%') // Percentual + { + if (valueType == ValueType::Max || valueType == ValueType::Min) + { + // '%' cannot be used with Max/Min values. + return false; + } + + valueType = ValueType::Percentual; + } + else if (*selectorSz == L'/') // Scale + { + errno = 0; + scale = _wtoi(selectorSz + 1); + if (errno == EINVAL || scale == 0) + { + // Invalid scale value. + return false; + } + } + else + { + if (decimalsSz) + { + return false; + } + + decimalsSz = selectorSz; + } + + const double value = + (valueType == ValueType::Percentual) ? measure->GetRelativeValue() * 100.0 : + (valueType == ValueType::Max) ? measure->GetMaxValue() / scale : + (valueType == ValueType::Min) ? measure->GetMinValue() / scale : + measure->GetValue() / scale; + int decimals = 10; + if (decimalsSz) + { + while (iswspace(*decimalsSz)) ++decimalsSz; + + if (*decimalsSz) + { + decimals = _wtoi(decimalsSz); + decimals = max(0, decimals); + decimals = min(32, decimals); + } + else + { + decimalsSz = nullptr; + } + } + + WCHAR format[32]; + WCHAR buffer[128]; + _snwprintf_s(format, _TRUNCATE, L"%%.%if", decimals); + int bufferLen = _snwprintf_s(buffer, _TRUNCATE, format, value); + + if (!decimalsSz) + { + // Remove trailing zeros if decimal count was not specified. + measure->RemoveTrailingZero(buffer, bufferLen); + bufferLen = (int)wcslen(buffer); + } + + strValue.assign(buffer, bufferLen); + return true; + } + + return false; +} + +void ConfigParser::ResetMonitorVariables(MeterWindow* meterWindow) +{ + // Set the SCREENAREA/WORKAREA variables + if (c_MonitorVariables.empty()) + { + SetMultiMonitorVariables(true); + } + + // Set the SCREENAREA/WORKAREA variables for present monitor + SetAutoSelectedMonitorVariables(meterWindow); +} + +/* +** Sets new values for the SCREENAREA/WORKAREA variables. +** +*/ +void ConfigParser::SetMultiMonitorVariables(bool reset) +{ + auto setMonitorVariable = [&](const WCHAR* variable, const WCHAR* value) + { + c_MonitorVariables[variable] = value; + }; + + if (!reset && c_MonitorVariables.empty()) + { + reset = true; // Set all variables + } + + const size_t numOfMonitors = System::GetMonitorCount(); // intentional + const MultiMonitorInfo& monitorsInfo = System::GetMultiMonitorInfo(); + const std::vector& monitors = monitorsInfo.monitors; + + WCHAR buffer[32]; + const RECT workArea = monitors[monitorsInfo.primary - 1].work; + const RECT scrArea = monitors[monitorsInfo.primary - 1].screen; + + _itow_s(workArea.left, buffer, 10); + setMonitorVariable(L"WORKAREAX", buffer); + setMonitorVariable(L"PWORKAREAX", buffer); + _itow_s(workArea.top, buffer, 10); + setMonitorVariable(L"WORKAREAY", buffer); + setMonitorVariable(L"PWORKAREAY", buffer); + _itow_s(workArea.right - workArea.left, buffer, 10); + setMonitorVariable(L"WORKAREAWIDTH", buffer); + setMonitorVariable(L"PWORKAREAWIDTH", buffer); + _itow_s(workArea.bottom - workArea.top, buffer, 10); + setMonitorVariable(L"WORKAREAHEIGHT", buffer); + setMonitorVariable(L"PWORKAREAHEIGHT", buffer); + + if (reset) + { + _itow_s(scrArea.left, buffer, 10); + setMonitorVariable(L"SCREENAREAX", buffer); + setMonitorVariable(L"PSCREENAREAX", buffer); + _itow_s(scrArea.top, buffer, 10); + setMonitorVariable(L"SCREENAREAY", buffer); + setMonitorVariable(L"PSCREENAREAY", buffer); + _itow_s(scrArea.right - scrArea.left, buffer, 10); + setMonitorVariable(L"SCREENAREAWIDTH", buffer); + setMonitorVariable(L"PSCREENAREAWIDTH", buffer); + _itow_s(scrArea.bottom - scrArea.top, buffer, 10); + setMonitorVariable(L"SCREENAREAHEIGHT", buffer); + setMonitorVariable(L"PSCREENAREAHEIGHT", buffer); + + _itow_s(monitorsInfo.vsL, buffer, 10); + setMonitorVariable(L"VSCREENAREAX", buffer); + _itow_s(monitorsInfo.vsT, buffer, 10); + setMonitorVariable(L"VSCREENAREAY", buffer); + _itow_s(monitorsInfo.vsW, buffer, 10); + setMonitorVariable(L"VSCREENAREAWIDTH", buffer); + _itow_s(monitorsInfo.vsH, buffer, 10); + setMonitorVariable(L"VSCREENAREAHEIGHT", buffer); + } + + int i = 1; + for (auto iter = monitors.cbegin(); iter != monitors.cend(); ++iter, ++i) + { + WCHAR buffer2[64]; + + const RECT work = ((*iter).active) ? (*iter).work : workArea; + + _itow_s(work.left, buffer, 10); + _snwprintf_s(buffer2, _TRUNCATE, L"WORKAREAX@%i", i); + setMonitorVariable(buffer2, buffer); + _itow_s(work.top, buffer, 10); + _snwprintf_s(buffer2, _TRUNCATE, L"WORKAREAY@%i", i); + setMonitorVariable(buffer2, buffer); + _itow_s(work.right - work.left, buffer, 10); + _snwprintf_s(buffer2, _TRUNCATE, L"WORKAREAWIDTH@%i", i); + setMonitorVariable(buffer2, buffer); + _itow_s(work.bottom - work.top, buffer, 10); + _snwprintf_s(buffer2, _TRUNCATE, L"WORKAREAHEIGHT@%i", i); + setMonitorVariable(buffer2, buffer); + + if (reset) + { + const RECT screen = ((*iter).active) ? (*iter).screen : scrArea; + + _itow_s(screen.left, buffer, 10); + _snwprintf_s(buffer2, _TRUNCATE, L"SCREENAREAX@%i", i); + setMonitorVariable(buffer2, buffer); + _itow_s(screen.top, buffer, 10); + _snwprintf_s(buffer2, _TRUNCATE, L"SCREENAREAY@%i", i); + setMonitorVariable(buffer2, buffer); + _itow_s(screen.right - screen.left, buffer, 10); + _snwprintf_s(buffer2, _TRUNCATE, L"SCREENAREAWIDTH@%i", i); + setMonitorVariable(buffer2, buffer); + _itow_s(screen.bottom - screen.top, buffer, 10); + _snwprintf_s(buffer2, _TRUNCATE, L"SCREENAREAHEIGHT@%i", i); + setMonitorVariable(buffer2, buffer); + } + } +} + +/* +** Sets new SCREENAREA/WORKAREA variables for present monitor. +** +*/ +void ConfigParser::SetAutoSelectedMonitorVariables(MeterWindow* meterWindow) +{ + if (meterWindow) + { + const int numOfMonitors = (int)System::GetMonitorCount(); + const MultiMonitorInfo& monitorsInfo = System::GetMultiMonitorInfo(); + const std::vector& monitors = monitorsInfo.monitors; + + WCHAR buffer[32]; + int w1, w2, s1, s2; + int screenIndex; + + // Set X / WIDTH + screenIndex = monitorsInfo.primary; + if (meterWindow->GetXScreenDefined()) + { + int i = meterWindow->GetXScreen(); + if (i >= 0 && (i == 0 || i <= numOfMonitors && monitors[i - 1].active)) + { + screenIndex = i; + } + } + + if (screenIndex == 0) + { + s1 = w1 = monitorsInfo.vsL; + s2 = w2 = monitorsInfo.vsW; + } + else + { + w1 = monitors[screenIndex - 1].work.left; + w2 = monitors[screenIndex - 1].work.right - monitors[screenIndex - 1].work.left; + s1 = monitors[screenIndex - 1].screen.left; + s2 = monitors[screenIndex - 1].screen.right - monitors[screenIndex - 1].screen.left; + } + + _itow_s(w1, buffer, 10); + SetBuiltInVariable(L"WORKAREAX", buffer); + _itow_s(w2, buffer, 10); + SetBuiltInVariable(L"WORKAREAWIDTH", buffer); + _itow_s(s1, buffer, 10); + SetBuiltInVariable(L"SCREENAREAX", buffer); + _itow_s(s2, buffer, 10); + SetBuiltInVariable(L"SCREENAREAWIDTH", buffer); + + // Set Y / HEIGHT + screenIndex = monitorsInfo.primary; + if (meterWindow->GetYScreenDefined()) + { + int i = meterWindow->GetYScreen(); + if (i >= 0 && (i == 0 || i <= numOfMonitors && monitors[i - 1].active)) + { + screenIndex = i; + } + } + + if (screenIndex == 0) + { + s1 = w1 = monitorsInfo.vsL; + s2 = w2 = monitorsInfo.vsW; + } + else + { + w1 = monitors[screenIndex - 1].work.top; + w2 = monitors[screenIndex - 1].work.bottom - monitors[screenIndex - 1].work.top; + s1 = monitors[screenIndex - 1].screen.top; + s2 = monitors[screenIndex - 1].screen.bottom - monitors[screenIndex - 1].screen.top; + } + + _itow_s(w1, buffer, 10); + SetBuiltInVariable(L"WORKAREAY", buffer); + _itow_s(w2, buffer, 10); + SetBuiltInVariable(L"WORKAREAHEIGHT", buffer); + _itow_s(s1, buffer, 10); + SetBuiltInVariable(L"SCREENAREAY", buffer); + _itow_s(s2, buffer, 10); + SetBuiltInVariable(L"SCREENAREAHEIGHT", buffer); + } +} + +/* +** Replaces environment and internal variables in the given string. +** +*/ +bool ConfigParser::ReplaceVariables(std::wstring& result) +{ + bool replaced = false; + + PathUtil::ExpandEnvironmentVariables(result); + + if (c_MonitorVariables.empty()) + { + SetMultiMonitorVariables(true); + } + + // Check for variables (#VAR#) + size_t start = 0, end; + bool loop = true; + + do + { + start = result.find(L'#', start); + if (start != std::wstring::npos) + { + size_t si = start + 1; + end = result.find(L'#', si); + if (end != std::wstring::npos) + { + size_t ei = end - 1; + if (si != ei && result[si] == L'*' && result[ei] == L'*') + { + result.erase(ei, 1); + result.erase(si, 1); + start = ei; + } + else + { + std::wstring strVariable = result.substr(si, end - si); + const std::wstring* value = GetVariable(strVariable); + if (value) + { + // Variable found, replace it with the value + result.replace(start, end - start + 1, *value); + start += (*value).length(); + replaced = true; + } + else + { + start = end; + } + } + } + else + { + loop = false; + } + } + else + { + loop = false; + } + } + while (loop); + + return replaced; +} + +/* +** Replaces measures in the given string. +** +*/ +bool ConfigParser::ReplaceMeasures(std::wstring& result) +{ + bool replaced = false; + + size_t start = 0; + while ((start = result.find(L'[', start)) != std::wstring::npos) + { + size_t si = start + 1; + size_t end = result.find(L']', si); + if (end == std::wstring::npos) + { + break; + } + + size_t next = result.find(L'[', si); + if (next == std::wstring::npos || end < next) + { + size_t ei = end - 1; + if (si != ei && result[si] == L'*' && result[ei] == L'*') + { + result.erase(ei, 1); + result.erase(si, 1); + start = ei; + } + else + { + std::wstring var = result.substr(si, end - si); + + Measure* measure = GetMeasure(var); + if (measure) + { + const WCHAR* value = measure->GetStringOrFormattedValue(AUTOSCALE_OFF, 1, -1, false); + size_t valueLen = wcslen(value); + + // Measure found, replace it with the value + result.replace(start, end - start + 1, value, valueLen); + start += valueLen; + replaced = true; + } + else + { + std::wstring value; + if (GetSectionVariable(var, value)) + { + // Replace section variable with the value. + result.replace(start, end - start + 1, value); + start += value.length(); + replaced = true; + } + else + { + start = end; + } + } + } + } + else + { + start = next; + } + } + + return replaced; +} + +const std::wstring& ConfigParser::ReadString(LPCTSTR section, LPCTSTR key, LPCTSTR defValue, bool bReplaceMeasures) +{ + static std::wstring result; + + // Clear last status + m_LastReplaced = false; + m_LastDefaultUsed = false; + m_LastValueDefined = false; + + const std::wstring strSection = section; + const std::wstring strKey = key; + const std::wstring strDefault = defValue; + + const std::wstring& strValue = GetValue(strSection, strKey, strDefault); + if (&strValue == &strDefault) + { + bool foundStyleValue = false; + + // If the template is defined read the value from there. + std::vector::const_reverse_iterator iter = m_StyleTemplate.rbegin(); + for ( ; iter != m_StyleTemplate.rend(); ++iter) + { + const std::wstring& strStyleValue = GetValue((*iter), strKey, strDefault); + + //LogDebugF(L"StyleTemplate: [%s] %s (from [%s]) : strDefault=%s (0x%p), strStyleValue=%s (0x%p)", + // section, key, (*iter).c_str(), strDefault.c_str(), &strDefault, strStyleValue.c_str(), &strStyleValue); + + if (&strStyleValue != &strDefault) + { + result = strStyleValue; + foundStyleValue = true; + break; + } + } + + if (!foundStyleValue) + { + result = strDefault; + m_LastDefaultUsed = true; + return result; + } + } + else + { + result = strValue; + } + + if (!result.empty()) + { + m_LastValueDefined = true; + + if (result.size() >= 3) + { + if (result.find(L'#') != std::wstring::npos) + { + m_CurrentSection->assign(strSection); // Set temporarily + + if (ReplaceVariables(result)) + { + m_LastReplaced = true; + } + + m_CurrentSection->clear(); // Reset + } + else + { + PathUtil::ExpandEnvironmentVariables(result); + } + + if (bReplaceMeasures && ReplaceMeasures(result)) + { + m_LastReplaced = true; + } + } + } + + return result; +} + +bool ConfigParser::IsKeyDefined(LPCTSTR section, LPCTSTR key) +{ + ReadString(section, key, L"", false); + return !m_LastDefaultUsed; +} + +bool ConfigParser::IsValueDefined(LPCTSTR section, LPCTSTR key) +{ + ReadString(section, key, L"", false); + return m_LastValueDefined; +} + +void ConfigParser::AddMeasure(Measure* pMeasure) +{ + if (pMeasure) + { + m_Measures[StrToUpper(pMeasure->GetOriginalName())] = pMeasure; + } +} + +Measure* ConfigParser::GetMeasure(const std::wstring& name) +{ + std::unordered_map::const_iterator iter = m_Measures.find(StrToUpper(name)); + if (iter != m_Measures.end()) + { + return (*iter).second; + } + + return nullptr; +} + +std::vector ConfigParser::ReadFloats(LPCTSTR section, LPCTSTR key) +{ + std::vector result; + const std::wstring& str = ReadString(section, key, L""); + if (!str.empty()) + { + // Tokenize and parse the floats + const WCHAR delimiter = L';'; + size_t lastPos, pos = 0; + do + { + lastPos = str.find_first_not_of(delimiter, pos); + if (lastPos == std::wstring::npos) break; + + pos = str.find_first_of(delimiter, lastPos + 1); + + result.push_back((Gdiplus::REAL)ParseDouble(str.substr(lastPos, pos - lastPos).c_str(), 0.0)); // (pos != std::wstring::npos) ? pos - lastPos : pos + if (pos == std::wstring::npos) break; + + ++pos; + } + while (true); + } + return result; +} + +int ConfigParser::ReadInt(LPCTSTR section, LPCTSTR key, int defValue) +{ + const std::wstring& result = ReadString(section, key, L""); + + if (!m_LastDefaultUsed) + { + const WCHAR* string = result.c_str(); + if (*string == L'(') + { + double dblValue; + const WCHAR* errMsg = MathParser::CheckedParse(string, &dblValue); + if (!errMsg) + { + return (int)dblValue; + } + + LogErrorF(m_MeterWindow, L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section); + } + else if (*string) + { + errno = 0; + int intValue = wcstol(string, nullptr, 10); + if (errno != ERANGE) + { + return intValue; + } + } + } + + return defValue; +} + +uint32_t ConfigParser::ReadUInt(LPCTSTR section, LPCTSTR key, uint32_t defValue) +{ + const std::wstring& result = ReadString(section, key, L""); + + if (!m_LastDefaultUsed) + { + const WCHAR* string = result.c_str(); + if (*string == L'(') + { + double dblValue; + const WCHAR* errMsg = MathParser::CheckedParse(string, &dblValue); + if (!errMsg) + { + return (uint32_t)dblValue; + } + + LogErrorF(m_MeterWindow, L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section); + } + else if (*string) + { + errno = 0; + uint32_t uintValue = wcstoul(string, nullptr, 10); + if (errno != ERANGE) + { + return uintValue; + } + } + } + + return defValue; +} + +uint64_t ConfigParser::ReadUInt64(LPCTSTR section, LPCTSTR key, uint64_t defValue) +{ + const std::wstring& result = ReadString(section, key, L""); + + if (!m_LastDefaultUsed) + { + const WCHAR* string = result.c_str(); + if (*string == L'(') + { + double dblValue; + const WCHAR* errMsg = MathParser::CheckedParse(string, &dblValue); + if (!errMsg) + { + return (uint64_t)dblValue; + } + + LogErrorF(m_MeterWindow, L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section); + } + else if (*string) + { + errno = 0; + uint64_t uint64Value = _wcstoui64(string, nullptr, 10); + if (errno != ERANGE) + { + return uint64Value; + } + } + } + + return defValue; +} + +double ConfigParser::ReadFloat(LPCTSTR section, LPCTSTR key, double defValue) +{ + const std::wstring& result = ReadString(section, key, L""); + + if (!m_LastDefaultUsed) + { + double value; + const WCHAR* string = result.c_str(); + if (*string == L'(') + { + const WCHAR* errMsg = MathParser::CheckedParse(string, &value); + if (!errMsg) + { + return value; + } + + LogErrorF(m_MeterWindow, L"Formula: %s in key \"%s\" in [%s]", errMsg, key, section); + } + else if (*string) + { + errno = 0; + value = wcstod(string, nullptr); + if (errno != ERANGE) + { + return value; + } + } + } + + return defValue; +} + +// Returns true if the formula was read successfully, false for failure. +bool ConfigParser::ParseFormula(const std::wstring& formula, double* resultValue) +{ + // Formulas must be surrounded by parenthesis + if (!formula.empty() && formula[0] == L'(' && formula[formula.size() - 1] == L')') + { + const WCHAR* string = formula.c_str(); + const WCHAR* errMsg = MathParser::CheckedParse(string, resultValue); + if (errMsg != nullptr) + { + LogErrorF(m_MeterWindow, L"Formula: %s: %s", errMsg, string); + return false; + } + + return true; + } + + return false; +} + +ARGB ConfigParser::ReadColor(LPCTSTR section, LPCTSTR key, ARGB defValue) +{ + const std::wstring& result = ReadString(section, key, L""); + + return (m_LastDefaultUsed) ? defValue : ParseColor(result.c_str()); +} + +Rect ConfigParser::ReadRect(LPCTSTR section, LPCTSTR key, const Rect& defValue) +{ + const std::wstring& result = ReadString(section, key, L""); + + return (m_LastDefaultUsed) ? defValue : ParseRect(result.c_str()); +} + +RECT ConfigParser::ReadRECT(LPCTSTR section, LPCTSTR key, const RECT& defValue) +{ + const std::wstring& result = ReadString(section, key, L""); + + RECT r; + if (m_LastDefaultUsed) + { + r = defValue; + } + else + { + r = ParseRECT(result.c_str()); + } + return r; +} + +/* +** Splits the string from the delimiters. +** Now trims empty element in vector and white-space in each string. +** +** Modified from http://www.digitalpeer.com/id/simple +*/ +std::vector ConfigParser::Tokenize(const std::wstring& str, const std::wstring& delimiters) +{ + std::vector tokens; + + size_t lastPos, pos = 0; + do + { + lastPos = str.find_first_not_of(delimiters, pos); + if (lastPos == std::wstring::npos) break; + + pos = str.find_first_of(delimiters, lastPos + 1); + std::wstring token = str.substr(lastPos, pos - lastPos); // len = (pos != std::wstring::npos) ? pos - lastPos : pos + + size_t pos2 = token.find_first_not_of(L" \t\r\n"); + if (pos2 != std::wstring::npos) + { + size_t lastPos2 = token.find_last_not_of(L" \t\r\n"); + if (pos2 != 0 || lastPos2 != (token.size() - 1)) + { + // Trim white-space + token.assign(token, pos2, lastPos2 - pos2 + 1); + } + tokens.push_back(token); + } + + if (pos == std::wstring::npos) break; + ++pos; + } + while (true); + + return tokens; +} + +/* +** Helper method that parses the floating-point value from the given string. +** If the given string is invalid format or causes overflow/underflow, returns given default value. +** +*/ +double ConfigParser::ParseDouble(LPCTSTR string, double defValue) +{ + assert(string); + + double value; + if (*string == L'(') + { + const WCHAR* errMsg = MathParser::CheckedParse(string, &value); + if (!errMsg) + { + return value; + } + + LogErrorF(L"Formula: %s: %s", errMsg, string); + } + else if (*string) + { + errno = 0; + double value = wcstod(string, nullptr); + if (errno != ERANGE) + { + return value; + } + } + + return defValue; +} + +/* +** Helper method that parses the integer value from the given string. +** If the given string is invalid format or causes overflow/underflow, returns given default value. +** +*/ +int ConfigParser::ParseInt(LPCTSTR string, int defValue) +{ + assert(string); + + if (*string == L'(') + { + double dblValue; + const WCHAR* errMsg = MathParser::CheckedParse(string, &dblValue); + if (!errMsg) + { + return (int)dblValue; + } + + LogErrorF(L"Formula: %s: %s", errMsg, string); + } + else if (*string) + { + errno = 0; + int intValue = wcstol(string, nullptr, 10); + if (errno != ERANGE) + { + return intValue; + } + } + + return defValue; +} + +/* +** Helper method that parses the unsigned integer value from the given string. +** If the given string is invalid format or causes overflow/underflow, returns given default value. +** +*/ +uint32_t ConfigParser::ParseUInt(LPCTSTR string, uint32_t defValue) +{ + assert(string); + + if (*string == L'(') + { + double dblValue; + const WCHAR* errMsg = MathParser::CheckedParse(string, &dblValue); + if (!errMsg) + { + return (uint32_t)dblValue; + } + + LogErrorF(L"Formula: %s: %s", errMsg, string); + } + else if (*string) + { + errno = 0; + uint32_t uintValue = wcstoul(string, nullptr, 10); + if (errno != ERANGE) + { + return uintValue; + } + } + + return defValue; +} + +/* +** Helper method that parses the 64bit unsigned integer value from the given string. +** If the given string is invalid format or causes overflow/underflow, returns given default value. +** +*/ +uint64_t ConfigParser::ParseUInt64(LPCTSTR string, uint64_t defValue) +{ + assert(string); + + if (*string == L'(') + { + double dblValue; + const WCHAR* errMsg = MathParser::CheckedParse(string, &dblValue); + if (!errMsg) + { + return (uint64_t)dblValue; + } + + LogErrorF(L"Formula: %s: %s", errMsg, string); + } + else if (*string) + { + errno = 0; + uint64_t uint64Value = _wcstoui64(string, nullptr, 10); + if (errno != ERANGE) + { + return uint64Value; + } + } + + return defValue; +} + +/* +** Helper template that parses four comma separated values from the given string. +** +*/ +template +bool ParseInt4(LPCTSTR string, T& v1, T& v2, T& v3, T& v4) +{ + if (wcschr(string, L',')) + { + WCHAR* parseSz = _wcsdup(string); + WCHAR* token; + + token = wcstok(parseSz, L","); + if (token) + { + v1 = ConfigParser::ParseInt(token, 0); + + token = wcstok(nullptr, L","); + if (token) + { + v2 = ConfigParser::ParseInt(token, 0); + + token = wcstok(nullptr, L","); + if (token) + { + v3 = ConfigParser::ParseInt(token, 0); + + token = wcstok(nullptr, L","); + if (token) + { + v4 = ConfigParser::ParseInt(token, 0); + } + } + } + } + free(parseSz); + return true; + } + + return false; +} + +/* +** Helper method that parses the color values from the given string. +** The color can be supplied as three/four comma separated values or as one +** hex-value. +** +*/ +ARGB ConfigParser::ParseColor(LPCTSTR string) +{ + int R = 255, G = 255, B = 255, A = 255; + + if (!ParseInt4(string, R, G, B, A)) + { + if (wcsncmp(string, L"0x", 2) == 0) + { + string += 2; // skip prefix + } + + size_t len = wcslen(string); + if (len >= 8 && !iswspace(string[6])) + { + swscanf(string, L"%02x%02x%02x%02x", &R, &G, &B, &A); + } + else if (len >= 6) + { + swscanf(string, L"%02x%02x%02x", &R, &G, &B); + } + } + + return Color::MakeARGB(A, R, G, B); +} + +/* +** Helper method that parses the Gdiplus::Rect values from the given string. +** The rect can be supplied as four comma separated values (X/Y/Width/Height). +** +*/ +Rect ConfigParser::ParseRect(LPCTSTR string) +{ + Rect r; + ParseInt4(string, r.X, r.Y, r.Width, r.Height); + return r; +} + +/* +** Helper method that parses the RECT values from the given string. +** The rect can be supplied as four comma separated values (left/top/right/bottom). +** +*/ +RECT ConfigParser::ParseRECT(LPCTSTR string) +{ + RECT r = {0}; + ParseInt4(string, r.left, r.top, r.right, r.bottom); + return r; +} + +/* +** Reads the given ini file and fills the m_Values and m_Keys maps. +** +*/ +void ConfigParser::ReadIniFile(const std::wstring& iniFile, LPCTSTR skinSection, int depth) +{ + if (depth > 100) // Is 100 enough to assume the include loop never ends? + { + Rainmeter::GetInstance().ShowMessage(nullptr, GetString(ID_STR_INCLUDEINFINITELOOP), MB_OK | MB_ICONERROR); + return; + } + + // Verify whether the file exists + if (_waccess(iniFile.c_str(), 0) == -1) + { + LogErrorF(m_MeterWindow, L"Unable to read file: %s", iniFile.c_str()); + return; + } + + // Avoid "IniFileMapping" + std::wstring iniRead = System::GetTemporaryFile(iniFile); + bool temporary = (!iniRead.empty() && (iniRead.size() != 1 || iniRead[0] != L'?')); + + if (temporary) + { + if (Rainmeter::GetInstance().GetDebug()) LogDebugF(m_MeterWindow, L"Reading file: %s (Temp: %s)", iniFile.c_str(), iniRead.c_str()); + } + else + { + if (Rainmeter::GetInstance().GetDebug()) LogDebugF(m_MeterWindow, L"Reading file: %s", iniFile.c_str()); + iniRead = iniFile; + } + + // Get all the sections (i.e. different meters) + std::list sections; + std::unordered_set unique; + std::wstring key, value; // buffer + + DWORD itemsSize = MAX_LINE_LENGTH; + WCHAR* items = new WCHAR[itemsSize]; + WCHAR* pos = nullptr; + WCHAR* epos = nullptr; + + if (skinSection == nullptr) + { + // Get all the sections + do + { + items[0] = 0; + DWORD res = GetPrivateProfileSectionNames(items, itemsSize, iniRead.c_str()); + if (res == 0) // File not found + { + delete [] items; + if (temporary) System::RemoveFile(iniRead); + return; + } + if (res < itemsSize - 2) // Fits in the buffer + { + epos = items + res; + break; + } + + delete [] items; + itemsSize *= 2; + items = new WCHAR[itemsSize]; + } + while (true); + + // Read the sections + pos = items; + while (pos < epos) + { + if (*pos) + { + value = pos; // section name + StrToUpperC(key.assign(value)); + if (unique.insert(key).second) + { + if (m_FoundSections.insert(key).second) + { + m_Sections.insert(m_SectionInsertPos, value); + } + sections.push_back(value); + } + pos += value.size() + 1; + } + else // Empty string + { + ++pos; + } + } + } + else + { + // Special case: Read only "Rainmeter" and specified section from "Rainmeter.ini" + const std::wstring strRainmeter = L"Rainmeter"; + const std::wstring strFolder = skinSection; + + sections.push_back(strRainmeter); + sections.push_back(strFolder); + + if (depth == 0) // Add once + { + m_Sections.push_back(strRainmeter); + m_Sections.push_back(strFolder); + } + } + + // Read the keys and values + for (auto it = sections.cbegin(); it != sections.cend(); ++it) + { + unique.clear(); + + const WCHAR* sectionName = (*it).c_str(); + bool isVariables = (_wcsicmp(sectionName, L"Variables") == 0); + bool isMetadata = (skinSection == nullptr && !isVariables && _wcsicmp(sectionName, L"Metadata") == 0); + bool resetInsertPos = true; + + // Read all "key=value" from the section + do + { + items[0] = 0; + DWORD res = GetPrivateProfileSection(sectionName, items, itemsSize, iniRead.c_str()); + if (res < itemsSize - 2) // Fits in the buffer + { + epos = items + res; + break; + } + + delete [] items; + itemsSize *= 2; + items = new WCHAR[itemsSize]; + } + while (true); + + pos = items; + while (pos < epos) + { + if (*pos) + { + size_t len = wcslen(pos); + WCHAR* sep = wmemchr(pos, L'=', len); + if (sep != nullptr && sep != pos) + { + size_t clen = sep - pos; // key's length + + StrToUpperC(key.assign(pos, clen)); + if (unique.insert(key).second) + { + ++sep; + clen = len - (clen + 1); // value's length + + // Trim surrounded quotes from value + if (clen >= 2 && (sep[0] == L'"' || sep[0] == L'\'') && sep[clen - 1] == sep[0]) + { + clen -= 2; + ++sep; + } + + if (wcsncmp(key.c_str(), L"@INCLUDE", 8) == 0) + { + if (clen > 0) + { + value.assign(sep, clen); + ReadVariables(); + ReplaceVariables(value); + if (!PathUtil::IsAbsolute(value)) + { + // Relative to the ini folder + value.insert(0, PathUtil::GetFolderFromFilePath(iniFile)); + } + + if (resetInsertPos) + { + auto jt = it; + if (++jt == sections.end()) // Special case: @include was used in the last section of the current file + { + // Set the insertion place to the last + m_SectionInsertPos = m_Sections.end(); + resetInsertPos = false; + } + else + { + // Find the appropriate insertion place + for (jt = m_Sections.cbegin(); jt != m_Sections.cend(); ++jt) + { + if (_wcsicmp((*jt).c_str(), sectionName) == 0) + { + m_SectionInsertPos = ++jt; + resetInsertPos = false; + break; + } + } + } + } + + ReadIniFile(value, skinSection, depth + 1); + } + } + else + { + if (!isMetadata) // Uncache Metadata's key-value pair in the skin + { + value.assign(sep, clen); + SetValue((*it), key, value); + + if (isVariables) + { + m_ListVariables.push_back(key); + } + } + } + } + } + pos += len + 1; + } + else // Empty string + { + ++pos; + } + } + } + + delete [] items; + if (temporary) System::RemoveFile(iniRead); +} + +/* +** Sets the value for the key under the given section. +** +*/ +void ConfigParser::SetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strValue) +{ + // LogDebugF(L"[%s] %s=%s (size: %i)", strSection.c_str(), strKey.c_str(), strValue.c_str(), (int)m_Values.size()); + + std::wstring strTmp; + strTmp.reserve(strSection.size() + 1 + strKey.size()); + strTmp = strSection; + strTmp += L'~'; + strTmp += strKey; + + m_Values[StrToUpperC(strTmp)] = strValue; +} + +/* +** Deletes the value for the key under the given section. +** +*/ +void ConfigParser::DeleteValue(const std::wstring& strSection, const std::wstring& strKey) +{ + std::wstring strTmp; + strTmp.reserve(strSection.size() + 1 + strKey.size()); + strTmp = strSection; + strTmp += L'~'; + strTmp += strKey; + + std::unordered_map::const_iterator iter = m_Values.find(StrToUpperC(strTmp)); + if (iter != m_Values.end()) + { + m_Values.erase(iter); + } +} + +/* +** Returns the value for the key under the given section. +** +*/ +const std::wstring& ConfigParser::GetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strDefault) +{ + std::wstring strTmp; + strTmp.reserve(strSection.size() + 1 + strKey.size()); + strTmp = strSection; + strTmp += L'~'; + strTmp += strKey; + + std::unordered_map::const_iterator iter = m_Values.find(StrToUpperC(strTmp)); + return (iter != m_Values.end()) ? (*iter).second : strDefault; +} diff --git a/Library/ConfigParser.h b/Library/ConfigParser.h index d37a3a9e..b3995554 100644 --- a/Library/ConfigParser.h +++ b/Library/ConfigParser.h @@ -1,151 +1,151 @@ -/* - Copyright (C) 2004 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __CONFIGPARSER_H__ -#define __CONFIGPARSER_H__ - -#pragma warning(disable: 4503) - -#include -#include -#include -#include -#include -#include -#include -#include // For Gdiplus.h. -#include - -class Rainmeter; -class MeterWindow; -class Measure; -class Meter; - -class ConfigParser -{ -public: - ConfigParser(); - ~ConfigParser(); - - ConfigParser(const ConfigParser& other) = delete; - ConfigParser& operator=(ConfigParser other) = delete; - - void Initialize(const std::wstring& filename, MeterWindow* meterWindow = nullptr, LPCTSTR skinSection = nullptr, const std::wstring* resourcePath = nullptr); - - void AddMeasure(Measure* pMeasure); - Measure* GetMeasure(const std::wstring& name); - - const std::wstring* GetVariable(const std::wstring& strVariable); - void SetVariable(std::wstring strVariable, const std::wstring& strValue); - void SetBuiltInVariable(const std::wstring& strVariable, const std::wstring& strValue); - - const std::unordered_map& GetVariables() { return m_Variables; } - - const std::wstring& GetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strDefault); - void SetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strValue); - void DeleteValue(const std::wstring& strSection, const std::wstring& strKey); - - void SetStyleTemplate(const std::wstring& strStyle) { static const std::wstring delim(1, L'|'); Tokenize(strStyle, delim).swap(m_StyleTemplate); } - void ClearStyleTemplate() { m_StyleTemplate.clear(); } - - bool GetLastReplaced() { return m_LastReplaced; } - bool GetLastDefaultUsed() { return m_LastDefaultUsed; } - bool GetLastKeyDefined() { return !m_LastDefaultUsed; } - bool GetLastValueDefined() { return m_LastValueDefined; } - - void ResetMonitorVariables(MeterWindow* meterWindow = nullptr); - - const std::wstring& ReadString(LPCTSTR section, LPCTSTR key, LPCTSTR defValue, bool bReplaceMeasures = true); - bool IsKeyDefined(LPCTSTR section, LPCTSTR key); - bool IsValueDefined(LPCTSTR section, LPCTSTR key); - bool ReadBool(LPCTSTR section, LPCTSTR key, bool defValue) { return ReadInt(section, key, (int)defValue) != 0; } - int ReadInt(LPCTSTR section, LPCTSTR key, int defValue); - uint32_t ReadUInt(LPCTSTR section, LPCTSTR key, uint32_t defValue); - uint64_t ReadUInt64(LPCTSTR section, LPCTSTR key, uint64_t defValue); - double ReadFloat(LPCTSTR section, LPCTSTR key, double defValue); - Gdiplus::ARGB ReadColor(LPCTSTR section, LPCTSTR key, Gdiplus::ARGB defValue); - Gdiplus::Rect ReadRect(LPCTSTR section, LPCTSTR key, const Gdiplus::Rect& defValue); - RECT ReadRECT(LPCTSTR section, LPCTSTR key, const RECT& defValue); - std::vector ReadFloats(LPCTSTR section, LPCTSTR key); - - bool ParseFormula(const std::wstring& formula, double* resultValue); - - const std::list& GetSections() { return m_Sections; } - - bool ReplaceVariables(std::wstring& result); - bool ReplaceMeasures(std::wstring& result); - - static std::vector Tokenize(const std::wstring& str, const std::wstring& delimiters); - static double ParseDouble(LPCTSTR string, double defValue); - static int ParseInt(LPCTSTR string, int defValue); - static uint32_t ParseUInt(LPCTSTR string, uint32_t defValue); - static uint64_t ParseUInt64(LPCTSTR string, uint64_t defValue); - static Gdiplus::ARGB ParseColor(LPCTSTR string); - static Gdiplus::Rect ParseRect(LPCTSTR string); - static RECT ParseRECT(LPCTSTR string); - - static void ClearMultiMonitorVariables() { c_MonitorVariables.clear(); } - static void UpdateWorkareaVariables() { SetMultiMonitorVariables(false); } - -private: - void SetBuiltInVariables(const std::wstring& filename, const std::wstring* resourcePath, MeterWindow* meterWindow); - - void ReadVariables(); - - void ReadIniFile(const std::wstring& iniFile, LPCTSTR skinSection = nullptr, int depth = 0); - - void SetAutoSelectedMonitorVariables(MeterWindow* meterWindow); - - bool GetSectionVariable(std::wstring& strVariable, std::wstring& strValue); - - static void SetVariable(std::unordered_map& variables, const std::wstring& strVariable, const std::wstring& strValue); - static void SetVariable(std::unordered_map& variables, const WCHAR* strVariable, const WCHAR* strValue); - - static void SetMultiMonitorVariables(bool reset); - static void SetMonitorVariable(const WCHAR* strVariable, const WCHAR* strValue); - - static std::wstring StrToUpper(const std::wstring& str) { std::wstring strTmp(str); StrToUpperC(strTmp); return strTmp; } - static std::wstring StrToUpper(const WCHAR* str) { std::wstring strTmp(str); StrToUpperC(strTmp); return strTmp; } - static std::wstring& StrToUpperC(std::wstring& str) { _wcsupr(&str[0]); return str; } - - std::unordered_map m_Measures; - - std::vector m_StyleTemplate; - - bool m_LastReplaced; - bool m_LastDefaultUsed; - bool m_LastValueDefined; - - std::wstring* m_CurrentSection; - - std::list m_Sections; // Ordered section - std::unordered_map m_Values; - - std::unordered_set m_FoundSections; - std::list m_ListVariables; - std::list::const_iterator m_SectionInsertPos; - - std::unordered_map m_BuiltInVariables; - std::unordered_map m_Variables; - - MeterWindow* m_MeterWindow; - - static std::unordered_map c_MonitorVariables; -}; - -#endif +/* + Copyright (C) 2004 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __CONFIGPARSER_H__ +#define __CONFIGPARSER_H__ + +#pragma warning(disable: 4503) + +#include +#include +#include +#include +#include +#include +#include +#include // For Gdiplus.h. +#include + +class Rainmeter; +class MeterWindow; +class Measure; +class Meter; + +class ConfigParser +{ +public: + ConfigParser(); + ~ConfigParser(); + + ConfigParser(const ConfigParser& other) = delete; + ConfigParser& operator=(ConfigParser other) = delete; + + void Initialize(const std::wstring& filename, MeterWindow* meterWindow = nullptr, LPCTSTR skinSection = nullptr, const std::wstring* resourcePath = nullptr); + + void AddMeasure(Measure* pMeasure); + Measure* GetMeasure(const std::wstring& name); + + const std::wstring* GetVariable(const std::wstring& strVariable); + void SetVariable(std::wstring strVariable, const std::wstring& strValue); + void SetBuiltInVariable(const std::wstring& strVariable, const std::wstring& strValue); + + const std::unordered_map& GetVariables() { return m_Variables; } + + const std::wstring& GetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strDefault); + void SetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strValue); + void DeleteValue(const std::wstring& strSection, const std::wstring& strKey); + + void SetStyleTemplate(const std::wstring& strStyle) { static const std::wstring delim(1, L'|'); Tokenize(strStyle, delim).swap(m_StyleTemplate); } + void ClearStyleTemplate() { m_StyleTemplate.clear(); } + + bool GetLastReplaced() { return m_LastReplaced; } + bool GetLastDefaultUsed() { return m_LastDefaultUsed; } + bool GetLastKeyDefined() { return !m_LastDefaultUsed; } + bool GetLastValueDefined() { return m_LastValueDefined; } + + void ResetMonitorVariables(MeterWindow* meterWindow = nullptr); + + const std::wstring& ReadString(LPCTSTR section, LPCTSTR key, LPCTSTR defValue, bool bReplaceMeasures = true); + bool IsKeyDefined(LPCTSTR section, LPCTSTR key); + bool IsValueDefined(LPCTSTR section, LPCTSTR key); + bool ReadBool(LPCTSTR section, LPCTSTR key, bool defValue) { return ReadInt(section, key, (int)defValue) != 0; } + int ReadInt(LPCTSTR section, LPCTSTR key, int defValue); + uint32_t ReadUInt(LPCTSTR section, LPCTSTR key, uint32_t defValue); + uint64_t ReadUInt64(LPCTSTR section, LPCTSTR key, uint64_t defValue); + double ReadFloat(LPCTSTR section, LPCTSTR key, double defValue); + Gdiplus::ARGB ReadColor(LPCTSTR section, LPCTSTR key, Gdiplus::ARGB defValue); + Gdiplus::Rect ReadRect(LPCTSTR section, LPCTSTR key, const Gdiplus::Rect& defValue); + RECT ReadRECT(LPCTSTR section, LPCTSTR key, const RECT& defValue); + std::vector ReadFloats(LPCTSTR section, LPCTSTR key); + + bool ParseFormula(const std::wstring& formula, double* resultValue); + + const std::list& GetSections() { return m_Sections; } + + bool ReplaceVariables(std::wstring& result); + bool ReplaceMeasures(std::wstring& result); + + static std::vector Tokenize(const std::wstring& str, const std::wstring& delimiters); + static double ParseDouble(LPCTSTR string, double defValue); + static int ParseInt(LPCTSTR string, int defValue); + static uint32_t ParseUInt(LPCTSTR string, uint32_t defValue); + static uint64_t ParseUInt64(LPCTSTR string, uint64_t defValue); + static Gdiplus::ARGB ParseColor(LPCTSTR string); + static Gdiplus::Rect ParseRect(LPCTSTR string); + static RECT ParseRECT(LPCTSTR string); + + static void ClearMultiMonitorVariables() { c_MonitorVariables.clear(); } + static void UpdateWorkareaVariables() { SetMultiMonitorVariables(false); } + +private: + void SetBuiltInVariables(const std::wstring& filename, const std::wstring* resourcePath, MeterWindow* meterWindow); + + void ReadVariables(); + + void ReadIniFile(const std::wstring& iniFile, LPCTSTR skinSection = nullptr, int depth = 0); + + void SetAutoSelectedMonitorVariables(MeterWindow* meterWindow); + + bool GetSectionVariable(std::wstring& strVariable, std::wstring& strValue); + + static void SetVariable(std::unordered_map& variables, const std::wstring& strVariable, const std::wstring& strValue); + static void SetVariable(std::unordered_map& variables, const WCHAR* strVariable, const WCHAR* strValue); + + static void SetMultiMonitorVariables(bool reset); + static void SetMonitorVariable(const WCHAR* strVariable, const WCHAR* strValue); + + static std::wstring StrToUpper(const std::wstring& str) { std::wstring strTmp(str); StrToUpperC(strTmp); return strTmp; } + static std::wstring StrToUpper(const WCHAR* str) { std::wstring strTmp(str); StrToUpperC(strTmp); return strTmp; } + static std::wstring& StrToUpperC(std::wstring& str) { _wcsupr(&str[0]); return str; } + + std::unordered_map m_Measures; + + std::vector m_StyleTemplate; + + bool m_LastReplaced; + bool m_LastDefaultUsed; + bool m_LastValueDefined; + + std::wstring* m_CurrentSection; + + std::list m_Sections; // Ordered section + std::unordered_map m_Values; + + std::unordered_set m_FoundSections; + std::list m_ListVariables; + std::list::const_iterator m_SectionInsertPos; + + std::unordered_map m_BuiltInVariables; + std::unordered_map m_Variables; + + MeterWindow* m_MeterWindow; + + static std::unordered_map c_MonitorVariables; +}; + +#endif diff --git a/Library/ConfigParser_Test.cpp b/Library/ConfigParser_Test.cpp index ac3053d3..cf153a5c 100644 --- a/Library/ConfigParser_Test.cpp +++ b/Library/ConfigParser_Test.cpp @@ -1,113 +1,113 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "ConfigParser.h" -#include "../Common/UnitTest.h" - -TEST_CLASS(Library_ConfigParser_Test) -{ -public: - TEST_METHOD(TestReadFunctions) - { - ConfigParser parser; - parser.Initialize(L""); // TODO: Better way to initialize without file. - - parser.SetValue(L"A", L"String", L"abc"); - Assert::AreEqual(parser.ReadString(L"A", L"String", L"").c_str(), L"abc"); - Assert::AreEqual(parser.ReadString(L"A", L"StringNA", L"def").c_str(), L"def"); - - parser.SetValue(L"A", L"Number", L"2"); - Assert::AreEqual(parser.ReadInt(L"A", L"Number", 0), 2); - - parser.SetValue(L"A", L"NumberFloat", L"1.23"); - Assert::AreEqual(parser.ReadFloat(L"A", L"NumberFloat", 0.0), 1.23); - - parser.SetValue(L"A", L"NumberU64", L"18446744073709551615"); - Assert::AreEqual(parser.ReadUInt64(L"A", L"NumberU64", 0), 18446744073709551615); - - parser.SetValue(L"A", L"Formula", L"(1 + 2)"); - Assert::AreEqual(parser.ReadInt(L"A", L"Formula", 0), 3); - Assert::AreEqual(parser.ReadUInt(L"A", L"Formula", 0), 3U); - Assert::AreEqual(parser.ReadFloat(L"A", L"Formula", 0.0), 3.0); - - parser.SetValue(L"A", L"Color1", L"AABBCCDD"); - parser.SetValue(L"A", L"Color2", L"170,187,204,221"); - parser.SetValue(L"A", L"Color3", L"AABBCC"); - parser.SetValue(L"A", L"Color4", L"170,187,204"); - Assert::AreEqual(parser.ReadColor(L"A", L"Color1", 0x00000000), (Gdiplus::ARGB)0xDDAABBCC); - Assert::AreEqual(parser.ReadColor(L"A", L"Color2", 0x00000000), (Gdiplus::ARGB)0xDDAABBCC); - Assert::AreEqual(parser.ReadColor(L"A", L"Color3", 0x00000000), (Gdiplus::ARGB)0xFFAABBCC); - Assert::AreEqual(parser.ReadColor(L"A", L"Color4", 0x00000000), (Gdiplus::ARGB)0xFFAABBCC); - Assert::AreEqual(parser.ReadColor(L"A", L"ColorNA", 0x00000000), (Gdiplus::ARGB)0x00000000); - - parser.SetValue(L"A", L"Rect", L"1,2,11,22"); - const RECT defRect = {}; - const RECT expRect = {1, 2, 11, 22}; - const RECT readRect = parser.ReadRECT(L"A", L"Rect", defRect); - Assert::AreEqual(readRect.left, expRect.left); - Assert::AreEqual(readRect.top, expRect.top); - Assert::AreEqual(readRect.right, expRect.right); - Assert::AreEqual(readRect.bottom, expRect.bottom); - - parser.SetValue(L"A", L"Floats", L"1.1;2.1;;3.1"); - std::vector expFloats; - expFloats.push_back(1.1f); - expFloats.push_back(2.1f); - expFloats.push_back(3.1f); - Assert::IsTrue(parser.ReadFloats(L"A", L"Floats") == expFloats); - Assert::IsTrue(parser.ReadFloats(L"A", L"FloatsNA").empty()); - } - - TEST_METHOD(TestVariables) - { - ConfigParser parser; - parser.Initialize(L""); // TODO: Better way to initialize without file. - - parser.SetVariable(L"A", L"abc"); - parser.SetVariable(L"BB", L"def"); - parser.SetVariable(L"CCC", L"#A#"); - parser.SetVariable(L"Var", L"Normal"); - parser.SetBuiltInVariable(L"Var", L"BuiltIn"); - - std::wstring string1 = L"A"; - Assert::IsFalse(parser.ReplaceVariables(string1)); - Assert::AreEqual(string1.c_str(), L"A"); - - std::wstring string2 = L"#A#"; - Assert::IsTrue(parser.ReplaceVariables(string2)); - Assert::AreEqual(string2.c_str(), L"abc"); - - std::wstring string3 = L"#*A*#"; - Assert::IsFalse(parser.ReplaceVariables(string3)); - Assert::AreEqual(string3.c_str(), L"#A#"); - - std::wstring string4 = L"#A##a# #*CCC*# #BB##CCC#"; - Assert::IsTrue(parser.ReplaceVariables(string4)); - Assert::AreEqual(string4.c_str(), L"abcabc #CCC# def#A#"); - - parser.SetValue(L"A", L"String", L"#A#"); - Assert::AreEqual(parser.ReadString(L"A", L"String", L"").c_str(), L"abc"); - - parser.SetValue(L"A", L"String", L"%WINDIR%"); - Assert::AreNotEqual(parser.ReadString(L"A", L"String", L"").c_str(), L"%WINDIR%"); - - parser.SetValue(L"A", L"String", L"#Var#"); - Assert::AreNotEqual(parser.ReadString(L"A", L"String", L"").c_str(), L"BuiltIn"); - } -}; +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "ConfigParser.h" +#include "../Common/UnitTest.h" + +TEST_CLASS(Library_ConfigParser_Test) +{ +public: + TEST_METHOD(TestReadFunctions) + { + ConfigParser parser; + parser.Initialize(L""); // TODO: Better way to initialize without file. + + parser.SetValue(L"A", L"String", L"abc"); + Assert::AreEqual(parser.ReadString(L"A", L"String", L"").c_str(), L"abc"); + Assert::AreEqual(parser.ReadString(L"A", L"StringNA", L"def").c_str(), L"def"); + + parser.SetValue(L"A", L"Number", L"2"); + Assert::AreEqual(parser.ReadInt(L"A", L"Number", 0), 2); + + parser.SetValue(L"A", L"NumberFloat", L"1.23"); + Assert::AreEqual(parser.ReadFloat(L"A", L"NumberFloat", 0.0), 1.23); + + parser.SetValue(L"A", L"NumberU64", L"18446744073709551615"); + Assert::AreEqual(parser.ReadUInt64(L"A", L"NumberU64", 0), 18446744073709551615); + + parser.SetValue(L"A", L"Formula", L"(1 + 2)"); + Assert::AreEqual(parser.ReadInt(L"A", L"Formula", 0), 3); + Assert::AreEqual(parser.ReadUInt(L"A", L"Formula", 0), 3U); + Assert::AreEqual(parser.ReadFloat(L"A", L"Formula", 0.0), 3.0); + + parser.SetValue(L"A", L"Color1", L"AABBCCDD"); + parser.SetValue(L"A", L"Color2", L"170,187,204,221"); + parser.SetValue(L"A", L"Color3", L"AABBCC"); + parser.SetValue(L"A", L"Color4", L"170,187,204"); + Assert::AreEqual(parser.ReadColor(L"A", L"Color1", 0x00000000), (Gdiplus::ARGB)0xDDAABBCC); + Assert::AreEqual(parser.ReadColor(L"A", L"Color2", 0x00000000), (Gdiplus::ARGB)0xDDAABBCC); + Assert::AreEqual(parser.ReadColor(L"A", L"Color3", 0x00000000), (Gdiplus::ARGB)0xFFAABBCC); + Assert::AreEqual(parser.ReadColor(L"A", L"Color4", 0x00000000), (Gdiplus::ARGB)0xFFAABBCC); + Assert::AreEqual(parser.ReadColor(L"A", L"ColorNA", 0x00000000), (Gdiplus::ARGB)0x00000000); + + parser.SetValue(L"A", L"Rect", L"1,2,11,22"); + const RECT defRect = {}; + const RECT expRect = {1, 2, 11, 22}; + const RECT readRect = parser.ReadRECT(L"A", L"Rect", defRect); + Assert::AreEqual(readRect.left, expRect.left); + Assert::AreEqual(readRect.top, expRect.top); + Assert::AreEqual(readRect.right, expRect.right); + Assert::AreEqual(readRect.bottom, expRect.bottom); + + parser.SetValue(L"A", L"Floats", L"1.1;2.1;;3.1"); + std::vector expFloats; + expFloats.push_back(1.1f); + expFloats.push_back(2.1f); + expFloats.push_back(3.1f); + Assert::IsTrue(parser.ReadFloats(L"A", L"Floats") == expFloats); + Assert::IsTrue(parser.ReadFloats(L"A", L"FloatsNA").empty()); + } + + TEST_METHOD(TestVariables) + { + ConfigParser parser; + parser.Initialize(L""); // TODO: Better way to initialize without file. + + parser.SetVariable(L"A", L"abc"); + parser.SetVariable(L"BB", L"def"); + parser.SetVariable(L"CCC", L"#A#"); + parser.SetVariable(L"Var", L"Normal"); + parser.SetBuiltInVariable(L"Var", L"BuiltIn"); + + std::wstring string1 = L"A"; + Assert::IsFalse(parser.ReplaceVariables(string1)); + Assert::AreEqual(string1.c_str(), L"A"); + + std::wstring string2 = L"#A#"; + Assert::IsTrue(parser.ReplaceVariables(string2)); + Assert::AreEqual(string2.c_str(), L"abc"); + + std::wstring string3 = L"#*A*#"; + Assert::IsFalse(parser.ReplaceVariables(string3)); + Assert::AreEqual(string3.c_str(), L"#A#"); + + std::wstring string4 = L"#A##a# #*CCC*# #BB##CCC#"; + Assert::IsTrue(parser.ReplaceVariables(string4)); + Assert::AreEqual(string4.c_str(), L"abcabc #CCC# def#A#"); + + parser.SetValue(L"A", L"String", L"#A#"); + Assert::AreEqual(parser.ReadString(L"A", L"String", L"").c_str(), L"abc"); + + parser.SetValue(L"A", L"String", L"%WINDIR%"); + Assert::AreNotEqual(parser.ReadString(L"A", L"String", L"").c_str(), L"%WINDIR%"); + + parser.SetValue(L"A", L"String", L"#Var#"); + Assert::AreNotEqual(parser.ReadString(L"A", L"String", L"").c_str(), L"BuiltIn"); + } +}; diff --git a/Library/ContextMenu.cpp b/Library/ContextMenu.cpp index 3eae3830..22738bc1 100644 --- a/Library/ContextMenu.cpp +++ b/Library/ContextMenu.cpp @@ -1,690 +1,690 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../Common/MenuTemplate.h" -#include "../Common/Gfx/CanvasD2D.h" -#include "ContextMenu.h" -#include "Rainmeter.h" -#include "Litestep.h" -#include "MeterWindow.h" -#include "System.h" -#include "TrayWindow.h" -#include "resource.h" - -ContextMenu::ContextMenu() : - m_MenuActive(false) -{ -} - -/* -** Opens the context menu in given coordinates. -*/ -void ContextMenu::ShowMenu(POINT pos, MeterWindow* meterWindow) -{ - static const MenuTemplate s_Menu[] = - { - MENU_ITEM(IDM_MANAGE, ID_STR_MANAGE), - MENU_ITEM(IDM_ABOUT, ID_STR_ABOUT), - MENU_ITEM(IDM_SHOW_HELP, ID_STR_HELP), - MENU_SEPARATOR(), - MENU_SUBMENU(ID_STR_SKINS, - MENU_ITEM_GRAYED(0, ID_STR_NOSKINS), - MENU_SEPARATOR(), - MENU_ITEM(IDM_OPENSKINSFOLDER, ID_STR_OPENFOLDER), - MENU_ITEM(IDM_DISABLEDRAG, ID_STR_DISABLEDRAGGING)), - MENU_SUBMENU(ID_STR_THEMES, - MENU_ITEM_GRAYED(0, ID_STR_NOTHEMES)), - MENU_SEPARATOR(), - MENU_ITEM(IDM_EDITCONFIG, ID_STR_EDITSETTINGS), - MENU_ITEM(IDM_REFRESH, ID_STR_REFRESHALL), - MENU_SEPARATOR(), - MENU_SUBMENU(ID_STR_LOGGING, - MENU_ITEM(IDM_SHOWLOGFILE, ID_STR_SHOWLOGFILE), - MENU_SEPARATOR(), - MENU_ITEM(IDM_STARTLOG, ID_STR_STARTLOGGING), - MENU_ITEM(IDM_STOPLOG, ID_STR_STOPLOGGING), - MENU_SEPARATOR(), - MENU_ITEM(IDM_DELETELOGFILE, ID_STR_DELETELOGFILE), - MENU_ITEM(IDM_DEBUGLOG, ID_STR_DEBUGMODE)), - MENU_SEPARATOR(), - MENU_ITEM(IDM_QUIT, ID_STR_EXIT) - }; - - if (m_MenuActive || (meterWindow && meterWindow->IsClosing())) return; - - // Show context menu, if no actions were executed - HMENU menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); - if (!menu) return; - - m_MenuActive = true; - Rainmeter& rainmeter = Rainmeter::GetInstance(); - - SetMenuDefaultItem(menu, IDM_MANAGE, MF_BYCOMMAND); - - if (_waccess(GetLogger().GetLogFilePath().c_str(), 0) == -1) - { - EnableMenuItem(menu, IDM_SHOWLOGFILE, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(menu, IDM_DELETELOGFILE, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(menu, IDM_STOPLOG, MF_BYCOMMAND | MF_GRAYED); - } - else - { - EnableMenuItem( - menu, - (GetLogger().IsLogToFile()) ? IDM_STARTLOG : IDM_STOPLOG, - MF_BYCOMMAND | MF_GRAYED); - } - - if (rainmeter.m_Debug) - { - CheckMenuItem(menu, IDM_DEBUGLOG, MF_BYCOMMAND | MF_CHECKED); - } - - HMENU allSkinsMenu = GetSubMenu(menu, 4); - if (allSkinsMenu) - { - if (!rainmeter.m_SkinRegistry.IsEmpty()) - { - DeleteMenu(allSkinsMenu, 0, MF_BYPOSITION); // "No skins available" menuitem - CreateAllSkinsMenu(allSkinsMenu); - } - - if (rainmeter.m_DisableDragging) - { - CheckMenuItem(allSkinsMenu, IDM_DISABLEDRAG, MF_BYCOMMAND | MF_CHECKED); - } - } - - HMENU layoutMenu = GetSubMenu(menu, 5); - if (layoutMenu) - { - if (!rainmeter.m_Layouts.empty()) - { - DeleteMenu(layoutMenu, 0, MF_BYPOSITION); // "No layouts available" menuitem - CreateLayoutMenu(layoutMenu); - } - } - - if (meterWindow) - { - HMENU rainmeterMenu = menu; - menu = CreateSkinMenu(meterWindow, 0, allSkinsMenu); - - InsertMenu(menu, IDM_CLOSESKIN, MF_BYCOMMAND | MF_POPUP, (UINT_PTR)rainmeterMenu, L"Rainmeter"); - InsertMenu(menu, IDM_CLOSESKIN, MF_BYCOMMAND | MF_SEPARATOR, 0, nullptr); - } - else - { - InsertMenu(menu, 12, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); - - // Create a menu for all active skins - int index = 0; - std::map::const_iterator iter = rainmeter.m_MeterWindows.begin(); - for (; iter != rainmeter.m_MeterWindows.end(); ++iter) - { - MeterWindow* mw = ((*iter).second); - HMENU skinMenu = CreateSkinMenu(mw, index, allSkinsMenu); - InsertMenu(menu, 12, MF_BYPOSITION | MF_POPUP, (UINT_PTR)skinMenu, mw->GetFolderPath().c_str()); - ++index; - } - - // Add update notification item - if (rainmeter.m_NewVersion) - { - InsertMenu(menu, 0, MF_BYPOSITION, IDM_NEW_VERSION, GetString(ID_STR_UPDATEAVAILABLE)); - HiliteMenuItem(rainmeter.GetTrayWindow()->GetWindow(), menu, 0, MF_BYPOSITION | MF_HILITE); - InsertMenu(menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); - } - } - - HWND hWnd = WindowFromPoint(pos); - if (hWnd != nullptr) - { - MeterWindow* mw = rainmeter.GetMeterWindow(hWnd); - if (mw) - { - // Cancel the mouse event beforehand - mw->SetMouseLeaveEvent(true); - } - } - - DisplayMenu(pos, menu, meterWindow ? meterWindow->GetWindow() : rainmeter.m_TrayWindow->GetWindow()); - DestroyMenu(menu); - - m_MenuActive = false; -} - -void ContextMenu::ShowSkinCustomMenu(POINT pos, MeterWindow* meterWindow) -{ - if (m_MenuActive || meterWindow->IsClosing()) return; - - m_MenuActive = true; - - HMENU menu = CreatePopupMenu(); - AppendSkinCustomMenu(meterWindow, 0, menu, true); - - DisplayMenu(pos, menu, meterWindow->GetWindow()); - DestroyMenu(menu); - - m_MenuActive = false; -} - -void ContextMenu::DisplayMenu(POINT pos, HMENU menu, HWND parentWindow) -{ - // Set the window to foreground - HWND foregroundWindow = GetForegroundWindow(); - if (foregroundWindow != parentWindow) - { - const DWORD foregroundThreadID = GetWindowThreadProcessId(foregroundWindow, nullptr); - const DWORD currentThreadID = GetCurrentThreadId(); - AttachThreadInput(currentThreadID, foregroundThreadID, TRUE); - SetForegroundWindow(parentWindow); - AttachThreadInput(currentThreadID, foregroundThreadID, FALSE); - } - - // Show context menu - TrackPopupMenu( - menu, - TPM_RIGHTBUTTON | TPM_LEFTALIGN | (*GetString(ID_STR_ISRTL) == L'1' ? TPM_LAYOUTRTL : 0), - pos.x, - pos.y, - 0, - parentWindow, - nullptr); -} - -HMENU ContextMenu::CreateSkinMenu(MeterWindow* meterWindow, int index, HMENU menu) -{ - static const MenuTemplate s_Menu[] = - { - MENU_ITEM(IDM_SKIN_OPENSKINSFOLDER, 0), - MENU_SEPARATOR(), - MENU_SUBMENU(ID_STR_VARIANTS, - MENU_SEPARATOR()), - MENU_SEPARATOR(), - MENU_SUBMENU(ID_STR_SETTINGS, - MENU_SUBMENU(ID_STR_POSITION, - MENU_SUBMENU(ID_STR_DISPLAYMONITOR, - MENU_ITEM(IDM_SKIN_MONITOR_PRIMARY, ID_STR_USEDEFAULTMONITOR), - MENU_ITEM(ID_MONITOR_FIRST, ID_STR_VIRTUALSCREEN), - MENU_SEPARATOR(), - MENU_SEPARATOR(), - MENU_ITEM(IDM_SKIN_MONITOR_AUTOSELECT, ID_STR_AUTOSELECTMONITOR)), - MENU_SEPARATOR(), - MENU_ITEM(IDM_SKIN_VERYTOPMOST, ID_STR_STAYTOPMOST), - MENU_ITEM(IDM_SKIN_TOPMOST, ID_STR_TOPMOST), - MENU_ITEM(IDM_SKIN_NORMAL, ID_STR_NORMAL), - MENU_ITEM(IDM_SKIN_BOTTOM, ID_STR_BOTTOM), - MENU_ITEM(IDM_SKIN_ONDESKTOP, ID_STR_ONDESKTOP), - MENU_SEPARATOR(), - MENU_ITEM(IDM_SKIN_FROMRIGHT, ID_STR_FROMRIGHT), - MENU_ITEM(IDM_SKIN_FROMBOTTOM, ID_STR_FROMBOTTOM), - MENU_ITEM(IDM_SKIN_XPERCENTAGE, ID_STR_XASPERCENTAGE), - MENU_ITEM(IDM_SKIN_YPERCENTAGE, ID_STR_YASPERCENTAGE)), - MENU_SUBMENU(ID_STR_TRANSPARENCY, - MENU_ITEM(IDM_SKIN_TRANSPARENCY_0, ID_STR_0PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_10, ID_STR_10PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_20, ID_STR_20PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_30, ID_STR_30PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_40, ID_STR_40PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_50, ID_STR_50PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_60, ID_STR_60PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_70, ID_STR_70PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_80, ID_STR_80PERCENT), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_90, ID_STR_90PERCENT), - MENU_SEPARATOR(), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_FADEIN, ID_STR_FADEIN), - MENU_ITEM(IDM_SKIN_TRANSPARENCY_FADEOUT, ID_STR_FADEOUT)), - MENU_SEPARATOR(), - MENU_ITEM(IDM_SKIN_HIDEONMOUSE, ID_STR_HIDEONMOUSEOVER), - MENU_ITEM(IDM_SKIN_DRAGGABLE, ID_STR_DRAGGABLE), - MENU_ITEM(IDM_SKIN_REMEMBERPOSITION, ID_STR_SAVEPOSITION), - MENU_ITEM(IDM_SKIN_SNAPTOEDGES, ID_STR_SNAPTOEDGES), - MENU_ITEM(IDM_SKIN_CLICKTHROUGH, ID_STR_CLICKTHROUGH), - MENU_ITEM(IDM_SKIN_KEEPONSCREEN, ID_STR_KEEPONSCREEN), - MENU_ITEM(IDM_SKIN_USED2D, ID_STR_USED2D)), - MENU_SEPARATOR(), - MENU_ITEM(IDM_SKIN_MANAGESKIN, ID_STR_MANAGESKIN), - MENU_ITEM(IDM_SKIN_EDITSKIN, ID_STR_EDITSKIN), - MENU_ITEM(IDM_SKIN_REFRESH, ID_STR_REFRESHSKIN), - MENU_SEPARATOR(), - MENU_ITEM(IDM_CLOSESKIN, ID_STR_UNLOADSKIN) - }; - - HMENU skinMenu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); - if (!skinMenu) return nullptr; - - // Tick the position - HMENU settingsMenu = GetSubMenu(skinMenu, 4); - if (settingsMenu) - { - HMENU posMenu = GetSubMenu(settingsMenu, 0); - if (posMenu) - { - const UINT checkPos = IDM_SKIN_NORMAL - (UINT)meterWindow->GetWindowZPosition(); - CheckMenuRadioItem(posMenu, checkPos, checkPos, checkPos, MF_BYCOMMAND); - - if (meterWindow->GetXFromRight()) CheckMenuItem(posMenu, IDM_SKIN_FROMRIGHT, MF_BYCOMMAND | MF_CHECKED); - if (meterWindow->GetYFromBottom()) CheckMenuItem(posMenu, IDM_SKIN_FROMBOTTOM, MF_BYCOMMAND | MF_CHECKED); - if (meterWindow->GetXPercentage()) CheckMenuItem(posMenu, IDM_SKIN_XPERCENTAGE, MF_BYCOMMAND | MF_CHECKED); - if (meterWindow->GetYPercentage()) CheckMenuItem(posMenu, IDM_SKIN_YPERCENTAGE, MF_BYCOMMAND | MF_CHECKED); - - HMENU monitorMenu = GetSubMenu(posMenu, 0); - if (monitorMenu) - { - CreateMonitorMenu(monitorMenu, meterWindow); - } - } - - // Tick the transparency - HMENU alphaMenu = GetSubMenu(settingsMenu, 1); - if (alphaMenu) - { - UINT checkPos = (UINT)(10 - meterWindow->GetAlphaValue() / 25.5); - checkPos = min(9, checkPos); - checkPos = max(0, checkPos); - CheckMenuRadioItem(alphaMenu, checkPos, checkPos, checkPos, MF_BYPOSITION); - - switch (meterWindow->GetWindowHide()) - { - case HIDEMODE_FADEIN: - CheckMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEIN, MF_BYCOMMAND | MF_CHECKED); - EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEOUT, MF_BYCOMMAND | MF_GRAYED); - break; - - case HIDEMODE_FADEOUT: - CheckMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEOUT, MF_BYCOMMAND | MF_CHECKED); - EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEIN, MF_BYCOMMAND | MF_GRAYED); - break; - - case HIDEMODE_HIDE: - EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEIN, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEOUT, MF_BYCOMMAND | MF_GRAYED); - break; - } - } - - // Tick the settings - switch (meterWindow->GetWindowHide()) - { - case HIDEMODE_HIDE: - CheckMenuItem(settingsMenu, IDM_SKIN_HIDEONMOUSE, MF_BYCOMMAND | MF_CHECKED); - break; - - case HIDEMODE_FADEIN: - case HIDEMODE_FADEOUT: - EnableMenuItem(settingsMenu, IDM_SKIN_HIDEONMOUSE, MF_BYCOMMAND | MF_GRAYED); - break; - } - - if (meterWindow->GetSnapEdges()) - { - CheckMenuItem(settingsMenu, IDM_SKIN_SNAPTOEDGES, MF_BYCOMMAND | MF_CHECKED); - } - - if (meterWindow->GetSavePosition()) - { - CheckMenuItem(settingsMenu, IDM_SKIN_REMEMBERPOSITION, MF_BYCOMMAND | MF_CHECKED); - } - - if (Rainmeter::GetInstance().m_DisableDragging) - { - EnableMenuItem(settingsMenu, IDM_SKIN_DRAGGABLE, MF_BYCOMMAND | MF_GRAYED); - } - else if (meterWindow->GetWindowDraggable()) - { - CheckMenuItem(settingsMenu, IDM_SKIN_DRAGGABLE, MF_BYCOMMAND | MF_CHECKED); - } - - if (meterWindow->GetClickThrough()) - { - CheckMenuItem(settingsMenu, IDM_SKIN_CLICKTHROUGH, MF_BYCOMMAND | MF_CHECKED); - } - - if (meterWindow->GetKeepOnScreen()) - { - CheckMenuItem(settingsMenu, IDM_SKIN_KEEPONSCREEN, MF_BYCOMMAND | MF_CHECKED); - } - - if (Gfx::CanvasD2D::Initialize()) - { - if (!Rainmeter::GetInstance().GetUseD2D()) - { - EnableMenuItem(settingsMenu, IDM_SKIN_USED2D, MF_BYCOMMAND | MF_GRAYED); - } - else if (meterWindow->GetUseD2D()) - { - CheckMenuItem(settingsMenu, IDM_SKIN_USED2D, MF_BYCOMMAND | MF_CHECKED); - } - } - else - { - DeleteMenu(settingsMenu, IDM_SKIN_USED2D, MF_BYCOMMAND); - } - Gfx::CanvasD2D::Finalize(); - } - - // Add the name of the Skin to the menu - const std::wstring& skinName = meterWindow->GetFolderPath(); - ModifyMenu(skinMenu, IDM_SKIN_OPENSKINSFOLDER, MF_BYCOMMAND, IDM_SKIN_OPENSKINSFOLDER, skinName.c_str()); - SetMenuDefaultItem(skinMenu, IDM_SKIN_OPENSKINSFOLDER, FALSE); - - // Remove dummy menuitem from the variants menu - HMENU variantsMenu = GetSubMenu(skinMenu, 2); - if (variantsMenu) - { - DeleteMenu(variantsMenu, 0, MF_BYPOSITION); - } - - // Give the menuitem the unique id that depends on the skin - ChangeSkinIndex(skinMenu, index); - - // Add the variants menu - if (variantsMenu) - { - const SkinRegistry::Folder& skinFolder = *Rainmeter::GetInstance().m_SkinRegistry.FindFolder(skinName); - for (int i = 0, isize = (int)skinFolder.files.size(); i < isize; ++i) - { - InsertMenu(variantsMenu, i, MF_BYPOSITION, skinFolder.baseID + i, skinFolder.files[i].c_str()); - } - - if (skinFolder.active) - { - UINT checkPos = skinFolder.active - 1; - CheckMenuRadioItem(variantsMenu, checkPos, checkPos, checkPos, MF_BYPOSITION); - } - } - - // Add skin root menu - int itemCount = GetMenuItemCount(menu); - if (itemCount > 0) - { - std::wstring root = meterWindow->GetFolderPath(); - std::wstring::size_type pos = root.find_first_of(L'\\'); - if (pos != std::wstring::npos) - { - root.erase(pos); - } - - for (int i = 0; i < itemCount; ++i) - { - const UINT state = GetMenuState(menu, i, MF_BYPOSITION); - if (state == 0xFFFFFFFF || (state & MF_POPUP) == 0) break; - - WCHAR buffer[MAX_PATH]; - if (GetMenuString(menu, i, buffer, MAX_PATH, MF_BYPOSITION)) - { - if (_wcsicmp(root.c_str(), buffer) == 0) - { - HMENU skinRootMenu = GetSubMenu(menu, i); - if (skinRootMenu) - { - InsertMenu(skinMenu, 3, MF_BYPOSITION | MF_POPUP, (UINT_PTR)skinRootMenu, root.c_str()); - } - break; - } - } - } - } - - AppendSkinCustomMenu(meterWindow, index, skinMenu, false); - - return skinMenu; -} - -void ContextMenu::AppendSkinCustomMenu( - MeterWindow* meterWindow, int index, HMENU menu, bool standaloneMenu) -{ - // Add custom actions to the context menu - std::wstring contextTitle = meterWindow->GetParser().ReadString(L"Rainmeter", L"ContextTitle", L""); - if (contextTitle.empty()) - { - return; - } - - auto isTitleSeparator = [](const std::wstring& title) - { - return title.find_first_not_of(L'-') == std::wstring::npos; - }; - - std::wstring contextAction = meterWindow->GetParser().ReadString(L"Rainmeter", L"ContextAction", L""); - if (contextAction.empty() && !isTitleSeparator(contextTitle)) - { - return; - } - - std::vector cTitles; - WCHAR buffer[128]; - int i = 1; - - while (!contextTitle.empty() && - (!contextAction.empty() || isTitleSeparator(contextTitle)) && - (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i - 1) <= IDM_SKIN_CUSTOMCONTEXTMENU_LAST) // Set maximum context items in resource.h - { - // Trim long titles - if (contextTitle.size() > 30) - { - contextTitle.replace(27, contextTitle.size() - 27, L"..."); - } - - cTitles.push_back(contextTitle); - - _snwprintf_s(buffer, _TRUNCATE, L"ContextTitle%i", ++i); - contextTitle = meterWindow->GetParser().ReadString(L"Rainmeter", buffer, L""); - _snwprintf_s(buffer, _TRUNCATE, L"ContextAction%i", i); - contextAction = meterWindow->GetParser().ReadString(L"Rainmeter", buffer, L""); - } - - // Build a sub-menu if more than three items - const size_t titleSize = cTitles.size(); - if (titleSize <= 3 || standaloneMenu) - { - size_t position = 0; - for (size_t i = 0; i < titleSize; ++i) - { - if (isTitleSeparator(cTitles[i])) - { - if (standaloneMenu) - { - AppendMenu(menu, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); - } - else - { - // Separators not allowed in main top-level menu - --position; - } - } - else - { - const UINT_PTR id = (index << 16) | (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i); - InsertMenu(menu, (UINT)(position + 1), MF_BYPOSITION | MF_STRING, id, cTitles[i].c_str()); - } - - ++position; - } - - if (position != 0 && !standaloneMenu) - { - InsertMenu(menu, 1, MF_BYPOSITION | MF_STRING | MF_GRAYED, 0, L"Custom skin actions"); - InsertMenu(menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); - } - } - else - { - HMENU customMenu = CreatePopupMenu(); - InsertMenu(menu, 1, MF_BYPOSITION | MF_POPUP, (UINT_PTR)customMenu, L"Custom skin actions"); - - for (size_t i = 0; i < titleSize; ++i) - { - if (isTitleSeparator(cTitles[i])) - { - AppendMenu(customMenu, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); - } - else - { - const UINT_PTR id = (index << 16) | (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i); - AppendMenu(customMenu, MF_BYPOSITION | MF_STRING, id, cTitles[i].c_str()); - } - } - - InsertMenu(menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); - } -} - -int ContextMenu::CreateAllSkinsMenuRecursive(HMENU skinMenu, int index) -{ - SkinRegistry& skinRegistry = Rainmeter::GetInstance().m_SkinRegistry; - const int initialLevel = skinRegistry.GetFolder(index).level; - int menuIndex = 0; - - const size_t max = skinRegistry.GetFolderCount(); - while (index < max) - { - const SkinRegistry::Folder& skinFolder = skinRegistry.GetFolder(index); - if (skinFolder.level != initialLevel) - { - return index - 1; - } - - HMENU subMenu = CreatePopupMenu(); - - // Add current folder - InsertMenu(skinMenu, menuIndex, MF_POPUP | MF_BYPOSITION, (UINT_PTR)subMenu, skinFolder.name.c_str()); - - // Add subfolders - const bool hasSubfolder = (index + 1) < max && skinRegistry.GetFolder(index + 1).level == initialLevel + 1; - if (hasSubfolder) - { - index = CreateAllSkinsMenuRecursive(subMenu, index + 1); - } - - // Add files - { - int fileIndex = 0; - const int fileCount = (int)skinFolder.files.size(); - for ( ; fileIndex < fileCount; ++fileIndex) - { - InsertMenu(subMenu, fileIndex, MF_STRING | MF_BYPOSITION, skinFolder.baseID + fileIndex, skinFolder.files[fileIndex].c_str()); - } - - if (skinFolder.active) - { - UINT checkPos = skinFolder.active - 1; - CheckMenuRadioItem(subMenu, checkPos, checkPos, checkPos, MF_BYPOSITION); - } - - if (hasSubfolder && fileIndex != 0) - { - InsertMenu(subMenu, fileIndex, MF_SEPARATOR | MF_BYPOSITION, 0, nullptr); - } - } - - ++menuIndex; - ++index; - } - - return index; -} - -void ContextMenu::CreateLayoutMenu(HMENU layoutMenu) -{ - const auto& layouts = Rainmeter::GetInstance().m_Layouts; - for (size_t i = 0, isize = layouts.size(); i < isize; ++i) - { - InsertMenu(layoutMenu, (UINT)i, MF_BYPOSITION, ID_THEME_FIRST + i, layouts[i].c_str()); - } -} - -void ContextMenu::CreateMonitorMenu(HMENU monitorMenu, MeterWindow* meterWindow) -{ - const bool screenDefined = meterWindow->GetXScreenDefined(); - const int screenIndex = meterWindow->GetXScreen(); - - // for the "Specified monitor" (@n) - const size_t numOfMonitors = System::GetMonitorCount(); // intentional - const std::vector& monitors = System::GetMultiMonitorInfo().monitors; - - int i = 1; - for (auto iter = monitors.cbegin(); iter != monitors.cend(); ++iter, ++i) - { - WCHAR buffer[64]; - size_t len = _snwprintf_s(buffer, _TRUNCATE, L"@%i: ", i); - - std::wstring item(buffer, len); - - if ((*iter).monitorName.size() > 32) - { - item.append((*iter).monitorName, 0, 32); - item += L"..."; - } - else - { - item += (*iter).monitorName; - } - - const UINT flags = - MF_BYPOSITION | - ((screenDefined && screenIndex == i) ? MF_CHECKED : MF_UNCHECKED) | - ((*iter).active ? MF_ENABLED : MF_GRAYED); - InsertMenu(monitorMenu, i + 2, flags, ID_MONITOR_FIRST + i, item.c_str()); - } - - if (!screenDefined) - { - CheckMenuItem(monitorMenu, IDM_SKIN_MONITOR_PRIMARY, MF_BYCOMMAND | MF_CHECKED); - } - - if (screenDefined && screenIndex == 0) - { - CheckMenuItem(monitorMenu, ID_MONITOR_FIRST, MF_BYCOMMAND | MF_CHECKED); - } - - if (meterWindow->GetAutoSelectScreen()) - { - CheckMenuItem(monitorMenu, IDM_SKIN_MONITOR_AUTOSELECT, MF_BYCOMMAND | MF_CHECKED); - } -} - -void ContextMenu::ChangeSkinIndex(HMENU menu, int index) -{ - if (index > 0) - { - const int count = GetMenuItemCount(menu); - for (int i = 0; i < count; ++i) - { - HMENU subMenu = GetSubMenu(menu, i); - if (subMenu) - { - ChangeSkinIndex(subMenu, index); - } - else - { - MENUITEMINFO mii = {sizeof(MENUITEMINFO)}; - mii.fMask = MIIM_FTYPE | MIIM_ID; - GetMenuItemInfo(menu, i, TRUE, &mii); - if ((mii.fType & MFT_SEPARATOR) == 0) - { - mii.wID |= (index << 16); - mii.fMask = MIIM_ID; - SetMenuItemInfo(menu, i, TRUE, &mii); - } - } - } - } -} +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../Common/MenuTemplate.h" +#include "../Common/Gfx/CanvasD2D.h" +#include "ContextMenu.h" +#include "Rainmeter.h" +#include "Litestep.h" +#include "MeterWindow.h" +#include "System.h" +#include "TrayWindow.h" +#include "resource.h" + +ContextMenu::ContextMenu() : + m_MenuActive(false) +{ +} + +/* +** Opens the context menu in given coordinates. +*/ +void ContextMenu::ShowMenu(POINT pos, MeterWindow* meterWindow) +{ + static const MenuTemplate s_Menu[] = + { + MENU_ITEM(IDM_MANAGE, ID_STR_MANAGE), + MENU_ITEM(IDM_ABOUT, ID_STR_ABOUT), + MENU_ITEM(IDM_SHOW_HELP, ID_STR_HELP), + MENU_SEPARATOR(), + MENU_SUBMENU(ID_STR_SKINS, + MENU_ITEM_GRAYED(0, ID_STR_NOSKINS), + MENU_SEPARATOR(), + MENU_ITEM(IDM_OPENSKINSFOLDER, ID_STR_OPENFOLDER), + MENU_ITEM(IDM_DISABLEDRAG, ID_STR_DISABLEDRAGGING)), + MENU_SUBMENU(ID_STR_THEMES, + MENU_ITEM_GRAYED(0, ID_STR_NOTHEMES)), + MENU_SEPARATOR(), + MENU_ITEM(IDM_EDITCONFIG, ID_STR_EDITSETTINGS), + MENU_ITEM(IDM_REFRESH, ID_STR_REFRESHALL), + MENU_SEPARATOR(), + MENU_SUBMENU(ID_STR_LOGGING, + MENU_ITEM(IDM_SHOWLOGFILE, ID_STR_SHOWLOGFILE), + MENU_SEPARATOR(), + MENU_ITEM(IDM_STARTLOG, ID_STR_STARTLOGGING), + MENU_ITEM(IDM_STOPLOG, ID_STR_STOPLOGGING), + MENU_SEPARATOR(), + MENU_ITEM(IDM_DELETELOGFILE, ID_STR_DELETELOGFILE), + MENU_ITEM(IDM_DEBUGLOG, ID_STR_DEBUGMODE)), + MENU_SEPARATOR(), + MENU_ITEM(IDM_QUIT, ID_STR_EXIT) + }; + + if (m_MenuActive || (meterWindow && meterWindow->IsClosing())) return; + + // Show context menu, if no actions were executed + HMENU menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); + if (!menu) return; + + m_MenuActive = true; + Rainmeter& rainmeter = Rainmeter::GetInstance(); + + SetMenuDefaultItem(menu, IDM_MANAGE, MF_BYCOMMAND); + + if (_waccess(GetLogger().GetLogFilePath().c_str(), 0) == -1) + { + EnableMenuItem(menu, IDM_SHOWLOGFILE, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menu, IDM_DELETELOGFILE, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(menu, IDM_STOPLOG, MF_BYCOMMAND | MF_GRAYED); + } + else + { + EnableMenuItem( + menu, + (GetLogger().IsLogToFile()) ? IDM_STARTLOG : IDM_STOPLOG, + MF_BYCOMMAND | MF_GRAYED); + } + + if (rainmeter.m_Debug) + { + CheckMenuItem(menu, IDM_DEBUGLOG, MF_BYCOMMAND | MF_CHECKED); + } + + HMENU allSkinsMenu = GetSubMenu(menu, 4); + if (allSkinsMenu) + { + if (!rainmeter.m_SkinRegistry.IsEmpty()) + { + DeleteMenu(allSkinsMenu, 0, MF_BYPOSITION); // "No skins available" menuitem + CreateAllSkinsMenu(allSkinsMenu); + } + + if (rainmeter.m_DisableDragging) + { + CheckMenuItem(allSkinsMenu, IDM_DISABLEDRAG, MF_BYCOMMAND | MF_CHECKED); + } + } + + HMENU layoutMenu = GetSubMenu(menu, 5); + if (layoutMenu) + { + if (!rainmeter.m_Layouts.empty()) + { + DeleteMenu(layoutMenu, 0, MF_BYPOSITION); // "No layouts available" menuitem + CreateLayoutMenu(layoutMenu); + } + } + + if (meterWindow) + { + HMENU rainmeterMenu = menu; + menu = CreateSkinMenu(meterWindow, 0, allSkinsMenu); + + InsertMenu(menu, IDM_CLOSESKIN, MF_BYCOMMAND | MF_POPUP, (UINT_PTR)rainmeterMenu, L"Rainmeter"); + InsertMenu(menu, IDM_CLOSESKIN, MF_BYCOMMAND | MF_SEPARATOR, 0, nullptr); + } + else + { + InsertMenu(menu, 12, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); + + // Create a menu for all active skins + int index = 0; + std::map::const_iterator iter = rainmeter.m_MeterWindows.begin(); + for (; iter != rainmeter.m_MeterWindows.end(); ++iter) + { + MeterWindow* mw = ((*iter).second); + HMENU skinMenu = CreateSkinMenu(mw, index, allSkinsMenu); + InsertMenu(menu, 12, MF_BYPOSITION | MF_POPUP, (UINT_PTR)skinMenu, mw->GetFolderPath().c_str()); + ++index; + } + + // Add update notification item + if (rainmeter.m_NewVersion) + { + InsertMenu(menu, 0, MF_BYPOSITION, IDM_NEW_VERSION, GetString(ID_STR_UPDATEAVAILABLE)); + HiliteMenuItem(rainmeter.GetTrayWindow()->GetWindow(), menu, 0, MF_BYPOSITION | MF_HILITE); + InsertMenu(menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); + } + } + + HWND hWnd = WindowFromPoint(pos); + if (hWnd != nullptr) + { + MeterWindow* mw = rainmeter.GetMeterWindow(hWnd); + if (mw) + { + // Cancel the mouse event beforehand + mw->SetMouseLeaveEvent(true); + } + } + + DisplayMenu(pos, menu, meterWindow ? meterWindow->GetWindow() : rainmeter.m_TrayWindow->GetWindow()); + DestroyMenu(menu); + + m_MenuActive = false; +} + +void ContextMenu::ShowSkinCustomMenu(POINT pos, MeterWindow* meterWindow) +{ + if (m_MenuActive || meterWindow->IsClosing()) return; + + m_MenuActive = true; + + HMENU menu = CreatePopupMenu(); + AppendSkinCustomMenu(meterWindow, 0, menu, true); + + DisplayMenu(pos, menu, meterWindow->GetWindow()); + DestroyMenu(menu); + + m_MenuActive = false; +} + +void ContextMenu::DisplayMenu(POINT pos, HMENU menu, HWND parentWindow) +{ + // Set the window to foreground + HWND foregroundWindow = GetForegroundWindow(); + if (foregroundWindow != parentWindow) + { + const DWORD foregroundThreadID = GetWindowThreadProcessId(foregroundWindow, nullptr); + const DWORD currentThreadID = GetCurrentThreadId(); + AttachThreadInput(currentThreadID, foregroundThreadID, TRUE); + SetForegroundWindow(parentWindow); + AttachThreadInput(currentThreadID, foregroundThreadID, FALSE); + } + + // Show context menu + TrackPopupMenu( + menu, + TPM_RIGHTBUTTON | TPM_LEFTALIGN | (*GetString(ID_STR_ISRTL) == L'1' ? TPM_LAYOUTRTL : 0), + pos.x, + pos.y, + 0, + parentWindow, + nullptr); +} + +HMENU ContextMenu::CreateSkinMenu(MeterWindow* meterWindow, int index, HMENU menu) +{ + static const MenuTemplate s_Menu[] = + { + MENU_ITEM(IDM_SKIN_OPENSKINSFOLDER, 0), + MENU_SEPARATOR(), + MENU_SUBMENU(ID_STR_VARIANTS, + MENU_SEPARATOR()), + MENU_SEPARATOR(), + MENU_SUBMENU(ID_STR_SETTINGS, + MENU_SUBMENU(ID_STR_POSITION, + MENU_SUBMENU(ID_STR_DISPLAYMONITOR, + MENU_ITEM(IDM_SKIN_MONITOR_PRIMARY, ID_STR_USEDEFAULTMONITOR), + MENU_ITEM(ID_MONITOR_FIRST, ID_STR_VIRTUALSCREEN), + MENU_SEPARATOR(), + MENU_SEPARATOR(), + MENU_ITEM(IDM_SKIN_MONITOR_AUTOSELECT, ID_STR_AUTOSELECTMONITOR)), + MENU_SEPARATOR(), + MENU_ITEM(IDM_SKIN_VERYTOPMOST, ID_STR_STAYTOPMOST), + MENU_ITEM(IDM_SKIN_TOPMOST, ID_STR_TOPMOST), + MENU_ITEM(IDM_SKIN_NORMAL, ID_STR_NORMAL), + MENU_ITEM(IDM_SKIN_BOTTOM, ID_STR_BOTTOM), + MENU_ITEM(IDM_SKIN_ONDESKTOP, ID_STR_ONDESKTOP), + MENU_SEPARATOR(), + MENU_ITEM(IDM_SKIN_FROMRIGHT, ID_STR_FROMRIGHT), + MENU_ITEM(IDM_SKIN_FROMBOTTOM, ID_STR_FROMBOTTOM), + MENU_ITEM(IDM_SKIN_XPERCENTAGE, ID_STR_XASPERCENTAGE), + MENU_ITEM(IDM_SKIN_YPERCENTAGE, ID_STR_YASPERCENTAGE)), + MENU_SUBMENU(ID_STR_TRANSPARENCY, + MENU_ITEM(IDM_SKIN_TRANSPARENCY_0, ID_STR_0PERCENT), + MENU_ITEM(IDM_SKIN_TRANSPARENCY_10, ID_STR_10PERCENT), + MENU_ITEM(IDM_SKIN_TRANSPARENCY_20, ID_STR_20PERCENT), + MENU_ITEM(IDM_SKIN_TRANSPARENCY_30, ID_STR_30PERCENT), + MENU_ITEM(IDM_SKIN_TRANSPARENCY_40, ID_STR_40PERCENT), + MENU_ITEM(IDM_SKIN_TRANSPARENCY_50, ID_STR_50PERCENT), + MENU_ITEM(IDM_SKIN_TRANSPARENCY_60, ID_STR_60PERCENT), + MENU_ITEM(IDM_SKIN_TRANSPARENCY_70, ID_STR_70PERCENT), + MENU_ITEM(IDM_SKIN_TRANSPARENCY_80, ID_STR_80PERCENT), + MENU_ITEM(IDM_SKIN_TRANSPARENCY_90, ID_STR_90PERCENT), + MENU_SEPARATOR(), + MENU_ITEM(IDM_SKIN_TRANSPARENCY_FADEIN, ID_STR_FADEIN), + MENU_ITEM(IDM_SKIN_TRANSPARENCY_FADEOUT, ID_STR_FADEOUT)), + MENU_SEPARATOR(), + MENU_ITEM(IDM_SKIN_HIDEONMOUSE, ID_STR_HIDEONMOUSEOVER), + MENU_ITEM(IDM_SKIN_DRAGGABLE, ID_STR_DRAGGABLE), + MENU_ITEM(IDM_SKIN_REMEMBERPOSITION, ID_STR_SAVEPOSITION), + MENU_ITEM(IDM_SKIN_SNAPTOEDGES, ID_STR_SNAPTOEDGES), + MENU_ITEM(IDM_SKIN_CLICKTHROUGH, ID_STR_CLICKTHROUGH), + MENU_ITEM(IDM_SKIN_KEEPONSCREEN, ID_STR_KEEPONSCREEN), + MENU_ITEM(IDM_SKIN_USED2D, ID_STR_USED2D)), + MENU_SEPARATOR(), + MENU_ITEM(IDM_SKIN_MANAGESKIN, ID_STR_MANAGESKIN), + MENU_ITEM(IDM_SKIN_EDITSKIN, ID_STR_EDITSKIN), + MENU_ITEM(IDM_SKIN_REFRESH, ID_STR_REFRESHSKIN), + MENU_SEPARATOR(), + MENU_ITEM(IDM_CLOSESKIN, ID_STR_UNLOADSKIN) + }; + + HMENU skinMenu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); + if (!skinMenu) return nullptr; + + // Tick the position + HMENU settingsMenu = GetSubMenu(skinMenu, 4); + if (settingsMenu) + { + HMENU posMenu = GetSubMenu(settingsMenu, 0); + if (posMenu) + { + const UINT checkPos = IDM_SKIN_NORMAL - (UINT)meterWindow->GetWindowZPosition(); + CheckMenuRadioItem(posMenu, checkPos, checkPos, checkPos, MF_BYCOMMAND); + + if (meterWindow->GetXFromRight()) CheckMenuItem(posMenu, IDM_SKIN_FROMRIGHT, MF_BYCOMMAND | MF_CHECKED); + if (meterWindow->GetYFromBottom()) CheckMenuItem(posMenu, IDM_SKIN_FROMBOTTOM, MF_BYCOMMAND | MF_CHECKED); + if (meterWindow->GetXPercentage()) CheckMenuItem(posMenu, IDM_SKIN_XPERCENTAGE, MF_BYCOMMAND | MF_CHECKED); + if (meterWindow->GetYPercentage()) CheckMenuItem(posMenu, IDM_SKIN_YPERCENTAGE, MF_BYCOMMAND | MF_CHECKED); + + HMENU monitorMenu = GetSubMenu(posMenu, 0); + if (monitorMenu) + { + CreateMonitorMenu(monitorMenu, meterWindow); + } + } + + // Tick the transparency + HMENU alphaMenu = GetSubMenu(settingsMenu, 1); + if (alphaMenu) + { + UINT checkPos = (UINT)(10 - meterWindow->GetAlphaValue() / 25.5); + checkPos = min(9, checkPos); + checkPos = max(0, checkPos); + CheckMenuRadioItem(alphaMenu, checkPos, checkPos, checkPos, MF_BYPOSITION); + + switch (meterWindow->GetWindowHide()) + { + case HIDEMODE_FADEIN: + CheckMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEIN, MF_BYCOMMAND | MF_CHECKED); + EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEOUT, MF_BYCOMMAND | MF_GRAYED); + break; + + case HIDEMODE_FADEOUT: + CheckMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEOUT, MF_BYCOMMAND | MF_CHECKED); + EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEIN, MF_BYCOMMAND | MF_GRAYED); + break; + + case HIDEMODE_HIDE: + EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEIN, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(alphaMenu, IDM_SKIN_TRANSPARENCY_FADEOUT, MF_BYCOMMAND | MF_GRAYED); + break; + } + } + + // Tick the settings + switch (meterWindow->GetWindowHide()) + { + case HIDEMODE_HIDE: + CheckMenuItem(settingsMenu, IDM_SKIN_HIDEONMOUSE, MF_BYCOMMAND | MF_CHECKED); + break; + + case HIDEMODE_FADEIN: + case HIDEMODE_FADEOUT: + EnableMenuItem(settingsMenu, IDM_SKIN_HIDEONMOUSE, MF_BYCOMMAND | MF_GRAYED); + break; + } + + if (meterWindow->GetSnapEdges()) + { + CheckMenuItem(settingsMenu, IDM_SKIN_SNAPTOEDGES, MF_BYCOMMAND | MF_CHECKED); + } + + if (meterWindow->GetSavePosition()) + { + CheckMenuItem(settingsMenu, IDM_SKIN_REMEMBERPOSITION, MF_BYCOMMAND | MF_CHECKED); + } + + if (Rainmeter::GetInstance().m_DisableDragging) + { + EnableMenuItem(settingsMenu, IDM_SKIN_DRAGGABLE, MF_BYCOMMAND | MF_GRAYED); + } + else if (meterWindow->GetWindowDraggable()) + { + CheckMenuItem(settingsMenu, IDM_SKIN_DRAGGABLE, MF_BYCOMMAND | MF_CHECKED); + } + + if (meterWindow->GetClickThrough()) + { + CheckMenuItem(settingsMenu, IDM_SKIN_CLICKTHROUGH, MF_BYCOMMAND | MF_CHECKED); + } + + if (meterWindow->GetKeepOnScreen()) + { + CheckMenuItem(settingsMenu, IDM_SKIN_KEEPONSCREEN, MF_BYCOMMAND | MF_CHECKED); + } + + if (Gfx::CanvasD2D::Initialize()) + { + if (!Rainmeter::GetInstance().GetUseD2D()) + { + EnableMenuItem(settingsMenu, IDM_SKIN_USED2D, MF_BYCOMMAND | MF_GRAYED); + } + else if (meterWindow->GetUseD2D()) + { + CheckMenuItem(settingsMenu, IDM_SKIN_USED2D, MF_BYCOMMAND | MF_CHECKED); + } + } + else + { + DeleteMenu(settingsMenu, IDM_SKIN_USED2D, MF_BYCOMMAND); + } + Gfx::CanvasD2D::Finalize(); + } + + // Add the name of the Skin to the menu + const std::wstring& skinName = meterWindow->GetFolderPath(); + ModifyMenu(skinMenu, IDM_SKIN_OPENSKINSFOLDER, MF_BYCOMMAND, IDM_SKIN_OPENSKINSFOLDER, skinName.c_str()); + SetMenuDefaultItem(skinMenu, IDM_SKIN_OPENSKINSFOLDER, FALSE); + + // Remove dummy menuitem from the variants menu + HMENU variantsMenu = GetSubMenu(skinMenu, 2); + if (variantsMenu) + { + DeleteMenu(variantsMenu, 0, MF_BYPOSITION); + } + + // Give the menuitem the unique id that depends on the skin + ChangeSkinIndex(skinMenu, index); + + // Add the variants menu + if (variantsMenu) + { + const SkinRegistry::Folder& skinFolder = *Rainmeter::GetInstance().m_SkinRegistry.FindFolder(skinName); + for (int i = 0, isize = (int)skinFolder.files.size(); i < isize; ++i) + { + InsertMenu(variantsMenu, i, MF_BYPOSITION, skinFolder.baseID + i, skinFolder.files[i].c_str()); + } + + if (skinFolder.active) + { + UINT checkPos = skinFolder.active - 1; + CheckMenuRadioItem(variantsMenu, checkPos, checkPos, checkPos, MF_BYPOSITION); + } + } + + // Add skin root menu + int itemCount = GetMenuItemCount(menu); + if (itemCount > 0) + { + std::wstring root = meterWindow->GetFolderPath(); + std::wstring::size_type pos = root.find_first_of(L'\\'); + if (pos != std::wstring::npos) + { + root.erase(pos); + } + + for (int i = 0; i < itemCount; ++i) + { + const UINT state = GetMenuState(menu, i, MF_BYPOSITION); + if (state == 0xFFFFFFFF || (state & MF_POPUP) == 0) break; + + WCHAR buffer[MAX_PATH]; + if (GetMenuString(menu, i, buffer, MAX_PATH, MF_BYPOSITION)) + { + if (_wcsicmp(root.c_str(), buffer) == 0) + { + HMENU skinRootMenu = GetSubMenu(menu, i); + if (skinRootMenu) + { + InsertMenu(skinMenu, 3, MF_BYPOSITION | MF_POPUP, (UINT_PTR)skinRootMenu, root.c_str()); + } + break; + } + } + } + } + + AppendSkinCustomMenu(meterWindow, index, skinMenu, false); + + return skinMenu; +} + +void ContextMenu::AppendSkinCustomMenu( + MeterWindow* meterWindow, int index, HMENU menu, bool standaloneMenu) +{ + // Add custom actions to the context menu + std::wstring contextTitle = meterWindow->GetParser().ReadString(L"Rainmeter", L"ContextTitle", L""); + if (contextTitle.empty()) + { + return; + } + + auto isTitleSeparator = [](const std::wstring& title) + { + return title.find_first_not_of(L'-') == std::wstring::npos; + }; + + std::wstring contextAction = meterWindow->GetParser().ReadString(L"Rainmeter", L"ContextAction", L""); + if (contextAction.empty() && !isTitleSeparator(contextTitle)) + { + return; + } + + std::vector cTitles; + WCHAR buffer[128]; + int i = 1; + + while (!contextTitle.empty() && + (!contextAction.empty() || isTitleSeparator(contextTitle)) && + (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i - 1) <= IDM_SKIN_CUSTOMCONTEXTMENU_LAST) // Set maximum context items in resource.h + { + // Trim long titles + if (contextTitle.size() > 30) + { + contextTitle.replace(27, contextTitle.size() - 27, L"..."); + } + + cTitles.push_back(contextTitle); + + _snwprintf_s(buffer, _TRUNCATE, L"ContextTitle%i", ++i); + contextTitle = meterWindow->GetParser().ReadString(L"Rainmeter", buffer, L""); + _snwprintf_s(buffer, _TRUNCATE, L"ContextAction%i", i); + contextAction = meterWindow->GetParser().ReadString(L"Rainmeter", buffer, L""); + } + + // Build a sub-menu if more than three items + const size_t titleSize = cTitles.size(); + if (titleSize <= 3 || standaloneMenu) + { + size_t position = 0; + for (size_t i = 0; i < titleSize; ++i) + { + if (isTitleSeparator(cTitles[i])) + { + if (standaloneMenu) + { + AppendMenu(menu, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); + } + else + { + // Separators not allowed in main top-level menu + --position; + } + } + else + { + const UINT_PTR id = (index << 16) | (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i); + InsertMenu(menu, (UINT)(position + 1), MF_BYPOSITION | MF_STRING, id, cTitles[i].c_str()); + } + + ++position; + } + + if (position != 0 && !standaloneMenu) + { + InsertMenu(menu, 1, MF_BYPOSITION | MF_STRING | MF_GRAYED, 0, L"Custom skin actions"); + InsertMenu(menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); + } + } + else + { + HMENU customMenu = CreatePopupMenu(); + InsertMenu(menu, 1, MF_BYPOSITION | MF_POPUP, (UINT_PTR)customMenu, L"Custom skin actions"); + + for (size_t i = 0; i < titleSize; ++i) + { + if (isTitleSeparator(cTitles[i])) + { + AppendMenu(customMenu, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); + } + else + { + const UINT_PTR id = (index << 16) | (IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + i); + AppendMenu(customMenu, MF_BYPOSITION | MF_STRING, id, cTitles[i].c_str()); + } + } + + InsertMenu(menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); + } +} + +int ContextMenu::CreateAllSkinsMenuRecursive(HMENU skinMenu, int index) +{ + SkinRegistry& skinRegistry = Rainmeter::GetInstance().m_SkinRegistry; + const int initialLevel = skinRegistry.GetFolder(index).level; + int menuIndex = 0; + + const size_t max = skinRegistry.GetFolderCount(); + while (index < max) + { + const SkinRegistry::Folder& skinFolder = skinRegistry.GetFolder(index); + if (skinFolder.level != initialLevel) + { + return index - 1; + } + + HMENU subMenu = CreatePopupMenu(); + + // Add current folder + InsertMenu(skinMenu, menuIndex, MF_POPUP | MF_BYPOSITION, (UINT_PTR)subMenu, skinFolder.name.c_str()); + + // Add subfolders + const bool hasSubfolder = (index + 1) < max && skinRegistry.GetFolder(index + 1).level == initialLevel + 1; + if (hasSubfolder) + { + index = CreateAllSkinsMenuRecursive(subMenu, index + 1); + } + + // Add files + { + int fileIndex = 0; + const int fileCount = (int)skinFolder.files.size(); + for ( ; fileIndex < fileCount; ++fileIndex) + { + InsertMenu(subMenu, fileIndex, MF_STRING | MF_BYPOSITION, skinFolder.baseID + fileIndex, skinFolder.files[fileIndex].c_str()); + } + + if (skinFolder.active) + { + UINT checkPos = skinFolder.active - 1; + CheckMenuRadioItem(subMenu, checkPos, checkPos, checkPos, MF_BYPOSITION); + } + + if (hasSubfolder && fileIndex != 0) + { + InsertMenu(subMenu, fileIndex, MF_SEPARATOR | MF_BYPOSITION, 0, nullptr); + } + } + + ++menuIndex; + ++index; + } + + return index; +} + +void ContextMenu::CreateLayoutMenu(HMENU layoutMenu) +{ + const auto& layouts = Rainmeter::GetInstance().m_Layouts; + for (size_t i = 0, isize = layouts.size(); i < isize; ++i) + { + InsertMenu(layoutMenu, (UINT)i, MF_BYPOSITION, ID_THEME_FIRST + i, layouts[i].c_str()); + } +} + +void ContextMenu::CreateMonitorMenu(HMENU monitorMenu, MeterWindow* meterWindow) +{ + const bool screenDefined = meterWindow->GetXScreenDefined(); + const int screenIndex = meterWindow->GetXScreen(); + + // for the "Specified monitor" (@n) + const size_t numOfMonitors = System::GetMonitorCount(); // intentional + const std::vector& monitors = System::GetMultiMonitorInfo().monitors; + + int i = 1; + for (auto iter = monitors.cbegin(); iter != monitors.cend(); ++iter, ++i) + { + WCHAR buffer[64]; + size_t len = _snwprintf_s(buffer, _TRUNCATE, L"@%i: ", i); + + std::wstring item(buffer, len); + + if ((*iter).monitorName.size() > 32) + { + item.append((*iter).monitorName, 0, 32); + item += L"..."; + } + else + { + item += (*iter).monitorName; + } + + const UINT flags = + MF_BYPOSITION | + ((screenDefined && screenIndex == i) ? MF_CHECKED : MF_UNCHECKED) | + ((*iter).active ? MF_ENABLED : MF_GRAYED); + InsertMenu(monitorMenu, i + 2, flags, ID_MONITOR_FIRST + i, item.c_str()); + } + + if (!screenDefined) + { + CheckMenuItem(monitorMenu, IDM_SKIN_MONITOR_PRIMARY, MF_BYCOMMAND | MF_CHECKED); + } + + if (screenDefined && screenIndex == 0) + { + CheckMenuItem(monitorMenu, ID_MONITOR_FIRST, MF_BYCOMMAND | MF_CHECKED); + } + + if (meterWindow->GetAutoSelectScreen()) + { + CheckMenuItem(monitorMenu, IDM_SKIN_MONITOR_AUTOSELECT, MF_BYCOMMAND | MF_CHECKED); + } +} + +void ContextMenu::ChangeSkinIndex(HMENU menu, int index) +{ + if (index > 0) + { + const int count = GetMenuItemCount(menu); + for (int i = 0; i < count; ++i) + { + HMENU subMenu = GetSubMenu(menu, i); + if (subMenu) + { + ChangeSkinIndex(subMenu, index); + } + else + { + MENUITEMINFO mii = {sizeof(MENUITEMINFO)}; + mii.fMask = MIIM_FTYPE | MIIM_ID; + GetMenuItemInfo(menu, i, TRUE, &mii); + if ((mii.fType & MFT_SEPARATOR) == 0) + { + mii.wID |= (index << 16); + mii.fMask = MIIM_ID; + SetMenuItemInfo(menu, i, TRUE, &mii); + } + } + } + } +} diff --git a/Library/ContextMenu.h b/Library/ContextMenu.h index 79e1986d..cc6f759d 100644 --- a/Library/ContextMenu.h +++ b/Library/ContextMenu.h @@ -1,58 +1,58 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_LIBRARY_CONTEXTMENU_H -#define RM_LIBRARY_CONTEXTMENU_H - -#include - -class MeterWindow; - -// Handles the creation and display of Rainmeter and skin context menus. -class ContextMenu -{ -public: - ContextMenu(); - - ContextMenu(const ContextMenu& other) = delete; - ContextMenu& operator=(ContextMenu other) = delete; - - bool IsMenuActive() { return m_MenuActive; } - - void ShowMenu(POINT pos, MeterWindow* meterWindow); - void ShowSkinCustomMenu(POINT pos, MeterWindow* meterWindow); - - static void CreateMonitorMenu(HMENU monitorMenu, MeterWindow* meterWindow); - -private: - static void DisplayMenu(POINT pos, HMENU menu, HWND parentWindow); - - static HMENU CreateSkinMenu(MeterWindow* meterWindow, int index, HMENU menu); - static void AppendSkinCustomMenu( - MeterWindow* meterWindow, int index, HMENU menu, bool standaloneMenu); - static void ChangeSkinIndex(HMENU subMenu, int index); - - static void CreateAllSkinsMenu(HMENU skinMenu) { CreateAllSkinsMenuRecursive(skinMenu, 0); } - static int CreateAllSkinsMenuRecursive(HMENU skinMenu, int index); - - static void CreateLayoutMenu(HMENU layoutMenu); - - bool m_MenuActive; -}; - -#endif +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_LIBRARY_CONTEXTMENU_H +#define RM_LIBRARY_CONTEXTMENU_H + +#include + +class MeterWindow; + +// Handles the creation and display of Rainmeter and skin context menus. +class ContextMenu +{ +public: + ContextMenu(); + + ContextMenu(const ContextMenu& other) = delete; + ContextMenu& operator=(ContextMenu other) = delete; + + bool IsMenuActive() { return m_MenuActive; } + + void ShowMenu(POINT pos, MeterWindow* meterWindow); + void ShowSkinCustomMenu(POINT pos, MeterWindow* meterWindow); + + static void CreateMonitorMenu(HMENU monitorMenu, MeterWindow* meterWindow); + +private: + static void DisplayMenu(POINT pos, HMENU menu, HWND parentWindow); + + static HMENU CreateSkinMenu(MeterWindow* meterWindow, int index, HMENU menu); + static void AppendSkinCustomMenu( + MeterWindow* meterWindow, int index, HMENU menu, bool standaloneMenu); + static void ChangeSkinIndex(HMENU subMenu, int index); + + static void CreateAllSkinsMenu(HMENU skinMenu) { CreateAllSkinsMenuRecursive(skinMenu, 0); } + static int CreateAllSkinsMenuRecursive(HMENU skinMenu, int index); + + static void CreateLayoutMenu(HMENU layoutMenu); + + bool m_MenuActive; +}; + +#endif diff --git a/Library/Dialog.cpp b/Library/Dialog.cpp index 269ace12..138d530a 100644 --- a/Library/Dialog.cpp +++ b/Library/Dialog.cpp @@ -1,173 +1,173 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Dialog.h" - -HWND Dialog::c_ActiveDialogWindow = nullptr; -HWND Dialog::c_ActiveTabWindow = nullptr; - -/* -** Constructor. -** -*/ -Dialog::Dialog(HWND wnd) : - m_Window(wnd), - m_Font(), - m_FontBold() -{ - NONCLIENTMETRICS ncm; - ncm.cbSize = sizeof(NONCLIENTMETRICS) - sizeof(ncm.iPaddedBorderWidth); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0); - m_Font = CreateFontIndirect(&ncm.lfMenuFont); - ncm.lfMenuFont.lfWeight = FW_BOLD; - ncm.lfMenuFont.lfHeight -= 2; - m_FontBold = CreateFontIndirect(&ncm.lfMenuFont); -} - -/* -** Destructor. -** -*/ -Dialog::~Dialog() -{ - DeleteObject(m_Font); - DeleteObject(m_FontBold); -} - -INT_PTR Dialog::OnActivate(WPARAM wParam, LPARAM lParam) -{ - if (wParam) - { - c_ActiveDialogWindow = m_Window; - c_ActiveTabWindow = GetActiveWindow(); - } - else - { - c_ActiveDialogWindow = c_ActiveTabWindow = nullptr; - } - - return FALSE; -} - -/* -** Sets dialog font to UI font. -** -*/ -void Dialog::SetDialogFont(HWND window) -{ - EnumChildWindows(window, SetFontProc, (WPARAM)m_Font); -} - -BOOL CALLBACK Dialog::SetFontProc(HWND hWnd, LPARAM lParam) -{ - SendMessage(hWnd, WM_SETFONT, (WPARAM)lParam, 0); - return TRUE; -} - -/* -** Subclass button control to draw arrow on the right. -** -*/ -void Dialog::SetMenuButton(HWND button) -{ - SetWindowSubclass(button, MenuButtonProc, 0, 0); -} - -LRESULT CALLBACK Dialog::MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) -{ - LRESULT result = DefSubclassProc(hWnd, uMsg, wParam, lParam); - - switch (uMsg) - { - case WM_PAINT: - { - // Draw arrow on top of the button - RECT buttonRect; - GetClientRect(hWnd, &buttonRect); - int arrowX = buttonRect.right - 18; - int arrowY = buttonRect.top + 4; - RECT arrowRect = { arrowX, arrowY, arrowX + 14, arrowY + 14 }; - - HDC dc = GetDC(hWnd); - const WORD DFCS_MENUARROWDOWN = 0x0010; // Undocumented - DWORD drawFlags = DFCS_TRANSPARENT | DFCS_MENUARROWDOWN | (IsWindowEnabled(hWnd) ? 0 : DFCS_INACTIVE); - DrawFrameControl(dc, &arrowRect, DFC_MENU, drawFlags); - ReleaseDC(hWnd, dc); - } - break; - - case WM_GETTEXT: - { - // Append 3 spaces to the button text to move text to the left so - // that it looks better with BS_CENTER. - WCHAR* str = (WCHAR*)lParam + result; - str[0] = str[1] = str[2] = L' '; - str[3] = '\0'; - result += 3; - } - break; - - case WM_GETTEXTLENGTH: - result += 3; - break; - - case WM_NCDESTROY: - RemoveWindowSubclass(hWnd, MenuButtonProc, uIdSubclass); - break; - } - - return result; -} - -/* -** Constructor. -** -*/ -Dialog::Tab::Tab(HINSTANCE instance, HWND owner, WORD tabId, DLGPROC tabProc) : - m_Window(CreateDialog(instance, MAKEINTRESOURCE(tabId), owner, tabProc)), - m_Initialized(false) -{ - EnableThemeDialogTexture(m_Window, ETDT_ENABLETAB); -} - -/* -** Destructor. -** -*/ -Dialog::Tab::~Tab() -{ - DestroyWindow(m_Window); -} - -/* -** Activates the tab. -** -*/ -void Dialog::Tab::Activate() -{ - c_ActiveTabWindow = m_Window; - - if (!m_Initialized) - { - Initialize(); - } - - EnableWindow(m_Window, TRUE); - BringWindowToTop(m_Window); -} +/* + Copyright (C) 2011 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Dialog.h" + +HWND Dialog::c_ActiveDialogWindow = nullptr; +HWND Dialog::c_ActiveTabWindow = nullptr; + +/* +** Constructor. +** +*/ +Dialog::Dialog(HWND wnd) : + m_Window(wnd), + m_Font(), + m_FontBold() +{ + NONCLIENTMETRICS ncm; + ncm.cbSize = sizeof(NONCLIENTMETRICS) - sizeof(ncm.iPaddedBorderWidth); + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0); + m_Font = CreateFontIndirect(&ncm.lfMenuFont); + ncm.lfMenuFont.lfWeight = FW_BOLD; + ncm.lfMenuFont.lfHeight -= 2; + m_FontBold = CreateFontIndirect(&ncm.lfMenuFont); +} + +/* +** Destructor. +** +*/ +Dialog::~Dialog() +{ + DeleteObject(m_Font); + DeleteObject(m_FontBold); +} + +INT_PTR Dialog::OnActivate(WPARAM wParam, LPARAM lParam) +{ + if (wParam) + { + c_ActiveDialogWindow = m_Window; + c_ActiveTabWindow = GetActiveWindow(); + } + else + { + c_ActiveDialogWindow = c_ActiveTabWindow = nullptr; + } + + return FALSE; +} + +/* +** Sets dialog font to UI font. +** +*/ +void Dialog::SetDialogFont(HWND window) +{ + EnumChildWindows(window, SetFontProc, (WPARAM)m_Font); +} + +BOOL CALLBACK Dialog::SetFontProc(HWND hWnd, LPARAM lParam) +{ + SendMessage(hWnd, WM_SETFONT, (WPARAM)lParam, 0); + return TRUE; +} + +/* +** Subclass button control to draw arrow on the right. +** +*/ +void Dialog::SetMenuButton(HWND button) +{ + SetWindowSubclass(button, MenuButtonProc, 0, 0); +} + +LRESULT CALLBACK Dialog::MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) +{ + LRESULT result = DefSubclassProc(hWnd, uMsg, wParam, lParam); + + switch (uMsg) + { + case WM_PAINT: + { + // Draw arrow on top of the button + RECT buttonRect; + GetClientRect(hWnd, &buttonRect); + int arrowX = buttonRect.right - 18; + int arrowY = buttonRect.top + 4; + RECT arrowRect = { arrowX, arrowY, arrowX + 14, arrowY + 14 }; + + HDC dc = GetDC(hWnd); + const WORD DFCS_MENUARROWDOWN = 0x0010; // Undocumented + DWORD drawFlags = DFCS_TRANSPARENT | DFCS_MENUARROWDOWN | (IsWindowEnabled(hWnd) ? 0 : DFCS_INACTIVE); + DrawFrameControl(dc, &arrowRect, DFC_MENU, drawFlags); + ReleaseDC(hWnd, dc); + } + break; + + case WM_GETTEXT: + { + // Append 3 spaces to the button text to move text to the left so + // that it looks better with BS_CENTER. + WCHAR* str = (WCHAR*)lParam + result; + str[0] = str[1] = str[2] = L' '; + str[3] = '\0'; + result += 3; + } + break; + + case WM_GETTEXTLENGTH: + result += 3; + break; + + case WM_NCDESTROY: + RemoveWindowSubclass(hWnd, MenuButtonProc, uIdSubclass); + break; + } + + return result; +} + +/* +** Constructor. +** +*/ +Dialog::Tab::Tab(HINSTANCE instance, HWND owner, WORD tabId, DLGPROC tabProc) : + m_Window(CreateDialog(instance, MAKEINTRESOURCE(tabId), owner, tabProc)), + m_Initialized(false) +{ + EnableThemeDialogTexture(m_Window, ETDT_ENABLETAB); +} + +/* +** Destructor. +** +*/ +Dialog::Tab::~Tab() +{ + DestroyWindow(m_Window); +} + +/* +** Activates the tab. +** +*/ +void Dialog::Tab::Activate() +{ + c_ActiveTabWindow = m_Window; + + if (!m_Initialized) + { + Initialize(); + } + + EnableWindow(m_Window, TRUE); + BringWindowToTop(m_Window); +} diff --git a/Library/Dialog.h b/Library/Dialog.h index 0a603385..9f6f9363 100644 --- a/Library/Dialog.h +++ b/Library/Dialog.h @@ -1,73 +1,73 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __DIALOG_H__ -#define __DIALOG_H__ - -class Dialog -{ -public: - HWND GetWindow() { return m_Window; } - - static HWND GetActiveDialogWindow() { return c_ActiveDialogWindow; } - static HWND GetActiveTabWindow() { return c_ActiveTabWindow; } - -protected: - class Tab - { - public: - HWND GetWindow() { return m_Window; } - bool IsInitialized() { return m_Initialized; } - void Activate(); - - virtual void Initialize() {} - virtual void Resize(int w, int h) {} - - protected: - Tab(HINSTANCE instance, HWND owner, WORD tabId, DLGPROC tabProc); - virtual ~Tab(); - - HWND m_Window; - bool m_Initialized; - }; - - Dialog(HWND wnd); - virtual ~Dialog(); - - virtual HWND GetActiveWindow() { return m_Window; } - - INT_PTR OnActivate(WPARAM wParam, LPARAM lParam); - - void SetDialogFont(HWND window); - void SetDialogFont() { SetDialogFont(m_Window); } - - static void SetMenuButton(HWND button); - - HWND m_Window; - HFONT m_Font; - HFONT m_FontBold; - -private: - static BOOL CALLBACK SetFontProc(HWND hWnd, LPARAM lParam); - static LRESULT CALLBACK MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData); - - static HWND c_ActiveDialogWindow; - static HWND c_ActiveTabWindow; -}; - -#endif +/* + Copyright (C) 2011 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __DIALOG_H__ +#define __DIALOG_H__ + +class Dialog +{ +public: + HWND GetWindow() { return m_Window; } + + static HWND GetActiveDialogWindow() { return c_ActiveDialogWindow; } + static HWND GetActiveTabWindow() { return c_ActiveTabWindow; } + +protected: + class Tab + { + public: + HWND GetWindow() { return m_Window; } + bool IsInitialized() { return m_Initialized; } + void Activate(); + + virtual void Initialize() {} + virtual void Resize(int w, int h) {} + + protected: + Tab(HINSTANCE instance, HWND owner, WORD tabId, DLGPROC tabProc); + virtual ~Tab(); + + HWND m_Window; + bool m_Initialized; + }; + + Dialog(HWND wnd); + virtual ~Dialog(); + + virtual HWND GetActiveWindow() { return m_Window; } + + INT_PTR OnActivate(WPARAM wParam, LPARAM lParam); + + void SetDialogFont(HWND window); + void SetDialogFont() { SetDialogFont(m_Window); } + + static void SetMenuButton(HWND button); + + HWND m_Window; + HFONT m_Font; + HFONT m_FontBold; + +private: + static BOOL CALLBACK SetFontProc(HWND hWnd, LPARAM lParam); + static LRESULT CALLBACK MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData); + + static HWND c_ActiveDialogWindow; + static HWND c_ActiveTabWindow; +}; + +#endif diff --git a/Library/DialogAbout.cpp b/Library/DialogAbout.cpp index 7f0c04a4..9f3a3940 100644 --- a/Library/DialogAbout.cpp +++ b/Library/DialogAbout.cpp @@ -1,1331 +1,1331 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas, Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Rainmeter.h" -#include "System.h" -#include "MeterWindow.h" -#include "TrayWindow.h" -#include "Measure.h" -#include "resource.h" -#include "DialogAbout.h" -#include "../Version.h" -#include "../Common/Platform.h" - -WINDOWPLACEMENT DialogAbout::c_WindowPlacement = {0}; -DialogAbout* DialogAbout::c_Dialog = nullptr; - -/* -** Constructor. -** -*/ -DialogAbout::DialogAbout() : Dialog() -{ -} - -/* -** Destructor. -** -*/ -DialogAbout::~DialogAbout() -{ -} - -/* -** Opens the About dialog. -** -*/ -void DialogAbout::Open(int tab) -{ - if (!c_Dialog) - { - c_Dialog = new DialogAbout(); - } - - c_Dialog->ShowDialogWindow( - GetString(ID_STR_ABOUTRAINMETER), - 0, 0, 400, 210, - DS_CENTER | WS_POPUP | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME, - WS_EX_APPWINDOW | WS_EX_CONTROLPARENT | ((*GetString(ID_STR_ISRTL) == L'1') ? WS_EX_LAYOUTRTL : 0), - Rainmeter::GetInstance().GetWindow()); - - // Fake WM_NOTIFY to change tab - NMHDR nm; - nm.code = TCN_SELCHANGE; - nm.idFrom = Id_Tab; - nm.hwndFrom = c_Dialog->GetControl(Id_Tab); - TabCtrl_SetCurSel(nm.hwndFrom, tab); - c_Dialog->OnNotify(0, (LPARAM)&nm); -} - -/* -** Opens the About dialog by tab name. -** -*/ -void DialogAbout::Open(const WCHAR* name) -{ - int tab = 0; - - if (name) - { - if (_wcsicmp(name, L"Skins") == 0 || - _wcsicmp(name, L"Measures") == 0) // For backwards compatibility - { - tab = 1; - } - else if (_wcsicmp(name, L"Plugins") == 0) - { - tab = 2; - } - else if (_wcsicmp(name, L"Version") == 0) - { - tab = 3; - } - } - - Open(tab); -} - -/* -** Shows log if dialog isn't already open. -** -*/ -void DialogAbout::ShowAboutLog() -{ - if (!c_Dialog) - { - Open(); - } -} - -void DialogAbout::AddLogItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message) -{ - if (c_Dialog && c_Dialog->m_TabLog.IsInitialized()) - { - c_Dialog->m_TabLog.AddItem(level, time, source, message); - } -} - -void DialogAbout::UpdateSkins() -{ - if (c_Dialog && c_Dialog->m_TabSkins.IsInitialized()) - { - c_Dialog->m_TabSkins.UpdateSkinList(); - } -} - -void DialogAbout::UpdateMeasures(MeterWindow* meterWindow) -{ - if (c_Dialog && c_Dialog->m_TabSkins.IsInitialized()) - { - c_Dialog->m_TabSkins.UpdateMeasureList(meterWindow); - } -} - -Dialog::Tab& DialogAbout::GetActiveTab() -{ - int sel = TabCtrl_GetCurSel(GetControl(Id_Tab)); - if (sel == 0) - { - return m_TabLog; - } - else if (sel == 1) - { - return m_TabSkins; - } - else if (sel == 2) - { - return m_TabPlugins; - } - else // if (sel == 3) - { - return m_TabVersion; - } -} - -INT_PTR DialogAbout::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_INITDIALOG: - return OnInitDialog(wParam, lParam); - - case WM_ACTIVATE: - return OnActivate(wParam, lParam); - - case WM_COMMAND: - return OnCommand(wParam, lParam); - - case WM_NOTIFY: - return OnNotify(wParam, lParam); - - case WM_GETMINMAXINFO: - { - MINMAXINFO* mmi = (MINMAXINFO*)lParam; - mmi->ptMinTrackSize.x = 700; - mmi->ptMinTrackSize.y = 350; - } - return TRUE; - - case WM_SIZE: - { - if (wParam != SIZE_MINIMIZED) - { - int w = LOWORD(lParam); - int h = HIWORD(lParam); - RECT r; - - HWND item = GetControl(Id_Tab); - SetWindowPos(item, nullptr, 0, 0, w - 18, h - 47, SWP_NOMOVE | SWP_NOZORDER); - - item = GetControl(Id_CloseButton); - GetClientRect(item, &r); - SetWindowPos(item, nullptr, w - r.right - 9, h - r.bottom - 8, 0, 0, SWP_NOSIZE | SWP_NOZORDER); - - w -= 48; - h -= 100; - m_TabLog.Resize(w, h); - m_TabSkins.Resize(w, h); - m_TabPlugins.Resize(w, h); - m_TabVersion.Resize(w, h); - } - } - return TRUE; - - case WM_CLOSE: - { - GetWindowPlacement(m_Window, &c_WindowPlacement); - if (c_WindowPlacement.showCmd == SW_SHOWMINIMIZED) - { - c_WindowPlacement.showCmd = SW_SHOWNORMAL; - } - - delete c_Dialog; - c_Dialog = nullptr; - } - return TRUE; - } - - return FALSE; -} - -INT_PTR DialogAbout::OnInitDialog(WPARAM wParam, LPARAM lParam) -{ - static const ControlTemplate::Control s_Controls[] = - { - CT_BUTTON(Id_CloseButton, ID_STR_CLOSE, - 344, 191, 50, 14, - WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 0), - CT_TAB(Id_Tab, 0, - 6, 6, 388, 181, - WS_VISIBLE | WS_TABSTOP | TCS_FIXEDWIDTH, 0) // Last for correct tab order. - }; - - CreateControls(s_Controls, _countof(s_Controls), m_Font, GetString); - - HWND item = GetControl(Id_Tab); - m_TabLog.Create(m_Window); - m_TabSkins.Create(m_Window); - m_TabPlugins.Create(m_Window); - m_TabVersion.Create(m_Window); - - TCITEM tci = {0}; - tci.mask = TCIF_TEXT; - tci.pszText = GetString(ID_STR_LOG); - TabCtrl_InsertItem(item, 0, &tci); - tci.pszText = GetString(ID_STR_SKINS); - TabCtrl_InsertItem(item, 1, &tci); - tci.pszText = GetString(ID_STR_PLUGINS); - TabCtrl_InsertItem(item, 2, &tci); - tci.pszText = GetString(ID_STR_VERSION); - TabCtrl_InsertItem(item, 3, &tci); - - HICON hIcon = GetIcon(IDI_RAINMETER); - SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); - - item = GetControl(Id_CloseButton); - SendMessage(m_Window, WM_NEXTDLGCTL, (WPARAM)item, TRUE); - - if (IsWindowsVistaOrGreater()) - { - item = m_TabLog.GetControl(TabLog::Id_ItemsListView); - SetWindowTheme(item, L"explorer", nullptr); - item = m_TabSkins.GetControl(TabSkins::Id_ItemsListView); - SetWindowTheme(item, L"explorer", nullptr); - } - - if (c_WindowPlacement.length == 0) - { - c_WindowPlacement.length = sizeof(WINDOWPLACEMENT); - GetWindowPlacement(m_Window, &c_WindowPlacement); - } - SetWindowPlacement(m_Window, &c_WindowPlacement); - - return TRUE; -} - -INT_PTR DialogAbout::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case Id_CloseButton: - PostMessage(m_Window, WM_CLOSE, 0, 0); - break; - - default: - return FALSE; - } - - return TRUE; -} - -INT_PTR DialogAbout::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->idFrom) - { - case Id_Tab: - if (nm->code == TCN_SELCHANGE) - { - // Disable all tab windows first - EnableWindow(m_TabLog.GetWindow(), FALSE); - EnableWindow(m_TabSkins.GetWindow(), FALSE); - EnableWindow(m_TabPlugins.GetWindow(), FALSE); - EnableWindow(m_TabVersion.GetWindow(), FALSE); - - GetActiveTab().Activate(); - } - break; - - default: - return 1; - } - - return 0; -} - -// ----------------------------------------------------------------------------------------------- -// -// Log tab -// -// ----------------------------------------------------------------------------------------------- - -/* -** Constructor. -** -*/ -DialogAbout::TabLog::TabLog() : Tab(), - m_Error(true), - m_Warning(true), - m_Notice(true), - m_Debug(true) -{ -} - -void DialogAbout::TabLog::Create(HWND owner) -{ - Tab::CreateTabWindow(15, 30, 370, 148, owner); - - // FIXME: Temporary hack. - short buttonWidth = (short)_wtoi(GetString(ID_STR_NUM_BUTTONWIDTH)); - - static const ControlTemplate::Control s_Controls[] = - { - CT_LISTVIEW(Id_ItemsListView, 0, - 0, 0, 368, 135, - WS_VISIBLE | WS_TABSTOP | WS_BORDER | LVS_ICON | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER, 0), - CT_CHECKBOX(Id_ErrorCheckBox, ID_STR_ERROR, - 0, 139, 70, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_WarningCheckBox, ID_STR_WARNING, - 70, 139, 70, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_NoticeCheckBox, ID_STR_NOTICE, - 140, 139, 70, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_DebugCheckBox, ID_STR_DEBUG, - 210, 139, 70, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_ClearButton, ID_STR_CLEAR, - (368 - buttonWidth), 139, buttonWidth, 14, - WS_VISIBLE | WS_TABSTOP, 0) - }; - - CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); -} - -/* -** Called when tab is displayed. -** -*/ -void DialogAbout::TabLog::Initialize() -{ - // Add columns to the list view - HWND item = GetControl(Id_ItemsListView); - ListView_SetExtendedListViewStyleEx(item, 0, LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER); - - // Set folder/.ini icons for tree list - HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR32, 3, 1); - HMODULE hDLL = GetModuleHandle(L"user32"); - - HICON hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(103), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); - ImageList_AddIcon(hImageList, hIcon); - DeleteObject(hIcon); - - hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(101), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); - ImageList_AddIcon(hImageList, hIcon); - DeleteObject(hIcon); - - hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(104), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); - ImageList_AddIcon(hImageList, hIcon); - DeleteObject(hIcon); - - ListView_SetImageList(item, (WPARAM)hImageList, LVSIL_SMALL); - - LVCOLUMN lvc; - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - lvc.fmt = LVCFMT_LEFT; // left-aligned column - lvc.iSubItem = 0; - lvc.cx = 75; - lvc.pszText = GetString(ID_STR_TYPE); - ListView_InsertColumn(item, 0, &lvc); - lvc.iSubItem = 1; - lvc.cx = 85; - lvc.pszText = GetString(ID_STR_TIME); - ListView_InsertColumn(item, 1, &lvc); - lvc.iSubItem = 2; - lvc.cx = 225; - lvc.pszText = GetString(ID_STR_SOURCE); - ListView_InsertColumn(item, 2, &lvc); - lvc.iSubItem = 4; - - // Start 4th column at max width - RECT rect; - lvc.cx = GetWindowRect(item, &rect) ? (rect.right - rect.left - 405) : 180; - lvc.pszText = GetString(ID_STR_MESSAGE); - ListView_InsertColumn(item, 3, &lvc); - - // Add stored entires - for (const auto& entry : GetLogger().GetEntries()) - { - AddItem(entry.level, entry.timestamp.c_str(), entry.source.c_str(), entry.message.c_str()); - } - - item = GetControl(Id_ErrorCheckBox); - Button_SetCheck(item, BST_CHECKED); - - item = GetControl(Id_WarningCheckBox); - Button_SetCheck(item, BST_CHECKED); - - item = GetControl(Id_NoticeCheckBox); - Button_SetCheck(item, BST_CHECKED); - - item = GetControl(Id_DebugCheckBox); - Button_SetCheck(item, BST_CHECKED); - - m_Initialized = true; -} - -/* -** Resizes window and repositions controls. -** -*/ -void DialogAbout::TabLog::Resize(int w, int h) -{ - SetWindowPos(m_Window, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); - - // FIXME: Temporary hack. - short buttonWidth = (short)_wtoi(GetString(ID_STR_NUM_BUTTONWIDTH)); - - RECT r; - LONG bottom; - HWND item = GetControl(Id_ClearButton); - GetClientRect(item, &r); - bottom = r.bottom; - - SetWindowPos(item, nullptr, w - r.right, h - bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); - - item = GetControl(Id_ErrorCheckBox); - GetClientRect(item, &r); - SetWindowPos(item, nullptr, 0, h - bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); - - item = GetControl(Id_WarningCheckBox); - SetWindowPos(item, nullptr, r.right, h - bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); - - item = GetControl(Id_NoticeCheckBox); - SetWindowPos(item, nullptr, r.right * 2, h - bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); - - item = GetControl(Id_DebugCheckBox); - SetWindowPos(item, nullptr, r.right * 3, h - bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); - - item = GetControl(Id_ItemsListView); - SetWindowPos(item, nullptr, 0, 0, w, h - bottom - 10, SWP_NOMOVE | SWP_NOZORDER); - - // Adjust 4th colum - LVCOLUMN lvc; - lvc.mask = LVCF_WIDTH; - lvc.cx = w - 20 - - (ListView_GetColumnWidth(item, 0) + - ListView_GetColumnWidth(item, 1) + - ListView_GetColumnWidth(item, 2)); - ListView_SetColumn(item, 3, &lvc); -} - -/* -** Adds item to log. -** -*/ -void DialogAbout::TabLog::AddItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message) -{ - WCHAR buffer[32]; - LVITEM vitem; - vitem.mask = LVIF_IMAGE | LVIF_TEXT; - vitem.iItem = 0; - vitem.iSubItem = 0; - vitem.pszText = buffer; - HWND item; - - switch (level) - { - case Logger::Level::Error: - if (!m_Error) return; - item = GetControl(Id_ErrorCheckBox); - vitem.iImage = 0; - break; - - case Logger::Level::Warning: - if (!m_Warning) return; - item = GetControl(Id_WarningCheckBox); - vitem.iImage = 1; - break; - - case Logger::Level::Notice: - if (!m_Notice) return; - item = GetControl(Id_NoticeCheckBox); - vitem.iImage = 2; - break; - - case Logger::Level::Debug: - if (!m_Debug) return; - item = GetControl(Id_DebugCheckBox); - vitem.iImage = I_IMAGENONE; - break; - } - - GetWindowText(item, buffer, 32); - item = GetControl(Id_ItemsListView); - ListView_InsertItem(item, &vitem); - ListView_SetItemText(item, vitem.iItem, 1, (WCHAR*)time); - ListView_SetItemText(item, vitem.iItem, 2, (WCHAR*)source); - ListView_SetItemText(item, vitem.iItem, 3, (WCHAR*)message); - if (!ListView_IsItemVisible(item, 0)) - { - ListView_Scroll(item, 0, 16); - } -} - -INT_PTR DialogAbout::TabLog::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return OnCommand(wParam, lParam); - - case WM_NOTIFY: - return OnNotify(wParam, lParam); - } - - return FALSE; -} - -INT_PTR DialogAbout::TabLog::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case Id_ErrorCheckBox: - if (HIWORD(wParam) == BN_CLICKED) - { - m_Error = !m_Error; - } - break; - - case Id_WarningCheckBox: - if (HIWORD(wParam) == BN_CLICKED) - { - m_Warning = !m_Warning; - } - break; - - case Id_NoticeCheckBox: - if (HIWORD(wParam) == BN_CLICKED) - { - m_Notice = !m_Notice; - } - break; - - case Id_DebugCheckBox: - if (HIWORD(wParam) == BN_CLICKED) - { - m_Debug = !m_Debug; - } - break; - - case Id_ClearButton: - if (HIWORD(wParam) == BN_CLICKED) - { - HWND item = GetControl(Id_ItemsListView); - ListView_DeleteAllItems(item); - } - break; - - default: - return 1; - } - - return 0; -} - -INT_PTR DialogAbout::TabLog::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->code) - { - case LVN_KEYDOWN: - { - NMLVKEYDOWN* lvkd = (NMLVKEYDOWN*)nm; - if (lvkd->wVKey == 0x43 && // C key. - IsCtrlKeyDown()) - { - const int sel = ListView_GetNextItem(nm->hwndFrom, -1, LVNI_FOCUSED | LVNI_SELECTED); - if (sel != -1) - { - WCHAR buffer[512]; - - // Get message. - ListView_GetItemText(nm->hwndFrom, sel, 3, buffer, 512); - std::wstring message = buffer; - - // Get source (if any). - ListView_GetItemText(nm->hwndFrom, sel, 2, buffer, 512); - if (*buffer) - { - message += L" ("; - message += buffer; - message += L')'; - } - - System::SetClipboardText(message); - } - } - } - break; - - default: - return FALSE; - } - - return TRUE; -} - -// ----------------------------------------------------------------------------------------------- -// -// Measures tab -// -// ----------------------------------------------------------------------------------------------- - -/* -** Constructor. -** -*/ -DialogAbout::TabSkins::TabSkins() : Tab(), - m_SkinWindow() -{ -} - -void DialogAbout::TabSkins::Create(HWND owner) -{ - Tab::CreateTabWindow(15, 30, 370, 148, owner); - - static const ControlTemplate::Control s_Controls[] = - { - CT_LISTBOX(Id_SkinsListBox, 0, - 0, 0, 120, 148, - WS_VISIBLE | WS_TABSTOP | LBS_NOTIFY | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL, WS_EX_CLIENTEDGE), - CT_LISTVIEW(Id_ItemsListView, 0, - 125, 0, 242, 148, - WS_VISIBLE | WS_TABSTOP | WS_BORDER | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER, 0) - }; - - CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); -} - -void DialogAbout::TabSkins::Initialize() -{ - // Add columns to the list view - HWND item = GetControl(Id_ItemsListView); - ListView_SetExtendedListViewStyleEx(item, 0, LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER); - - LVGROUP lvg; - lvg.cbSize = sizeof(LVGROUP); - lvg.mask = LVGF_HEADER | LVGF_GROUPID | LVGF_STATE; - lvg.state = (IsWindowsVistaOrGreater()) ? LVGS_COLLAPSIBLE : LVGS_NORMAL; - lvg.iGroupId = 0; - lvg.pszHeader = GetString(ID_STR_MEASURES); - ListView_InsertGroup(item, 0, &lvg); - lvg.iGroupId = 1; - lvg.pszHeader = GetString(ID_STR_VARIABLES); - ListView_InsertGroup(item, 1, &lvg); - - ListView_EnableGroupView(item, TRUE); - - LVCOLUMN lvc; - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - lvc.fmt = LVCFMT_LEFT; - lvc.iSubItem = 0; - lvc.cx = 120; - lvc.pszText = GetString(ID_STR_NAME); - ListView_InsertColumn(item, 0, &lvc); - lvc.iSubItem = 1; - lvc.cx = 90; - lvc.pszText = GetString(ID_STR_RANGE); - ListView_InsertColumn(item, 1, &lvc); - lvc.iSubItem = 2; - - // Start 3rd column at max width - RECT rect; - lvc.cx = GetWindowRect(item, &rect) ? (rect.right - rect.left - 230) : 130; - lvc.pszText = GetString(ID_STR_VALUE); - ListView_InsertColumn(item, 2, &lvc); - - UpdateSkinList(); - - m_Initialized = true; -} - -/* -** Resizes window and repositions controls. -** -*/ -void DialogAbout::TabSkins::Resize(int w, int h) -{ - SetWindowPos(m_Window, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); - - HWND item = GetControl(Id_SkinsListBox); - SetWindowPos(item, nullptr, 0, 0, 265, h, SWP_NOMOVE | SWP_NOZORDER); - - item = GetControl(Id_ItemsListView); - SetWindowPos(item, nullptr, 275, 0, w - 275, h, SWP_NOZORDER); - - // Adjust third column - LVCOLUMN lvc; - lvc.mask = LVCF_WIDTH; - lvc.cx = w - 275 - 20 - - (ListView_GetColumnWidth(item, 0) + - ListView_GetColumnWidth(item, 1)); - ListView_SetColumn(item, 2, &lvc); -} - -/* -** Updates the list of skins. -** -*/ -void DialogAbout::TabSkins::UpdateSkinList() -{ - // Delete all entries - HWND item = GetControl(Id_SkinsListBox); - ListBox_ResetContent(item); - - // Add entries for each skin - std::wstring::size_type maxLength = 0; - const std::map& windows = Rainmeter::GetInstance().GetAllMeterWindows(); - std::map::const_iterator iter = windows.begin(); - bool found = false; - for ( ; iter != windows.end(); ++iter) - { - const std::wstring& skinName = (*iter).first; - std::wstring::size_type curLength = skinName.length(); - if (curLength > maxLength) - { - maxLength = curLength; - } - - const WCHAR* name = skinName.c_str(); - int index = ListBox_AddString(item, name); - if (!found && m_SkinWindow == (*iter).second) - { - found = true; - m_SkinWindow = (*iter).second; - ListBox_SetCurSel(item, index); - } - } - - ListBox_SetHorizontalExtent(item, 6 * maxLength); - - if (!found) - { - if (windows.empty()) - { - m_SkinWindow = nullptr; - item = GetControl(Id_ItemsListView); - ListView_DeleteAllItems(item); - } - else - { - // Default to first skin - m_SkinWindow = (*windows.begin()).second; - ListBox_SetCurSel(item, 0); - UpdateMeasureList(m_SkinWindow); - } - } -} - -/* -** Updates the list of measures and values. -** -*/ -void DialogAbout::TabSkins::UpdateMeasureList(MeterWindow* meterWindow) -{ - if (!meterWindow) - { - // Find selected skin - HWND item = GetControl(Id_SkinsListBox); - int selected = (int)SendMessage(item, LB_GETCURSEL, 0, 0); - - const std::map& windows = Rainmeter::GetInstance().GetAllMeterWindows(); - std::map::const_iterator iter = windows.begin(); - while (selected && iter != windows.end()) - { - ++iter; - --selected; - } - - m_SkinWindow = (*iter).second; - } - else if (meterWindow != m_SkinWindow) - { - // Called by a skin other than currently visible one, so return - return; - } - - HWND item = GetControl(Id_ItemsListView); - SendMessage(item, WM_SETREDRAW, FALSE, 0); - int count = ListView_GetItemCount(item); - - LVITEM lvi; - lvi.mask = LVIF_TEXT | LVIF_GROUPID | LVIF_PARAM; - lvi.iSubItem = 0; - lvi.iItem = 0; - lvi.lParam = 0; - - lvi.iGroupId = 0; - const std::vector& measures = m_SkinWindow->GetMeasures(); - std::vector::const_iterator j = measures.begin(); - for ( ; j != measures.end(); ++j) - { - lvi.pszText = (WCHAR*)(*j)->GetName(); - - if (lvi.iItem < count) - { - ListView_SetItem(item, &lvi); - } - else - { - ListView_InsertItem(item, &lvi); - } - - WCHAR buffer[256]; - Measure::GetScaledValue(AUTOSCALE_ON, 1, (*j)->GetMinValue(), buffer, _countof(buffer)); - std::wstring range = buffer; - range += L" - "; - Measure::GetScaledValue(AUTOSCALE_ON, 1, (*j)->GetMaxValue(), buffer, _countof(buffer)); - range += buffer; - - ListView_SetItemText(item, lvi.iItem, 1, (WCHAR*)range.c_str()); - ListView_SetItemText(item, lvi.iItem, 2, (WCHAR*)(*j)->GetStringOrFormattedValue( - AUTOSCALE_OFF, 1, -1, false)); - ++lvi.iItem; - } - - lvi.iGroupId = 1; - const auto& variables = m_SkinWindow->GetParser().GetVariables(); - for (auto iter = variables.cbegin(); iter != variables.cend(); ++iter) - { - const WCHAR* name = (*iter).first.c_str(); - lvi.lParam = (LPARAM)name; - - if (wcscmp(name, L"@") == 0) - { - // Ignore reserved variables - continue; - } - - std::wstring tmpStr = (*iter).first; - _wcslwr(&tmpStr[0]); - lvi.pszText = (WCHAR*)tmpStr.c_str(); - - if (lvi.iItem < count) - { - ListView_SetItem(item, &lvi); - } - else - { - ListView_InsertItem(item, &lvi); - } - - ListView_SetItemText(item, lvi.iItem, 1, L""); - ListView_SetItemText(item, lvi.iItem, 2, (WCHAR*)(*iter).second.c_str()); - ++lvi.iItem; - } - - // Delete unnecessary items - while (count > lvi.iItem) - { - ListView_DeleteItem(item, lvi.iItem); - --count; - } - - int selIndex = ListView_GetNextItem(item, -1, LVNI_FOCUSED | LVNI_SELECTED); - - ListView_SortItems(item, ListSortProc, 0); - - if (selIndex != -1) - { - // Re-select previously selected item - ListView_SetItemState(item, selIndex, LVIS_FOCUSED | LVNI_SELECTED, LVIS_FOCUSED | LVNI_SELECTED); - } - - SendMessage(item, WM_SETREDRAW, TRUE, 0); -} - -int CALLBACK DialogAbout::TabSkins::ListSortProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) -{ - // Measures - if (!lParam1 && !lParam2) return 0; - if (!lParam1) return -1; - if (!lParam2) return 1; - - // Variables - return wcscmp((const WCHAR*)lParam1, (const WCHAR*)lParam2); -} - -INT_PTR DialogAbout::TabSkins::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return OnCommand(wParam, lParam); - - case WM_NOTIFY: - return OnNotify(wParam, lParam); - } - - return FALSE; -} - -INT_PTR DialogAbout::TabSkins::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case Id_SkinsListBox: - if (HIWORD(wParam) == LBN_SELCHANGE) - { - UpdateMeasureList(nullptr); - } - break; - - default: - return 1; - } - - return 0; -} - -INT_PTR DialogAbout::TabSkins::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->code) - { - case LVN_KEYDOWN: - { - NMLVKEYDOWN* lvkd = (NMLVKEYDOWN*)nm; - if (lvkd->wVKey == 0x43 && IsCtrlKeyDown()) // CTRL + C. - { - int sel = ListView_GetNextItem(nm->hwndFrom, -1, LVNI_FOCUSED | LVNI_SELECTED); - if (sel != -1) - { - std::wstring tmpSz(512, L'0'); - ListView_GetItemText(nm->hwndFrom, sel, 2, &tmpSz[0], 512); - System::SetClipboardText(tmpSz); - } - } - } - break; - - default: - return FALSE; - } - - return TRUE; -} - -// ----------------------------------------------------------------------------------------------- -// -// Plugins tab -// -// ----------------------------------------------------------------------------------------------- - -DialogAbout::TabPlugins::TabPlugins() : Tab() -{ -} - -void DialogAbout::TabPlugins::Create(HWND owner) -{ - Tab::CreateTabWindow(15, 30, 370, 148, owner); - - static const ControlTemplate::Control s_Controls[] = - { - CT_LISTVIEW(Id_ItemsListView, 0, - 0, 0, 368, 148, - WS_VISIBLE | WS_TABSTOP | WS_BORDER | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER, 0) - }; - - CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); -} - -void DialogAbout::TabPlugins::Initialize() -{ - // Add columns to the list view - HWND item = GetControl(Id_ItemsListView); - - LVCOLUMN lvc; - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - lvc.fmt = LVCFMT_LEFT; // left-aligned column - lvc.iSubItem = 0; - lvc.cx = 140; - lvc.pszText = GetString(ID_STR_NAME); - ListView_InsertColumn(item, 0, &lvc); - lvc.iSubItem = 1; - lvc.cx = 80; - lvc.pszText = GetString(ID_STR_VERSION); - ListView_InsertColumn(item, 1, &lvc); - lvc.iSubItem = 2; - - // Start 3rd column at max width - RECT rect; - lvc.cx = GetWindowRect(item, &rect) ? (rect.right - rect.left - 193) : 290; - lvc.pszText = GetString(ID_STR_AUTHOR); - ListView_InsertColumn(item, 2, &lvc); - - LVITEM vitem; - vitem.mask = LVIF_TEXT; - vitem.iItem = 0; - vitem.iSubItem = 0; - - auto findPlugins = [&](const std::wstring& path) - { - std::wstring filter = path + L"*.dll"; - - WIN32_FIND_DATA fd; - HANDLE hSearch = FindFirstFile(filter.c_str(), &fd); - if (hSearch == INVALID_HANDLE_VALUE) - { - return; - } - - int index = 0; - do - { - // Try to get the version and author - std::wstring tmpSz = path + fd.cFileName; - const WCHAR* path = tmpSz.c_str(); - - vitem.iItem = index; - vitem.pszText = fd.cFileName; - - // Try to get version and author from file resources first - DWORD handle; - DWORD versionSize = GetFileVersionInfoSize(path, &handle); - if (versionSize) - { - bool found = false; - void* data = new BYTE[versionSize]; - if (GetFileVersionInfo(path, 0, versionSize, data)) - { - UINT len; - struct LANGCODEPAGE - { - WORD wLanguage; - WORD wCodePage; - } *lcp; - - if (VerQueryValue(data, L"\\VarFileInfo\\Translation", (LPVOID*)&lcp, &len)) - { - WCHAR key[64]; - LPWSTR value; - - _snwprintf_s(key, _TRUNCATE, L"\\StringFileInfo\\%04x%04x\\ProductName", lcp[0].wLanguage, lcp[0].wCodePage); - if (VerQueryValue(data, (LPTSTR)(LPCTSTR)key, (void**)&value, &len) && - wcscmp(value, L"Rainmeter") == 0) - { - ListView_InsertItem(item, &vitem); - ++index; - found = true; - - _snwprintf_s(key, _TRUNCATE, L"\\StringFileInfo\\%04x%04x\\FileVersion", lcp[0].wLanguage, lcp[0].wCodePage); - if (VerQueryValue(data, (LPTSTR)(LPCTSTR)key, (void**)&value, &len)) - { - ListView_SetItemText(item, vitem.iItem, 1, value); - } - - _snwprintf_s(key, _TRUNCATE, L"\\StringFileInfo\\%04x%04x\\LegalCopyright", lcp[0].wLanguage, lcp[0].wCodePage); - if (VerQueryValue(data, (LPTSTR)(LPCTSTR)key, (void**)&value, &len)) - { - ListView_SetItemText(item, vitem.iItem, 2, value); - } - } - } - } - - delete [] data; - if (found) continue; - } - - // Try old calling GetPluginVersion/GetPluginAuthor for backwards compatibility - DWORD err = 0; - HMODULE dll = System::RmLoadLibrary(path, &err); - if (dll) - { - ListView_InsertItem(item, &vitem); - ++index; - - GETPLUGINVERSION GetVersionFunc = (GETPLUGINVERSION)GetProcAddress(dll, "GetPluginVersion"); - if (GetVersionFunc) - { - UINT version = GetVersionFunc(); - WCHAR buffer[64]; - _snwprintf_s(buffer, _TRUNCATE, L"%u.%u", version / 1000, version % 1000); - ListView_SetItemText(item, vitem.iItem, 1, buffer); - } - - GETPLUGINAUTHOR GetAuthorFunc = (GETPLUGINAUTHOR)GetProcAddress(dll, "GetPluginAuthor"); - if (GetAuthorFunc) - { - LPCTSTR author = GetAuthorFunc(); - if (author && *author) - { - ListView_SetItemText(item, vitem.iItem, 2, (LPWSTR)author); - } - } - - FreeLibrary(dll); - } - else - { - LogErrorF(L"About Dialog - Unable to load plugin: %s (%u)", tmpSz.c_str(), err); - } - } - while (FindNextFile(hSearch, &fd)); - FindClose(hSearch); - }; - - findPlugins(Rainmeter::GetInstance().GetPluginPath()); - if (Rainmeter::GetInstance().HasUserPluginPath()) - { - findPlugins(Rainmeter::GetInstance().GetUserPluginPath()); - } - - m_Initialized = true; -} - -/* -** Resizes window and repositions controls. -** -*/ -void DialogAbout::TabPlugins::Resize(int w, int h) -{ - SetWindowPos(m_Window, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); - - HWND item = GetControl(Id_ItemsListView); - SetWindowPos(item, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); - - // Adjust third colum - LVCOLUMN lvc; - lvc.mask = LVCF_WIDTH; - lvc.cx = w - 20 - - (ListView_GetColumnWidth(item, 0) + - ListView_GetColumnWidth(item, 1)); - ListView_SetColumn(item, 2, &lvc); -} - -// ----------------------------------------------------------------------------------------------- -// -// Version tab -// -// ----------------------------------------------------------------------------------------------- - -/* -** Constructor. -** -*/ -DialogAbout::TabVersion::TabVersion() : Tab() -{ -} - -void DialogAbout::TabVersion::Create(HWND owner) -{ - Tab::CreateTabWindow(15, 30, 370, 148, owner); - - // FIXME: Temporary hack. - short buttonWidth = (short)_wtoi(GetString(ID_STR_NUM_BUTTONWIDTH)); - - const ControlTemplate::Control s_Controls[] = - { - CT_ICON(Id_AppIcon, 0, - 0, 8, 24, 24, - WS_VISIBLE, 0), - CT_LABEL(Id_VersionLabel, 0, - 28, 0, 300, 9, - WS_VISIBLE, 0), - CT_LINKLABEL(Id_HomeLink, ID_STR_GETLATESTVERSION, - 28, 13, 300, 9, - WS_VISIBLE, 0), - CT_LINKLABEL(Id_LicenseLink, ID_STR_COPYRIGHTNOTICE, - 28, 26, 300, 9, - WS_VISIBLE, 0), - CT_LABEL(Id_WinVerLabel, 0, - 0, 43, 360, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(Id_PathLabel, 0, - 0, 56, 360, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(Id_IniFileLabel, 0, - 0, 69, 360, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(Id_SkinPathLabel, 0, - 0, 82, 360, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_BUTTON(Id_CopyButton, ID_STR_COPYTOCLIPBOARD, - 0, 98, buttonWidth + 25, 14, - WS_VISIBLE | WS_TABSTOP, 0) - }; - - CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); -} - -void DialogAbout::TabVersion::Initialize() -{ - HWND item = GetControl(Id_AppIcon); - HICON icon = GetIcon(IDI_RAINMETER, true); - Static_SetIcon(item, icon); - - item = GetControl(Id_VersionLabel); - WCHAR tmpSz[64]; - _snwprintf_s(tmpSz, _TRUNCATE, L"%s%s r%i %s (%s)", APPVERSION, revision_beta ? L" beta" : L"", revision_number, APPBITS, APPDATE); - SetWindowText(item, tmpSz); - - item = GetControl(Id_WinVerLabel); - SetWindowText(item, Platform::GetPlatformFriendlyName().c_str()); - - item = GetControl(Id_PathLabel); - std::wstring text = L"Path: " + Rainmeter::GetInstance().GetPath(); - SetWindowText(item, text.c_str()); - - item = GetControl(Id_IniFileLabel); - text = L"IniFile: " + Rainmeter::GetInstance().GetIniFile(); - SetWindowText(item, text.c_str()); - - item = GetControl(Id_SkinPathLabel); - text = L"SkinPath: " + Rainmeter::GetInstance().GetSkinPath(); - SetWindowText(item, text.c_str()); - - m_Initialized = true; -} - -/* -** Resizes window and repositions controls. -** -*/ -void DialogAbout::TabVersion::Resize(int w, int h) -{ - SetWindowPos(m_Window, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); -} - -INT_PTR DialogAbout::TabVersion::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return OnCommand(wParam, lParam); - - case WM_NOTIFY: - return OnNotify(wParam, lParam); - } - - return FALSE; -} - -INT_PTR DialogAbout::TabVersion::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case Id_CopyButton: - { - WCHAR tmpSz[64]; - int len = _snwprintf_s(tmpSz, _TRUNCATE, L"%s%s r%i %s (%s)", APPVERSION, revision_beta ? L" beta" : L"", revision_number, APPBITS, APPDATE); - std::wstring text(tmpSz, len); - text += L'\n'; - text += Platform::GetPlatformFriendlyName(); - text += L"\nPath: "; - text += Rainmeter::GetInstance().GetPath(); - text += L"\nIniFile: "; - text += Rainmeter::GetInstance().GetIniFile(); - text += L"\nSkinPath: "; - text += Rainmeter::GetInstance().GetSkinPath(); - System::SetClipboardText(text); - } - break; - - default: - return 1; - } - - return 0; -} - -INT_PTR DialogAbout::TabVersion::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->code) - { - case NM_CLICK: - if (nm->idFrom == Id_HomeLink) - { - CommandHandler::RunFile(L"http://rainmeter.net"); - } - else if (nm->idFrom == Id_HomeLink) - { - CommandHandler::RunFile(L"http://gnu.org/licenses"); - } - break; - - default: - return FALSE; - } - - return TRUE; -} +/* + Copyright (C) 2011 Birunthan Mohanathas, Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Rainmeter.h" +#include "System.h" +#include "MeterWindow.h" +#include "TrayWindow.h" +#include "Measure.h" +#include "resource.h" +#include "DialogAbout.h" +#include "../Version.h" +#include "../Common/Platform.h" + +WINDOWPLACEMENT DialogAbout::c_WindowPlacement = {0}; +DialogAbout* DialogAbout::c_Dialog = nullptr; + +/* +** Constructor. +** +*/ +DialogAbout::DialogAbout() : Dialog() +{ +} + +/* +** Destructor. +** +*/ +DialogAbout::~DialogAbout() +{ +} + +/* +** Opens the About dialog. +** +*/ +void DialogAbout::Open(int tab) +{ + if (!c_Dialog) + { + c_Dialog = new DialogAbout(); + } + + c_Dialog->ShowDialogWindow( + GetString(ID_STR_ABOUTRAINMETER), + 0, 0, 400, 210, + DS_CENTER | WS_POPUP | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME, + WS_EX_APPWINDOW | WS_EX_CONTROLPARENT | ((*GetString(ID_STR_ISRTL) == L'1') ? WS_EX_LAYOUTRTL : 0), + Rainmeter::GetInstance().GetWindow()); + + // Fake WM_NOTIFY to change tab + NMHDR nm; + nm.code = TCN_SELCHANGE; + nm.idFrom = Id_Tab; + nm.hwndFrom = c_Dialog->GetControl(Id_Tab); + TabCtrl_SetCurSel(nm.hwndFrom, tab); + c_Dialog->OnNotify(0, (LPARAM)&nm); +} + +/* +** Opens the About dialog by tab name. +** +*/ +void DialogAbout::Open(const WCHAR* name) +{ + int tab = 0; + + if (name) + { + if (_wcsicmp(name, L"Skins") == 0 || + _wcsicmp(name, L"Measures") == 0) // For backwards compatibility + { + tab = 1; + } + else if (_wcsicmp(name, L"Plugins") == 0) + { + tab = 2; + } + else if (_wcsicmp(name, L"Version") == 0) + { + tab = 3; + } + } + + Open(tab); +} + +/* +** Shows log if dialog isn't already open. +** +*/ +void DialogAbout::ShowAboutLog() +{ + if (!c_Dialog) + { + Open(); + } +} + +void DialogAbout::AddLogItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message) +{ + if (c_Dialog && c_Dialog->m_TabLog.IsInitialized()) + { + c_Dialog->m_TabLog.AddItem(level, time, source, message); + } +} + +void DialogAbout::UpdateSkins() +{ + if (c_Dialog && c_Dialog->m_TabSkins.IsInitialized()) + { + c_Dialog->m_TabSkins.UpdateSkinList(); + } +} + +void DialogAbout::UpdateMeasures(MeterWindow* meterWindow) +{ + if (c_Dialog && c_Dialog->m_TabSkins.IsInitialized()) + { + c_Dialog->m_TabSkins.UpdateMeasureList(meterWindow); + } +} + +Dialog::Tab& DialogAbout::GetActiveTab() +{ + int sel = TabCtrl_GetCurSel(GetControl(Id_Tab)); + if (sel == 0) + { + return m_TabLog; + } + else if (sel == 1) + { + return m_TabSkins; + } + else if (sel == 2) + { + return m_TabPlugins; + } + else // if (sel == 3) + { + return m_TabVersion; + } +} + +INT_PTR DialogAbout::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_INITDIALOG: + return OnInitDialog(wParam, lParam); + + case WM_ACTIVATE: + return OnActivate(wParam, lParam); + + case WM_COMMAND: + return OnCommand(wParam, lParam); + + case WM_NOTIFY: + return OnNotify(wParam, lParam); + + case WM_GETMINMAXINFO: + { + MINMAXINFO* mmi = (MINMAXINFO*)lParam; + mmi->ptMinTrackSize.x = 700; + mmi->ptMinTrackSize.y = 350; + } + return TRUE; + + case WM_SIZE: + { + if (wParam != SIZE_MINIMIZED) + { + int w = LOWORD(lParam); + int h = HIWORD(lParam); + RECT r; + + HWND item = GetControl(Id_Tab); + SetWindowPos(item, nullptr, 0, 0, w - 18, h - 47, SWP_NOMOVE | SWP_NOZORDER); + + item = GetControl(Id_CloseButton); + GetClientRect(item, &r); + SetWindowPos(item, nullptr, w - r.right - 9, h - r.bottom - 8, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + w -= 48; + h -= 100; + m_TabLog.Resize(w, h); + m_TabSkins.Resize(w, h); + m_TabPlugins.Resize(w, h); + m_TabVersion.Resize(w, h); + } + } + return TRUE; + + case WM_CLOSE: + { + GetWindowPlacement(m_Window, &c_WindowPlacement); + if (c_WindowPlacement.showCmd == SW_SHOWMINIMIZED) + { + c_WindowPlacement.showCmd = SW_SHOWNORMAL; + } + + delete c_Dialog; + c_Dialog = nullptr; + } + return TRUE; + } + + return FALSE; +} + +INT_PTR DialogAbout::OnInitDialog(WPARAM wParam, LPARAM lParam) +{ + static const ControlTemplate::Control s_Controls[] = + { + CT_BUTTON(Id_CloseButton, ID_STR_CLOSE, + 344, 191, 50, 14, + WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 0), + CT_TAB(Id_Tab, 0, + 6, 6, 388, 181, + WS_VISIBLE | WS_TABSTOP | TCS_FIXEDWIDTH, 0) // Last for correct tab order. + }; + + CreateControls(s_Controls, _countof(s_Controls), m_Font, GetString); + + HWND item = GetControl(Id_Tab); + m_TabLog.Create(m_Window); + m_TabSkins.Create(m_Window); + m_TabPlugins.Create(m_Window); + m_TabVersion.Create(m_Window); + + TCITEM tci = {0}; + tci.mask = TCIF_TEXT; + tci.pszText = GetString(ID_STR_LOG); + TabCtrl_InsertItem(item, 0, &tci); + tci.pszText = GetString(ID_STR_SKINS); + TabCtrl_InsertItem(item, 1, &tci); + tci.pszText = GetString(ID_STR_PLUGINS); + TabCtrl_InsertItem(item, 2, &tci); + tci.pszText = GetString(ID_STR_VERSION); + TabCtrl_InsertItem(item, 3, &tci); + + HICON hIcon = GetIcon(IDI_RAINMETER); + SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); + + item = GetControl(Id_CloseButton); + SendMessage(m_Window, WM_NEXTDLGCTL, (WPARAM)item, TRUE); + + if (IsWindowsVistaOrGreater()) + { + item = m_TabLog.GetControl(TabLog::Id_ItemsListView); + SetWindowTheme(item, L"explorer", nullptr); + item = m_TabSkins.GetControl(TabSkins::Id_ItemsListView); + SetWindowTheme(item, L"explorer", nullptr); + } + + if (c_WindowPlacement.length == 0) + { + c_WindowPlacement.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(m_Window, &c_WindowPlacement); + } + SetWindowPlacement(m_Window, &c_WindowPlacement); + + return TRUE; +} + +INT_PTR DialogAbout::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case Id_CloseButton: + PostMessage(m_Window, WM_CLOSE, 0, 0); + break; + + default: + return FALSE; + } + + return TRUE; +} + +INT_PTR DialogAbout::OnNotify(WPARAM wParam, LPARAM lParam) +{ + LPNMHDR nm = (LPNMHDR)lParam; + switch (nm->idFrom) + { + case Id_Tab: + if (nm->code == TCN_SELCHANGE) + { + // Disable all tab windows first + EnableWindow(m_TabLog.GetWindow(), FALSE); + EnableWindow(m_TabSkins.GetWindow(), FALSE); + EnableWindow(m_TabPlugins.GetWindow(), FALSE); + EnableWindow(m_TabVersion.GetWindow(), FALSE); + + GetActiveTab().Activate(); + } + break; + + default: + return 1; + } + + return 0; +} + +// ----------------------------------------------------------------------------------------------- +// +// Log tab +// +// ----------------------------------------------------------------------------------------------- + +/* +** Constructor. +** +*/ +DialogAbout::TabLog::TabLog() : Tab(), + m_Error(true), + m_Warning(true), + m_Notice(true), + m_Debug(true) +{ +} + +void DialogAbout::TabLog::Create(HWND owner) +{ + Tab::CreateTabWindow(15, 30, 370, 148, owner); + + // FIXME: Temporary hack. + short buttonWidth = (short)_wtoi(GetString(ID_STR_NUM_BUTTONWIDTH)); + + static const ControlTemplate::Control s_Controls[] = + { + CT_LISTVIEW(Id_ItemsListView, 0, + 0, 0, 368, 135, + WS_VISIBLE | WS_TABSTOP | WS_BORDER | LVS_ICON | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER, 0), + CT_CHECKBOX(Id_ErrorCheckBox, ID_STR_ERROR, + 0, 139, 70, 9, + WS_VISIBLE | WS_TABSTOP, 0), + CT_CHECKBOX(Id_WarningCheckBox, ID_STR_WARNING, + 70, 139, 70, 9, + WS_VISIBLE | WS_TABSTOP, 0), + CT_CHECKBOX(Id_NoticeCheckBox, ID_STR_NOTICE, + 140, 139, 70, 9, + WS_VISIBLE | WS_TABSTOP, 0), + CT_CHECKBOX(Id_DebugCheckBox, ID_STR_DEBUG, + 210, 139, 70, 9, + WS_VISIBLE | WS_TABSTOP, 0), + CT_BUTTON(Id_ClearButton, ID_STR_CLEAR, + (368 - buttonWidth), 139, buttonWidth, 14, + WS_VISIBLE | WS_TABSTOP, 0) + }; + + CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); +} + +/* +** Called when tab is displayed. +** +*/ +void DialogAbout::TabLog::Initialize() +{ + // Add columns to the list view + HWND item = GetControl(Id_ItemsListView); + ListView_SetExtendedListViewStyleEx(item, 0, LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER); + + // Set folder/.ini icons for tree list + HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR32, 3, 1); + HMODULE hDLL = GetModuleHandle(L"user32"); + + HICON hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(103), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); + ImageList_AddIcon(hImageList, hIcon); + DeleteObject(hIcon); + + hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(101), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); + ImageList_AddIcon(hImageList, hIcon); + DeleteObject(hIcon); + + hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(104), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); + ImageList_AddIcon(hImageList, hIcon); + DeleteObject(hIcon); + + ListView_SetImageList(item, (WPARAM)hImageList, LVSIL_SMALL); + + LVCOLUMN lvc; + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.fmt = LVCFMT_LEFT; // left-aligned column + lvc.iSubItem = 0; + lvc.cx = 75; + lvc.pszText = GetString(ID_STR_TYPE); + ListView_InsertColumn(item, 0, &lvc); + lvc.iSubItem = 1; + lvc.cx = 85; + lvc.pszText = GetString(ID_STR_TIME); + ListView_InsertColumn(item, 1, &lvc); + lvc.iSubItem = 2; + lvc.cx = 225; + lvc.pszText = GetString(ID_STR_SOURCE); + ListView_InsertColumn(item, 2, &lvc); + lvc.iSubItem = 4; + + // Start 4th column at max width + RECT rect; + lvc.cx = GetWindowRect(item, &rect) ? (rect.right - rect.left - 405) : 180; + lvc.pszText = GetString(ID_STR_MESSAGE); + ListView_InsertColumn(item, 3, &lvc); + + // Add stored entires + for (const auto& entry : GetLogger().GetEntries()) + { + AddItem(entry.level, entry.timestamp.c_str(), entry.source.c_str(), entry.message.c_str()); + } + + item = GetControl(Id_ErrorCheckBox); + Button_SetCheck(item, BST_CHECKED); + + item = GetControl(Id_WarningCheckBox); + Button_SetCheck(item, BST_CHECKED); + + item = GetControl(Id_NoticeCheckBox); + Button_SetCheck(item, BST_CHECKED); + + item = GetControl(Id_DebugCheckBox); + Button_SetCheck(item, BST_CHECKED); + + m_Initialized = true; +} + +/* +** Resizes window and repositions controls. +** +*/ +void DialogAbout::TabLog::Resize(int w, int h) +{ + SetWindowPos(m_Window, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); + + // FIXME: Temporary hack. + short buttonWidth = (short)_wtoi(GetString(ID_STR_NUM_BUTTONWIDTH)); + + RECT r; + LONG bottom; + HWND item = GetControl(Id_ClearButton); + GetClientRect(item, &r); + bottom = r.bottom; + + SetWindowPos(item, nullptr, w - r.right, h - bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + item = GetControl(Id_ErrorCheckBox); + GetClientRect(item, &r); + SetWindowPos(item, nullptr, 0, h - bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + item = GetControl(Id_WarningCheckBox); + SetWindowPos(item, nullptr, r.right, h - bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + item = GetControl(Id_NoticeCheckBox); + SetWindowPos(item, nullptr, r.right * 2, h - bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + item = GetControl(Id_DebugCheckBox); + SetWindowPos(item, nullptr, r.right * 3, h - bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + item = GetControl(Id_ItemsListView); + SetWindowPos(item, nullptr, 0, 0, w, h - bottom - 10, SWP_NOMOVE | SWP_NOZORDER); + + // Adjust 4th colum + LVCOLUMN lvc; + lvc.mask = LVCF_WIDTH; + lvc.cx = w - 20 - + (ListView_GetColumnWidth(item, 0) + + ListView_GetColumnWidth(item, 1) + + ListView_GetColumnWidth(item, 2)); + ListView_SetColumn(item, 3, &lvc); +} + +/* +** Adds item to log. +** +*/ +void DialogAbout::TabLog::AddItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message) +{ + WCHAR buffer[32]; + LVITEM vitem; + vitem.mask = LVIF_IMAGE | LVIF_TEXT; + vitem.iItem = 0; + vitem.iSubItem = 0; + vitem.pszText = buffer; + HWND item; + + switch (level) + { + case Logger::Level::Error: + if (!m_Error) return; + item = GetControl(Id_ErrorCheckBox); + vitem.iImage = 0; + break; + + case Logger::Level::Warning: + if (!m_Warning) return; + item = GetControl(Id_WarningCheckBox); + vitem.iImage = 1; + break; + + case Logger::Level::Notice: + if (!m_Notice) return; + item = GetControl(Id_NoticeCheckBox); + vitem.iImage = 2; + break; + + case Logger::Level::Debug: + if (!m_Debug) return; + item = GetControl(Id_DebugCheckBox); + vitem.iImage = I_IMAGENONE; + break; + } + + GetWindowText(item, buffer, 32); + item = GetControl(Id_ItemsListView); + ListView_InsertItem(item, &vitem); + ListView_SetItemText(item, vitem.iItem, 1, (WCHAR*)time); + ListView_SetItemText(item, vitem.iItem, 2, (WCHAR*)source); + ListView_SetItemText(item, vitem.iItem, 3, (WCHAR*)message); + if (!ListView_IsItemVisible(item, 0)) + { + ListView_Scroll(item, 0, 16); + } +} + +INT_PTR DialogAbout::TabLog::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + return OnCommand(wParam, lParam); + + case WM_NOTIFY: + return OnNotify(wParam, lParam); + } + + return FALSE; +} + +INT_PTR DialogAbout::TabLog::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case Id_ErrorCheckBox: + if (HIWORD(wParam) == BN_CLICKED) + { + m_Error = !m_Error; + } + break; + + case Id_WarningCheckBox: + if (HIWORD(wParam) == BN_CLICKED) + { + m_Warning = !m_Warning; + } + break; + + case Id_NoticeCheckBox: + if (HIWORD(wParam) == BN_CLICKED) + { + m_Notice = !m_Notice; + } + break; + + case Id_DebugCheckBox: + if (HIWORD(wParam) == BN_CLICKED) + { + m_Debug = !m_Debug; + } + break; + + case Id_ClearButton: + if (HIWORD(wParam) == BN_CLICKED) + { + HWND item = GetControl(Id_ItemsListView); + ListView_DeleteAllItems(item); + } + break; + + default: + return 1; + } + + return 0; +} + +INT_PTR DialogAbout::TabLog::OnNotify(WPARAM wParam, LPARAM lParam) +{ + LPNMHDR nm = (LPNMHDR)lParam; + switch (nm->code) + { + case LVN_KEYDOWN: + { + NMLVKEYDOWN* lvkd = (NMLVKEYDOWN*)nm; + if (lvkd->wVKey == 0x43 && // C key. + IsCtrlKeyDown()) + { + const int sel = ListView_GetNextItem(nm->hwndFrom, -1, LVNI_FOCUSED | LVNI_SELECTED); + if (sel != -1) + { + WCHAR buffer[512]; + + // Get message. + ListView_GetItemText(nm->hwndFrom, sel, 3, buffer, 512); + std::wstring message = buffer; + + // Get source (if any). + ListView_GetItemText(nm->hwndFrom, sel, 2, buffer, 512); + if (*buffer) + { + message += L" ("; + message += buffer; + message += L')'; + } + + System::SetClipboardText(message); + } + } + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------------------------------- +// +// Measures tab +// +// ----------------------------------------------------------------------------------------------- + +/* +** Constructor. +** +*/ +DialogAbout::TabSkins::TabSkins() : Tab(), + m_SkinWindow() +{ +} + +void DialogAbout::TabSkins::Create(HWND owner) +{ + Tab::CreateTabWindow(15, 30, 370, 148, owner); + + static const ControlTemplate::Control s_Controls[] = + { + CT_LISTBOX(Id_SkinsListBox, 0, + 0, 0, 120, 148, + WS_VISIBLE | WS_TABSTOP | LBS_NOTIFY | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL, WS_EX_CLIENTEDGE), + CT_LISTVIEW(Id_ItemsListView, 0, + 125, 0, 242, 148, + WS_VISIBLE | WS_TABSTOP | WS_BORDER | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER, 0) + }; + + CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); +} + +void DialogAbout::TabSkins::Initialize() +{ + // Add columns to the list view + HWND item = GetControl(Id_ItemsListView); + ListView_SetExtendedListViewStyleEx(item, 0, LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER); + + LVGROUP lvg; + lvg.cbSize = sizeof(LVGROUP); + lvg.mask = LVGF_HEADER | LVGF_GROUPID | LVGF_STATE; + lvg.state = (IsWindowsVistaOrGreater()) ? LVGS_COLLAPSIBLE : LVGS_NORMAL; + lvg.iGroupId = 0; + lvg.pszHeader = GetString(ID_STR_MEASURES); + ListView_InsertGroup(item, 0, &lvg); + lvg.iGroupId = 1; + lvg.pszHeader = GetString(ID_STR_VARIABLES); + ListView_InsertGroup(item, 1, &lvg); + + ListView_EnableGroupView(item, TRUE); + + LVCOLUMN lvc; + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.fmt = LVCFMT_LEFT; + lvc.iSubItem = 0; + lvc.cx = 120; + lvc.pszText = GetString(ID_STR_NAME); + ListView_InsertColumn(item, 0, &lvc); + lvc.iSubItem = 1; + lvc.cx = 90; + lvc.pszText = GetString(ID_STR_RANGE); + ListView_InsertColumn(item, 1, &lvc); + lvc.iSubItem = 2; + + // Start 3rd column at max width + RECT rect; + lvc.cx = GetWindowRect(item, &rect) ? (rect.right - rect.left - 230) : 130; + lvc.pszText = GetString(ID_STR_VALUE); + ListView_InsertColumn(item, 2, &lvc); + + UpdateSkinList(); + + m_Initialized = true; +} + +/* +** Resizes window and repositions controls. +** +*/ +void DialogAbout::TabSkins::Resize(int w, int h) +{ + SetWindowPos(m_Window, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); + + HWND item = GetControl(Id_SkinsListBox); + SetWindowPos(item, nullptr, 0, 0, 265, h, SWP_NOMOVE | SWP_NOZORDER); + + item = GetControl(Id_ItemsListView); + SetWindowPos(item, nullptr, 275, 0, w - 275, h, SWP_NOZORDER); + + // Adjust third column + LVCOLUMN lvc; + lvc.mask = LVCF_WIDTH; + lvc.cx = w - 275 - 20 - + (ListView_GetColumnWidth(item, 0) + + ListView_GetColumnWidth(item, 1)); + ListView_SetColumn(item, 2, &lvc); +} + +/* +** Updates the list of skins. +** +*/ +void DialogAbout::TabSkins::UpdateSkinList() +{ + // Delete all entries + HWND item = GetControl(Id_SkinsListBox); + ListBox_ResetContent(item); + + // Add entries for each skin + std::wstring::size_type maxLength = 0; + const std::map& windows = Rainmeter::GetInstance().GetAllMeterWindows(); + std::map::const_iterator iter = windows.begin(); + bool found = false; + for ( ; iter != windows.end(); ++iter) + { + const std::wstring& skinName = (*iter).first; + std::wstring::size_type curLength = skinName.length(); + if (curLength > maxLength) + { + maxLength = curLength; + } + + const WCHAR* name = skinName.c_str(); + int index = ListBox_AddString(item, name); + if (!found && m_SkinWindow == (*iter).second) + { + found = true; + m_SkinWindow = (*iter).second; + ListBox_SetCurSel(item, index); + } + } + + ListBox_SetHorizontalExtent(item, 6 * maxLength); + + if (!found) + { + if (windows.empty()) + { + m_SkinWindow = nullptr; + item = GetControl(Id_ItemsListView); + ListView_DeleteAllItems(item); + } + else + { + // Default to first skin + m_SkinWindow = (*windows.begin()).second; + ListBox_SetCurSel(item, 0); + UpdateMeasureList(m_SkinWindow); + } + } +} + +/* +** Updates the list of measures and values. +** +*/ +void DialogAbout::TabSkins::UpdateMeasureList(MeterWindow* meterWindow) +{ + if (!meterWindow) + { + // Find selected skin + HWND item = GetControl(Id_SkinsListBox); + int selected = (int)SendMessage(item, LB_GETCURSEL, 0, 0); + + const std::map& windows = Rainmeter::GetInstance().GetAllMeterWindows(); + std::map::const_iterator iter = windows.begin(); + while (selected && iter != windows.end()) + { + ++iter; + --selected; + } + + m_SkinWindow = (*iter).second; + } + else if (meterWindow != m_SkinWindow) + { + // Called by a skin other than currently visible one, so return + return; + } + + HWND item = GetControl(Id_ItemsListView); + SendMessage(item, WM_SETREDRAW, FALSE, 0); + int count = ListView_GetItemCount(item); + + LVITEM lvi; + lvi.mask = LVIF_TEXT | LVIF_GROUPID | LVIF_PARAM; + lvi.iSubItem = 0; + lvi.iItem = 0; + lvi.lParam = 0; + + lvi.iGroupId = 0; + const std::vector& measures = m_SkinWindow->GetMeasures(); + std::vector::const_iterator j = measures.begin(); + for ( ; j != measures.end(); ++j) + { + lvi.pszText = (WCHAR*)(*j)->GetName(); + + if (lvi.iItem < count) + { + ListView_SetItem(item, &lvi); + } + else + { + ListView_InsertItem(item, &lvi); + } + + WCHAR buffer[256]; + Measure::GetScaledValue(AUTOSCALE_ON, 1, (*j)->GetMinValue(), buffer, _countof(buffer)); + std::wstring range = buffer; + range += L" - "; + Measure::GetScaledValue(AUTOSCALE_ON, 1, (*j)->GetMaxValue(), buffer, _countof(buffer)); + range += buffer; + + ListView_SetItemText(item, lvi.iItem, 1, (WCHAR*)range.c_str()); + ListView_SetItemText(item, lvi.iItem, 2, (WCHAR*)(*j)->GetStringOrFormattedValue( + AUTOSCALE_OFF, 1, -1, false)); + ++lvi.iItem; + } + + lvi.iGroupId = 1; + const auto& variables = m_SkinWindow->GetParser().GetVariables(); + for (auto iter = variables.cbegin(); iter != variables.cend(); ++iter) + { + const WCHAR* name = (*iter).first.c_str(); + lvi.lParam = (LPARAM)name; + + if (wcscmp(name, L"@") == 0) + { + // Ignore reserved variables + continue; + } + + std::wstring tmpStr = (*iter).first; + _wcslwr(&tmpStr[0]); + lvi.pszText = (WCHAR*)tmpStr.c_str(); + + if (lvi.iItem < count) + { + ListView_SetItem(item, &lvi); + } + else + { + ListView_InsertItem(item, &lvi); + } + + ListView_SetItemText(item, lvi.iItem, 1, L""); + ListView_SetItemText(item, lvi.iItem, 2, (WCHAR*)(*iter).second.c_str()); + ++lvi.iItem; + } + + // Delete unnecessary items + while (count > lvi.iItem) + { + ListView_DeleteItem(item, lvi.iItem); + --count; + } + + int selIndex = ListView_GetNextItem(item, -1, LVNI_FOCUSED | LVNI_SELECTED); + + ListView_SortItems(item, ListSortProc, 0); + + if (selIndex != -1) + { + // Re-select previously selected item + ListView_SetItemState(item, selIndex, LVIS_FOCUSED | LVNI_SELECTED, LVIS_FOCUSED | LVNI_SELECTED); + } + + SendMessage(item, WM_SETREDRAW, TRUE, 0); +} + +int CALLBACK DialogAbout::TabSkins::ListSortProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) +{ + // Measures + if (!lParam1 && !lParam2) return 0; + if (!lParam1) return -1; + if (!lParam2) return 1; + + // Variables + return wcscmp((const WCHAR*)lParam1, (const WCHAR*)lParam2); +} + +INT_PTR DialogAbout::TabSkins::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + return OnCommand(wParam, lParam); + + case WM_NOTIFY: + return OnNotify(wParam, lParam); + } + + return FALSE; +} + +INT_PTR DialogAbout::TabSkins::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case Id_SkinsListBox: + if (HIWORD(wParam) == LBN_SELCHANGE) + { + UpdateMeasureList(nullptr); + } + break; + + default: + return 1; + } + + return 0; +} + +INT_PTR DialogAbout::TabSkins::OnNotify(WPARAM wParam, LPARAM lParam) +{ + LPNMHDR nm = (LPNMHDR)lParam; + switch (nm->code) + { + case LVN_KEYDOWN: + { + NMLVKEYDOWN* lvkd = (NMLVKEYDOWN*)nm; + if (lvkd->wVKey == 0x43 && IsCtrlKeyDown()) // CTRL + C. + { + int sel = ListView_GetNextItem(nm->hwndFrom, -1, LVNI_FOCUSED | LVNI_SELECTED); + if (sel != -1) + { + std::wstring tmpSz(512, L'0'); + ListView_GetItemText(nm->hwndFrom, sel, 2, &tmpSz[0], 512); + System::SetClipboardText(tmpSz); + } + } + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------------------------------- +// +// Plugins tab +// +// ----------------------------------------------------------------------------------------------- + +DialogAbout::TabPlugins::TabPlugins() : Tab() +{ +} + +void DialogAbout::TabPlugins::Create(HWND owner) +{ + Tab::CreateTabWindow(15, 30, 370, 148, owner); + + static const ControlTemplate::Control s_Controls[] = + { + CT_LISTVIEW(Id_ItemsListView, 0, + 0, 0, 368, 148, + WS_VISIBLE | WS_TABSTOP | WS_BORDER | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER, 0) + }; + + CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); +} + +void DialogAbout::TabPlugins::Initialize() +{ + // Add columns to the list view + HWND item = GetControl(Id_ItemsListView); + + LVCOLUMN lvc; + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.fmt = LVCFMT_LEFT; // left-aligned column + lvc.iSubItem = 0; + lvc.cx = 140; + lvc.pszText = GetString(ID_STR_NAME); + ListView_InsertColumn(item, 0, &lvc); + lvc.iSubItem = 1; + lvc.cx = 80; + lvc.pszText = GetString(ID_STR_VERSION); + ListView_InsertColumn(item, 1, &lvc); + lvc.iSubItem = 2; + + // Start 3rd column at max width + RECT rect; + lvc.cx = GetWindowRect(item, &rect) ? (rect.right - rect.left - 193) : 290; + lvc.pszText = GetString(ID_STR_AUTHOR); + ListView_InsertColumn(item, 2, &lvc); + + LVITEM vitem; + vitem.mask = LVIF_TEXT; + vitem.iItem = 0; + vitem.iSubItem = 0; + + auto findPlugins = [&](const std::wstring& path) + { + std::wstring filter = path + L"*.dll"; + + WIN32_FIND_DATA fd; + HANDLE hSearch = FindFirstFile(filter.c_str(), &fd); + if (hSearch == INVALID_HANDLE_VALUE) + { + return; + } + + int index = 0; + do + { + // Try to get the version and author + std::wstring tmpSz = path + fd.cFileName; + const WCHAR* path = tmpSz.c_str(); + + vitem.iItem = index; + vitem.pszText = fd.cFileName; + + // Try to get version and author from file resources first + DWORD handle; + DWORD versionSize = GetFileVersionInfoSize(path, &handle); + if (versionSize) + { + bool found = false; + void* data = new BYTE[versionSize]; + if (GetFileVersionInfo(path, 0, versionSize, data)) + { + UINT len; + struct LANGCODEPAGE + { + WORD wLanguage; + WORD wCodePage; + } *lcp; + + if (VerQueryValue(data, L"\\VarFileInfo\\Translation", (LPVOID*)&lcp, &len)) + { + WCHAR key[64]; + LPWSTR value; + + _snwprintf_s(key, _TRUNCATE, L"\\StringFileInfo\\%04x%04x\\ProductName", lcp[0].wLanguage, lcp[0].wCodePage); + if (VerQueryValue(data, (LPTSTR)(LPCTSTR)key, (void**)&value, &len) && + wcscmp(value, L"Rainmeter") == 0) + { + ListView_InsertItem(item, &vitem); + ++index; + found = true; + + _snwprintf_s(key, _TRUNCATE, L"\\StringFileInfo\\%04x%04x\\FileVersion", lcp[0].wLanguage, lcp[0].wCodePage); + if (VerQueryValue(data, (LPTSTR)(LPCTSTR)key, (void**)&value, &len)) + { + ListView_SetItemText(item, vitem.iItem, 1, value); + } + + _snwprintf_s(key, _TRUNCATE, L"\\StringFileInfo\\%04x%04x\\LegalCopyright", lcp[0].wLanguage, lcp[0].wCodePage); + if (VerQueryValue(data, (LPTSTR)(LPCTSTR)key, (void**)&value, &len)) + { + ListView_SetItemText(item, vitem.iItem, 2, value); + } + } + } + } + + delete [] data; + if (found) continue; + } + + // Try old calling GetPluginVersion/GetPluginAuthor for backwards compatibility + DWORD err = 0; + HMODULE dll = System::RmLoadLibrary(path, &err); + if (dll) + { + ListView_InsertItem(item, &vitem); + ++index; + + GETPLUGINVERSION GetVersionFunc = (GETPLUGINVERSION)GetProcAddress(dll, "GetPluginVersion"); + if (GetVersionFunc) + { + UINT version = GetVersionFunc(); + WCHAR buffer[64]; + _snwprintf_s(buffer, _TRUNCATE, L"%u.%u", version / 1000, version % 1000); + ListView_SetItemText(item, vitem.iItem, 1, buffer); + } + + GETPLUGINAUTHOR GetAuthorFunc = (GETPLUGINAUTHOR)GetProcAddress(dll, "GetPluginAuthor"); + if (GetAuthorFunc) + { + LPCTSTR author = GetAuthorFunc(); + if (author && *author) + { + ListView_SetItemText(item, vitem.iItem, 2, (LPWSTR)author); + } + } + + FreeLibrary(dll); + } + else + { + LogErrorF(L"About Dialog - Unable to load plugin: %s (%u)", tmpSz.c_str(), err); + } + } + while (FindNextFile(hSearch, &fd)); + FindClose(hSearch); + }; + + findPlugins(Rainmeter::GetInstance().GetPluginPath()); + if (Rainmeter::GetInstance().HasUserPluginPath()) + { + findPlugins(Rainmeter::GetInstance().GetUserPluginPath()); + } + + m_Initialized = true; +} + +/* +** Resizes window and repositions controls. +** +*/ +void DialogAbout::TabPlugins::Resize(int w, int h) +{ + SetWindowPos(m_Window, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); + + HWND item = GetControl(Id_ItemsListView); + SetWindowPos(item, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); + + // Adjust third colum + LVCOLUMN lvc; + lvc.mask = LVCF_WIDTH; + lvc.cx = w - 20 - + (ListView_GetColumnWidth(item, 0) + + ListView_GetColumnWidth(item, 1)); + ListView_SetColumn(item, 2, &lvc); +} + +// ----------------------------------------------------------------------------------------------- +// +// Version tab +// +// ----------------------------------------------------------------------------------------------- + +/* +** Constructor. +** +*/ +DialogAbout::TabVersion::TabVersion() : Tab() +{ +} + +void DialogAbout::TabVersion::Create(HWND owner) +{ + Tab::CreateTabWindow(15, 30, 370, 148, owner); + + // FIXME: Temporary hack. + short buttonWidth = (short)_wtoi(GetString(ID_STR_NUM_BUTTONWIDTH)); + + const ControlTemplate::Control s_Controls[] = + { + CT_ICON(Id_AppIcon, 0, + 0, 8, 24, 24, + WS_VISIBLE, 0), + CT_LABEL(Id_VersionLabel, 0, + 28, 0, 300, 9, + WS_VISIBLE, 0), + CT_LINKLABEL(Id_HomeLink, ID_STR_GETLATESTVERSION, + 28, 13, 300, 9, + WS_VISIBLE, 0), + CT_LINKLABEL(Id_LicenseLink, ID_STR_COPYRIGHTNOTICE, + 28, 26, 300, 9, + WS_VISIBLE, 0), + CT_LABEL(Id_WinVerLabel, 0, + 0, 43, 360, 9, + WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), + CT_LABEL(Id_PathLabel, 0, + 0, 56, 360, 9, + WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), + CT_LABEL(Id_IniFileLabel, 0, + 0, 69, 360, 9, + WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), + CT_LABEL(Id_SkinPathLabel, 0, + 0, 82, 360, 9, + WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), + CT_BUTTON(Id_CopyButton, ID_STR_COPYTOCLIPBOARD, + 0, 98, buttonWidth + 25, 14, + WS_VISIBLE | WS_TABSTOP, 0) + }; + + CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); +} + +void DialogAbout::TabVersion::Initialize() +{ + HWND item = GetControl(Id_AppIcon); + HICON icon = GetIcon(IDI_RAINMETER, true); + Static_SetIcon(item, icon); + + item = GetControl(Id_VersionLabel); + WCHAR tmpSz[64]; + _snwprintf_s(tmpSz, _TRUNCATE, L"%s%s r%i %s (%s)", APPVERSION, revision_beta ? L" beta" : L"", revision_number, APPBITS, APPDATE); + SetWindowText(item, tmpSz); + + item = GetControl(Id_WinVerLabel); + SetWindowText(item, Platform::GetPlatformFriendlyName().c_str()); + + item = GetControl(Id_PathLabel); + std::wstring text = L"Path: " + Rainmeter::GetInstance().GetPath(); + SetWindowText(item, text.c_str()); + + item = GetControl(Id_IniFileLabel); + text = L"IniFile: " + Rainmeter::GetInstance().GetIniFile(); + SetWindowText(item, text.c_str()); + + item = GetControl(Id_SkinPathLabel); + text = L"SkinPath: " + Rainmeter::GetInstance().GetSkinPath(); + SetWindowText(item, text.c_str()); + + m_Initialized = true; +} + +/* +** Resizes window and repositions controls. +** +*/ +void DialogAbout::TabVersion::Resize(int w, int h) +{ + SetWindowPos(m_Window, nullptr, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); +} + +INT_PTR DialogAbout::TabVersion::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + return OnCommand(wParam, lParam); + + case WM_NOTIFY: + return OnNotify(wParam, lParam); + } + + return FALSE; +} + +INT_PTR DialogAbout::TabVersion::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case Id_CopyButton: + { + WCHAR tmpSz[64]; + int len = _snwprintf_s(tmpSz, _TRUNCATE, L"%s%s r%i %s (%s)", APPVERSION, revision_beta ? L" beta" : L"", revision_number, APPBITS, APPDATE); + std::wstring text(tmpSz, len); + text += L'\n'; + text += Platform::GetPlatformFriendlyName(); + text += L"\nPath: "; + text += Rainmeter::GetInstance().GetPath(); + text += L"\nIniFile: "; + text += Rainmeter::GetInstance().GetIniFile(); + text += L"\nSkinPath: "; + text += Rainmeter::GetInstance().GetSkinPath(); + System::SetClipboardText(text); + } + break; + + default: + return 1; + } + + return 0; +} + +INT_PTR DialogAbout::TabVersion::OnNotify(WPARAM wParam, LPARAM lParam) +{ + LPNMHDR nm = (LPNMHDR)lParam; + switch (nm->code) + { + case NM_CLICK: + if (nm->idFrom == Id_HomeLink) + { + CommandHandler::RunFile(L"http://rainmeter.net"); + } + else if (nm->idFrom == Id_HomeLink) + { + CommandHandler::RunFile(L"http://gnu.org/licenses"); + } + break; + + default: + return FALSE; + } + + return TRUE; +} diff --git a/Library/DialogAbout.h b/Library/DialogAbout.h index 760b071b..6b8a1a59 100644 --- a/Library/DialogAbout.h +++ b/Library/DialogAbout.h @@ -1,182 +1,182 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __DIALOGABOUT_H__ -#define __DIALOGABOUT_H__ - -#include "../Common/Dialog.h" -#include "Logger.h" -#include "MeterWindow.h" - -class DialogAbout : public Dialog -{ -public: - DialogAbout(); - virtual ~DialogAbout(); - - DialogAbout(const DialogAbout& other) = delete; - DialogAbout& operator=(DialogAbout other) = delete; - - static Dialog* GetDialog() { return c_Dialog; } - - static void Open(int tab = 0); - static void Open(const WCHAR* name); - static void ShowAboutLog(); - - static void AddLogItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message); - static void UpdateSkins(); - static void UpdateMeasures(MeterWindow* meterWindow); - -protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - -private: - // Log tab - class TabLog : public Tab - { - public: - enum Id - { - Id_ItemsListView = 100, - Id_ErrorCheckBox, - Id_WarningCheckBox, - Id_NoticeCheckBox, - Id_DebugCheckBox, - Id_ClearButton - }; - - TabLog(); - - void Create(HWND owner); - virtual void Initialize(); - virtual void Resize(int w, int h); - - void AddItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message); - - protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - - private: - bool m_Error; - bool m_Warning; - bool m_Notice; - bool m_Debug; - }; - - // Measures tab - class TabSkins : public Tab - { - public: - enum Id - { - Id_SkinsListBox = 100, - Id_ItemsListView - }; - - TabSkins(); - - void Create(HWND owner); - virtual void Initialize(); - virtual void Resize(int w, int h); - - void UpdateSkinList(); - void UpdateMeasureList(MeterWindow* meterWindow); - - protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - - private: - static int CALLBACK ListSortProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); - - MeterWindow* m_SkinWindow; - }; - - // Plugins tab - class TabPlugins : public Tab - { - public: - enum Id - { - Id_ItemsListView = 100 - }; - - TabPlugins(); - - void Create(HWND owner); - virtual void Initialize(); - virtual void Resize(int w, int h); - - private: - typedef LPCTSTR (*GETPLUGINAUTHOR)(); - typedef UINT (*GETPLUGINVERSION)(); - }; - - // Version tab - class TabVersion : public Tab - { - public: - enum Id - { - Id_AppIcon = 100, - Id_VersionLabel, - Id_HomeLink, - Id_LicenseLink, - Id_WinVerLabel, - Id_PathLabel, - Id_IniFileLabel, - Id_SkinPathLabel, - Id_CopyButton - }; - - TabVersion(); - - void Create(HWND owner); - virtual void Initialize(); - virtual void Resize(int w, int h); - - protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - }; - - enum Id - { - Id_CloseButton = IDCLOSE, - Id_Tab = 100 - }; - - Tab& GetActiveTab(); - - TabLog m_TabLog; - TabSkins m_TabSkins; - TabPlugins m_TabPlugins; - TabVersion m_TabVersion; - - static WINDOWPLACEMENT c_WindowPlacement; - static DialogAbout* c_Dialog; -}; - -#endif +/* + Copyright (C) 2011 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __DIALOGABOUT_H__ +#define __DIALOGABOUT_H__ + +#include "../Common/Dialog.h" +#include "Logger.h" +#include "MeterWindow.h" + +class DialogAbout : public Dialog +{ +public: + DialogAbout(); + virtual ~DialogAbout(); + + DialogAbout(const DialogAbout& other) = delete; + DialogAbout& operator=(DialogAbout other) = delete; + + static Dialog* GetDialog() { return c_Dialog; } + + static void Open(int tab = 0); + static void Open(const WCHAR* name); + static void ShowAboutLog(); + + static void AddLogItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message); + static void UpdateSkins(); + static void UpdateMeasures(MeterWindow* meterWindow); + +protected: + virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + +private: + // Log tab + class TabLog : public Tab + { + public: + enum Id + { + Id_ItemsListView = 100, + Id_ErrorCheckBox, + Id_WarningCheckBox, + Id_NoticeCheckBox, + Id_DebugCheckBox, + Id_ClearButton + }; + + TabLog(); + + void Create(HWND owner); + virtual void Initialize(); + virtual void Resize(int w, int h); + + void AddItem(Logger::Level level, LPCWSTR time, LPCWSTR source, LPCWSTR message); + + protected: + virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + + private: + bool m_Error; + bool m_Warning; + bool m_Notice; + bool m_Debug; + }; + + // Measures tab + class TabSkins : public Tab + { + public: + enum Id + { + Id_SkinsListBox = 100, + Id_ItemsListView + }; + + TabSkins(); + + void Create(HWND owner); + virtual void Initialize(); + virtual void Resize(int w, int h); + + void UpdateSkinList(); + void UpdateMeasureList(MeterWindow* meterWindow); + + protected: + virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + + private: + static int CALLBACK ListSortProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); + + MeterWindow* m_SkinWindow; + }; + + // Plugins tab + class TabPlugins : public Tab + { + public: + enum Id + { + Id_ItemsListView = 100 + }; + + TabPlugins(); + + void Create(HWND owner); + virtual void Initialize(); + virtual void Resize(int w, int h); + + private: + typedef LPCTSTR (*GETPLUGINAUTHOR)(); + typedef UINT (*GETPLUGINVERSION)(); + }; + + // Version tab + class TabVersion : public Tab + { + public: + enum Id + { + Id_AppIcon = 100, + Id_VersionLabel, + Id_HomeLink, + Id_LicenseLink, + Id_WinVerLabel, + Id_PathLabel, + Id_IniFileLabel, + Id_SkinPathLabel, + Id_CopyButton + }; + + TabVersion(); + + void Create(HWND owner); + virtual void Initialize(); + virtual void Resize(int w, int h); + + protected: + virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + }; + + enum Id + { + Id_CloseButton = IDCLOSE, + Id_Tab = 100 + }; + + Tab& GetActiveTab(); + + TabLog m_TabLog; + TabSkins m_TabSkins; + TabPlugins m_TabPlugins; + TabVersion m_TabVersion; + + static WINDOWPLACEMENT c_WindowPlacement; + static DialogAbout* c_Dialog; +}; + +#endif diff --git a/Library/DialogManage.cpp b/Library/DialogManage.cpp index 47902bb5..ad48debd 100644 --- a/Library/DialogManage.cpp +++ b/Library/DialogManage.cpp @@ -1,2137 +1,2137 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../Common/MenuTemplate.h" -#include "Rainmeter.h" -#include "System.h" -#include "MeterWindow.h" -#include "TrayWindow.h" -#include "Measure.h" -#include "resource.h" -#include "DialogManage.h" -#include "DialogAbout.h" -#include "../Version.h" -#include - -WINDOWPLACEMENT DialogManage::c_WindowPlacement = {0}; -DialogManage* DialogManage::c_Dialog = nullptr; - -/* -** Constructor. -** -*/ -DialogManage::DialogManage() : Dialog() -{ -} - -/* -** Destructor. -** -*/ -DialogManage::~DialogManage() -{ -} - -/* -** Opens the Manage dialog by tab name. -** -*/ -void DialogManage::Open(const WCHAR* name) -{ - int tab = 0; - - if (name) - { - if (_wcsicmp(name, L"Layouts") == 0 || - _wcsicmp(name, L"Themes") == 0) // For backwards compatibility. - { - tab = 1; - } - else if (_wcsicmp(name, L"Settings") == 0) - { - tab = 2; - } - } - - Open(tab); -} - -/* -** Opens the Manage dialog. -** -*/ -void DialogManage::Open(int tab) -{ - if (!c_Dialog) - { - c_Dialog = new DialogManage(); - } - - c_Dialog->ShowDialogWindow( - GetString(ID_STR_MANAGERAINMETER), - 0, 0, 500, 322, - DS_CENTER | WS_POPUP | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU, - WS_EX_APPWINDOW | WS_EX_CONTROLPARENT | ((*GetString(ID_STR_ISRTL) == L'1') ? WS_EX_LAYOUTRTL : 0), - Rainmeter::GetInstance().GetWindow()); - - // Fake WM_NOTIFY to change tab - NMHDR nm; - nm.code = TCN_SELCHANGE; - nm.idFrom = Id_Tab; - nm.hwndFrom = c_Dialog->GetControl(Id_Tab); - TabCtrl_SetCurSel(nm.hwndFrom, tab); - c_Dialog->OnNotify(0, (LPARAM)&nm); -} - -/* -** Opens the Manage dialog Skins tab with skin selected. -** -*/ -void DialogManage::OpenSkin(MeterWindow* meterWindow) -{ - Open(); - - if (c_Dialog) - { - std::wstring name = meterWindow->GetFolderPath() + L'\\'; - name += meterWindow->GetFileName(); - - HWND item = c_Dialog->m_TabSkins.GetControl(TabSkins::Id_SkinsTreeView); - c_Dialog->m_TabSkins.SelectTreeItem(item, TreeView_GetRoot(item), name.c_str()); - } -} - -/* -** Opens the Manage dialog tab with parameters -** -*/ -void DialogManage::Open(const WCHAR* tabName, const WCHAR* param1, const WCHAR* param2) -{ - Open(tabName); - - if (c_Dialog) - { - // "Skins" tab - if (_wcsicmp(tabName, L"Skins") == 0) - { - // |param1| represents the config (ie. "illustro\Clock") - // |param2| represents the file (ie. "Clock.ini") - - std::wstring name = param1; - - if (param2) - { - name += L'\\'; - name += param2; - } - - HWND item = c_Dialog->m_TabSkins.GetControl(TabSkins::Id_SkinsTreeView); - c_Dialog->m_TabSkins.SelectTreeItem(item, TreeView_GetRoot(item), name.c_str()); - } - // Future use: Allow optional params for different tabs - //else if (_wcsicmp(tabName, L"Layouts") == 0) - } -} - -void DialogManage::UpdateSkins(MeterWindow* meterWindow, bool deleted) -{ - if (c_Dialog && c_Dialog->m_TabSkins.IsInitialized()) - { - c_Dialog->m_TabSkins.Update(meterWindow, deleted); - } -} - -void DialogManage::UpdateLayouts() -{ - if (c_Dialog && c_Dialog->m_TabLayouts.IsInitialized()) - { - c_Dialog->m_TabLayouts.Update(); - } -} - -Dialog::Tab& DialogManage::GetActiveTab() -{ - int sel = TabCtrl_GetCurSel(GetControl(Id_Tab)); - if (sel == 0) - { - return m_TabSkins; - } - else if (sel == 1) - { - return m_TabLayouts; - } - else // if (sel == 2) - { - return m_TabSettings; - } -} - -INT_PTR DialogManage::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_INITDIALOG: - return OnInitDialog(wParam, lParam); - - case WM_ACTIVATE: - return OnActivate(wParam, lParam); - - case WM_COMMAND: - return OnCommand(wParam, lParam); - - case WM_NOTIFY: - return OnNotify(wParam, lParam); - - case WM_CLOSE: - { - GetWindowPlacement(m_Window, &c_WindowPlacement); - if (c_WindowPlacement.showCmd == SW_SHOWMINIMIZED) - { - c_WindowPlacement.showCmd = SW_SHOWNORMAL; - } - - delete c_Dialog; - c_Dialog = nullptr; - } - return TRUE; - } - - return FALSE; -} - -INT_PTR DialogManage::OnInitDialog(WPARAM wParam, LPARAM lParam) -{ - // FIXME: Temporary hack. - short buttonWidth = (short)_wtoi(GetString(ID_STR_NUM_BUTTONWIDTH)); - - const ControlTemplate::Control s_Controls[] = - { - CT_BUTTON(Id_RefreshAllButton, ID_STR_REFRESHALL, - 5, 303, buttonWidth, 14, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_EditSettingsButton, ID_STR_EDITSETTINGS, - buttonWidth + 9, 303, buttonWidth, 14, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_OpenLogButton, ID_STR_OPENLOG, - buttonWidth + buttonWidth + 13, 303, buttonWidth, 14, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_HelpButton, ID_STR_HELP, - 389, 303, 50, 14, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_CloseButton, ID_STR_CLOSE, - 444, 303, 50, 14, - WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 0), - CT_TAB(Id_Tab, 0, - 6, 6, 488, 293, - WS_VISIBLE | WS_TABSTOP | TCS_FIXEDWIDTH, 0) // Last for correct tab order. - }; - - CreateControls(s_Controls, _countof(s_Controls), m_Font, GetString); - - HWND item = GetControl(Id_Tab); - m_TabSkins.Create(m_Window); - m_TabLayouts.Create(m_Window); - m_TabSettings.Create(m_Window); - - TCITEM tci = {0}; - tci.mask = TCIF_TEXT; - tci.pszText = GetString(ID_STR_SKINS); - TabCtrl_InsertItem(item, 0, &tci); - tci.pszText = GetString(ID_STR_THEMES); - TabCtrl_InsertItem(item, 1, &tci); - tci.pszText = GetString(ID_STR_SETTINGS); - TabCtrl_InsertItem(item, 2, &tci); - - HICON hIcon = GetIcon(IDI_RAINMETER); - SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); - - item = GetControl(Id_CloseButton); - SendMessage(m_Window, WM_NEXTDLGCTL, (WPARAM)item, TRUE); - - item = m_TabSkins.GetControl(TabSkins::Id_FileLabel); - SendMessage(item, WM_SETFONT, (WPARAM)m_FontBold, 0); - - if (IsWindowsVistaOrGreater()) - { - // Use arrows instead of plus/minus in the tree for Vista+ - item = m_TabSkins.GetControl(TabSkins::Id_SkinsTreeView); - SetWindowTheme(item, L"explorer", nullptr); - } - - if (c_WindowPlacement.length == 0) - { - c_WindowPlacement.length = sizeof(WINDOWPLACEMENT); - GetWindowPlacement(m_Window, &c_WindowPlacement); - } - - SetWindowPlacement(m_Window, &c_WindowPlacement); - - return FALSE; -} - -INT_PTR DialogManage::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case Id_RefreshAllButton: - Rainmeter::GetInstance().RefreshAll(); - break; - - case Id_EditSettingsButton: - Rainmeter::GetInstance().EditSettings(); - break; - - case Id_OpenLogButton: - DialogAbout::Open(); - break; - - case Id_CloseButton: - HandleMessage(WM_CLOSE, 0, 0); - break; - - case Id_HelpButton: - { - std::wstring url = L"http://docs.rainmeter.net/manual/user-interface/manage#"; - - Tab& tab = GetActiveTab(); - if (&tab == &m_TabSkins) - { - url += L"Skins"; - } - else if (&tab == &m_TabLayouts) - { - url += L"Layouts"; - } - else // if (&tab == &m_TabSettings) - { - url += L"Settings"; - } - - url += L"Tab"; - ShellExecute(m_Window, L"open", url.c_str(), nullptr, nullptr, SW_SHOWNORMAL); - } - break; - - default: - return FALSE; - } - - return TRUE; -} - -INT_PTR DialogManage::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->idFrom) - { - case Id_Tab: - if (nm->code == TCN_SELCHANGE) - { - // Disable all tab windows first - EnableWindow(m_TabSkins.GetWindow(), FALSE); - EnableWindow(m_TabLayouts.GetWindow(), FALSE); - EnableWindow(m_TabSettings.GetWindow(), FALSE); - - GetActiveTab().Activate(); - } - break; - - default: - return 1; - } - - return 0; -} - -// ----------------------------------------------------------------------------------------------- -// -// Skins tab -// -// ----------------------------------------------------------------------------------------------- - -/* -** Constructor. -** -*/ -DialogManage::TabSkins::TabSkins() : Tab(), - m_SkinWindow(), - m_HandleCommands(false), - m_IgnoreUpdate(false) -{ -} - -void DialogManage::TabSkins::Create(HWND owner) -{ - Tab::CreateTabWindow(15, 30, 470, 260, owner); - - // FIXME: Temporary hack. - short labelWidth = (short)_wtoi(GetString(ID_STR_NUM_LABELWIDTH)); - - const ControlTemplate::Control s_Controls[] = - { - CT_BUTTON(Id_ActiveSkinsButton, ID_STR_ACTIVESKINS, - 0, 0, 146, 14, - WS_VISIBLE | WS_TABSTOP, 0), - CT_TREEVIEW(Id_SkinsTreeView, 0, - 0, 18, 145, 221, - WS_VISIBLE | WS_TABSTOP | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_SHOWSELALWAYS | WS_VSCROLL, WS_EX_CLIENTEDGE), - CT_BUTTON(Id_CreateSkinPackageButton, ID_STR_CREATERMSKINPACKAGE, - 0, 244, 146, 14, - WS_VISIBLE | WS_TABSTOP, 0), - - CT_LABEL(Id_FileLabel, ID_STR_ELLIPSIS, - 165, 0, 130, 14, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(Id_ConfigLabel, 0, - 165, 15, 130, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_BUTTON(Id_LoadButton, ID_STR_LOAD, - 310, 0, 50, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_BUTTON(Id_RefreshButton, ID_STR_REFRESH, - 364, 0, 50, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_BUTTON(Id_EditButton, ID_STR_EDIT, - 418, 0, 50, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - - CT_LABEL(-1, ID_STR_AUTHORSC, - 165, 30, 80, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(Id_AuthorLabel, 0, - 230, 30, 245, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(-1, ID_STR_VERSIONSC, - 165, 43, 80, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(Id_VersionLabel, 0, - 230, 43, 245, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(-1, ID_STR_LICENSESC, - 165, 56, 80, 9, - WS_VISIBLE | WS_TABSTOP | SS_NOPREFIX, 0), - CT_LABEL(Id_LicenseLabel, 0, - 230, 56, 245, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_LABEL(-1, ID_STR_INFORMATIONSC, - 165, 69, 80, 9, - WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), - CT_EDIT(Id_DescriptionLabel, 0, - 228, 69, 238, 64, - WS_VISIBLE | ES_MULTILINE | ES_READONLY, 0), - CT_LINKLABEL(Id_AddMetadataLink, ID_STR_ADDMETADATA, - 165, 142, 150, 9, - 0, 0), - - CT_LINEH(-1, ID_STR_COORDINATESSC, - 165, 156, 304, 1, - WS_VISIBLE, 0), - - CT_LABEL(-1, ID_STR_COORDINATESSC, - 165, 169, labelWidth, 9, - WS_VISIBLE, 0), - CT_EDIT(Id_XPositionEdit, 0, - 165 + labelWidth, 166, 38, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, WS_EX_CLIENTEDGE), - CT_EDIT(Id_YPositionEdit, 0, - 165 + labelWidth + 42, 166, 38, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, WS_EX_CLIENTEDGE), - CT_LABEL(-1, ID_STR_POSITIONSC, - 165, 190, labelWidth, 9, - WS_VISIBLE, 0), - CT_COMBOBOX(Id_ZPositionDropDownList, 0, - 165 + labelWidth, 187, 80, 14, - WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL | WS_DISABLED, 0), - CT_LABEL(-1, ID_STR_LOADORDERSC, - 165, 208, labelWidth, 9, - WS_VISIBLE, 0), - CT_EDIT(Id_LoadOrderEdit, 0, - 165 + labelWidth, 205, 80, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, WS_EX_CLIENTEDGE), - CT_LABEL(-1, ID_STR_TRANSPARENCYSC, - 165, 229, labelWidth, 9, - WS_VISIBLE, 0), - CT_COMBOBOX(Id_TransparencyDropDownList, 0, - 165 + labelWidth, 226, 80, 14, - WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL | WS_DISABLED, 0), - CT_LABEL(-1, ID_STR_ONHOVERSC, - 165, 247, labelWidth, 9, - WS_VISIBLE, 0), - CT_COMBOBOX(Id_OnHoverDropDownList, 0, - 165 + labelWidth, 244, 80, 14, - WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL | WS_DISABLED, 0), - - CT_BUTTON(Id_DisplayMonitorButton, ID_STR_DISPLAYMONITOR, - 350, 166, 118, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_CHECKBOX(Id_DraggableCheckBox, ID_STR_DRAGGABLE, - 350, 190, 118, 9, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_CHECKBOX(Id_ClickThroughCheckBox, ID_STR_CLICKTHROUGH, - 350, 203, 118, 9, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_CHECKBOX(Id_KeepOnScreenCheckBox, ID_STR_KEEPONSCREEN, - 350, 216, 118, 9, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_CHECKBOX(Id_SavePositionCheckBox, ID_STR_SAVEPOSITION, - 350, 229, 118, 9, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_CHECKBOX(Id_SnapToEdgesCheckBox, ID_STR_SNAPTOEDGES, - 350, 242, 118, 9, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0) - }; - - CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); -} - -void DialogManage::TabSkins::Initialize() -{ - BUTTON_SPLITINFO bsi; - bsi.mask = BCSIF_SIZE; - bsi.size.cx = 20; - bsi.size.cy = 14; - - HWND item = GetControl(Id_ActiveSkinsButton); - Dialog::SetMenuButton(item); - - item = GetControl(Id_DisplayMonitorButton); - Dialog::SetMenuButton(item); - - // Load folder/.ini icons from shell32 - HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR32, 2, 10); - HMODULE hDLL = GetModuleHandle(L"shell32"); - - HICON hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(4), IMAGE_ICON, 16, 16, LR_SHARED); - ImageList_AddIcon(hImageList, hIcon); - hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(151), IMAGE_ICON, 16, 16, LR_SHARED); - ImageList_AddIcon(hImageList, hIcon); - - // Apply icons and populate tree - item = GetControl(Id_SkinsTreeView); - TreeView_SetImageList(item, hImageList, TVSIL_NORMAL); - Update(nullptr, false); - - // Get rid of the EDITTEXT control border - item = GetControl(Id_DescriptionLabel); - SetWindowLongPtr(item, GWL_EXSTYLE, GetWindowLongPtr(item, GWL_EXSTYLE) &~ WS_EX_CLIENTEDGE); - SetWindowPos(item, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER); - - item = GetControl(Id_TransparencyDropDownList); - ComboBox_AddString(item, L"0%"); - ComboBox_AddString(item, L"10%"); - ComboBox_AddString(item, L"20%"); - ComboBox_AddString(item, L"30%"); - ComboBox_AddString(item, L"40%"); - ComboBox_AddString(item, L"50%"); - ComboBox_AddString(item, L"60%"); - ComboBox_AddString(item, L"70%"); - ComboBox_AddString(item, L"80%"); - ComboBox_AddString(item, L"90%"); - - item = GetControl(Id_ZPositionDropDownList); - ComboBox_AddString(item, GetString(ID_STR_ONDESKTOP)); - ComboBox_AddString(item, GetString(ID_STR_BOTTOM)); - ComboBox_AddString(item, GetString(ID_STR_NORMAL)); - ComboBox_AddString(item, GetString(ID_STR_TOPMOST)); - ComboBox_AddString(item, GetString(ID_STR_STAYTOPMOST)); - - item = GetControl(Id_OnHoverDropDownList); - ComboBox_AddString(item, GetString(ID_STR_DONOTHING)); - ComboBox_AddString(item, GetString(ID_STR_HIDE)); - ComboBox_AddString(item, GetString(ID_STR_FADEIN)); - ComboBox_AddString(item, GetString(ID_STR_FADEOUT)); - - m_Initialized = true; - m_HandleCommands = true; -} - -/* -** Updates metadata and settings when changed. -** -*/ -void DialogManage::TabSkins::Update(MeterWindow* meterWindow, bool deleted) -{ - if (meterWindow) - { - if (!deleted && m_IgnoreUpdate) - { - // Changed setting from dialog, no need to update - m_IgnoreUpdate = false; - } - else if (m_SkinWindow && m_SkinWindow == meterWindow) - { - // Update from currently open skin - m_HandleCommands = false; - if (deleted) - { - DisableControls(); - m_SkinWindow = nullptr; - } - else - { - SetControls(); - } - m_HandleCommands = true; - } - else if (wcscmp(meterWindow->GetFolderPath().c_str(), m_SkinFolderPath.c_str()) == 0 && - wcscmp(meterWindow->GetFileName().c_str(), m_SkinFileName.c_str()) == 0) - { - ReadSkin(); - } - } - else - { - // Populate tree - HWND item = GetControl(Id_SkinsTreeView); - TreeView_DeleteAllItems(item); - - TVINSERTSTRUCT tvi = {0}; - tvi.hInsertAfter = TVI_LAST; - tvi.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; - tvi.item.iImage = tvi.item.iSelectedImage = 0; - - if (!Rainmeter::GetInstance().m_SkinRegistry.IsEmpty()) - { - PopulateTree(item, tvi); - } - } -} - -void DialogManage::TabSkins::SetControls() -{ - WCHAR buffer[64]; - - HWND item = GetControl(Id_EditButton); - EnableWindow(item, TRUE); - - item = GetControl(Id_LoadButton); - EnableWindow(item, TRUE); - - if (m_SkinWindow) - { - SetWindowText(item, GetString(ID_STR_UNLOAD)); - - item = GetControl(Id_RefreshButton); - EnableWindow(item, TRUE); - - item = GetControl(Id_XPositionEdit); - EnableWindow(item, TRUE); - _itow_s(m_SkinWindow->GetX(), buffer, 10); - SetWindowText(item, buffer); - - item = GetControl(Id_YPositionEdit); - EnableWindow(item, TRUE); - _itow_s(m_SkinWindow->GetY(), buffer, 10); - SetWindowText(item, buffer); - - item = GetControl(Id_DisplayMonitorButton); - EnableWindow(item, TRUE); - - item = GetControl(Id_DraggableCheckBox); - if (Rainmeter::GetInstance().GetDisableDragging()) - { - EnableWindow(item, FALSE); - Button_SetCheck(item, BST_UNCHECKED); - } - else - { - EnableWindow(item, TRUE); - Button_SetCheck(item, m_SkinWindow->GetWindowDraggable()); - } - - item = GetControl(Id_ClickThroughCheckBox); - EnableWindow(item, TRUE); - Button_SetCheck(item, m_SkinWindow->GetClickThrough()); - - item = GetControl(Id_KeepOnScreenCheckBox); - EnableWindow(item, TRUE); - Button_SetCheck(item, m_SkinWindow->GetKeepOnScreen()); - - item = GetControl(Id_SavePositionCheckBox); - EnableWindow(item, TRUE); - Button_SetCheck(item, m_SkinWindow->GetSavePosition()); - - item = GetControl(Id_SnapToEdgesCheckBox); - EnableWindow(item, TRUE); - Button_SetCheck(item, m_SkinWindow->GetSnapEdges()); - - item = GetControl(Id_TransparencyDropDownList); - EnableWindow(item, TRUE); - int value = (int)(10 - m_SkinWindow->GetAlphaValue() / 25.5); - value = min(9, value); - value = max(0, value); - ComboBox_SetCurSel(item, value); - - item = GetControl(Id_ZPositionDropDownList); - EnableWindow(item, TRUE); - ComboBox_SetCurSel(item, m_SkinWindow->GetWindowZPosition() + 2); - - item = GetControl(Id_LoadOrderEdit); - EnableWindow(item, TRUE); - _itow_s(Rainmeter::GetInstance().GetLoadOrder(m_SkinFolderPath), buffer, 10); - SetWindowText(item, buffer); - - item = GetControl(Id_OnHoverDropDownList); - EnableWindow(item, TRUE); - ComboBox_SetCurSel(item, m_SkinWindow->GetWindowHide()); - } - else - { - SetWindowText(item, GetString(ID_STR_LOAD)); - } -} - -void DialogManage::TabSkins::DisableControls(bool clear) -{ - HWND item = GetControl(Id_LoadButton); - SetWindowText(item, GetString(ID_STR_LOAD)); - - if (clear) - { - EnableWindow(item, FALSE); - - item = GetControl(Id_EditButton); - EnableWindow(item, FALSE); - - item = GetControl(Id_FileLabel); - SetWindowText(item, GetString(ID_STR_ELLIPSIS)); - - item = GetControl(Id_ConfigLabel); - SetWindowText(item, L""); - - item = GetControl(Id_AuthorLabel); - SetWindowText(item, L""); - - item = GetControl(Id_VersionLabel); - SetWindowText(item, L""); - - item = GetControl(Id_LicenseLabel); - SetWindowText(item, L""); - - item = GetControl(Id_DescriptionLabel); - SetWindowText(item, L""); - ShowScrollBar(item, SB_VERT, FALSE); - - item = GetControl(Id_AddMetadataLink); - ShowWindow(item, SW_HIDE); - } - else - { - EnableWindow(item, TRUE); - } - - item = GetControl(Id_RefreshButton); - EnableWindow(item, FALSE); - - item = GetControl(Id_XPositionEdit); - SetWindowText(item, L""); - EnableWindow(item, FALSE); - - item = GetControl(Id_YPositionEdit); - SetWindowText(item, L""); - EnableWindow(item, FALSE); - - item = GetControl(Id_DisplayMonitorButton); - EnableWindow(item, FALSE); - - item = GetControl(Id_DraggableCheckBox); - EnableWindow(item, FALSE); - Button_SetCheck(item, BST_UNCHECKED); - - item = GetControl(Id_ClickThroughCheckBox); - EnableWindow(item, FALSE); - Button_SetCheck(item, BST_UNCHECKED); - - item = GetControl(Id_KeepOnScreenCheckBox); - EnableWindow(item, FALSE); - Button_SetCheck(item, BST_UNCHECKED); - - item = GetControl(Id_SavePositionCheckBox); - EnableWindow(item, FALSE); - Button_SetCheck(item, BST_UNCHECKED); - - item = GetControl(Id_SnapToEdgesCheckBox); - EnableWindow(item, FALSE); - Button_SetCheck(item, BST_UNCHECKED); - - item = GetControl(Id_TransparencyDropDownList); - EnableWindow(item, FALSE); - ComboBox_SetCurSel(item, -1); - - item = GetControl(Id_ZPositionDropDownList); - EnableWindow(item, FALSE); - ComboBox_SetCurSel(item, -1); - - item = GetControl(Id_LoadOrderEdit); - SetWindowText(item, L""); - EnableWindow(item, FALSE); - - item = GetControl(Id_OnHoverDropDownList); - EnableWindow(item, FALSE); - ComboBox_SetCurSel(item, -1); -} - -void DialogManage::TabSkins::ReadSkin() -{ - HWND item = GetControl(Id_FileLabel); - SetWindowText(item, m_SkinFileName.c_str()); - - PathSetDlgItemPath(m_Window, Id_ConfigLabel, m_SkinFolderPath.c_str()); - - item = GetControl(Id_EditButton); - EnableWindow(item, TRUE); - - std::wstring file = Rainmeter::GetInstance().GetSkinPath() + m_SkinFolderPath; - file += L'\\'; - file += m_SkinFileName; - m_SkinWindow = Rainmeter::GetInstance().GetMeterWindowByINI(file); - if (!m_SkinWindow) - { - DisableControls(); - } - - SetControls(); - - WCHAR* buffer = new WCHAR[MAX_LINE_LENGTH]; - const WCHAR* fileSz = file.c_str(); - - item = GetControl(Id_AuthorLabel); - if (GetPrivateProfileString(L"Metadata", L"Author", nullptr, buffer, MAX_LINE_LENGTH, fileSz) == 0) - { - // For backwards compatibility. - GetPrivateProfileString(L"Rainmeter", L"Author", nullptr, buffer, MAX_LINE_LENGTH, fileSz); - } - SetWindowText(item, buffer); - - item = GetControl(Id_AddMetadataLink); - if (GetPrivateProfileSection(L"Metadata", buffer, 8, fileSz) > 0) - { - ShowWindow(item, SW_HIDE); - - // Set metadata - item = GetControl(Id_VersionLabel); - GetPrivateProfileString(L"Metadata", L"Version", nullptr, buffer, MAX_LINE_LENGTH, fileSz); - SetWindowText(item, buffer); - - item = GetControl(Id_LicenseLabel); - GetPrivateProfileString(L"Metadata", L"License", nullptr, buffer, MAX_LINE_LENGTH, fileSz); - SetWindowText(item, buffer); - - item = GetControl(Id_DescriptionLabel); - std::wstring text; - if (GetPrivateProfileString(L"Metadata", L"Information", nullptr, buffer, MAX_LINE_LENGTH, fileSz) > 0) - { - text = buffer; - } - else - { - // For backwards compatibility - GetPrivateProfileString(L"Metadata", L"Description", nullptr, buffer, MAX_LINE_LENGTH, fileSz); - text = buffer; - - if (GetPrivateProfileString(L"Metadata", L"Instructions", nullptr, buffer, MAX_LINE_LENGTH, fileSz) > 0) - { - text += L"\r\n\r\n"; - text += buffer; - } - } - - // Replace | with newline - std::wstring::size_type pos; - while ((pos = text.find_first_of(L'|')) != std::wstring::npos) - { - size_t count = (pos + 1 < text.length() && text[pos + 1] == L' ') ? 2 : 1; - if (text[pos - 1] == L' ') - { - --pos; - count += 1; - } - text.replace(pos, count, L"\r\n"); - } - - SetWindowText(item, text.c_str()); - - int lines = Edit_GetLineCount(item); - ShowScrollBar(item, SB_VERT, (BOOL)(lines > 6)); - } - else - { - ShowWindow(item, SW_SHOWNORMAL); - - item = GetControl(Id_VersionLabel); - SetWindowText(item, L""); - - item = GetControl(Id_LicenseLabel); - SetWindowText(item, L""); - - item = GetControl(Id_DescriptionLabel); - SetWindowText(item, L""); - ShowScrollBar(item, SB_VERT, FALSE); - } - - delete [] buffer; -} - -std::wstring DialogManage::TabSkins::GetTreeSelectionPath(HWND tree) -{ - WCHAR buffer[MAX_PATH]; - - // Get current selection name - TVITEM tvi = {0}; - tvi.hItem = TreeView_GetSelection(tree); - tvi.mask = TVIF_TEXT; - tvi.pszText = buffer; - tvi.cchTextMax = MAX_PATH; - TreeView_GetItem(tree, &tvi); - - std::wstring path = buffer; - while ((tvi.hItem = TreeView_GetParent(tree, tvi.hItem)) != nullptr) - { - TreeView_GetItem(tree, &tvi); - path.insert(0, 1, L'\\'); - path.insert(0, buffer); - } - - return path; -} - -/* -** Populates the treeview with folders and skins. -** -*/ -int DialogManage::TabSkins::PopulateTree(HWND tree, TVINSERTSTRUCT& tvi, int index) -{ - int initialLevel = Rainmeter::GetInstance().m_SkinRegistry.GetFolder(index).level; - - const size_t max = Rainmeter::GetInstance().m_SkinRegistry.GetFolderCount(); - while (index < max) - { - const auto& skinFolder = Rainmeter::GetInstance().m_SkinRegistry.GetFolder(index); - if (skinFolder.level != initialLevel) - { - return index - 1; - } - - HTREEITEM oldParent = tvi.hParent; - - // Add folder - tvi.item.iImage = tvi.item.iSelectedImage = 0; - tvi.item.pszText = (WCHAR*)skinFolder.name.c_str(); - tvi.hParent = TreeView_InsertItem(tree, &tvi); - - // Add subfolders - if ((index + 1) < max && - Rainmeter::GetInstance().m_SkinRegistry.GetFolder(index + 1).level == initialLevel + 1) - { - index = PopulateTree(tree, tvi, index + 1); - } - - // Add files - tvi.item.iImage = tvi.item.iSelectedImage = 1; - for (int i = 0, isize = (int)skinFolder.files.size(); i < isize; ++i) - { - tvi.item.pszText = (WCHAR*)skinFolder.files[i].c_str(); - TreeView_InsertItem(tree, &tvi); - } - - tvi.hParent = oldParent; - - ++index; - } - - return index; -} - -/* -** Selects an item in the treeview. -** -*/ -void DialogManage::TabSkins::SelectTreeItem(HWND tree, HTREEITEM item, LPCWSTR name) -{ - WCHAR buffer[MAX_PATH]; - TVITEM tvi = {0}; - tvi.mask = TVIF_TEXT; - tvi.hItem = item; - tvi.pszText = buffer; - - const WCHAR* pos = wcschr(name, L'\\'); - if (pos) - { - const int folderLen = (int)(pos - name); - tvi.cchTextMax = folderLen + 1; // Length of folder name plus 1 for nullptr - - // Find and expand the folder - do - { - TreeView_GetItem(tree, &tvi); - if (wcsncmp(buffer, name, folderLen) == 0) - { - if ((item = TreeView_GetChild(tree, tvi.hItem)) != nullptr) - { - TreeView_Expand(tree, tvi.hItem, TVE_EXPAND); - TreeView_Select(tree, tvi.hItem, TVGN_CARET); - ++pos; // Skip the slash - SelectTreeItem(tree, item, pos); - } - - break; - } - } - while ((tvi.hItem = TreeView_GetNextSibling(tree, tvi.hItem)) != nullptr); - } - else - { - tvi.cchTextMax = MAX_PATH; - - // Find and select the file - do - { - TreeView_GetItem(tree, &tvi); - if (wcscmp(buffer, name) == 0) - { - TreeView_Select(tree, tvi.hItem, TVGN_CARET); - break; - } - } - while ((tvi.hItem = TreeView_GetNextSibling(tree, tvi.hItem)) != nullptr); - } -} - -INT_PTR DialogManage::TabSkins::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return OnCommand(wParam, lParam); - - case WM_NOTIFY: - return OnNotify(wParam, lParam); - } - - return FALSE; -} - -INT_PTR DialogManage::TabSkins::OnCommand(WPARAM wParam, LPARAM lParam) -{ - if (!m_HandleCommands) - { - // Values are being changed/reset, no need to apply changes. - return FALSE; - } - - switch (LOWORD(wParam)) - { - case Id_ActiveSkinsButton: - { - HMENU menu = CreatePopupMenu(); - - // Add active skins to menu - std::map::const_iterator iter = Rainmeter::GetInstance().GetAllMeterWindows().begin(); - int index = 0; - for ( ; iter != Rainmeter::GetInstance().GetAllMeterWindows().end(); ++iter) - { - std::wstring name = ((*iter).second)->GetFolderPath() + L'\\'; - name += ((*iter).second)->GetFileName(); - InsertMenu(menu, index, MF_BYPOSITION, ID_CONFIG_FIRST + index, name.c_str()); - ++index; - } - - if (index > 0) - { - RECT r; - GetWindowRect((HWND)lParam, &r); - - // Show context menu - TrackPopupMenu( - menu, - TPM_RIGHTBUTTON | TPM_LEFTALIGN, - (*GetString(ID_STR_ISRTL) == L'1') ? r.right : r.left, - --r.bottom, - 0, - m_Window, - nullptr - ); - } - - DestroyMenu(menu); - } - break; - - case Id_CreateSkinPackageButton: - { - std::wstring file = Rainmeter::GetInstance().GetPath() + L"SkinInstaller.exe"; - CommandHandler::RunFile(file.c_str(), L"/Packager"); - } - break; - - case Id_LoadButton: - { - if (!m_SkinWindow) - { - // Skin not active, load - const SkinRegistry::Indexes indexes = - Rainmeter::GetInstance().m_SkinRegistry.FindIndexes(m_SkinFolderPath, m_SkinFileName); - if (indexes.IsValid()) - { - m_HandleCommands = false; - Rainmeter::GetInstance().ActivateSkin(indexes.folder, indexes.file); - m_HandleCommands = true; - - // Fake selection change to update controls - NMHDR nm; - nm.code = TVN_SELCHANGED; - nm.idFrom = Id_SkinsTreeView; - nm.hwndFrom = GetControl(Id_SkinsTreeView); - OnNotify(0, (LPARAM)&nm); - } - } - else - { - m_HandleCommands = false; - Rainmeter::GetInstance().DeactivateSkin(m_SkinWindow, -1); - } - } - break; - - case Id_RefreshButton: - if (m_SkinWindow) - { - m_SkinWindow->Refresh(false); - } - break; - - case Id_EditButton: - Rainmeter::GetInstance().EditSkinFile(m_SkinFolderPath, m_SkinFileName); - break; - - case Id_XPositionEdit: - if (HIWORD(wParam) == EN_CHANGE) - { - WCHAR buffer[32]; - m_IgnoreUpdate = true; - int x = (GetWindowText((HWND)lParam, buffer, 32) > 0) ? _wtoi(buffer) : 0; - m_SkinWindow->MoveWindow(x, m_SkinWindow->GetY()); - - if (x > m_SkinWindow->GetX()) - { - _itow_s(m_SkinWindow->GetX(), buffer, 10); - Edit_SetText((HWND)lParam, buffer); - } - } - break; - - case Id_YPositionEdit: - if (HIWORD(wParam) == EN_CHANGE) - { - WCHAR buffer[32]; - m_IgnoreUpdate = true; - int y = (GetWindowText((HWND)lParam, buffer, 32) > 0) ? _wtoi(buffer) : 0; - m_SkinWindow->MoveWindow(m_SkinWindow->GetX(), y); - - if (y > m_SkinWindow->GetY()) - { - _itow_s(m_SkinWindow->GetY(), buffer, 10); - Edit_SetText((HWND)lParam, buffer); - } - } - break; - - case Id_LoadOrderEdit: - if (HIWORD(wParam) == EN_CHANGE) - { - if (m_IgnoreUpdate) - { - // To avoid infinite loop after setting value below - m_IgnoreUpdate = false; - } - else - { - // Convert text to number and set it to get rid of extra chars - WCHAR buffer[32]; - int len = GetWindowText((HWND)lParam, buffer, 32); - if ((len == 0) || (len == 1 && buffer[0] == L'-')) - { - // Ignore if empty or if - is only char - break; - } - - // Get selection - DWORD sel = Edit_GetSel((HWND)lParam); - - // Reset value (to get rid of invalid chars) - m_IgnoreUpdate = true; - int value = _wtoi(buffer); - - _itow_s(value, buffer, 10); - SetWindowText((HWND)lParam, buffer); - - // Reset selection - Edit_SetSel((HWND)lParam, LOWORD(sel), HIWORD(sel)); - - WritePrivateProfileString(m_SkinFolderPath.c_str(), L"LoadOrder", buffer, Rainmeter::GetInstance().GetIniFile().c_str()); - const SkinRegistry::Indexes indexes = Rainmeter::GetInstance().m_SkinRegistry.FindIndexes( - m_SkinWindow->GetFolderPath(), m_SkinWindow->GetFileName()); - if (indexes.IsValid()) - { - Rainmeter::GetInstance().SetLoadOrder(indexes.folder, value); - - std::multimap windows; - Rainmeter::GetInstance().GetMeterWindowsByLoadOrder(windows); - - System::PrepareHelperWindow(); - - // Reorder window z-position to reflect load order - std::multimap::const_iterator iter = windows.begin(); - for ( ; iter != windows.end(); ++iter) - { - MeterWindow* mw = (*iter).second; - mw->ChangeZPos(mw->GetWindowZPosition(), true); - } - } - } - } - break; - - case Id_DisplayMonitorButton: - { - static const MenuTemplate s_Menu[] = - { - MENU_ITEM(IDM_SKIN_MONITOR_PRIMARY, ID_STR_USEDEFAULTMONITOR), - MENU_ITEM(ID_MONITOR_FIRST, ID_STR_VIRTUALSCREEN), - MENU_SEPARATOR(), - MENU_SEPARATOR(), - MENU_ITEM(IDM_SKIN_MONITOR_AUTOSELECT, ID_STR_AUTOSELECTMONITOR) - }; - - HMENU menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); - if (menu) - { - ContextMenu::CreateMonitorMenu(menu, m_SkinWindow); - - RECT r; - GetWindowRect((HWND)lParam, &r); - - // Show context menu - TrackPopupMenu( - menu, - TPM_RIGHTBUTTON | TPM_LEFTALIGN, - (*GetString(ID_STR_ISRTL) == L'1') ? r.right : r.left, - --r.bottom, - 0, - m_Window, - nullptr - ); - - DestroyMenu(menu); - } - } - break; - - case Id_DraggableCheckBox: - m_IgnoreUpdate = true; - m_SkinWindow->SetWindowDraggable(!m_SkinWindow->GetWindowDraggable()); - break; - - case Id_ClickThroughCheckBox: - m_IgnoreUpdate = true; - m_SkinWindow->SetClickThrough(!m_SkinWindow->GetClickThrough()); - break; - - case Id_KeepOnScreenCheckBox: - m_IgnoreUpdate = true; - m_SkinWindow->SetKeepOnScreen(!m_SkinWindow->GetKeepOnScreen()); - break; - - case Id_SavePositionCheckBox: - m_IgnoreUpdate = true; - m_SkinWindow->SetSavePosition(!m_SkinWindow->GetSavePosition()); - break; - - case Id_SnapToEdgesCheckBox: - m_IgnoreUpdate = true; - m_SkinWindow->SetSnapEdges(!m_SkinWindow->GetSnapEdges()); - break; - - case Id_ZPositionDropDownList: - if (HIWORD(wParam) == CBN_SELCHANGE) - { - m_IgnoreUpdate = true; - ZPOSITION zpos = (ZPOSITION)(ComboBox_GetCurSel((HWND)lParam) - 2); - m_SkinWindow->SetWindowZPosition(zpos); - } - break; - - case Id_TransparencyDropDownList: - if (HIWORD(wParam) == CBN_SELCHANGE) - { - m_IgnoreUpdate = true; - int sel = ComboBox_GetCurSel((HWND)lParam) + IDM_SKIN_TRANSPARENCY_0; - SendMessage(m_SkinWindow->GetWindow(), WM_COMMAND, sel, 0); - } - break; - - case Id_OnHoverDropDownList: - if (HIWORD(wParam) == CBN_SELCHANGE) - { - m_IgnoreUpdate = true; - HIDEMODE hide = (HIDEMODE)ComboBox_GetCurSel((HWND)lParam); - m_SkinWindow->SetWindowHide(hide); - } - break; - - case IDM_MANAGESKINSMENU_EXPAND: - { - HWND tree = GetControl(Id_SkinsTreeView); - HTREEITEM item = TreeView_GetSelection(tree); - TreeView_Expand(tree, item, TVE_TOGGLE); - } - break; - - case IDM_MANAGESKINSMENU_OPENFOLDER: - { - HWND tree = GetControl(Id_SkinsTreeView); - Rainmeter::GetInstance().OpenSkinFolder(GetTreeSelectionPath(tree)); - } - break; - - default: - if (wParam >= ID_CONFIG_FIRST && wParam <= ID_CONFIG_LAST) - { - std::map::const_iterator iter = Rainmeter::GetInstance().GetAllMeterWindows().begin(); - int index = (int)wParam - ID_CONFIG_FIRST; - int i = 0; - for ( ; iter != Rainmeter::GetInstance().GetAllMeterWindows().end(); ++iter) - { - if (i == index) - { - std::wstring name = ((*iter).second)->GetFolderPath() + L'\\'; - name += ((*iter).second)->GetFileName(); - - HWND item = GetControl(Id_SkinsTreeView); - SelectTreeItem(item, TreeView_GetRoot(item), name.c_str()); - break; - } - - ++i; - } - } - else if (wParam == IDM_SKIN_MONITOR_AUTOSELECT || - wParam == IDM_SKIN_MONITOR_PRIMARY || - wParam >= ID_MONITOR_FIRST && wParam <= ID_MONITOR_LAST) - { - if (m_SkinWindow) - { - SendMessage(m_SkinWindow->GetWindow(), WM_COMMAND, wParam, 0); - } - break; - } - - return 1; - } - - return 0; -} - -INT_PTR DialogManage::TabSkins::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->code) - { - case NM_CLICK: - if (nm->idFrom == Id_AddMetadataLink) - { - std::wstring file = Rainmeter::GetInstance().GetSkinPath() + m_SkinFolderPath; - file += L'\\'; - file += m_SkinFileName; - const WCHAR* str = L"\r\n" // Hack to add below [Rainmeter]. - L"[Metadata]\r\n" - L"Name=\r\n" - L"Author=\r\n" - L"Information=\r\n" - L"License=\r\n" - L"Version"; - WritePrivateProfileString(L"Rainmeter", str, L"", file.c_str()); - SendMessage(m_Window, WM_COMMAND, MAKEWPARAM(Id_EditButton, 0), 0); - ShowWindow(nm->hwndFrom, SW_HIDE); - } - break; - - case NM_DBLCLK: - if (nm->idFrom == Id_SkinsTreeView && !m_SkinFileName.empty()) - { - OnCommand(MAKEWPARAM(Id_LoadButton, 0), 0); - } - break; - - case NM_RCLICK: - if (nm->idFrom == Id_SkinsTreeView) - { - POINT pt = System::GetCursorPosition(); - - TVHITTESTINFO ht; - ht.pt = pt; - ScreenToClient(nm->hwndFrom, &ht.pt); - - if (TreeView_HitTest(nm->hwndFrom, &ht) && !(ht.flags & TVHT_NOWHERE)) - { - TreeView_SelectItem(nm->hwndFrom, ht.hItem); - - TVITEM tvi = {0}; - tvi.hItem = TreeView_GetSelection(nm->hwndFrom); - tvi.mask = TVIF_STATE; - - if (TreeView_GetItem(nm->hwndFrom, &tvi)) - { - HMENU menu = nullptr; - MENUITEMINFO mii = {0}; - mii.cbSize = sizeof(MENUITEMINFO); - mii.fMask = MIIM_STRING; - - if (m_SkinFileName.empty()) - { - // Folder menu. - static const MenuTemplate s_Menu[] = - { - MENU_ITEM(IDM_MANAGESKINSMENU_EXPAND, ID_STR_EXPAND), - MENU_ITEM(IDM_MANAGESKINSMENU_OPENFOLDER, ID_STR_OPENFOLDER), - }; - - menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); - SetMenuDefaultItem(menu, IDM_MANAGESKINSMENU_EXPAND, MF_BYCOMMAND); - - if (tvi.state & TVIS_EXPANDED) - { - mii.dwTypeData = GetString(ID_STR_COLLAPSE); - SetMenuItemInfo(menu, IDM_MANAGESKINSMENU_EXPAND, MF_BYCOMMAND, &mii); - } - } - else - { - // Skin menu. - static const MenuTemplate s_Menu[] = - { - MENU_ITEM(IDM_MANAGESKINSMENU_LOAD, ID_STR_LOAD), - MENU_ITEM(IDM_MANAGESKINSMENU_REFRESH, ID_STR_REFRESH), - MENU_ITEM(IDM_MANAGESKINSMENU_EDIT, ID_STR_EDIT), - }; - - menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); - SetMenuDefaultItem(menu, IDM_MANAGESKINSMENU_LOAD, MF_BYCOMMAND); - - if (m_SkinWindow) - { - mii.dwTypeData = GetString(ID_STR_UNLOAD); - SetMenuItemInfo(menu, IDM_MANAGESKINSMENU_LOAD, MF_BYCOMMAND, &mii); - } - else - { - EnableMenuItem(menu, IDM_MANAGESKINSMENU_REFRESH, MF_BYCOMMAND | MF_GRAYED); - } - } - - // Show context menu - TrackPopupMenu( - menu, - TPM_RIGHTBUTTON | TPM_LEFTALIGN, - pt.x, - pt.y, - 0, - m_Window, - nullptr - ); - - DestroyMenu(menu); - } - } - } - break; - - case TVN_SELCHANGED: - if (nm->idFrom == Id_SkinsTreeView) - { - m_SkinWindow = nullptr; - m_SkinFileName.clear(); - m_SkinFolderPath.clear(); - - // Temporarily disable handling commands - m_HandleCommands = false; - - WCHAR buffer[MAX_PATH]; - - // Get current selection name - TVITEM tvi = {0}; - tvi.hItem = TreeView_GetSelection(nm->hwndFrom); - tvi.mask = TVIF_TEXT | TVIF_CHILDREN; - tvi.pszText = buffer; - tvi.cchTextMax = MAX_PATH; - TreeView_GetItem(nm->hwndFrom, &tvi); - - if (tvi.cChildren == 0) - { - // Current selection is file - m_SkinFileName = buffer; - tvi.mask = TVIF_TEXT; - - // Loop through parents to get skin folder - m_SkinFolderPath.clear(); - while ((tvi.hItem = TreeView_GetParent(nm->hwndFrom, tvi.hItem)) != nullptr) - { - TreeView_GetItem(nm->hwndFrom, &tvi); - m_SkinFolderPath.insert(0, 1, L'\\'); - m_SkinFolderPath.insert(0, buffer); - } - - m_SkinFolderPath.resize(m_SkinFolderPath.length() - 1); // Get rid of trailing slash - - ReadSkin(); - } - else - { - DisableControls(true); - } - - m_HandleCommands = true; - } - break; - - default: - return FALSE; - } - - return TRUE; -} - -// ----------------------------------------------------------------------------------------------- -// -// Layouts tab -// -// ----------------------------------------------------------------------------------------------- - -/* -** Constructor. -** -*/ -DialogManage::TabLayouts::TabLayouts() : Tab() -{ -} - -void DialogManage::TabLayouts::Create(HWND owner) -{ - Tab::CreateTabWindow(15, 30, 470, 260, owner); - - static const ControlTemplate::Control s_Controls[] = - { - CT_GROUPBOX(-1, ID_STR_SAVENEWTHEME, - 0, 0, 230, 150, - WS_VISIBLE, 0), - CT_LABEL(-1, ID_STR_THEMEDESCRIPTION, - 6, 16, 205, 44, - WS_VISIBLE, 0), - CT_CHECKBOX(Id_SaveEmptyThemeCheckBox, ID_STR_SAVEASEMPTYTHEME, - 6, 70, 220, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_ExcludeUnusedSkinsCheckBox, ID_STR_EXCLUDEUNUSEDSKINS, - 6, 83, 220, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_IncludeWallpaperCheckBox, ID_STR_INCLUDEWALLPAPER, - 6, 96, 220, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_LABEL(-1, ID_STR_NAMESC, - 6, 115, 100, 9, - WS_VISIBLE, 0), - CT_EDIT(Id_NameLabel, 0, - 6, 128, 162, 14, - WS_VISIBLE | WS_TABSTOP, WS_EX_CLIENTEDGE), - CT_BUTTON(Id_SaveButton, ID_STR_SAVE, - 172, 128, 50, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - - CT_GROUPBOX(-1, ID_STR_SAVEDTHEMES, - 238, 0, 230, 150, - WS_VISIBLE, 0), - CT_LISTBOX(Id_List, 0, - 244, 16, 160, 125, - WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_SORT | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT, WS_EX_CLIENTEDGE), - CT_BUTTON(Id_LoadButton, ID_STR_LOAD, - 410, 16, 50, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_BUTTON(Id_EditButton, ID_STR_EDIT, - 410, 34, 50, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), - CT_BUTTON(Id_DeleteButton, ID_STR_DELETE, - 410, 52, 50, 14, - WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0) - }; - - CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); -} - -void DialogManage::TabLayouts::Initialize() -{ - HWND item = GetControl(Id_List); - ListBox_ResetContent(item); - const std::vector& layouts = Rainmeter::GetInstance().GetAllLayouts(); - for (size_t i = 0, isize = layouts.size(); i < isize; ++i) - { - ListBox_AddString(item, layouts[i].c_str()); - } - - m_Initialized = true; -} - -void DialogManage::TabLayouts::Update() -{ - Initialize(); -} - -INT_PTR DialogManage::TabLayouts::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return OnCommand(wParam, lParam); - } - - return FALSE; -} - -INT_PTR DialogManage::TabLayouts::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case Id_SaveEmptyThemeCheckBox: - { - BOOL state = !(Button_GetCheck((HWND)lParam) == BST_CHECKED); - - HWND item = GetControl(Id_ExcludeUnusedSkinsCheckBox); - EnableWindow(item, state); - Button_SetCheck(item, BST_UNCHECKED); - - item = GetControl(Id_IncludeWallpaperCheckBox); - EnableWindow(item, state); - Button_SetCheck(item, BST_UNCHECKED); - } - break; - - case Id_NameLabel: - if (HIWORD(wParam) == EN_CHANGE) - { - WCHAR buffer[32]; - int len = Edit_GetText((HWND)lParam, buffer, 32); - - // Disable save button if no text or if backup - BOOL state = (len > 0 && _wcsicmp(buffer, L"@Backup") != 0); - EnableWindow(GetControl(Id_SaveButton), state); - } - break; - - case Id_List: - if (HIWORD(wParam) == LBN_SELCHANGE) - { - // Ignore clicks that don't hit items - if (ListBox_GetCurSel((HWND)lParam) != LB_ERR) - { - HWND item = GetControl(Id_LoadButton); - EnableWindow(item, TRUE); - item = GetControl(Id_DeleteButton); - EnableWindow(item, TRUE); - item = GetControl(Id_EditButton); - EnableWindow(item, TRUE); - - const std::vector& layouts = Rainmeter::GetInstance().GetAllLayouts(); - item = GetControl(Id_List); - int sel = ListBox_GetCurSel(item); - - item = GetControl(Id_NameLabel); - Edit_SetText(item, layouts[sel].c_str()); - } - } - break; - - case Id_SaveButton: - { - WCHAR buffer[MAX_PATH]; - HWND item = GetControl(Id_NameLabel); - Edit_GetText(item, buffer, MAX_PATH); - - std::wstring layout = buffer; - std::wstring path = Rainmeter::GetInstance().GetLayoutPath(); - CreateDirectory(path.c_str(), 0); - - path += layout; - bool alreadyExists = (_waccess(path.c_str(), 0) != -1); - if (alreadyExists) - { - std::wstring text = GetFormattedString(ID_STR_THEMEALREADYEXISTS, layout.c_str()); - if (Rainmeter::GetInstance().ShowMessage(m_Window, text.c_str(), MB_ICONWARNING | MB_YESNO) != IDYES) - { - // Cancel - break; - } - } - else - { - // Make sure path exists - CreateDirectory(path.c_str(), nullptr); - } - - path += L"\\Rainmeter.ini"; - - item = GetControl(Id_SaveEmptyThemeCheckBox); - if (Button_GetCheck(item) != BST_CHECKED) - { - if (!System::CopyFiles(Rainmeter::GetInstance().GetIniFile(), path)) - { - std::wstring text = GetFormattedString(ID_STR_THEMESAVEFAIL, path.c_str()); - Rainmeter::GetInstance().ShowMessage(m_Window, text.c_str(), MB_OK | MB_ICONERROR); - break; - } - - // Exclude unused skins - item = GetControl(Id_ExcludeUnusedSkinsCheckBox); - if (Button_GetCheck(item) == BST_CHECKED) - { - ConfigParser parser; - parser.Initialize(path); - - // Remove sections with Active=0 - std::list::const_iterator iter = parser.GetSections().begin(); - for ( ; iter != parser.GetSections().end(); ++iter) - { - if (parser.GetValue(*iter, L"Active", L"") == L"0") - { - WritePrivateProfileString((*iter).c_str(), nullptr, nullptr, path.c_str()); - } - } - } - - // Save wallpaper - item = GetControl(Id_IncludeWallpaperCheckBox); - if (Button_GetCheck(item) == BST_CHECKED) - { - // Get current wallpaper - if (SystemParametersInfo(SPI_GETDESKWALLPAPER, MAX_PATH, &buffer, 0)) - { - std::wstring::size_type pos = path.find_last_of(L'\\'); - path.replace(pos + 1, path.length() - pos - 1, L"Wallpaper.bmp"); - System::CopyFiles((std::wstring)buffer, path); - } - } - } - else - { - // Create empty layout - HANDLE file = CreateFile(path.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - if (file == INVALID_HANDLE_VALUE) - { - std::wstring text = GetFormattedString(ID_STR_THEMESAVEFAIL, path.c_str()); - Rainmeter::GetInstance().ShowMessage(m_Window, text.c_str(), MB_OK | MB_ICONERROR); - break; - } - - CloseHandle(file); - } - - if (!alreadyExists) - { - item = GetControl(Id_List); - ListBox_AddString(item, layout.c_str()); - - Rainmeter::GetInstance().ScanForLayouts(); - } - } - break; - - case Id_LoadButton: - { - HWND item = GetControl(Id_List); - int sel = ListBox_GetCurSel(item); - Rainmeter::GetInstance().LoadLayout(Rainmeter::GetInstance().m_Layouts[sel]); - } - break; - - case Id_EditButton: - { - HWND item = GetControl(Id_List); - int sel = ListBox_GetCurSel(item); - const std::vector& layouts = Rainmeter::GetInstance().GetAllLayouts(); - - std::wstring args = L"\"" + Rainmeter::GetInstance().GetLayoutPath(); - args += layouts[sel]; - args += L"\\Rainmeter.ini"; - args += L'"'; - CommandHandler::RunFile(Rainmeter::GetInstance().GetSkinEditor().c_str(), args.c_str()); - } - break; - - case Id_DeleteButton: - { - HWND item = GetControl(Id_List); - int sel = ListBox_GetCurSel(item); - std::vector& layouts = const_cast&>(Rainmeter::GetInstance().GetAllLayouts()); - - std::wstring text = GetFormattedString(ID_STR_THEMEDELETE, layouts[sel].c_str()); - if (Rainmeter::GetInstance().ShowMessage(m_Window, text.c_str(), MB_ICONQUESTION | MB_YESNO) != IDYES) - { - // Cancel - break; - } - - std::wstring folder = Rainmeter::GetInstance().GetLayoutPath(); - folder += layouts[sel]; - - if (System::RemoveFolder(folder)) - { - ListBox_DeleteString(item, sel); - - // Remove layout from vector - std::vector::iterator iter = layouts.begin(); - for ( ; iter != layouts.end(); ++iter) - { - if (wcscmp(layouts[sel].c_str(), (*iter).c_str()) == 0) - { - layouts.erase(iter); - break; - } - } - - EnableWindow(GetControl(Id_LoadButton), FALSE); - EnableWindow(GetControl(Id_DeleteButton), FALSE); - EnableWindow(GetControl(Id_EditButton), FALSE); - } - } - break; - - default: - return 1; - } - - return 0; -} - -// ----------------------------------------------------------------------------------------------- -// -// Settings tab -// -// ----------------------------------------------------------------------------------------------- - -/* -** Constructor. -** -*/ -DialogManage::TabSettings::TabSettings() : Tab() -{ -} - -void DialogManage::TabSettings::Create(HWND owner) -{ - Tab::CreateTabWindow(15, 30, 470, 260, owner); - - // FIXME: Temporary hack. - short buttonWidth = (short)_wtoi(GetString(ID_STR_NUM_BUTTONWIDTH)); - - const ControlTemplate::Control s_Controls[] = - { - CT_GROUPBOX(-1, ID_STR_GENERAL, - 0, 0, 468, 131, - WS_VISIBLE, 0), - CT_LABEL(-1, ID_STR_LANGUAGESC, - 6, 16, 107, 14, - WS_VISIBLE, 0), - CT_COMBOBOX(Id_LanguageDropDownList, 0, - 107, 13, 222, 14, - WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL, 0), - CT_LABEL(-1, ID_STR_EDITORSC, - 6, 37, 107, 9, - WS_VISIBLE, 0), - CT_EDIT(Id_EditorEdit, 0, - 107, 34, 222, 14, - WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL | ES_READONLY, WS_EX_CLIENTEDGE), - CT_BUTTON(Id_EditorBrowseButton, ID_STR_ELLIPSIS, - 333, 34, 25, 14, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_CheckForUpdatesCheckBox, ID_STR_CHECKFORUPDATES, - 6, 55, 200, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_LockSkinsCheckBox, ID_STR_DISABLEDRAGGING, - 6, 68, 200, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_ShowTrayIconCheckBox, ID_STR_SHOWNOTIFICATIONAREAICON, - 6, 81, 200, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_UseD2DCheckBox, ID_STR_USED2D, - 6, 94, 200, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_ResetStatisticsButton, ID_STR_RESETSTATISTICS, - 6, 110, buttonWidth + 20, 14, - WS_VISIBLE | WS_TABSTOP, 0), - - CT_GROUPBOX(-1, ID_STR_LOGGING, - 0, 138, 468, 66, - WS_VISIBLE, 0), - CT_CHECKBOX(Id_VerboseLoggingCheckbox, ID_STR_DEBUGMODE, - 6, 154, 200, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_CHECKBOX(Id_LogToFileCheckBox, ID_STR_LOGTOFILE, - 6, 167, 200, 9, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_ShowLogFileButton, ID_STR_SHOWLOGFILE, - 6, 183, buttonWidth + 20, 14, - WS_VISIBLE | WS_TABSTOP, 0), - CT_BUTTON(Id_DeleteLogFileButton, ID_STR_DELETELOGFILE, - buttonWidth + 30, 183, buttonWidth + 20, 14, - WS_VISIBLE | WS_TABSTOP, 0) - }; - - CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); -} - -void DialogManage::TabSettings::Initialize() -{ - // Scan for languages - HWND item = GetControl(Id_LanguageDropDownList); - - std::wstring files = Rainmeter::GetInstance().GetPath() + L"Languages\\*.dll"; - WIN32_FIND_DATA fd; - HANDLE hSearch = FindFirstFile(files.c_str(), &fd); - if (hSearch != INVALID_HANDLE_VALUE) - { - do - { - WCHAR* pos = wcschr(fd.cFileName, L'.'); - if (pos) - { - LCID lcid = (LCID)wcstoul(fd.cFileName, &pos, 10); - if (pos != fd.cFileName && - _wcsicmp(pos, L".dll") == 0 && - GetLocaleInfo(lcid, LOCALE_SENGLISHLANGUAGENAME, fd.cFileName, MAX_PATH) > 0) - { - // Strip brackets in language name - std::wstring text = fd.cFileName; - text += L" - "; - - GetLocaleInfo(lcid, LOCALE_SNATIVEDISPLAYNAME, fd.cFileName, MAX_PATH); - text += fd.cFileName; - - int index = ComboBox_AddString(item, text.c_str()); - ComboBox_SetItemData(item, index, (LPARAM)lcid); - - if (lcid == Rainmeter::GetInstance().GetResourceLCID()) - { - ComboBox_SetCurSel(item, index); - } - } - } - } - while (FindNextFile(hSearch, &fd)); - - FindClose(hSearch); - } - - Button_SetCheck(GetControl(Id_CheckForUpdatesCheckBox), !Rainmeter::GetInstance().GetDisableVersionCheck()); - Button_SetCheck(GetControl(Id_LockSkinsCheckBox), Rainmeter::GetInstance().GetDisableDragging()); - Button_SetCheck(GetControl(Id_LogToFileCheckBox), GetLogger().IsLogToFile()); - Button_SetCheck(GetControl(Id_VerboseLoggingCheckbox), Rainmeter::GetInstance().GetDebug()); - - BOOL isLogFile = (_waccess(GetLogger().GetLogFilePath().c_str(), 0) != -1); - EnableWindow(GetControl(Id_ShowLogFileButton), isLogFile); - EnableWindow(GetControl(Id_DeleteLogFileButton), isLogFile); - - Edit_SetText(GetControl(Id_EditorEdit), Rainmeter::GetInstance().GetSkinEditor().c_str()); - - bool iconEnabled = Rainmeter::GetInstance().GetTrayWindow()->IsTrayIconEnabled(); - Button_SetCheck(GetControl(Id_ShowTrayIconCheckBox), iconEnabled); - - if (IsWindowsVistaOrGreater()) - { - Button_SetCheck(GetControl(Id_UseD2DCheckBox), Rainmeter::GetInstance().GetUseD2D()); - } - else - { - Button_Enable(GetControl(Id_UseD2DCheckBox), FALSE); - } - - m_Initialized = true; -} - -INT_PTR DialogManage::TabSettings::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return OnCommand(wParam, lParam); - } - - return FALSE; -} - -INT_PTR DialogManage::TabSettings::OnCommand(WPARAM wParam, LPARAM lParam) -{ - if (!m_Initialized) - { - return FALSE; - } - - switch (LOWORD(wParam)) - { - case Id_LanguageDropDownList: - if (HIWORD(wParam) == CBN_SELCHANGE) - { - int sel = ComboBox_GetCurSel((HWND)lParam); - LCID lcid = (LCID)ComboBox_GetItemData((HWND)lParam, sel); - if (lcid != Rainmeter::GetInstance().m_ResourceLCID) - { - WCHAR buffer[16]; - _ultow(lcid, buffer, 10); - WritePrivateProfileString(L"Rainmeter", L"Language", buffer, Rainmeter::GetInstance().GetIniFile().c_str()); - - std::wstring resource = Rainmeter::GetInstance().GetPath() + L"Languages\\"; - resource += buffer; - resource += L".dll"; - FreeLibrary(Rainmeter::GetInstance().m_ResourceInstance); - Rainmeter::GetInstance().m_ResourceInstance = LoadLibraryEx(resource.c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); - Rainmeter::GetInstance().m_ResourceLCID = lcid; - - if (DialogAbout::GetDialog()) - { - int sel = TabCtrl_GetCurSel(DialogAbout::GetDialog()->GetControl(DialogManage::Id_Tab)); - SendMessage(DialogAbout::GetDialog()->GetWindow(), WM_CLOSE, 0, 0); - if (sel == 0) - { - Rainmeter::GetInstance().DelayedExecuteCommand(L"!About"); - } - else if (sel == 1) - { - Rainmeter::GetInstance().DelayedExecuteCommand(L"!About Skins"); - } - else if (sel == 2) - { - Rainmeter::GetInstance().DelayedExecuteCommand(L"!About Plugins"); - } - else //if (sel == 3) - { - Rainmeter::GetInstance().DelayedExecuteCommand(L"!About Version"); - } - } - - SendMessage(c_Dialog->GetWindow(), WM_CLOSE, 0, 0); - Rainmeter::GetInstance().DelayedExecuteCommand(L"!Manage Settings"); - } - } - break; - - case Id_CheckForUpdatesCheckBox: - Rainmeter::GetInstance().SetDisableVersionCheck(!Rainmeter::GetInstance().GetDisableVersionCheck()); - break; - - case Id_LockSkinsCheckBox: - Rainmeter::GetInstance().SetDisableDragging(!Rainmeter::GetInstance().GetDisableDragging()); - break; - - case Id_ResetStatisticsButton: - Rainmeter::GetInstance().ResetStats(); - break; - - case Id_ShowLogFileButton: - Rainmeter::GetInstance().ShowLogFile(); - break; - - case Id_DeleteLogFileButton: - GetLogger().DeleteLogFile(); - if (_waccess(GetLogger().GetLogFilePath().c_str(), 0) == -1) - { - Button_SetCheck(GetControl(Id_LogToFileCheckBox), BST_UNCHECKED); - EnableWindow(GetControl(Id_ShowLogFileButton), FALSE); - EnableWindow(GetControl(Id_DeleteLogFileButton), FALSE); - } - break; - - case Id_LogToFileCheckBox: - if (GetLogger().IsLogToFile()) - { - GetLogger().StopLogFile(); - } - else - { - GetLogger().StartLogFile(); - if (_waccess(GetLogger().GetLogFilePath().c_str(), 0) != -1) - { - EnableWindow(GetControl(Id_ShowLogFileButton), TRUE); - EnableWindow(GetControl(Id_DeleteLogFileButton), TRUE); - } - } - break; - - case Id_VerboseLoggingCheckbox: - Rainmeter::GetInstance().SetDebug(!Rainmeter::GetInstance().GetDebug()); - break; - - case Id_EditorEdit: - if (HIWORD(wParam) == EN_CHANGE) - { - WCHAR buffer[MAX_PATH]; - if (GetWindowText((HWND)lParam, buffer, _countof(buffer)) > 0) - { - Rainmeter::GetInstance().SetSkinEditor(buffer); - } - } - break; - - case Id_EditorBrowseButton: - { - WCHAR buffer[MAX_PATH]; - buffer[0] = L'\0'; - - std::wstring editor = Rainmeter::GetInstance().GetSkinEditor(); - editor = editor.substr(0, editor.find_last_of(L"/\\")).c_str(); - - OPENFILENAME ofn = { sizeof(OPENFILENAME) }; - ofn.Flags = OFN_FILEMUSTEXIST; - ofn.lpstrFilter = L"Executable File (.exe)\0*.exe"; - ofn.lpstrTitle = L"Select executable file"; - ofn.lpstrDefExt = L"exe"; - ofn.lpstrInitialDir = editor.c_str(); - ofn.nFilterIndex = 0; - ofn.lpstrFile = buffer; - ofn.nMaxFile = _countof(buffer); - ofn.hwndOwner = c_Dialog->GetWindow(); - - if (!GetOpenFileName(&ofn)) - { - break; - } - - Edit_SetText(GetControl(Id_EditorEdit), buffer); - } - break; - - case Id_ShowTrayIconCheckBox: - Rainmeter::GetInstance().GetTrayWindow()->SetTrayIcon(!Rainmeter::GetInstance().GetTrayWindow()->IsTrayIconEnabled()); - break; - - case Id_UseD2DCheckBox: - Rainmeter::GetInstance().SetUseD2D(!Rainmeter::GetInstance().GetUseD2D()); - break; - - default: - return 1; - } - - return 0; +/* + Copyright (C) 2011 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../Common/MenuTemplate.h" +#include "Rainmeter.h" +#include "System.h" +#include "MeterWindow.h" +#include "TrayWindow.h" +#include "Measure.h" +#include "resource.h" +#include "DialogManage.h" +#include "DialogAbout.h" +#include "../Version.h" +#include + +WINDOWPLACEMENT DialogManage::c_WindowPlacement = {0}; +DialogManage* DialogManage::c_Dialog = nullptr; + +/* +** Constructor. +** +*/ +DialogManage::DialogManage() : Dialog() +{ +} + +/* +** Destructor. +** +*/ +DialogManage::~DialogManage() +{ +} + +/* +** Opens the Manage dialog by tab name. +** +*/ +void DialogManage::Open(const WCHAR* name) +{ + int tab = 0; + + if (name) + { + if (_wcsicmp(name, L"Layouts") == 0 || + _wcsicmp(name, L"Themes") == 0) // For backwards compatibility. + { + tab = 1; + } + else if (_wcsicmp(name, L"Settings") == 0) + { + tab = 2; + } + } + + Open(tab); +} + +/* +** Opens the Manage dialog. +** +*/ +void DialogManage::Open(int tab) +{ + if (!c_Dialog) + { + c_Dialog = new DialogManage(); + } + + c_Dialog->ShowDialogWindow( + GetString(ID_STR_MANAGERAINMETER), + 0, 0, 500, 322, + DS_CENTER | WS_POPUP | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU, + WS_EX_APPWINDOW | WS_EX_CONTROLPARENT | ((*GetString(ID_STR_ISRTL) == L'1') ? WS_EX_LAYOUTRTL : 0), + Rainmeter::GetInstance().GetWindow()); + + // Fake WM_NOTIFY to change tab + NMHDR nm; + nm.code = TCN_SELCHANGE; + nm.idFrom = Id_Tab; + nm.hwndFrom = c_Dialog->GetControl(Id_Tab); + TabCtrl_SetCurSel(nm.hwndFrom, tab); + c_Dialog->OnNotify(0, (LPARAM)&nm); +} + +/* +** Opens the Manage dialog Skins tab with skin selected. +** +*/ +void DialogManage::OpenSkin(MeterWindow* meterWindow) +{ + Open(); + + if (c_Dialog) + { + std::wstring name = meterWindow->GetFolderPath() + L'\\'; + name += meterWindow->GetFileName(); + + HWND item = c_Dialog->m_TabSkins.GetControl(TabSkins::Id_SkinsTreeView); + c_Dialog->m_TabSkins.SelectTreeItem(item, TreeView_GetRoot(item), name.c_str()); + } +} + +/* +** Opens the Manage dialog tab with parameters +** +*/ +void DialogManage::Open(const WCHAR* tabName, const WCHAR* param1, const WCHAR* param2) +{ + Open(tabName); + + if (c_Dialog) + { + // "Skins" tab + if (_wcsicmp(tabName, L"Skins") == 0) + { + // |param1| represents the config (ie. "illustro\Clock") + // |param2| represents the file (ie. "Clock.ini") + + std::wstring name = param1; + + if (param2) + { + name += L'\\'; + name += param2; + } + + HWND item = c_Dialog->m_TabSkins.GetControl(TabSkins::Id_SkinsTreeView); + c_Dialog->m_TabSkins.SelectTreeItem(item, TreeView_GetRoot(item), name.c_str()); + } + // Future use: Allow optional params for different tabs + //else if (_wcsicmp(tabName, L"Layouts") == 0) + } +} + +void DialogManage::UpdateSkins(MeterWindow* meterWindow, bool deleted) +{ + if (c_Dialog && c_Dialog->m_TabSkins.IsInitialized()) + { + c_Dialog->m_TabSkins.Update(meterWindow, deleted); + } +} + +void DialogManage::UpdateLayouts() +{ + if (c_Dialog && c_Dialog->m_TabLayouts.IsInitialized()) + { + c_Dialog->m_TabLayouts.Update(); + } +} + +Dialog::Tab& DialogManage::GetActiveTab() +{ + int sel = TabCtrl_GetCurSel(GetControl(Id_Tab)); + if (sel == 0) + { + return m_TabSkins; + } + else if (sel == 1) + { + return m_TabLayouts; + } + else // if (sel == 2) + { + return m_TabSettings; + } +} + +INT_PTR DialogManage::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_INITDIALOG: + return OnInitDialog(wParam, lParam); + + case WM_ACTIVATE: + return OnActivate(wParam, lParam); + + case WM_COMMAND: + return OnCommand(wParam, lParam); + + case WM_NOTIFY: + return OnNotify(wParam, lParam); + + case WM_CLOSE: + { + GetWindowPlacement(m_Window, &c_WindowPlacement); + if (c_WindowPlacement.showCmd == SW_SHOWMINIMIZED) + { + c_WindowPlacement.showCmd = SW_SHOWNORMAL; + } + + delete c_Dialog; + c_Dialog = nullptr; + } + return TRUE; + } + + return FALSE; +} + +INT_PTR DialogManage::OnInitDialog(WPARAM wParam, LPARAM lParam) +{ + // FIXME: Temporary hack. + short buttonWidth = (short)_wtoi(GetString(ID_STR_NUM_BUTTONWIDTH)); + + const ControlTemplate::Control s_Controls[] = + { + CT_BUTTON(Id_RefreshAllButton, ID_STR_REFRESHALL, + 5, 303, buttonWidth, 14, + WS_VISIBLE | WS_TABSTOP, 0), + CT_BUTTON(Id_EditSettingsButton, ID_STR_EDITSETTINGS, + buttonWidth + 9, 303, buttonWidth, 14, + WS_VISIBLE | WS_TABSTOP, 0), + CT_BUTTON(Id_OpenLogButton, ID_STR_OPENLOG, + buttonWidth + buttonWidth + 13, 303, buttonWidth, 14, + WS_VISIBLE | WS_TABSTOP, 0), + CT_BUTTON(Id_HelpButton, ID_STR_HELP, + 389, 303, 50, 14, + WS_VISIBLE | WS_TABSTOP, 0), + CT_BUTTON(Id_CloseButton, ID_STR_CLOSE, + 444, 303, 50, 14, + WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 0), + CT_TAB(Id_Tab, 0, + 6, 6, 488, 293, + WS_VISIBLE | WS_TABSTOP | TCS_FIXEDWIDTH, 0) // Last for correct tab order. + }; + + CreateControls(s_Controls, _countof(s_Controls), m_Font, GetString); + + HWND item = GetControl(Id_Tab); + m_TabSkins.Create(m_Window); + m_TabLayouts.Create(m_Window); + m_TabSettings.Create(m_Window); + + TCITEM tci = {0}; + tci.mask = TCIF_TEXT; + tci.pszText = GetString(ID_STR_SKINS); + TabCtrl_InsertItem(item, 0, &tci); + tci.pszText = GetString(ID_STR_THEMES); + TabCtrl_InsertItem(item, 1, &tci); + tci.pszText = GetString(ID_STR_SETTINGS); + TabCtrl_InsertItem(item, 2, &tci); + + HICON hIcon = GetIcon(IDI_RAINMETER); + SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); + + item = GetControl(Id_CloseButton); + SendMessage(m_Window, WM_NEXTDLGCTL, (WPARAM)item, TRUE); + + item = m_TabSkins.GetControl(TabSkins::Id_FileLabel); + SendMessage(item, WM_SETFONT, (WPARAM)m_FontBold, 0); + + if (IsWindowsVistaOrGreater()) + { + // Use arrows instead of plus/minus in the tree for Vista+ + item = m_TabSkins.GetControl(TabSkins::Id_SkinsTreeView); + SetWindowTheme(item, L"explorer", nullptr); + } + + if (c_WindowPlacement.length == 0) + { + c_WindowPlacement.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(m_Window, &c_WindowPlacement); + } + + SetWindowPlacement(m_Window, &c_WindowPlacement); + + return FALSE; +} + +INT_PTR DialogManage::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case Id_RefreshAllButton: + Rainmeter::GetInstance().RefreshAll(); + break; + + case Id_EditSettingsButton: + Rainmeter::GetInstance().EditSettings(); + break; + + case Id_OpenLogButton: + DialogAbout::Open(); + break; + + case Id_CloseButton: + HandleMessage(WM_CLOSE, 0, 0); + break; + + case Id_HelpButton: + { + std::wstring url = L"http://docs.rainmeter.net/manual/user-interface/manage#"; + + Tab& tab = GetActiveTab(); + if (&tab == &m_TabSkins) + { + url += L"Skins"; + } + else if (&tab == &m_TabLayouts) + { + url += L"Layouts"; + } + else // if (&tab == &m_TabSettings) + { + url += L"Settings"; + } + + url += L"Tab"; + ShellExecute(m_Window, L"open", url.c_str(), nullptr, nullptr, SW_SHOWNORMAL); + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +INT_PTR DialogManage::OnNotify(WPARAM wParam, LPARAM lParam) +{ + LPNMHDR nm = (LPNMHDR)lParam; + switch (nm->idFrom) + { + case Id_Tab: + if (nm->code == TCN_SELCHANGE) + { + // Disable all tab windows first + EnableWindow(m_TabSkins.GetWindow(), FALSE); + EnableWindow(m_TabLayouts.GetWindow(), FALSE); + EnableWindow(m_TabSettings.GetWindow(), FALSE); + + GetActiveTab().Activate(); + } + break; + + default: + return 1; + } + + return 0; +} + +// ----------------------------------------------------------------------------------------------- +// +// Skins tab +// +// ----------------------------------------------------------------------------------------------- + +/* +** Constructor. +** +*/ +DialogManage::TabSkins::TabSkins() : Tab(), + m_SkinWindow(), + m_HandleCommands(false), + m_IgnoreUpdate(false) +{ +} + +void DialogManage::TabSkins::Create(HWND owner) +{ + Tab::CreateTabWindow(15, 30, 470, 260, owner); + + // FIXME: Temporary hack. + short labelWidth = (short)_wtoi(GetString(ID_STR_NUM_LABELWIDTH)); + + const ControlTemplate::Control s_Controls[] = + { + CT_BUTTON(Id_ActiveSkinsButton, ID_STR_ACTIVESKINS, + 0, 0, 146, 14, + WS_VISIBLE | WS_TABSTOP, 0), + CT_TREEVIEW(Id_SkinsTreeView, 0, + 0, 18, 145, 221, + WS_VISIBLE | WS_TABSTOP | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_SHOWSELALWAYS | WS_VSCROLL, WS_EX_CLIENTEDGE), + CT_BUTTON(Id_CreateSkinPackageButton, ID_STR_CREATERMSKINPACKAGE, + 0, 244, 146, 14, + WS_VISIBLE | WS_TABSTOP, 0), + + CT_LABEL(Id_FileLabel, ID_STR_ELLIPSIS, + 165, 0, 130, 14, + WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), + CT_LABEL(Id_ConfigLabel, 0, + 165, 15, 130, 9, + WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), + CT_BUTTON(Id_LoadButton, ID_STR_LOAD, + 310, 0, 50, 14, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), + CT_BUTTON(Id_RefreshButton, ID_STR_REFRESH, + 364, 0, 50, 14, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), + CT_BUTTON(Id_EditButton, ID_STR_EDIT, + 418, 0, 50, 14, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), + + CT_LABEL(-1, ID_STR_AUTHORSC, + 165, 30, 80, 9, + WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), + CT_LABEL(Id_AuthorLabel, 0, + 230, 30, 245, 9, + WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), + CT_LABEL(-1, ID_STR_VERSIONSC, + 165, 43, 80, 9, + WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), + CT_LABEL(Id_VersionLabel, 0, + 230, 43, 245, 9, + WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), + CT_LABEL(-1, ID_STR_LICENSESC, + 165, 56, 80, 9, + WS_VISIBLE | WS_TABSTOP | SS_NOPREFIX, 0), + CT_LABEL(Id_LicenseLabel, 0, + 230, 56, 245, 9, + WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), + CT_LABEL(-1, ID_STR_INFORMATIONSC, + 165, 69, 80, 9, + WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0), + CT_EDIT(Id_DescriptionLabel, 0, + 228, 69, 238, 64, + WS_VISIBLE | ES_MULTILINE | ES_READONLY, 0), + CT_LINKLABEL(Id_AddMetadataLink, ID_STR_ADDMETADATA, + 165, 142, 150, 9, + 0, 0), + + CT_LINEH(-1, ID_STR_COORDINATESSC, + 165, 156, 304, 1, + WS_VISIBLE, 0), + + CT_LABEL(-1, ID_STR_COORDINATESSC, + 165, 169, labelWidth, 9, + WS_VISIBLE, 0), + CT_EDIT(Id_XPositionEdit, 0, + 165 + labelWidth, 166, 38, 14, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, WS_EX_CLIENTEDGE), + CT_EDIT(Id_YPositionEdit, 0, + 165 + labelWidth + 42, 166, 38, 14, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, WS_EX_CLIENTEDGE), + CT_LABEL(-1, ID_STR_POSITIONSC, + 165, 190, labelWidth, 9, + WS_VISIBLE, 0), + CT_COMBOBOX(Id_ZPositionDropDownList, 0, + 165 + labelWidth, 187, 80, 14, + WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL | WS_DISABLED, 0), + CT_LABEL(-1, ID_STR_LOADORDERSC, + 165, 208, labelWidth, 9, + WS_VISIBLE, 0), + CT_EDIT(Id_LoadOrderEdit, 0, + 165 + labelWidth, 205, 80, 14, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, WS_EX_CLIENTEDGE), + CT_LABEL(-1, ID_STR_TRANSPARENCYSC, + 165, 229, labelWidth, 9, + WS_VISIBLE, 0), + CT_COMBOBOX(Id_TransparencyDropDownList, 0, + 165 + labelWidth, 226, 80, 14, + WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL | WS_DISABLED, 0), + CT_LABEL(-1, ID_STR_ONHOVERSC, + 165, 247, labelWidth, 9, + WS_VISIBLE, 0), + CT_COMBOBOX(Id_OnHoverDropDownList, 0, + 165 + labelWidth, 244, 80, 14, + WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL | WS_DISABLED, 0), + + CT_BUTTON(Id_DisplayMonitorButton, ID_STR_DISPLAYMONITOR, + 350, 166, 118, 14, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), + CT_CHECKBOX(Id_DraggableCheckBox, ID_STR_DRAGGABLE, + 350, 190, 118, 9, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), + CT_CHECKBOX(Id_ClickThroughCheckBox, ID_STR_CLICKTHROUGH, + 350, 203, 118, 9, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), + CT_CHECKBOX(Id_KeepOnScreenCheckBox, ID_STR_KEEPONSCREEN, + 350, 216, 118, 9, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), + CT_CHECKBOX(Id_SavePositionCheckBox, ID_STR_SAVEPOSITION, + 350, 229, 118, 9, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), + CT_CHECKBOX(Id_SnapToEdgesCheckBox, ID_STR_SNAPTOEDGES, + 350, 242, 118, 9, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0) + }; + + CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); +} + +void DialogManage::TabSkins::Initialize() +{ + BUTTON_SPLITINFO bsi; + bsi.mask = BCSIF_SIZE; + bsi.size.cx = 20; + bsi.size.cy = 14; + + HWND item = GetControl(Id_ActiveSkinsButton); + Dialog::SetMenuButton(item); + + item = GetControl(Id_DisplayMonitorButton); + Dialog::SetMenuButton(item); + + // Load folder/.ini icons from shell32 + HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR32, 2, 10); + HMODULE hDLL = GetModuleHandle(L"shell32"); + + HICON hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(4), IMAGE_ICON, 16, 16, LR_SHARED); + ImageList_AddIcon(hImageList, hIcon); + hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(151), IMAGE_ICON, 16, 16, LR_SHARED); + ImageList_AddIcon(hImageList, hIcon); + + // Apply icons and populate tree + item = GetControl(Id_SkinsTreeView); + TreeView_SetImageList(item, hImageList, TVSIL_NORMAL); + Update(nullptr, false); + + // Get rid of the EDITTEXT control border + item = GetControl(Id_DescriptionLabel); + SetWindowLongPtr(item, GWL_EXSTYLE, GetWindowLongPtr(item, GWL_EXSTYLE) &~ WS_EX_CLIENTEDGE); + SetWindowPos(item, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER); + + item = GetControl(Id_TransparencyDropDownList); + ComboBox_AddString(item, L"0%"); + ComboBox_AddString(item, L"10%"); + ComboBox_AddString(item, L"20%"); + ComboBox_AddString(item, L"30%"); + ComboBox_AddString(item, L"40%"); + ComboBox_AddString(item, L"50%"); + ComboBox_AddString(item, L"60%"); + ComboBox_AddString(item, L"70%"); + ComboBox_AddString(item, L"80%"); + ComboBox_AddString(item, L"90%"); + + item = GetControl(Id_ZPositionDropDownList); + ComboBox_AddString(item, GetString(ID_STR_ONDESKTOP)); + ComboBox_AddString(item, GetString(ID_STR_BOTTOM)); + ComboBox_AddString(item, GetString(ID_STR_NORMAL)); + ComboBox_AddString(item, GetString(ID_STR_TOPMOST)); + ComboBox_AddString(item, GetString(ID_STR_STAYTOPMOST)); + + item = GetControl(Id_OnHoverDropDownList); + ComboBox_AddString(item, GetString(ID_STR_DONOTHING)); + ComboBox_AddString(item, GetString(ID_STR_HIDE)); + ComboBox_AddString(item, GetString(ID_STR_FADEIN)); + ComboBox_AddString(item, GetString(ID_STR_FADEOUT)); + + m_Initialized = true; + m_HandleCommands = true; +} + +/* +** Updates metadata and settings when changed. +** +*/ +void DialogManage::TabSkins::Update(MeterWindow* meterWindow, bool deleted) +{ + if (meterWindow) + { + if (!deleted && m_IgnoreUpdate) + { + // Changed setting from dialog, no need to update + m_IgnoreUpdate = false; + } + else if (m_SkinWindow && m_SkinWindow == meterWindow) + { + // Update from currently open skin + m_HandleCommands = false; + if (deleted) + { + DisableControls(); + m_SkinWindow = nullptr; + } + else + { + SetControls(); + } + m_HandleCommands = true; + } + else if (wcscmp(meterWindow->GetFolderPath().c_str(), m_SkinFolderPath.c_str()) == 0 && + wcscmp(meterWindow->GetFileName().c_str(), m_SkinFileName.c_str()) == 0) + { + ReadSkin(); + } + } + else + { + // Populate tree + HWND item = GetControl(Id_SkinsTreeView); + TreeView_DeleteAllItems(item); + + TVINSERTSTRUCT tvi = {0}; + tvi.hInsertAfter = TVI_LAST; + tvi.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvi.item.iImage = tvi.item.iSelectedImage = 0; + + if (!Rainmeter::GetInstance().m_SkinRegistry.IsEmpty()) + { + PopulateTree(item, tvi); + } + } +} + +void DialogManage::TabSkins::SetControls() +{ + WCHAR buffer[64]; + + HWND item = GetControl(Id_EditButton); + EnableWindow(item, TRUE); + + item = GetControl(Id_LoadButton); + EnableWindow(item, TRUE); + + if (m_SkinWindow) + { + SetWindowText(item, GetString(ID_STR_UNLOAD)); + + item = GetControl(Id_RefreshButton); + EnableWindow(item, TRUE); + + item = GetControl(Id_XPositionEdit); + EnableWindow(item, TRUE); + _itow_s(m_SkinWindow->GetX(), buffer, 10); + SetWindowText(item, buffer); + + item = GetControl(Id_YPositionEdit); + EnableWindow(item, TRUE); + _itow_s(m_SkinWindow->GetY(), buffer, 10); + SetWindowText(item, buffer); + + item = GetControl(Id_DisplayMonitorButton); + EnableWindow(item, TRUE); + + item = GetControl(Id_DraggableCheckBox); + if (Rainmeter::GetInstance().GetDisableDragging()) + { + EnableWindow(item, FALSE); + Button_SetCheck(item, BST_UNCHECKED); + } + else + { + EnableWindow(item, TRUE); + Button_SetCheck(item, m_SkinWindow->GetWindowDraggable()); + } + + item = GetControl(Id_ClickThroughCheckBox); + EnableWindow(item, TRUE); + Button_SetCheck(item, m_SkinWindow->GetClickThrough()); + + item = GetControl(Id_KeepOnScreenCheckBox); + EnableWindow(item, TRUE); + Button_SetCheck(item, m_SkinWindow->GetKeepOnScreen()); + + item = GetControl(Id_SavePositionCheckBox); + EnableWindow(item, TRUE); + Button_SetCheck(item, m_SkinWindow->GetSavePosition()); + + item = GetControl(Id_SnapToEdgesCheckBox); + EnableWindow(item, TRUE); + Button_SetCheck(item, m_SkinWindow->GetSnapEdges()); + + item = GetControl(Id_TransparencyDropDownList); + EnableWindow(item, TRUE); + int value = (int)(10 - m_SkinWindow->GetAlphaValue() / 25.5); + value = min(9, value); + value = max(0, value); + ComboBox_SetCurSel(item, value); + + item = GetControl(Id_ZPositionDropDownList); + EnableWindow(item, TRUE); + ComboBox_SetCurSel(item, m_SkinWindow->GetWindowZPosition() + 2); + + item = GetControl(Id_LoadOrderEdit); + EnableWindow(item, TRUE); + _itow_s(Rainmeter::GetInstance().GetLoadOrder(m_SkinFolderPath), buffer, 10); + SetWindowText(item, buffer); + + item = GetControl(Id_OnHoverDropDownList); + EnableWindow(item, TRUE); + ComboBox_SetCurSel(item, m_SkinWindow->GetWindowHide()); + } + else + { + SetWindowText(item, GetString(ID_STR_LOAD)); + } +} + +void DialogManage::TabSkins::DisableControls(bool clear) +{ + HWND item = GetControl(Id_LoadButton); + SetWindowText(item, GetString(ID_STR_LOAD)); + + if (clear) + { + EnableWindow(item, FALSE); + + item = GetControl(Id_EditButton); + EnableWindow(item, FALSE); + + item = GetControl(Id_FileLabel); + SetWindowText(item, GetString(ID_STR_ELLIPSIS)); + + item = GetControl(Id_ConfigLabel); + SetWindowText(item, L""); + + item = GetControl(Id_AuthorLabel); + SetWindowText(item, L""); + + item = GetControl(Id_VersionLabel); + SetWindowText(item, L""); + + item = GetControl(Id_LicenseLabel); + SetWindowText(item, L""); + + item = GetControl(Id_DescriptionLabel); + SetWindowText(item, L""); + ShowScrollBar(item, SB_VERT, FALSE); + + item = GetControl(Id_AddMetadataLink); + ShowWindow(item, SW_HIDE); + } + else + { + EnableWindow(item, TRUE); + } + + item = GetControl(Id_RefreshButton); + EnableWindow(item, FALSE); + + item = GetControl(Id_XPositionEdit); + SetWindowText(item, L""); + EnableWindow(item, FALSE); + + item = GetControl(Id_YPositionEdit); + SetWindowText(item, L""); + EnableWindow(item, FALSE); + + item = GetControl(Id_DisplayMonitorButton); + EnableWindow(item, FALSE); + + item = GetControl(Id_DraggableCheckBox); + EnableWindow(item, FALSE); + Button_SetCheck(item, BST_UNCHECKED); + + item = GetControl(Id_ClickThroughCheckBox); + EnableWindow(item, FALSE); + Button_SetCheck(item, BST_UNCHECKED); + + item = GetControl(Id_KeepOnScreenCheckBox); + EnableWindow(item, FALSE); + Button_SetCheck(item, BST_UNCHECKED); + + item = GetControl(Id_SavePositionCheckBox); + EnableWindow(item, FALSE); + Button_SetCheck(item, BST_UNCHECKED); + + item = GetControl(Id_SnapToEdgesCheckBox); + EnableWindow(item, FALSE); + Button_SetCheck(item, BST_UNCHECKED); + + item = GetControl(Id_TransparencyDropDownList); + EnableWindow(item, FALSE); + ComboBox_SetCurSel(item, -1); + + item = GetControl(Id_ZPositionDropDownList); + EnableWindow(item, FALSE); + ComboBox_SetCurSel(item, -1); + + item = GetControl(Id_LoadOrderEdit); + SetWindowText(item, L""); + EnableWindow(item, FALSE); + + item = GetControl(Id_OnHoverDropDownList); + EnableWindow(item, FALSE); + ComboBox_SetCurSel(item, -1); +} + +void DialogManage::TabSkins::ReadSkin() +{ + HWND item = GetControl(Id_FileLabel); + SetWindowText(item, m_SkinFileName.c_str()); + + PathSetDlgItemPath(m_Window, Id_ConfigLabel, m_SkinFolderPath.c_str()); + + item = GetControl(Id_EditButton); + EnableWindow(item, TRUE); + + std::wstring file = Rainmeter::GetInstance().GetSkinPath() + m_SkinFolderPath; + file += L'\\'; + file += m_SkinFileName; + m_SkinWindow = Rainmeter::GetInstance().GetMeterWindowByINI(file); + if (!m_SkinWindow) + { + DisableControls(); + } + + SetControls(); + + WCHAR* buffer = new WCHAR[MAX_LINE_LENGTH]; + const WCHAR* fileSz = file.c_str(); + + item = GetControl(Id_AuthorLabel); + if (GetPrivateProfileString(L"Metadata", L"Author", nullptr, buffer, MAX_LINE_LENGTH, fileSz) == 0) + { + // For backwards compatibility. + GetPrivateProfileString(L"Rainmeter", L"Author", nullptr, buffer, MAX_LINE_LENGTH, fileSz); + } + SetWindowText(item, buffer); + + item = GetControl(Id_AddMetadataLink); + if (GetPrivateProfileSection(L"Metadata", buffer, 8, fileSz) > 0) + { + ShowWindow(item, SW_HIDE); + + // Set metadata + item = GetControl(Id_VersionLabel); + GetPrivateProfileString(L"Metadata", L"Version", nullptr, buffer, MAX_LINE_LENGTH, fileSz); + SetWindowText(item, buffer); + + item = GetControl(Id_LicenseLabel); + GetPrivateProfileString(L"Metadata", L"License", nullptr, buffer, MAX_LINE_LENGTH, fileSz); + SetWindowText(item, buffer); + + item = GetControl(Id_DescriptionLabel); + std::wstring text; + if (GetPrivateProfileString(L"Metadata", L"Information", nullptr, buffer, MAX_LINE_LENGTH, fileSz) > 0) + { + text = buffer; + } + else + { + // For backwards compatibility + GetPrivateProfileString(L"Metadata", L"Description", nullptr, buffer, MAX_LINE_LENGTH, fileSz); + text = buffer; + + if (GetPrivateProfileString(L"Metadata", L"Instructions", nullptr, buffer, MAX_LINE_LENGTH, fileSz) > 0) + { + text += L"\r\n\r\n"; + text += buffer; + } + } + + // Replace | with newline + std::wstring::size_type pos; + while ((pos = text.find_first_of(L'|')) != std::wstring::npos) + { + size_t count = (pos + 1 < text.length() && text[pos + 1] == L' ') ? 2 : 1; + if (text[pos - 1] == L' ') + { + --pos; + count += 1; + } + text.replace(pos, count, L"\r\n"); + } + + SetWindowText(item, text.c_str()); + + int lines = Edit_GetLineCount(item); + ShowScrollBar(item, SB_VERT, (BOOL)(lines > 6)); + } + else + { + ShowWindow(item, SW_SHOWNORMAL); + + item = GetControl(Id_VersionLabel); + SetWindowText(item, L""); + + item = GetControl(Id_LicenseLabel); + SetWindowText(item, L""); + + item = GetControl(Id_DescriptionLabel); + SetWindowText(item, L""); + ShowScrollBar(item, SB_VERT, FALSE); + } + + delete [] buffer; +} + +std::wstring DialogManage::TabSkins::GetTreeSelectionPath(HWND tree) +{ + WCHAR buffer[MAX_PATH]; + + // Get current selection name + TVITEM tvi = {0}; + tvi.hItem = TreeView_GetSelection(tree); + tvi.mask = TVIF_TEXT; + tvi.pszText = buffer; + tvi.cchTextMax = MAX_PATH; + TreeView_GetItem(tree, &tvi); + + std::wstring path = buffer; + while ((tvi.hItem = TreeView_GetParent(tree, tvi.hItem)) != nullptr) + { + TreeView_GetItem(tree, &tvi); + path.insert(0, 1, L'\\'); + path.insert(0, buffer); + } + + return path; +} + +/* +** Populates the treeview with folders and skins. +** +*/ +int DialogManage::TabSkins::PopulateTree(HWND tree, TVINSERTSTRUCT& tvi, int index) +{ + int initialLevel = Rainmeter::GetInstance().m_SkinRegistry.GetFolder(index).level; + + const size_t max = Rainmeter::GetInstance().m_SkinRegistry.GetFolderCount(); + while (index < max) + { + const auto& skinFolder = Rainmeter::GetInstance().m_SkinRegistry.GetFolder(index); + if (skinFolder.level != initialLevel) + { + return index - 1; + } + + HTREEITEM oldParent = tvi.hParent; + + // Add folder + tvi.item.iImage = tvi.item.iSelectedImage = 0; + tvi.item.pszText = (WCHAR*)skinFolder.name.c_str(); + tvi.hParent = TreeView_InsertItem(tree, &tvi); + + // Add subfolders + if ((index + 1) < max && + Rainmeter::GetInstance().m_SkinRegistry.GetFolder(index + 1).level == initialLevel + 1) + { + index = PopulateTree(tree, tvi, index + 1); + } + + // Add files + tvi.item.iImage = tvi.item.iSelectedImage = 1; + for (int i = 0, isize = (int)skinFolder.files.size(); i < isize; ++i) + { + tvi.item.pszText = (WCHAR*)skinFolder.files[i].c_str(); + TreeView_InsertItem(tree, &tvi); + } + + tvi.hParent = oldParent; + + ++index; + } + + return index; +} + +/* +** Selects an item in the treeview. +** +*/ +void DialogManage::TabSkins::SelectTreeItem(HWND tree, HTREEITEM item, LPCWSTR name) +{ + WCHAR buffer[MAX_PATH]; + TVITEM tvi = {0}; + tvi.mask = TVIF_TEXT; + tvi.hItem = item; + tvi.pszText = buffer; + + const WCHAR* pos = wcschr(name, L'\\'); + if (pos) + { + const int folderLen = (int)(pos - name); + tvi.cchTextMax = folderLen + 1; // Length of folder name plus 1 for nullptr + + // Find and expand the folder + do + { + TreeView_GetItem(tree, &tvi); + if (wcsncmp(buffer, name, folderLen) == 0) + { + if ((item = TreeView_GetChild(tree, tvi.hItem)) != nullptr) + { + TreeView_Expand(tree, tvi.hItem, TVE_EXPAND); + TreeView_Select(tree, tvi.hItem, TVGN_CARET); + ++pos; // Skip the slash + SelectTreeItem(tree, item, pos); + } + + break; + } + } + while ((tvi.hItem = TreeView_GetNextSibling(tree, tvi.hItem)) != nullptr); + } + else + { + tvi.cchTextMax = MAX_PATH; + + // Find and select the file + do + { + TreeView_GetItem(tree, &tvi); + if (wcscmp(buffer, name) == 0) + { + TreeView_Select(tree, tvi.hItem, TVGN_CARET); + break; + } + } + while ((tvi.hItem = TreeView_GetNextSibling(tree, tvi.hItem)) != nullptr); + } +} + +INT_PTR DialogManage::TabSkins::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + return OnCommand(wParam, lParam); + + case WM_NOTIFY: + return OnNotify(wParam, lParam); + } + + return FALSE; +} + +INT_PTR DialogManage::TabSkins::OnCommand(WPARAM wParam, LPARAM lParam) +{ + if (!m_HandleCommands) + { + // Values are being changed/reset, no need to apply changes. + return FALSE; + } + + switch (LOWORD(wParam)) + { + case Id_ActiveSkinsButton: + { + HMENU menu = CreatePopupMenu(); + + // Add active skins to menu + std::map::const_iterator iter = Rainmeter::GetInstance().GetAllMeterWindows().begin(); + int index = 0; + for ( ; iter != Rainmeter::GetInstance().GetAllMeterWindows().end(); ++iter) + { + std::wstring name = ((*iter).second)->GetFolderPath() + L'\\'; + name += ((*iter).second)->GetFileName(); + InsertMenu(menu, index, MF_BYPOSITION, ID_CONFIG_FIRST + index, name.c_str()); + ++index; + } + + if (index > 0) + { + RECT r; + GetWindowRect((HWND)lParam, &r); + + // Show context menu + TrackPopupMenu( + menu, + TPM_RIGHTBUTTON | TPM_LEFTALIGN, + (*GetString(ID_STR_ISRTL) == L'1') ? r.right : r.left, + --r.bottom, + 0, + m_Window, + nullptr + ); + } + + DestroyMenu(menu); + } + break; + + case Id_CreateSkinPackageButton: + { + std::wstring file = Rainmeter::GetInstance().GetPath() + L"SkinInstaller.exe"; + CommandHandler::RunFile(file.c_str(), L"/Packager"); + } + break; + + case Id_LoadButton: + { + if (!m_SkinWindow) + { + // Skin not active, load + const SkinRegistry::Indexes indexes = + Rainmeter::GetInstance().m_SkinRegistry.FindIndexes(m_SkinFolderPath, m_SkinFileName); + if (indexes.IsValid()) + { + m_HandleCommands = false; + Rainmeter::GetInstance().ActivateSkin(indexes.folder, indexes.file); + m_HandleCommands = true; + + // Fake selection change to update controls + NMHDR nm; + nm.code = TVN_SELCHANGED; + nm.idFrom = Id_SkinsTreeView; + nm.hwndFrom = GetControl(Id_SkinsTreeView); + OnNotify(0, (LPARAM)&nm); + } + } + else + { + m_HandleCommands = false; + Rainmeter::GetInstance().DeactivateSkin(m_SkinWindow, -1); + } + } + break; + + case Id_RefreshButton: + if (m_SkinWindow) + { + m_SkinWindow->Refresh(false); + } + break; + + case Id_EditButton: + Rainmeter::GetInstance().EditSkinFile(m_SkinFolderPath, m_SkinFileName); + break; + + case Id_XPositionEdit: + if (HIWORD(wParam) == EN_CHANGE) + { + WCHAR buffer[32]; + m_IgnoreUpdate = true; + int x = (GetWindowText((HWND)lParam, buffer, 32) > 0) ? _wtoi(buffer) : 0; + m_SkinWindow->MoveWindow(x, m_SkinWindow->GetY()); + + if (x > m_SkinWindow->GetX()) + { + _itow_s(m_SkinWindow->GetX(), buffer, 10); + Edit_SetText((HWND)lParam, buffer); + } + } + break; + + case Id_YPositionEdit: + if (HIWORD(wParam) == EN_CHANGE) + { + WCHAR buffer[32]; + m_IgnoreUpdate = true; + int y = (GetWindowText((HWND)lParam, buffer, 32) > 0) ? _wtoi(buffer) : 0; + m_SkinWindow->MoveWindow(m_SkinWindow->GetX(), y); + + if (y > m_SkinWindow->GetY()) + { + _itow_s(m_SkinWindow->GetY(), buffer, 10); + Edit_SetText((HWND)lParam, buffer); + } + } + break; + + case Id_LoadOrderEdit: + if (HIWORD(wParam) == EN_CHANGE) + { + if (m_IgnoreUpdate) + { + // To avoid infinite loop after setting value below + m_IgnoreUpdate = false; + } + else + { + // Convert text to number and set it to get rid of extra chars + WCHAR buffer[32]; + int len = GetWindowText((HWND)lParam, buffer, 32); + if ((len == 0) || (len == 1 && buffer[0] == L'-')) + { + // Ignore if empty or if - is only char + break; + } + + // Get selection + DWORD sel = Edit_GetSel((HWND)lParam); + + // Reset value (to get rid of invalid chars) + m_IgnoreUpdate = true; + int value = _wtoi(buffer); + + _itow_s(value, buffer, 10); + SetWindowText((HWND)lParam, buffer); + + // Reset selection + Edit_SetSel((HWND)lParam, LOWORD(sel), HIWORD(sel)); + + WritePrivateProfileString(m_SkinFolderPath.c_str(), L"LoadOrder", buffer, Rainmeter::GetInstance().GetIniFile().c_str()); + const SkinRegistry::Indexes indexes = Rainmeter::GetInstance().m_SkinRegistry.FindIndexes( + m_SkinWindow->GetFolderPath(), m_SkinWindow->GetFileName()); + if (indexes.IsValid()) + { + Rainmeter::GetInstance().SetLoadOrder(indexes.folder, value); + + std::multimap windows; + Rainmeter::GetInstance().GetMeterWindowsByLoadOrder(windows); + + System::PrepareHelperWindow(); + + // Reorder window z-position to reflect load order + std::multimap::const_iterator iter = windows.begin(); + for ( ; iter != windows.end(); ++iter) + { + MeterWindow* mw = (*iter).second; + mw->ChangeZPos(mw->GetWindowZPosition(), true); + } + } + } + } + break; + + case Id_DisplayMonitorButton: + { + static const MenuTemplate s_Menu[] = + { + MENU_ITEM(IDM_SKIN_MONITOR_PRIMARY, ID_STR_USEDEFAULTMONITOR), + MENU_ITEM(ID_MONITOR_FIRST, ID_STR_VIRTUALSCREEN), + MENU_SEPARATOR(), + MENU_SEPARATOR(), + MENU_ITEM(IDM_SKIN_MONITOR_AUTOSELECT, ID_STR_AUTOSELECTMONITOR) + }; + + HMENU menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); + if (menu) + { + ContextMenu::CreateMonitorMenu(menu, m_SkinWindow); + + RECT r; + GetWindowRect((HWND)lParam, &r); + + // Show context menu + TrackPopupMenu( + menu, + TPM_RIGHTBUTTON | TPM_LEFTALIGN, + (*GetString(ID_STR_ISRTL) == L'1') ? r.right : r.left, + --r.bottom, + 0, + m_Window, + nullptr + ); + + DestroyMenu(menu); + } + } + break; + + case Id_DraggableCheckBox: + m_IgnoreUpdate = true; + m_SkinWindow->SetWindowDraggable(!m_SkinWindow->GetWindowDraggable()); + break; + + case Id_ClickThroughCheckBox: + m_IgnoreUpdate = true; + m_SkinWindow->SetClickThrough(!m_SkinWindow->GetClickThrough()); + break; + + case Id_KeepOnScreenCheckBox: + m_IgnoreUpdate = true; + m_SkinWindow->SetKeepOnScreen(!m_SkinWindow->GetKeepOnScreen()); + break; + + case Id_SavePositionCheckBox: + m_IgnoreUpdate = true; + m_SkinWindow->SetSavePosition(!m_SkinWindow->GetSavePosition()); + break; + + case Id_SnapToEdgesCheckBox: + m_IgnoreUpdate = true; + m_SkinWindow->SetSnapEdges(!m_SkinWindow->GetSnapEdges()); + break; + + case Id_ZPositionDropDownList: + if (HIWORD(wParam) == CBN_SELCHANGE) + { + m_IgnoreUpdate = true; + ZPOSITION zpos = (ZPOSITION)(ComboBox_GetCurSel((HWND)lParam) - 2); + m_SkinWindow->SetWindowZPosition(zpos); + } + break; + + case Id_TransparencyDropDownList: + if (HIWORD(wParam) == CBN_SELCHANGE) + { + m_IgnoreUpdate = true; + int sel = ComboBox_GetCurSel((HWND)lParam) + IDM_SKIN_TRANSPARENCY_0; + SendMessage(m_SkinWindow->GetWindow(), WM_COMMAND, sel, 0); + } + break; + + case Id_OnHoverDropDownList: + if (HIWORD(wParam) == CBN_SELCHANGE) + { + m_IgnoreUpdate = true; + HIDEMODE hide = (HIDEMODE)ComboBox_GetCurSel((HWND)lParam); + m_SkinWindow->SetWindowHide(hide); + } + break; + + case IDM_MANAGESKINSMENU_EXPAND: + { + HWND tree = GetControl(Id_SkinsTreeView); + HTREEITEM item = TreeView_GetSelection(tree); + TreeView_Expand(tree, item, TVE_TOGGLE); + } + break; + + case IDM_MANAGESKINSMENU_OPENFOLDER: + { + HWND tree = GetControl(Id_SkinsTreeView); + Rainmeter::GetInstance().OpenSkinFolder(GetTreeSelectionPath(tree)); + } + break; + + default: + if (wParam >= ID_CONFIG_FIRST && wParam <= ID_CONFIG_LAST) + { + std::map::const_iterator iter = Rainmeter::GetInstance().GetAllMeterWindows().begin(); + int index = (int)wParam - ID_CONFIG_FIRST; + int i = 0; + for ( ; iter != Rainmeter::GetInstance().GetAllMeterWindows().end(); ++iter) + { + if (i == index) + { + std::wstring name = ((*iter).second)->GetFolderPath() + L'\\'; + name += ((*iter).second)->GetFileName(); + + HWND item = GetControl(Id_SkinsTreeView); + SelectTreeItem(item, TreeView_GetRoot(item), name.c_str()); + break; + } + + ++i; + } + } + else if (wParam == IDM_SKIN_MONITOR_AUTOSELECT || + wParam == IDM_SKIN_MONITOR_PRIMARY || + wParam >= ID_MONITOR_FIRST && wParam <= ID_MONITOR_LAST) + { + if (m_SkinWindow) + { + SendMessage(m_SkinWindow->GetWindow(), WM_COMMAND, wParam, 0); + } + break; + } + + return 1; + } + + return 0; +} + +INT_PTR DialogManage::TabSkins::OnNotify(WPARAM wParam, LPARAM lParam) +{ + LPNMHDR nm = (LPNMHDR)lParam; + switch (nm->code) + { + case NM_CLICK: + if (nm->idFrom == Id_AddMetadataLink) + { + std::wstring file = Rainmeter::GetInstance().GetSkinPath() + m_SkinFolderPath; + file += L'\\'; + file += m_SkinFileName; + const WCHAR* str = L"\r\n" // Hack to add below [Rainmeter]. + L"[Metadata]\r\n" + L"Name=\r\n" + L"Author=\r\n" + L"Information=\r\n" + L"License=\r\n" + L"Version"; + WritePrivateProfileString(L"Rainmeter", str, L"", file.c_str()); + SendMessage(m_Window, WM_COMMAND, MAKEWPARAM(Id_EditButton, 0), 0); + ShowWindow(nm->hwndFrom, SW_HIDE); + } + break; + + case NM_DBLCLK: + if (nm->idFrom == Id_SkinsTreeView && !m_SkinFileName.empty()) + { + OnCommand(MAKEWPARAM(Id_LoadButton, 0), 0); + } + break; + + case NM_RCLICK: + if (nm->idFrom == Id_SkinsTreeView) + { + POINT pt = System::GetCursorPosition(); + + TVHITTESTINFO ht; + ht.pt = pt; + ScreenToClient(nm->hwndFrom, &ht.pt); + + if (TreeView_HitTest(nm->hwndFrom, &ht) && !(ht.flags & TVHT_NOWHERE)) + { + TreeView_SelectItem(nm->hwndFrom, ht.hItem); + + TVITEM tvi = {0}; + tvi.hItem = TreeView_GetSelection(nm->hwndFrom); + tvi.mask = TVIF_STATE; + + if (TreeView_GetItem(nm->hwndFrom, &tvi)) + { + HMENU menu = nullptr; + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_STRING; + + if (m_SkinFileName.empty()) + { + // Folder menu. + static const MenuTemplate s_Menu[] = + { + MENU_ITEM(IDM_MANAGESKINSMENU_EXPAND, ID_STR_EXPAND), + MENU_ITEM(IDM_MANAGESKINSMENU_OPENFOLDER, ID_STR_OPENFOLDER), + }; + + menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); + SetMenuDefaultItem(menu, IDM_MANAGESKINSMENU_EXPAND, MF_BYCOMMAND); + + if (tvi.state & TVIS_EXPANDED) + { + mii.dwTypeData = GetString(ID_STR_COLLAPSE); + SetMenuItemInfo(menu, IDM_MANAGESKINSMENU_EXPAND, MF_BYCOMMAND, &mii); + } + } + else + { + // Skin menu. + static const MenuTemplate s_Menu[] = + { + MENU_ITEM(IDM_MANAGESKINSMENU_LOAD, ID_STR_LOAD), + MENU_ITEM(IDM_MANAGESKINSMENU_REFRESH, ID_STR_REFRESH), + MENU_ITEM(IDM_MANAGESKINSMENU_EDIT, ID_STR_EDIT), + }; + + menu = MenuTemplate::CreateMenu(s_Menu, _countof(s_Menu), GetString); + SetMenuDefaultItem(menu, IDM_MANAGESKINSMENU_LOAD, MF_BYCOMMAND); + + if (m_SkinWindow) + { + mii.dwTypeData = GetString(ID_STR_UNLOAD); + SetMenuItemInfo(menu, IDM_MANAGESKINSMENU_LOAD, MF_BYCOMMAND, &mii); + } + else + { + EnableMenuItem(menu, IDM_MANAGESKINSMENU_REFRESH, MF_BYCOMMAND | MF_GRAYED); + } + } + + // Show context menu + TrackPopupMenu( + menu, + TPM_RIGHTBUTTON | TPM_LEFTALIGN, + pt.x, + pt.y, + 0, + m_Window, + nullptr + ); + + DestroyMenu(menu); + } + } + } + break; + + case TVN_SELCHANGED: + if (nm->idFrom == Id_SkinsTreeView) + { + m_SkinWindow = nullptr; + m_SkinFileName.clear(); + m_SkinFolderPath.clear(); + + // Temporarily disable handling commands + m_HandleCommands = false; + + WCHAR buffer[MAX_PATH]; + + // Get current selection name + TVITEM tvi = {0}; + tvi.hItem = TreeView_GetSelection(nm->hwndFrom); + tvi.mask = TVIF_TEXT | TVIF_CHILDREN; + tvi.pszText = buffer; + tvi.cchTextMax = MAX_PATH; + TreeView_GetItem(nm->hwndFrom, &tvi); + + if (tvi.cChildren == 0) + { + // Current selection is file + m_SkinFileName = buffer; + tvi.mask = TVIF_TEXT; + + // Loop through parents to get skin folder + m_SkinFolderPath.clear(); + while ((tvi.hItem = TreeView_GetParent(nm->hwndFrom, tvi.hItem)) != nullptr) + { + TreeView_GetItem(nm->hwndFrom, &tvi); + m_SkinFolderPath.insert(0, 1, L'\\'); + m_SkinFolderPath.insert(0, buffer); + } + + m_SkinFolderPath.resize(m_SkinFolderPath.length() - 1); // Get rid of trailing slash + + ReadSkin(); + } + else + { + DisableControls(true); + } + + m_HandleCommands = true; + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------------------------------- +// +// Layouts tab +// +// ----------------------------------------------------------------------------------------------- + +/* +** Constructor. +** +*/ +DialogManage::TabLayouts::TabLayouts() : Tab() +{ +} + +void DialogManage::TabLayouts::Create(HWND owner) +{ + Tab::CreateTabWindow(15, 30, 470, 260, owner); + + static const ControlTemplate::Control s_Controls[] = + { + CT_GROUPBOX(-1, ID_STR_SAVENEWTHEME, + 0, 0, 230, 150, + WS_VISIBLE, 0), + CT_LABEL(-1, ID_STR_THEMEDESCRIPTION, + 6, 16, 205, 44, + WS_VISIBLE, 0), + CT_CHECKBOX(Id_SaveEmptyThemeCheckBox, ID_STR_SAVEASEMPTYTHEME, + 6, 70, 220, 9, + WS_VISIBLE | WS_TABSTOP, 0), + CT_CHECKBOX(Id_ExcludeUnusedSkinsCheckBox, ID_STR_EXCLUDEUNUSEDSKINS, + 6, 83, 220, 9, + WS_VISIBLE | WS_TABSTOP, 0), + CT_CHECKBOX(Id_IncludeWallpaperCheckBox, ID_STR_INCLUDEWALLPAPER, + 6, 96, 220, 9, + WS_VISIBLE | WS_TABSTOP, 0), + CT_LABEL(-1, ID_STR_NAMESC, + 6, 115, 100, 9, + WS_VISIBLE, 0), + CT_EDIT(Id_NameLabel, 0, + 6, 128, 162, 14, + WS_VISIBLE | WS_TABSTOP, WS_EX_CLIENTEDGE), + CT_BUTTON(Id_SaveButton, ID_STR_SAVE, + 172, 128, 50, 14, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), + + CT_GROUPBOX(-1, ID_STR_SAVEDTHEMES, + 238, 0, 230, 150, + WS_VISIBLE, 0), + CT_LISTBOX(Id_List, 0, + 244, 16, 160, 125, + WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_SORT | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT, WS_EX_CLIENTEDGE), + CT_BUTTON(Id_LoadButton, ID_STR_LOAD, + 410, 16, 50, 14, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), + CT_BUTTON(Id_EditButton, ID_STR_EDIT, + 410, 34, 50, 14, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0), + CT_BUTTON(Id_DeleteButton, ID_STR_DELETE, + 410, 52, 50, 14, + WS_VISIBLE | WS_TABSTOP | WS_DISABLED, 0) + }; + + CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); +} + +void DialogManage::TabLayouts::Initialize() +{ + HWND item = GetControl(Id_List); + ListBox_ResetContent(item); + const std::vector& layouts = Rainmeter::GetInstance().GetAllLayouts(); + for (size_t i = 0, isize = layouts.size(); i < isize; ++i) + { + ListBox_AddString(item, layouts[i].c_str()); + } + + m_Initialized = true; +} + +void DialogManage::TabLayouts::Update() +{ + Initialize(); +} + +INT_PTR DialogManage::TabLayouts::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + return OnCommand(wParam, lParam); + } + + return FALSE; +} + +INT_PTR DialogManage::TabLayouts::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case Id_SaveEmptyThemeCheckBox: + { + BOOL state = !(Button_GetCheck((HWND)lParam) == BST_CHECKED); + + HWND item = GetControl(Id_ExcludeUnusedSkinsCheckBox); + EnableWindow(item, state); + Button_SetCheck(item, BST_UNCHECKED); + + item = GetControl(Id_IncludeWallpaperCheckBox); + EnableWindow(item, state); + Button_SetCheck(item, BST_UNCHECKED); + } + break; + + case Id_NameLabel: + if (HIWORD(wParam) == EN_CHANGE) + { + WCHAR buffer[32]; + int len = Edit_GetText((HWND)lParam, buffer, 32); + + // Disable save button if no text or if backup + BOOL state = (len > 0 && _wcsicmp(buffer, L"@Backup") != 0); + EnableWindow(GetControl(Id_SaveButton), state); + } + break; + + case Id_List: + if (HIWORD(wParam) == LBN_SELCHANGE) + { + // Ignore clicks that don't hit items + if (ListBox_GetCurSel((HWND)lParam) != LB_ERR) + { + HWND item = GetControl(Id_LoadButton); + EnableWindow(item, TRUE); + item = GetControl(Id_DeleteButton); + EnableWindow(item, TRUE); + item = GetControl(Id_EditButton); + EnableWindow(item, TRUE); + + const std::vector& layouts = Rainmeter::GetInstance().GetAllLayouts(); + item = GetControl(Id_List); + int sel = ListBox_GetCurSel(item); + + item = GetControl(Id_NameLabel); + Edit_SetText(item, layouts[sel].c_str()); + } + } + break; + + case Id_SaveButton: + { + WCHAR buffer[MAX_PATH]; + HWND item = GetControl(Id_NameLabel); + Edit_GetText(item, buffer, MAX_PATH); + + std::wstring layout = buffer; + std::wstring path = Rainmeter::GetInstance().GetLayoutPath(); + CreateDirectory(path.c_str(), 0); + + path += layout; + bool alreadyExists = (_waccess(path.c_str(), 0) != -1); + if (alreadyExists) + { + std::wstring text = GetFormattedString(ID_STR_THEMEALREADYEXISTS, layout.c_str()); + if (Rainmeter::GetInstance().ShowMessage(m_Window, text.c_str(), MB_ICONWARNING | MB_YESNO) != IDYES) + { + // Cancel + break; + } + } + else + { + // Make sure path exists + CreateDirectory(path.c_str(), nullptr); + } + + path += L"\\Rainmeter.ini"; + + item = GetControl(Id_SaveEmptyThemeCheckBox); + if (Button_GetCheck(item) != BST_CHECKED) + { + if (!System::CopyFiles(Rainmeter::GetInstance().GetIniFile(), path)) + { + std::wstring text = GetFormattedString(ID_STR_THEMESAVEFAIL, path.c_str()); + Rainmeter::GetInstance().ShowMessage(m_Window, text.c_str(), MB_OK | MB_ICONERROR); + break; + } + + // Exclude unused skins + item = GetControl(Id_ExcludeUnusedSkinsCheckBox); + if (Button_GetCheck(item) == BST_CHECKED) + { + ConfigParser parser; + parser.Initialize(path); + + // Remove sections with Active=0 + std::list::const_iterator iter = parser.GetSections().begin(); + for ( ; iter != parser.GetSections().end(); ++iter) + { + if (parser.GetValue(*iter, L"Active", L"") == L"0") + { + WritePrivateProfileString((*iter).c_str(), nullptr, nullptr, path.c_str()); + } + } + } + + // Save wallpaper + item = GetControl(Id_IncludeWallpaperCheckBox); + if (Button_GetCheck(item) == BST_CHECKED) + { + // Get current wallpaper + if (SystemParametersInfo(SPI_GETDESKWALLPAPER, MAX_PATH, &buffer, 0)) + { + std::wstring::size_type pos = path.find_last_of(L'\\'); + path.replace(pos + 1, path.length() - pos - 1, L"Wallpaper.bmp"); + System::CopyFiles((std::wstring)buffer, path); + } + } + } + else + { + // Create empty layout + HANDLE file = CreateFile(path.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + if (file == INVALID_HANDLE_VALUE) + { + std::wstring text = GetFormattedString(ID_STR_THEMESAVEFAIL, path.c_str()); + Rainmeter::GetInstance().ShowMessage(m_Window, text.c_str(), MB_OK | MB_ICONERROR); + break; + } + + CloseHandle(file); + } + + if (!alreadyExists) + { + item = GetControl(Id_List); + ListBox_AddString(item, layout.c_str()); + + Rainmeter::GetInstance().ScanForLayouts(); + } + } + break; + + case Id_LoadButton: + { + HWND item = GetControl(Id_List); + int sel = ListBox_GetCurSel(item); + Rainmeter::GetInstance().LoadLayout(Rainmeter::GetInstance().m_Layouts[sel]); + } + break; + + case Id_EditButton: + { + HWND item = GetControl(Id_List); + int sel = ListBox_GetCurSel(item); + const std::vector& layouts = Rainmeter::GetInstance().GetAllLayouts(); + + std::wstring args = L"\"" + Rainmeter::GetInstance().GetLayoutPath(); + args += layouts[sel]; + args += L"\\Rainmeter.ini"; + args += L'"'; + CommandHandler::RunFile(Rainmeter::GetInstance().GetSkinEditor().c_str(), args.c_str()); + } + break; + + case Id_DeleteButton: + { + HWND item = GetControl(Id_List); + int sel = ListBox_GetCurSel(item); + std::vector& layouts = const_cast&>(Rainmeter::GetInstance().GetAllLayouts()); + + std::wstring text = GetFormattedString(ID_STR_THEMEDELETE, layouts[sel].c_str()); + if (Rainmeter::GetInstance().ShowMessage(m_Window, text.c_str(), MB_ICONQUESTION | MB_YESNO) != IDYES) + { + // Cancel + break; + } + + std::wstring folder = Rainmeter::GetInstance().GetLayoutPath(); + folder += layouts[sel]; + + if (System::RemoveFolder(folder)) + { + ListBox_DeleteString(item, sel); + + // Remove layout from vector + std::vector::iterator iter = layouts.begin(); + for ( ; iter != layouts.end(); ++iter) + { + if (wcscmp(layouts[sel].c_str(), (*iter).c_str()) == 0) + { + layouts.erase(iter); + break; + } + } + + EnableWindow(GetControl(Id_LoadButton), FALSE); + EnableWindow(GetControl(Id_DeleteButton), FALSE); + EnableWindow(GetControl(Id_EditButton), FALSE); + } + } + break; + + default: + return 1; + } + + return 0; +} + +// ----------------------------------------------------------------------------------------------- +// +// Settings tab +// +// ----------------------------------------------------------------------------------------------- + +/* +** Constructor. +** +*/ +DialogManage::TabSettings::TabSettings() : Tab() +{ +} + +void DialogManage::TabSettings::Create(HWND owner) +{ + Tab::CreateTabWindow(15, 30, 470, 260, owner); + + // FIXME: Temporary hack. + short buttonWidth = (short)_wtoi(GetString(ID_STR_NUM_BUTTONWIDTH)); + + const ControlTemplate::Control s_Controls[] = + { + CT_GROUPBOX(-1, ID_STR_GENERAL, + 0, 0, 468, 131, + WS_VISIBLE, 0), + CT_LABEL(-1, ID_STR_LANGUAGESC, + 6, 16, 107, 14, + WS_VISIBLE, 0), + CT_COMBOBOX(Id_LanguageDropDownList, 0, + 107, 13, 222, 14, + WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL, 0), + CT_LABEL(-1, ID_STR_EDITORSC, + 6, 37, 107, 9, + WS_VISIBLE, 0), + CT_EDIT(Id_EditorEdit, 0, + 107, 34, 222, 14, + WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL | ES_READONLY, WS_EX_CLIENTEDGE), + CT_BUTTON(Id_EditorBrowseButton, ID_STR_ELLIPSIS, + 333, 34, 25, 14, + WS_VISIBLE | WS_TABSTOP, 0), + CT_CHECKBOX(Id_CheckForUpdatesCheckBox, ID_STR_CHECKFORUPDATES, + 6, 55, 200, 9, + WS_VISIBLE | WS_TABSTOP, 0), + CT_CHECKBOX(Id_LockSkinsCheckBox, ID_STR_DISABLEDRAGGING, + 6, 68, 200, 9, + WS_VISIBLE | WS_TABSTOP, 0), + CT_CHECKBOX(Id_ShowTrayIconCheckBox, ID_STR_SHOWNOTIFICATIONAREAICON, + 6, 81, 200, 9, + WS_VISIBLE | WS_TABSTOP, 0), + CT_CHECKBOX(Id_UseD2DCheckBox, ID_STR_USED2D, + 6, 94, 200, 9, + WS_VISIBLE | WS_TABSTOP, 0), + CT_BUTTON(Id_ResetStatisticsButton, ID_STR_RESETSTATISTICS, + 6, 110, buttonWidth + 20, 14, + WS_VISIBLE | WS_TABSTOP, 0), + + CT_GROUPBOX(-1, ID_STR_LOGGING, + 0, 138, 468, 66, + WS_VISIBLE, 0), + CT_CHECKBOX(Id_VerboseLoggingCheckbox, ID_STR_DEBUGMODE, + 6, 154, 200, 9, + WS_VISIBLE | WS_TABSTOP, 0), + CT_CHECKBOX(Id_LogToFileCheckBox, ID_STR_LOGTOFILE, + 6, 167, 200, 9, + WS_VISIBLE | WS_TABSTOP, 0), + CT_BUTTON(Id_ShowLogFileButton, ID_STR_SHOWLOGFILE, + 6, 183, buttonWidth + 20, 14, + WS_VISIBLE | WS_TABSTOP, 0), + CT_BUTTON(Id_DeleteLogFileButton, ID_STR_DELETELOGFILE, + buttonWidth + 30, 183, buttonWidth + 20, 14, + WS_VISIBLE | WS_TABSTOP, 0) + }; + + CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString); +} + +void DialogManage::TabSettings::Initialize() +{ + // Scan for languages + HWND item = GetControl(Id_LanguageDropDownList); + + std::wstring files = Rainmeter::GetInstance().GetPath() + L"Languages\\*.dll"; + WIN32_FIND_DATA fd; + HANDLE hSearch = FindFirstFile(files.c_str(), &fd); + if (hSearch != INVALID_HANDLE_VALUE) + { + do + { + WCHAR* pos = wcschr(fd.cFileName, L'.'); + if (pos) + { + LCID lcid = (LCID)wcstoul(fd.cFileName, &pos, 10); + if (pos != fd.cFileName && + _wcsicmp(pos, L".dll") == 0 && + GetLocaleInfo(lcid, LOCALE_SENGLISHLANGUAGENAME, fd.cFileName, MAX_PATH) > 0) + { + // Strip brackets in language name + std::wstring text = fd.cFileName; + text += L" - "; + + GetLocaleInfo(lcid, LOCALE_SNATIVEDISPLAYNAME, fd.cFileName, MAX_PATH); + text += fd.cFileName; + + int index = ComboBox_AddString(item, text.c_str()); + ComboBox_SetItemData(item, index, (LPARAM)lcid); + + if (lcid == Rainmeter::GetInstance().GetResourceLCID()) + { + ComboBox_SetCurSel(item, index); + } + } + } + } + while (FindNextFile(hSearch, &fd)); + + FindClose(hSearch); + } + + Button_SetCheck(GetControl(Id_CheckForUpdatesCheckBox), !Rainmeter::GetInstance().GetDisableVersionCheck()); + Button_SetCheck(GetControl(Id_LockSkinsCheckBox), Rainmeter::GetInstance().GetDisableDragging()); + Button_SetCheck(GetControl(Id_LogToFileCheckBox), GetLogger().IsLogToFile()); + Button_SetCheck(GetControl(Id_VerboseLoggingCheckbox), Rainmeter::GetInstance().GetDebug()); + + BOOL isLogFile = (_waccess(GetLogger().GetLogFilePath().c_str(), 0) != -1); + EnableWindow(GetControl(Id_ShowLogFileButton), isLogFile); + EnableWindow(GetControl(Id_DeleteLogFileButton), isLogFile); + + Edit_SetText(GetControl(Id_EditorEdit), Rainmeter::GetInstance().GetSkinEditor().c_str()); + + bool iconEnabled = Rainmeter::GetInstance().GetTrayWindow()->IsTrayIconEnabled(); + Button_SetCheck(GetControl(Id_ShowTrayIconCheckBox), iconEnabled); + + if (IsWindowsVistaOrGreater()) + { + Button_SetCheck(GetControl(Id_UseD2DCheckBox), Rainmeter::GetInstance().GetUseD2D()); + } + else + { + Button_Enable(GetControl(Id_UseD2DCheckBox), FALSE); + } + + m_Initialized = true; +} + +INT_PTR DialogManage::TabSettings::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + return OnCommand(wParam, lParam); + } + + return FALSE; +} + +INT_PTR DialogManage::TabSettings::OnCommand(WPARAM wParam, LPARAM lParam) +{ + if (!m_Initialized) + { + return FALSE; + } + + switch (LOWORD(wParam)) + { + case Id_LanguageDropDownList: + if (HIWORD(wParam) == CBN_SELCHANGE) + { + int sel = ComboBox_GetCurSel((HWND)lParam); + LCID lcid = (LCID)ComboBox_GetItemData((HWND)lParam, sel); + if (lcid != Rainmeter::GetInstance().m_ResourceLCID) + { + WCHAR buffer[16]; + _ultow(lcid, buffer, 10); + WritePrivateProfileString(L"Rainmeter", L"Language", buffer, Rainmeter::GetInstance().GetIniFile().c_str()); + + std::wstring resource = Rainmeter::GetInstance().GetPath() + L"Languages\\"; + resource += buffer; + resource += L".dll"; + FreeLibrary(Rainmeter::GetInstance().m_ResourceInstance); + Rainmeter::GetInstance().m_ResourceInstance = LoadLibraryEx(resource.c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); + Rainmeter::GetInstance().m_ResourceLCID = lcid; + + if (DialogAbout::GetDialog()) + { + int sel = TabCtrl_GetCurSel(DialogAbout::GetDialog()->GetControl(DialogManage::Id_Tab)); + SendMessage(DialogAbout::GetDialog()->GetWindow(), WM_CLOSE, 0, 0); + if (sel == 0) + { + Rainmeter::GetInstance().DelayedExecuteCommand(L"!About"); + } + else if (sel == 1) + { + Rainmeter::GetInstance().DelayedExecuteCommand(L"!About Skins"); + } + else if (sel == 2) + { + Rainmeter::GetInstance().DelayedExecuteCommand(L"!About Plugins"); + } + else //if (sel == 3) + { + Rainmeter::GetInstance().DelayedExecuteCommand(L"!About Version"); + } + } + + SendMessage(c_Dialog->GetWindow(), WM_CLOSE, 0, 0); + Rainmeter::GetInstance().DelayedExecuteCommand(L"!Manage Settings"); + } + } + break; + + case Id_CheckForUpdatesCheckBox: + Rainmeter::GetInstance().SetDisableVersionCheck(!Rainmeter::GetInstance().GetDisableVersionCheck()); + break; + + case Id_LockSkinsCheckBox: + Rainmeter::GetInstance().SetDisableDragging(!Rainmeter::GetInstance().GetDisableDragging()); + break; + + case Id_ResetStatisticsButton: + Rainmeter::GetInstance().ResetStats(); + break; + + case Id_ShowLogFileButton: + Rainmeter::GetInstance().ShowLogFile(); + break; + + case Id_DeleteLogFileButton: + GetLogger().DeleteLogFile(); + if (_waccess(GetLogger().GetLogFilePath().c_str(), 0) == -1) + { + Button_SetCheck(GetControl(Id_LogToFileCheckBox), BST_UNCHECKED); + EnableWindow(GetControl(Id_ShowLogFileButton), FALSE); + EnableWindow(GetControl(Id_DeleteLogFileButton), FALSE); + } + break; + + case Id_LogToFileCheckBox: + if (GetLogger().IsLogToFile()) + { + GetLogger().StopLogFile(); + } + else + { + GetLogger().StartLogFile(); + if (_waccess(GetLogger().GetLogFilePath().c_str(), 0) != -1) + { + EnableWindow(GetControl(Id_ShowLogFileButton), TRUE); + EnableWindow(GetControl(Id_DeleteLogFileButton), TRUE); + } + } + break; + + case Id_VerboseLoggingCheckbox: + Rainmeter::GetInstance().SetDebug(!Rainmeter::GetInstance().GetDebug()); + break; + + case Id_EditorEdit: + if (HIWORD(wParam) == EN_CHANGE) + { + WCHAR buffer[MAX_PATH]; + if (GetWindowText((HWND)lParam, buffer, _countof(buffer)) > 0) + { + Rainmeter::GetInstance().SetSkinEditor(buffer); + } + } + break; + + case Id_EditorBrowseButton: + { + WCHAR buffer[MAX_PATH]; + buffer[0] = L'\0'; + + std::wstring editor = Rainmeter::GetInstance().GetSkinEditor(); + editor = editor.substr(0, editor.find_last_of(L"/\\")).c_str(); + + OPENFILENAME ofn = { sizeof(OPENFILENAME) }; + ofn.Flags = OFN_FILEMUSTEXIST; + ofn.lpstrFilter = L"Executable File (.exe)\0*.exe"; + ofn.lpstrTitle = L"Select executable file"; + ofn.lpstrDefExt = L"exe"; + ofn.lpstrInitialDir = editor.c_str(); + ofn.nFilterIndex = 0; + ofn.lpstrFile = buffer; + ofn.nMaxFile = _countof(buffer); + ofn.hwndOwner = c_Dialog->GetWindow(); + + if (!GetOpenFileName(&ofn)) + { + break; + } + + Edit_SetText(GetControl(Id_EditorEdit), buffer); + } + break; + + case Id_ShowTrayIconCheckBox: + Rainmeter::GetInstance().GetTrayWindow()->SetTrayIcon(!Rainmeter::GetInstance().GetTrayWindow()->IsTrayIconEnabled()); + break; + + case Id_UseD2DCheckBox: + Rainmeter::GetInstance().SetUseD2D(!Rainmeter::GetInstance().GetUseD2D()); + break; + + default: + return 1; + } + + return 0; } \ No newline at end of file diff --git a/Library/DialogManage.h b/Library/DialogManage.h index 8e61b2b8..1308128c 100644 --- a/Library/DialogManage.h +++ b/Library/DialogManage.h @@ -1,193 +1,193 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __DIALOGMANAGE_H__ -#define __DIALOGMANAGE_H__ - -#include "../Common/Dialog.h" -#include "resource.h" - -class DialogManage : public Dialog -{ -public: - DialogManage(); - virtual ~DialogManage(); - - DialogManage(const DialogManage& other) = delete; - DialogManage& operator=(DialogManage other) = delete; - - static Dialog* GetDialog() { return c_Dialog; } - - static void Open(const WCHAR* tabName, const WCHAR* param1, const WCHAR* param2); - static void Open(const WCHAR* name); - static void Open(int tab = 0); - static void OpenSkin(MeterWindow* meterWindow); - - static void UpdateSkins(MeterWindow* meterWindow, bool deleted = false); - static void UpdateLayouts(); - -protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - -private: - // Skins tab - class TabSkins : public Tab - { - public: - enum Id - { - Id_ActiveSkinsButton = 100, - Id_SkinsTreeView, - Id_CreateSkinPackageButton, - Id_FileLabel, - Id_ConfigLabel, - Id_AuthorLabel, - Id_VersionLabel, - Id_LicenseLabel, - Id_DescriptionLabel, - Id_AddMetadataLink, - Id_XPositionEdit, - Id_YPositionEdit, - Id_ZPositionDropDownList, - Id_LoadOrderEdit, - Id_OnHoverDropDownList, - Id_TransparencyDropDownList, - Id_DisplayMonitorButton, - Id_DraggableCheckBox, - Id_ClickThroughCheckBox, - Id_KeepOnScreenCheckBox, - Id_SavePositionCheckBox, - Id_SnapToEdgesCheckBox, - - Id_LoadButton = IDM_MANAGESKINSMENU_LOAD, - Id_RefreshButton = IDM_MANAGESKINSMENU_REFRESH, - Id_EditButton = IDM_MANAGESKINSMENU_EDIT - }; - - TabSkins(); - - void Create(HWND owner); - virtual void Initialize(); - - void Update(MeterWindow* meterWindow, bool deleted); - - static void SelectTreeItem(HWND tree, HTREEITEM item, LPCWSTR name); - - protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - - private: - void SetControls(); - void DisableControls(bool clear = false); - void ReadSkin(); - - static std::wstring GetTreeSelectionPath(HWND tree); - static int PopulateTree(HWND tree, TVINSERTSTRUCT& tvi, int index = 0); - - std::wstring m_SkinFileName; - std::wstring m_SkinFolderPath; - MeterWindow* m_SkinWindow; - bool m_HandleCommands; - bool m_IgnoreUpdate; - }; - - // Layouts tab - class TabLayouts : public Tab - { - public: - enum Id - { - Id_List = 100, - Id_LoadButton, - Id_DeleteButton, - Id_EditButton, - Id_SaveButton, - Id_SaveEmptyThemeCheckBox, - Id_ExcludeUnusedSkinsCheckBox, - Id_IncludeWallpaperCheckBox, - Id_NameLabel - }; - - TabLayouts(); - - void Create(HWND owner); - virtual void Initialize(); - - void Update(); - - protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - }; - - // Settings tab - class TabSettings : public Tab - { - public: - enum Id - { - Id_CheckForUpdatesCheckBox = 100, - Id_LockSkinsCheckBox, - Id_ResetStatisticsButton, - Id_LogToFileCheckBox, - Id_VerboseLoggingCheckbox, - Id_ShowLogFileButton, - Id_DeleteLogFileButton, - Id_LanguageDropDownList, - Id_EditorEdit, - Id_EditorBrowseButton, - Id_ShowTrayIconCheckBox, - Id_UseD2DCheckBox - }; - - TabSettings(); - - void Create(HWND owner); - virtual void Initialize(); - - protected: - virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - }; - - enum Id - { - Id_CloseButton = IDCLOSE, - Id_Tab = 100, - Id_RefreshAllButton, - Id_EditSettingsButton, - Id_OpenLogButton, - Id_HelpButton - }; - - Tab& GetActiveTab(); - - TabSkins m_TabSkins; - TabLayouts m_TabLayouts; - TabSettings m_TabSettings; - - static WINDOWPLACEMENT c_WindowPlacement; - static DialogManage* c_Dialog; -}; - -#endif +/* + Copyright (C) 2011 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __DIALOGMANAGE_H__ +#define __DIALOGMANAGE_H__ + +#include "../Common/Dialog.h" +#include "resource.h" + +class DialogManage : public Dialog +{ +public: + DialogManage(); + virtual ~DialogManage(); + + DialogManage(const DialogManage& other) = delete; + DialogManage& operator=(DialogManage other) = delete; + + static Dialog* GetDialog() { return c_Dialog; } + + static void Open(const WCHAR* tabName, const WCHAR* param1, const WCHAR* param2); + static void Open(const WCHAR* name); + static void Open(int tab = 0); + static void OpenSkin(MeterWindow* meterWindow); + + static void UpdateSkins(MeterWindow* meterWindow, bool deleted = false); + static void UpdateLayouts(); + +protected: + virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + +private: + // Skins tab + class TabSkins : public Tab + { + public: + enum Id + { + Id_ActiveSkinsButton = 100, + Id_SkinsTreeView, + Id_CreateSkinPackageButton, + Id_FileLabel, + Id_ConfigLabel, + Id_AuthorLabel, + Id_VersionLabel, + Id_LicenseLabel, + Id_DescriptionLabel, + Id_AddMetadataLink, + Id_XPositionEdit, + Id_YPositionEdit, + Id_ZPositionDropDownList, + Id_LoadOrderEdit, + Id_OnHoverDropDownList, + Id_TransparencyDropDownList, + Id_DisplayMonitorButton, + Id_DraggableCheckBox, + Id_ClickThroughCheckBox, + Id_KeepOnScreenCheckBox, + Id_SavePositionCheckBox, + Id_SnapToEdgesCheckBox, + + Id_LoadButton = IDM_MANAGESKINSMENU_LOAD, + Id_RefreshButton = IDM_MANAGESKINSMENU_REFRESH, + Id_EditButton = IDM_MANAGESKINSMENU_EDIT + }; + + TabSkins(); + + void Create(HWND owner); + virtual void Initialize(); + + void Update(MeterWindow* meterWindow, bool deleted); + + static void SelectTreeItem(HWND tree, HTREEITEM item, LPCWSTR name); + + protected: + virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + + private: + void SetControls(); + void DisableControls(bool clear = false); + void ReadSkin(); + + static std::wstring GetTreeSelectionPath(HWND tree); + static int PopulateTree(HWND tree, TVINSERTSTRUCT& tvi, int index = 0); + + std::wstring m_SkinFileName; + std::wstring m_SkinFolderPath; + MeterWindow* m_SkinWindow; + bool m_HandleCommands; + bool m_IgnoreUpdate; + }; + + // Layouts tab + class TabLayouts : public Tab + { + public: + enum Id + { + Id_List = 100, + Id_LoadButton, + Id_DeleteButton, + Id_EditButton, + Id_SaveButton, + Id_SaveEmptyThemeCheckBox, + Id_ExcludeUnusedSkinsCheckBox, + Id_IncludeWallpaperCheckBox, + Id_NameLabel + }; + + TabLayouts(); + + void Create(HWND owner); + virtual void Initialize(); + + void Update(); + + protected: + virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + }; + + // Settings tab + class TabSettings : public Tab + { + public: + enum Id + { + Id_CheckForUpdatesCheckBox = 100, + Id_LockSkinsCheckBox, + Id_ResetStatisticsButton, + Id_LogToFileCheckBox, + Id_VerboseLoggingCheckbox, + Id_ShowLogFileButton, + Id_DeleteLogFileButton, + Id_LanguageDropDownList, + Id_EditorEdit, + Id_EditorBrowseButton, + Id_ShowTrayIconCheckBox, + Id_UseD2DCheckBox + }; + + TabSettings(); + + void Create(HWND owner); + virtual void Initialize(); + + protected: + virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + }; + + enum Id + { + Id_CloseButton = IDCLOSE, + Id_Tab = 100, + Id_RefreshAllButton, + Id_EditSettingsButton, + Id_OpenLogButton, + Id_HelpButton + }; + + Tab& GetActiveTab(); + + TabSkins m_TabSkins; + TabLayouts m_TabLayouts; + TabSettings m_TabSettings; + + static WINDOWPLACEMENT c_WindowPlacement; + static DialogManage* c_Dialog; +}; + +#endif diff --git a/Library/Error.cpp b/Library/Error.cpp index 31cf0759..8135eac8 100644 --- a/Library/Error.cpp +++ b/Library/Error.cpp @@ -1,22 +1,22 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Error.h" - -// Leave this file as it is for history on Google code. +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Error.h" + +// Leave this file as it is for history on Google code. diff --git a/Library/Error.h b/Library/Error.h index 2a329218..f2676eb9 100644 --- a/Library/Error.h +++ b/Library/Error.h @@ -1,37 +1,37 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __ERROR_H__ -#define __ERROR_H__ - -#include -#include - -class CError -{ -public: - CError(const std::wstring& String) : m_String(String) {} - CError(const WCHAR* String) : m_String(String) {} - - const std::wstring& GetString() { return m_String; } - -private: - std::wstring m_String; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __ERROR_H__ +#define __ERROR_H__ + +#include +#include + +class CError +{ +public: + CError(const std::wstring& String) : m_String(String) {} + CError(const WCHAR* String) : m_String(String) {} + + const std::wstring& GetString() { return m_String; } + +private: + std::wstring m_String; +}; + +#endif diff --git a/Library/Export.cpp b/Library/Export.cpp index 8e297001..ab82057b 100644 --- a/Library/Export.cpp +++ b/Library/Export.cpp @@ -1,262 +1,262 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas, Peter Souza - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Rainmeter.h" -#include "Export.h" -#include "MeterWindow.h" -#include "Measure.h" -#include "MeasurePlugin.h" - -#define NULLCHECK(str) { if ((str) == nullptr) { (str) = L""; } } - -static std::wstring g_Buffer; - -LPCWSTR __stdcall RmReadString(void* rm, LPCWSTR option, LPCWSTR defValue, BOOL replaceMeasures) -{ - NULLCHECK(option); - NULLCHECK(defValue); - - MeasurePlugin* measure = (MeasurePlugin*)rm; - ConfigParser& parser = measure->GetMeterWindow()->GetParser(); - return parser.ReadString(measure->GetName(), option, defValue, replaceMeasures != FALSE).c_str(); -} - -double __stdcall RmReadFormula(void* rm, LPCWSTR option, double defValue) -{ - NULLCHECK(option); - - MeasurePlugin* measure = (MeasurePlugin*)rm; - ConfigParser& parser = measure->GetMeterWindow()->GetParser(); - return parser.ReadFloat(measure->GetName(), option, defValue); -} - -LPCWSTR __stdcall RmReplaceVariables(void* rm, LPCWSTR str) -{ - NULLCHECK(str); - - MeasurePlugin* measure = (MeasurePlugin*)rm; - ConfigParser& parser = measure->GetMeterWindow()->GetParser(); - g_Buffer = str; - parser.ReplaceVariables(g_Buffer); - parser.ReplaceMeasures(g_Buffer); - return g_Buffer.c_str(); -} - -LPCWSTR __stdcall RmPathToAbsolute(void* rm, LPCWSTR relativePath) -{ - NULLCHECK(relativePath); - - MeasurePlugin* measure = (MeasurePlugin*)rm; - g_Buffer = relativePath; - measure->GetMeterWindow()->MakePathAbsolute(g_Buffer); - return g_Buffer.c_str(); -} - -void* __stdcall RmGet(void* rm, int type) -{ - MeasurePlugin* measure = (MeasurePlugin*)rm; - - switch (type) - { - case RMG_MEASURENAME: - { - return (void*)measure->GetName(); - } - - case RMG_SKIN: - { - return (void*)measure->GetMeterWindow(); - } - - case RMG_SETTINGSFILE: - { - return (void*)Rainmeter::GetInstance().GetDataFile().c_str(); - } - - case RMG_SKINNAME: - { - MeterWindow* window = measure->GetMeterWindow(); - if (!window) break; - return (void*)window->GetFolderPath().c_str(); - } - - case RMG_SKINWINDOWHANDLE: - { - MeterWindow* window = measure->GetMeterWindow(); - if (!window) break; - return (void*)window->GetWindow(); - } - } - - return nullptr; -} - -void __stdcall RmExecute(void* skin, LPCWSTR command) -{ - MeterWindow* mw = (MeterWindow*)skin; - if (command) - { - // WM_RAINMETER_EXECUTE used instead of ExecuteCommand for thread-safety - SendMessage(Rainmeter::GetInstance().GetWindow(), WM_RAINMETER_EXECUTE, (WPARAM)mw, (LPARAM)command); - } -} - -BOOL LSLog(int level, LPCWSTR unused, LPCWSTR message) -{ - NULLCHECK(message); - - // Ignore Debug messages from plugins unless in debug mode. - if (level != (int)Logger::Level::Debug || Rainmeter::GetInstance().GetDebug()) - { - GetLogger().Log((Logger::Level)level, L"", message); - } - - return TRUE; -} - -void __stdcall RmLog(void* rm, int level, LPCWSTR message) -{ - NULLCHECK(message); - - MeasurePlugin* measure = (MeasurePlugin*)rm; - - // Ignore Debug messages from plugins unless in debug mode. - if (level != (int)Logger::Level::Debug || Rainmeter::GetInstance().GetDebug()) - { - GetLogger().LogSection((Logger::Level)level, measure, message); - } -} - -void RmLogF(void* rm, int level, LPCWSTR format, ...) -{ - NULLCHECK(format); - - MeasurePlugin* measure = (MeasurePlugin*)rm; - - // Ignore Debug messages from plugins unless in debug mode. - if (level != (int)Logger::Level::Debug || Rainmeter::GetInstance().GetDebug()) - { - va_list args; - va_start(args, format); - GetLogger().LogSectionVF((Logger::Level)level, measure, format, args); - va_end(args); - } -} - -// Deprecated! -LPCWSTR ReadConfigString(LPCWSTR section, LPCWSTR option, LPCWSTR defValue) -{ - NULLCHECK(section); - NULLCHECK(option); - NULLCHECK(defValue); - - ConfigParser* parser = Rainmeter::GetInstance().GetCurrentParser(); - if (parser) - { - return parser->ReadString(section, option, defValue, false).c_str(); - } - - return defValue; -} - -// Deprecated! -LPCWSTR PluginBridge(LPCWSTR command, LPCWSTR data) -{ - if (command == nullptr || *command == L'\0') - { - return L"noop"; - } - - NULLCHECK(data); - - if (_wcsicmp(command, L"GetConfig") == 0) - { - MeterWindow* meterWindow = Rainmeter::GetInstance().GetMeterWindowByINI(data); - if (meterWindow) - { - g_Buffer = L"\""; - g_Buffer += meterWindow->GetFolderPath(); - g_Buffer += L"\""; - return g_Buffer.c_str(); - } - - return L""; - } - else if (_wcsicmp(command, L"GetWindow") == 0) - { - std::vector subStrings = CommandHandler::ParseString(data); - - if (subStrings.size() >= 1) - { - const std::wstring& config = subStrings[0]; - - MeterWindow* meterWindow = Rainmeter::GetInstance().GetMeterWindow(config); - if (meterWindow) - { - WCHAR buf1[64]; - _snwprintf_s(buf1, _TRUNCATE, L"%lu", PtrToUlong(meterWindow->GetWindow())); - g_Buffer = buf1; - return g_Buffer.c_str(); - } - } - - return L"error"; - } - else if (_wcsicmp(command, L"GetVariable") == 0) - { - std::vector subStrings = CommandHandler::ParseString(data); - - if (subStrings.size() >= 2) - { - const std::wstring& config = subStrings[0]; - - MeterWindow* meterWindow = Rainmeter::GetInstance().GetMeterWindow(config); - if (meterWindow) - { - const std::wstring& variable = subStrings[1]; - - const std::wstring* value = meterWindow->GetParser().GetVariable(variable); - if (value) - { - return (*value).c_str(); - } - } - } - - return L""; - } - else if (_wcsicmp(command, L"SetVariable") == 0) - { - std::vector subStrings = CommandHandler::ParseString(data); - - if (subStrings.size() == 3) - { - MeterWindow* meterWindow = Rainmeter::GetInstance().GetMeterWindow(subStrings[0]); - if (meterWindow) - { - meterWindow->SetVariable(subStrings[1], subStrings[2]); - return L"success"; - } - } - - return L"error"; - } - - return L"noop"; -} +/* + Copyright (C) 2011 Birunthan Mohanathas, Peter Souza + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Rainmeter.h" +#include "Export.h" +#include "MeterWindow.h" +#include "Measure.h" +#include "MeasurePlugin.h" + +#define NULLCHECK(str) { if ((str) == nullptr) { (str) = L""; } } + +static std::wstring g_Buffer; + +LPCWSTR __stdcall RmReadString(void* rm, LPCWSTR option, LPCWSTR defValue, BOOL replaceMeasures) +{ + NULLCHECK(option); + NULLCHECK(defValue); + + MeasurePlugin* measure = (MeasurePlugin*)rm; + ConfigParser& parser = measure->GetMeterWindow()->GetParser(); + return parser.ReadString(measure->GetName(), option, defValue, replaceMeasures != FALSE).c_str(); +} + +double __stdcall RmReadFormula(void* rm, LPCWSTR option, double defValue) +{ + NULLCHECK(option); + + MeasurePlugin* measure = (MeasurePlugin*)rm; + ConfigParser& parser = measure->GetMeterWindow()->GetParser(); + return parser.ReadFloat(measure->GetName(), option, defValue); +} + +LPCWSTR __stdcall RmReplaceVariables(void* rm, LPCWSTR str) +{ + NULLCHECK(str); + + MeasurePlugin* measure = (MeasurePlugin*)rm; + ConfigParser& parser = measure->GetMeterWindow()->GetParser(); + g_Buffer = str; + parser.ReplaceVariables(g_Buffer); + parser.ReplaceMeasures(g_Buffer); + return g_Buffer.c_str(); +} + +LPCWSTR __stdcall RmPathToAbsolute(void* rm, LPCWSTR relativePath) +{ + NULLCHECK(relativePath); + + MeasurePlugin* measure = (MeasurePlugin*)rm; + g_Buffer = relativePath; + measure->GetMeterWindow()->MakePathAbsolute(g_Buffer); + return g_Buffer.c_str(); +} + +void* __stdcall RmGet(void* rm, int type) +{ + MeasurePlugin* measure = (MeasurePlugin*)rm; + + switch (type) + { + case RMG_MEASURENAME: + { + return (void*)measure->GetName(); + } + + case RMG_SKIN: + { + return (void*)measure->GetMeterWindow(); + } + + case RMG_SETTINGSFILE: + { + return (void*)Rainmeter::GetInstance().GetDataFile().c_str(); + } + + case RMG_SKINNAME: + { + MeterWindow* window = measure->GetMeterWindow(); + if (!window) break; + return (void*)window->GetFolderPath().c_str(); + } + + case RMG_SKINWINDOWHANDLE: + { + MeterWindow* window = measure->GetMeterWindow(); + if (!window) break; + return (void*)window->GetWindow(); + } + } + + return nullptr; +} + +void __stdcall RmExecute(void* skin, LPCWSTR command) +{ + MeterWindow* mw = (MeterWindow*)skin; + if (command) + { + // WM_RAINMETER_EXECUTE used instead of ExecuteCommand for thread-safety + SendMessage(Rainmeter::GetInstance().GetWindow(), WM_RAINMETER_EXECUTE, (WPARAM)mw, (LPARAM)command); + } +} + +BOOL LSLog(int level, LPCWSTR unused, LPCWSTR message) +{ + NULLCHECK(message); + + // Ignore Debug messages from plugins unless in debug mode. + if (level != (int)Logger::Level::Debug || Rainmeter::GetInstance().GetDebug()) + { + GetLogger().Log((Logger::Level)level, L"", message); + } + + return TRUE; +} + +void __stdcall RmLog(void* rm, int level, LPCWSTR message) +{ + NULLCHECK(message); + + MeasurePlugin* measure = (MeasurePlugin*)rm; + + // Ignore Debug messages from plugins unless in debug mode. + if (level != (int)Logger::Level::Debug || Rainmeter::GetInstance().GetDebug()) + { + GetLogger().LogSection((Logger::Level)level, measure, message); + } +} + +void RmLogF(void* rm, int level, LPCWSTR format, ...) +{ + NULLCHECK(format); + + MeasurePlugin* measure = (MeasurePlugin*)rm; + + // Ignore Debug messages from plugins unless in debug mode. + if (level != (int)Logger::Level::Debug || Rainmeter::GetInstance().GetDebug()) + { + va_list args; + va_start(args, format); + GetLogger().LogSectionVF((Logger::Level)level, measure, format, args); + va_end(args); + } +} + +// Deprecated! +LPCWSTR ReadConfigString(LPCWSTR section, LPCWSTR option, LPCWSTR defValue) +{ + NULLCHECK(section); + NULLCHECK(option); + NULLCHECK(defValue); + + ConfigParser* parser = Rainmeter::GetInstance().GetCurrentParser(); + if (parser) + { + return parser->ReadString(section, option, defValue, false).c_str(); + } + + return defValue; +} + +// Deprecated! +LPCWSTR PluginBridge(LPCWSTR command, LPCWSTR data) +{ + if (command == nullptr || *command == L'\0') + { + return L"noop"; + } + + NULLCHECK(data); + + if (_wcsicmp(command, L"GetConfig") == 0) + { + MeterWindow* meterWindow = Rainmeter::GetInstance().GetMeterWindowByINI(data); + if (meterWindow) + { + g_Buffer = L"\""; + g_Buffer += meterWindow->GetFolderPath(); + g_Buffer += L"\""; + return g_Buffer.c_str(); + } + + return L""; + } + else if (_wcsicmp(command, L"GetWindow") == 0) + { + std::vector subStrings = CommandHandler::ParseString(data); + + if (subStrings.size() >= 1) + { + const std::wstring& config = subStrings[0]; + + MeterWindow* meterWindow = Rainmeter::GetInstance().GetMeterWindow(config); + if (meterWindow) + { + WCHAR buf1[64]; + _snwprintf_s(buf1, _TRUNCATE, L"%lu", PtrToUlong(meterWindow->GetWindow())); + g_Buffer = buf1; + return g_Buffer.c_str(); + } + } + + return L"error"; + } + else if (_wcsicmp(command, L"GetVariable") == 0) + { + std::vector subStrings = CommandHandler::ParseString(data); + + if (subStrings.size() >= 2) + { + const std::wstring& config = subStrings[0]; + + MeterWindow* meterWindow = Rainmeter::GetInstance().GetMeterWindow(config); + if (meterWindow) + { + const std::wstring& variable = subStrings[1]; + + const std::wstring* value = meterWindow->GetParser().GetVariable(variable); + if (value) + { + return (*value).c_str(); + } + } + } + + return L""; + } + else if (_wcsicmp(command, L"SetVariable") == 0) + { + std::vector subStrings = CommandHandler::ParseString(data); + + if (subStrings.size() == 3) + { + MeterWindow* meterWindow = Rainmeter::GetInstance().GetMeterWindow(subStrings[0]); + if (meterWindow) + { + meterWindow->SetVariable(subStrings[1], subStrings[2]); + return L"success"; + } + } + + return L"error"; + } + + return L"noop"; +} diff --git a/Library/Export.h b/Library/Export.h index db3e90df..eb93323e 100644 --- a/Library/Export.h +++ b/Library/Export.h @@ -1,28 +1,28 @@ -/* - Copyright (C) 2011 Kimmo Pekkola, Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __EXPORT_H__ -#define __EXPORT_H__ - -#include "../Plugins/API/RainmeterAPI.h" - -/* DEPRECATED */ LIBRARY_EXPORT __declspec(deprecated) LPCWSTR ReadConfigString(LPCWSTR section, LPCWSTR option, LPCWSTR defValue); - -/* DEPRECATED */ LIBRARY_EXPORT __declspec(deprecated) LPCWSTR PluginBridge(LPCWSTR command, LPCWSTR data); - -#endif +/* + Copyright (C) 2011 Kimmo Pekkola, Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __EXPORT_H__ +#define __EXPORT_H__ + +#include "../Plugins/API/RainmeterAPI.h" + +/* DEPRECATED */ LIBRARY_EXPORT __declspec(deprecated) LPCWSTR ReadConfigString(LPCWSTR section, LPCWSTR option, LPCWSTR defValue); + +/* DEPRECATED */ LIBRARY_EXPORT __declspec(deprecated) LPCWSTR PluginBridge(LPCWSTR command, LPCWSTR data); + +#endif diff --git a/Library/Exports.def b/Library/Exports.def index 58b76fc1..98380625 100644 --- a/Library/Exports.def +++ b/Library/Exports.def @@ -1,22 +1,22 @@ -LIBRARY -EXPORTS - ; Note: If new functions are added, the Rainmeter.lib files in Plugins\API\{x32,x64} must be - ; replaced by the corresponding file in {x32,x64}-Release\Obj\Library. - ; Set 'true' in Rainmeter.props first to minimize the .lib size. - RmReadString - RmReadFormula - RmReplaceVariables - RmPathToAbsolute - RmExecute - RmGet - RmLog - RmLogF - LSLog - ReadConfigString - PluginBridge - - ; Private - RainmeterMain @1 NONAME - pcre_compile @2 NONAME - pcre_exec @3 NONAME - pcre_study @4 NONAME +LIBRARY +EXPORTS + ; Note: If new functions are added, the Rainmeter.lib files in Plugins\API\{x32,x64} must be + ; replaced by the corresponding file in {x32,x64}-Release\Obj\Library. + ; Set 'true' in Rainmeter.props first to minimize the .lib size. + RmReadString + RmReadFormula + RmReplaceVariables + RmPathToAbsolute + RmExecute + RmGet + RmLog + RmLogF + LSLog + ReadConfigString + PluginBridge + + ; Private + RainmeterMain @1 NONAME + pcre_compile @2 NONAME + pcre_exec @3 NONAME + pcre_study @4 NONAME diff --git a/Library/Group.cpp b/Library/Group.cpp index 9e14d544..365aaddc 100644 --- a/Library/Group.cpp +++ b/Library/Group.cpp @@ -1,66 +1,66 @@ -/* - Copyright (C) 2010 spx - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Group.h" -#include "ConfigParser.h" - -void Group::InitializeGroup(const std::wstring& groups) -{ - if (wcscmp(groups.c_str(), m_OldGroups.c_str()) != 0) - { - m_OldGroups = groups; - m_Groups.clear(); - - if (!groups.empty()) - { - std::vector vGroups = ConfigParser::Tokenize(groups, L"|"); - for (auto iter = vGroups.begin(); iter != vGroups.end(); ++iter) - { - m_Groups.insert(CreateGroup(*iter)); - } - } - } -} - -bool Group::BelongsToGroup(const std::wstring& group) const -{ - return (m_Groups.find(VerifyGroup(group)) != m_Groups.end()); -} - -std::wstring& Group::CreateGroup(std::wstring& str) const -{ - _wcsupr(&str[0]); - return str; -} - -std::wstring Group::VerifyGroup(const std::wstring& str) const -{ - std::wstring strTmp; - - std::wstring::size_type pos = str.find_first_not_of(L" \t\r\n"); - if (pos != std::wstring::npos) - { - // Trim white-space - strTmp.assign(str, pos, str.find_last_not_of(L" \t\r\n") - pos + 1); - - CreateGroup(strTmp); - } - - return strTmp; +/* + Copyright (C) 2010 spx + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Group.h" +#include "ConfigParser.h" + +void Group::InitializeGroup(const std::wstring& groups) +{ + if (wcscmp(groups.c_str(), m_OldGroups.c_str()) != 0) + { + m_OldGroups = groups; + m_Groups.clear(); + + if (!groups.empty()) + { + std::vector vGroups = ConfigParser::Tokenize(groups, L"|"); + for (auto iter = vGroups.begin(); iter != vGroups.end(); ++iter) + { + m_Groups.insert(CreateGroup(*iter)); + } + } + } +} + +bool Group::BelongsToGroup(const std::wstring& group) const +{ + return (m_Groups.find(VerifyGroup(group)) != m_Groups.end()); +} + +std::wstring& Group::CreateGroup(std::wstring& str) const +{ + _wcsupr(&str[0]); + return str; +} + +std::wstring Group::VerifyGroup(const std::wstring& str) const +{ + std::wstring strTmp; + + std::wstring::size_type pos = str.find_first_not_of(L" \t\r\n"); + if (pos != std::wstring::npos) + { + // Trim white-space + strTmp.assign(str, pos, str.find_last_not_of(L" \t\r\n") - pos + 1); + + CreateGroup(strTmp); + } + + return strTmp; } \ No newline at end of file diff --git a/Library/Group.h b/Library/Group.h index d7464a6a..aece6674 100644 --- a/Library/Group.h +++ b/Library/Group.h @@ -1,49 +1,49 @@ -/* - Copyright (C) 2010 spx - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __GROUP_H__ -#define __GROUP_H__ - -#include -#include - -class __declspec(novtable) Group -{ -public: - virtual ~Group() {} - - Group(const Group& other) = delete; - Group& operator=(Group other) = delete; - - bool BelongsToGroup(const std::wstring& group) const; - -protected: - Group() {} - - void InitializeGroup(const std::wstring& groups); - -private: - std::wstring& CreateGroup(std::wstring& str) const; - std::wstring VerifyGroup(const std::wstring& str) const; - - std::unordered_set m_Groups; - std::wstring m_OldGroups; - -}; - -#endif +/* + Copyright (C) 2010 spx + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __GROUP_H__ +#define __GROUP_H__ + +#include +#include + +class __declspec(novtable) Group +{ +public: + virtual ~Group() {} + + Group(const Group& other) = delete; + Group& operator=(Group other) = delete; + + bool BelongsToGroup(const std::wstring& group) const; + +protected: + Group() {} + + void InitializeGroup(const std::wstring& groups); + +private: + std::wstring& CreateGroup(std::wstring& str) const; + std::wstring VerifyGroup(const std::wstring& str) const; + + std::unordered_set m_Groups; + std::wstring m_OldGroups; + +}; + +#endif diff --git a/Library/IfActions.cpp b/Library/IfActions.cpp index 0f219a81..178274ee 100644 --- a/Library/IfActions.cpp +++ b/Library/IfActions.cpp @@ -1,367 +1,367 @@ -/* - Copyright (C) 2013 Brian Ferguson - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Measure.h" -#include "IfActions.h" -#include "Rainmeter.h" -#include "../Common/MathParser.h" -#include "pcre-8.10/config.h" -#include "pcre-8.10/pcre.h" - -IfActions::IfActions() : - m_AboveValue(0.0f), - m_BelowValue(0.0f), - m_EqualValue(0), - m_AboveAction(), - m_BelowAction(), - m_EqualAction(), - m_AboveCommitted(false), - m_BelowCommitted(false), - m_EqualCommitted(false), - m_Conditions(), - m_ConditionMode(false), - m_Matches(), - m_MatchMode(false) -{ -} - -IfActions::~IfActions() -{ -} - -void IfActions::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - m_AboveAction = parser.ReadString(section, L"IfAboveAction", L"", false); - m_AboveValue = parser.ReadFloat(section, L"IfAboveValue", 0.0f); - - m_BelowAction = parser.ReadString(section, L"IfBelowAction", L"", false); - m_BelowValue = parser.ReadFloat(section, L"IfBelowValue", 0.0f); - - m_EqualAction = parser.ReadString(section, L"IfEqualAction", L"", false); - m_EqualValue = (int64_t)parser.ReadFloat(section, L"IfEqualValue", 0.0f); -} - -void IfActions::ReadConditionOptions(ConfigParser& parser, const WCHAR* section) -{ - // IfCondition options - m_ConditionMode = parser.ReadBool(section, L"IfConditionMode", false); - - std::wstring condition = parser.ReadString(section, L"IfCondition", L""); - if (!condition.empty()) - { - std::wstring tAction = parser.ReadString(section, L"IfTrueAction", L"", false); - std::wstring fAction = parser.ReadString(section, L"IfFalseAction", L"", false); - if (!tAction.empty() || !fAction.empty()) - { - size_t i = 1; - do - { - if (m_Conditions.size() > (i - 1)) - { - m_Conditions[i - 1].Set(condition, tAction, fAction); - } - else - { - m_Conditions.emplace_back(condition, tAction, fAction); - } - - // Check for IfCondition2/IfTrueAction2/IfFalseAction2 ... etc. - const std::wstring num = std::to_wstring(++i); - - std::wstring key = L"IfCondition" + num; - condition = parser.ReadString(section, key.c_str(), L""); - if (condition.empty()) break; - - key = L"IfTrueAction" + num; - tAction = parser.ReadString(section, key.c_str(), L"", false); - key = L"IfFalseAction" + num; - fAction = parser.ReadString(section, key.c_str(), L"", false); - } - while (!tAction.empty() || !fAction.empty()); - } - else - { - m_Conditions.clear(); - } - } - else - { - m_Conditions.clear(); - } - - // IfMatch options - m_MatchMode = parser.ReadBool(section, L"IfMatchMode", false); - - std::wstring match = parser.ReadString(section, L"IfMatch", L""); - if (!match.empty()) - { - std::wstring tAction = parser.ReadString(section, L"IfMatchAction", L"", false); - std::wstring fAction = parser.ReadString(section, L"IfNotMatchAction", L"", false); - if (!tAction.empty() || !fAction.empty()) - { - size_t i = 1; - do - { - if (m_Matches.size() > (i - 1)) - { - m_Matches[i - 1].Set(match, tAction, fAction); - } - else - { - m_Matches.emplace_back(match, tAction, fAction); - } - - // Check for IfMatch2/IfMatchAction2/IfNotMatchAction2 ... etc. - const std::wstring num = std::to_wstring(++i); - - std::wstring key = L"IfMatch" + num; - match = parser.ReadString(section, key.c_str(), L""); - if (match.empty()) break; - - key = L"IfMatchAction" + num; - tAction = parser.ReadString(section, key.c_str(), L"", false); - key = L"IfNotMatchAction" + num; - fAction = parser.ReadString(section, key.c_str(), L"", false); - } while (!tAction.empty() || !fAction.empty()); - } - else - { - m_Matches.clear(); - } - } - else - { - m_Matches.clear(); - } -} - -void IfActions::DoIfActions(Measure& measure, double value) -{ - // IfEqual - if (!m_EqualAction.empty()) - { - if ((int64_t)value == m_EqualValue) - { - if (!m_EqualCommitted) - { - m_EqualCommitted = true; // To avoid infinite loop from !Update - Rainmeter::GetInstance().ExecuteCommand(m_EqualAction.c_str(), measure.GetMeterWindow()); - } - } - else - { - m_EqualCommitted = false; - } - } - - // IfAbove - if (!m_AboveAction.empty()) - { - if (value > m_AboveValue) - { - if (!m_AboveCommitted) - { - m_AboveCommitted = true; // To avoid infinite loop from !Update - Rainmeter::GetInstance().ExecuteCommand(m_AboveAction.c_str(), measure.GetMeterWindow()); - } - } - else - { - m_AboveCommitted = false; - } - } - - // IfBelow - if (!m_BelowAction.empty()) - { - if (value < m_BelowValue) - { - if (!m_BelowCommitted) - { - m_BelowCommitted = true; // To avoid infinite loop from !Update - Rainmeter::GetInstance().ExecuteCommand(m_BelowAction.c_str(), measure.GetMeterWindow()); - } - } - else - { - m_BelowCommitted = false; - } - } - - // IfCondition - int i = 0; - for (auto& item : m_Conditions) - { - ++i; - if (!item.value.empty() && (!item.tAction.empty() || !item.fAction.empty())) - { - double result = 0.0f; - const WCHAR* errMsg = MathParser::Parse( - item.value.c_str(), &result, measure.GetCurrentMeasureValue, &measure); - if (errMsg != nullptr) - { - if (!item.parseError) - { - if (i == 1) - { - LogErrorF(&measure, L"%s: IfCondition=%s", errMsg, item.value.c_str()); - } - else - { - LogErrorF(&measure, L"%s: IfCondition%i=%s", errMsg, i, item.value.c_str()); - } - item.parseError = true; - } - } - else - { - item.parseError = false; - - if (result == 1.0f) // "True" - { - item.fCommitted = false; - - if (m_ConditionMode || !item.tCommitted) - { - item.tCommitted = true; - Rainmeter::GetInstance().ExecuteCommand(item.tAction.c_str(), measure.GetMeterWindow()); - } - } - else if (result == 0.0f) // "False" - { - item.tCommitted = false; - - if (m_ConditionMode || !item.fCommitted) - { - item.fCommitted = true; - Rainmeter::GetInstance().ExecuteCommand(item.fAction.c_str(), measure.GetMeterWindow()); - } - } - } - } - } - - // IfMatch - i = 0; - for (auto& item : m_Matches) - { - ++i; - if (!item.value.empty() && (!item.tAction.empty() || !item.fAction.empty())) - { - const char* error; - int errorOffset; - - pcre* re = pcre_compile( - StringUtil::NarrowUTF8(item.value).c_str(), - PCRE_UTF8, - &error, - &errorOffset, - nullptr); - - if (!re) - { - if (!item.parseError) - { - if (i == 1) - { - LogErrorF(&measure, L"Error: \"%S\" in IfMatch=%s", error, item.value.c_str()); - } - else - { - LogErrorF(&measure, L"Error: \"%S\" in IfMatch%i=%s", error, i, item.value.c_str()); - } - - item.parseError = true; - } - } - else - { - item.parseError = false; - - std::string utf8str = StringUtil::NarrowUTF8(measure.GetStringValue()); - int ovector[300]; - - int rc = pcre_exec( - re, - nullptr, - utf8str.c_str(), - (int)utf8str.length(), - 0, - 0, - ovector, - (int)_countof(ovector)); - - if (rc > 0) // Match - { - item.fCommitted = false; - - if (m_MatchMode || !item.tCommitted) - { - item.tCommitted = true; - Rainmeter::GetInstance().ExecuteCommand(item.tAction.c_str(), measure.GetMeterWindow()); - } - } - else // Not Match - { - item.tCommitted = false; - - if (m_MatchMode || !item.fCommitted) - { - item.fCommitted = true; - Rainmeter::GetInstance().ExecuteCommand(item.fAction.c_str(), measure.GetMeterWindow()); - } - } - } - - // Release memory used for the compiled pattern - pcre_free(re); - } - } -} - -void IfActions::SetState(double& value) -{ - // Set IfAction committed state to false if condition is not met with value = 0 - if (m_EqualValue != (int64_t)value) - { - m_EqualCommitted = false; - } - - if (m_AboveValue <= value) - { - m_AboveCommitted = false; - } - - if (m_BelowValue >= value) - { - m_BelowCommitted = false; - } - - for (auto& item : m_Conditions) - { - item.tCommitted = false; - item.fCommitted = false; - } - - for (auto& item : m_Matches) - { - item.tCommitted = false; - item.fCommitted = false; - } -} +/* + Copyright (C) 2013 Brian Ferguson + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Measure.h" +#include "IfActions.h" +#include "Rainmeter.h" +#include "../Common/MathParser.h" +#include "pcre-8.10/config.h" +#include "pcre-8.10/pcre.h" + +IfActions::IfActions() : + m_AboveValue(0.0f), + m_BelowValue(0.0f), + m_EqualValue(0), + m_AboveAction(), + m_BelowAction(), + m_EqualAction(), + m_AboveCommitted(false), + m_BelowCommitted(false), + m_EqualCommitted(false), + m_Conditions(), + m_ConditionMode(false), + m_Matches(), + m_MatchMode(false) +{ +} + +IfActions::~IfActions() +{ +} + +void IfActions::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + m_AboveAction = parser.ReadString(section, L"IfAboveAction", L"", false); + m_AboveValue = parser.ReadFloat(section, L"IfAboveValue", 0.0f); + + m_BelowAction = parser.ReadString(section, L"IfBelowAction", L"", false); + m_BelowValue = parser.ReadFloat(section, L"IfBelowValue", 0.0f); + + m_EqualAction = parser.ReadString(section, L"IfEqualAction", L"", false); + m_EqualValue = (int64_t)parser.ReadFloat(section, L"IfEqualValue", 0.0f); +} + +void IfActions::ReadConditionOptions(ConfigParser& parser, const WCHAR* section) +{ + // IfCondition options + m_ConditionMode = parser.ReadBool(section, L"IfConditionMode", false); + + std::wstring condition = parser.ReadString(section, L"IfCondition", L""); + if (!condition.empty()) + { + std::wstring tAction = parser.ReadString(section, L"IfTrueAction", L"", false); + std::wstring fAction = parser.ReadString(section, L"IfFalseAction", L"", false); + if (!tAction.empty() || !fAction.empty()) + { + size_t i = 1; + do + { + if (m_Conditions.size() > (i - 1)) + { + m_Conditions[i - 1].Set(condition, tAction, fAction); + } + else + { + m_Conditions.emplace_back(condition, tAction, fAction); + } + + // Check for IfCondition2/IfTrueAction2/IfFalseAction2 ... etc. + const std::wstring num = std::to_wstring(++i); + + std::wstring key = L"IfCondition" + num; + condition = parser.ReadString(section, key.c_str(), L""); + if (condition.empty()) break; + + key = L"IfTrueAction" + num; + tAction = parser.ReadString(section, key.c_str(), L"", false); + key = L"IfFalseAction" + num; + fAction = parser.ReadString(section, key.c_str(), L"", false); + } + while (!tAction.empty() || !fAction.empty()); + } + else + { + m_Conditions.clear(); + } + } + else + { + m_Conditions.clear(); + } + + // IfMatch options + m_MatchMode = parser.ReadBool(section, L"IfMatchMode", false); + + std::wstring match = parser.ReadString(section, L"IfMatch", L""); + if (!match.empty()) + { + std::wstring tAction = parser.ReadString(section, L"IfMatchAction", L"", false); + std::wstring fAction = parser.ReadString(section, L"IfNotMatchAction", L"", false); + if (!tAction.empty() || !fAction.empty()) + { + size_t i = 1; + do + { + if (m_Matches.size() > (i - 1)) + { + m_Matches[i - 1].Set(match, tAction, fAction); + } + else + { + m_Matches.emplace_back(match, tAction, fAction); + } + + // Check for IfMatch2/IfMatchAction2/IfNotMatchAction2 ... etc. + const std::wstring num = std::to_wstring(++i); + + std::wstring key = L"IfMatch" + num; + match = parser.ReadString(section, key.c_str(), L""); + if (match.empty()) break; + + key = L"IfMatchAction" + num; + tAction = parser.ReadString(section, key.c_str(), L"", false); + key = L"IfNotMatchAction" + num; + fAction = parser.ReadString(section, key.c_str(), L"", false); + } while (!tAction.empty() || !fAction.empty()); + } + else + { + m_Matches.clear(); + } + } + else + { + m_Matches.clear(); + } +} + +void IfActions::DoIfActions(Measure& measure, double value) +{ + // IfEqual + if (!m_EqualAction.empty()) + { + if ((int64_t)value == m_EqualValue) + { + if (!m_EqualCommitted) + { + m_EqualCommitted = true; // To avoid infinite loop from !Update + Rainmeter::GetInstance().ExecuteCommand(m_EqualAction.c_str(), measure.GetMeterWindow()); + } + } + else + { + m_EqualCommitted = false; + } + } + + // IfAbove + if (!m_AboveAction.empty()) + { + if (value > m_AboveValue) + { + if (!m_AboveCommitted) + { + m_AboveCommitted = true; // To avoid infinite loop from !Update + Rainmeter::GetInstance().ExecuteCommand(m_AboveAction.c_str(), measure.GetMeterWindow()); + } + } + else + { + m_AboveCommitted = false; + } + } + + // IfBelow + if (!m_BelowAction.empty()) + { + if (value < m_BelowValue) + { + if (!m_BelowCommitted) + { + m_BelowCommitted = true; // To avoid infinite loop from !Update + Rainmeter::GetInstance().ExecuteCommand(m_BelowAction.c_str(), measure.GetMeterWindow()); + } + } + else + { + m_BelowCommitted = false; + } + } + + // IfCondition + int i = 0; + for (auto& item : m_Conditions) + { + ++i; + if (!item.value.empty() && (!item.tAction.empty() || !item.fAction.empty())) + { + double result = 0.0f; + const WCHAR* errMsg = MathParser::Parse( + item.value.c_str(), &result, measure.GetCurrentMeasureValue, &measure); + if (errMsg != nullptr) + { + if (!item.parseError) + { + if (i == 1) + { + LogErrorF(&measure, L"%s: IfCondition=%s", errMsg, item.value.c_str()); + } + else + { + LogErrorF(&measure, L"%s: IfCondition%i=%s", errMsg, i, item.value.c_str()); + } + item.parseError = true; + } + } + else + { + item.parseError = false; + + if (result == 1.0f) // "True" + { + item.fCommitted = false; + + if (m_ConditionMode || !item.tCommitted) + { + item.tCommitted = true; + Rainmeter::GetInstance().ExecuteCommand(item.tAction.c_str(), measure.GetMeterWindow()); + } + } + else if (result == 0.0f) // "False" + { + item.tCommitted = false; + + if (m_ConditionMode || !item.fCommitted) + { + item.fCommitted = true; + Rainmeter::GetInstance().ExecuteCommand(item.fAction.c_str(), measure.GetMeterWindow()); + } + } + } + } + } + + // IfMatch + i = 0; + for (auto& item : m_Matches) + { + ++i; + if (!item.value.empty() && (!item.tAction.empty() || !item.fAction.empty())) + { + const char* error; + int errorOffset; + + pcre* re = pcre_compile( + StringUtil::NarrowUTF8(item.value).c_str(), + PCRE_UTF8, + &error, + &errorOffset, + nullptr); + + if (!re) + { + if (!item.parseError) + { + if (i == 1) + { + LogErrorF(&measure, L"Error: \"%S\" in IfMatch=%s", error, item.value.c_str()); + } + else + { + LogErrorF(&measure, L"Error: \"%S\" in IfMatch%i=%s", error, i, item.value.c_str()); + } + + item.parseError = true; + } + } + else + { + item.parseError = false; + + std::string utf8str = StringUtil::NarrowUTF8(measure.GetStringValue()); + int ovector[300]; + + int rc = pcre_exec( + re, + nullptr, + utf8str.c_str(), + (int)utf8str.length(), + 0, + 0, + ovector, + (int)_countof(ovector)); + + if (rc > 0) // Match + { + item.fCommitted = false; + + if (m_MatchMode || !item.tCommitted) + { + item.tCommitted = true; + Rainmeter::GetInstance().ExecuteCommand(item.tAction.c_str(), measure.GetMeterWindow()); + } + } + else // Not Match + { + item.tCommitted = false; + + if (m_MatchMode || !item.fCommitted) + { + item.fCommitted = true; + Rainmeter::GetInstance().ExecuteCommand(item.fAction.c_str(), measure.GetMeterWindow()); + } + } + } + + // Release memory used for the compiled pattern + pcre_free(re); + } + } +} + +void IfActions::SetState(double& value) +{ + // Set IfAction committed state to false if condition is not met with value = 0 + if (m_EqualValue != (int64_t)value) + { + m_EqualCommitted = false; + } + + if (m_AboveValue <= value) + { + m_AboveCommitted = false; + } + + if (m_BelowValue >= value) + { + m_BelowCommitted = false; + } + + for (auto& item : m_Conditions) + { + item.tCommitted = false; + item.fCommitted = false; + } + + for (auto& item : m_Matches) + { + item.tCommitted = false; + item.fCommitted = false; + } +} diff --git a/Library/IfActions.h b/Library/IfActions.h index 1243a599..d9141bec 100644 --- a/Library/IfActions.h +++ b/Library/IfActions.h @@ -1,93 +1,93 @@ -/* - Copyright (C) 2013 Brian Ferguson - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __IFACTIONS_H__ -#define __IFACTIONS_H__ - -#include -#include -#include - -class ConfigParser; -class Measure; -class MeterWindow; - -// Helper class for IfCondition/IfMatch -class IfState -{ -public: - IfState(std::wstring value, std::wstring trueAction, std::wstring falseAction) : - value(), - tAction(), - fAction(), - parseError(false), - tCommitted(false), - fCommitted(false) - { - Set(value, trueAction, falseAction); - } - - inline void Set(std::wstring value, std::wstring trueAction, std::wstring falseAction) - { - this->value = value; - this->tAction = trueAction; - this->fAction = falseAction; - } - - std::wstring value; // IfCondition/IfMatch - std::wstring tAction; // IfTrueAction/IfMatchAction - std::wstring fAction; // IfFalseAction/IfNotMatchAction - bool parseError; - bool tCommitted; - bool fCommitted; -}; - -class IfActions -{ -public: - IfActions(); - ~IfActions(); - - IfActions(const IfActions& other) = delete; - IfActions& operator=(IfActions other) = delete; - - void ReadOptions(ConfigParser& parser, const WCHAR* section); - void ReadConditionOptions(ConfigParser& parser, const WCHAR* section); - void DoIfActions(Measure& measure, double value); - void SetState(double& value); - -private: - double m_AboveValue; - double m_BelowValue; - int64_t m_EqualValue; - - std::wstring m_AboveAction; - std::wstring m_BelowAction; - std::wstring m_EqualAction; - - bool m_AboveCommitted; - bool m_BelowCommitted; - bool m_EqualCommitted; - - std::vector m_Conditions; - bool m_ConditionMode; - - std::vector m_Matches; - bool m_MatchMode; -}; -#endif +/* + Copyright (C) 2013 Brian Ferguson + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __IFACTIONS_H__ +#define __IFACTIONS_H__ + +#include +#include +#include + +class ConfigParser; +class Measure; +class MeterWindow; + +// Helper class for IfCondition/IfMatch +class IfState +{ +public: + IfState(std::wstring value, std::wstring trueAction, std::wstring falseAction) : + value(), + tAction(), + fAction(), + parseError(false), + tCommitted(false), + fCommitted(false) + { + Set(value, trueAction, falseAction); + } + + inline void Set(std::wstring value, std::wstring trueAction, std::wstring falseAction) + { + this->value = value; + this->tAction = trueAction; + this->fAction = falseAction; + } + + std::wstring value; // IfCondition/IfMatch + std::wstring tAction; // IfTrueAction/IfMatchAction + std::wstring fAction; // IfFalseAction/IfNotMatchAction + bool parseError; + bool tCommitted; + bool fCommitted; +}; + +class IfActions +{ +public: + IfActions(); + ~IfActions(); + + IfActions(const IfActions& other) = delete; + IfActions& operator=(IfActions other) = delete; + + void ReadOptions(ConfigParser& parser, const WCHAR* section); + void ReadConditionOptions(ConfigParser& parser, const WCHAR* section); + void DoIfActions(Measure& measure, double value); + void SetState(double& value); + +private: + double m_AboveValue; + double m_BelowValue; + int64_t m_EqualValue; + + std::wstring m_AboveAction; + std::wstring m_BelowAction; + std::wstring m_EqualAction; + + bool m_AboveCommitted; + bool m_BelowCommitted; + bool m_EqualCommitted; + + std::vector m_Conditions; + bool m_ConditionMode; + + std::vector m_Matches; + bool m_MatchMode; +}; +#endif diff --git a/Library/Library.rc b/Library/Library.rc index 42bef88a..33e1eb5d 100644 --- a/Library/Library.rc +++ b/Library/Library.rc @@ -1,55 +1,55 @@ -#include -#include "resource.h" -#include "../Version.h" - -LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT -#pragma code_page(1252) - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION FILEVER - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", STRFILEVER - VALUE "LegalCopyright", " 2011 - All authors" - VALUE "OriginalFilename", "Rainmeter.dll" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} - -///////////////////////////////////////////////////////////////////////////// -// -// Accelerator -// - -IDR_DIALOG_ACCELERATORS ACCELERATORS -{ - "^C", IDM_COPY +#include +#include "resource.h" +#include "../Version.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION FILEVER + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", STRFILEVER + VALUE "LegalCopyright", " 2011 - All authors" + VALUE "OriginalFilename", "Rainmeter.dll" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_DIALOG_ACCELERATORS ACCELERATORS +{ + "^C", IDM_COPY } \ No newline at end of file diff --git a/Library/Library.vcxproj b/Library/Library.vcxproj index 53b31838..c83e061f 100644 --- a/Library/Library.vcxproj +++ b/Library/Library.vcxproj @@ -1,172 +1,172 @@ - - - - - {BE9D2400-7F1C-49D6-8498-5CE495491AD6} - DynamicLibrary - Rainmeter - - - - - - - - - - - - - .\;lua/include;lua/lua;%(AdditionalIncludeDirectories) - _USRDLL;LIBRARY_EXPORTS;%(PreprocessorDefinitions) - Use - - - comctl32.lib;Wininet.lib;UxTheme.lib;Winmm.lib;gdiplus.lib;Iphlpapi.lib;shlwapi.lib;d2d1.lib;dwrite.lib;windowscodecs.lib;Version.lib;%(AdditionalDependencies) - Winmm.dll;Version.dll;d2d1.dll;dwrite.dll;$(DelayLoadTestDLL) - - - - - - - - - $(ExcludeTests) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $(ExcludeTests) - - - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {19312085-aa51-4bd6-be92-4b6098cca539} - - - - - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6} - - - - - {6D61FBE9-6913-4885-A95D-1A8C0C223D82} - - - - - + + + + + {BE9D2400-7F1C-49D6-8498-5CE495491AD6} + DynamicLibrary + Rainmeter + + + + + + + + + + + + + .\;lua/include;lua/lua;%(AdditionalIncludeDirectories) + _USRDLL;LIBRARY_EXPORTS;%(PreprocessorDefinitions) + Use + + + comctl32.lib;Wininet.lib;UxTheme.lib;Winmm.lib;gdiplus.lib;Iphlpapi.lib;shlwapi.lib;d2d1.lib;dwrite.lib;windowscodecs.lib;Version.lib;%(AdditionalDependencies) + Winmm.dll;Version.dll;d2d1.dll;dwrite.dll;$(DelayLoadTestDLL) + + + + + + + + + $(ExcludeTests) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(ExcludeTests) + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {19312085-aa51-4bd6-be92-4b6098cca539} + + + + + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6} + + + + + {6D61FBE9-6913-4885-A95D-1A8C0C223D82} + + + + + \ No newline at end of file diff --git a/Library/Library.vcxproj.filters b/Library/Library.vcxproj.filters index 7810ec0b..540a7b85 100644 --- a/Library/Library.vcxproj.filters +++ b/Library/Library.vcxproj.filters @@ -1,358 +1,358 @@ - - - - - {976df8a7-1f37-4f6c-a341-22311ba418a3} - cpp;c;cxx;rc;def;r;odl;idl;hpj;bat - - - {d68c51de-41f6-4d17-8f8b-c03388b8c59d} - h;hpp;hxx;hm;inl - - - {2d6bf39d-48e1-4de3-8924-46c5666cb141} - ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe - - - {6570e2b7-2e40-4fba-a051-01de85760fea} - - - {941dce28-a314-4492-befb-5770432c98bf} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Lua - - - Lua - - - Lua\glue - - - Lua\glue - - - Lua\glue - - - Lua\glue - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Lua - - - Lua - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Resource Files - - - - - Source Files - - + + + + + {976df8a7-1f37-4f6c-a341-22311ba418a3} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {d68c51de-41f6-4d17-8f8b-c03388b8c59d} + h;hpp;hxx;hm;inl + + + {2d6bf39d-48e1-4de3-8924-46c5666cb141} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + {6570e2b7-2e40-4fba-a051-01de85760fea} + + + {941dce28-a314-4492-befb-5770432c98bf} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Lua + + + Lua + + + Lua\glue + + + Lua\glue + + + Lua\glue + + + Lua\glue + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Lua + + + Lua + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + + + Source Files + + \ No newline at end of file diff --git a/Library/Litestep.cpp b/Library/Litestep.cpp index b832ff26..488335a3 100644 --- a/Library/Litestep.cpp +++ b/Library/Litestep.cpp @@ -1,90 +1,90 @@ -/* - Copyright (C) 2002 Kimmo Pekkola + few lsapi developers - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Litestep.h" -#include "Rainmeter.h" -#include "DialogAbout.h" -#include "System.h" - -UINT GetUniqueID() -{ - static UINT id = 0; - return id++; -} - -WCHAR* GetString(UINT id) -{ - LPWSTR pData; - int len = LoadString(Rainmeter::GetInstance().GetResourceInstance(), id, (LPWSTR)&pData, 0); - return len ? pData : L""; -} - -std::wstring GetFormattedString(UINT id, ...) -{ - LPWSTR pBuffer = nullptr; - va_list args = nullptr; - va_start(args, id); - - DWORD len = FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, - GetString(id), - 0, - 0, - (LPWSTR)&pBuffer, - 0, - &args); - - va_end(args); - - std::wstring tmpSz(len ? pBuffer : L"", len); - if (pBuffer) LocalFree(pBuffer); - return tmpSz; -} - -HICON GetIcon(UINT id, bool large) -{ - HINSTANCE hExe = GetModuleHandle(nullptr); - HINSTANCE hComctl = GetModuleHandle(L"Comctl32"); - if (hComctl) - { - // Try LoadIconMetric for better quality with high DPI - auto loadIconMetric = (decltype(LoadIconMetric)*)GetProcAddress(hComctl, "LoadIconMetric"); - if (loadIconMetric) - { - HICON icon; - HRESULT hr = loadIconMetric(hExe, MAKEINTRESOURCE(id), large ? LIM_LARGE : LIM_SMALL, &icon); - if (SUCCEEDED(hr)) - { - return icon; - } - } - } - - return (HICON)LoadImage( - hExe, - MAKEINTRESOURCE(id), - IMAGE_ICON, - GetSystemMetrics(large ? SM_CXICON : SM_CXSMICON), - GetSystemMetrics(large ? SM_CYICON : SM_CYSMICON), - LR_SHARED); -} - -void RmNullCRTInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved) -{ - // Do nothing. -} +/* + Copyright (C) 2002 Kimmo Pekkola + few lsapi developers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Litestep.h" +#include "Rainmeter.h" +#include "DialogAbout.h" +#include "System.h" + +UINT GetUniqueID() +{ + static UINT id = 0; + return id++; +} + +WCHAR* GetString(UINT id) +{ + LPWSTR pData; + int len = LoadString(Rainmeter::GetInstance().GetResourceInstance(), id, (LPWSTR)&pData, 0); + return len ? pData : L""; +} + +std::wstring GetFormattedString(UINT id, ...) +{ + LPWSTR pBuffer = nullptr; + va_list args = nullptr; + va_start(args, id); + + DWORD len = FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, + GetString(id), + 0, + 0, + (LPWSTR)&pBuffer, + 0, + &args); + + va_end(args); + + std::wstring tmpSz(len ? pBuffer : L"", len); + if (pBuffer) LocalFree(pBuffer); + return tmpSz; +} + +HICON GetIcon(UINT id, bool large) +{ + HINSTANCE hExe = GetModuleHandle(nullptr); + HINSTANCE hComctl = GetModuleHandle(L"Comctl32"); + if (hComctl) + { + // Try LoadIconMetric for better quality with high DPI + auto loadIconMetric = (decltype(LoadIconMetric)*)GetProcAddress(hComctl, "LoadIconMetric"); + if (loadIconMetric) + { + HICON icon; + HRESULT hr = loadIconMetric(hExe, MAKEINTRESOURCE(id), large ? LIM_LARGE : LIM_SMALL, &icon); + if (SUCCEEDED(hr)) + { + return icon; + } + } + } + + return (HICON)LoadImage( + hExe, + MAKEINTRESOURCE(id), + IMAGE_ICON, + GetSystemMetrics(large ? SM_CXICON : SM_CXSMICON), + GetSystemMetrics(large ? SM_CYICON : SM_CYSMICON), + LR_SHARED); +} + +void RmNullCRTInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved) +{ + // Do nothing. +} diff --git a/Library/Litestep.h b/Library/Litestep.h index c0aa2466..6816af9a 100644 --- a/Library/Litestep.h +++ b/Library/Litestep.h @@ -1,40 +1,40 @@ -/* - Copyright (C) 2002 Kimmo Pekkola + few lsapi developers - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __LITESTEP_H__ -#define __LITESTEP_H__ - -#include -#include -#include -#include "../Common/StringUtil.h" -#include "Error.h" - -UINT GetUniqueID(); - -template -UINT TypeID() { static UINT id = GetUniqueID(); return id; } - -WCHAR* GetString(UINT id); -std::wstring GetFormattedString(UINT id, ...); - -HICON GetIcon(UINT id, bool large = false); - -void RmNullCRTInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved); - -#endif +/* + Copyright (C) 2002 Kimmo Pekkola + few lsapi developers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __LITESTEP_H__ +#define __LITESTEP_H__ + +#include +#include +#include +#include "../Common/StringUtil.h" +#include "Error.h" + +UINT GetUniqueID(); + +template +UINT TypeID() { static UINT id = GetUniqueID(); return id; } + +WCHAR* GetString(UINT id); +std::wstring GetFormattedString(UINT id, ...); + +HICON GetIcon(UINT id, bool large = false); + +void RmNullCRTInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved); + +#endif diff --git a/Library/Logger.cpp b/Library/Logger.cpp index 242d12e1..700a57eb 100644 --- a/Library/Logger.cpp +++ b/Library/Logger.cpp @@ -1,276 +1,276 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Logger.h" -#include "DialogAbout.h" -#include "Litestep.h" -#include "Rainmeter.h" -#include "Section.h" -#include "MeterWindow.h" -#include "System.h" -#include "resource.h" - -namespace { - -const size_t MAX_LOG_ENTIRES = 20; - -} // namespace - -Logger::Logger() : - m_LogToFile(false) -{ - System::InitializeCriticalSection(&m_CsLog); - System::InitializeCriticalSection(&m_CsLogDelay); -} - -Logger::~Logger() -{ - DeleteCriticalSection(&m_CsLog); - DeleteCriticalSection(&m_CsLogDelay); -} - -Logger& Logger::GetInstance() -{ - static Logger s_Logger; - return s_Logger; -} - -void Logger::StartLogFile() -{ - const WCHAR* filePath = m_LogFilePath.c_str(); - if (_waccess(filePath, 0) == -1) - { - // Create empty log file. - HANDLE file = CreateFile(filePath, GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr); - if (file != INVALID_HANDLE_VALUE) - { - CloseHandle(file); - } - else - { - const std::wstring text = GetFormattedString(ID_STR_LOGFILECREATEFAIL, filePath); - Rainmeter::GetInstance().ShowMessage(nullptr, text.c_str(), MB_OK | MB_ICONERROR); - SetLogToFile(false); - return; - } - } - - SetLogToFile(true); -} - -void Logger::StopLogFile() -{ - SetLogToFile(false); -} - -void Logger::DeleteLogFile() -{ - const WCHAR* filePath = m_LogFilePath.c_str(); - if (_waccess(filePath, 0) != -1) - { - const std::wstring text = GetFormattedString(ID_STR_LOGFILEDELETE, filePath); - const int res = Rainmeter::GetInstance().ShowMessage(nullptr, text.c_str(), MB_YESNO | MB_ICONQUESTION); - if (res == IDYES) - { - SetLogToFile(false); - System::RemoveFile(m_LogFilePath); - } - } -} - -void Logger::SetLogToFile(bool logToFile) -{ - m_LogToFile = logToFile; - WritePrivateProfileString( - L"Rainmeter", L"Logging", logToFile ? L"1" : L"0", Rainmeter::GetInstance().GetIniFile().c_str()); -} - -void Logger::LogInternal(Level level, ULONGLONG timestamp, const WCHAR* source, const WCHAR* msg) -{ - WCHAR timestampSz[128]; - size_t len = _snwprintf_s( - timestampSz, - _TRUNCATE, - L"%02llu:%02llu:%02llu.%03llu", - timestamp / (1000 * 60 * 60), - (timestamp / (1000 * 60)) % 60, - (timestamp / 1000) % 60, - timestamp % 1000); - - // Store up to MAX_LOG_ENTIRES entries. - Entry entry = {level, std::wstring(timestampSz, len), source, msg}; - m_Entries.push_back(entry); - if (m_Entries.size() > MAX_LOG_ENTIRES) - { - m_Entries.pop_front(); - } - - DialogAbout::AddLogItem(level, timestampSz, source, msg); - WriteToLogFile(entry); -} - -void Logger::WriteToLogFile(Entry& entry) -{ -#ifndef _DEBUG - if (!m_LogToFile) return; -#endif - - const WCHAR* levelSz = - (entry.level == Level::Error) ? L"ERRO" : - (entry.level == Level::Warning) ? L"WARN" : - (entry.level == Level::Notice) ? L"NOTE" : - L"DBUG"; - - std::wstring message = levelSz; - message += L" ("; - message.append(entry.timestamp); - message += L") "; - message += entry.source; - message += L": "; - message += entry.message; - message += L'\n'; - -#ifdef _DEBUG - _RPTW0(_CRT_WARN, message.c_str()); - if (!m_LogToFile) return; -#endif - - const WCHAR* filePath = m_LogFilePath.c_str(); - if (_waccess(filePath, 0) == -1) - { - // The file has been deleted manually. - StopLogFile(); - } - else - { - FILE* file = _wfopen(filePath, L"a+, ccs=UTF-8"); - if (file) - { - fputws(message.c_str(), file); - fclose(file); - } - } -} - -void Logger::Log(Level level, const WCHAR* source, const WCHAR* msg) -{ - struct DelayedEntry - { - Level level; - ULONGLONG elapsed; - std::wstring message; - }; - static std::list s_DelayedEntries; - - static ULONGLONG s_StartTime = System::GetTickCount64(); - ULONGLONG elapsed = System::GetTickCount64() - s_StartTime; - - if (TryEnterCriticalSection(&m_CsLog)) - { - // Log queued messages first. - EnterCriticalSection(&m_CsLogDelay); - - while (!s_DelayedEntries.empty()) - { - DelayedEntry& entry = s_DelayedEntries.front(); - LogInternal(entry.level, entry.elapsed, source, entry.message.c_str()); - - s_DelayedEntries.erase(s_DelayedEntries.begin()); - } - - LeaveCriticalSection(&m_CsLogDelay); - - // Log the actual message. - LogInternal(level, elapsed, source, msg); - - LeaveCriticalSection(&m_CsLog); - } - else - { - // Queue message. - EnterCriticalSection(&m_CsLogDelay); - - DelayedEntry entry = {level, elapsed, msg}; - s_DelayedEntries.push_back(entry); - - LeaveCriticalSection(&m_CsLogDelay); - } -} - -void Logger::LogVF(Level level, const WCHAR* source, const WCHAR* format, va_list args) -{ - WCHAR* buffer = new WCHAR[1024]; - - _invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(RmNullCRTInvalidParameterHandler); - _CrtSetReportMode(_CRT_ASSERT, 0); - - errno = 0; - _vsnwprintf_s(buffer, 1024, _TRUNCATE, format, args); - if (errno != 0) - { - level = Level::Error; - _snwprintf_s(buffer, 1024, _TRUNCATE, L"Internal error: %s", format); - } - - _set_invalid_parameter_handler(oldHandler); - - Log(level, source, buffer); - delete [] buffer; -} - -std::wstring GetSectionSourceString(Section* section) -{ - std::wstring source; - if (section) - { - MeterWindow* meterWindow = section->GetMeterWindow(); - if (meterWindow) - { - source = meterWindow->GetSkinPath(); - source += L" - "; - } - - source += L'['; - source += section->GetOriginalName(); - source += L']'; - } - return source; -} - -void Logger::LogSection(Logger::Level level, Section* section, const WCHAR* message) -{ - const std::wstring source = GetSectionSourceString(section); - GetLogger().Log(level, source.c_str(), message); -} - -void Logger::LogSectionVF(Logger::Level level, Section* section, const WCHAR* format, va_list args) -{ - const std::wstring source = GetSectionSourceString(section); - GetLogger().LogVF(level, source.c_str(), format, args); -} - -void Logger::LogMeterWindowVF(Logger::Level level, MeterWindow* meterWindow, const WCHAR* format, va_list args) -{ - std::wstring source; - if (meterWindow) - { - source = meterWindow->GetSkinPath(); - } - GetLogger().LogVF(level, source.c_str(), format, args); -} +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Logger.h" +#include "DialogAbout.h" +#include "Litestep.h" +#include "Rainmeter.h" +#include "Section.h" +#include "MeterWindow.h" +#include "System.h" +#include "resource.h" + +namespace { + +const size_t MAX_LOG_ENTIRES = 20; + +} // namespace + +Logger::Logger() : + m_LogToFile(false) +{ + System::InitializeCriticalSection(&m_CsLog); + System::InitializeCriticalSection(&m_CsLogDelay); +} + +Logger::~Logger() +{ + DeleteCriticalSection(&m_CsLog); + DeleteCriticalSection(&m_CsLogDelay); +} + +Logger& Logger::GetInstance() +{ + static Logger s_Logger; + return s_Logger; +} + +void Logger::StartLogFile() +{ + const WCHAR* filePath = m_LogFilePath.c_str(); + if (_waccess(filePath, 0) == -1) + { + // Create empty log file. + HANDLE file = CreateFile(filePath, GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr); + if (file != INVALID_HANDLE_VALUE) + { + CloseHandle(file); + } + else + { + const std::wstring text = GetFormattedString(ID_STR_LOGFILECREATEFAIL, filePath); + Rainmeter::GetInstance().ShowMessage(nullptr, text.c_str(), MB_OK | MB_ICONERROR); + SetLogToFile(false); + return; + } + } + + SetLogToFile(true); +} + +void Logger::StopLogFile() +{ + SetLogToFile(false); +} + +void Logger::DeleteLogFile() +{ + const WCHAR* filePath = m_LogFilePath.c_str(); + if (_waccess(filePath, 0) != -1) + { + const std::wstring text = GetFormattedString(ID_STR_LOGFILEDELETE, filePath); + const int res = Rainmeter::GetInstance().ShowMessage(nullptr, text.c_str(), MB_YESNO | MB_ICONQUESTION); + if (res == IDYES) + { + SetLogToFile(false); + System::RemoveFile(m_LogFilePath); + } + } +} + +void Logger::SetLogToFile(bool logToFile) +{ + m_LogToFile = logToFile; + WritePrivateProfileString( + L"Rainmeter", L"Logging", logToFile ? L"1" : L"0", Rainmeter::GetInstance().GetIniFile().c_str()); +} + +void Logger::LogInternal(Level level, ULONGLONG timestamp, const WCHAR* source, const WCHAR* msg) +{ + WCHAR timestampSz[128]; + size_t len = _snwprintf_s( + timestampSz, + _TRUNCATE, + L"%02llu:%02llu:%02llu.%03llu", + timestamp / (1000 * 60 * 60), + (timestamp / (1000 * 60)) % 60, + (timestamp / 1000) % 60, + timestamp % 1000); + + // Store up to MAX_LOG_ENTIRES entries. + Entry entry = {level, std::wstring(timestampSz, len), source, msg}; + m_Entries.push_back(entry); + if (m_Entries.size() > MAX_LOG_ENTIRES) + { + m_Entries.pop_front(); + } + + DialogAbout::AddLogItem(level, timestampSz, source, msg); + WriteToLogFile(entry); +} + +void Logger::WriteToLogFile(Entry& entry) +{ +#ifndef _DEBUG + if (!m_LogToFile) return; +#endif + + const WCHAR* levelSz = + (entry.level == Level::Error) ? L"ERRO" : + (entry.level == Level::Warning) ? L"WARN" : + (entry.level == Level::Notice) ? L"NOTE" : + L"DBUG"; + + std::wstring message = levelSz; + message += L" ("; + message.append(entry.timestamp); + message += L") "; + message += entry.source; + message += L": "; + message += entry.message; + message += L'\n'; + +#ifdef _DEBUG + _RPTW0(_CRT_WARN, message.c_str()); + if (!m_LogToFile) return; +#endif + + const WCHAR* filePath = m_LogFilePath.c_str(); + if (_waccess(filePath, 0) == -1) + { + // The file has been deleted manually. + StopLogFile(); + } + else + { + FILE* file = _wfopen(filePath, L"a+, ccs=UTF-8"); + if (file) + { + fputws(message.c_str(), file); + fclose(file); + } + } +} + +void Logger::Log(Level level, const WCHAR* source, const WCHAR* msg) +{ + struct DelayedEntry + { + Level level; + ULONGLONG elapsed; + std::wstring message; + }; + static std::list s_DelayedEntries; + + static ULONGLONG s_StartTime = System::GetTickCount64(); + ULONGLONG elapsed = System::GetTickCount64() - s_StartTime; + + if (TryEnterCriticalSection(&m_CsLog)) + { + // Log queued messages first. + EnterCriticalSection(&m_CsLogDelay); + + while (!s_DelayedEntries.empty()) + { + DelayedEntry& entry = s_DelayedEntries.front(); + LogInternal(entry.level, entry.elapsed, source, entry.message.c_str()); + + s_DelayedEntries.erase(s_DelayedEntries.begin()); + } + + LeaveCriticalSection(&m_CsLogDelay); + + // Log the actual message. + LogInternal(level, elapsed, source, msg); + + LeaveCriticalSection(&m_CsLog); + } + else + { + // Queue message. + EnterCriticalSection(&m_CsLogDelay); + + DelayedEntry entry = {level, elapsed, msg}; + s_DelayedEntries.push_back(entry); + + LeaveCriticalSection(&m_CsLogDelay); + } +} + +void Logger::LogVF(Level level, const WCHAR* source, const WCHAR* format, va_list args) +{ + WCHAR* buffer = new WCHAR[1024]; + + _invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(RmNullCRTInvalidParameterHandler); + _CrtSetReportMode(_CRT_ASSERT, 0); + + errno = 0; + _vsnwprintf_s(buffer, 1024, _TRUNCATE, format, args); + if (errno != 0) + { + level = Level::Error; + _snwprintf_s(buffer, 1024, _TRUNCATE, L"Internal error: %s", format); + } + + _set_invalid_parameter_handler(oldHandler); + + Log(level, source, buffer); + delete [] buffer; +} + +std::wstring GetSectionSourceString(Section* section) +{ + std::wstring source; + if (section) + { + MeterWindow* meterWindow = section->GetMeterWindow(); + if (meterWindow) + { + source = meterWindow->GetSkinPath(); + source += L" - "; + } + + source += L'['; + source += section->GetOriginalName(); + source += L']'; + } + return source; +} + +void Logger::LogSection(Logger::Level level, Section* section, const WCHAR* message) +{ + const std::wstring source = GetSectionSourceString(section); + GetLogger().Log(level, source.c_str(), message); +} + +void Logger::LogSectionVF(Logger::Level level, Section* section, const WCHAR* format, va_list args) +{ + const std::wstring source = GetSectionSourceString(section); + GetLogger().LogVF(level, source.c_str(), format, args); +} + +void Logger::LogMeterWindowVF(Logger::Level level, MeterWindow* meterWindow, const WCHAR* format, va_list args) +{ + std::wstring source; + if (meterWindow) + { + source = meterWindow->GetSkinPath(); + } + GetLogger().LogVF(level, source.c_str(), format, args); +} diff --git a/Library/Logger.h b/Library/Logger.h index 08db6c12..f8165ffa 100644 --- a/Library/Logger.h +++ b/Library/Logger.h @@ -1,130 +1,130 @@ -/* - Copyright (C) 2013 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_LOGGER_H_ -#define RM_LOGGER_H_ - -#include -#include -#include -#include - -class Section; -class MeterWindow; - -// Singleton class to handle and store log messages and control the log file. -class Logger -{ -public: - enum class Level - { - Error = 1, - Warning = 2, - Notice = 3, - Debug = 4 - }; - - struct Entry - { - Level level; - std::wstring timestamp; - std::wstring source; - std::wstring message; - }; - - static Logger& GetInstance(); - - void SetLogFilePath(std::wstring path) { m_LogFilePath = path; } - - void StartLogFile(); - void StopLogFile(); - void DeleteLogFile(); - - bool IsLogToFile() { return m_LogToFile; } - void SetLogToFile(bool logToFile); - - void Log(Level level, const WCHAR* source, const WCHAR* msg); - void LogVF(Level level, const WCHAR* source, const WCHAR* format, va_list args); - void LogMeterWindowVF(Logger::Level level, MeterWindow* meterWindow, const WCHAR* format, va_list args); - void LogSection(Logger::Level level, Section* section, const WCHAR* message); - void LogSectionVF(Logger::Level level, Section* section, const WCHAR* format, va_list args); - - const std::wstring& GetLogFilePath() { return m_LogFilePath; } - - const std::list& GetEntries() { return m_Entries; } - -private: - void LogInternal(Level level, ULONGLONG timestamp, const WCHAR* source, const WCHAR* msg); - - // Appends |entry| to the log file. - void WriteToLogFile(Entry& entry); - - Logger(); - ~Logger(); - - Logger(const Logger& other) = delete; - Logger& operator=(Logger other) = delete; - - bool m_LogToFile; - std::wstring m_LogFilePath; - - std::list m_Entries; - - CRITICAL_SECTION m_CsLog; - CRITICAL_SECTION m_CsLogDelay; -}; - -// Convenience functions. -inline Logger& GetLogger() { return Logger::GetInstance(); } - -#define RM_LOGGER_DEFINE_LOG_FUNCTIONS(name) \ - inline void Log ## name(const WCHAR* msg) \ - { \ - GetLogger().Log(Logger::Level::name, L"", msg); \ - } \ - \ - inline void Log ## name ## F(const WCHAR* format, ...) \ - { \ - va_list args; \ - va_start(args, format); \ - GetLogger().LogVF(Logger::Level::name, L"", format, args); \ - va_end(args); \ - } \ - \ - inline void Log ## name ## F(Section* section, const WCHAR* format, ...) \ - { \ - va_list args; \ - va_start(args, format); \ - GetLogger().LogSectionVF(Logger::Level::name, section, format, args); \ - va_end(args); \ - } \ - \ - inline void Log ## name ## F(MeterWindow* meterWindow, const WCHAR* format, ...) \ - { \ - va_list args; \ - va_start(args, format); \ - GetLogger().LogMeterWindowVF(Logger::Level::name, meterWindow, format, args); \ - va_end(args); \ - } - -RM_LOGGER_DEFINE_LOG_FUNCTIONS(Error) -RM_LOGGER_DEFINE_LOG_FUNCTIONS(Warning) -RM_LOGGER_DEFINE_LOG_FUNCTIONS(Notice) -RM_LOGGER_DEFINE_LOG_FUNCTIONS(Debug) - +/* + Copyright (C) 2013 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_LOGGER_H_ +#define RM_LOGGER_H_ + +#include +#include +#include +#include + +class Section; +class MeterWindow; + +// Singleton class to handle and store log messages and control the log file. +class Logger +{ +public: + enum class Level + { + Error = 1, + Warning = 2, + Notice = 3, + Debug = 4 + }; + + struct Entry + { + Level level; + std::wstring timestamp; + std::wstring source; + std::wstring message; + }; + + static Logger& GetInstance(); + + void SetLogFilePath(std::wstring path) { m_LogFilePath = path; } + + void StartLogFile(); + void StopLogFile(); + void DeleteLogFile(); + + bool IsLogToFile() { return m_LogToFile; } + void SetLogToFile(bool logToFile); + + void Log(Level level, const WCHAR* source, const WCHAR* msg); + void LogVF(Level level, const WCHAR* source, const WCHAR* format, va_list args); + void LogMeterWindowVF(Logger::Level level, MeterWindow* meterWindow, const WCHAR* format, va_list args); + void LogSection(Logger::Level level, Section* section, const WCHAR* message); + void LogSectionVF(Logger::Level level, Section* section, const WCHAR* format, va_list args); + + const std::wstring& GetLogFilePath() { return m_LogFilePath; } + + const std::list& GetEntries() { return m_Entries; } + +private: + void LogInternal(Level level, ULONGLONG timestamp, const WCHAR* source, const WCHAR* msg); + + // Appends |entry| to the log file. + void WriteToLogFile(Entry& entry); + + Logger(); + ~Logger(); + + Logger(const Logger& other) = delete; + Logger& operator=(Logger other) = delete; + + bool m_LogToFile; + std::wstring m_LogFilePath; + + std::list m_Entries; + + CRITICAL_SECTION m_CsLog; + CRITICAL_SECTION m_CsLogDelay; +}; + +// Convenience functions. +inline Logger& GetLogger() { return Logger::GetInstance(); } + +#define RM_LOGGER_DEFINE_LOG_FUNCTIONS(name) \ + inline void Log ## name(const WCHAR* msg) \ + { \ + GetLogger().Log(Logger::Level::name, L"", msg); \ + } \ + \ + inline void Log ## name ## F(const WCHAR* format, ...) \ + { \ + va_list args; \ + va_start(args, format); \ + GetLogger().LogVF(Logger::Level::name, L"", format, args); \ + va_end(args); \ + } \ + \ + inline void Log ## name ## F(Section* section, const WCHAR* format, ...) \ + { \ + va_list args; \ + va_start(args, format); \ + GetLogger().LogSectionVF(Logger::Level::name, section, format, args); \ + va_end(args); \ + } \ + \ + inline void Log ## name ## F(MeterWindow* meterWindow, const WCHAR* format, ...) \ + { \ + va_list args; \ + va_start(args, format); \ + GetLogger().LogMeterWindowVF(Logger::Level::name, meterWindow, format, args); \ + va_end(args); \ + } + +RM_LOGGER_DEFINE_LOG_FUNCTIONS(Error) +RM_LOGGER_DEFINE_LOG_FUNCTIONS(Warning) +RM_LOGGER_DEFINE_LOG_FUNCTIONS(Notice) +RM_LOGGER_DEFINE_LOG_FUNCTIONS(Debug) + #endif \ No newline at end of file diff --git a/Library/Measure.cpp b/Library/Measure.cpp index acbe6c29..773c0efc 100644 --- a/Library/Measure.cpp +++ b/Library/Measure.cpp @@ -1,838 +1,838 @@ -/* - Copyright (C) 2000 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Measure.h" -#include "MeasureCPU.h" -#include "MeasureMemory.h" -#include "MeasurePhysicalMemory.h" -#include "MeasureVirtualMemory.h" -#include "MeasureNetIn.h" -#include "MeasureNetOut.h" -#include "MeasureNetTotal.h" -#include "MeasureDiskSpace.h" -#include "MeasureUptime.h" -#include "MeasurePlugin.h" -#include "MeasureRegistry.h" -#include "MeasureString.h" -#include "MeasureTime.h" -#include "MeasureCalc.h" -#include "MeasureScript.h" -#include "Rainmeter.h" -#include "Error.h" -#include "Litestep.h" -#include "pcre-8.10/config.h" -#include "pcre-8.10/pcre.h" - -#define OVECCOUNT 300 // Should be a multiple of 3 - -enum AUTOSCALE_INDEX -{ - AUTOSCALE_INDEX_1024 = 0, - AUTOSCALE_INDEX_1000 = 1 -}; - -static const double g_TblScale[2][4] = { - { - 1024.0 * 1024.0 * 1024.0 * 1024.0, - 1024.0 * 1024.0 * 1024.0, - 1024.0 * 1024.0, - 1024.0 - }, - { - 1000.0 * 1000.0 * 1000.0 * 1000.0, - 1000.0 * 1000.0 * 1000.0, - 1000.0 * 1000.0, - 1000.0 - } -}; - -const int MEDIAN_SIZE = 3; - -/* -** The constructor -** -*/ -Measure::Measure(MeterWindow* meterWindow, const WCHAR* name) : Section(meterWindow, name), - m_Invert(false), - m_LogMaxValue(false), - m_MinValue(), - m_MaxValue(1.0), - m_Value(), - m_RegExpSubstitute(false), - m_MedianPos(), - m_AveragePos(), - m_AverageSize(), - m_Disabled(false), - m_Paused(false), - m_Initialized(false), - m_OldValue(), - m_ValueAssigned(false) -{ -} - -/* -** The destructor -** -*/ -Measure::~Measure() -{ - delete m_OldValue; -} - -/* -** Initializes the measure. -** -*/ -void Measure::Initialize() -{ - m_Initialized = true; -} - -/* -** Read the common options specified in the ini file. The inherited classes must -** call this base implementation if they overwrite this method. -** -*/ -void Measure::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - bool oldOnChangeActionEmpty = m_OnChangeAction.empty(); - - Section::ReadOptions(parser, section); - - // Clear substitutes to prevent from being added more than once. - if (!m_Substitute.empty()) - { - m_Substitute.clear(); - } - - m_Invert = parser.ReadBool(section, L"InvertMeasure", false); - - m_Disabled = parser.ReadBool(section, L"Disabled", false); - m_Paused = parser.ReadBool(section, L"Paused", false); - - m_MinValue = parser.ReadFloat(section, L"MinValue", m_MinValue); - m_MaxValue = parser.ReadFloat(section, L"MaxValue", m_MaxValue); - - m_IfActions.ReadOptions(parser, section); - - // The first time around, we read the conditions here. Subsequent rereads will be done in - // Update() if needed. - if (!m_Initialized) - { - m_IfActions.ReadConditionOptions(parser, section); - } - - m_OnChangeAction = parser.ReadString(section, L"OnChangeAction", L"", false); - - m_AverageSize = parser.ReadUInt(section, L"AverageSize", 0); - - m_RegExpSubstitute = parser.ReadBool(section, L"RegExpSubstitute", false); - std::wstring subs = parser.ReadString(section, L"Substitute", L""); - if (!subs.empty()) - { - if ((subs[0] != L'"' || subs[subs.length() - 1] != L'\'') && - (subs[0] != L'\'' || subs[subs.length() - 1] != L'"')) - { - // Add quotes since they are removed by the GetProfileString - subs.insert(0, 1, L'"'); - subs += L'"'; - } - if (!ParseSubstitute(subs)) - { - LogErrorF(this, L"Measure: Invalid Substitute=%s", subs.c_str()); - } - } - - if (m_Initialized && - oldOnChangeActionEmpty && !m_OnChangeAction.empty()) - { - DoChangeAction(false); - } -} - -void Measure::Disable() -{ - m_Disabled = true; - - // Change the option as well to avoid reset in ReadOptions(). - m_MeterWindow->GetParser().SetValue(m_Name, L"Disabled", L"1"); -} - -void Measure::Enable() -{ - m_Disabled = false; - - // Change the option as well to avoid reset in ReadOptions(). - m_MeterWindow->GetParser().SetValue(m_Name, L"Disabled", L"0"); -} - -void Measure::Pause() -{ - m_Paused = true; - - // Change the option as well to avoid reset in ReadOptions(). - m_MeterWindow->GetParser().SetValue(m_Name, L"Paused", L"1"); -} - -void Measure::Unpause() -{ - m_Paused = false; - - // Change the option as well to avoid reset in ReadOptions(). - m_MeterWindow->GetParser().SetValue(m_Name, L"Paused", L"0"); -} - -/* -** Substitues text using a straight find and replace method -*/ -bool Measure::MakePlainSubstitute(std::wstring& str, size_t index) -{ - size_t start = 0, pos; - - do - { - pos = str.find(m_Substitute[index], start); - if (pos != std::wstring::npos) - { - str.replace(pos, m_Substitute[index].length(), m_Substitute[index + 1]); - start = pos + m_Substitute[index + 1].length(); - } - } - while (pos != std::wstring::npos); - - return true; -} - -/* -** Substitutes part of the text -*/ -const WCHAR* Measure::CheckSubstitute(const WCHAR* buffer) -{ - static std::wstring str; - - if (m_Substitute.empty()) - { - return buffer; - } - - if (!m_RegExpSubstitute) - { - str = buffer; - - for (size_t i = 0, isize = m_Substitute.size(); i < isize; i += 2) - { - if (!m_Substitute[i].empty()) - { - MakePlainSubstitute(str, i); - } - else if (str.empty()) - { - // Empty result and empty substitute -> use second - str = m_Substitute[i + 1]; - } - } - } - else - { - std::string utf8str = StringUtil::NarrowUTF8(buffer); - int ovector[300]; - - for (size_t i = 0, isize = m_Substitute.size(); i < isize; i += 2) - { - const char* error; - int errorOffset; - int offset = 0; - pcre* re = pcre_compile( - StringUtil::NarrowUTF8(m_Substitute[i]).c_str(), - PCRE_UTF8, - &error, - &errorOffset, - nullptr); // Use default character tables. - if (!re) - { - MakePlainSubstitute(str, i); - LogNoticeF(this, L"Substitute: %S", error); - } - else - { - do - { - const int rc = pcre_exec( - re, - nullptr, // No extra data - we didn't study the pattern - utf8str.c_str(), // The subject string - (int)utf8str.length(), // The length of the subject - offset, - 0, - ovector, - (int)_countof(ovector)); - if (rc <= 0) - { - break; - } - - std::string result = StringUtil::NarrowUTF8(m_Substitute[i + 1]); - - if (rc > 1) - { - for (int j = rc - 1 ; j >= 0 ; --j) - { - size_t newStart = ovector[2 * j]; - size_t inLength = ovector[2 * j + 1] - ovector[2 * j]; - - char tmpName[64]; - size_t cutLength = _snprintf_s(tmpName, _TRUNCATE, "\\%i", j);; - size_t start = 0, pos; - do - { - pos = result.find(tmpName, start, cutLength); - if (pos != std::string::npos) - { - result.replace(pos, cutLength, utf8str, newStart, inLength); - start = pos + inLength; - } - } - while (pos != std::string::npos); - } - } - - const int start = ovector[0]; - const int length = ovector[1] - ovector[0]; - utf8str.replace(start, length, result); - offset = start + (int)result.length(); - } - while (true); - - pcre_free(re); - } - } - - str = StringUtil::WidenUTF8(utf8str); - } - - return str.c_str(); -} - -/* -** Reads the buffer for "Name":"Value"-pairs separated with comma and -** fills the map with the parsed data. -*/ -bool Measure::ParseSubstitute(std::wstring buffer) -{ - if (buffer.empty()) return true; - - do - { - std::wstring word1 = ExtractWord(buffer); - std::wstring sep = ExtractWord(buffer); - if (sep.size() != 1 || sep[0] != L':') return false; - std::wstring word2 = ExtractWord(buffer); - - if (wcscmp(word1.c_str(), word2.c_str()) != 0) - { - if (m_RegExpSubstitute && word1.empty()) - { - word1 = L"^$"; - } - - m_Substitute.push_back(word1); - m_Substitute.push_back(word2); - } - - std::wstring sep2 = ExtractWord(buffer); - if (!sep2.empty() && (sep2.size() != 1 || sep2[0] != L',')) return false; - } - while (!buffer.empty()); - - return true; -} - -/* -** Returns the first word from the buffer. The word can be inside quotes. -** If not, the separators are ' ', '\t', ',' and ':'. Whitespaces are removed -** and buffer _will_ be modified. -*/ -std::wstring Measure::ExtractWord(std::wstring& buffer) -{ - std::wstring::size_type end, len = buffer.size(); - std::wstring ret; - - if (len == 0) return ret; - - // Remove whitespaces - end = 0; - while (end < len && (buffer[end] == L' ' || buffer[end] == L'\t' || buffer[end] == L'\n')) ++end; - if (end == len) - { - // End of line reached - end = std::wstring::npos; - } - else - { - buffer.erase(0, end); - len = buffer.size(); - - if (buffer[0] == L'"' || buffer[0] == L'\'') - { - WCHAR quote = buffer[0]; - - end = 1; // Skip the '"' - // Quotes around the word - while (end < len && (buffer[end] != quote)) ++end; - if (end == len) end = std::wstring::npos; - - if (end != std::wstring::npos) - { - ret.assign(buffer, 1, end - 1); - ++end; - } - else - { - // End of string reached - discard result - } - } - else - { - end = 0; - while (end < len && (buffer[end] != L',' && buffer[end] != L':' && buffer[end] != L' ' && buffer[end] != L'\t')) ++end; - if (end == len) end = std::wstring::npos; - - if (end == std::wstring::npos) - { - // End of line reached - ret = buffer; - } - else - { - ret.assign(buffer, 0, ++end); // The separator is also returned! - } - } - } - - buffer.erase(0, end); - - return ret; -} - -bool Measure::Update(bool rereadOptions) -{ - if (rereadOptions) - { - ReadOptions(m_MeterWindow->GetParser()); - } - - // Don't do anything if paused - if (m_Paused) return false; - - if (!m_Disabled) - { - // Only update the counter if the divider - if (!UpdateCounter()) return false; - - // Call derived method to update value - UpdateValue(); - - if (m_AverageSize > 0) - { - size_t averageValuesSize = m_AverageValues.size(); - - if (m_AverageSize != averageValuesSize) - { - m_AverageValues.resize(m_AverageSize, m_Value); - averageValuesSize = m_AverageValues.size(); - if (m_AveragePos >= averageValuesSize) m_AveragePos = 0; - } - m_AverageValues[m_AveragePos] = m_Value; - - ++m_AveragePos; - m_AveragePos %= averageValuesSize; - - // Calculate the average value - double value = 0; - for (size_t i = 0; i < averageValuesSize; ++i) - { - value += m_AverageValues[i]; - } - m_Value = value / (double)averageValuesSize; - } - - // If we're logging the maximum value of the measure, check if - // the new value is greater than the old one, and update if necessary. - if (m_LogMaxValue) - { - if (m_MedianValues.empty()) - { - m_MedianValues.resize(MEDIAN_SIZE, 0); - } - - m_MedianValues[m_MedianPos] = m_Value; - ++m_MedianPos; - m_MedianPos %= MEDIAN_SIZE; - - auto medianArray = m_MedianValues; - std::sort(&medianArray.data()[0], &medianArray.data()[MEDIAN_SIZE]); // Workaround for "Debug" build mode - - double medianValue = medianArray[MEDIAN_SIZE / 2]; - m_MaxValue = max(m_MaxValue, medianValue); - m_MinValue = min(m_MinValue, medianValue); - } - - m_ValueAssigned = true; - - // For the conditional options to work with the current measure value when using - // [MeasureName], we need to read the options after m_Value has been changed. - if (rereadOptions) - { - m_IfActions.ReadConditionOptions(m_MeterWindow->GetParser(), GetName()); - } - - if (m_MeterWindow) - { - m_IfActions.DoIfActions(*this, m_Value); - } - - return true; - } - else - { - // Disabled measures have 0 as value - m_Value = 0.0; - - m_IfActions.SetState(m_Value); - - return false; - } -} - -/* -** Returns the value of the measure. -** -*/ -double Measure::GetValue() -{ - // Invert if so requested - if (m_Invert) - { - return m_MaxValue - m_Value + m_MinValue; - } - - return m_Value; -} - -/* -** Returns the relative value of the measure (0.0 - 1.0). -** -*/ -double Measure::GetRelativeValue() -{ - double range = GetValueRange(); - - if (range != 0.0) - { - double value = GetValue(); - - value = min(m_MaxValue, value); - value = max(m_MinValue, value); - - value -= m_MinValue; - - return value / range; - } - - return 1.0; -} - -/* -** Returns the value range. -** -*/ -double Measure::GetValueRange() -{ - return m_MaxValue - m_MinValue; -} - -/* -** Base implementation. Derivied classes can provide an alternative implementation if they have a -** string value that is not based on m_Value. -** -*/ -const WCHAR* Measure::GetStringValue() -{ - return nullptr; -} - -/* -** Returns the unformatted string value if the measure has one or a formatted value otherwise. -** -*/ -const WCHAR* Measure::GetStringOrFormattedValue(AUTOSCALE autoScale, double scale, int decimals, bool percentual) -{ - const WCHAR* stringValue = GetStringValue(); - return stringValue ? stringValue : GetFormattedValue(autoScale, scale, decimals, percentual); -} - -/* -** This method returns the value as text string. The actual value is -** get with GetValue() so we don't have to worry about m_Invert. -** -** autoScale If true, scale the value automatically to some sensible range. -** scale The scale to use if autoScale is false. -** decimals Number of decimals used in the value. If -1, get rid of ".00000" for dynamic variables. -** percentual Return the value as % from the maximum value. -*/ -const WCHAR* Measure::GetFormattedValue(AUTOSCALE autoScale, double scale, int decimals, bool percentual) -{ - static WCHAR buffer[128]; - WCHAR format[32]; - - if (percentual) - { - double val = 100.0 * GetRelativeValue(); - - _snwprintf_s(format, _TRUNCATE, L"%%.%if", decimals); - _snwprintf_s(buffer, _TRUNCATE, format, val); - } - else if (autoScale != AUTOSCALE_OFF) - { - GetScaledValue(autoScale, decimals, GetValue(), buffer, _countof(buffer)); - } - else - { - double val = GetValue() / scale; - - if (decimals == -1) - { - int len = _snwprintf_s(buffer, _TRUNCATE, L"%.5f", val); - RemoveTrailingZero(buffer, len); - } - else - { - _snwprintf_s(format, _TRUNCATE, L"%%.%if", decimals); - _snwprintf_s(buffer, _TRUNCATE, format, val); - } - } - - return CheckSubstitute(buffer); -} - -void Measure::GetScaledValue(AUTOSCALE autoScale, int decimals, double theValue, WCHAR* buffer, size_t sizeInWords) -{ - WCHAR format[32]; - double value = 0; - - if (decimals == 0) - { - wcsncpy_s(format, L"%.0f", _TRUNCATE); - } - else - { - _snwprintf_s(format, _TRUNCATE, L"%%.%if", decimals); - } - - const double* tblScale = - g_TblScale[(autoScale == AUTOSCALE_1000 || autoScale == AUTOSCALE_1000K) ? AUTOSCALE_INDEX_1000 : AUTOSCALE_INDEX_1024]; - - if (theValue >= tblScale[0]) - { - value = theValue / tblScale[0]; - wcsncat_s(format, L" T", _TRUNCATE); - } - else if (theValue >= tblScale[1]) - { - value = theValue / tblScale[1]; - wcsncat_s(format, L" G", _TRUNCATE); - } - else if (theValue >= tblScale[2]) - { - value = theValue / tblScale[2]; - wcsncat_s(format, L" M", _TRUNCATE); - } - else if (autoScale == AUTOSCALE_1024K || autoScale == AUTOSCALE_1000K || theValue >= tblScale[3]) - { - value = theValue / tblScale[3]; - wcsncat_s(format, L" k", _TRUNCATE); - } - else - { - value = theValue; - wcsncat_s(format, L" ", _TRUNCATE); - } - _snwprintf_s(buffer, sizeInWords, _TRUNCATE, format, value); -} - -void Measure::RemoveTrailingZero(WCHAR* str, int strLen) -{ - --strLen; - while (strLen >= 0) - { - if (str[strLen] == L'0') - { - str[strLen] = L'\0'; - --strLen; - } - else - { - if (str[strLen] == L'.') - { - str[strLen] = L'\0'; - } - break; - } - } -} - -/* -** Executes OnChangeAction if action is set. -** If execute parameter is set to false, only updates old value with current value. -** -*/ -void Measure::DoChangeAction(bool execute) -{ - if (!m_OnChangeAction.empty() && m_ValueAssigned) - { - double newValue = GetValue(); - const WCHAR* newStringValue = GetStringValue(); - if (!newStringValue) - { - newStringValue = L""; - } - - if (!m_OldValue) - { - m_OldValue = new MeasureValueSet(newValue, newStringValue); - } - else if (execute) - { - if (m_OldValue->IsChanged(newValue, newStringValue)) - { - Rainmeter::GetInstance().ExecuteCommand(m_OnChangeAction.c_str(), m_MeterWindow); - } - } - else - { - m_OldValue->Set(newValue, newStringValue); - } - } -} - -/* -** Creates the given measure. This is the factory method for the measures. -** If new measures are implemented this method needs to be updated. -** -*/ -Measure* Measure::Create(const WCHAR* measure, MeterWindow* meterWindow, const WCHAR* name) -{ - // Comparison is caseinsensitive - - if (_wcsicmp(L"CPU", measure) == 0) - { - return new MeasureCPU(meterWindow, name); - } - else if (_wcsicmp(L"Memory", measure) == 0) - { - return new MeasureMemory(meterWindow, name); - } - else if (_wcsicmp(L"NetIn", measure) == 0) - { - return new MeasureNetIn(meterWindow, name); - } - else if (_wcsicmp(L"NetOut", measure) == 0) - { - return new MeasureNetOut(meterWindow, name); - } - else if (_wcsicmp(L"NetTotal", measure) == 0) - { - return new MeasureNetTotal(meterWindow, name); - } - else if (_wcsicmp(L"PhysicalMemory", measure) == 0) - { - return new MeasurePhysicalMemory(meterWindow, name); - } - else if (_wcsicmp(L"SwapMemory", measure) == 0) - { - return new MeasureVirtualMemory(meterWindow, name); - } - else if (_wcsicmp(L"FreeDiskSpace", measure) == 0) - { - return new MeasureDiskSpace(meterWindow, name); - } - else if (_wcsicmp(L"Uptime", measure) == 0) - { - return new MeasureUptime(meterWindow, name); - } - else if (_wcsicmp(L"Time", measure) == 0) - { - return new MeasureTime(meterWindow, name); - } - else if (_wcsicmp(L"Plugin", measure) == 0) - { - return new MeasurePlugin(meterWindow, name); - } - else if (_wcsicmp(L"Registry", measure) == 0) - { - return new MeasureRegistry(meterWindow, name); - } - else if (_wcsicmp(L"Calc", measure) == 0) - { - return new MeasureCalc(meterWindow, name); - } - else if (_wcsicmp(L"Script", measure) == 0) - { - return new MeasureScript(meterWindow, name); - } - else if (_wcsicmp(L"String", measure) == 0) - { - return new MeasureString(meterWindow, name); - } - - LogErrorF(meterWindow, L"Measure=%s is not valid in [%s]", measure, name); - - return nullptr; -} - -/* -** Executes a custom bang. -** -*/ -void Measure::Command(const std::wstring& command) -{ - LogWarningF(this, L"!CommandMeasure: Not supported"); -} - -/* -** Returns the number value of a measure, used by IfCondition's. -** -*/ -bool Measure::GetCurrentMeasureValue(const WCHAR* str, int len, double* value, void* context) -{ - auto measure = (Measure*)context; - const std::vector& measures = measure->m_MeterWindow->GetMeasures(); - - for (const auto& iter : measures) - { - if (iter->GetOriginalName().length() == len && - _wcsnicmp(str, iter->GetName(), len) == 0) - { - *value = iter->GetValue(); - return true; - } - } - - return false; -} +/* + Copyright (C) 2000 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Measure.h" +#include "MeasureCPU.h" +#include "MeasureMemory.h" +#include "MeasurePhysicalMemory.h" +#include "MeasureVirtualMemory.h" +#include "MeasureNetIn.h" +#include "MeasureNetOut.h" +#include "MeasureNetTotal.h" +#include "MeasureDiskSpace.h" +#include "MeasureUptime.h" +#include "MeasurePlugin.h" +#include "MeasureRegistry.h" +#include "MeasureString.h" +#include "MeasureTime.h" +#include "MeasureCalc.h" +#include "MeasureScript.h" +#include "Rainmeter.h" +#include "Error.h" +#include "Litestep.h" +#include "pcre-8.10/config.h" +#include "pcre-8.10/pcre.h" + +#define OVECCOUNT 300 // Should be a multiple of 3 + +enum AUTOSCALE_INDEX +{ + AUTOSCALE_INDEX_1024 = 0, + AUTOSCALE_INDEX_1000 = 1 +}; + +static const double g_TblScale[2][4] = { + { + 1024.0 * 1024.0 * 1024.0 * 1024.0, + 1024.0 * 1024.0 * 1024.0, + 1024.0 * 1024.0, + 1024.0 + }, + { + 1000.0 * 1000.0 * 1000.0 * 1000.0, + 1000.0 * 1000.0 * 1000.0, + 1000.0 * 1000.0, + 1000.0 + } +}; + +const int MEDIAN_SIZE = 3; + +/* +** The constructor +** +*/ +Measure::Measure(MeterWindow* meterWindow, const WCHAR* name) : Section(meterWindow, name), + m_Invert(false), + m_LogMaxValue(false), + m_MinValue(), + m_MaxValue(1.0), + m_Value(), + m_RegExpSubstitute(false), + m_MedianPos(), + m_AveragePos(), + m_AverageSize(), + m_Disabled(false), + m_Paused(false), + m_Initialized(false), + m_OldValue(), + m_ValueAssigned(false) +{ +} + +/* +** The destructor +** +*/ +Measure::~Measure() +{ + delete m_OldValue; +} + +/* +** Initializes the measure. +** +*/ +void Measure::Initialize() +{ + m_Initialized = true; +} + +/* +** Read the common options specified in the ini file. The inherited classes must +** call this base implementation if they overwrite this method. +** +*/ +void Measure::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + bool oldOnChangeActionEmpty = m_OnChangeAction.empty(); + + Section::ReadOptions(parser, section); + + // Clear substitutes to prevent from being added more than once. + if (!m_Substitute.empty()) + { + m_Substitute.clear(); + } + + m_Invert = parser.ReadBool(section, L"InvertMeasure", false); + + m_Disabled = parser.ReadBool(section, L"Disabled", false); + m_Paused = parser.ReadBool(section, L"Paused", false); + + m_MinValue = parser.ReadFloat(section, L"MinValue", m_MinValue); + m_MaxValue = parser.ReadFloat(section, L"MaxValue", m_MaxValue); + + m_IfActions.ReadOptions(parser, section); + + // The first time around, we read the conditions here. Subsequent rereads will be done in + // Update() if needed. + if (!m_Initialized) + { + m_IfActions.ReadConditionOptions(parser, section); + } + + m_OnChangeAction = parser.ReadString(section, L"OnChangeAction", L"", false); + + m_AverageSize = parser.ReadUInt(section, L"AverageSize", 0); + + m_RegExpSubstitute = parser.ReadBool(section, L"RegExpSubstitute", false); + std::wstring subs = parser.ReadString(section, L"Substitute", L""); + if (!subs.empty()) + { + if ((subs[0] != L'"' || subs[subs.length() - 1] != L'\'') && + (subs[0] != L'\'' || subs[subs.length() - 1] != L'"')) + { + // Add quotes since they are removed by the GetProfileString + subs.insert(0, 1, L'"'); + subs += L'"'; + } + if (!ParseSubstitute(subs)) + { + LogErrorF(this, L"Measure: Invalid Substitute=%s", subs.c_str()); + } + } + + if (m_Initialized && + oldOnChangeActionEmpty && !m_OnChangeAction.empty()) + { + DoChangeAction(false); + } +} + +void Measure::Disable() +{ + m_Disabled = true; + + // Change the option as well to avoid reset in ReadOptions(). + m_MeterWindow->GetParser().SetValue(m_Name, L"Disabled", L"1"); +} + +void Measure::Enable() +{ + m_Disabled = false; + + // Change the option as well to avoid reset in ReadOptions(). + m_MeterWindow->GetParser().SetValue(m_Name, L"Disabled", L"0"); +} + +void Measure::Pause() +{ + m_Paused = true; + + // Change the option as well to avoid reset in ReadOptions(). + m_MeterWindow->GetParser().SetValue(m_Name, L"Paused", L"1"); +} + +void Measure::Unpause() +{ + m_Paused = false; + + // Change the option as well to avoid reset in ReadOptions(). + m_MeterWindow->GetParser().SetValue(m_Name, L"Paused", L"0"); +} + +/* +** Substitues text using a straight find and replace method +*/ +bool Measure::MakePlainSubstitute(std::wstring& str, size_t index) +{ + size_t start = 0, pos; + + do + { + pos = str.find(m_Substitute[index], start); + if (pos != std::wstring::npos) + { + str.replace(pos, m_Substitute[index].length(), m_Substitute[index + 1]); + start = pos + m_Substitute[index + 1].length(); + } + } + while (pos != std::wstring::npos); + + return true; +} + +/* +** Substitutes part of the text +*/ +const WCHAR* Measure::CheckSubstitute(const WCHAR* buffer) +{ + static std::wstring str; + + if (m_Substitute.empty()) + { + return buffer; + } + + if (!m_RegExpSubstitute) + { + str = buffer; + + for (size_t i = 0, isize = m_Substitute.size(); i < isize; i += 2) + { + if (!m_Substitute[i].empty()) + { + MakePlainSubstitute(str, i); + } + else if (str.empty()) + { + // Empty result and empty substitute -> use second + str = m_Substitute[i + 1]; + } + } + } + else + { + std::string utf8str = StringUtil::NarrowUTF8(buffer); + int ovector[300]; + + for (size_t i = 0, isize = m_Substitute.size(); i < isize; i += 2) + { + const char* error; + int errorOffset; + int offset = 0; + pcre* re = pcre_compile( + StringUtil::NarrowUTF8(m_Substitute[i]).c_str(), + PCRE_UTF8, + &error, + &errorOffset, + nullptr); // Use default character tables. + if (!re) + { + MakePlainSubstitute(str, i); + LogNoticeF(this, L"Substitute: %S", error); + } + else + { + do + { + const int rc = pcre_exec( + re, + nullptr, // No extra data - we didn't study the pattern + utf8str.c_str(), // The subject string + (int)utf8str.length(), // The length of the subject + offset, + 0, + ovector, + (int)_countof(ovector)); + if (rc <= 0) + { + break; + } + + std::string result = StringUtil::NarrowUTF8(m_Substitute[i + 1]); + + if (rc > 1) + { + for (int j = rc - 1 ; j >= 0 ; --j) + { + size_t newStart = ovector[2 * j]; + size_t inLength = ovector[2 * j + 1] - ovector[2 * j]; + + char tmpName[64]; + size_t cutLength = _snprintf_s(tmpName, _TRUNCATE, "\\%i", j);; + size_t start = 0, pos; + do + { + pos = result.find(tmpName, start, cutLength); + if (pos != std::string::npos) + { + result.replace(pos, cutLength, utf8str, newStart, inLength); + start = pos + inLength; + } + } + while (pos != std::string::npos); + } + } + + const int start = ovector[0]; + const int length = ovector[1] - ovector[0]; + utf8str.replace(start, length, result); + offset = start + (int)result.length(); + } + while (true); + + pcre_free(re); + } + } + + str = StringUtil::WidenUTF8(utf8str); + } + + return str.c_str(); +} + +/* +** Reads the buffer for "Name":"Value"-pairs separated with comma and +** fills the map with the parsed data. +*/ +bool Measure::ParseSubstitute(std::wstring buffer) +{ + if (buffer.empty()) return true; + + do + { + std::wstring word1 = ExtractWord(buffer); + std::wstring sep = ExtractWord(buffer); + if (sep.size() != 1 || sep[0] != L':') return false; + std::wstring word2 = ExtractWord(buffer); + + if (wcscmp(word1.c_str(), word2.c_str()) != 0) + { + if (m_RegExpSubstitute && word1.empty()) + { + word1 = L"^$"; + } + + m_Substitute.push_back(word1); + m_Substitute.push_back(word2); + } + + std::wstring sep2 = ExtractWord(buffer); + if (!sep2.empty() && (sep2.size() != 1 || sep2[0] != L',')) return false; + } + while (!buffer.empty()); + + return true; +} + +/* +** Returns the first word from the buffer. The word can be inside quotes. +** If not, the separators are ' ', '\t', ',' and ':'. Whitespaces are removed +** and buffer _will_ be modified. +*/ +std::wstring Measure::ExtractWord(std::wstring& buffer) +{ + std::wstring::size_type end, len = buffer.size(); + std::wstring ret; + + if (len == 0) return ret; + + // Remove whitespaces + end = 0; + while (end < len && (buffer[end] == L' ' || buffer[end] == L'\t' || buffer[end] == L'\n')) ++end; + if (end == len) + { + // End of line reached + end = std::wstring::npos; + } + else + { + buffer.erase(0, end); + len = buffer.size(); + + if (buffer[0] == L'"' || buffer[0] == L'\'') + { + WCHAR quote = buffer[0]; + + end = 1; // Skip the '"' + // Quotes around the word + while (end < len && (buffer[end] != quote)) ++end; + if (end == len) end = std::wstring::npos; + + if (end != std::wstring::npos) + { + ret.assign(buffer, 1, end - 1); + ++end; + } + else + { + // End of string reached - discard result + } + } + else + { + end = 0; + while (end < len && (buffer[end] != L',' && buffer[end] != L':' && buffer[end] != L' ' && buffer[end] != L'\t')) ++end; + if (end == len) end = std::wstring::npos; + + if (end == std::wstring::npos) + { + // End of line reached + ret = buffer; + } + else + { + ret.assign(buffer, 0, ++end); // The separator is also returned! + } + } + } + + buffer.erase(0, end); + + return ret; +} + +bool Measure::Update(bool rereadOptions) +{ + if (rereadOptions) + { + ReadOptions(m_MeterWindow->GetParser()); + } + + // Don't do anything if paused + if (m_Paused) return false; + + if (!m_Disabled) + { + // Only update the counter if the divider + if (!UpdateCounter()) return false; + + // Call derived method to update value + UpdateValue(); + + if (m_AverageSize > 0) + { + size_t averageValuesSize = m_AverageValues.size(); + + if (m_AverageSize != averageValuesSize) + { + m_AverageValues.resize(m_AverageSize, m_Value); + averageValuesSize = m_AverageValues.size(); + if (m_AveragePos >= averageValuesSize) m_AveragePos = 0; + } + m_AverageValues[m_AveragePos] = m_Value; + + ++m_AveragePos; + m_AveragePos %= averageValuesSize; + + // Calculate the average value + double value = 0; + for (size_t i = 0; i < averageValuesSize; ++i) + { + value += m_AverageValues[i]; + } + m_Value = value / (double)averageValuesSize; + } + + // If we're logging the maximum value of the measure, check if + // the new value is greater than the old one, and update if necessary. + if (m_LogMaxValue) + { + if (m_MedianValues.empty()) + { + m_MedianValues.resize(MEDIAN_SIZE, 0); + } + + m_MedianValues[m_MedianPos] = m_Value; + ++m_MedianPos; + m_MedianPos %= MEDIAN_SIZE; + + auto medianArray = m_MedianValues; + std::sort(&medianArray.data()[0], &medianArray.data()[MEDIAN_SIZE]); // Workaround for "Debug" build mode + + double medianValue = medianArray[MEDIAN_SIZE / 2]; + m_MaxValue = max(m_MaxValue, medianValue); + m_MinValue = min(m_MinValue, medianValue); + } + + m_ValueAssigned = true; + + // For the conditional options to work with the current measure value when using + // [MeasureName], we need to read the options after m_Value has been changed. + if (rereadOptions) + { + m_IfActions.ReadConditionOptions(m_MeterWindow->GetParser(), GetName()); + } + + if (m_MeterWindow) + { + m_IfActions.DoIfActions(*this, m_Value); + } + + return true; + } + else + { + // Disabled measures have 0 as value + m_Value = 0.0; + + m_IfActions.SetState(m_Value); + + return false; + } +} + +/* +** Returns the value of the measure. +** +*/ +double Measure::GetValue() +{ + // Invert if so requested + if (m_Invert) + { + return m_MaxValue - m_Value + m_MinValue; + } + + return m_Value; +} + +/* +** Returns the relative value of the measure (0.0 - 1.0). +** +*/ +double Measure::GetRelativeValue() +{ + double range = GetValueRange(); + + if (range != 0.0) + { + double value = GetValue(); + + value = min(m_MaxValue, value); + value = max(m_MinValue, value); + + value -= m_MinValue; + + return value / range; + } + + return 1.0; +} + +/* +** Returns the value range. +** +*/ +double Measure::GetValueRange() +{ + return m_MaxValue - m_MinValue; +} + +/* +** Base implementation. Derivied classes can provide an alternative implementation if they have a +** string value that is not based on m_Value. +** +*/ +const WCHAR* Measure::GetStringValue() +{ + return nullptr; +} + +/* +** Returns the unformatted string value if the measure has one or a formatted value otherwise. +** +*/ +const WCHAR* Measure::GetStringOrFormattedValue(AUTOSCALE autoScale, double scale, int decimals, bool percentual) +{ + const WCHAR* stringValue = GetStringValue(); + return stringValue ? stringValue : GetFormattedValue(autoScale, scale, decimals, percentual); +} + +/* +** This method returns the value as text string. The actual value is +** get with GetValue() so we don't have to worry about m_Invert. +** +** autoScale If true, scale the value automatically to some sensible range. +** scale The scale to use if autoScale is false. +** decimals Number of decimals used in the value. If -1, get rid of ".00000" for dynamic variables. +** percentual Return the value as % from the maximum value. +*/ +const WCHAR* Measure::GetFormattedValue(AUTOSCALE autoScale, double scale, int decimals, bool percentual) +{ + static WCHAR buffer[128]; + WCHAR format[32]; + + if (percentual) + { + double val = 100.0 * GetRelativeValue(); + + _snwprintf_s(format, _TRUNCATE, L"%%.%if", decimals); + _snwprintf_s(buffer, _TRUNCATE, format, val); + } + else if (autoScale != AUTOSCALE_OFF) + { + GetScaledValue(autoScale, decimals, GetValue(), buffer, _countof(buffer)); + } + else + { + double val = GetValue() / scale; + + if (decimals == -1) + { + int len = _snwprintf_s(buffer, _TRUNCATE, L"%.5f", val); + RemoveTrailingZero(buffer, len); + } + else + { + _snwprintf_s(format, _TRUNCATE, L"%%.%if", decimals); + _snwprintf_s(buffer, _TRUNCATE, format, val); + } + } + + return CheckSubstitute(buffer); +} + +void Measure::GetScaledValue(AUTOSCALE autoScale, int decimals, double theValue, WCHAR* buffer, size_t sizeInWords) +{ + WCHAR format[32]; + double value = 0; + + if (decimals == 0) + { + wcsncpy_s(format, L"%.0f", _TRUNCATE); + } + else + { + _snwprintf_s(format, _TRUNCATE, L"%%.%if", decimals); + } + + const double* tblScale = + g_TblScale[(autoScale == AUTOSCALE_1000 || autoScale == AUTOSCALE_1000K) ? AUTOSCALE_INDEX_1000 : AUTOSCALE_INDEX_1024]; + + if (theValue >= tblScale[0]) + { + value = theValue / tblScale[0]; + wcsncat_s(format, L" T", _TRUNCATE); + } + else if (theValue >= tblScale[1]) + { + value = theValue / tblScale[1]; + wcsncat_s(format, L" G", _TRUNCATE); + } + else if (theValue >= tblScale[2]) + { + value = theValue / tblScale[2]; + wcsncat_s(format, L" M", _TRUNCATE); + } + else if (autoScale == AUTOSCALE_1024K || autoScale == AUTOSCALE_1000K || theValue >= tblScale[3]) + { + value = theValue / tblScale[3]; + wcsncat_s(format, L" k", _TRUNCATE); + } + else + { + value = theValue; + wcsncat_s(format, L" ", _TRUNCATE); + } + _snwprintf_s(buffer, sizeInWords, _TRUNCATE, format, value); +} + +void Measure::RemoveTrailingZero(WCHAR* str, int strLen) +{ + --strLen; + while (strLen >= 0) + { + if (str[strLen] == L'0') + { + str[strLen] = L'\0'; + --strLen; + } + else + { + if (str[strLen] == L'.') + { + str[strLen] = L'\0'; + } + break; + } + } +} + +/* +** Executes OnChangeAction if action is set. +** If execute parameter is set to false, only updates old value with current value. +** +*/ +void Measure::DoChangeAction(bool execute) +{ + if (!m_OnChangeAction.empty() && m_ValueAssigned) + { + double newValue = GetValue(); + const WCHAR* newStringValue = GetStringValue(); + if (!newStringValue) + { + newStringValue = L""; + } + + if (!m_OldValue) + { + m_OldValue = new MeasureValueSet(newValue, newStringValue); + } + else if (execute) + { + if (m_OldValue->IsChanged(newValue, newStringValue)) + { + Rainmeter::GetInstance().ExecuteCommand(m_OnChangeAction.c_str(), m_MeterWindow); + } + } + else + { + m_OldValue->Set(newValue, newStringValue); + } + } +} + +/* +** Creates the given measure. This is the factory method for the measures. +** If new measures are implemented this method needs to be updated. +** +*/ +Measure* Measure::Create(const WCHAR* measure, MeterWindow* meterWindow, const WCHAR* name) +{ + // Comparison is caseinsensitive + + if (_wcsicmp(L"CPU", measure) == 0) + { + return new MeasureCPU(meterWindow, name); + } + else if (_wcsicmp(L"Memory", measure) == 0) + { + return new MeasureMemory(meterWindow, name); + } + else if (_wcsicmp(L"NetIn", measure) == 0) + { + return new MeasureNetIn(meterWindow, name); + } + else if (_wcsicmp(L"NetOut", measure) == 0) + { + return new MeasureNetOut(meterWindow, name); + } + else if (_wcsicmp(L"NetTotal", measure) == 0) + { + return new MeasureNetTotal(meterWindow, name); + } + else if (_wcsicmp(L"PhysicalMemory", measure) == 0) + { + return new MeasurePhysicalMemory(meterWindow, name); + } + else if (_wcsicmp(L"SwapMemory", measure) == 0) + { + return new MeasureVirtualMemory(meterWindow, name); + } + else if (_wcsicmp(L"FreeDiskSpace", measure) == 0) + { + return new MeasureDiskSpace(meterWindow, name); + } + else if (_wcsicmp(L"Uptime", measure) == 0) + { + return new MeasureUptime(meterWindow, name); + } + else if (_wcsicmp(L"Time", measure) == 0) + { + return new MeasureTime(meterWindow, name); + } + else if (_wcsicmp(L"Plugin", measure) == 0) + { + return new MeasurePlugin(meterWindow, name); + } + else if (_wcsicmp(L"Registry", measure) == 0) + { + return new MeasureRegistry(meterWindow, name); + } + else if (_wcsicmp(L"Calc", measure) == 0) + { + return new MeasureCalc(meterWindow, name); + } + else if (_wcsicmp(L"Script", measure) == 0) + { + return new MeasureScript(meterWindow, name); + } + else if (_wcsicmp(L"String", measure) == 0) + { + return new MeasureString(meterWindow, name); + } + + LogErrorF(meterWindow, L"Measure=%s is not valid in [%s]", measure, name); + + return nullptr; +} + +/* +** Executes a custom bang. +** +*/ +void Measure::Command(const std::wstring& command) +{ + LogWarningF(this, L"!CommandMeasure: Not supported"); +} + +/* +** Returns the number value of a measure, used by IfCondition's. +** +*/ +bool Measure::GetCurrentMeasureValue(const WCHAR* str, int len, double* value, void* context) +{ + auto measure = (Measure*)context; + const std::vector& measures = measure->m_MeterWindow->GetMeasures(); + + for (const auto& iter : measures) + { + if (iter->GetOriginalName().length() == len && + _wcsnicmp(str, iter->GetName(), len) == 0) + { + *value = iter->GetValue(); + return true; + } + } + + return false; +} diff --git a/Library/Measure.h b/Library/Measure.h index 61a3ba71..83b71cbc 100644 --- a/Library/Measure.h +++ b/Library/Measure.h @@ -1,134 +1,134 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASURE_H__ -#define __MEASURE_H__ - -#include -#include -#include -#include "IfActions.h" -#include "Litestep.h" -#include "Section.h" - -enum AUTOSCALE -{ - AUTOSCALE_1024 = 1, // scales by 1024 - AUTOSCALE_1000 = 2, // scales by 1000 - - AUTOSCALE_1024K = 101, // scales by 1024, and uses kilo as the lowest unit - AUTOSCALE_1000K = 102, // scales by 1000, and uses kilo as the lowest unit - - AUTOSCALE_OFF = 0, - AUTOSCALE_ON = AUTOSCALE_1024 -}; - -class MeasureValueSet -{ -public: - MeasureValueSet(double val, const WCHAR* str) : m_Value(val), m_StringValue(str) {} - void Set(double val, const WCHAR* str) { m_Value = val; m_StringValue = str; } - bool IsChanged(double val, const WCHAR* str) { if (m_Value != val || wcscmp(m_StringValue.c_str(), str) != 0) { Set(val, str); return true; } return false; } -private: - double m_Value; - std::wstring m_StringValue; -}; - -class Meter; -class MeterWindow; -class ConfigParser; - -class __declspec(novtable) Measure : public Section -{ -public: - virtual ~Measure(); - - Measure(const Measure& other) = delete; - - void ReadOptions(ConfigParser& parser) { ReadOptions(parser, GetName()); } - - virtual void Initialize(); - bool Update(bool rereadOptions = false); - - void Disable(); - void Enable(); - bool IsDisabled() { return m_Disabled; } - - void Pause(); - void Unpause(); - bool IsPaused() { return m_Paused; } - - virtual void Command(const std::wstring& command); - - double GetValue(); - double GetRelativeValue(); - double GetValueRange(); - double GetMinValue() { return m_MinValue; } - double GetMaxValue() { return m_MaxValue; } - - virtual const WCHAR* GetStringValue(); - const WCHAR* GetStringOrFormattedValue(AUTOSCALE autoScale, double scale, int decimals, bool percentual); - const WCHAR* GetFormattedValue(AUTOSCALE autoScale, double scale, int decimals, bool percentual); - - static void GetScaledValue(AUTOSCALE autoScale, int decimals, double theValue, WCHAR* buffer, size_t sizeInWords); - static void RemoveTrailingZero(WCHAR* str, int strLen); - - const std::wstring& GetOnChangeAction() { return m_OnChangeAction; } - void DoChangeAction(bool execute = true); - - static Measure* Create(const WCHAR* measure, MeterWindow* meterWindow, const WCHAR* name); - static bool GetCurrentMeasureValue(const WCHAR* str, int len, double* value, void* context); - -protected: - Measure(MeterWindow* meterWindow, const WCHAR* name); - - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void UpdateValue() = 0; - - bool ParseSubstitute(std::wstring buffer); - std::wstring ExtractWord(std::wstring& buffer); - const WCHAR* CheckSubstitute(const WCHAR* buffer); - bool MakePlainSubstitute(std::wstring& str, size_t index); - - bool m_Invert; // If true, the value should be inverted - bool m_LogMaxValue; // If true, The maximum & minimum values are logged - double m_MinValue; // The minimum value (so far) - double m_MaxValue; // The maximum value (so far) - double m_Value; // The current value - - std::vector m_Substitute; // Vec of substitute strings - bool m_RegExpSubstitute; - - std::vector m_MedianValues; // The values for the median filtering - UINT m_MedianPos; // Position in the median array, where the new value is placed - - std::vector m_AverageValues; - UINT m_AveragePos; - UINT m_AverageSize; - - IfActions m_IfActions; - bool m_Disabled; // Status of the measure - bool m_Paused; - bool m_Initialized; - - std::wstring m_OnChangeAction; - MeasureValueSet* m_OldValue; - bool m_ValueAssigned; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASURE_H__ +#define __MEASURE_H__ + +#include +#include +#include +#include "IfActions.h" +#include "Litestep.h" +#include "Section.h" + +enum AUTOSCALE +{ + AUTOSCALE_1024 = 1, // scales by 1024 + AUTOSCALE_1000 = 2, // scales by 1000 + + AUTOSCALE_1024K = 101, // scales by 1024, and uses kilo as the lowest unit + AUTOSCALE_1000K = 102, // scales by 1000, and uses kilo as the lowest unit + + AUTOSCALE_OFF = 0, + AUTOSCALE_ON = AUTOSCALE_1024 +}; + +class MeasureValueSet +{ +public: + MeasureValueSet(double val, const WCHAR* str) : m_Value(val), m_StringValue(str) {} + void Set(double val, const WCHAR* str) { m_Value = val; m_StringValue = str; } + bool IsChanged(double val, const WCHAR* str) { if (m_Value != val || wcscmp(m_StringValue.c_str(), str) != 0) { Set(val, str); return true; } return false; } +private: + double m_Value; + std::wstring m_StringValue; +}; + +class Meter; +class MeterWindow; +class ConfigParser; + +class __declspec(novtable) Measure : public Section +{ +public: + virtual ~Measure(); + + Measure(const Measure& other) = delete; + + void ReadOptions(ConfigParser& parser) { ReadOptions(parser, GetName()); } + + virtual void Initialize(); + bool Update(bool rereadOptions = false); + + void Disable(); + void Enable(); + bool IsDisabled() { return m_Disabled; } + + void Pause(); + void Unpause(); + bool IsPaused() { return m_Paused; } + + virtual void Command(const std::wstring& command); + + double GetValue(); + double GetRelativeValue(); + double GetValueRange(); + double GetMinValue() { return m_MinValue; } + double GetMaxValue() { return m_MaxValue; } + + virtual const WCHAR* GetStringValue(); + const WCHAR* GetStringOrFormattedValue(AUTOSCALE autoScale, double scale, int decimals, bool percentual); + const WCHAR* GetFormattedValue(AUTOSCALE autoScale, double scale, int decimals, bool percentual); + + static void GetScaledValue(AUTOSCALE autoScale, int decimals, double theValue, WCHAR* buffer, size_t sizeInWords); + static void RemoveTrailingZero(WCHAR* str, int strLen); + + const std::wstring& GetOnChangeAction() { return m_OnChangeAction; } + void DoChangeAction(bool execute = true); + + static Measure* Create(const WCHAR* measure, MeterWindow* meterWindow, const WCHAR* name); + static bool GetCurrentMeasureValue(const WCHAR* str, int len, double* value, void* context); + +protected: + Measure(MeterWindow* meterWindow, const WCHAR* name); + + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void UpdateValue() = 0; + + bool ParseSubstitute(std::wstring buffer); + std::wstring ExtractWord(std::wstring& buffer); + const WCHAR* CheckSubstitute(const WCHAR* buffer); + bool MakePlainSubstitute(std::wstring& str, size_t index); + + bool m_Invert; // If true, the value should be inverted + bool m_LogMaxValue; // If true, The maximum & minimum values are logged + double m_MinValue; // The minimum value (so far) + double m_MaxValue; // The maximum value (so far) + double m_Value; // The current value + + std::vector m_Substitute; // Vec of substitute strings + bool m_RegExpSubstitute; + + std::vector m_MedianValues; // The values for the median filtering + UINT m_MedianPos; // Position in the median array, where the new value is placed + + std::vector m_AverageValues; + UINT m_AveragePos; + UINT m_AverageSize; + + IfActions m_IfActions; + bool m_Disabled; // Status of the measure + bool m_Paused; + bool m_Initialized; + + std::wstring m_OnChangeAction; + MeasureValueSet* m_OldValue; + bool m_ValueAssigned; +}; + +#endif diff --git a/Library/MeasureCPU.cpp b/Library/MeasureCPU.cpp index 1253a0ed..f000f043 100644 --- a/Library/MeasureCPU.cpp +++ b/Library/MeasureCPU.cpp @@ -1,221 +1,221 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeasureCPU.h" -#include "Rainmeter.h" -#include "System.h" -#include "Error.h" - -#define STATUS_SUCCESS 0 -#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004 - -#define SystemProcessorPerformanceInformation 8 - -typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { - LARGE_INTEGER IdleTime; - LARGE_INTEGER KernelTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER Reserved1[2]; - ULONG Reserved2; -} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; - -#define Li2Double(x) ((double)((x).QuadPart)) -#define Ft2Double(x) ((double)((x).dwHighDateTime) * 4.294967296E9 + (double)((x).dwLowDateTime)) - -FPNTQSI MeasureCPU::c_NtQuerySystemInformation = nullptr; -int MeasureCPU::c_NumOfProcessors = 0; -ULONG MeasureCPU::c_BufferSize = 0; - -// ntdll!NtQuerySystemInformation (NT specific!) -// -// The function copies the system information of the -// specified type into a buffer -// -// NTSYSAPI -// NTSTATUS -// NTAPI -// NtQuerySystemInformation( -// IN UINT SystemInformationClass, // information type -// OUT PVOID SystemInformation, // pointer to buffer -// IN ULONG SystemInformationLength, // buffer size in bytes -// OUT PULONG ReturnLength OPTIONAL // pointer to a 32-bit -// // variable that receives -// // the number of bytes -// // written to the buffer -// ); - -/* -** The constructor -** -*/ -MeasureCPU::MeasureCPU(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), - m_Processor(), - m_OldTime() -{ - m_MaxValue = 100.0; -} - -/* -** The destructor -** -*/ -MeasureCPU::~MeasureCPU() -{ -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeasureCPU::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - Measure::ReadOptions(parser, section); - - int processor = parser.ReadInt(section, L"Processor", 0); - - if (processor < 0 || processor > c_NumOfProcessors) - { - LogWarningF(this, L"CPU: Processor=%i is not valid", processor); - processor = 0; - } - - if (processor != m_Processor) - { - m_Processor = processor; - m_OldTime[0] = m_OldTime[1] = 0.0; - } -} - -/* -** Updates the current CPU utilization value. -** -*/ -void MeasureCPU::UpdateValue() -{ - if (m_Processor == 0) - { - BOOL status; - FILETIME ftIdleTime, ftKernelTime, ftUserTime; - - // get new CPU's idle/kernel/user time - status = GetSystemTimes(&ftIdleTime, &ftKernelTime, &ftUserTime); - if (status == 0) return; - - CalcUsage(Ft2Double(ftIdleTime), - Ft2Double(ftKernelTime) + Ft2Double(ftUserTime)); - } - else if (c_NtQuerySystemInformation) - { - LONG status; - ULONG bufSize = c_BufferSize; - BYTE* buf = (bufSize > 0) ? new BYTE[bufSize] : nullptr; - - int loop = 0; - - do - { - ULONG size = 0; - - status = c_NtQuerySystemInformation(SystemProcessorPerformanceInformation, buf, bufSize, &size); - if (status == STATUS_INFO_LENGTH_MISMATCH) - { - if (size == 0) // Returned required buffer size is always 0 on Windows 2000/XP. - { - if (bufSize == 0) - { - bufSize = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * c_NumOfProcessors; - } - else - { - bufSize += sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); - } - } - else - { - if (size != bufSize) - { - bufSize = size; - } - else // ?? - { - bufSize += sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); - } - } - - delete [] buf; - buf = new BYTE[bufSize]; - } - else - { - break; - } - - ++loop; - } - while (loop < 5); - - if (status == STATUS_SUCCESS) - { - if (bufSize != c_BufferSize) - { - // Store the new buffer size - c_BufferSize = bufSize; - } - - PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION systemPerfInfo = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)buf; - - int processor = m_Processor - 1; - - CalcUsage(Li2Double(systemPerfInfo[processor].IdleTime), - Li2Double(systemPerfInfo[processor].KernelTime) + Li2Double(systemPerfInfo[processor].UserTime)); - } - - delete [] buf; - } -} - -/* -** Calculates the current CPU utilization value. -** -*/ -void MeasureCPU::CalcUsage(double idleTime, double systemTime) -{ - // CurrentCpuUsage% = 100 - ((IdleTime / SystemTime) * 100) - double dbCpuUsage = 100.0 - ((idleTime - m_OldTime[0]) / (systemTime - m_OldTime[1])) * 100.0; - - dbCpuUsage = min(dbCpuUsage, 100.0); - m_Value = max(dbCpuUsage, 0.0); - - // store new CPU's idle and system time - m_OldTime[0] = idleTime; - m_OldTime[1] = systemTime; -} - -void MeasureCPU::InitializeStatic() -{ - c_NtQuerySystemInformation = (FPNTQSI)GetProcAddress(GetModuleHandle(L"ntdll"), "NtQuerySystemInformation"); - - SYSTEM_INFO systemInfo; - GetSystemInfo(&systemInfo); - c_NumOfProcessors = (int)systemInfo.dwNumberOfProcessors; -} - -void MeasureCPU::FinalizeStatic() -{ -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeasureCPU.h" +#include "Rainmeter.h" +#include "System.h" +#include "Error.h" + +#define STATUS_SUCCESS 0 +#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004 + +#define SystemProcessorPerformanceInformation 8 + +typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { + LARGE_INTEGER IdleTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER Reserved1[2]; + ULONG Reserved2; +} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; + +#define Li2Double(x) ((double)((x).QuadPart)) +#define Ft2Double(x) ((double)((x).dwHighDateTime) * 4.294967296E9 + (double)((x).dwLowDateTime)) + +FPNTQSI MeasureCPU::c_NtQuerySystemInformation = nullptr; +int MeasureCPU::c_NumOfProcessors = 0; +ULONG MeasureCPU::c_BufferSize = 0; + +// ntdll!NtQuerySystemInformation (NT specific!) +// +// The function copies the system information of the +// specified type into a buffer +// +// NTSYSAPI +// NTSTATUS +// NTAPI +// NtQuerySystemInformation( +// IN UINT SystemInformationClass, // information type +// OUT PVOID SystemInformation, // pointer to buffer +// IN ULONG SystemInformationLength, // buffer size in bytes +// OUT PULONG ReturnLength OPTIONAL // pointer to a 32-bit +// // variable that receives +// // the number of bytes +// // written to the buffer +// ); + +/* +** The constructor +** +*/ +MeasureCPU::MeasureCPU(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), + m_Processor(), + m_OldTime() +{ + m_MaxValue = 100.0; +} + +/* +** The destructor +** +*/ +MeasureCPU::~MeasureCPU() +{ +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeasureCPU::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + Measure::ReadOptions(parser, section); + + int processor = parser.ReadInt(section, L"Processor", 0); + + if (processor < 0 || processor > c_NumOfProcessors) + { + LogWarningF(this, L"CPU: Processor=%i is not valid", processor); + processor = 0; + } + + if (processor != m_Processor) + { + m_Processor = processor; + m_OldTime[0] = m_OldTime[1] = 0.0; + } +} + +/* +** Updates the current CPU utilization value. +** +*/ +void MeasureCPU::UpdateValue() +{ + if (m_Processor == 0) + { + BOOL status; + FILETIME ftIdleTime, ftKernelTime, ftUserTime; + + // get new CPU's idle/kernel/user time + status = GetSystemTimes(&ftIdleTime, &ftKernelTime, &ftUserTime); + if (status == 0) return; + + CalcUsage(Ft2Double(ftIdleTime), + Ft2Double(ftKernelTime) + Ft2Double(ftUserTime)); + } + else if (c_NtQuerySystemInformation) + { + LONG status; + ULONG bufSize = c_BufferSize; + BYTE* buf = (bufSize > 0) ? new BYTE[bufSize] : nullptr; + + int loop = 0; + + do + { + ULONG size = 0; + + status = c_NtQuerySystemInformation(SystemProcessorPerformanceInformation, buf, bufSize, &size); + if (status == STATUS_INFO_LENGTH_MISMATCH) + { + if (size == 0) // Returned required buffer size is always 0 on Windows 2000/XP. + { + if (bufSize == 0) + { + bufSize = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * c_NumOfProcessors; + } + else + { + bufSize += sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); + } + } + else + { + if (size != bufSize) + { + bufSize = size; + } + else // ?? + { + bufSize += sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); + } + } + + delete [] buf; + buf = new BYTE[bufSize]; + } + else + { + break; + } + + ++loop; + } + while (loop < 5); + + if (status == STATUS_SUCCESS) + { + if (bufSize != c_BufferSize) + { + // Store the new buffer size + c_BufferSize = bufSize; + } + + PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION systemPerfInfo = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)buf; + + int processor = m_Processor - 1; + + CalcUsage(Li2Double(systemPerfInfo[processor].IdleTime), + Li2Double(systemPerfInfo[processor].KernelTime) + Li2Double(systemPerfInfo[processor].UserTime)); + } + + delete [] buf; + } +} + +/* +** Calculates the current CPU utilization value. +** +*/ +void MeasureCPU::CalcUsage(double idleTime, double systemTime) +{ + // CurrentCpuUsage% = 100 - ((IdleTime / SystemTime) * 100) + double dbCpuUsage = 100.0 - ((idleTime - m_OldTime[0]) / (systemTime - m_OldTime[1])) * 100.0; + + dbCpuUsage = min(dbCpuUsage, 100.0); + m_Value = max(dbCpuUsage, 0.0); + + // store new CPU's idle and system time + m_OldTime[0] = idleTime; + m_OldTime[1] = systemTime; +} + +void MeasureCPU::InitializeStatic() +{ + c_NtQuerySystemInformation = (FPNTQSI)GetProcAddress(GetModuleHandle(L"ntdll"), "NtQuerySystemInformation"); + + SYSTEM_INFO systemInfo; + GetSystemInfo(&systemInfo); + c_NumOfProcessors = (int)systemInfo.dwNumberOfProcessors; +} + +void MeasureCPU::FinalizeStatic() +{ +} diff --git a/Library/MeasureCPU.h b/Library/MeasureCPU.h index 26f21402..cbf6b11c 100644 --- a/Library/MeasureCPU.h +++ b/Library/MeasureCPU.h @@ -1,57 +1,57 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASURECPU_H__ -#define __MEASURECPU_H__ - -#include "Measure.h" - -typedef LONG (WINAPI *FPNTQSI)(UINT, PVOID, ULONG, PULONG); - -class MeasureCPU : public Measure -{ -public: - MeasureCPU(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeasureCPU(); - - MeasureCPU(const MeasureCPU& other) = delete; - MeasureCPU& operator=(MeasureCPU other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - static void InitializeStatic(); - static void FinalizeStatic(); - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void UpdateValue(); - -private: - void CalcUsage(double idleTime, double systemTime); - - int m_Processor; - - double m_OldTime[2]; - - static FPNTQSI c_NtQuerySystemInformation; - - static int c_NumOfProcessors; - static ULONG c_BufferSize; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASURECPU_H__ +#define __MEASURECPU_H__ + +#include "Measure.h" + +typedef LONG (WINAPI *FPNTQSI)(UINT, PVOID, ULONG, PULONG); + +class MeasureCPU : public Measure +{ +public: + MeasureCPU(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeasureCPU(); + + MeasureCPU(const MeasureCPU& other) = delete; + MeasureCPU& operator=(MeasureCPU other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + static void InitializeStatic(); + static void FinalizeStatic(); + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void UpdateValue(); + +private: + void CalcUsage(double idleTime, double systemTime); + + int m_Processor; + + double m_OldTime[2]; + + static FPNTQSI c_NtQuerySystemInformation; + + static int c_NumOfProcessors; + static ULONG c_BufferSize; +}; + +#endif diff --git a/Library/MeasureCalc.cpp b/Library/MeasureCalc.cpp index 4912b977..6ba10bf2 100644 --- a/Library/MeasureCalc.cpp +++ b/Library/MeasureCalc.cpp @@ -1,240 +1,240 @@ -/* - Copyright (C) 2004 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../Common/MathParser.h" -#include "MeasureCalc.h" -#include "Rainmeter.h" -#include - -const int DEFAULT_LOWER_BOUND = 0; -const int DEFAULT_UPPER_BOUND = 100; -const int DEFAULT_UNIQUELIMIT = 65535; - -std::mt19937& GetRandomEngine() -{ - static std::unique_ptr s_Engine(new std::mt19937((uint32_t)time(nullptr))); - return *s_Engine; -} - -/* -** The constructor -** -*/ -MeasureCalc::MeasureCalc(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), - m_ParseError(false), - m_LowBound(DEFAULT_LOWER_BOUND), - m_HighBound(DEFAULT_UPPER_BOUND), - m_UpdateRandom(false), - m_UniqueRandom(false) -{ -} - -/* -** The destructor -** -*/ -MeasureCalc::~MeasureCalc() -{ -} - -/* -** Updates the calculation -** -*/ -void MeasureCalc::UpdateValue() -{ - const WCHAR* errMsg = MathParser::Parse(m_Formula.c_str(), &m_Value, GetMeasureValue, this); - if (errMsg != nullptr) - { - if (!m_ParseError) - { - LogErrorF(this, L"Calc: %s", errMsg); - m_ParseError = true; - } - } - else - { - m_ParseError = false; - } -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeasureCalc::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - Measure::ReadOptions(parser, section); - - // Store the current values so we know if the value needs to be updated - int oldLowBound = m_LowBound; - int oldHighBound = m_HighBound; - bool oldUpdateRandom = m_UpdateRandom; - bool oldUniqueRandom = m_UniqueRandom; - - std::wstring oldFormula = m_Formula; - m_Formula = parser.ReadString(section, L"Formula", L""); - - m_LowBound = parser.ReadInt(section, L"LowBound", DEFAULT_LOWER_BOUND); - m_HighBound = parser.ReadInt(section, L"HighBound", DEFAULT_UPPER_BOUND); - m_UpdateRandom = parser.ReadBool(section, L"UpdateRandom", false); - const size_t range = (m_HighBound - m_LowBound) + 1; - - m_UniqueRandom = (range <= DEFAULT_UNIQUELIMIT) && parser.ReadBool(section, L"UniqueRandom", false); - if (!m_UniqueRandom) - { - m_UniqueNumbers.clear(); - } - - if (!m_Initialized || - wcscmp(m_Formula.c_str(), oldFormula.c_str()) != 0 || - oldLowBound != m_LowBound || - oldHighBound != m_HighBound || - oldUpdateRandom != m_UpdateRandom || - oldUniqueRandom != m_UniqueRandom) - { - // Reset bounds if |m_LowBound| is greater than |m_HighBound|. - if (m_LowBound > m_HighBound && - (oldLowBound != m_LowBound || oldHighBound != m_HighBound)) - { - LogErrorF(this, L"\"LowBound\" (%i) must be less then or equal to \"HighBound\" (%i)", m_LowBound, m_HighBound); - } - - // Reset the list if the bounds are changed - if (m_UniqueRandom && ( - oldLowBound != m_LowBound || - oldHighBound != m_HighBound)) - { - UpdateUniqueNumberList(); - } - - if (!m_UpdateRandom) - { - FormulaReplace(); - } - - const WCHAR* errMsg = MathParser::Check(m_Formula.c_str()); - if (errMsg != nullptr) - { - LogErrorF(this, L"Calc: %s", errMsg); - m_Formula.clear(); - } - } -} - -/* -** This replaces the word Random in the formula with a random number -** -*/ -void MeasureCalc::FormulaReplace() -{ - size_t start = 0, pos; - do - { - pos = m_Formula.find_first_of(L"Rr", start); - if (pos != std::wstring::npos) - { - if (_wcsnicmp(L"random", m_Formula.c_str() + pos, 6) == 0 && - (pos == 0 || MathParser::IsDelimiter((*(m_Formula.c_str() + pos - 1))) && - (pos == (m_Formula.length() - 6) || MathParser::IsDelimiter((*(m_Formula.c_str() + pos + 6)))))) - { - int randNumber = GetRandom(); - - WCHAR buffer[32]; - _itow_s(randNumber, buffer, 10); - size_t len = wcslen(buffer); - - m_Formula.replace(pos, 6, buffer, len); - start = pos + len; - } - else - { - start = pos + 1; - } - } - } - while (pos != std::wstring::npos); -} - -bool MeasureCalc::GetMeasureValue(const WCHAR* str, int len, double* value, void* context) -{ - auto calc = (MeasureCalc*)context; - const std::vector& measures = calc->m_MeterWindow->GetMeasures(); - - std::vector::const_iterator iter = measures.begin(); - for ( ; iter != measures.end(); ++iter) - { - if ((*iter)->GetOriginalName().length() == len && - _wcsnicmp(str, (*iter)->GetName(), len) == 0) - { - *value = (*iter)->GetValue(); - return true; - } - } - - if (_wcsnicmp(str, L"counter", len) == 0) - { - *value = calc->m_MeterWindow->GetUpdateCounter(); - return true; - } - else if (_wcsnicmp(str, L"random", len) == 0) - { - *value = calc->GetRandom(); - return true; - } - - return false; -} - -int MeasureCalc::GetRandom() -{ - if (m_LowBound == m_HighBound || m_LowBound > m_HighBound) - { - return m_LowBound; - } - else if (m_UniqueRandom) - { - if (m_UniqueNumbers.empty()) - { - UpdateUniqueNumberList(); - } - - const int value = m_UniqueNumbers.back(); - m_UniqueNumbers.pop_back(); - return value; - } - else - { - const std::uniform_int_distribution distribution(m_LowBound, m_HighBound); - return distribution(GetRandomEngine()); - } -} - -void MeasureCalc::UpdateUniqueNumberList() -{ - const size_t range = (m_HighBound - m_LowBound) + 1; - m_UniqueNumbers.resize(range); - - for (int i = 0; i < (int)range; ++i) - { - m_UniqueNumbers[i] = m_LowBound + i; - } - - std::shuffle(m_UniqueNumbers.begin(), m_UniqueNumbers.end(), GetRandomEngine()); -} +/* + Copyright (C) 2004 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../Common/MathParser.h" +#include "MeasureCalc.h" +#include "Rainmeter.h" +#include + +const int DEFAULT_LOWER_BOUND = 0; +const int DEFAULT_UPPER_BOUND = 100; +const int DEFAULT_UNIQUELIMIT = 65535; + +std::mt19937& GetRandomEngine() +{ + static std::unique_ptr s_Engine(new std::mt19937((uint32_t)time(nullptr))); + return *s_Engine; +} + +/* +** The constructor +** +*/ +MeasureCalc::MeasureCalc(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), + m_ParseError(false), + m_LowBound(DEFAULT_LOWER_BOUND), + m_HighBound(DEFAULT_UPPER_BOUND), + m_UpdateRandom(false), + m_UniqueRandom(false) +{ +} + +/* +** The destructor +** +*/ +MeasureCalc::~MeasureCalc() +{ +} + +/* +** Updates the calculation +** +*/ +void MeasureCalc::UpdateValue() +{ + const WCHAR* errMsg = MathParser::Parse(m_Formula.c_str(), &m_Value, GetMeasureValue, this); + if (errMsg != nullptr) + { + if (!m_ParseError) + { + LogErrorF(this, L"Calc: %s", errMsg); + m_ParseError = true; + } + } + else + { + m_ParseError = false; + } +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeasureCalc::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + Measure::ReadOptions(parser, section); + + // Store the current values so we know if the value needs to be updated + int oldLowBound = m_LowBound; + int oldHighBound = m_HighBound; + bool oldUpdateRandom = m_UpdateRandom; + bool oldUniqueRandom = m_UniqueRandom; + + std::wstring oldFormula = m_Formula; + m_Formula = parser.ReadString(section, L"Formula", L""); + + m_LowBound = parser.ReadInt(section, L"LowBound", DEFAULT_LOWER_BOUND); + m_HighBound = parser.ReadInt(section, L"HighBound", DEFAULT_UPPER_BOUND); + m_UpdateRandom = parser.ReadBool(section, L"UpdateRandom", false); + const size_t range = (m_HighBound - m_LowBound) + 1; + + m_UniqueRandom = (range <= DEFAULT_UNIQUELIMIT) && parser.ReadBool(section, L"UniqueRandom", false); + if (!m_UniqueRandom) + { + m_UniqueNumbers.clear(); + } + + if (!m_Initialized || + wcscmp(m_Formula.c_str(), oldFormula.c_str()) != 0 || + oldLowBound != m_LowBound || + oldHighBound != m_HighBound || + oldUpdateRandom != m_UpdateRandom || + oldUniqueRandom != m_UniqueRandom) + { + // Reset bounds if |m_LowBound| is greater than |m_HighBound|. + if (m_LowBound > m_HighBound && + (oldLowBound != m_LowBound || oldHighBound != m_HighBound)) + { + LogErrorF(this, L"\"LowBound\" (%i) must be less then or equal to \"HighBound\" (%i)", m_LowBound, m_HighBound); + } + + // Reset the list if the bounds are changed + if (m_UniqueRandom && ( + oldLowBound != m_LowBound || + oldHighBound != m_HighBound)) + { + UpdateUniqueNumberList(); + } + + if (!m_UpdateRandom) + { + FormulaReplace(); + } + + const WCHAR* errMsg = MathParser::Check(m_Formula.c_str()); + if (errMsg != nullptr) + { + LogErrorF(this, L"Calc: %s", errMsg); + m_Formula.clear(); + } + } +} + +/* +** This replaces the word Random in the formula with a random number +** +*/ +void MeasureCalc::FormulaReplace() +{ + size_t start = 0, pos; + do + { + pos = m_Formula.find_first_of(L"Rr", start); + if (pos != std::wstring::npos) + { + if (_wcsnicmp(L"random", m_Formula.c_str() + pos, 6) == 0 && + (pos == 0 || MathParser::IsDelimiter((*(m_Formula.c_str() + pos - 1))) && + (pos == (m_Formula.length() - 6) || MathParser::IsDelimiter((*(m_Formula.c_str() + pos + 6)))))) + { + int randNumber = GetRandom(); + + WCHAR buffer[32]; + _itow_s(randNumber, buffer, 10); + size_t len = wcslen(buffer); + + m_Formula.replace(pos, 6, buffer, len); + start = pos + len; + } + else + { + start = pos + 1; + } + } + } + while (pos != std::wstring::npos); +} + +bool MeasureCalc::GetMeasureValue(const WCHAR* str, int len, double* value, void* context) +{ + auto calc = (MeasureCalc*)context; + const std::vector& measures = calc->m_MeterWindow->GetMeasures(); + + std::vector::const_iterator iter = measures.begin(); + for ( ; iter != measures.end(); ++iter) + { + if ((*iter)->GetOriginalName().length() == len && + _wcsnicmp(str, (*iter)->GetName(), len) == 0) + { + *value = (*iter)->GetValue(); + return true; + } + } + + if (_wcsnicmp(str, L"counter", len) == 0) + { + *value = calc->m_MeterWindow->GetUpdateCounter(); + return true; + } + else if (_wcsnicmp(str, L"random", len) == 0) + { + *value = calc->GetRandom(); + return true; + } + + return false; +} + +int MeasureCalc::GetRandom() +{ + if (m_LowBound == m_HighBound || m_LowBound > m_HighBound) + { + return m_LowBound; + } + else if (m_UniqueRandom) + { + if (m_UniqueNumbers.empty()) + { + UpdateUniqueNumberList(); + } + + const int value = m_UniqueNumbers.back(); + m_UniqueNumbers.pop_back(); + return value; + } + else + { + const std::uniform_int_distribution distribution(m_LowBound, m_HighBound); + return distribution(GetRandomEngine()); + } +} + +void MeasureCalc::UpdateUniqueNumberList() +{ + const size_t range = (m_HighBound - m_LowBound) + 1; + m_UniqueNumbers.resize(range); + + for (int i = 0; i < (int)range; ++i) + { + m_UniqueNumbers[i] = m_LowBound + i; + } + + std::shuffle(m_UniqueNumbers.begin(), m_UniqueNumbers.end(), GetRandomEngine()); +} diff --git a/Library/MeasureCalc.h b/Library/MeasureCalc.h index ceb386e6..af6dd342 100644 --- a/Library/MeasureCalc.h +++ b/Library/MeasureCalc.h @@ -1,58 +1,58 @@ -/* - Copyright (C) 2004 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASURECALC_H__ -#define __MEASURECALC_H__ - -#include "Measure.h" - -class MeasureCalc : public Measure -{ -public: - MeasureCalc(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeasureCalc(); - - MeasureCalc(const MeasureCalc& other) = delete; - MeasureCalc& operator=(MeasureCalc other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void UpdateValue(); - -private: - static bool GetMeasureValue(const WCHAR* str, int len, double* value, void* context); - - void FormulaReplace(); - int GetRandom(); - - std::wstring m_Formula; - bool m_ParseError; - - int m_LowBound; - int m_HighBound; - - bool m_UpdateRandom; - bool m_UniqueRandom; - - std::vector m_UniqueNumbers; - void UpdateUniqueNumberList(); -}; - -#endif +/* + Copyright (C) 2004 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASURECALC_H__ +#define __MEASURECALC_H__ + +#include "Measure.h" + +class MeasureCalc : public Measure +{ +public: + MeasureCalc(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeasureCalc(); + + MeasureCalc(const MeasureCalc& other) = delete; + MeasureCalc& operator=(MeasureCalc other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void UpdateValue(); + +private: + static bool GetMeasureValue(const WCHAR* str, int len, double* value, void* context); + + void FormulaReplace(); + int GetRandom(); + + std::wstring m_Formula; + bool m_ParseError; + + int m_LowBound; + int m_HighBound; + + bool m_UpdateRandom; + bool m_UniqueRandom; + + std::vector m_UniqueNumbers; + void UpdateUniqueNumberList(); +}; + +#endif diff --git a/Library/MeasureDiskSpace.cpp b/Library/MeasureDiskSpace.cpp index 3229ed4c..c6d890b5 100644 --- a/Library/MeasureDiskSpace.cpp +++ b/Library/MeasureDiskSpace.cpp @@ -1,245 +1,245 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeasureDiskSpace.h" -#include "Rainmeter.h" -#include "System.h" -#include "../Common/PathUtil.h" - -enum DRIVETYPE -{ - DRIVETYPE_ERROR = 0, - DRIVETYPE_REMOVED = 1, - DRIVETYPE_REMOVABLE = 3, - DRIVETYPE_FIXED = 4, - DRIVETYPE_NETWORK = 5, - DRIVETYPE_CDROM = 6, - DRIVETYPE_RAM = 7, - - DRIVETYPE_MAX = DRIVETYPE_RAM -}; - -/* -** The constructor -** -*/ -MeasureDiskSpace::MeasureDiskSpace(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), - m_Type(false), - m_Total(false), - m_Label(false), - m_IgnoreRemovable(true), - m_DiskQuota(true), - m_OldTotalBytes() -{ -} - -/* -** The destructor -** -*/ -MeasureDiskSpace::~MeasureDiskSpace() -{ -} - -/* -** Updates the current disk free space value. -** -*/ -void MeasureDiskSpace::UpdateValue() -{ - if (!m_Drive.empty()) - { - const WCHAR* drive = m_Drive.c_str(); - UINT type = GetDriveType(drive); - - if (m_Type) - { - switch (type) - { - case DRIVE_UNKNOWN: - case DRIVE_NO_ROOT_DIR: - m_Value = DRIVETYPE_REMOVED; - m_StringValue = L"Removed"; - break; - case DRIVE_REMOVABLE: - m_Value = DRIVETYPE_REMOVABLE; - m_StringValue = L"Removable"; - break; - case DRIVE_FIXED: - m_Value = DRIVETYPE_FIXED; - m_StringValue = L"Fixed"; - break; - case DRIVE_REMOTE: - m_Value = DRIVETYPE_NETWORK; - m_StringValue = L"Network"; - break; - case DRIVE_CDROM: - m_Value = DRIVETYPE_CDROM; - m_StringValue = L"CDRom"; - break; - case DRIVE_RAMDISK: - m_Value = DRIVETYPE_RAM; - m_StringValue = L"Ram"; - break; - default: - m_Value = DRIVETYPE_ERROR; - m_StringValue = L"Error"; - break; - } - } - else - { - BOOL sizeResult = FALSE; - ULONGLONG i64TotalBytes, i64FreeBytes; - - if (type != DRIVE_NO_ROOT_DIR && - type != DRIVE_CDROM && - (!m_IgnoreRemovable || type != DRIVE_REMOVABLE)) // Ignore CD-ROMS and removable drives - { - if (!m_DiskQuota) - { - sizeResult = GetDiskFreeSpaceEx(drive, nullptr, (PULARGE_INTEGER)&i64TotalBytes, (PULARGE_INTEGER)&i64FreeBytes); - } - else - { - sizeResult = GetDiskFreeSpaceEx(drive, (PULARGE_INTEGER)&i64FreeBytes, (PULARGE_INTEGER)&i64TotalBytes, nullptr); - } - } - - if (sizeResult) - { - m_Value = (double)(__int64)((m_Total) ? i64TotalBytes : i64FreeBytes); - - if (i64TotalBytes != m_OldTotalBytes) - { - // Total size was changed, so set new max value. - m_MaxValue = (double)(__int64)i64TotalBytes; - m_OldTotalBytes = i64TotalBytes; - } - } - else - { - m_Value = 0.0; - m_MaxValue = 0.0; - m_OldTotalBytes = 0; - } - - if (m_Label) - { - BOOL labelResult = FALSE; - WCHAR volumeName[MAX_PATH + 1]; - - if (type != DRIVE_NO_ROOT_DIR && - (!m_IgnoreRemovable || type != DRIVE_REMOVABLE)) // Ignore removable drives - { - labelResult = GetVolumeInformation(drive, volumeName, MAX_PATH + 1, nullptr, nullptr, nullptr, nullptr, 0); - } - - m_StringValue = (labelResult) ? volumeName : L""; - } - else if (!m_StringValue.empty()) - { - m_StringValue.clear(); - } - } - } -} - -/* -** Returns the time as string. -** -*/ -const WCHAR* MeasureDiskSpace::GetStringValue() -{ - return (m_Type || m_Label) ? CheckSubstitute(m_StringValue.c_str()) : nullptr; -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeasureDiskSpace::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - double oldMaxValue = m_MaxValue; - - Measure::ReadOptions(parser, section); - - m_Drive = parser.ReadString(section, L"Drive", L"C:\\"); - if (m_Drive.empty()) - { - LogWarningF(this, L"FreeDiskSpace: Drive= empty"); - m_Value = 0.0; - m_MaxValue = 0.0; - m_OldTotalBytes = 0; - m_StringValue.clear(); - } - else - { - // A trailing backslash is required for GetDiskFreeSpaceEx(). - PathUtil::AppendBacklashIfMissing(m_Drive); - } - - m_Type = parser.ReadBool(section, L"Type", false); - m_Total = parser.ReadBool(section, L"Total", false); - m_Label = parser.ReadBool(section, L"Label", false); - m_IgnoreRemovable = parser.ReadBool(section, L"IgnoreRemovable", true); - m_DiskQuota = parser.ReadBool(section, L"DiskQuota", true); - - // Set the m_MaxValue - if (!m_Initialized) - { - BOOL result = FALSE; - ULONGLONG i64TotalBytes; - - if (!m_Drive.empty()) - { - const WCHAR* drive = m_Drive.c_str(); - UINT type = GetDriveType(drive); - if (type != DRIVE_NO_ROOT_DIR && - type != DRIVE_CDROM && - (!m_IgnoreRemovable || type != DRIVE_REMOVABLE)) // Ignore CD-ROMS and removable drives - { - result = GetDiskFreeSpaceEx(drive, nullptr, (PULARGE_INTEGER)&i64TotalBytes, nullptr); - } - } - - if (result) - { - m_MaxValue = (double)(__int64)i64TotalBytes; - m_OldTotalBytes = i64TotalBytes; - } - else - { - m_MaxValue = 0.0; - m_OldTotalBytes = 0; - } - } - else - { - if (m_Type) - { - m_MaxValue = DRIVETYPE_MAX; - m_OldTotalBytes = 0; - } - else - { - m_MaxValue = oldMaxValue; - } - } -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeasureDiskSpace.h" +#include "Rainmeter.h" +#include "System.h" +#include "../Common/PathUtil.h" + +enum DRIVETYPE +{ + DRIVETYPE_ERROR = 0, + DRIVETYPE_REMOVED = 1, + DRIVETYPE_REMOVABLE = 3, + DRIVETYPE_FIXED = 4, + DRIVETYPE_NETWORK = 5, + DRIVETYPE_CDROM = 6, + DRIVETYPE_RAM = 7, + + DRIVETYPE_MAX = DRIVETYPE_RAM +}; + +/* +** The constructor +** +*/ +MeasureDiskSpace::MeasureDiskSpace(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), + m_Type(false), + m_Total(false), + m_Label(false), + m_IgnoreRemovable(true), + m_DiskQuota(true), + m_OldTotalBytes() +{ +} + +/* +** The destructor +** +*/ +MeasureDiskSpace::~MeasureDiskSpace() +{ +} + +/* +** Updates the current disk free space value. +** +*/ +void MeasureDiskSpace::UpdateValue() +{ + if (!m_Drive.empty()) + { + const WCHAR* drive = m_Drive.c_str(); + UINT type = GetDriveType(drive); + + if (m_Type) + { + switch (type) + { + case DRIVE_UNKNOWN: + case DRIVE_NO_ROOT_DIR: + m_Value = DRIVETYPE_REMOVED; + m_StringValue = L"Removed"; + break; + case DRIVE_REMOVABLE: + m_Value = DRIVETYPE_REMOVABLE; + m_StringValue = L"Removable"; + break; + case DRIVE_FIXED: + m_Value = DRIVETYPE_FIXED; + m_StringValue = L"Fixed"; + break; + case DRIVE_REMOTE: + m_Value = DRIVETYPE_NETWORK; + m_StringValue = L"Network"; + break; + case DRIVE_CDROM: + m_Value = DRIVETYPE_CDROM; + m_StringValue = L"CDRom"; + break; + case DRIVE_RAMDISK: + m_Value = DRIVETYPE_RAM; + m_StringValue = L"Ram"; + break; + default: + m_Value = DRIVETYPE_ERROR; + m_StringValue = L"Error"; + break; + } + } + else + { + BOOL sizeResult = FALSE; + ULONGLONG i64TotalBytes, i64FreeBytes; + + if (type != DRIVE_NO_ROOT_DIR && + type != DRIVE_CDROM && + (!m_IgnoreRemovable || type != DRIVE_REMOVABLE)) // Ignore CD-ROMS and removable drives + { + if (!m_DiskQuota) + { + sizeResult = GetDiskFreeSpaceEx(drive, nullptr, (PULARGE_INTEGER)&i64TotalBytes, (PULARGE_INTEGER)&i64FreeBytes); + } + else + { + sizeResult = GetDiskFreeSpaceEx(drive, (PULARGE_INTEGER)&i64FreeBytes, (PULARGE_INTEGER)&i64TotalBytes, nullptr); + } + } + + if (sizeResult) + { + m_Value = (double)(__int64)((m_Total) ? i64TotalBytes : i64FreeBytes); + + if (i64TotalBytes != m_OldTotalBytes) + { + // Total size was changed, so set new max value. + m_MaxValue = (double)(__int64)i64TotalBytes; + m_OldTotalBytes = i64TotalBytes; + } + } + else + { + m_Value = 0.0; + m_MaxValue = 0.0; + m_OldTotalBytes = 0; + } + + if (m_Label) + { + BOOL labelResult = FALSE; + WCHAR volumeName[MAX_PATH + 1]; + + if (type != DRIVE_NO_ROOT_DIR && + (!m_IgnoreRemovable || type != DRIVE_REMOVABLE)) // Ignore removable drives + { + labelResult = GetVolumeInformation(drive, volumeName, MAX_PATH + 1, nullptr, nullptr, nullptr, nullptr, 0); + } + + m_StringValue = (labelResult) ? volumeName : L""; + } + else if (!m_StringValue.empty()) + { + m_StringValue.clear(); + } + } + } +} + +/* +** Returns the time as string. +** +*/ +const WCHAR* MeasureDiskSpace::GetStringValue() +{ + return (m_Type || m_Label) ? CheckSubstitute(m_StringValue.c_str()) : nullptr; +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeasureDiskSpace::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + double oldMaxValue = m_MaxValue; + + Measure::ReadOptions(parser, section); + + m_Drive = parser.ReadString(section, L"Drive", L"C:\\"); + if (m_Drive.empty()) + { + LogWarningF(this, L"FreeDiskSpace: Drive= empty"); + m_Value = 0.0; + m_MaxValue = 0.0; + m_OldTotalBytes = 0; + m_StringValue.clear(); + } + else + { + // A trailing backslash is required for GetDiskFreeSpaceEx(). + PathUtil::AppendBacklashIfMissing(m_Drive); + } + + m_Type = parser.ReadBool(section, L"Type", false); + m_Total = parser.ReadBool(section, L"Total", false); + m_Label = parser.ReadBool(section, L"Label", false); + m_IgnoreRemovable = parser.ReadBool(section, L"IgnoreRemovable", true); + m_DiskQuota = parser.ReadBool(section, L"DiskQuota", true); + + // Set the m_MaxValue + if (!m_Initialized) + { + BOOL result = FALSE; + ULONGLONG i64TotalBytes; + + if (!m_Drive.empty()) + { + const WCHAR* drive = m_Drive.c_str(); + UINT type = GetDriveType(drive); + if (type != DRIVE_NO_ROOT_DIR && + type != DRIVE_CDROM && + (!m_IgnoreRemovable || type != DRIVE_REMOVABLE)) // Ignore CD-ROMS and removable drives + { + result = GetDiskFreeSpaceEx(drive, nullptr, (PULARGE_INTEGER)&i64TotalBytes, nullptr); + } + } + + if (result) + { + m_MaxValue = (double)(__int64)i64TotalBytes; + m_OldTotalBytes = i64TotalBytes; + } + else + { + m_MaxValue = 0.0; + m_OldTotalBytes = 0; + } + } + else + { + if (m_Type) + { + m_MaxValue = DRIVETYPE_MAX; + m_OldTotalBytes = 0; + } + else + { + m_MaxValue = oldMaxValue; + } + } +} diff --git a/Library/MeasureDiskSpace.h b/Library/MeasureDiskSpace.h index d96546f9..8d63edf2 100644 --- a/Library/MeasureDiskSpace.h +++ b/Library/MeasureDiskSpace.h @@ -1,53 +1,53 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASUREDISKSPACE_H__ -#define __MEASUREDISKSPACE_H__ - -#include "Measure.h" - -class MeasureDiskSpace : public Measure -{ -public: - MeasureDiskSpace(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeasureDiskSpace(); - - MeasureDiskSpace(const MeasureDiskSpace& other) = delete; - MeasureDiskSpace& operator=(MeasureDiskSpace other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - virtual const WCHAR* GetStringValue(); - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void UpdateValue(); - -private: - std::wstring m_Drive; - std::wstring m_StringValue; - bool m_Type; - bool m_Total; - bool m_Label; - bool m_IgnoreRemovable; - bool m_DiskQuota; - - ULONGLONG m_OldTotalBytes; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASUREDISKSPACE_H__ +#define __MEASUREDISKSPACE_H__ + +#include "Measure.h" + +class MeasureDiskSpace : public Measure +{ +public: + MeasureDiskSpace(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeasureDiskSpace(); + + MeasureDiskSpace(const MeasureDiskSpace& other) = delete; + MeasureDiskSpace& operator=(MeasureDiskSpace other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + virtual const WCHAR* GetStringValue(); + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void UpdateValue(); + +private: + std::wstring m_Drive; + std::wstring m_StringValue; + bool m_Type; + bool m_Total; + bool m_Label; + bool m_IgnoreRemovable; + bool m_DiskQuota; + + ULONGLONG m_OldTotalBytes; +}; + +#endif diff --git a/Library/MeasureMemory.cpp b/Library/MeasureMemory.cpp index 9b82a91b..f3223911 100644 --- a/Library/MeasureMemory.cpp +++ b/Library/MeasureMemory.cpp @@ -1,76 +1,76 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeasureMemory.h" -#include "ConfigParser.h" - -/* -** The constructor -** -*/ -MeasureMemory::MeasureMemory(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), - m_Total(false) -{ - MEMORYSTATUSEX stat; - stat.dwLength = sizeof(MEMORYSTATUSEX); - GlobalMemoryStatusEx(&stat); - m_MaxValue = (double)(__int64)(stat.ullTotalPageFile + stat.ullTotalPhys); -} - -/* -** The destructor -** -*/ -MeasureMemory::~MeasureMemory() -{ -} - -/* -** Updates the current total memory value. -** -*/ -void MeasureMemory::UpdateValue() -{ - MEMORYSTATUSEX stat; - stat.dwLength = sizeof(MEMORYSTATUSEX); - GlobalMemoryStatusEx(&stat); - m_MaxValue = (double)(__int64)(stat.ullTotalPageFile + stat.ullTotalPhys); - - if (m_Total) - { - m_Value = m_MaxValue; - } - else - { - m_Value = (double)(__int64)(stat.ullTotalPageFile + stat.ullTotalPhys - stat.ullAvailPageFile - stat.ullAvailPhys); - } -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeasureMemory::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - double oldMaxValue = m_MaxValue; - Measure::ReadOptions(parser, section); - m_MaxValue = oldMaxValue; - - m_Total = parser.ReadBool(section, L"Total", false); -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeasureMemory.h" +#include "ConfigParser.h" + +/* +** The constructor +** +*/ +MeasureMemory::MeasureMemory(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), + m_Total(false) +{ + MEMORYSTATUSEX stat; + stat.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&stat); + m_MaxValue = (double)(__int64)(stat.ullTotalPageFile + stat.ullTotalPhys); +} + +/* +** The destructor +** +*/ +MeasureMemory::~MeasureMemory() +{ +} + +/* +** Updates the current total memory value. +** +*/ +void MeasureMemory::UpdateValue() +{ + MEMORYSTATUSEX stat; + stat.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&stat); + m_MaxValue = (double)(__int64)(stat.ullTotalPageFile + stat.ullTotalPhys); + + if (m_Total) + { + m_Value = m_MaxValue; + } + else + { + m_Value = (double)(__int64)(stat.ullTotalPageFile + stat.ullTotalPhys - stat.ullAvailPageFile - stat.ullAvailPhys); + } +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeasureMemory::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + double oldMaxValue = m_MaxValue; + Measure::ReadOptions(parser, section); + m_MaxValue = oldMaxValue; + + m_Total = parser.ReadBool(section, L"Total", false); +} diff --git a/Library/MeasureMemory.h b/Library/MeasureMemory.h index ae0798ba..b7f9ba36 100644 --- a/Library/MeasureMemory.h +++ b/Library/MeasureMemory.h @@ -1,43 +1,43 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASUREMEMORY_H__ -#define __MEASUREMEMORY_H__ - -#include "Measure.h" - -class MeasureMemory : public Measure -{ -public: - MeasureMemory(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeasureMemory(); - - MeasureMemory(const MeasureMemory& other) = delete; - MeasureMemory& operator=(MeasureMemory other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void UpdateValue(); - -private: - bool m_Total; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASUREMEMORY_H__ +#define __MEASUREMEMORY_H__ + +#include "Measure.h" + +class MeasureMemory : public Measure +{ +public: + MeasureMemory(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeasureMemory(); + + MeasureMemory(const MeasureMemory& other) = delete; + MeasureMemory& operator=(MeasureMemory other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void UpdateValue(); + +private: + bool m_Total; +}; + +#endif diff --git a/Library/MeasureNet.cpp b/Library/MeasureNet.cpp index 8a29ac85..902b1e4f 100644 --- a/Library/MeasureNet.cpp +++ b/Library/MeasureNet.cpp @@ -1,736 +1,736 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeasureNet.h" -#include "Rainmeter.h" -#include "System.h" - -BYTE* MeasureNet::c_Table = nullptr; -UINT MeasureNet::c_NumOfTables = 0; -std::vector MeasureNet::c_StatValues; -std::vector MeasureNet::c_OldStatValues; - -decltype(GetIfTable2)* MeasureNet::c_GetIfTable2 = nullptr; -decltype(FreeMibTable)* MeasureNet::c_FreeMibTable = nullptr; - -/* -** The constructor. This is the base class for the net-meters. -** -*/ -MeasureNet::MeasureNet(MeterWindow* meterWindow, const WCHAR* name, NET type) : Measure(meterWindow, name), - m_Net(type), - m_Interface(), - m_Octets(), - m_FirstTime(true), - m_Cumulative(false) -{ -} - -/* -** The destructor -** -*/ -MeasureNet::~MeasureNet() -{ -} - -/* -** Reads the tables for all net interfaces -** -*/ -void MeasureNet::UpdateIFTable() -{ - bool logging = false; - - if (c_GetIfTable2) - { - if (c_Table) - { - c_FreeMibTable(c_Table); - c_Table = nullptr; - } - - if (c_GetIfTable2((MIB_IF_TABLE2**)&c_Table) == NO_ERROR) - { - MIB_IF_TABLE2* ifTable = (MIB_IF_TABLE2*)c_Table; - - if (c_NumOfTables != ifTable->NumEntries) - { - c_NumOfTables = ifTable->NumEntries; - logging = true; - } - - if (Rainmeter::GetInstance().GetDebug() && logging) - { - LogDebug(L"------------------------------"); - LogDebugF(L"* NETWORK-INTERFACE: Count=%i", c_NumOfTables); - - for (size_t i = 0; i < c_NumOfTables; ++i) - { - const WCHAR* type = L"Other"; - switch (ifTable->Table[i].Type) - { - case IF_TYPE_ETHERNET_CSMACD: - type = L"Ethernet"; - break; - case IF_TYPE_PPP: - type = L"PPP"; - break; - case IF_TYPE_SOFTWARE_LOOPBACK: - type = L"Loopback"; - break; - case IF_TYPE_IEEE80211: - type = L"IEEE802.11"; - break; - case IF_TYPE_TUNNEL: - type = L"Tunnel"; - break; - case IF_TYPE_IEEE1394: - type = L"IEEE1394"; - break; - } - - LogDebugF(L"%i: %s", (int)i + 1, ifTable->Table[i].Description); - LogDebugF(L" Alias: %s", ifTable->Table[i].Alias); - LogDebugF(L" Type=%s(%i), Hardware=%s, Filter=%s", - type, ifTable->Table[i].Type, - (ifTable->Table[i].InterfaceAndOperStatusFlags.HardwareInterface == 1) ? L"Yes" : L"No", - (ifTable->Table[i].InterfaceAndOperStatusFlags.FilterInterface == 1) ? L"Yes" : L"No"); - } - LogDebug(L"------------------------------"); - } - } - else - { - // Something's wrong. Unable to get the table. - c_Table = nullptr; - c_NumOfTables = 0; - } - } - else - { - if (c_Table == nullptr) - { - // Gotta reserve few bytes for the tables - DWORD value = 0; - if (GetNumberOfInterfaces(&value) == NO_ERROR) - { - if (c_NumOfTables != value) - { - c_NumOfTables = value; - logging = true; - } - - if (c_NumOfTables > 0) - { - DWORD size = sizeof(MIB_IFTABLE) + sizeof(MIB_IFROW) * c_NumOfTables; - c_Table = new BYTE[size]; - } - } - } - - if (c_Table) - { - DWORD ret, size = 0; - - MIB_IFTABLE* ifTable = (MIB_IFTABLE*)c_Table; - - if ((ret = GetIfTable(ifTable, &size, FALSE)) == ERROR_INSUFFICIENT_BUFFER) - { - delete [] c_Table; - c_Table = new BYTE[size]; - - ifTable = (MIB_IFTABLE*)c_Table; - - ret = GetIfTable(ifTable, &size, FALSE); - } - - if (ret == NO_ERROR) - { - if (c_NumOfTables != ifTable->dwNumEntries) - { - c_NumOfTables = ifTable->dwNumEntries; - logging = true; - } - - if (Rainmeter::GetInstance().GetDebug() && logging) - { - LogDebug(L"------------------------------"); - LogDebugF(L"* NETWORK-INTERFACE: Count=%i", c_NumOfTables); - - for (size_t i = 0; i < c_NumOfTables; ++i) - { - const WCHAR* type = L""; - switch (ifTable->table[i].dwType) - { - case IF_TYPE_ETHERNET_CSMACD: - type = L"Ethernet"; - break; - case IF_TYPE_PPP: - type = L"PPP"; - break; - case IF_TYPE_SOFTWARE_LOOPBACK: - type = L"Loopback"; - break; - case IF_TYPE_IEEE80211: - type = L"IEEE802.11"; - break; - case IF_TYPE_TUNNEL: - type = L"Tunnel"; - break; - case IF_TYPE_IEEE1394: - type = L"IEEE1394"; - break; - default: - type = L"Other"; - break; - } - - LogDebugF(L"%i: %.*S", (int)i + 1, ifTable->table[i].dwDescrLen, (char*)ifTable->table[i].bDescr); - LogDebugF(L" Type=%s(%i)", type, ifTable->table[i].dwType); - } - LogDebug(L"------------------------------"); - } - } - else - { - // Something's wrong. Unable to get the table. - delete [] c_Table; - c_Table = nullptr; - c_NumOfTables = 0; - } - } - } -} - -/* -** Reads the amount of octets. This is the same for in, out and total. -** the net-parameter informs which inherited class called this method. -** -*/ -ULONG64 MeasureNet::GetNetOctets(NET net) -{ - ULONG64 value = 0; - - if (c_GetIfTable2) - { - MIB_IF_ROW2* table = (MIB_IF_ROW2*)((MIB_IF_TABLE2*)c_Table)->Table; - - if (m_Interface == 0) - { - // Get all interfaces - for (UINT i = 0; i < c_NumOfTables; ++i) - { - // Ignore the loopback and filter interfaces - if (table[i].Type == IF_TYPE_SOFTWARE_LOOPBACK || - table[i].InterfaceAndOperStatusFlags.FilterInterface == 1) continue; - - switch (net) - { - case NET_IN: - value += table[i].InOctets; - break; - - case NET_OUT: - value += table[i].OutOctets; - break; - - case NET_TOTAL: - value += table[i].InOctets; - value += table[i].OutOctets; - break; - } - } - } - else - { - // Get the selected interface - if (m_Interface <= c_NumOfTables) - { - switch (net) - { - case NET_IN: - value += table[m_Interface - 1].InOctets; - break; - - case NET_OUT: - value += table[m_Interface - 1].OutOctets; - break; - - case NET_TOTAL: - value += table[m_Interface - 1].InOctets; - value += table[m_Interface - 1].OutOctets; - break; - } - } - } - } - else - { - MIB_IFROW* table = (MIB_IFROW*)((MIB_IFTABLE*)c_Table)->table; - - if (m_Interface == 0) - { - // Get all interfaces - for (UINT i = 0; i < c_NumOfTables; ++i) - { - // Ignore the loopback - if (table[i].dwType == IF_TYPE_SOFTWARE_LOOPBACK) continue; - - switch (net) - { - case NET_IN: - value += table[i].dwInOctets; - break; - - case NET_OUT: - value += table[i].dwOutOctets; - break; - - case NET_TOTAL: - value += table[i].dwInOctets; - value += table[i].dwOutOctets; - break; - } - } - } - else - { - // Get the selected interface - if (m_Interface <= c_NumOfTables) - { - switch (net) - { - case NET_IN: - value += table[m_Interface - 1].dwInOctets; - break; - - case NET_OUT: - value += table[m_Interface - 1].dwOutOctets; - break; - - case NET_TOTAL: - value += table[m_Interface - 1].dwInOctets; - value += table[m_Interface - 1].dwOutOctets; - break; - } - } - } - } - - return value; -} - -/* -** Returns the stats value of the interface -** -*/ -ULONG64 MeasureNet::GetNetStatsValue(NET net) -{ - ULONG64 value = 0; - size_t statsSize = c_StatValues.size() / 2; - - if (m_Interface == 0) - { - // Get all interfaces - for (size_t i = 0; i < statsSize; ++i) - { - // Ignore the loopback and filter interfaces - if (c_NumOfTables == statsSize) - { - if (c_GetIfTable2) - { - if (((MIB_IF_TABLE2*)c_Table)->Table[i].Type == IF_TYPE_SOFTWARE_LOOPBACK || - ((MIB_IF_TABLE2*)c_Table)->Table[i].InterfaceAndOperStatusFlags.FilterInterface == 1) continue; - } - else - { - if (((MIB_IFTABLE*)c_Table)->table[i].dwType == IF_TYPE_SOFTWARE_LOOPBACK) continue; - } - } - - switch (net) - { - case NET_IN: - value += c_StatValues[i * 2 + 0]; - break; - - case NET_OUT: - value += c_StatValues[i * 2 + 1]; - break; - - case NET_TOTAL: - value += c_StatValues[i * 2 + 0]; - value += c_StatValues[i * 2 + 1]; - break; - } - } - } - else - { - // Get the selected interface - if (m_Interface <= statsSize) - { - switch (net) - { - case NET_IN: - value += c_StatValues[(m_Interface - 1) * 2 + 0]; - break; - - case NET_OUT: - value += c_StatValues[(m_Interface - 1) * 2 + 1]; - break; - - case NET_TOTAL: - value += c_StatValues[(m_Interface - 1) * 2 + 0]; - value += c_StatValues[(m_Interface - 1) * 2 + 1]; - break; - } - } - } - - return value; -} - -/* -** Updates the current value. -** -*/ -void MeasureNet::UpdateValue() -{ - if (c_Table == nullptr) return; - - if (m_Cumulative) - { - m_Value = (double)(__int64)GetNetStatsValue(m_Net); - } - else - { - ULONG64 value = 0; - - if (!m_FirstTime) - { - value = GetNetOctets(m_Net); - if (value > m_Octets) - { - ULONG64 tmpValue = value; - value -= m_Octets; - m_Octets = tmpValue; - } - else - { - m_Octets = value; - value = 0; - } - } - else - { - m_Octets = GetNetOctets(m_Net); - m_FirstTime = false; - } - - m_Value = (double)(__int64)value; - } -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeasureNet::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - Measure::ReadOptions(parser, section); - - double value; - const WCHAR* netName = nullptr; - - if (m_Net == NET_IN) - { - netName = L"NetInSpeed"; - value = Rainmeter::GetInstance().GetGlobalOptions().netInSpeed; - } - else if (m_Net == NET_OUT) - { - netName = L"NetOutSpeed"; - value = Rainmeter::GetInstance().GetGlobalOptions().netOutSpeed; - } - else // if (m_Net == NET_TOTAL) - { - netName = L"NetTotalSpeed"; - value = Rainmeter::GetInstance().GetGlobalOptions().netInSpeed + Rainmeter::GetInstance().GetGlobalOptions().netOutSpeed; - } - - double maxValue = parser.ReadFloat(section, L"MaxValue", -1); - if (maxValue == -1) - { - maxValue = parser.ReadFloat(section, netName, -1); - if (maxValue == -1) - { - maxValue = value; - } - } - - m_Interface = parser.ReadInt(section, L"Interface", 0); - - m_Cumulative = parser.ReadBool(section, L"Cumulative", false); - if (m_Cumulative) - { - Rainmeter::GetInstance().SetNetworkStatisticsTimer(); - } - - if (maxValue == 0.0) - { - if (!m_LogMaxValue) - { - m_MaxValue = 1.0; - m_LogMaxValue = true; - m_MedianValues.clear(); - } - } - else - { - m_MaxValue = maxValue / 8; - m_LogMaxValue = false; - } -} - -/* -** Updates the statistics. -** -*/ -void MeasureNet::UpdateStats() -{ - if (c_Table) - { - size_t statsSize = c_NumOfTables * 2; - - // Fill the vectors - if (c_StatValues.size() < statsSize) - { - c_StatValues.resize(statsSize, 0); - } - - if (c_OldStatValues.size() < statsSize) - { - c_OldStatValues.resize(statsSize, 0); - } - - for (UINT i = 0; i < c_NumOfTables; ++i) - { - ULONG64 in, out; - - if (c_GetIfTable2) - { - in = ((MIB_IF_TABLE2*)c_Table)->Table[i].InOctets; - out = ((MIB_IF_TABLE2*)c_Table)->Table[i].OutOctets; - } - else - { - in = ((MIB_IFTABLE*)c_Table)->table[i].dwInOctets; - out = ((MIB_IFTABLE*)c_Table)->table[i].dwOutOctets; - } - - if (c_OldStatValues[i * 2 + 0] != 0) - { - if (in > c_OldStatValues[i * 2 + 0]) - { - c_StatValues[i * 2 + 0] += in - c_OldStatValues[i * 2 + 0]; - } - } - - if (c_OldStatValues[i * 2 + 1] != 0) - { - if (out > c_OldStatValues[i * 2 + 1]) - { - c_StatValues[i * 2 + 1] += out - c_OldStatValues[i * 2 + 1]; - } - } - - c_OldStatValues[i * 2 + 0] = in; - c_OldStatValues[i * 2 + 1] = out; - } - } -} - -/* -** Resets the statistics. -** -*/ -void MeasureNet::ResetStats() -{ - c_StatValues.clear(); -} - -/* -** Reads statistics. -** -*/ -void MeasureNet::ReadStats(const std::wstring& iniFile, std::wstring& statsDate) -{ - WCHAR buffer[48]; - - ConfigParser parser; - parser.Initialize(iniFile, nullptr, L"Statistics"); - - const std::wstring& date = parser.ReadString(L"Statistics", L"Since", L"", false); - if (!date.empty()) - { - statsDate = date; - } - - uint32_t count = parser.ReadUInt(L"Statistics", L"Count", 0); - if (parser.GetLastDefaultUsed()) - { - count = parser.ReadUInt(L"Statistics", L"NetStatsCount", 0); - } - - c_StatValues.clear(); - c_StatValues.reserve(count * 2); - - for (uint32_t i = 1; i <= count; ++i) - { - ULARGE_INTEGER value; - - _snwprintf_s(buffer, _TRUNCATE, L"In%u", i); - value.QuadPart = parser.ReadUInt64(L"Statistics", buffer, 0); - if (parser.GetLastDefaultUsed()) - { - _snwprintf_s(buffer, _TRUNCATE, L"NetStatsInHigh%u", i); - value.HighPart = parser.ReadUInt(L"Statistics", buffer, 0); - - _snwprintf_s(buffer, _TRUNCATE, L"NetStatsInLow%u", i); - value.LowPart = parser.ReadUInt(L"Statistics", buffer, 0); - } - c_StatValues.push_back(value.QuadPart); - - _snwprintf_s(buffer, _TRUNCATE, L"Out%u", i); - value.QuadPart = parser.ReadUInt64(L"Statistics", buffer, 0); - if (parser.GetLastDefaultUsed()) - { - _snwprintf_s(buffer, _TRUNCATE, L"NetStatsOutHigh%u", i); - value.HighPart = parser.ReadUInt(L"Statistics", buffer, 0); - - _snwprintf_s(buffer, _TRUNCATE, L"NetStatsOutLow%u", i); - value.LowPart = parser.ReadUInt(L"Statistics", buffer, 0); - } - c_StatValues.push_back(value.QuadPart); - } -} - -/* -** Writes statistics. -** -*/ -void MeasureNet::WriteStats(const WCHAR* iniFile, const std::wstring& statsDate) -{ - WCHAR buffer[48]; - int len; - - uint32_t count = (uint32_t)c_StatValues.size() / 2; - - // Reserve sufficient buffer for statistics - std::wstring data; - data.reserve(48 * (2 + count)); - - // Add date - data = L"Since="; - data += statsDate; - data += L'\0'; - - auto appendStatsValue = [&]() - { - data.append(buffer, len); - data += L'\0'; - }; - - // Add stats count - len = _snwprintf_s(buffer, _TRUNCATE, L"Count=%u", count); - appendStatsValue(); - - // Add stats - for (uint32_t i = 0; i < count; ++i) - { - if (c_StatValues[i * 2] > 0) - { - len = _snwprintf_s(buffer, _TRUNCATE, L"In%u=%llu", i + 1, c_StatValues[i * 2]); - appendStatsValue(); - } - - if (c_StatValues[i * 2 + 1] > 0) - { - len = _snwprintf_s(buffer, _TRUNCATE, L"Out%u=%llu", i + 1, c_StatValues[i * 2 + 1]); - appendStatsValue(); - } - } - - // Write statistics - WritePrivateProfileSection(L"Statistics", data.c_str(), iniFile); -} - -/* -** Prepares in order to use the new APIs which are available on Vista or newer. -** -*/ -void MeasureNet::InitializeStatic() -{ - if (IsWindowsVistaOrGreater()) - { - HMODULE IpHlpApiLibrary = GetModuleHandle(L"IpHlpApi.dll"); - if (IpHlpApiLibrary) - { - c_GetIfTable2 = (decltype(c_GetIfTable2))GetProcAddress(IpHlpApiLibrary, "GetIfTable2"); - c_FreeMibTable = (decltype(c_FreeMibTable))GetProcAddress(IpHlpApiLibrary, "FreeMibTable"); - } - - if (!c_GetIfTable2 || !c_FreeMibTable) - { - c_GetIfTable2 = nullptr; - c_FreeMibTable = nullptr; - } - } - - if (Rainmeter::GetInstance().GetDebug()) - { - UpdateIFTable(); - } -} - -/* -** Frees the resources. -** -*/ -void MeasureNet::FinalizeStatic() -{ - if (c_GetIfTable2) - { - if (c_Table) - { - c_FreeMibTable(c_Table); - } - - c_GetIfTable2 = nullptr; - c_FreeMibTable = nullptr; - } - else - { - delete [] c_Table; - } - c_Table = nullptr; - c_NumOfTables = 0; -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeasureNet.h" +#include "Rainmeter.h" +#include "System.h" + +BYTE* MeasureNet::c_Table = nullptr; +UINT MeasureNet::c_NumOfTables = 0; +std::vector MeasureNet::c_StatValues; +std::vector MeasureNet::c_OldStatValues; + +decltype(GetIfTable2)* MeasureNet::c_GetIfTable2 = nullptr; +decltype(FreeMibTable)* MeasureNet::c_FreeMibTable = nullptr; + +/* +** The constructor. This is the base class for the net-meters. +** +*/ +MeasureNet::MeasureNet(MeterWindow* meterWindow, const WCHAR* name, NET type) : Measure(meterWindow, name), + m_Net(type), + m_Interface(), + m_Octets(), + m_FirstTime(true), + m_Cumulative(false) +{ +} + +/* +** The destructor +** +*/ +MeasureNet::~MeasureNet() +{ +} + +/* +** Reads the tables for all net interfaces +** +*/ +void MeasureNet::UpdateIFTable() +{ + bool logging = false; + + if (c_GetIfTable2) + { + if (c_Table) + { + c_FreeMibTable(c_Table); + c_Table = nullptr; + } + + if (c_GetIfTable2((MIB_IF_TABLE2**)&c_Table) == NO_ERROR) + { + MIB_IF_TABLE2* ifTable = (MIB_IF_TABLE2*)c_Table; + + if (c_NumOfTables != ifTable->NumEntries) + { + c_NumOfTables = ifTable->NumEntries; + logging = true; + } + + if (Rainmeter::GetInstance().GetDebug() && logging) + { + LogDebug(L"------------------------------"); + LogDebugF(L"* NETWORK-INTERFACE: Count=%i", c_NumOfTables); + + for (size_t i = 0; i < c_NumOfTables; ++i) + { + const WCHAR* type = L"Other"; + switch (ifTable->Table[i].Type) + { + case IF_TYPE_ETHERNET_CSMACD: + type = L"Ethernet"; + break; + case IF_TYPE_PPP: + type = L"PPP"; + break; + case IF_TYPE_SOFTWARE_LOOPBACK: + type = L"Loopback"; + break; + case IF_TYPE_IEEE80211: + type = L"IEEE802.11"; + break; + case IF_TYPE_TUNNEL: + type = L"Tunnel"; + break; + case IF_TYPE_IEEE1394: + type = L"IEEE1394"; + break; + } + + LogDebugF(L"%i: %s", (int)i + 1, ifTable->Table[i].Description); + LogDebugF(L" Alias: %s", ifTable->Table[i].Alias); + LogDebugF(L" Type=%s(%i), Hardware=%s, Filter=%s", + type, ifTable->Table[i].Type, + (ifTable->Table[i].InterfaceAndOperStatusFlags.HardwareInterface == 1) ? L"Yes" : L"No", + (ifTable->Table[i].InterfaceAndOperStatusFlags.FilterInterface == 1) ? L"Yes" : L"No"); + } + LogDebug(L"------------------------------"); + } + } + else + { + // Something's wrong. Unable to get the table. + c_Table = nullptr; + c_NumOfTables = 0; + } + } + else + { + if (c_Table == nullptr) + { + // Gotta reserve few bytes for the tables + DWORD value = 0; + if (GetNumberOfInterfaces(&value) == NO_ERROR) + { + if (c_NumOfTables != value) + { + c_NumOfTables = value; + logging = true; + } + + if (c_NumOfTables > 0) + { + DWORD size = sizeof(MIB_IFTABLE) + sizeof(MIB_IFROW) * c_NumOfTables; + c_Table = new BYTE[size]; + } + } + } + + if (c_Table) + { + DWORD ret, size = 0; + + MIB_IFTABLE* ifTable = (MIB_IFTABLE*)c_Table; + + if ((ret = GetIfTable(ifTable, &size, FALSE)) == ERROR_INSUFFICIENT_BUFFER) + { + delete [] c_Table; + c_Table = new BYTE[size]; + + ifTable = (MIB_IFTABLE*)c_Table; + + ret = GetIfTable(ifTable, &size, FALSE); + } + + if (ret == NO_ERROR) + { + if (c_NumOfTables != ifTable->dwNumEntries) + { + c_NumOfTables = ifTable->dwNumEntries; + logging = true; + } + + if (Rainmeter::GetInstance().GetDebug() && logging) + { + LogDebug(L"------------------------------"); + LogDebugF(L"* NETWORK-INTERFACE: Count=%i", c_NumOfTables); + + for (size_t i = 0; i < c_NumOfTables; ++i) + { + const WCHAR* type = L""; + switch (ifTable->table[i].dwType) + { + case IF_TYPE_ETHERNET_CSMACD: + type = L"Ethernet"; + break; + case IF_TYPE_PPP: + type = L"PPP"; + break; + case IF_TYPE_SOFTWARE_LOOPBACK: + type = L"Loopback"; + break; + case IF_TYPE_IEEE80211: + type = L"IEEE802.11"; + break; + case IF_TYPE_TUNNEL: + type = L"Tunnel"; + break; + case IF_TYPE_IEEE1394: + type = L"IEEE1394"; + break; + default: + type = L"Other"; + break; + } + + LogDebugF(L"%i: %.*S", (int)i + 1, ifTable->table[i].dwDescrLen, (char*)ifTable->table[i].bDescr); + LogDebugF(L" Type=%s(%i)", type, ifTable->table[i].dwType); + } + LogDebug(L"------------------------------"); + } + } + else + { + // Something's wrong. Unable to get the table. + delete [] c_Table; + c_Table = nullptr; + c_NumOfTables = 0; + } + } + } +} + +/* +** Reads the amount of octets. This is the same for in, out and total. +** the net-parameter informs which inherited class called this method. +** +*/ +ULONG64 MeasureNet::GetNetOctets(NET net) +{ + ULONG64 value = 0; + + if (c_GetIfTable2) + { + MIB_IF_ROW2* table = (MIB_IF_ROW2*)((MIB_IF_TABLE2*)c_Table)->Table; + + if (m_Interface == 0) + { + // Get all interfaces + for (UINT i = 0; i < c_NumOfTables; ++i) + { + // Ignore the loopback and filter interfaces + if (table[i].Type == IF_TYPE_SOFTWARE_LOOPBACK || + table[i].InterfaceAndOperStatusFlags.FilterInterface == 1) continue; + + switch (net) + { + case NET_IN: + value += table[i].InOctets; + break; + + case NET_OUT: + value += table[i].OutOctets; + break; + + case NET_TOTAL: + value += table[i].InOctets; + value += table[i].OutOctets; + break; + } + } + } + else + { + // Get the selected interface + if (m_Interface <= c_NumOfTables) + { + switch (net) + { + case NET_IN: + value += table[m_Interface - 1].InOctets; + break; + + case NET_OUT: + value += table[m_Interface - 1].OutOctets; + break; + + case NET_TOTAL: + value += table[m_Interface - 1].InOctets; + value += table[m_Interface - 1].OutOctets; + break; + } + } + } + } + else + { + MIB_IFROW* table = (MIB_IFROW*)((MIB_IFTABLE*)c_Table)->table; + + if (m_Interface == 0) + { + // Get all interfaces + for (UINT i = 0; i < c_NumOfTables; ++i) + { + // Ignore the loopback + if (table[i].dwType == IF_TYPE_SOFTWARE_LOOPBACK) continue; + + switch (net) + { + case NET_IN: + value += table[i].dwInOctets; + break; + + case NET_OUT: + value += table[i].dwOutOctets; + break; + + case NET_TOTAL: + value += table[i].dwInOctets; + value += table[i].dwOutOctets; + break; + } + } + } + else + { + // Get the selected interface + if (m_Interface <= c_NumOfTables) + { + switch (net) + { + case NET_IN: + value += table[m_Interface - 1].dwInOctets; + break; + + case NET_OUT: + value += table[m_Interface - 1].dwOutOctets; + break; + + case NET_TOTAL: + value += table[m_Interface - 1].dwInOctets; + value += table[m_Interface - 1].dwOutOctets; + break; + } + } + } + } + + return value; +} + +/* +** Returns the stats value of the interface +** +*/ +ULONG64 MeasureNet::GetNetStatsValue(NET net) +{ + ULONG64 value = 0; + size_t statsSize = c_StatValues.size() / 2; + + if (m_Interface == 0) + { + // Get all interfaces + for (size_t i = 0; i < statsSize; ++i) + { + // Ignore the loopback and filter interfaces + if (c_NumOfTables == statsSize) + { + if (c_GetIfTable2) + { + if (((MIB_IF_TABLE2*)c_Table)->Table[i].Type == IF_TYPE_SOFTWARE_LOOPBACK || + ((MIB_IF_TABLE2*)c_Table)->Table[i].InterfaceAndOperStatusFlags.FilterInterface == 1) continue; + } + else + { + if (((MIB_IFTABLE*)c_Table)->table[i].dwType == IF_TYPE_SOFTWARE_LOOPBACK) continue; + } + } + + switch (net) + { + case NET_IN: + value += c_StatValues[i * 2 + 0]; + break; + + case NET_OUT: + value += c_StatValues[i * 2 + 1]; + break; + + case NET_TOTAL: + value += c_StatValues[i * 2 + 0]; + value += c_StatValues[i * 2 + 1]; + break; + } + } + } + else + { + // Get the selected interface + if (m_Interface <= statsSize) + { + switch (net) + { + case NET_IN: + value += c_StatValues[(m_Interface - 1) * 2 + 0]; + break; + + case NET_OUT: + value += c_StatValues[(m_Interface - 1) * 2 + 1]; + break; + + case NET_TOTAL: + value += c_StatValues[(m_Interface - 1) * 2 + 0]; + value += c_StatValues[(m_Interface - 1) * 2 + 1]; + break; + } + } + } + + return value; +} + +/* +** Updates the current value. +** +*/ +void MeasureNet::UpdateValue() +{ + if (c_Table == nullptr) return; + + if (m_Cumulative) + { + m_Value = (double)(__int64)GetNetStatsValue(m_Net); + } + else + { + ULONG64 value = 0; + + if (!m_FirstTime) + { + value = GetNetOctets(m_Net); + if (value > m_Octets) + { + ULONG64 tmpValue = value; + value -= m_Octets; + m_Octets = tmpValue; + } + else + { + m_Octets = value; + value = 0; + } + } + else + { + m_Octets = GetNetOctets(m_Net); + m_FirstTime = false; + } + + m_Value = (double)(__int64)value; + } +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeasureNet::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + Measure::ReadOptions(parser, section); + + double value; + const WCHAR* netName = nullptr; + + if (m_Net == NET_IN) + { + netName = L"NetInSpeed"; + value = Rainmeter::GetInstance().GetGlobalOptions().netInSpeed; + } + else if (m_Net == NET_OUT) + { + netName = L"NetOutSpeed"; + value = Rainmeter::GetInstance().GetGlobalOptions().netOutSpeed; + } + else // if (m_Net == NET_TOTAL) + { + netName = L"NetTotalSpeed"; + value = Rainmeter::GetInstance().GetGlobalOptions().netInSpeed + Rainmeter::GetInstance().GetGlobalOptions().netOutSpeed; + } + + double maxValue = parser.ReadFloat(section, L"MaxValue", -1); + if (maxValue == -1) + { + maxValue = parser.ReadFloat(section, netName, -1); + if (maxValue == -1) + { + maxValue = value; + } + } + + m_Interface = parser.ReadInt(section, L"Interface", 0); + + m_Cumulative = parser.ReadBool(section, L"Cumulative", false); + if (m_Cumulative) + { + Rainmeter::GetInstance().SetNetworkStatisticsTimer(); + } + + if (maxValue == 0.0) + { + if (!m_LogMaxValue) + { + m_MaxValue = 1.0; + m_LogMaxValue = true; + m_MedianValues.clear(); + } + } + else + { + m_MaxValue = maxValue / 8; + m_LogMaxValue = false; + } +} + +/* +** Updates the statistics. +** +*/ +void MeasureNet::UpdateStats() +{ + if (c_Table) + { + size_t statsSize = c_NumOfTables * 2; + + // Fill the vectors + if (c_StatValues.size() < statsSize) + { + c_StatValues.resize(statsSize, 0); + } + + if (c_OldStatValues.size() < statsSize) + { + c_OldStatValues.resize(statsSize, 0); + } + + for (UINT i = 0; i < c_NumOfTables; ++i) + { + ULONG64 in, out; + + if (c_GetIfTable2) + { + in = ((MIB_IF_TABLE2*)c_Table)->Table[i].InOctets; + out = ((MIB_IF_TABLE2*)c_Table)->Table[i].OutOctets; + } + else + { + in = ((MIB_IFTABLE*)c_Table)->table[i].dwInOctets; + out = ((MIB_IFTABLE*)c_Table)->table[i].dwOutOctets; + } + + if (c_OldStatValues[i * 2 + 0] != 0) + { + if (in > c_OldStatValues[i * 2 + 0]) + { + c_StatValues[i * 2 + 0] += in - c_OldStatValues[i * 2 + 0]; + } + } + + if (c_OldStatValues[i * 2 + 1] != 0) + { + if (out > c_OldStatValues[i * 2 + 1]) + { + c_StatValues[i * 2 + 1] += out - c_OldStatValues[i * 2 + 1]; + } + } + + c_OldStatValues[i * 2 + 0] = in; + c_OldStatValues[i * 2 + 1] = out; + } + } +} + +/* +** Resets the statistics. +** +*/ +void MeasureNet::ResetStats() +{ + c_StatValues.clear(); +} + +/* +** Reads statistics. +** +*/ +void MeasureNet::ReadStats(const std::wstring& iniFile, std::wstring& statsDate) +{ + WCHAR buffer[48]; + + ConfigParser parser; + parser.Initialize(iniFile, nullptr, L"Statistics"); + + const std::wstring& date = parser.ReadString(L"Statistics", L"Since", L"", false); + if (!date.empty()) + { + statsDate = date; + } + + uint32_t count = parser.ReadUInt(L"Statistics", L"Count", 0); + if (parser.GetLastDefaultUsed()) + { + count = parser.ReadUInt(L"Statistics", L"NetStatsCount", 0); + } + + c_StatValues.clear(); + c_StatValues.reserve(count * 2); + + for (uint32_t i = 1; i <= count; ++i) + { + ULARGE_INTEGER value; + + _snwprintf_s(buffer, _TRUNCATE, L"In%u", i); + value.QuadPart = parser.ReadUInt64(L"Statistics", buffer, 0); + if (parser.GetLastDefaultUsed()) + { + _snwprintf_s(buffer, _TRUNCATE, L"NetStatsInHigh%u", i); + value.HighPart = parser.ReadUInt(L"Statistics", buffer, 0); + + _snwprintf_s(buffer, _TRUNCATE, L"NetStatsInLow%u", i); + value.LowPart = parser.ReadUInt(L"Statistics", buffer, 0); + } + c_StatValues.push_back(value.QuadPart); + + _snwprintf_s(buffer, _TRUNCATE, L"Out%u", i); + value.QuadPart = parser.ReadUInt64(L"Statistics", buffer, 0); + if (parser.GetLastDefaultUsed()) + { + _snwprintf_s(buffer, _TRUNCATE, L"NetStatsOutHigh%u", i); + value.HighPart = parser.ReadUInt(L"Statistics", buffer, 0); + + _snwprintf_s(buffer, _TRUNCATE, L"NetStatsOutLow%u", i); + value.LowPart = parser.ReadUInt(L"Statistics", buffer, 0); + } + c_StatValues.push_back(value.QuadPart); + } +} + +/* +** Writes statistics. +** +*/ +void MeasureNet::WriteStats(const WCHAR* iniFile, const std::wstring& statsDate) +{ + WCHAR buffer[48]; + int len; + + uint32_t count = (uint32_t)c_StatValues.size() / 2; + + // Reserve sufficient buffer for statistics + std::wstring data; + data.reserve(48 * (2 + count)); + + // Add date + data = L"Since="; + data += statsDate; + data += L'\0'; + + auto appendStatsValue = [&]() + { + data.append(buffer, len); + data += L'\0'; + }; + + // Add stats count + len = _snwprintf_s(buffer, _TRUNCATE, L"Count=%u", count); + appendStatsValue(); + + // Add stats + for (uint32_t i = 0; i < count; ++i) + { + if (c_StatValues[i * 2] > 0) + { + len = _snwprintf_s(buffer, _TRUNCATE, L"In%u=%llu", i + 1, c_StatValues[i * 2]); + appendStatsValue(); + } + + if (c_StatValues[i * 2 + 1] > 0) + { + len = _snwprintf_s(buffer, _TRUNCATE, L"Out%u=%llu", i + 1, c_StatValues[i * 2 + 1]); + appendStatsValue(); + } + } + + // Write statistics + WritePrivateProfileSection(L"Statistics", data.c_str(), iniFile); +} + +/* +** Prepares in order to use the new APIs which are available on Vista or newer. +** +*/ +void MeasureNet::InitializeStatic() +{ + if (IsWindowsVistaOrGreater()) + { + HMODULE IpHlpApiLibrary = GetModuleHandle(L"IpHlpApi.dll"); + if (IpHlpApiLibrary) + { + c_GetIfTable2 = (decltype(c_GetIfTable2))GetProcAddress(IpHlpApiLibrary, "GetIfTable2"); + c_FreeMibTable = (decltype(c_FreeMibTable))GetProcAddress(IpHlpApiLibrary, "FreeMibTable"); + } + + if (!c_GetIfTable2 || !c_FreeMibTable) + { + c_GetIfTable2 = nullptr; + c_FreeMibTable = nullptr; + } + } + + if (Rainmeter::GetInstance().GetDebug()) + { + UpdateIFTable(); + } +} + +/* +** Frees the resources. +** +*/ +void MeasureNet::FinalizeStatic() +{ + if (c_GetIfTable2) + { + if (c_Table) + { + c_FreeMibTable(c_Table); + } + + c_GetIfTable2 = nullptr; + c_FreeMibTable = nullptr; + } + else + { + delete [] c_Table; + } + c_Table = nullptr; + c_NumOfTables = 0; +} diff --git a/Library/MeasureNet.h b/Library/MeasureNet.h index 0c63bf21..3774ab5e 100644 --- a/Library/MeasureNet.h +++ b/Library/MeasureNet.h @@ -1,79 +1,79 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASURENET_H__ -#define __MEASURENET_H__ - -#include -#include -#include -#include "Measure.h" - -class MeasureNet : public Measure -{ -public: - virtual UINT GetTypeID() { return TypeID(); } - - static void UpdateIFTable(); - - static void UpdateStats(); - static void ResetStats(); - static void ReadStats(const std::wstring& iniFile, std::wstring& statsDate); - static void WriteStats(const WCHAR* iniFile, const std::wstring& statsDate); - - static void InitializeStatic(); - static void FinalizeStatic(); - -protected: - enum NET - { - NET_IN, - NET_OUT, - NET_TOTAL - }; - - MeasureNet(MeterWindow* meterWindow, const WCHAR* name, NET type); - virtual ~MeasureNet(); - - MeasureNet(const MeasureNet& other) = delete; - MeasureNet& operator=(MeasureNet other) = delete; - - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void UpdateValue(); - -private: - ULONG64 GetNetOctets(NET net); - ULONG64 GetNetStatsValue(NET net); - - NET m_Net; - UINT m_Interface; - - ULONG64 m_Octets; - bool m_FirstTime; - bool m_Cumulative; - - static std::vector c_OldStatValues; - static std::vector c_StatValues; - static BYTE* c_Table; - static UINT c_NumOfTables; - - static decltype(GetIfTable2)* c_GetIfTable2; - static decltype(FreeMibTable)* c_FreeMibTable; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASURENET_H__ +#define __MEASURENET_H__ + +#include +#include +#include +#include "Measure.h" + +class MeasureNet : public Measure +{ +public: + virtual UINT GetTypeID() { return TypeID(); } + + static void UpdateIFTable(); + + static void UpdateStats(); + static void ResetStats(); + static void ReadStats(const std::wstring& iniFile, std::wstring& statsDate); + static void WriteStats(const WCHAR* iniFile, const std::wstring& statsDate); + + static void InitializeStatic(); + static void FinalizeStatic(); + +protected: + enum NET + { + NET_IN, + NET_OUT, + NET_TOTAL + }; + + MeasureNet(MeterWindow* meterWindow, const WCHAR* name, NET type); + virtual ~MeasureNet(); + + MeasureNet(const MeasureNet& other) = delete; + MeasureNet& operator=(MeasureNet other) = delete; + + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void UpdateValue(); + +private: + ULONG64 GetNetOctets(NET net); + ULONG64 GetNetStatsValue(NET net); + + NET m_Net; + UINT m_Interface; + + ULONG64 m_Octets; + bool m_FirstTime; + bool m_Cumulative; + + static std::vector c_OldStatValues; + static std::vector c_StatValues; + static BYTE* c_Table; + static UINT c_NumOfTables; + + static decltype(GetIfTable2)* c_GetIfTable2; + static decltype(FreeMibTable)* c_FreeMibTable; +}; + +#endif diff --git a/Library/MeasureNetIn.cpp b/Library/MeasureNetIn.cpp index bd849ad0..0f300796 100644 --- a/Library/MeasureNetIn.cpp +++ b/Library/MeasureNetIn.cpp @@ -1,36 +1,36 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeasureNetIn.h" - -/* -** The constructor -** -*/ -MeasureNetIn::MeasureNetIn(MeterWindow* meterWindow, const WCHAR* name) : MeasureNet(meterWindow, name, NET_IN) -{ -} - -/* -** The destructor -** -*/ -MeasureNetIn::~MeasureNetIn() -{ +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeasureNetIn.h" + +/* +** The constructor +** +*/ +MeasureNetIn::MeasureNetIn(MeterWindow* meterWindow, const WCHAR* name) : MeasureNet(meterWindow, name, NET_IN) +{ +} + +/* +** The destructor +** +*/ +MeasureNetIn::~MeasureNetIn() +{ } \ No newline at end of file diff --git a/Library/MeasureNetIn.h b/Library/MeasureNetIn.h index 508c3d73..32ab255c 100644 --- a/Library/MeasureNetIn.h +++ b/Library/MeasureNetIn.h @@ -1,34 +1,34 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASURENETIN_H__ -#define __MEASURENETIN_H__ - -#include "MeasureNet.h" - -class MeasureNetIn : public MeasureNet -{ -public: - MeasureNetIn(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeasureNetIn(); - - MeasureNetIn(const MeasureNetIn& other) = delete; - MeasureNetIn& operator=(MeasureNetIn other) = delete; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASURENETIN_H__ +#define __MEASURENETIN_H__ + +#include "MeasureNet.h" + +class MeasureNetIn : public MeasureNet +{ +public: + MeasureNetIn(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeasureNetIn(); + + MeasureNetIn(const MeasureNetIn& other) = delete; + MeasureNetIn& operator=(MeasureNetIn other) = delete; +}; + +#endif diff --git a/Library/MeasureNetOut.cpp b/Library/MeasureNetOut.cpp index 40c04983..4da1fc79 100644 --- a/Library/MeasureNetOut.cpp +++ b/Library/MeasureNetOut.cpp @@ -1,36 +1,36 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeasureNetOut.h" - -/* -** The constructor -** -*/ -MeasureNetOut::MeasureNetOut(MeterWindow* meterWindow, const WCHAR* name) : MeasureNet(meterWindow, name, NET_OUT) -{ -} - -/* -** The destructor -** -*/ -MeasureNetOut::~MeasureNetOut() -{ -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeasureNetOut.h" + +/* +** The constructor +** +*/ +MeasureNetOut::MeasureNetOut(MeterWindow* meterWindow, const WCHAR* name) : MeasureNet(meterWindow, name, NET_OUT) +{ +} + +/* +** The destructor +** +*/ +MeasureNetOut::~MeasureNetOut() +{ +} diff --git a/Library/MeasureNetOut.h b/Library/MeasureNetOut.h index ebd30323..74ff8ecf 100644 --- a/Library/MeasureNetOut.h +++ b/Library/MeasureNetOut.h @@ -1,34 +1,34 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASURENETOUT_H__ -#define __MEASURENETOUT_H__ - -#include "MeasureNet.h" - -class MeasureNetOut : public MeasureNet -{ -public: - MeasureNetOut(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeasureNetOut(); - - MeasureNetOut(const MeasureNetOut& other) = delete; - MeasureNetOut& operator=(MeasureNetOut other) = delete; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASURENETOUT_H__ +#define __MEASURENETOUT_H__ + +#include "MeasureNet.h" + +class MeasureNetOut : public MeasureNet +{ +public: + MeasureNetOut(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeasureNetOut(); + + MeasureNetOut(const MeasureNetOut& other) = delete; + MeasureNetOut& operator=(MeasureNetOut other) = delete; +}; + +#endif diff --git a/Library/MeasureNetTotal.cpp b/Library/MeasureNetTotal.cpp index de8cebbd..b34afcc1 100644 --- a/Library/MeasureNetTotal.cpp +++ b/Library/MeasureNetTotal.cpp @@ -1,36 +1,36 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeasureNetTotal.h" - -/* -** The constructor -** -*/ -MeasureNetTotal::MeasureNetTotal(MeterWindow* meterWindow, const WCHAR* name) : MeasureNet(meterWindow, name, NET_TOTAL) -{ -} - -/* -** The destructor -** -*/ -MeasureNetTotal::~MeasureNetTotal() -{ -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeasureNetTotal.h" + +/* +** The constructor +** +*/ +MeasureNetTotal::MeasureNetTotal(MeterWindow* meterWindow, const WCHAR* name) : MeasureNet(meterWindow, name, NET_TOTAL) +{ +} + +/* +** The destructor +** +*/ +MeasureNetTotal::~MeasureNetTotal() +{ +} diff --git a/Library/MeasureNetTotal.h b/Library/MeasureNetTotal.h index 812a6a37..61931b1e 100644 --- a/Library/MeasureNetTotal.h +++ b/Library/MeasureNetTotal.h @@ -1,34 +1,34 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASURENETTOTAL_H__ -#define __MEASURENETTOTAL_H__ - -#include "MeasureNet.h" - -class MeasureNetTotal : public MeasureNet -{ -public: - MeasureNetTotal(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeasureNetTotal(); - - MeasureNetTotal(const MeasureNetTotal& other) = delete; - MeasureNetTotal& operator=(MeasureNetTotal other) = delete; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASURENETTOTAL_H__ +#define __MEASURENETTOTAL_H__ + +#include "MeasureNet.h" + +class MeasureNetTotal : public MeasureNet +{ +public: + MeasureNetTotal(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeasureNetTotal(); + + MeasureNetTotal(const MeasureNetTotal& other) = delete; + MeasureNetTotal& operator=(MeasureNetTotal other) = delete; +}; + +#endif diff --git a/Library/MeasurePhysicalMemory.cpp b/Library/MeasurePhysicalMemory.cpp index 42e41725..994ef8f7 100644 --- a/Library/MeasurePhysicalMemory.cpp +++ b/Library/MeasurePhysicalMemory.cpp @@ -1,76 +1,76 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeasurePhysicalMemory.h" -#include "ConfigParser.h" - -/* -** The constructor -** -*/ -MeasurePhysicalMemory::MeasurePhysicalMemory(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), - m_Total(false) -{ - MEMORYSTATUSEX stat; - stat.dwLength = sizeof(MEMORYSTATUSEX); - GlobalMemoryStatusEx(&stat); - m_MaxValue = (double)(__int64)stat.ullTotalPhys; -} - -/* -** The destructor -** -*/ -MeasurePhysicalMemory::~MeasurePhysicalMemory() -{ -} - -/* -** Updates the current physical memory value. -** -*/ -void MeasurePhysicalMemory::UpdateValue() -{ - if (!m_Total) - { - MEMORYSTATUSEX stat; - stat.dwLength = sizeof(MEMORYSTATUSEX); - GlobalMemoryStatusEx(&stat); - - m_Value = (double)(__int64)(stat.ullTotalPhys - stat.ullAvailPhys); - } -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeasurePhysicalMemory::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - double oldMaxValue = m_MaxValue; - Measure::ReadOptions(parser, section); - m_MaxValue = oldMaxValue; - - m_Total = parser.ReadBool(section, L"Total", false); - if (m_Total) - { - m_Value = m_MaxValue; - } -} - +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeasurePhysicalMemory.h" +#include "ConfigParser.h" + +/* +** The constructor +** +*/ +MeasurePhysicalMemory::MeasurePhysicalMemory(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), + m_Total(false) +{ + MEMORYSTATUSEX stat; + stat.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&stat); + m_MaxValue = (double)(__int64)stat.ullTotalPhys; +} + +/* +** The destructor +** +*/ +MeasurePhysicalMemory::~MeasurePhysicalMemory() +{ +} + +/* +** Updates the current physical memory value. +** +*/ +void MeasurePhysicalMemory::UpdateValue() +{ + if (!m_Total) + { + MEMORYSTATUSEX stat; + stat.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&stat); + + m_Value = (double)(__int64)(stat.ullTotalPhys - stat.ullAvailPhys); + } +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeasurePhysicalMemory::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + double oldMaxValue = m_MaxValue; + Measure::ReadOptions(parser, section); + m_MaxValue = oldMaxValue; + + m_Total = parser.ReadBool(section, L"Total", false); + if (m_Total) + { + m_Value = m_MaxValue; + } +} + diff --git a/Library/MeasurePhysicalMemory.h b/Library/MeasurePhysicalMemory.h index fbacd696..7d5a4d02 100644 --- a/Library/MeasurePhysicalMemory.h +++ b/Library/MeasurePhysicalMemory.h @@ -1,43 +1,43 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASUREPHYSICALMEMORY_H__ -#define __MEASUREPHYSICALMEMORY_H__ - -#include "Measure.h" - -class MeasurePhysicalMemory : public Measure -{ -public: - MeasurePhysicalMemory(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeasurePhysicalMemory(); - - MeasurePhysicalMemory(const MeasurePhysicalMemory& other) = delete; - MeasurePhysicalMemory& operator=(MeasurePhysicalMemory other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void UpdateValue(); - -private: - bool m_Total; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASUREPHYSICALMEMORY_H__ +#define __MEASUREPHYSICALMEMORY_H__ + +#include "Measure.h" + +class MeasurePhysicalMemory : public Measure +{ +public: + MeasurePhysicalMemory(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeasurePhysicalMemory(); + + MeasurePhysicalMemory(const MeasurePhysicalMemory& other) = delete; + MeasurePhysicalMemory& operator=(MeasurePhysicalMemory other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void UpdateValue(); + +private: + bool m_Total; +}; + +#endif diff --git a/Library/MeasurePlugin.cpp b/Library/MeasurePlugin.cpp index be072c14..949b04bd 100644 --- a/Library/MeasurePlugin.cpp +++ b/Library/MeasurePlugin.cpp @@ -1,258 +1,258 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeasurePlugin.h" -#include "Rainmeter.h" -#include "Export.h" -#include "System.h" -#include "Error.h" - -/* -** The constructor -** -*/ -MeasurePlugin::MeasurePlugin(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), - m_Plugin(), - m_ReloadFunc(), - m_ID(), - m_Update2(false), - m_PluginData(), - m_UpdateFunc(), - m_GetStringFunc(), - m_ExecuteBangFunc() -{ -} - -/* -** The destructor -** -*/ -MeasurePlugin::~MeasurePlugin() -{ - if (m_Plugin) - { - FARPROC finalizeFunc = GetProcAddress(m_Plugin, "Finalize"); - if (finalizeFunc) - { - if (IsNewApi()) - { - ((NEWFINALIZE)finalizeFunc)(m_PluginData); - } - else - { - ((FINALIZE)finalizeFunc)(m_Plugin, m_ID); - } - } - - FreeLibrary(m_Plugin); - } -} - -/* -** Gets the current value from the plugin -** -*/ -void MeasurePlugin::UpdateValue() -{ - if (m_UpdateFunc) - { - if (IsNewApi()) - { - m_Value = ((NEWUPDATE)m_UpdateFunc)(m_PluginData); - } - else - { - if (m_Update2) - { - m_Value = ((UPDATE2)m_UpdateFunc)(m_ID); - } - else - { - m_Value = ((UPDATE)m_UpdateFunc)(m_ID); - } - } - - // Reset to default - System::ResetWorkingDirectory(); - } -} - -/* -** Reads the options and loads the plugin -** -*/ -void MeasurePlugin::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - static UINT id = 0; - - Measure::ReadOptions(parser, section); - - if (m_Initialized) - { - if (IsNewApi()) - { - ((NEWRELOAD)m_ReloadFunc)(m_PluginData, this, &m_MaxValue); - } - - // DynamicVariables doesn't work with old plugins - return; - } - - const std::wstring& plugin = parser.ReadString(section, L"Plugin", L""); - size_t pos = plugin.find_last_of(L"\\/"); - std::wstring pluginName; - if (pos != std::wstring::npos) - { - pluginName.assign(plugin, pos, plugin.length() - pos); - } - else - { - pluginName = plugin; - } - - // First try from program path - std::wstring pluginFile = Rainmeter::GetInstance().GetPluginPath(); - pluginFile += pluginName; - m_Plugin = System::RmLoadLibrary(pluginFile.c_str()); - if (!m_Plugin) - { - if (Rainmeter::GetInstance().HasUserPluginPath()) - { - // Try from settings path - pluginFile = Rainmeter::GetInstance().GetUserPluginPath(); - pluginFile += pluginName; - m_Plugin = System::RmLoadLibrary(pluginFile.c_str()); - } - if (!m_Plugin) - { - LogErrorF( - this, L"Plugin: Unable to load \"%s\" (error %ld)", - pluginName.c_str(), GetLastError()); - return; - } - } - - FARPROC initializeFunc = GetProcAddress(m_Plugin, "Initialize"); - m_ReloadFunc = GetProcAddress(m_Plugin, "Reload"); - m_UpdateFunc = GetProcAddress(m_Plugin, "Update"); - m_GetStringFunc = GetProcAddress(m_Plugin, "GetString"); - m_ExecuteBangFunc = GetProcAddress(m_Plugin, "ExecuteBang"); - - // Remove current directory from DLL search path - SetDllDirectory(L""); - - double maxValue = 0.0; - - if (IsNewApi()) - { - m_PluginData = (void*)id; - - if (initializeFunc) - { - ((NEWINITIALIZE)initializeFunc)(&m_PluginData, this); - } - - ((NEWRELOAD)m_ReloadFunc)(m_PluginData, this, &maxValue); - } - else - { - m_ID = id; - - if (!m_UpdateFunc) - { - m_UpdateFunc = GetProcAddress(m_Plugin, "Update2"); - m_Update2 = true; - } - - if (initializeFunc) - { - maxValue = ((INITIALIZE)initializeFunc)(m_Plugin, m_MeterWindow->GetFilePath().c_str(), section, m_ID); - } - } - - const std::wstring& szMaxValue = parser.ReadString(section, L"MaxValue", L""); - if (szMaxValue.empty()) - { - if (maxValue == 0.0) - { - m_MaxValue = 1.0; - m_LogMaxValue = true; - m_MedianValues.clear(); - } - else - { - m_MaxValue = maxValue; - m_LogMaxValue = false; - } - } - - // Reset to default - SetDllDirectory(L""); - System::ResetWorkingDirectory(); - - ++id; -} - -/* -** Gets the string value from the plugin. -** -*/ -const WCHAR* MeasurePlugin::GetStringValue() -{ - if (m_GetStringFunc) - { - const WCHAR* ret; - if (IsNewApi()) - { - ret = ((NEWGETSTRING)m_GetStringFunc)(m_PluginData); - } - else - { - ret = ((GETSTRING)m_GetStringFunc)(m_ID, 0); - } - - if (ret) return CheckSubstitute(ret); - } - - return nullptr; -} - -/* -** Sends a bang to the plugin -** -*/ -void MeasurePlugin::Command(const std::wstring& command) -{ - if (m_ExecuteBangFunc) - { - const WCHAR* str = command.c_str(); - if (IsNewApi()) - { - ((NEWEXECUTEBANG)m_ExecuteBangFunc)(m_PluginData, str); - } - else - { - ((EXECUTEBANG)m_ExecuteBangFunc)(str, m_ID); - } - } - else - { - Measure::Command(command); - } -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeasurePlugin.h" +#include "Rainmeter.h" +#include "Export.h" +#include "System.h" +#include "Error.h" + +/* +** The constructor +** +*/ +MeasurePlugin::MeasurePlugin(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), + m_Plugin(), + m_ReloadFunc(), + m_ID(), + m_Update2(false), + m_PluginData(), + m_UpdateFunc(), + m_GetStringFunc(), + m_ExecuteBangFunc() +{ +} + +/* +** The destructor +** +*/ +MeasurePlugin::~MeasurePlugin() +{ + if (m_Plugin) + { + FARPROC finalizeFunc = GetProcAddress(m_Plugin, "Finalize"); + if (finalizeFunc) + { + if (IsNewApi()) + { + ((NEWFINALIZE)finalizeFunc)(m_PluginData); + } + else + { + ((FINALIZE)finalizeFunc)(m_Plugin, m_ID); + } + } + + FreeLibrary(m_Plugin); + } +} + +/* +** Gets the current value from the plugin +** +*/ +void MeasurePlugin::UpdateValue() +{ + if (m_UpdateFunc) + { + if (IsNewApi()) + { + m_Value = ((NEWUPDATE)m_UpdateFunc)(m_PluginData); + } + else + { + if (m_Update2) + { + m_Value = ((UPDATE2)m_UpdateFunc)(m_ID); + } + else + { + m_Value = ((UPDATE)m_UpdateFunc)(m_ID); + } + } + + // Reset to default + System::ResetWorkingDirectory(); + } +} + +/* +** Reads the options and loads the plugin +** +*/ +void MeasurePlugin::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + static UINT id = 0; + + Measure::ReadOptions(parser, section); + + if (m_Initialized) + { + if (IsNewApi()) + { + ((NEWRELOAD)m_ReloadFunc)(m_PluginData, this, &m_MaxValue); + } + + // DynamicVariables doesn't work with old plugins + return; + } + + const std::wstring& plugin = parser.ReadString(section, L"Plugin", L""); + size_t pos = plugin.find_last_of(L"\\/"); + std::wstring pluginName; + if (pos != std::wstring::npos) + { + pluginName.assign(plugin, pos, plugin.length() - pos); + } + else + { + pluginName = plugin; + } + + // First try from program path + std::wstring pluginFile = Rainmeter::GetInstance().GetPluginPath(); + pluginFile += pluginName; + m_Plugin = System::RmLoadLibrary(pluginFile.c_str()); + if (!m_Plugin) + { + if (Rainmeter::GetInstance().HasUserPluginPath()) + { + // Try from settings path + pluginFile = Rainmeter::GetInstance().GetUserPluginPath(); + pluginFile += pluginName; + m_Plugin = System::RmLoadLibrary(pluginFile.c_str()); + } + if (!m_Plugin) + { + LogErrorF( + this, L"Plugin: Unable to load \"%s\" (error %ld)", + pluginName.c_str(), GetLastError()); + return; + } + } + + FARPROC initializeFunc = GetProcAddress(m_Plugin, "Initialize"); + m_ReloadFunc = GetProcAddress(m_Plugin, "Reload"); + m_UpdateFunc = GetProcAddress(m_Plugin, "Update"); + m_GetStringFunc = GetProcAddress(m_Plugin, "GetString"); + m_ExecuteBangFunc = GetProcAddress(m_Plugin, "ExecuteBang"); + + // Remove current directory from DLL search path + SetDllDirectory(L""); + + double maxValue = 0.0; + + if (IsNewApi()) + { + m_PluginData = (void*)id; + + if (initializeFunc) + { + ((NEWINITIALIZE)initializeFunc)(&m_PluginData, this); + } + + ((NEWRELOAD)m_ReloadFunc)(m_PluginData, this, &maxValue); + } + else + { + m_ID = id; + + if (!m_UpdateFunc) + { + m_UpdateFunc = GetProcAddress(m_Plugin, "Update2"); + m_Update2 = true; + } + + if (initializeFunc) + { + maxValue = ((INITIALIZE)initializeFunc)(m_Plugin, m_MeterWindow->GetFilePath().c_str(), section, m_ID); + } + } + + const std::wstring& szMaxValue = parser.ReadString(section, L"MaxValue", L""); + if (szMaxValue.empty()) + { + if (maxValue == 0.0) + { + m_MaxValue = 1.0; + m_LogMaxValue = true; + m_MedianValues.clear(); + } + else + { + m_MaxValue = maxValue; + m_LogMaxValue = false; + } + } + + // Reset to default + SetDllDirectory(L""); + System::ResetWorkingDirectory(); + + ++id; +} + +/* +** Gets the string value from the plugin. +** +*/ +const WCHAR* MeasurePlugin::GetStringValue() +{ + if (m_GetStringFunc) + { + const WCHAR* ret; + if (IsNewApi()) + { + ret = ((NEWGETSTRING)m_GetStringFunc)(m_PluginData); + } + else + { + ret = ((GETSTRING)m_GetStringFunc)(m_ID, 0); + } + + if (ret) return CheckSubstitute(ret); + } + + return nullptr; +} + +/* +** Sends a bang to the plugin +** +*/ +void MeasurePlugin::Command(const std::wstring& command) +{ + if (m_ExecuteBangFunc) + { + const WCHAR* str = command.c_str(); + if (IsNewApi()) + { + ((NEWEXECUTEBANG)m_ExecuteBangFunc)(m_PluginData, str); + } + else + { + ((EXECUTEBANG)m_ExecuteBangFunc)(str, m_ID); + } + } + else + { + Measure::Command(command); + } +} diff --git a/Library/MeasurePlugin.h b/Library/MeasurePlugin.h index 075cec9c..386d4f5b 100644 --- a/Library/MeasurePlugin.h +++ b/Library/MeasurePlugin.h @@ -1,83 +1,83 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASUREPLUGIN_H__ -#define __MEASUREPLUGIN_H__ - -#include "Measure.h" -#include "Export.h" - -typedef UINT (*INITIALIZE)(HMODULE, LPCTSTR, LPCTSTR, UINT); -typedef VOID (*FINALIZE)(HMODULE, UINT); -typedef UINT (*UPDATE)(UINT); -typedef double (*UPDATE2)(UINT); -typedef LPCTSTR (*GETSTRING)(UINT, UINT); -typedef void (*EXECUTEBANG)(LPCWSTR, UINT); - -typedef void (*NEWINITIALIZE)(void*, void*); -typedef void (*NEWRELOAD)(void*, void*, double*); -typedef void (*NEWFINALIZE)(void*); -typedef double (*NEWUPDATE)(void*); -typedef LPCWSTR (*NEWGETSTRING)(void*); -typedef void (*NEWEXECUTEBANG)(void*, LPCWSTR); - -class MeasurePlugin : public Measure -{ -public: - MeasurePlugin(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeasurePlugin(); - - MeasurePlugin(const MeasurePlugin& other) = delete; - MeasurePlugin& operator=(MeasurePlugin other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - virtual const WCHAR* GetStringValue(); - virtual void Command(const std::wstring& command); - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void UpdateValue(); - -private: - bool IsNewApi() { return m_ReloadFunc != nullptr; } - - HMODULE m_Plugin; - - void* m_ReloadFunc; - - union - { - struct - { - UINT m_ID; - bool m_Update2; - }; - - struct - { - void* m_PluginData; - }; - }; - - void* m_UpdateFunc; - void* m_GetStringFunc; - void* m_ExecuteBangFunc; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASUREPLUGIN_H__ +#define __MEASUREPLUGIN_H__ + +#include "Measure.h" +#include "Export.h" + +typedef UINT (*INITIALIZE)(HMODULE, LPCTSTR, LPCTSTR, UINT); +typedef VOID (*FINALIZE)(HMODULE, UINT); +typedef UINT (*UPDATE)(UINT); +typedef double (*UPDATE2)(UINT); +typedef LPCTSTR (*GETSTRING)(UINT, UINT); +typedef void (*EXECUTEBANG)(LPCWSTR, UINT); + +typedef void (*NEWINITIALIZE)(void*, void*); +typedef void (*NEWRELOAD)(void*, void*, double*); +typedef void (*NEWFINALIZE)(void*); +typedef double (*NEWUPDATE)(void*); +typedef LPCWSTR (*NEWGETSTRING)(void*); +typedef void (*NEWEXECUTEBANG)(void*, LPCWSTR); + +class MeasurePlugin : public Measure +{ +public: + MeasurePlugin(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeasurePlugin(); + + MeasurePlugin(const MeasurePlugin& other) = delete; + MeasurePlugin& operator=(MeasurePlugin other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + virtual const WCHAR* GetStringValue(); + virtual void Command(const std::wstring& command); + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void UpdateValue(); + +private: + bool IsNewApi() { return m_ReloadFunc != nullptr; } + + HMODULE m_Plugin; + + void* m_ReloadFunc; + + union + { + struct + { + UINT m_ID; + bool m_Update2; + }; + + struct + { + void* m_PluginData; + }; + }; + + void* m_UpdateFunc; + void* m_GetStringFunc; + void* m_ExecuteBangFunc; +}; + +#endif diff --git a/Library/MeasureRegistry.cpp b/Library/MeasureRegistry.cpp index c8cc015c..7ab3b767 100644 --- a/Library/MeasureRegistry.cpp +++ b/Library/MeasureRegistry.cpp @@ -1,164 +1,164 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeasureRegistry.h" -#include "Rainmeter.h" -#include "Error.h" - -/* -** The constructor -** -*/ -MeasureRegistry::MeasureRegistry(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), - m_RegKey(), - m_HKey(HKEY_CURRENT_USER) -{ - m_MaxValue = 0.0; -} - -/* -** The destructor -** -*/ -MeasureRegistry::~MeasureRegistry() -{ - if (m_RegKey) RegCloseKey(m_RegKey); -} - -/* -** Gets the current value from the registry -** -*/ -void MeasureRegistry::UpdateValue() -{ - if (m_RegKey != nullptr) - { - DWORD size = 4096; - WCHAR* data = new WCHAR[size]; - DWORD type = 0; - - if (RegQueryValueEx( - m_RegKey, - m_RegValueName.c_str(), - nullptr, - (LPDWORD)&type, - (LPBYTE)data, - (LPDWORD)&size) == ERROR_SUCCESS) - { - switch (type) - { - case REG_DWORD: - m_Value = *((LPDWORD)data); - m_StringValue.clear(); - break; - - case REG_SZ: - case REG_EXPAND_SZ: - case REG_MULTI_SZ: - m_Value = wcstod(data, nullptr); - m_StringValue = data; - break; - - case REG_QWORD: - m_Value = (double)((LARGE_INTEGER*)data)->QuadPart; - m_StringValue.clear(); - break; - - default: // Other types are not supported - m_Value = 0.0; - m_StringValue.clear(); - } - } - else - { - m_Value = 0.0; - m_StringValue.clear(); - RegOpenKeyEx(m_HKey, m_RegKeyName.c_str(), 0, KEY_READ, &m_RegKey); - } - - delete [] data; - } - else - { - RegOpenKeyEx(m_HKey, m_RegKeyName.c_str(), 0, KEY_READ, &m_RegKey); - } -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeasureRegistry::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - Measure::ReadOptions(parser, section); - - const WCHAR* keyname = parser.ReadString(section, L"RegHKey", L"HKEY_CURRENT_USER").c_str(); - if (_wcsicmp(keyname, L"HKEY_CURRENT_USER") == 0) - { - m_HKey = HKEY_CURRENT_USER; - } - else if (_wcsicmp(keyname, L"HKEY_LOCAL_MACHINE") == 0) - { - m_HKey = HKEY_LOCAL_MACHINE; - } - else if (_wcsicmp(keyname, L"HKEY_CLASSES_ROOT") == 0) - { - m_HKey = HKEY_CLASSES_ROOT; - } - else if (_wcsicmp(keyname, L"HKEY_CURRENT_CONFIG") == 0) - { - m_HKey = HKEY_CURRENT_CONFIG; - } - else if (_wcsicmp(keyname, L"HKEY_PERFORMANCE_DATA") == 0) - { - m_HKey = HKEY_PERFORMANCE_DATA; - } - else if (_wcsicmp(keyname, L"HKEY_DYN_DATA") == 0) - { - m_HKey = HKEY_DYN_DATA; - } - else - { - LogErrorF(this, L"RegHKey=%s is not valid", keyname); - } - - m_RegKeyName = parser.ReadString(section, L"RegKey", L""); - m_RegValueName = parser.ReadString(section, L"RegValue", L""); - - if (m_MaxValue == 0.0) - { - m_MaxValue = 1.0; - m_LogMaxValue = true; - } - - // Try to open the key - if (m_RegKey) RegCloseKey(m_RegKey); - RegOpenKeyEx(m_HKey, m_RegKeyName.c_str(), 0, KEY_READ, &m_RegKey); -} - -/* -** If the measured registry value is a string display it. Otherwise convert the -** value to string as normal. -** -*/ -const WCHAR* MeasureRegistry::GetStringValue() -{ - return !m_StringValue.empty() ? CheckSubstitute(m_StringValue.c_str()) : nullptr; -} - +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeasureRegistry.h" +#include "Rainmeter.h" +#include "Error.h" + +/* +** The constructor +** +*/ +MeasureRegistry::MeasureRegistry(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), + m_RegKey(), + m_HKey(HKEY_CURRENT_USER) +{ + m_MaxValue = 0.0; +} + +/* +** The destructor +** +*/ +MeasureRegistry::~MeasureRegistry() +{ + if (m_RegKey) RegCloseKey(m_RegKey); +} + +/* +** Gets the current value from the registry +** +*/ +void MeasureRegistry::UpdateValue() +{ + if (m_RegKey != nullptr) + { + DWORD size = 4096; + WCHAR* data = new WCHAR[size]; + DWORD type = 0; + + if (RegQueryValueEx( + m_RegKey, + m_RegValueName.c_str(), + nullptr, + (LPDWORD)&type, + (LPBYTE)data, + (LPDWORD)&size) == ERROR_SUCCESS) + { + switch (type) + { + case REG_DWORD: + m_Value = *((LPDWORD)data); + m_StringValue.clear(); + break; + + case REG_SZ: + case REG_EXPAND_SZ: + case REG_MULTI_SZ: + m_Value = wcstod(data, nullptr); + m_StringValue = data; + break; + + case REG_QWORD: + m_Value = (double)((LARGE_INTEGER*)data)->QuadPart; + m_StringValue.clear(); + break; + + default: // Other types are not supported + m_Value = 0.0; + m_StringValue.clear(); + } + } + else + { + m_Value = 0.0; + m_StringValue.clear(); + RegOpenKeyEx(m_HKey, m_RegKeyName.c_str(), 0, KEY_READ, &m_RegKey); + } + + delete [] data; + } + else + { + RegOpenKeyEx(m_HKey, m_RegKeyName.c_str(), 0, KEY_READ, &m_RegKey); + } +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeasureRegistry::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + Measure::ReadOptions(parser, section); + + const WCHAR* keyname = parser.ReadString(section, L"RegHKey", L"HKEY_CURRENT_USER").c_str(); + if (_wcsicmp(keyname, L"HKEY_CURRENT_USER") == 0) + { + m_HKey = HKEY_CURRENT_USER; + } + else if (_wcsicmp(keyname, L"HKEY_LOCAL_MACHINE") == 0) + { + m_HKey = HKEY_LOCAL_MACHINE; + } + else if (_wcsicmp(keyname, L"HKEY_CLASSES_ROOT") == 0) + { + m_HKey = HKEY_CLASSES_ROOT; + } + else if (_wcsicmp(keyname, L"HKEY_CURRENT_CONFIG") == 0) + { + m_HKey = HKEY_CURRENT_CONFIG; + } + else if (_wcsicmp(keyname, L"HKEY_PERFORMANCE_DATA") == 0) + { + m_HKey = HKEY_PERFORMANCE_DATA; + } + else if (_wcsicmp(keyname, L"HKEY_DYN_DATA") == 0) + { + m_HKey = HKEY_DYN_DATA; + } + else + { + LogErrorF(this, L"RegHKey=%s is not valid", keyname); + } + + m_RegKeyName = parser.ReadString(section, L"RegKey", L""); + m_RegValueName = parser.ReadString(section, L"RegValue", L""); + + if (m_MaxValue == 0.0) + { + m_MaxValue = 1.0; + m_LogMaxValue = true; + } + + // Try to open the key + if (m_RegKey) RegCloseKey(m_RegKey); + RegOpenKeyEx(m_HKey, m_RegKeyName.c_str(), 0, KEY_READ, &m_RegKey); +} + +/* +** If the measured registry value is a string display it. Otherwise convert the +** value to string as normal. +** +*/ +const WCHAR* MeasureRegistry::GetStringValue() +{ + return !m_StringValue.empty() ? CheckSubstitute(m_StringValue.c_str()) : nullptr; +} + diff --git a/Library/MeasureRegistry.h b/Library/MeasureRegistry.h index 73c0116d..f31329b9 100644 --- a/Library/MeasureRegistry.h +++ b/Library/MeasureRegistry.h @@ -1,49 +1,49 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASUREREGISTRY_H__ -#define __MEASUREREGISTRY_H__ - -#include "Measure.h" - -class MeasureRegistry : public Measure -{ -public: - MeasureRegistry(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeasureRegistry(); - - MeasureRegistry(const MeasureRegistry& other) = delete; - MeasureRegistry& operator=(MeasureRegistry other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - virtual const WCHAR* GetStringValue(); - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void UpdateValue(); - -private: - std::wstring m_RegKeyName; - std::wstring m_RegValueName; - std::wstring m_StringValue; - HKEY m_RegKey; - HKEY m_HKey; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASUREREGISTRY_H__ +#define __MEASUREREGISTRY_H__ + +#include "Measure.h" + +class MeasureRegistry : public Measure +{ +public: + MeasureRegistry(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeasureRegistry(); + + MeasureRegistry(const MeasureRegistry& other) = delete; + MeasureRegistry& operator=(MeasureRegistry other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + virtual const WCHAR* GetStringValue(); + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void UpdateValue(); + +private: + std::wstring m_RegKeyName; + std::wstring m_RegValueName; + std::wstring m_StringValue; + HKEY m_RegKey; + HKEY m_HKey; +}; + +#endif diff --git a/Library/MeasureScript.cpp b/Library/MeasureScript.cpp index 78fa9454..8182e674 100644 --- a/Library/MeasureScript.cpp +++ b/Library/MeasureScript.cpp @@ -1,229 +1,229 @@ -/* - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeasureScript.h" -#include "lua/LuaManager.h" -#include "Litestep.h" -#include "Rainmeter.h" - -const char* g_InitializeFunctionName = "Initialize"; -const char* g_UpdateFunctionName = "Update"; -const char* g_GetStringFunctionName = "GetStringValue"; - -/* -** The constructor -** -*/ -MeasureScript::MeasureScript(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), - m_HasUpdateFunction(false), - m_HasGetStringFunction(false), - m_ValueType(LUA_TNIL) -{ - LuaManager::Initialize(); -} - -/* -** The destructor -** -*/ -MeasureScript::~MeasureScript() -{ - UninitializeLuaScript(); - LuaManager::Finalize(); -} - -void MeasureScript::UninitializeLuaScript() -{ - m_LuaScript.Uninitialize(); - - m_HasUpdateFunction = false; - m_HasGetStringFunction = false; -} - -void MeasureScript::Initialize() -{ - Measure::Initialize(); - - if (m_LuaScript.IsFunction(g_InitializeFunctionName)) - { - m_LuaScript.RunFunction(g_InitializeFunctionName); - } -} - -/* -** Runs the function "Update()" in the script. -** -*/ -void MeasureScript::UpdateValue() -{ - if (m_HasUpdateFunction) - { - m_ValueType = m_LuaScript.RunFunctionWithReturn(g_UpdateFunctionName, m_Value, m_StringValue); - - if (m_ValueType == LUA_TNIL && m_HasGetStringFunction) - { - // For backwards compatbility - m_ValueType = m_LuaScript.RunFunctionWithReturn(g_GetStringFunctionName, m_Value, m_StringValue); - } - } -} - -/* -** Returns the value as a string. -** -*/ -const WCHAR* MeasureScript::GetStringValue() -{ - return (m_ValueType == LUA_TSTRING) ? CheckSubstitute(m_StringValue.c_str()) : nullptr; -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeasureScript::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - Measure::ReadOptions(parser, section); - - std::wstring scriptFile = parser.ReadString(section, L"ScriptFile", L""); - if (!scriptFile.empty()) - { - if (m_MeterWindow) - { - m_MeterWindow->MakePathAbsolute(scriptFile); - } - - if (!m_Initialized || - wcscmp(scriptFile.c_str(), m_LuaScript.GetFile().c_str()) != 0) - { - UninitializeLuaScript(); - - if (m_LuaScript.Initialize(scriptFile)) - { - bool hasInitializeFunction = m_LuaScript.IsFunction(g_InitializeFunctionName); - m_HasUpdateFunction = m_LuaScript.IsFunction(g_UpdateFunctionName); - - auto L = m_LuaScript.GetState(); - lua_rawgeti(L, LUA_GLOBALSINDEX, m_LuaScript.GetRef()); - - *(MeterWindow**)lua_newuserdata(L, sizeof(MeterWindow*)) = m_MeterWindow; - lua_getglobal(L, "MeterWindow"); - lua_setmetatable(L, -2); - lua_setfield(L, -2, "SKIN"); - - *(Measure**)lua_newuserdata(L, sizeof(Measure*)) = this; - lua_getglobal(L, "Measure"); - lua_setmetatable(L, -2); - lua_setfield(L, -2, "SELF"); - - if (!m_LuaScript.IsUnicode()) - { - // For backwards compatibility. - - m_HasGetStringFunction = m_LuaScript.IsFunction(g_GetStringFunctionName); - if (m_HasGetStringFunction) - { - LogWarningF(this, L"Script: Using deprecated GetStringValue()"); - } - - lua_getfield(L, -1, "PROPERTIES"); - if (lua_isnil(L, -1) == 0) - { - lua_pushnil(L); - - // Look in the table for values to read from the section - while (lua_next(L, -2)) - { - lua_pop(L, 1); - const char* strKey = lua_tostring(L, -1); - const std::wstring wstrKey = StringUtil::Widen(strKey); - const std::wstring& wstrValue = - parser.ReadString(section, wstrKey.c_str(), L""); - if (!wstrValue.empty()) - { - const std::string strStrVal = StringUtil::Narrow(wstrValue); - lua_pushstring(L, strStrVal.c_str()); - lua_setfield(L, -3, strKey); - } - } - } - - // Pop PROPERTIES table. - lua_pop(L, 1); - } - - // Pop our table. - lua_pop(L, 1); - - if (m_Initialized) - { - // If the measure is already initialized and the script has changed, we need to - // manually call Initialize(). - Initialize(); - } - - // Valid script. - return; - } - } - else if (m_LuaScript.IsInitialized()) - { - // Already initialized. - return; - } - } - - LogErrorF(this, L"Script: File not valid"); - UninitializeLuaScript(); -} - -/* -** Executes a custom bang. -** -*/ -void MeasureScript::Command(const std::wstring& command) -{ - m_LuaScript.RunString(command); -} - -//static void stackDump(lua_State *L) -//{ -// LuaManager::LuaLogger::Debug(" ---------------- Stack Dump ----------------" ); -// for (int i = lua_gettop(L); i > 0; --i) -// { -// int t = lua_type(L, i); -// switch (t) -// { -// case LUA_TSTRING: -// LuaManager::LuaLogger::Debug("%d:'%s'", i, lua_tostring(L, i)); -// break; -// -// case LUA_TBOOLEAN: -// LuaManager::LuaLogger::Debug("%d: %s", i, lua_toboolean(L, i) ? "true" : "false"); -// break; -// -// case LUA_TNUMBER: -// LuaManager::LuaLogger::Debug("%d: %g", i, lua_tonumber(L, i)); -// break; -// -// default: -// LuaManager::LuaLogger::Debug("%d: %s", i, lua_typename(L, t)); -// break; -// } -// } -// LuaManager::LuaLogger::Debug("--------------- Stack Dump Finished ---------------" ); -//} +/* + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeasureScript.h" +#include "lua/LuaManager.h" +#include "Litestep.h" +#include "Rainmeter.h" + +const char* g_InitializeFunctionName = "Initialize"; +const char* g_UpdateFunctionName = "Update"; +const char* g_GetStringFunctionName = "GetStringValue"; + +/* +** The constructor +** +*/ +MeasureScript::MeasureScript(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), + m_HasUpdateFunction(false), + m_HasGetStringFunction(false), + m_ValueType(LUA_TNIL) +{ + LuaManager::Initialize(); +} + +/* +** The destructor +** +*/ +MeasureScript::~MeasureScript() +{ + UninitializeLuaScript(); + LuaManager::Finalize(); +} + +void MeasureScript::UninitializeLuaScript() +{ + m_LuaScript.Uninitialize(); + + m_HasUpdateFunction = false; + m_HasGetStringFunction = false; +} + +void MeasureScript::Initialize() +{ + Measure::Initialize(); + + if (m_LuaScript.IsFunction(g_InitializeFunctionName)) + { + m_LuaScript.RunFunction(g_InitializeFunctionName); + } +} + +/* +** Runs the function "Update()" in the script. +** +*/ +void MeasureScript::UpdateValue() +{ + if (m_HasUpdateFunction) + { + m_ValueType = m_LuaScript.RunFunctionWithReturn(g_UpdateFunctionName, m_Value, m_StringValue); + + if (m_ValueType == LUA_TNIL && m_HasGetStringFunction) + { + // For backwards compatbility + m_ValueType = m_LuaScript.RunFunctionWithReturn(g_GetStringFunctionName, m_Value, m_StringValue); + } + } +} + +/* +** Returns the value as a string. +** +*/ +const WCHAR* MeasureScript::GetStringValue() +{ + return (m_ValueType == LUA_TSTRING) ? CheckSubstitute(m_StringValue.c_str()) : nullptr; +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeasureScript::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + Measure::ReadOptions(parser, section); + + std::wstring scriptFile = parser.ReadString(section, L"ScriptFile", L""); + if (!scriptFile.empty()) + { + if (m_MeterWindow) + { + m_MeterWindow->MakePathAbsolute(scriptFile); + } + + if (!m_Initialized || + wcscmp(scriptFile.c_str(), m_LuaScript.GetFile().c_str()) != 0) + { + UninitializeLuaScript(); + + if (m_LuaScript.Initialize(scriptFile)) + { + bool hasInitializeFunction = m_LuaScript.IsFunction(g_InitializeFunctionName); + m_HasUpdateFunction = m_LuaScript.IsFunction(g_UpdateFunctionName); + + auto L = m_LuaScript.GetState(); + lua_rawgeti(L, LUA_GLOBALSINDEX, m_LuaScript.GetRef()); + + *(MeterWindow**)lua_newuserdata(L, sizeof(MeterWindow*)) = m_MeterWindow; + lua_getglobal(L, "MeterWindow"); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "SKIN"); + + *(Measure**)lua_newuserdata(L, sizeof(Measure*)) = this; + lua_getglobal(L, "Measure"); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "SELF"); + + if (!m_LuaScript.IsUnicode()) + { + // For backwards compatibility. + + m_HasGetStringFunction = m_LuaScript.IsFunction(g_GetStringFunctionName); + if (m_HasGetStringFunction) + { + LogWarningF(this, L"Script: Using deprecated GetStringValue()"); + } + + lua_getfield(L, -1, "PROPERTIES"); + if (lua_isnil(L, -1) == 0) + { + lua_pushnil(L); + + // Look in the table for values to read from the section + while (lua_next(L, -2)) + { + lua_pop(L, 1); + const char* strKey = lua_tostring(L, -1); + const std::wstring wstrKey = StringUtil::Widen(strKey); + const std::wstring& wstrValue = + parser.ReadString(section, wstrKey.c_str(), L""); + if (!wstrValue.empty()) + { + const std::string strStrVal = StringUtil::Narrow(wstrValue); + lua_pushstring(L, strStrVal.c_str()); + lua_setfield(L, -3, strKey); + } + } + } + + // Pop PROPERTIES table. + lua_pop(L, 1); + } + + // Pop our table. + lua_pop(L, 1); + + if (m_Initialized) + { + // If the measure is already initialized and the script has changed, we need to + // manually call Initialize(). + Initialize(); + } + + // Valid script. + return; + } + } + else if (m_LuaScript.IsInitialized()) + { + // Already initialized. + return; + } + } + + LogErrorF(this, L"Script: File not valid"); + UninitializeLuaScript(); +} + +/* +** Executes a custom bang. +** +*/ +void MeasureScript::Command(const std::wstring& command) +{ + m_LuaScript.RunString(command); +} + +//static void stackDump(lua_State *L) +//{ +// LuaManager::LuaLogger::Debug(" ---------------- Stack Dump ----------------" ); +// for (int i = lua_gettop(L); i > 0; --i) +// { +// int t = lua_type(L, i); +// switch (t) +// { +// case LUA_TSTRING: +// LuaManager::LuaLogger::Debug("%d:'%s'", i, lua_tostring(L, i)); +// break; +// +// case LUA_TBOOLEAN: +// LuaManager::LuaLogger::Debug("%d: %s", i, lua_toboolean(L, i) ? "true" : "false"); +// break; +// +// case LUA_TNUMBER: +// LuaManager::LuaLogger::Debug("%d: %g", i, lua_tonumber(L, i)); +// break; +// +// default: +// LuaManager::LuaLogger::Debug("%d: %s", i, lua_typename(L, t)); +// break; +// } +// } +// LuaManager::LuaLogger::Debug("--------------- Stack Dump Finished ---------------" ); +//} diff --git a/Library/MeasureScript.h b/Library/MeasureScript.h index 26396270..525c834f 100644 --- a/Library/MeasureScript.h +++ b/Library/MeasureScript.h @@ -1,56 +1,56 @@ -/* - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASURESCRIPT_H__ -#define __MEASURESCRIPT_H__ - -#include "Measure.h" -#include "lua/LuaScript.h" -#include "MeterWindow.h" - -class MeasureScript : public Measure -{ -public: - MeasureScript(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeasureScript(); - - MeasureScript(const MeasureScript& other) = delete; - MeasureScript& operator=(MeasureScript other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - virtual const WCHAR* GetStringValue(); - virtual void Command(const std::wstring& command); - - void UninitializeLuaScript(); - -protected: - virtual void Initialize(); - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void UpdateValue(); - -private: - LuaScript m_LuaScript; - - bool m_HasUpdateFunction; - bool m_HasGetStringFunction; - - int m_ValueType; - - std::wstring m_StringValue; -}; - +/* + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASURESCRIPT_H__ +#define __MEASURESCRIPT_H__ + +#include "Measure.h" +#include "lua/LuaScript.h" +#include "MeterWindow.h" + +class MeasureScript : public Measure +{ +public: + MeasureScript(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeasureScript(); + + MeasureScript(const MeasureScript& other) = delete; + MeasureScript& operator=(MeasureScript other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + virtual const WCHAR* GetStringValue(); + virtual void Command(const std::wstring& command); + + void UninitializeLuaScript(); + +protected: + virtual void Initialize(); + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void UpdateValue(); + +private: + LuaScript m_LuaScript; + + bool m_HasUpdateFunction; + bool m_HasGetStringFunction; + + int m_ValueType; + + std::wstring m_StringValue; +}; + #endif \ No newline at end of file diff --git a/Library/MeasureString.cpp b/Library/MeasureString.cpp index 861af544..5fc0a2e6 100644 --- a/Library/MeasureString.cpp +++ b/Library/MeasureString.cpp @@ -1,67 +1,67 @@ -/* -Copyright (C) 2014 Brian Ferguson - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeasureString.h" -#include "Rainmeter.h" - -/* -** The constructor -** -*/ -MeasureString::MeasureString(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), - m_String() -{ -} - -/* -** The destructor -** -*/ -MeasureString::~MeasureString() -{ -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeasureString::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - Measure::ReadOptions(parser, section); - - m_String = parser.ReadString(section, L"String", L""); -} - -/* -** Converts the string to a number (if possible). -** -*/ -void MeasureString::UpdateValue() -{ - m_Value = _wtof(m_String.c_str()); -} - -/* -** Returns the string value of the measure. -** -*/ -const WCHAR* MeasureString::GetStringValue() -{ - return CheckSubstitute(m_String.c_str()); -} +/* +Copyright (C) 2014 Brian Ferguson + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeasureString.h" +#include "Rainmeter.h" + +/* +** The constructor +** +*/ +MeasureString::MeasureString(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), + m_String() +{ +} + +/* +** The destructor +** +*/ +MeasureString::~MeasureString() +{ +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeasureString::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + Measure::ReadOptions(parser, section); + + m_String = parser.ReadString(section, L"String", L""); +} + +/* +** Converts the string to a number (if possible). +** +*/ +void MeasureString::UpdateValue() +{ + m_Value = _wtof(m_String.c_str()); +} + +/* +** Returns the string value of the measure. +** +*/ +const WCHAR* MeasureString::GetStringValue() +{ + return CheckSubstitute(m_String.c_str()); +} diff --git a/Library/MeasureString.h b/Library/MeasureString.h index e02d1d49..663220ee 100644 --- a/Library/MeasureString.h +++ b/Library/MeasureString.h @@ -1,45 +1,45 @@ -/* -Copyright (C) 2014 Brian Ferguson - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASURESTRING_H__ -#define __MEASURESTRING_H__ - -#include "Measure.h" - -class MeasureString : public Measure -{ -public: - MeasureString(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeasureString(); - - MeasureString(const MeasureString& other) = delete; - MeasureString& operator=(MeasureString other) = delete; - - virtual const WCHAR* GetStringValue(); - - virtual UINT GetTypeID() { return TypeID(); } - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void UpdateValue(); - -private: - std::wstring m_String; -}; - -#endif +/* +Copyright (C) 2014 Brian Ferguson + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASURESTRING_H__ +#define __MEASURESTRING_H__ + +#include "Measure.h" + +class MeasureString : public Measure +{ +public: + MeasureString(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeasureString(); + + MeasureString(const MeasureString& other) = delete; + MeasureString& operator=(MeasureString other) = delete; + + virtual const WCHAR* GetStringValue(); + + virtual UINT GetTypeID() { return TypeID(); } + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void UpdateValue(); + +private: + std::wstring m_String; +}; + +#endif diff --git a/Library/MeasureTime.cpp b/Library/MeasureTime.cpp index c69c3431..bee39c16 100644 --- a/Library/MeasureTime.cpp +++ b/Library/MeasureTime.cpp @@ -1,282 +1,282 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeasureTime.h" -#include "Rainmeter.h" - -int GetYearDay(int year, int month, int day) -{ - static const int dates[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; - int yearDay = dates[month - 1] + day; - - if (month > 2 && ((((year % 4) == 0) && ((year % 100) != 0)) || (year % 400) == 0)) - { - ++yearDay; - } - - return yearDay - 1; -} - -/* -** The constructor -** -*/ -MeasureTime::MeasureTime(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), - m_DeltaTime(), - m_Time(), - m_TimeStamp(-1) -{ - /* Set time zone from TZ environment variable. If TZ is not set, - * the operating system is queried to obtain the default value - * for the variable. - */ - _tzset(); -} - -/* -** The destructor -** -*/ -MeasureTime::~MeasureTime() -{ -} - -/* -** Converts given time to string. -** This function is a wrapper function for wcsftime. -** -*/ -void MeasureTime::TimeToString(WCHAR* buf, size_t bufLen, const WCHAR* format, const struct tm* time) -{ - if (bufLen > 0) - { - _invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(RmNullCRTInvalidParameterHandler); - _CrtSetReportMode(_CRT_ASSERT, 0); - - errno = 0; - wcsftime(buf, bufLen, format, time); - if (errno == EINVAL) - { - LogErrorF(this, L"Time: \"Format=%s\" invalid", format); - buf[0] = 0; - } - - _set_invalid_parameter_handler(oldHandler); - } -} - -void MeasureTime::FillCurrentTime() -{ - if (m_TimeStamp < 0.0) - { - FILETIME ftUTCTime; - GetSystemTimeAsFileTime(&ftUTCTime); - - // Modify the ltime to match the current timezone - // This way we can use the value also for the clock - m_Time.HighPart = ftUTCTime.dwHighDateTime; - m_Time.LowPart = ftUTCTime.dwLowDateTime; - - m_Time.QuadPart += m_DeltaTime.QuadPart; - } - else - { - m_Time.QuadPart = (LONGLONG)(m_TimeStamp * 10000000); - } -} - -/* -** Updates the current time -** -*/ -void MeasureTime::UpdateValue() -{ - FillCurrentTime(); - - if (!m_Format.empty()) - { - // If there is some date format, parse the value from it instead - WCHAR* tmpSz = new WCHAR[MAX_LINE_LENGTH]; - SYSTEMTIME sysToday; - FILETIME ftToday; - - tmpSz[0] = 0; - - ftToday.dwHighDateTime = m_Time.HighPart; - ftToday.dwLowDateTime = m_Time.LowPart; - - FileTimeToSystemTime(&ftToday, &sysToday); - - const WCHAR* format = m_Format.c_str(); - if (_wcsicmp(L"locale-time", format) == 0) - { - GetTimeFormat(LOCALE_USER_DEFAULT, 0, &sysToday, nullptr, tmpSz, MAX_LINE_LENGTH); - } - else if (_wcsicmp(L"locale-date", format) == 0) - { - GetDateFormat(LOCALE_USER_DEFAULT, 0, &sysToday, nullptr, tmpSz, MAX_LINE_LENGTH); - } - else - { - struct tm today; - today.tm_isdst = 0; - today.tm_hour = sysToday.wHour; - today.tm_mday = sysToday.wDay; - today.tm_min = sysToday.wMinute; - today.tm_mon = sysToday.wMonth - 1; - today.tm_sec = sysToday.wSecond; - today.tm_wday = sysToday.wDayOfWeek; - today.tm_yday = GetYearDay(sysToday.wYear, sysToday.wMonth, sysToday.wDay); - today.tm_year = sysToday.wYear - 1900; - - TimeToString(tmpSz, MAX_LINE_LENGTH, format, &today); - } - - m_Value = wcstod(tmpSz, nullptr); - - delete [] tmpSz; - } - else - { - m_Value = (double)(m_Time.QuadPart / 10000000); - } -} - - -/* -** Returns the time as string. -** -*/ -const WCHAR* MeasureTime::GetStringValue() -{ - static WCHAR tmpSz[MAX_LINE_LENGTH]; - struct tm today; - - tmpSz[0] = 0; - - SYSTEMTIME sysToday; - FILETIME ftToday; - ftToday.dwHighDateTime = m_Time.HighPart; - ftToday.dwLowDateTime = m_Time.LowPart; - - FileTimeToSystemTime(&ftToday, &sysToday); - - today.tm_isdst = 0; - today.tm_hour = sysToday.wHour; - today.tm_mday = sysToday.wDay; - today.tm_min = sysToday.wMinute; - today.tm_mon = sysToday.wMonth - 1; - today.tm_sec = sysToday.wSecond; - today.tm_wday = sysToday.wDayOfWeek; - today.tm_yday = GetYearDay(sysToday.wYear, sysToday.wMonth, sysToday.wDay); - today.tm_year = sysToday.wYear - 1900; - - // Create the string - if (!m_Format.empty()) - { - const WCHAR* format = m_Format.c_str(); - if (_wcsicmp(L"locale-time", format) == 0) - { - GetTimeFormat(LOCALE_USER_DEFAULT, 0, &sysToday, nullptr, tmpSz, MAX_LINE_LENGTH); - } - else if (_wcsicmp(L"locale-date", format) == 0) - { - GetDateFormat(LOCALE_USER_DEFAULT, 0, &sysToday, nullptr, tmpSz, MAX_LINE_LENGTH); - } - else - { - TimeToString(tmpSz, MAX_LINE_LENGTH, format, &today); - } - } - else - { - TimeToString(tmpSz, MAX_LINE_LENGTH, L"%H:%M:%S", &today); - } - - return CheckSubstitute(tmpSz); -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeasureTime::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - Measure::ReadOptions(parser, section); - - m_Format = parser.ReadString(section, L"Format", L""); - - m_TimeStamp = parser.ReadFloat(section, L"TimeStamp", -1); - - if (m_TimeStamp < 0.0) - { - const WCHAR* timezone = parser.ReadString(section, L"TimeZone", L"local").c_str(); - if (_wcsicmp(L"local", timezone) == 0) - { - SYSTEMTIME sysLocalTime, sysUTCTime; - GetLocalTime(&sysLocalTime); - GetSystemTime(&sysUTCTime); - - FILETIME ftLocalTime, ftUTCTime; - SystemTimeToFileTime(&sysLocalTime, &ftLocalTime); - SystemTimeToFileTime(&sysUTCTime, &ftUTCTime); - - LARGE_INTEGER largeInt1, largeInt2; - largeInt1.HighPart = ftLocalTime.dwHighDateTime; - largeInt1.LowPart = ftLocalTime.dwLowDateTime; - largeInt2.HighPart = ftUTCTime.dwHighDateTime; - largeInt2.LowPart = ftUTCTime.dwLowDateTime; - - m_DeltaTime.QuadPart = largeInt1.QuadPart - largeInt2.QuadPart; - } - else - { - double zone = parser.ParseDouble(timezone, 0.0); - bool dst = parser.ReadBool(section, L"DaylightSavingTime", true); - - struct tm* today; - time_t now; - time(&now); - today = localtime(&now); - - if (dst && today->tm_isdst) - { - // Add DST - TIME_ZONE_INFORMATION tzi; - GetTimeZoneInformation(&tzi); - - m_DeltaTime.QuadPart = (LONGLONG)((zone * 3600) - tzi.DaylightBias * 60) * 10000000; - } - else - { - m_DeltaTime.QuadPart = (LONGLONG)(zone * 3600) * 10000000; - } - } - } - else - { - m_DeltaTime.QuadPart = 0; - } - - if (!m_Initialized) - { - // Initialize m_Time to avoid causing EINVAL in TimeToString() until calling UpdateValue() - FillCurrentTime(); - } -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeasureTime.h" +#include "Rainmeter.h" + +int GetYearDay(int year, int month, int day) +{ + static const int dates[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + int yearDay = dates[month - 1] + day; + + if (month > 2 && ((((year % 4) == 0) && ((year % 100) != 0)) || (year % 400) == 0)) + { + ++yearDay; + } + + return yearDay - 1; +} + +/* +** The constructor +** +*/ +MeasureTime::MeasureTime(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), + m_DeltaTime(), + m_Time(), + m_TimeStamp(-1) +{ + /* Set time zone from TZ environment variable. If TZ is not set, + * the operating system is queried to obtain the default value + * for the variable. + */ + _tzset(); +} + +/* +** The destructor +** +*/ +MeasureTime::~MeasureTime() +{ +} + +/* +** Converts given time to string. +** This function is a wrapper function for wcsftime. +** +*/ +void MeasureTime::TimeToString(WCHAR* buf, size_t bufLen, const WCHAR* format, const struct tm* time) +{ + if (bufLen > 0) + { + _invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(RmNullCRTInvalidParameterHandler); + _CrtSetReportMode(_CRT_ASSERT, 0); + + errno = 0; + wcsftime(buf, bufLen, format, time); + if (errno == EINVAL) + { + LogErrorF(this, L"Time: \"Format=%s\" invalid", format); + buf[0] = 0; + } + + _set_invalid_parameter_handler(oldHandler); + } +} + +void MeasureTime::FillCurrentTime() +{ + if (m_TimeStamp < 0.0) + { + FILETIME ftUTCTime; + GetSystemTimeAsFileTime(&ftUTCTime); + + // Modify the ltime to match the current timezone + // This way we can use the value also for the clock + m_Time.HighPart = ftUTCTime.dwHighDateTime; + m_Time.LowPart = ftUTCTime.dwLowDateTime; + + m_Time.QuadPart += m_DeltaTime.QuadPart; + } + else + { + m_Time.QuadPart = (LONGLONG)(m_TimeStamp * 10000000); + } +} + +/* +** Updates the current time +** +*/ +void MeasureTime::UpdateValue() +{ + FillCurrentTime(); + + if (!m_Format.empty()) + { + // If there is some date format, parse the value from it instead + WCHAR* tmpSz = new WCHAR[MAX_LINE_LENGTH]; + SYSTEMTIME sysToday; + FILETIME ftToday; + + tmpSz[0] = 0; + + ftToday.dwHighDateTime = m_Time.HighPart; + ftToday.dwLowDateTime = m_Time.LowPart; + + FileTimeToSystemTime(&ftToday, &sysToday); + + const WCHAR* format = m_Format.c_str(); + if (_wcsicmp(L"locale-time", format) == 0) + { + GetTimeFormat(LOCALE_USER_DEFAULT, 0, &sysToday, nullptr, tmpSz, MAX_LINE_LENGTH); + } + else if (_wcsicmp(L"locale-date", format) == 0) + { + GetDateFormat(LOCALE_USER_DEFAULT, 0, &sysToday, nullptr, tmpSz, MAX_LINE_LENGTH); + } + else + { + struct tm today; + today.tm_isdst = 0; + today.tm_hour = sysToday.wHour; + today.tm_mday = sysToday.wDay; + today.tm_min = sysToday.wMinute; + today.tm_mon = sysToday.wMonth - 1; + today.tm_sec = sysToday.wSecond; + today.tm_wday = sysToday.wDayOfWeek; + today.tm_yday = GetYearDay(sysToday.wYear, sysToday.wMonth, sysToday.wDay); + today.tm_year = sysToday.wYear - 1900; + + TimeToString(tmpSz, MAX_LINE_LENGTH, format, &today); + } + + m_Value = wcstod(tmpSz, nullptr); + + delete [] tmpSz; + } + else + { + m_Value = (double)(m_Time.QuadPart / 10000000); + } +} + + +/* +** Returns the time as string. +** +*/ +const WCHAR* MeasureTime::GetStringValue() +{ + static WCHAR tmpSz[MAX_LINE_LENGTH]; + struct tm today; + + tmpSz[0] = 0; + + SYSTEMTIME sysToday; + FILETIME ftToday; + ftToday.dwHighDateTime = m_Time.HighPart; + ftToday.dwLowDateTime = m_Time.LowPart; + + FileTimeToSystemTime(&ftToday, &sysToday); + + today.tm_isdst = 0; + today.tm_hour = sysToday.wHour; + today.tm_mday = sysToday.wDay; + today.tm_min = sysToday.wMinute; + today.tm_mon = sysToday.wMonth - 1; + today.tm_sec = sysToday.wSecond; + today.tm_wday = sysToday.wDayOfWeek; + today.tm_yday = GetYearDay(sysToday.wYear, sysToday.wMonth, sysToday.wDay); + today.tm_year = sysToday.wYear - 1900; + + // Create the string + if (!m_Format.empty()) + { + const WCHAR* format = m_Format.c_str(); + if (_wcsicmp(L"locale-time", format) == 0) + { + GetTimeFormat(LOCALE_USER_DEFAULT, 0, &sysToday, nullptr, tmpSz, MAX_LINE_LENGTH); + } + else if (_wcsicmp(L"locale-date", format) == 0) + { + GetDateFormat(LOCALE_USER_DEFAULT, 0, &sysToday, nullptr, tmpSz, MAX_LINE_LENGTH); + } + else + { + TimeToString(tmpSz, MAX_LINE_LENGTH, format, &today); + } + } + else + { + TimeToString(tmpSz, MAX_LINE_LENGTH, L"%H:%M:%S", &today); + } + + return CheckSubstitute(tmpSz); +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeasureTime::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + Measure::ReadOptions(parser, section); + + m_Format = parser.ReadString(section, L"Format", L""); + + m_TimeStamp = parser.ReadFloat(section, L"TimeStamp", -1); + + if (m_TimeStamp < 0.0) + { + const WCHAR* timezone = parser.ReadString(section, L"TimeZone", L"local").c_str(); + if (_wcsicmp(L"local", timezone) == 0) + { + SYSTEMTIME sysLocalTime, sysUTCTime; + GetLocalTime(&sysLocalTime); + GetSystemTime(&sysUTCTime); + + FILETIME ftLocalTime, ftUTCTime; + SystemTimeToFileTime(&sysLocalTime, &ftLocalTime); + SystemTimeToFileTime(&sysUTCTime, &ftUTCTime); + + LARGE_INTEGER largeInt1, largeInt2; + largeInt1.HighPart = ftLocalTime.dwHighDateTime; + largeInt1.LowPart = ftLocalTime.dwLowDateTime; + largeInt2.HighPart = ftUTCTime.dwHighDateTime; + largeInt2.LowPart = ftUTCTime.dwLowDateTime; + + m_DeltaTime.QuadPart = largeInt1.QuadPart - largeInt2.QuadPart; + } + else + { + double zone = parser.ParseDouble(timezone, 0.0); + bool dst = parser.ReadBool(section, L"DaylightSavingTime", true); + + struct tm* today; + time_t now; + time(&now); + today = localtime(&now); + + if (dst && today->tm_isdst) + { + // Add DST + TIME_ZONE_INFORMATION tzi; + GetTimeZoneInformation(&tzi); + + m_DeltaTime.QuadPart = (LONGLONG)((zone * 3600) - tzi.DaylightBias * 60) * 10000000; + } + else + { + m_DeltaTime.QuadPart = (LONGLONG)(zone * 3600) * 10000000; + } + } + } + else + { + m_DeltaTime.QuadPart = 0; + } + + if (!m_Initialized) + { + // Initialize m_Time to avoid causing EINVAL in TimeToString() until calling UpdateValue() + FillCurrentTime(); + } +} diff --git a/Library/MeasureTime.h b/Library/MeasureTime.h index 3b62a9fd..e64fd75a 100644 --- a/Library/MeasureTime.h +++ b/Library/MeasureTime.h @@ -1,52 +1,52 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASURETIME_H__ -#define __MEASURETIME_H__ - -#include "Measure.h" - -class MeasureTime : public Measure -{ -public: - MeasureTime(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeasureTime(); - - MeasureTime(const MeasureTime& other) = delete; - MeasureTime& operator=(MeasureTime other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - virtual const WCHAR* GetStringValue(); - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void UpdateValue(); - -private: - void TimeToString(WCHAR* buf, size_t bufLen, const WCHAR* format, const tm* time); - void FillCurrentTime(); - - std::wstring m_Format; - LARGE_INTEGER m_DeltaTime; - LARGE_INTEGER m_Time; - - double m_TimeStamp; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASURETIME_H__ +#define __MEASURETIME_H__ + +#include "Measure.h" + +class MeasureTime : public Measure +{ +public: + MeasureTime(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeasureTime(); + + MeasureTime(const MeasureTime& other) = delete; + MeasureTime& operator=(MeasureTime other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + virtual const WCHAR* GetStringValue(); + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void UpdateValue(); + +private: + void TimeToString(WCHAR* buf, size_t bufLen, const WCHAR* format, const tm* time); + void FillCurrentTime(); + + std::wstring m_Format; + LARGE_INTEGER m_DeltaTime; + LARGE_INTEGER m_Time; + + double m_TimeStamp; +}; + +#endif diff --git a/Library/MeasureUptime.cpp b/Library/MeasureUptime.cpp index e60db735..fc7bddce 100644 --- a/Library/MeasureUptime.cpp +++ b/Library/MeasureUptime.cpp @@ -1,103 +1,103 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeasureUptime.h" -#include "Rainmeter.h" -#include "System.h" - -/* -** The constructor -** -*/ -MeasureUptime::MeasureUptime(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), - m_AddDaysToHours(false) -{ -} - -/* -** The destructor -** -*/ -MeasureUptime::~MeasureUptime() -{ -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeasureUptime::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - Measure::ReadOptions(parser, section); - - m_Format = parser.ReadString(section, L"Format", L"%4!i!d %3!i!:%2!02i!"); - - if (m_Format.find(L"%4") == std::wstring::npos) - { - m_AddDaysToHours = parser.ReadBool(section, L"AddDaysToHours", true); - } - else - { - m_AddDaysToHours = false; - } -} - -/* -** Updates the current uptime -** -*/ -void MeasureUptime::UpdateValue() -{ - ULONGLONG ticks = System::GetTickCount64(); - m_Value = (double)(__int64)(ticks / 1000); -} - -/* -** Returns the uptime as string. -** -*/ -const WCHAR* MeasureUptime::GetStringValue() -{ - static WCHAR buffer[MAX_LINE_LENGTH]; - - size_t value = (size_t)m_Value; - size_t time[4]; - - time[0] = value % 60; - time[1] = (value / 60) % 60; - time[2] = (value / (60 * 60)); - time[3] = (value / (60 * 60 * 24)); - - if (!m_AddDaysToHours) - { - time[2] %= 24; - } - - __try - { - FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, m_Format.c_str(), 0, 0, buffer, MAX_LINE_LENGTH, (char**)time); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - LogErrorF(this, L"Uptime: \"Format=%s\" invalid", m_Format.c_str()); - buffer[0] = 0; - } - - return CheckSubstitute(buffer); -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeasureUptime.h" +#include "Rainmeter.h" +#include "System.h" + +/* +** The constructor +** +*/ +MeasureUptime::MeasureUptime(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), + m_AddDaysToHours(false) +{ +} + +/* +** The destructor +** +*/ +MeasureUptime::~MeasureUptime() +{ +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeasureUptime::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + Measure::ReadOptions(parser, section); + + m_Format = parser.ReadString(section, L"Format", L"%4!i!d %3!i!:%2!02i!"); + + if (m_Format.find(L"%4") == std::wstring::npos) + { + m_AddDaysToHours = parser.ReadBool(section, L"AddDaysToHours", true); + } + else + { + m_AddDaysToHours = false; + } +} + +/* +** Updates the current uptime +** +*/ +void MeasureUptime::UpdateValue() +{ + ULONGLONG ticks = System::GetTickCount64(); + m_Value = (double)(__int64)(ticks / 1000); +} + +/* +** Returns the uptime as string. +** +*/ +const WCHAR* MeasureUptime::GetStringValue() +{ + static WCHAR buffer[MAX_LINE_LENGTH]; + + size_t value = (size_t)m_Value; + size_t time[4]; + + time[0] = value % 60; + time[1] = (value / 60) % 60; + time[2] = (value / (60 * 60)); + time[3] = (value / (60 * 60 * 24)); + + if (!m_AddDaysToHours) + { + time[2] %= 24; + } + + __try + { + FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, m_Format.c_str(), 0, 0, buffer, MAX_LINE_LENGTH, (char**)time); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + LogErrorF(this, L"Uptime: \"Format=%s\" invalid", m_Format.c_str()); + buffer[0] = 0; + } + + return CheckSubstitute(buffer); +} diff --git a/Library/MeasureUptime.h b/Library/MeasureUptime.h index f94f1630..c34bd365 100644 --- a/Library/MeasureUptime.h +++ b/Library/MeasureUptime.h @@ -1,46 +1,46 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASUREUPTIME_H__ -#define __MEASUREUPTIME_H__ - -#include "Measure.h" - -class MeasureUptime : public Measure -{ -public: - MeasureUptime(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeasureUptime(); - - MeasureUptime(const MeasureUptime& other) = delete; - MeasureUptime& operator=(MeasureUptime other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - virtual const WCHAR* GetStringValue(); - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void UpdateValue(); - -private: - bool m_AddDaysToHours; - std::wstring m_Format; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASUREUPTIME_H__ +#define __MEASUREUPTIME_H__ + +#include "Measure.h" + +class MeasureUptime : public Measure +{ +public: + MeasureUptime(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeasureUptime(); + + MeasureUptime(const MeasureUptime& other) = delete; + MeasureUptime& operator=(MeasureUptime other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + virtual const WCHAR* GetStringValue(); + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void UpdateValue(); + +private: + bool m_AddDaysToHours; + std::wstring m_Format; +}; + +#endif diff --git a/Library/MeasureVirtualMemory.cpp b/Library/MeasureVirtualMemory.cpp index d6bb11bc..6e34ad13 100644 --- a/Library/MeasureVirtualMemory.cpp +++ b/Library/MeasureVirtualMemory.cpp @@ -1,77 +1,77 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeasureVirtualMemory.h" -#include "ConfigParser.h" - -/* -** The constructor -** -*/ -MeasureVirtualMemory::MeasureVirtualMemory(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), - m_Total(false) -{ - MEMORYSTATUSEX stat; - stat.dwLength = sizeof(MEMORYSTATUSEX); - GlobalMemoryStatusEx(&stat); - m_MaxValue = (double)(__int64)stat.ullTotalPageFile; -} - -/* -** The destructor -** -*/ -MeasureVirtualMemory::~MeasureVirtualMemory() -{ -} - -/* -** Updates the current virtual memory value. -** -*/ -void MeasureVirtualMemory::UpdateValue() -{ - MEMORYSTATUSEX stat; - stat.dwLength = sizeof(MEMORYSTATUSEX); - GlobalMemoryStatusEx(&stat); - m_MaxValue = (double)(__int64)stat.ullTotalPageFile; - - if (m_Total) - { - m_Value = m_MaxValue; - } - else - { - m_Value = (double)(__int64)(stat.ullTotalPageFile - stat.ullAvailPageFile); - } -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeasureVirtualMemory::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - double oldMaxValue = m_MaxValue; - Measure::ReadOptions(parser, section); - m_MaxValue = oldMaxValue; - - m_Total = parser.ReadBool(section, L"Total", false); -} - +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeasureVirtualMemory.h" +#include "ConfigParser.h" + +/* +** The constructor +** +*/ +MeasureVirtualMemory::MeasureVirtualMemory(MeterWindow* meterWindow, const WCHAR* name) : Measure(meterWindow, name), + m_Total(false) +{ + MEMORYSTATUSEX stat; + stat.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&stat); + m_MaxValue = (double)(__int64)stat.ullTotalPageFile; +} + +/* +** The destructor +** +*/ +MeasureVirtualMemory::~MeasureVirtualMemory() +{ +} + +/* +** Updates the current virtual memory value. +** +*/ +void MeasureVirtualMemory::UpdateValue() +{ + MEMORYSTATUSEX stat; + stat.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&stat); + m_MaxValue = (double)(__int64)stat.ullTotalPageFile; + + if (m_Total) + { + m_Value = m_MaxValue; + } + else + { + m_Value = (double)(__int64)(stat.ullTotalPageFile - stat.ullAvailPageFile); + } +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeasureVirtualMemory::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + double oldMaxValue = m_MaxValue; + Measure::ReadOptions(parser, section); + m_MaxValue = oldMaxValue; + + m_Total = parser.ReadBool(section, L"Total", false); +} + diff --git a/Library/MeasureVirtualMemory.h b/Library/MeasureVirtualMemory.h index 31c1265b..570b05ca 100644 --- a/Library/MeasureVirtualMemory.h +++ b/Library/MeasureVirtualMemory.h @@ -1,43 +1,43 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MEASUREVIRTUALMEMORY_H__ -#define __MEASUREVIRTUALMEMORY_H__ - -#include "Measure.h" - -class MeasureVirtualMemory : public Measure -{ -public: - MeasureVirtualMemory(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeasureVirtualMemory(); - - MeasureVirtualMemory(const MeasureVirtualMemory& other) = delete; - MeasureVirtualMemory& operator=(MeasureVirtualMemory other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void UpdateValue(); - -private: - bool m_Total; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MEASUREVIRTUALMEMORY_H__ +#define __MEASUREVIRTUALMEMORY_H__ + +#include "Measure.h" + +class MeasureVirtualMemory : public Measure +{ +public: + MeasureVirtualMemory(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeasureVirtualMemory(); + + MeasureVirtualMemory(const MeasureVirtualMemory& other) = delete; + MeasureVirtualMemory& operator=(MeasureVirtualMemory other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void UpdateValue(); + +private: + bool m_Total; +}; + +#endif diff --git a/Library/Meter.cpp b/Library/Meter.cpp index 68219b13..5c847a3b 100644 --- a/Library/Meter.cpp +++ b/Library/Meter.cpp @@ -1,760 +1,760 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Error.h" -#include "Meter.h" -#include "MeterBitmap.h" -#include "MeterBar.h" -#include "MeterHistogram.h" -#include "MeterString.h" -#include "MeterImage.h" -#include "MeterLine.h" -#include "MeterRoundLine.h" -#include "MeterRotator.h" -#include "MeterButton.h" -#include "Measure.h" -#include "Rainmeter.h" -#include "../Common/Gfx/Canvas.h" - -using namespace Gdiplus; - -/* -** The constructor -** -*/ -Meter::Meter(MeterWindow* meterWindow, const WCHAR* name) : Section(meterWindow, name), - m_X(), - m_Y(), - m_W(0), - m_H(0), - m_Hidden(false), - m_WDefined(false), - m_HDefined(false), - m_RelativeMeter(), - m_Transformation(), - m_ToolTipWidth(), - m_ToolTipType(false), - m_ToolTipHidden(meterWindow->GetMeterToolTipHidden()), - m_ToolTipHandle(), - m_Mouse(meterWindow, this), - m_HasMouseAction(false), - m_MouseOver(false), - m_RelativeX(POSITION_ABSOLUTE), - m_RelativeY(POSITION_ABSOLUTE), - m_SolidBevel(BEVELTYPE_NONE), - m_SolidAngle(), - m_Padding(), - m_AntiAlias(false), - m_Initialized(false) -{ -} - -/* -** The destructor -** -*/ -Meter::~Meter() -{ - delete m_Transformation; - - if (m_ToolTipHandle != nullptr) - { - DestroyWindow(m_ToolTipHandle); - } -} - -/* -** Initializes the meter. Usually this method is overwritten by the inherited -** classes, which load bitmaps and such things during initialization. -** -*/ -void Meter::Initialize() -{ - m_Initialized = true; -} - -/* -** Returns the X-position of the meter. -** -*/ -int Meter::GetX(bool abs) -{ - if (m_RelativeX != POSITION_ABSOLUTE && m_RelativeMeter) - { - if (m_RelativeX == POSITION_RELATIVE_TL) - { - return m_RelativeMeter->GetX(true) + m_X; - } - else - { - return m_RelativeMeter->GetX(true) + m_RelativeMeter->GetW() + m_X; - } - } - return m_X; -} - -/* -** Returns the Y-position of the meter. -** -*/ -int Meter::GetY(bool abs) -{ - if (m_RelativeY != POSITION_ABSOLUTE && m_RelativeMeter) - { - if (m_RelativeY == POSITION_RELATIVE_TL) - { - return m_RelativeMeter->GetY(true) + m_Y; - } - else - { - return m_RelativeMeter->GetY(true) + m_RelativeMeter->GetH() + m_Y; - } - } - return m_Y; -} - -void Meter::SetX(int x) -{ - m_X = x; - m_RelativeX = POSITION_ABSOLUTE; - - // Change the option as well to avoid reset in ReadOptions(). - WCHAR buffer[32]; - _itow_s(x, buffer, 10); - m_MeterWindow->GetParser().SetValue(m_Name, L"X", buffer); -} - -void Meter::SetY(int y) -{ - m_Y = y; - m_RelativeY = POSITION_ABSOLUTE; - - // Change the option as well to avoid reset in ReadOptions(). - WCHAR buffer[32]; - _itow_s(y, buffer, 10); - m_MeterWindow->GetParser().SetValue(m_Name, L"Y", buffer); -} - -/* -** Returns a RECT containing the dimensions of the meter within the MeterWindow -** -*/ -RECT Meter::GetMeterRect() -{ - RECT meterRect; - - meterRect.left = GetX(); - meterRect.top = GetY(); - meterRect.right = meterRect.left + m_W; - meterRect.bottom = meterRect.top + m_H; - - return meterRect; -} - -/* -** Returns a Rect containing the adjusted meter location with "Padding" option -** -*/ -Gdiplus::Rect Meter::GetMeterRectPadding() -{ - Gdiplus::Rect meterRect; - - meterRect.X = GetX() + m_Padding.X; - meterRect.Y = GetY() + m_Padding.Y; - meterRect.Width = m_W - m_Padding.X - m_Padding.Width; - meterRect.Height = m_H - m_Padding.Y - m_Padding.Height; - - return meterRect; -} - -/* -** Checks if the given point is inside the meter. -** This function doesn't check Hidden state, so check it before calling this function if needed. -** -*/ -bool Meter::HitTest(int x, int y) -{ - int p; - return (x >= (p = GetX()) && x < p + m_W && y >= (p = GetY()) && y < p + m_H); -} - -/* -** Shows the meter and tooltip. -** -*/ -void Meter::Show() -{ - m_Hidden = false; - - // Change the option as well to avoid reset in ReadOptions(). - m_MeterWindow->GetParser().SetValue(m_Name, L"Hidden", L"0"); - - if (m_ToolTipHandle != nullptr) - { - if (!m_ToolTipHidden) - { - SendMessage(m_ToolTipHandle, TTM_ACTIVATE, TRUE, 0); - } - } -} - -/* -** Hides the meter and tooltip. -** -*/ -void Meter::Hide() -{ - m_Hidden = true; - - // Change the option as well to avoid reset in ReadOptions(). - m_MeterWindow->GetParser().SetValue(m_Name, L"Hidden", L"1"); - - if (m_ToolTipHandle != nullptr) - { - SendMessage(m_ToolTipHandle, TTM_ACTIVATE, FALSE, 0); - } -} - -/* -** Read the common options specified in the ini file. The inherited classes must -** call this base implementation if they overwrite this method. -** -*/ -void Meter::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - // The MeterStyle defines a template where the values are read if the meter doesn't have it itself - const std::wstring& style = parser.ReadString(section, L"MeterStyle", L""); - if (!style.empty()) - { - parser.SetStyleTemplate(style); - } - - Section::ReadOptions(parser, section); - - BindMeasures(parser, section); - - int oldX = m_X; - std::wstring& x = (std::wstring&)parser.ReadString(section, L"X", L"0"); - if (!x.empty()) - { - WCHAR lastChar = x[x.size() - 1]; - if (lastChar == L'r') - { - m_RelativeX = POSITION_RELATIVE_TL; - x.pop_back(); - } - else if (lastChar == L'R') - { - m_RelativeX = POSITION_RELATIVE_BR; - x.pop_back(); - } - else - { - m_RelativeX = POSITION_ABSOLUTE; - } - - m_X = parser.ParseInt(x.c_str(), 0); - } - else - { - m_X = 0; - m_RelativeX = POSITION_ABSOLUTE; - } - - int oldY = m_Y; - std::wstring& y = (std::wstring&)parser.ReadString(section, L"Y", L"0"); - if (!y.empty()) - { - WCHAR lastChar = y[y.size() - 1]; - if (lastChar == L'r') - { - m_RelativeY = POSITION_RELATIVE_TL; - y.pop_back(); - } - else if (lastChar == L'R') - { - m_RelativeY = POSITION_RELATIVE_BR; - y.pop_back(); - } - else - { - m_RelativeY = POSITION_ABSOLUTE; - } - - m_Y = parser.ParseInt(y.c_str(), 0); - } - else - { - m_Y = 0; - m_RelativeY = POSITION_ABSOLUTE; - } - - static const Gdiplus::Rect defPadding; - m_Padding = parser.ReadRect(section, L"Padding", defPadding); - - const int oldW = m_W; - const bool oldWDefined = m_WDefined; - const int widthPadding = GetWidthPadding(); - - const int w = parser.ReadInt(section, L"W", m_W); - m_WDefined = parser.GetLastValueDefined(); - - if (IsFixedSize(true)) m_W = w; - if (oldW != (m_W - widthPadding)) m_W += widthPadding; - if (!m_WDefined && oldWDefined && IsFixedSize()) - { - m_W = 0; - } - - const int oldH = m_H; - const bool oldHDefined = m_HDefined; - const int heightPadding = GetHeightPadding(); - - const int h = parser.ReadInt(section, L"H", m_H); - m_HDefined = parser.GetLastValueDefined(); - - if (IsFixedSize(true)) m_H = h; - if (oldH != (m_H - heightPadding)) m_H += heightPadding; - if (!m_HDefined && oldHDefined && IsFixedSize()) - { - m_H = 0; - } - - bool oldHidden = m_Hidden; - m_Hidden = parser.ReadBool(section, L"Hidden", false); - - if (oldX != m_X || oldY != m_Y || oldHidden != m_Hidden) - { - m_MeterWindow->SetResizeWindowMode(RESIZEMODE_CHECK); // Need to recalculate the window size - } - - m_SolidBevel = (BEVELTYPE)parser.ReadInt(section, L"BevelType", BEVELTYPE_NONE); - - m_SolidColor = parser.ReadColor(section, L"SolidColor", Color::MakeARGB(0, 0, 0, 0)); - m_SolidColor2 = parser.ReadColor(section, L"SolidColor2", m_SolidColor.GetValue()); - m_SolidAngle = (Gdiplus::REAL)parser.ReadFloat(section, L"GradientAngle", 0.0); - - m_Mouse.ReadOptions(parser, section); - m_HasMouseAction = m_Mouse.HasButtonAction() || m_Mouse.HasScrollAction(); - - m_ToolTipText = parser.ReadString(section, L"ToolTipText", L""); - m_ToolTipTitle = parser.ReadString(section, L"ToolTipTitle", L""); - m_ToolTipIcon = parser.ReadString(section, L"ToolTipIcon", L""); - m_ToolTipWidth = parser.ReadInt(section, L"ToolTipWidth", 1000); - m_ToolTipType = parser.ReadBool(section, L"ToolTipType", false); - m_ToolTipHidden = parser.ReadBool(section, L"ToolTipHidden", m_MeterWindow->GetMeterToolTipHidden()); - - m_AntiAlias = parser.ReadBool(section, L"AntiAlias", false); - - std::vector matrix = parser.ReadFloats(section, L"TransformationMatrix"); - if (matrix.size() == 6) - { - if (m_Transformation) - { - m_Transformation->SetElements(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); - } - else - { - m_Transformation = new Matrix(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); - } - } - else if (!matrix.empty()) - { - delete m_Transformation; - m_Transformation = nullptr; - - LogErrorF(this, L"Meter: Incorrect number of values in TransformationMatrix=%s", parser.ReadString(section, L"TransformationMatrix", L"").c_str()); - } -} - -/* -** Binds this meter to the given measure. The same measure can be bound to -** several meters but one meter and only be bound to one measure. -** -*/ -void Meter::BindMeasures(ConfigParser& parser, const WCHAR* section) -{ - BindPrimaryMeasure(parser, section, false); -} - -/* -** Creates the given meter. This is the factory method for the meters. -** If new meters are implemented this method needs to be updated. -** -*/ -Meter* Meter::Create(const WCHAR* meter, MeterWindow* meterWindow, const WCHAR* name) -{ - if (_wcsicmp(L"STRING", meter) == 0) - { - return new MeterString(meterWindow, name); - } - else if (_wcsicmp(L"IMAGE", meter) == 0) - { - return new MeterImage(meterWindow, name); - } - else if (_wcsicmp(L"HISTOGRAM", meter) == 0) - { - return new MeterHistogram(meterWindow, name); - } - else if (_wcsicmp(L"BAR", meter) == 0) - { - return new MeterBar(meterWindow, name); - } - else if (_wcsicmp(L"BITMAP", meter) == 0) - { - return new MeterBitmap(meterWindow, name); - } - else if (_wcsicmp(L"LINE", meter) == 0) - { - return new MeterLine(meterWindow, name); - } - else if (_wcsicmp(L"ROUNDLINE", meter) == 0) - { - return new MeterRoundLine(meterWindow, name); - } - else if (_wcsicmp(L"ROTATOR", meter) == 0) - { - return new MeterRotator(meterWindow, name); - } - else if (_wcsicmp(L"BUTTON", meter) == 0) - { - return new MeterButton(meterWindow, name); - } - - LogErrorF(meterWindow, L"Meter=%s is not valid in [%s]", meter, name); - - return nullptr; -} - -/* -** Updates the value(s) from the measures. Derived classes should -** only update if this returns true; -*/ -bool Meter::Update() -{ - // Only update the meter's value when the divider is equal to the counter - return UpdateCounter(); -} - -/* -** Reads and binds the primary MeasureName. This must always be called in overridden -** BindMeasures() implementations. -** -*/ -bool Meter::BindPrimaryMeasure(ConfigParser& parser, const WCHAR* section, bool optional) -{ - m_Measures.clear(); - - const std::wstring& measureName = parser.ReadString(section, L"MeasureName", L""); - - Measure* measure = parser.GetMeasure(measureName); - if (measure) - { - m_Measures.push_back(measure); - return true; - } - else if (!optional) - { - LogErrorF(this, L"MeasureName=%s is not valid", measureName.c_str()); - } - - return false; -} - -/* -** Reads and binds secondary measures (MeasureName2 - MeasureNameN). -** -*/ -void Meter::BindSecondaryMeasures(ConfigParser& parser, const WCHAR* section) -{ - if (!m_Measures.empty()) - { - WCHAR tmpName[64]; - - int i = 2; - do - { - _snwprintf_s(tmpName, _TRUNCATE, L"MeasureName%i", i); - const std::wstring& measureName = parser.ReadString(section, tmpName, L""); - Measure* measure = parser.GetMeasure(measureName); - if (measure) - { - m_Measures.push_back(measure); - } - else - { - if (!measureName.empty()) - { - LogErrorF(this, L"MeasureName%i=%s is not valid", i, measureName.c_str()); - } - - break; - } - ++i; - } - while (true); - } -} - -/* -** Replaces %1, %2, ... with the corresponding measure value. -** -*/ -bool Meter::ReplaceMeasures(std::wstring& str, AUTOSCALE autoScale, double scale, int decimals, bool percentual) -{ - bool replaced = false; - - if (str.find(L'%') != std::wstring::npos) - { - WCHAR buffer[64]; - - for (size_t i = m_Measures.size(); i > 0; --i) - { - size_t len = _snwprintf_s(buffer, _TRUNCATE, L"%%%i", (int)i); - size_t start = 0, pos; - - const WCHAR* measureValue = m_Measures[i - 1]->GetStringOrFormattedValue( - autoScale, scale, decimals, percentual); - const size_t measureValueLen = wcslen(measureValue); - - do - { - pos = str.find(buffer, start, len); - if (pos != std::wstring::npos) - { - str.replace(pos, len, measureValue, measureValueLen); - start = pos + measureValueLen; - replaced = true; - } - } - while (pos != std::wstring::npos); - } - } - - return replaced; -} - -/* -** Does the initial construction of the ToolTip for the meter -*/ -void Meter::CreateToolTip(MeterWindow* meterWindow) -{ - HWND hMeterWindow = m_MeterWindow->GetWindow(); - HINSTANCE hInstance = Rainmeter::GetInstance().GetModuleInstance(); - DWORD style = WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP; - - if (m_ToolTipType) - { - style |= TTS_BALLOON; - } - - HWND hwndTT = CreateWindowEx(WS_EX_TOPMOST, - TOOLTIPS_CLASS, - nullptr, - style, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - hMeterWindow, - nullptr, - hInstance, - nullptr); - - if (hwndTT) - { - SetWindowPos(hwndTT, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - - TOOLINFO ti = {sizeof(TOOLINFO), TTF_SUBCLASS, hMeterWindow, 0, GetMeterRect(), hInstance}; - - SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM)&ti); - - m_ToolTipHandle = hwndTT; - UpdateToolTip(); - } -} - -/* -** Updates the ToolTip to match new values -*/ -void Meter::UpdateToolTip() -{ - HWND hwndTT = m_ToolTipHandle; - - TOOLINFO ti = {sizeof(TOOLINFO)}; - ti.hwnd = m_MeterWindow->GetWindow(); - - SendMessage(hwndTT, TTM_GETTOOLINFO, 0, (LPARAM)&ti); - - std::wstring text = m_ToolTipText; - ReplaceMeasures(text); - ti.lpszText = (LPTSTR)text.c_str(); - ti.rect = GetMeterRect(); - - SendMessage(hwndTT, TTM_SETTOOLINFO, 0, (LPARAM)&ti); - SendMessage(hwndTT, TTM_SETMAXTIPWIDTH, 0, m_ToolTipWidth); - - if (!m_ToolTipTitle.empty()) - { - HICON hIcon = nullptr; - bool destroy = false; - - if (!m_ToolTipIcon.empty()) - { - const WCHAR* tipIcon = m_ToolTipIcon.c_str(); - if (_wcsicmp(tipIcon, L"INFO") == 0) - { - hIcon = (HICON)TTI_INFO; - } - else if (_wcsicmp(tipIcon, L"WARNING") == 0) - { - hIcon = (HICON)TTI_WARNING; - } - else if (_wcsicmp(tipIcon, L"ERROR") == 0) - { - hIcon = (HICON)TTI_ERROR; - } - else if (_wcsicmp(tipIcon, L"QUESTION") == 0) - { - hIcon = LoadIcon(nullptr, IDI_QUESTION); - } - else if (_wcsicmp(tipIcon, L"SHIELD") == 0) - { - hIcon = LoadIcon(nullptr, IDI_SHIELD); - } - else - { - std::wstring iconPath = m_ToolTipIcon; - m_MeterWindow->MakePathAbsolute(iconPath); - hIcon = (HICON)LoadImage(nullptr, iconPath.c_str(), IMAGE_ICON, 0, 0, LR_LOADFROMFILE); - destroy = true; - } - } - - text = m_ToolTipTitle; - ReplaceMeasures(text); - SendMessage(hwndTT, TTM_SETTITLE, (WPARAM)hIcon, (LPARAM)text.c_str()); - - if (destroy) - { - DestroyIcon(hIcon); - } - } - - if (m_ToolTipHidden) - { - SendMessage(hwndTT, TTM_ACTIVATE, FALSE, 0); - } - else - { - SendMessage(hwndTT, TTM_ACTIVATE, !IsHidden(), 0); - } -} - -/* -** Draws the solid background & bevel if such are defined -*/ -bool Meter::Draw(Gfx::Canvas& canvas) -{ - if (IsHidden()) return false; - - canvas.SetAntiAliasing(m_AntiAlias); - - if (m_SolidColor.GetA() != 0 || m_SolidColor2.GetA() != 0) - { - int x = GetX(); - int y = GetY(); - - Rect r(x, y, m_W, m_H); - - if (m_SolidColor.GetValue() == m_SolidColor2.GetValue()) - { - SolidBrush solid(m_SolidColor); - canvas.FillRectangle(r, solid); - } - else - { - Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); - - if (!m_AntiAlias) - { - // Fix the tiling issue in some GradientAngle values - graphics.SetPixelOffsetMode(PixelOffsetModeHalf); - } - - LinearGradientBrush gradient(r, m_SolidColor, m_SolidColor2, m_SolidAngle, TRUE); - graphics.FillRectangle(&gradient, r); - - if (!m_AntiAlias) - { - graphics.SetPixelOffsetMode(PixelOffsetModeDefault); - } - - canvas.EndGdiplusContext(); - } - } - - if (m_SolidBevel != BEVELTYPE_NONE) - { - Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); - - int x = GetX(); - int y = GetY(); - - Color lightColor(255, 255, 255, 255); - Color darkColor(255, 0, 0, 0); - - if (m_SolidBevel == BEVELTYPE_DOWN) - { - lightColor.SetValue(Color::MakeARGB(255, 0, 0, 0)); - darkColor.SetValue(Color::MakeARGB(255, 255, 255, 255)); - } - - Pen light(lightColor); - Pen dark(darkColor); - - // The bevel is drawn outside the meter - Rect rect(x - 2, y - 2, m_W + 4, m_H + 4); - DrawBevel(graphics, rect, light, dark); - - canvas.EndGdiplusContext(); - } - - return true; -} - -/* -** Draws a bevel inside the given area -*/ -void Meter::DrawBevel(Graphics& graphics, const Rect& rect, const Pen& light, const Pen& dark) -{ - int l = rect.GetLeft(); - int r = rect.GetRight() - 1; - int t = rect.GetTop(); - int b = rect.GetBottom() - 1; - - graphics.DrawLine(&light, l, t, l, b); - graphics.DrawLine(&light, l, t, r, t); - graphics.DrawLine(&light, l + 1, t + 1, l + 1, b - 1); - graphics.DrawLine(&light, l + 1, t + 1, r - 1, t + 1); - graphics.DrawLine(&dark, l, b, r, b); - graphics.DrawLine(&dark, r, t, r, b); - graphics.DrawLine(&dark, l + 1, b - 1, r - 1, b - 1); - graphics.DrawLine(&dark, r - 1, t + 1, r - 1, b - 1); -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Error.h" +#include "Meter.h" +#include "MeterBitmap.h" +#include "MeterBar.h" +#include "MeterHistogram.h" +#include "MeterString.h" +#include "MeterImage.h" +#include "MeterLine.h" +#include "MeterRoundLine.h" +#include "MeterRotator.h" +#include "MeterButton.h" +#include "Measure.h" +#include "Rainmeter.h" +#include "../Common/Gfx/Canvas.h" + +using namespace Gdiplus; + +/* +** The constructor +** +*/ +Meter::Meter(MeterWindow* meterWindow, const WCHAR* name) : Section(meterWindow, name), + m_X(), + m_Y(), + m_W(0), + m_H(0), + m_Hidden(false), + m_WDefined(false), + m_HDefined(false), + m_RelativeMeter(), + m_Transformation(), + m_ToolTipWidth(), + m_ToolTipType(false), + m_ToolTipHidden(meterWindow->GetMeterToolTipHidden()), + m_ToolTipHandle(), + m_Mouse(meterWindow, this), + m_HasMouseAction(false), + m_MouseOver(false), + m_RelativeX(POSITION_ABSOLUTE), + m_RelativeY(POSITION_ABSOLUTE), + m_SolidBevel(BEVELTYPE_NONE), + m_SolidAngle(), + m_Padding(), + m_AntiAlias(false), + m_Initialized(false) +{ +} + +/* +** The destructor +** +*/ +Meter::~Meter() +{ + delete m_Transformation; + + if (m_ToolTipHandle != nullptr) + { + DestroyWindow(m_ToolTipHandle); + } +} + +/* +** Initializes the meter. Usually this method is overwritten by the inherited +** classes, which load bitmaps and such things during initialization. +** +*/ +void Meter::Initialize() +{ + m_Initialized = true; +} + +/* +** Returns the X-position of the meter. +** +*/ +int Meter::GetX(bool abs) +{ + if (m_RelativeX != POSITION_ABSOLUTE && m_RelativeMeter) + { + if (m_RelativeX == POSITION_RELATIVE_TL) + { + return m_RelativeMeter->GetX(true) + m_X; + } + else + { + return m_RelativeMeter->GetX(true) + m_RelativeMeter->GetW() + m_X; + } + } + return m_X; +} + +/* +** Returns the Y-position of the meter. +** +*/ +int Meter::GetY(bool abs) +{ + if (m_RelativeY != POSITION_ABSOLUTE && m_RelativeMeter) + { + if (m_RelativeY == POSITION_RELATIVE_TL) + { + return m_RelativeMeter->GetY(true) + m_Y; + } + else + { + return m_RelativeMeter->GetY(true) + m_RelativeMeter->GetH() + m_Y; + } + } + return m_Y; +} + +void Meter::SetX(int x) +{ + m_X = x; + m_RelativeX = POSITION_ABSOLUTE; + + // Change the option as well to avoid reset in ReadOptions(). + WCHAR buffer[32]; + _itow_s(x, buffer, 10); + m_MeterWindow->GetParser().SetValue(m_Name, L"X", buffer); +} + +void Meter::SetY(int y) +{ + m_Y = y; + m_RelativeY = POSITION_ABSOLUTE; + + // Change the option as well to avoid reset in ReadOptions(). + WCHAR buffer[32]; + _itow_s(y, buffer, 10); + m_MeterWindow->GetParser().SetValue(m_Name, L"Y", buffer); +} + +/* +** Returns a RECT containing the dimensions of the meter within the MeterWindow +** +*/ +RECT Meter::GetMeterRect() +{ + RECT meterRect; + + meterRect.left = GetX(); + meterRect.top = GetY(); + meterRect.right = meterRect.left + m_W; + meterRect.bottom = meterRect.top + m_H; + + return meterRect; +} + +/* +** Returns a Rect containing the adjusted meter location with "Padding" option +** +*/ +Gdiplus::Rect Meter::GetMeterRectPadding() +{ + Gdiplus::Rect meterRect; + + meterRect.X = GetX() + m_Padding.X; + meterRect.Y = GetY() + m_Padding.Y; + meterRect.Width = m_W - m_Padding.X - m_Padding.Width; + meterRect.Height = m_H - m_Padding.Y - m_Padding.Height; + + return meterRect; +} + +/* +** Checks if the given point is inside the meter. +** This function doesn't check Hidden state, so check it before calling this function if needed. +** +*/ +bool Meter::HitTest(int x, int y) +{ + int p; + return (x >= (p = GetX()) && x < p + m_W && y >= (p = GetY()) && y < p + m_H); +} + +/* +** Shows the meter and tooltip. +** +*/ +void Meter::Show() +{ + m_Hidden = false; + + // Change the option as well to avoid reset in ReadOptions(). + m_MeterWindow->GetParser().SetValue(m_Name, L"Hidden", L"0"); + + if (m_ToolTipHandle != nullptr) + { + if (!m_ToolTipHidden) + { + SendMessage(m_ToolTipHandle, TTM_ACTIVATE, TRUE, 0); + } + } +} + +/* +** Hides the meter and tooltip. +** +*/ +void Meter::Hide() +{ + m_Hidden = true; + + // Change the option as well to avoid reset in ReadOptions(). + m_MeterWindow->GetParser().SetValue(m_Name, L"Hidden", L"1"); + + if (m_ToolTipHandle != nullptr) + { + SendMessage(m_ToolTipHandle, TTM_ACTIVATE, FALSE, 0); + } +} + +/* +** Read the common options specified in the ini file. The inherited classes must +** call this base implementation if they overwrite this method. +** +*/ +void Meter::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + // The MeterStyle defines a template where the values are read if the meter doesn't have it itself + const std::wstring& style = parser.ReadString(section, L"MeterStyle", L""); + if (!style.empty()) + { + parser.SetStyleTemplate(style); + } + + Section::ReadOptions(parser, section); + + BindMeasures(parser, section); + + int oldX = m_X; + std::wstring& x = (std::wstring&)parser.ReadString(section, L"X", L"0"); + if (!x.empty()) + { + WCHAR lastChar = x[x.size() - 1]; + if (lastChar == L'r') + { + m_RelativeX = POSITION_RELATIVE_TL; + x.pop_back(); + } + else if (lastChar == L'R') + { + m_RelativeX = POSITION_RELATIVE_BR; + x.pop_back(); + } + else + { + m_RelativeX = POSITION_ABSOLUTE; + } + + m_X = parser.ParseInt(x.c_str(), 0); + } + else + { + m_X = 0; + m_RelativeX = POSITION_ABSOLUTE; + } + + int oldY = m_Y; + std::wstring& y = (std::wstring&)parser.ReadString(section, L"Y", L"0"); + if (!y.empty()) + { + WCHAR lastChar = y[y.size() - 1]; + if (lastChar == L'r') + { + m_RelativeY = POSITION_RELATIVE_TL; + y.pop_back(); + } + else if (lastChar == L'R') + { + m_RelativeY = POSITION_RELATIVE_BR; + y.pop_back(); + } + else + { + m_RelativeY = POSITION_ABSOLUTE; + } + + m_Y = parser.ParseInt(y.c_str(), 0); + } + else + { + m_Y = 0; + m_RelativeY = POSITION_ABSOLUTE; + } + + static const Gdiplus::Rect defPadding; + m_Padding = parser.ReadRect(section, L"Padding", defPadding); + + const int oldW = m_W; + const bool oldWDefined = m_WDefined; + const int widthPadding = GetWidthPadding(); + + const int w = parser.ReadInt(section, L"W", m_W); + m_WDefined = parser.GetLastValueDefined(); + + if (IsFixedSize(true)) m_W = w; + if (oldW != (m_W - widthPadding)) m_W += widthPadding; + if (!m_WDefined && oldWDefined && IsFixedSize()) + { + m_W = 0; + } + + const int oldH = m_H; + const bool oldHDefined = m_HDefined; + const int heightPadding = GetHeightPadding(); + + const int h = parser.ReadInt(section, L"H", m_H); + m_HDefined = parser.GetLastValueDefined(); + + if (IsFixedSize(true)) m_H = h; + if (oldH != (m_H - heightPadding)) m_H += heightPadding; + if (!m_HDefined && oldHDefined && IsFixedSize()) + { + m_H = 0; + } + + bool oldHidden = m_Hidden; + m_Hidden = parser.ReadBool(section, L"Hidden", false); + + if (oldX != m_X || oldY != m_Y || oldHidden != m_Hidden) + { + m_MeterWindow->SetResizeWindowMode(RESIZEMODE_CHECK); // Need to recalculate the window size + } + + m_SolidBevel = (BEVELTYPE)parser.ReadInt(section, L"BevelType", BEVELTYPE_NONE); + + m_SolidColor = parser.ReadColor(section, L"SolidColor", Color::MakeARGB(0, 0, 0, 0)); + m_SolidColor2 = parser.ReadColor(section, L"SolidColor2", m_SolidColor.GetValue()); + m_SolidAngle = (Gdiplus::REAL)parser.ReadFloat(section, L"GradientAngle", 0.0); + + m_Mouse.ReadOptions(parser, section); + m_HasMouseAction = m_Mouse.HasButtonAction() || m_Mouse.HasScrollAction(); + + m_ToolTipText = parser.ReadString(section, L"ToolTipText", L""); + m_ToolTipTitle = parser.ReadString(section, L"ToolTipTitle", L""); + m_ToolTipIcon = parser.ReadString(section, L"ToolTipIcon", L""); + m_ToolTipWidth = parser.ReadInt(section, L"ToolTipWidth", 1000); + m_ToolTipType = parser.ReadBool(section, L"ToolTipType", false); + m_ToolTipHidden = parser.ReadBool(section, L"ToolTipHidden", m_MeterWindow->GetMeterToolTipHidden()); + + m_AntiAlias = parser.ReadBool(section, L"AntiAlias", false); + + std::vector matrix = parser.ReadFloats(section, L"TransformationMatrix"); + if (matrix.size() == 6) + { + if (m_Transformation) + { + m_Transformation->SetElements(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); + } + else + { + m_Transformation = new Matrix(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); + } + } + else if (!matrix.empty()) + { + delete m_Transformation; + m_Transformation = nullptr; + + LogErrorF(this, L"Meter: Incorrect number of values in TransformationMatrix=%s", parser.ReadString(section, L"TransformationMatrix", L"").c_str()); + } +} + +/* +** Binds this meter to the given measure. The same measure can be bound to +** several meters but one meter and only be bound to one measure. +** +*/ +void Meter::BindMeasures(ConfigParser& parser, const WCHAR* section) +{ + BindPrimaryMeasure(parser, section, false); +} + +/* +** Creates the given meter. This is the factory method for the meters. +** If new meters are implemented this method needs to be updated. +** +*/ +Meter* Meter::Create(const WCHAR* meter, MeterWindow* meterWindow, const WCHAR* name) +{ + if (_wcsicmp(L"STRING", meter) == 0) + { + return new MeterString(meterWindow, name); + } + else if (_wcsicmp(L"IMAGE", meter) == 0) + { + return new MeterImage(meterWindow, name); + } + else if (_wcsicmp(L"HISTOGRAM", meter) == 0) + { + return new MeterHistogram(meterWindow, name); + } + else if (_wcsicmp(L"BAR", meter) == 0) + { + return new MeterBar(meterWindow, name); + } + else if (_wcsicmp(L"BITMAP", meter) == 0) + { + return new MeterBitmap(meterWindow, name); + } + else if (_wcsicmp(L"LINE", meter) == 0) + { + return new MeterLine(meterWindow, name); + } + else if (_wcsicmp(L"ROUNDLINE", meter) == 0) + { + return new MeterRoundLine(meterWindow, name); + } + else if (_wcsicmp(L"ROTATOR", meter) == 0) + { + return new MeterRotator(meterWindow, name); + } + else if (_wcsicmp(L"BUTTON", meter) == 0) + { + return new MeterButton(meterWindow, name); + } + + LogErrorF(meterWindow, L"Meter=%s is not valid in [%s]", meter, name); + + return nullptr; +} + +/* +** Updates the value(s) from the measures. Derived classes should +** only update if this returns true; +*/ +bool Meter::Update() +{ + // Only update the meter's value when the divider is equal to the counter + return UpdateCounter(); +} + +/* +** Reads and binds the primary MeasureName. This must always be called in overridden +** BindMeasures() implementations. +** +*/ +bool Meter::BindPrimaryMeasure(ConfigParser& parser, const WCHAR* section, bool optional) +{ + m_Measures.clear(); + + const std::wstring& measureName = parser.ReadString(section, L"MeasureName", L""); + + Measure* measure = parser.GetMeasure(measureName); + if (measure) + { + m_Measures.push_back(measure); + return true; + } + else if (!optional) + { + LogErrorF(this, L"MeasureName=%s is not valid", measureName.c_str()); + } + + return false; +} + +/* +** Reads and binds secondary measures (MeasureName2 - MeasureNameN). +** +*/ +void Meter::BindSecondaryMeasures(ConfigParser& parser, const WCHAR* section) +{ + if (!m_Measures.empty()) + { + WCHAR tmpName[64]; + + int i = 2; + do + { + _snwprintf_s(tmpName, _TRUNCATE, L"MeasureName%i", i); + const std::wstring& measureName = parser.ReadString(section, tmpName, L""); + Measure* measure = parser.GetMeasure(measureName); + if (measure) + { + m_Measures.push_back(measure); + } + else + { + if (!measureName.empty()) + { + LogErrorF(this, L"MeasureName%i=%s is not valid", i, measureName.c_str()); + } + + break; + } + ++i; + } + while (true); + } +} + +/* +** Replaces %1, %2, ... with the corresponding measure value. +** +*/ +bool Meter::ReplaceMeasures(std::wstring& str, AUTOSCALE autoScale, double scale, int decimals, bool percentual) +{ + bool replaced = false; + + if (str.find(L'%') != std::wstring::npos) + { + WCHAR buffer[64]; + + for (size_t i = m_Measures.size(); i > 0; --i) + { + size_t len = _snwprintf_s(buffer, _TRUNCATE, L"%%%i", (int)i); + size_t start = 0, pos; + + const WCHAR* measureValue = m_Measures[i - 1]->GetStringOrFormattedValue( + autoScale, scale, decimals, percentual); + const size_t measureValueLen = wcslen(measureValue); + + do + { + pos = str.find(buffer, start, len); + if (pos != std::wstring::npos) + { + str.replace(pos, len, measureValue, measureValueLen); + start = pos + measureValueLen; + replaced = true; + } + } + while (pos != std::wstring::npos); + } + } + + return replaced; +} + +/* +** Does the initial construction of the ToolTip for the meter +*/ +void Meter::CreateToolTip(MeterWindow* meterWindow) +{ + HWND hMeterWindow = m_MeterWindow->GetWindow(); + HINSTANCE hInstance = Rainmeter::GetInstance().GetModuleInstance(); + DWORD style = WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP; + + if (m_ToolTipType) + { + style |= TTS_BALLOON; + } + + HWND hwndTT = CreateWindowEx(WS_EX_TOPMOST, + TOOLTIPS_CLASS, + nullptr, + style, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + hMeterWindow, + nullptr, + hInstance, + nullptr); + + if (hwndTT) + { + SetWindowPos(hwndTT, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + + TOOLINFO ti = {sizeof(TOOLINFO), TTF_SUBCLASS, hMeterWindow, 0, GetMeterRect(), hInstance}; + + SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM)&ti); + + m_ToolTipHandle = hwndTT; + UpdateToolTip(); + } +} + +/* +** Updates the ToolTip to match new values +*/ +void Meter::UpdateToolTip() +{ + HWND hwndTT = m_ToolTipHandle; + + TOOLINFO ti = {sizeof(TOOLINFO)}; + ti.hwnd = m_MeterWindow->GetWindow(); + + SendMessage(hwndTT, TTM_GETTOOLINFO, 0, (LPARAM)&ti); + + std::wstring text = m_ToolTipText; + ReplaceMeasures(text); + ti.lpszText = (LPTSTR)text.c_str(); + ti.rect = GetMeterRect(); + + SendMessage(hwndTT, TTM_SETTOOLINFO, 0, (LPARAM)&ti); + SendMessage(hwndTT, TTM_SETMAXTIPWIDTH, 0, m_ToolTipWidth); + + if (!m_ToolTipTitle.empty()) + { + HICON hIcon = nullptr; + bool destroy = false; + + if (!m_ToolTipIcon.empty()) + { + const WCHAR* tipIcon = m_ToolTipIcon.c_str(); + if (_wcsicmp(tipIcon, L"INFO") == 0) + { + hIcon = (HICON)TTI_INFO; + } + else if (_wcsicmp(tipIcon, L"WARNING") == 0) + { + hIcon = (HICON)TTI_WARNING; + } + else if (_wcsicmp(tipIcon, L"ERROR") == 0) + { + hIcon = (HICON)TTI_ERROR; + } + else if (_wcsicmp(tipIcon, L"QUESTION") == 0) + { + hIcon = LoadIcon(nullptr, IDI_QUESTION); + } + else if (_wcsicmp(tipIcon, L"SHIELD") == 0) + { + hIcon = LoadIcon(nullptr, IDI_SHIELD); + } + else + { + std::wstring iconPath = m_ToolTipIcon; + m_MeterWindow->MakePathAbsolute(iconPath); + hIcon = (HICON)LoadImage(nullptr, iconPath.c_str(), IMAGE_ICON, 0, 0, LR_LOADFROMFILE); + destroy = true; + } + } + + text = m_ToolTipTitle; + ReplaceMeasures(text); + SendMessage(hwndTT, TTM_SETTITLE, (WPARAM)hIcon, (LPARAM)text.c_str()); + + if (destroy) + { + DestroyIcon(hIcon); + } + } + + if (m_ToolTipHidden) + { + SendMessage(hwndTT, TTM_ACTIVATE, FALSE, 0); + } + else + { + SendMessage(hwndTT, TTM_ACTIVATE, !IsHidden(), 0); + } +} + +/* +** Draws the solid background & bevel if such are defined +*/ +bool Meter::Draw(Gfx::Canvas& canvas) +{ + if (IsHidden()) return false; + + canvas.SetAntiAliasing(m_AntiAlias); + + if (m_SolidColor.GetA() != 0 || m_SolidColor2.GetA() != 0) + { + int x = GetX(); + int y = GetY(); + + Rect r(x, y, m_W, m_H); + + if (m_SolidColor.GetValue() == m_SolidColor2.GetValue()) + { + SolidBrush solid(m_SolidColor); + canvas.FillRectangle(r, solid); + } + else + { + Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); + + if (!m_AntiAlias) + { + // Fix the tiling issue in some GradientAngle values + graphics.SetPixelOffsetMode(PixelOffsetModeHalf); + } + + LinearGradientBrush gradient(r, m_SolidColor, m_SolidColor2, m_SolidAngle, TRUE); + graphics.FillRectangle(&gradient, r); + + if (!m_AntiAlias) + { + graphics.SetPixelOffsetMode(PixelOffsetModeDefault); + } + + canvas.EndGdiplusContext(); + } + } + + if (m_SolidBevel != BEVELTYPE_NONE) + { + Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); + + int x = GetX(); + int y = GetY(); + + Color lightColor(255, 255, 255, 255); + Color darkColor(255, 0, 0, 0); + + if (m_SolidBevel == BEVELTYPE_DOWN) + { + lightColor.SetValue(Color::MakeARGB(255, 0, 0, 0)); + darkColor.SetValue(Color::MakeARGB(255, 255, 255, 255)); + } + + Pen light(lightColor); + Pen dark(darkColor); + + // The bevel is drawn outside the meter + Rect rect(x - 2, y - 2, m_W + 4, m_H + 4); + DrawBevel(graphics, rect, light, dark); + + canvas.EndGdiplusContext(); + } + + return true; +} + +/* +** Draws a bevel inside the given area +*/ +void Meter::DrawBevel(Graphics& graphics, const Rect& rect, const Pen& light, const Pen& dark) +{ + int l = rect.GetLeft(); + int r = rect.GetRight() - 1; + int t = rect.GetTop(); + int b = rect.GetBottom() - 1; + + graphics.DrawLine(&light, l, t, l, b); + graphics.DrawLine(&light, l, t, r, t); + graphics.DrawLine(&light, l + 1, t + 1, l + 1, b - 1); + graphics.DrawLine(&light, l + 1, t + 1, r - 1, t + 1); + graphics.DrawLine(&dark, l, b, r, b); + graphics.DrawLine(&dark, r, t, r, b); + graphics.DrawLine(&dark, l + 1, b - 1, r - 1, b - 1); + graphics.DrawLine(&dark, r - 1, t + 1, r - 1, b - 1); +} diff --git a/Library/Meter.h b/Library/Meter.h index 5b0bb243..55531288 100644 --- a/Library/Meter.h +++ b/Library/Meter.h @@ -1,161 +1,161 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __METER_H__ -#define __METER_H__ - -#include -#include // For Gdiplus.h. -#include -#include -#include -#include "Litestep.h" -#include "ConfigParser.h" -#include "MeterWindow.h" -#include "Section.h" -#include "Measure.h" - -class Measure; - -class __declspec(novtable) Meter : public Section -{ -public: - virtual ~Meter(); - - Meter(const Meter& other) = delete; - - void ReadOptions(ConfigParser& parser) { ReadOptions(parser, GetName()); parser.ClearStyleTemplate(); } - - virtual void Initialize(); - virtual bool Update(); - virtual bool Draw(Gfx::Canvas& canvas); - virtual bool HasActiveTransition() { return false; } - - virtual int GetW() { return m_Hidden ? 0 : m_W; } - virtual int GetH() { return m_Hidden ? 0 : m_H; } - virtual int GetX(bool abs = false); - virtual int GetY(bool abs = false); - RECT GetMeterRect(); - - Gdiplus::Rect GetMeterRectPadding(); - int GetWidthPadding() { return m_Padding.X + m_Padding.Width; } - int GetHeightPadding() { return m_Padding.Y + m_Padding.Height; } - - void SetW(int w) { m_W = w; } - void SetH(int h) { m_H = h; } - void SetX(int x); - void SetY(int y); - - void SetRelativeMeter(Meter* meter) { m_RelativeMeter = meter; } - - const Mouse& GetMouse() { return m_Mouse; } - bool HasMouseAction() { return m_HasMouseAction; } - - const std::wstring& GetToolTipText() { return m_ToolTipText; } - bool HasToolTip() { return m_ToolTipHandle != nullptr; } - - void CreateToolTip(MeterWindow* meterWindow); - void UpdateToolTip(); - - void Hide(); - void Show(); - bool IsHidden() { return m_Hidden; } - - const Gdiplus::Matrix* GetTransformationMatrix() { return m_Transformation; } - - virtual bool HitTest(int x, int y); - - void SetMouseOver(bool over) { m_MouseOver = over; } - bool IsMouseOver() { return m_MouseOver; } - - static Meter* Create(const WCHAR* meter, MeterWindow* meterWindow, const WCHAR* name); - - static void DrawBevel(Gdiplus::Graphics& graphics, const Gdiplus::Rect& rect, const Gdiplus::Pen& light, const Gdiplus::Pen& dark); - -protected: - - enum METER_ALIGNMENT - { - ALIGN_LEFT, // Same as LeftTop - ALIGN_RIGHT, // Same as RightTop - ALIGN_CENTER, // Same as CenterTop - ALIGN_LEFTBOTTOM, - ALIGN_RIGHTBOTTOM, - ALIGN_CENTERBOTTOM, - ALIGN_LEFTCENTER, - ALIGN_RIGHTCENTER, - ALIGN_CENTERCENTER - }; - - enum METER_POSITION - { - POSITION_ABSOLUTE, - POSITION_RELATIVE_TL, - POSITION_RELATIVE_BR - }; - - Meter(MeterWindow* meterWindow, const WCHAR* name); - - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void BindMeasures(ConfigParser& parser, const WCHAR* section); - - virtual bool IsFixedSize(bool overwrite = false) { return true; } - - bool BindPrimaryMeasure(ConfigParser& parser, const WCHAR* section, bool optional); - void BindSecondaryMeasures(ConfigParser& parser, const WCHAR* section); - - bool ReplaceMeasures(std::wstring& str, AUTOSCALE autoScale = AUTOSCALE_ON, double scale = 1.0, int decimals = 0, bool percentual = false); - - std::vector m_Measures; - int m_X; - int m_Y; - int m_W; - int m_H; - bool m_Hidden; - bool m_WDefined; - bool m_HDefined; - Meter* m_RelativeMeter; - - Gdiplus::Matrix* m_Transformation; - - std::wstring m_ToolTipText; - std::wstring m_ToolTipTitle; - std::wstring m_ToolTipIcon; - unsigned int m_ToolTipWidth; - bool m_ToolTipType; - bool m_ToolTipHidden; - - HWND m_ToolTipHandle; - - Mouse m_Mouse; - bool m_HasMouseAction; - bool m_MouseOver; - - METER_POSITION m_RelativeX; - METER_POSITION m_RelativeY; - - BEVELTYPE m_SolidBevel; - Gdiplus::Color m_SolidColor; - Gdiplus::Color m_SolidColor2; - Gdiplus::REAL m_SolidAngle; - Gdiplus::Rect m_Padding; - bool m_AntiAlias; - bool m_Initialized; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __METER_H__ +#define __METER_H__ + +#include +#include // For Gdiplus.h. +#include +#include +#include +#include "Litestep.h" +#include "ConfigParser.h" +#include "MeterWindow.h" +#include "Section.h" +#include "Measure.h" + +class Measure; + +class __declspec(novtable) Meter : public Section +{ +public: + virtual ~Meter(); + + Meter(const Meter& other) = delete; + + void ReadOptions(ConfigParser& parser) { ReadOptions(parser, GetName()); parser.ClearStyleTemplate(); } + + virtual void Initialize(); + virtual bool Update(); + virtual bool Draw(Gfx::Canvas& canvas); + virtual bool HasActiveTransition() { return false; } + + virtual int GetW() { return m_Hidden ? 0 : m_W; } + virtual int GetH() { return m_Hidden ? 0 : m_H; } + virtual int GetX(bool abs = false); + virtual int GetY(bool abs = false); + RECT GetMeterRect(); + + Gdiplus::Rect GetMeterRectPadding(); + int GetWidthPadding() { return m_Padding.X + m_Padding.Width; } + int GetHeightPadding() { return m_Padding.Y + m_Padding.Height; } + + void SetW(int w) { m_W = w; } + void SetH(int h) { m_H = h; } + void SetX(int x); + void SetY(int y); + + void SetRelativeMeter(Meter* meter) { m_RelativeMeter = meter; } + + const Mouse& GetMouse() { return m_Mouse; } + bool HasMouseAction() { return m_HasMouseAction; } + + const std::wstring& GetToolTipText() { return m_ToolTipText; } + bool HasToolTip() { return m_ToolTipHandle != nullptr; } + + void CreateToolTip(MeterWindow* meterWindow); + void UpdateToolTip(); + + void Hide(); + void Show(); + bool IsHidden() { return m_Hidden; } + + const Gdiplus::Matrix* GetTransformationMatrix() { return m_Transformation; } + + virtual bool HitTest(int x, int y); + + void SetMouseOver(bool over) { m_MouseOver = over; } + bool IsMouseOver() { return m_MouseOver; } + + static Meter* Create(const WCHAR* meter, MeterWindow* meterWindow, const WCHAR* name); + + static void DrawBevel(Gdiplus::Graphics& graphics, const Gdiplus::Rect& rect, const Gdiplus::Pen& light, const Gdiplus::Pen& dark); + +protected: + + enum METER_ALIGNMENT + { + ALIGN_LEFT, // Same as LeftTop + ALIGN_RIGHT, // Same as RightTop + ALIGN_CENTER, // Same as CenterTop + ALIGN_LEFTBOTTOM, + ALIGN_RIGHTBOTTOM, + ALIGN_CENTERBOTTOM, + ALIGN_LEFTCENTER, + ALIGN_RIGHTCENTER, + ALIGN_CENTERCENTER + }; + + enum METER_POSITION + { + POSITION_ABSOLUTE, + POSITION_RELATIVE_TL, + POSITION_RELATIVE_BR + }; + + Meter(MeterWindow* meterWindow, const WCHAR* name); + + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void BindMeasures(ConfigParser& parser, const WCHAR* section); + + virtual bool IsFixedSize(bool overwrite = false) { return true; } + + bool BindPrimaryMeasure(ConfigParser& parser, const WCHAR* section, bool optional); + void BindSecondaryMeasures(ConfigParser& parser, const WCHAR* section); + + bool ReplaceMeasures(std::wstring& str, AUTOSCALE autoScale = AUTOSCALE_ON, double scale = 1.0, int decimals = 0, bool percentual = false); + + std::vector m_Measures; + int m_X; + int m_Y; + int m_W; + int m_H; + bool m_Hidden; + bool m_WDefined; + bool m_HDefined; + Meter* m_RelativeMeter; + + Gdiplus::Matrix* m_Transformation; + + std::wstring m_ToolTipText; + std::wstring m_ToolTipTitle; + std::wstring m_ToolTipIcon; + unsigned int m_ToolTipWidth; + bool m_ToolTipType; + bool m_ToolTipHidden; + + HWND m_ToolTipHandle; + + Mouse m_Mouse; + bool m_HasMouseAction; + bool m_MouseOver; + + METER_POSITION m_RelativeX; + METER_POSITION m_RelativeY; + + BEVELTYPE m_SolidBevel; + Gdiplus::Color m_SolidColor; + Gdiplus::Color m_SolidColor2; + Gdiplus::REAL m_SolidAngle; + Gdiplus::Rect m_Padding; + bool m_AntiAlias; + bool m_Initialized; +}; + +#endif diff --git a/Library/MeterBar.cpp b/Library/MeterBar.cpp index 28a565a7..29b1bef3 100644 --- a/Library/MeterBar.cpp +++ b/Library/MeterBar.cpp @@ -1,272 +1,272 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeterBar.h" -#include "Measure.h" -#include "Error.h" -#include "Litestep.h" -#include "Rainmeter.h" -#include "../Common/Gfx/Canvas.h" - -using namespace Gdiplus; - -/* -** The constructor -** -*/ -MeterBar::MeterBar(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), - m_Image(L"BarImage", nullptr, false, meterWindow), - m_NeedsReload(false), - m_Color(Color::Green), - m_Orientation(VERTICAL), - m_Value(), - m_Border(), - m_Flip(false) -{ -} - -/* -** The destructor -** -*/ -MeterBar::~MeterBar() -{ -} - -/* -** Load the image or create the brush. If image is used get the dimensions -** of the meter from it. -** -*/ -void MeterBar::Initialize() -{ - Meter::Initialize(); - - // Load the bitmaps if defined - if (!m_ImageName.empty()) - { - m_Image.LoadImage(m_ImageName, m_NeedsReload); - - if (m_Image.IsLoaded()) - { - Bitmap* bitmap = m_Image.GetImage(); - - m_W = bitmap->GetWidth() + GetWidthPadding(); - m_H = bitmap->GetHeight() + GetHeightPadding(); - } - } - else if (m_Image.IsLoaded()) - { - m_Image.DisposeImage(); - } -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeterBar::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - // Store the current values so we know if the image needs to be updated - std::wstring oldImageName = m_ImageName; - int oldW = m_W; - int oldH = m_H; - - Meter::ReadOptions(parser, section); - - m_Color = parser.ReadColor(section, L"BarColor", Color::Green); - - m_ImageName = parser.ReadString(section, L"BarImage", L""); - if (!m_ImageName.empty()) - { - // Read tinting options - m_Image.ReadOptions(parser, section); - } - else - { - m_Image.ClearOptionFlags(); - } - - m_Border = parser.ReadInt(section, L"BarBorder", 0); - - m_Flip = parser.ReadBool(section, L"Flip", false); - - const WCHAR* orientation = parser.ReadString(section, L"BarOrientation", L"VERTICAL").c_str(); - if (_wcsicmp(L"VERTICAL", orientation) == 0) - { - m_Orientation = VERTICAL; - } - else if (_wcsicmp(L"HORIZONTAL", orientation) == 0) - { - m_Orientation = HORIZONTAL; - } - else - { - LogErrorF(this, L"BarOrientation=%s is not valid", orientation); - } - - if (m_Initialized) - { - m_NeedsReload = (wcscmp(oldImageName.c_str(), m_ImageName.c_str()) != 0); - - if (m_NeedsReload || - m_Image.IsOptionsChanged()) - { - Initialize(); // Reload the image - } - else if (!m_ImageName.empty()) - { - // Reset to old dimensions - m_W = oldW; - m_H = oldH; - } - } -} - -/* -** Updates the value(s) from the measures. -** -*/ -bool MeterBar::Update() -{ - if (Meter::Update() && !m_Measures.empty()) - { - m_Value = m_Measures[0]->GetRelativeValue(); - return true; - } - return false; -} - -/* -** Draws the meter on the double buffer -** -*/ -bool MeterBar::Draw(Gfx::Canvas& canvas) -{ - if (!Meter::Draw(canvas)) return false; - - Gdiplus::Rect meterRect = GetMeterRectPadding(); - - Bitmap* drawBitmap = m_Image.GetImage(); - - if (m_Orientation == VERTICAL) - { - int barSize = meterRect.Height - 2 * m_Border; - int size = (int)(barSize * m_Value); - size = min(barSize, size); - size = max(0, size); - - if (drawBitmap) - { - if (m_Flip) - { - if (m_Border > 0) - { - Rect r2(meterRect.X, meterRect.Y, meterRect.Width, m_Border); - canvas.DrawBitmap(drawBitmap, r2, Rect(0, 0, meterRect.Width, m_Border)); - r2.Y = meterRect.Y + size + m_Border; - canvas.DrawBitmap(drawBitmap, r2, Rect(0, meterRect.Height - m_Border, meterRect.Width, m_Border)); - } - - Rect r(meterRect.X, meterRect.Y + m_Border, meterRect.Width, size); - canvas.DrawBitmap(drawBitmap, r, Rect(0, m_Border, meterRect.Width, size)); - } - else - { - if (m_Border > 0) - { - Rect r2(meterRect.X, meterRect.Y + meterRect.Height - size - 2 * m_Border, meterRect.Width, m_Border); - canvas.DrawBitmap(drawBitmap, r2, Rect(0, 0, meterRect.Width, m_Border)); - r2.Y = meterRect.Y + meterRect.Height - m_Border; - canvas.DrawBitmap(drawBitmap, r2, Rect(0, meterRect.Height - m_Border, meterRect.Width, m_Border)); - } - - Rect r(meterRect.X, meterRect.Y + meterRect.Height - size - m_Border, meterRect.Width, size); - canvas.DrawBitmap(drawBitmap, r, Rect(0, meterRect.Height - size - m_Border, meterRect.Width, size)); - } - } - else - { - SolidBrush brush(m_Color); - if (m_Flip) - { - Rect r(meterRect.X, meterRect.Y, meterRect.Width, size); - canvas.FillRectangle(r, brush); - } - else - { - Rect r(meterRect.X, meterRect.Y + meterRect.Height - size, meterRect.Width, size); - canvas.FillRectangle(r, brush); - } - } - } - else - { - int barSize = meterRect.Width - 2 * m_Border; - int size = (int)(barSize * m_Value); - size = min(barSize, size); - size = max(0, size); - - if (drawBitmap) - { - if (m_Flip) - { - if (m_Border > 0) - { - Rect r2(meterRect.X + meterRect.Width - size - 2 * m_Border, meterRect.Y, m_Border, meterRect.Height); - canvas.DrawBitmap(drawBitmap, r2, Rect(0, 0, m_Border, meterRect.Height)); - r2.X = meterRect.X + meterRect.Width - m_Border; - canvas.DrawBitmap(drawBitmap, r2, Rect(meterRect.Width - m_Border, 0, m_Border, meterRect.Height)); - } - - Rect r(meterRect.X + meterRect.Width - size - m_Border, meterRect.Y, size, meterRect.Height); - canvas.DrawBitmap(drawBitmap, r, Rect(meterRect.Width - size - m_Border, 0, size, meterRect.Height)); - } - else - { - if (m_Border > 0) - { - Rect r2(meterRect.X, meterRect.Y, m_Border, meterRect.Height); - canvas.DrawBitmap(drawBitmap, r2, Rect(0, 0, m_Border, meterRect.Height)); - r2.X = meterRect.X + size + m_Border; - canvas.DrawBitmap(drawBitmap, r2, Rect(meterRect.Width - m_Border, 0, m_Border, meterRect.Height)); - } - - Rect r(meterRect.X + m_Border, meterRect.Y, size, meterRect.Height); - canvas.DrawBitmap(drawBitmap, r, Rect(m_Border, 0, size, meterRect.Height)); - } - } - else - { - SolidBrush brush(m_Color); - if (m_Flip) - { - Rect r(meterRect.X + meterRect.Width - size, meterRect.Y, size, meterRect.Height); - canvas.FillRectangle(r, brush); - } - else - { - Rect r(meterRect.X, meterRect.Y, size, meterRect.Height); - canvas.FillRectangle(r, brush); - } - } - } - - return true; -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeterBar.h" +#include "Measure.h" +#include "Error.h" +#include "Litestep.h" +#include "Rainmeter.h" +#include "../Common/Gfx/Canvas.h" + +using namespace Gdiplus; + +/* +** The constructor +** +*/ +MeterBar::MeterBar(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), + m_Image(L"BarImage", nullptr, false, meterWindow), + m_NeedsReload(false), + m_Color(Color::Green), + m_Orientation(VERTICAL), + m_Value(), + m_Border(), + m_Flip(false) +{ +} + +/* +** The destructor +** +*/ +MeterBar::~MeterBar() +{ +} + +/* +** Load the image or create the brush. If image is used get the dimensions +** of the meter from it. +** +*/ +void MeterBar::Initialize() +{ + Meter::Initialize(); + + // Load the bitmaps if defined + if (!m_ImageName.empty()) + { + m_Image.LoadImage(m_ImageName, m_NeedsReload); + + if (m_Image.IsLoaded()) + { + Bitmap* bitmap = m_Image.GetImage(); + + m_W = bitmap->GetWidth() + GetWidthPadding(); + m_H = bitmap->GetHeight() + GetHeightPadding(); + } + } + else if (m_Image.IsLoaded()) + { + m_Image.DisposeImage(); + } +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeterBar::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + // Store the current values so we know if the image needs to be updated + std::wstring oldImageName = m_ImageName; + int oldW = m_W; + int oldH = m_H; + + Meter::ReadOptions(parser, section); + + m_Color = parser.ReadColor(section, L"BarColor", Color::Green); + + m_ImageName = parser.ReadString(section, L"BarImage", L""); + if (!m_ImageName.empty()) + { + // Read tinting options + m_Image.ReadOptions(parser, section); + } + else + { + m_Image.ClearOptionFlags(); + } + + m_Border = parser.ReadInt(section, L"BarBorder", 0); + + m_Flip = parser.ReadBool(section, L"Flip", false); + + const WCHAR* orientation = parser.ReadString(section, L"BarOrientation", L"VERTICAL").c_str(); + if (_wcsicmp(L"VERTICAL", orientation) == 0) + { + m_Orientation = VERTICAL; + } + else if (_wcsicmp(L"HORIZONTAL", orientation) == 0) + { + m_Orientation = HORIZONTAL; + } + else + { + LogErrorF(this, L"BarOrientation=%s is not valid", orientation); + } + + if (m_Initialized) + { + m_NeedsReload = (wcscmp(oldImageName.c_str(), m_ImageName.c_str()) != 0); + + if (m_NeedsReload || + m_Image.IsOptionsChanged()) + { + Initialize(); // Reload the image + } + else if (!m_ImageName.empty()) + { + // Reset to old dimensions + m_W = oldW; + m_H = oldH; + } + } +} + +/* +** Updates the value(s) from the measures. +** +*/ +bool MeterBar::Update() +{ + if (Meter::Update() && !m_Measures.empty()) + { + m_Value = m_Measures[0]->GetRelativeValue(); + return true; + } + return false; +} + +/* +** Draws the meter on the double buffer +** +*/ +bool MeterBar::Draw(Gfx::Canvas& canvas) +{ + if (!Meter::Draw(canvas)) return false; + + Gdiplus::Rect meterRect = GetMeterRectPadding(); + + Bitmap* drawBitmap = m_Image.GetImage(); + + if (m_Orientation == VERTICAL) + { + int barSize = meterRect.Height - 2 * m_Border; + int size = (int)(barSize * m_Value); + size = min(barSize, size); + size = max(0, size); + + if (drawBitmap) + { + if (m_Flip) + { + if (m_Border > 0) + { + Rect r2(meterRect.X, meterRect.Y, meterRect.Width, m_Border); + canvas.DrawBitmap(drawBitmap, r2, Rect(0, 0, meterRect.Width, m_Border)); + r2.Y = meterRect.Y + size + m_Border; + canvas.DrawBitmap(drawBitmap, r2, Rect(0, meterRect.Height - m_Border, meterRect.Width, m_Border)); + } + + Rect r(meterRect.X, meterRect.Y + m_Border, meterRect.Width, size); + canvas.DrawBitmap(drawBitmap, r, Rect(0, m_Border, meterRect.Width, size)); + } + else + { + if (m_Border > 0) + { + Rect r2(meterRect.X, meterRect.Y + meterRect.Height - size - 2 * m_Border, meterRect.Width, m_Border); + canvas.DrawBitmap(drawBitmap, r2, Rect(0, 0, meterRect.Width, m_Border)); + r2.Y = meterRect.Y + meterRect.Height - m_Border; + canvas.DrawBitmap(drawBitmap, r2, Rect(0, meterRect.Height - m_Border, meterRect.Width, m_Border)); + } + + Rect r(meterRect.X, meterRect.Y + meterRect.Height - size - m_Border, meterRect.Width, size); + canvas.DrawBitmap(drawBitmap, r, Rect(0, meterRect.Height - size - m_Border, meterRect.Width, size)); + } + } + else + { + SolidBrush brush(m_Color); + if (m_Flip) + { + Rect r(meterRect.X, meterRect.Y, meterRect.Width, size); + canvas.FillRectangle(r, brush); + } + else + { + Rect r(meterRect.X, meterRect.Y + meterRect.Height - size, meterRect.Width, size); + canvas.FillRectangle(r, brush); + } + } + } + else + { + int barSize = meterRect.Width - 2 * m_Border; + int size = (int)(barSize * m_Value); + size = min(barSize, size); + size = max(0, size); + + if (drawBitmap) + { + if (m_Flip) + { + if (m_Border > 0) + { + Rect r2(meterRect.X + meterRect.Width - size - 2 * m_Border, meterRect.Y, m_Border, meterRect.Height); + canvas.DrawBitmap(drawBitmap, r2, Rect(0, 0, m_Border, meterRect.Height)); + r2.X = meterRect.X + meterRect.Width - m_Border; + canvas.DrawBitmap(drawBitmap, r2, Rect(meterRect.Width - m_Border, 0, m_Border, meterRect.Height)); + } + + Rect r(meterRect.X + meterRect.Width - size - m_Border, meterRect.Y, size, meterRect.Height); + canvas.DrawBitmap(drawBitmap, r, Rect(meterRect.Width - size - m_Border, 0, size, meterRect.Height)); + } + else + { + if (m_Border > 0) + { + Rect r2(meterRect.X, meterRect.Y, m_Border, meterRect.Height); + canvas.DrawBitmap(drawBitmap, r2, Rect(0, 0, m_Border, meterRect.Height)); + r2.X = meterRect.X + size + m_Border; + canvas.DrawBitmap(drawBitmap, r2, Rect(meterRect.Width - m_Border, 0, m_Border, meterRect.Height)); + } + + Rect r(meterRect.X + m_Border, meterRect.Y, size, meterRect.Height); + canvas.DrawBitmap(drawBitmap, r, Rect(m_Border, 0, size, meterRect.Height)); + } + } + else + { + SolidBrush brush(m_Color); + if (m_Flip) + { + Rect r(meterRect.X + meterRect.Width - size, meterRect.Y, size, meterRect.Height); + canvas.FillRectangle(r, brush); + } + else + { + Rect r(meterRect.X, meterRect.Y, size, meterRect.Height); + canvas.FillRectangle(r, brush); + } + } + } + + return true; +} diff --git a/Library/MeterBar.h b/Library/MeterBar.h index 16434824..59732bbe 100644 --- a/Library/MeterBar.h +++ b/Library/MeterBar.h @@ -1,63 +1,63 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __METERBAR_H__ -#define __METERBAR_H__ - -#include "Meter.h" -#include "TintedImage.h" - -class MeterBar : public Meter -{ -public: - MeterBar(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeterBar(); - - MeterBar(const MeterBar& other) = delete; - MeterBar& operator=(MeterBar other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - virtual void Initialize(); - virtual bool Update(); - virtual bool Draw(Gfx::Canvas& canvas); - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - - virtual bool IsFixedSize(bool overwrite = false) { return m_ImageName.empty(); } - -private: - enum ORIENTATION - { - HORIZONTAL, - VERTICAL - }; - - TintedImage m_Image; - std::wstring m_ImageName; - bool m_NeedsReload; - - Gdiplus::Color m_Color; - ORIENTATION m_Orientation; // Growth direction - double m_Value; - int m_Border; - bool m_Flip; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __METERBAR_H__ +#define __METERBAR_H__ + +#include "Meter.h" +#include "TintedImage.h" + +class MeterBar : public Meter +{ +public: + MeterBar(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeterBar(); + + MeterBar(const MeterBar& other) = delete; + MeterBar& operator=(MeterBar other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + virtual void Initialize(); + virtual bool Update(); + virtual bool Draw(Gfx::Canvas& canvas); + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + + virtual bool IsFixedSize(bool overwrite = false) { return m_ImageName.empty(); } + +private: + enum ORIENTATION + { + HORIZONTAL, + VERTICAL + }; + + TintedImage m_Image; + std::wstring m_ImageName; + bool m_NeedsReload; + + Gdiplus::Color m_Color; + ORIENTATION m_Orientation; // Growth direction + double m_Value; + int m_Border; + bool m_Flip; +}; + +#endif diff --git a/Library/MeterBitmap.cpp b/Library/MeterBitmap.cpp index 5fd7ad4e..f27a2b1f 100644 --- a/Library/MeterBitmap.cpp +++ b/Library/MeterBitmap.cpp @@ -1,450 +1,450 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeterBitmap.h" -#include "Measure.h" -#include "Error.h" -#include "Rainmeter.h" -#include "System.h" -#include "../Common/Gfx/Canvas.h" - -using namespace Gdiplus; - -/* -** The constructor -** -*/ -MeterBitmap::MeterBitmap(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), - m_Image(L"BitmapImage", nullptr, true, meterWindow), - m_NeedsReload(false), - m_ZeroFrame(false), - m_FrameCount(1), - m_TransitionFrameCount(), - m_Align(ALIGN_LEFT), - m_Extend(false), - m_Separation(), - m_Digits(), - m_Value(), - m_TransitionStartTicks(), - m_TransitionStartValue() -{ -} - -/* -** The destructor -** -*/ -MeterBitmap::~MeterBitmap() -{ -} - -/* -** Load the image and get the dimensions of the meter from it. -** -*/ -void MeterBitmap::Initialize() -{ - Meter::Initialize(); - - // Load the bitmaps if defined - if (!m_ImageName.empty()) - { - m_Image.LoadImage(m_ImageName, m_NeedsReload); - - if (m_Image.IsLoaded()) - { - Bitmap* bitmap = m_Image.GetImage(); - - m_W = bitmap->GetWidth(); - m_H = bitmap->GetHeight(); - - if (m_H > m_W) - { - m_H = m_H / m_FrameCount; - } - else - { - m_W = m_W / m_FrameCount; - } - - m_W += GetWidthPadding(); - m_H += GetHeightPadding(); - } - } - else if (m_Image.IsLoaded()) - { - m_Image.DisposeImage(); - } -} - -/* -** Checks if the given point is inside the meter. -** -*/ -bool MeterBitmap::HitTest(int x, int y) -{ - if (m_Extend) - { - // Calc the number of numbers - int numOfNums = 0; - - if (m_Digits > 0) - { - numOfNums = m_Digits; - } - else - { - int tmpValue = (int)m_Value; - tmpValue = max(0, tmpValue); // Only positive integers are supported - - int realFrames = (m_FrameCount / (m_TransitionFrameCount + 1)); - do - { - ++numOfNums; - if (realFrames == 1) - { - tmpValue /= 2; - } - else - { - tmpValue /= realFrames; - } - } - while (tmpValue > 0); - } - - Rect rect(GetX(), GetY(), m_W * numOfNums + (numOfNums - 1) * m_Separation, m_H); - - if (m_Align == ALIGN_CENTER) - { - rect.Offset(-rect.Width / 2, 0); - } - else if (m_Align == ALIGN_RIGHT) - { - rect.Offset(-rect.Width, 0); - } - - if (rect.Contains(x, y)) - { - return true; - } - return false; - } - else - { - return Meter::HitTest(x, y); - } -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeterBitmap::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - // Store the current values so we know if the image needs to be updated - std::wstring oldImageName = m_ImageName; - int oldW = m_W; - int oldH = m_H; - - Meter::ReadOptions(parser, section); - - m_ImageName = parser.ReadString(section, L"BitmapImage", L""); - if (!m_ImageName.empty()) - { - // Read tinting options - m_Image.ReadOptions(parser, section); - } - else - { - m_Image.ClearOptionFlags(); - } - - m_FrameCount = parser.ReadInt(section, L"BitmapFrames", 1); - m_ZeroFrame = parser.ReadBool(section, L"BitmapZeroFrame", false); - - m_Separation = parser.ReadInt(section, L"BitmapSeparation", 0); - m_Extend = parser.ReadBool(section, L"BitmapExtend", false); - m_Digits = parser.ReadInt(section, L"BitmapDigits", 0); - - m_TransitionFrameCount = parser.ReadInt(section, L"BitmapTransitionFrames", 0); - - const WCHAR* align = parser.ReadString(section, L"BitmapAlign", L"LEFT").c_str(); - if (_wcsicmp(align, L"LEFT") == 0) - { - m_Align = ALIGN_LEFT; - } - else if (_wcsicmp(align, L"RIGHT") == 0) - { - m_Align = ALIGN_RIGHT; - } - else if (_wcsicmp(align, L"CENTER") == 0) - { - m_Align = ALIGN_CENTER; - } - else - { - LogErrorF(this, L"BitmapAlign=%s is not valid", align); - } - - if (m_Initialized) - { - m_NeedsReload = (wcscmp(oldImageName.c_str(), m_ImageName.c_str()) != 0); - - if (m_NeedsReload || - m_Image.IsOptionsChanged()) - { - Initialize(); // Reload the image - } - else - { - // Reset to old dimensions - m_W = oldW; - m_H = oldH; - } - } -} - -/* -** Updates the value(s) from the measures. -** -*/ -bool MeterBitmap::Update() -{ - if (Meter::Update() && !m_Measures.empty()) - { - Measure* measure = m_Measures[0]; - double value = (m_Extend) ? measure->GetValue() : measure->GetRelativeValue(); - - if (m_TransitionFrameCount > 0) - { - int realFrames = m_FrameCount / (m_TransitionFrameCount + 1); - if ((int)(value * realFrames) != (int)(m_Value * realFrames)) - { - m_TransitionStartValue = m_Value; - m_TransitionStartTicks = System::GetTickCount64(); - } - else - { - m_TransitionStartTicks = 0; - } - } - - m_Value = value; - - return true; - } - return false; -} - -/* -** Returns true if the meter has active transition animation. -** -*/ -bool MeterBitmap::HasActiveTransition() -{ - if (m_TransitionStartTicks > 0) - { - return true; - } - return false; -} - -/* -** Draws the meter on the double buffer -** -*/ -bool MeterBitmap::Draw(Gfx::Canvas& canvas) -{ - if (!Meter::Draw(canvas)) return false; - - int newY, newX; - - if (m_FrameCount == 0 || !m_Image.IsLoaded()) return false; // Unable to continue - - Bitmap* bitmap = m_Image.GetImage(); - - Gdiplus::Rect meterRect = GetMeterRectPadding(); - - if (m_Extend) - { - int value = (int)m_Value; - value = max(0, value); // Only positive integers are supported - - int transitionValue = (int)m_TransitionStartValue; - transitionValue = max(0, transitionValue); // Only positive integers are supported - - // Calc the number of numbers - int numOfNums = 0; - - if (m_Digits > 0) - { - numOfNums = m_Digits; - } - else - { - int tmpValue = value; - - do - { - ++numOfNums; - if (m_FrameCount == 1) - { - tmpValue /= 2; - } - else - { - tmpValue /= m_FrameCount; - } - } - while (tmpValue > 0); - } - - // Blit the images - int offset; - if (m_Align == ALIGN_RIGHT) - { - offset = 0; - } - else if (m_Align == ALIGN_CENTER) - { - offset = numOfNums * (meterRect.Width + m_Separation) / 2; - } - else - { - offset = numOfNums * (meterRect.Width + m_Separation); - } - - do - { - offset = offset - (meterRect.Width + m_Separation); - - int realFrames = (m_FrameCount / (m_TransitionFrameCount + 1)); - int frame = (value % realFrames) * (m_TransitionFrameCount + 1); - - // If transition is ongoing the pick the correct frame - if (m_TransitionStartTicks > 0) - { - int diffTicks = (int)(System::GetTickCount64() - m_TransitionStartTicks); - - int range = ((value % realFrames) - (transitionValue % realFrames)) * (m_TransitionFrameCount + 1); - if (range < 0) - { - range += m_FrameCount; - } - int frameAdjustment = range * diffTicks / ((m_TransitionFrameCount + 1) * m_MeterWindow->GetTransitionUpdate()); - if (frameAdjustment > range) - { - m_TransitionStartTicks = 0; // The transition is over. Draw with the real value. - } - else - { - frame = (transitionValue % realFrames) * (m_TransitionFrameCount + 1); - frame += frameAdjustment; - frame %= m_FrameCount; - } - } - -// LogDebugF(L"[%u] Value: %f Frame: %i (Transition = %s)", GetTickCount(), m_Value, frame, m_TransitionStartTicks > 0 ? L"true" : L"false"); - - if (bitmap->GetHeight() > bitmap->GetWidth()) - { - newX = 0; - newY = meterRect.Height * frame; - } - else - { - newX = meterRect.Width * frame; - newY = 0; - } - - canvas.DrawBitmap(bitmap, Rect(meterRect.X + offset, meterRect.Y, meterRect.Width, meterRect.Height), Rect(newX, newY, meterRect.Width, meterRect.Height)); - if (m_FrameCount == 1) - { - value /= 2; - transitionValue /= 2; - } - else - { - value /= realFrames; - transitionValue /= realFrames; - } - --numOfNums; - } - while (numOfNums > 0); - } - else - { - int frame = 0; - int realFrames = (m_FrameCount / (m_TransitionFrameCount + 1)); - - if (m_ZeroFrame) - { - // Use the first frame only if the value is zero - if (m_Value > 0) - { - frame = (int)(m_Value * (realFrames - 1)) * (m_TransitionFrameCount + 1); - } - } - else - { - // Select the correct frame linearly - frame = (int)(m_Value * realFrames) * (m_TransitionFrameCount + 1); - } - - // If transition is ongoing the pick the correct frame - if (m_TransitionStartTicks > 0) - { - int diffTicks = (int)(System::GetTickCount64() - m_TransitionStartTicks); - - if (diffTicks > ((m_TransitionFrameCount + 1) * m_MeterWindow->GetTransitionUpdate())) - { - m_TransitionStartTicks = 0; // The transition is over. Draw with the real value. - } - else - { - double range = (m_Value - m_TransitionStartValue); - double adjustment = range * diffTicks / ((m_TransitionFrameCount + 1) * m_MeterWindow->GetTransitionUpdate()); - double frameAdjustment = adjustment * m_FrameCount; - - frame = (int)(m_TransitionStartValue * realFrames) * (m_TransitionFrameCount + 1); - frame += (int)frameAdjustment; - frame %= m_FrameCount; - frame = max(0, frame); - } - } - -// LogDebugF(L"[%u] Value: %f Frame: %i (Transition = %s)", GetTickCount(), m_Value, frame, m_TransitionStartTicks > 0 ? L"true" : L"false"); - - if (bitmap->GetHeight() > bitmap->GetWidth()) - { - newX = 0; - newY = frame * meterRect.Height; - } - else - { - newX = frame * meterRect.Width; - newY = 0; - } - - canvas.DrawBitmap(bitmap, Rect(meterRect.X, meterRect.Y, meterRect.Width, meterRect.Height), Rect(newX, newY, meterRect.Width, m_H)); - } - - return true; -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeterBitmap.h" +#include "Measure.h" +#include "Error.h" +#include "Rainmeter.h" +#include "System.h" +#include "../Common/Gfx/Canvas.h" + +using namespace Gdiplus; + +/* +** The constructor +** +*/ +MeterBitmap::MeterBitmap(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), + m_Image(L"BitmapImage", nullptr, true, meterWindow), + m_NeedsReload(false), + m_ZeroFrame(false), + m_FrameCount(1), + m_TransitionFrameCount(), + m_Align(ALIGN_LEFT), + m_Extend(false), + m_Separation(), + m_Digits(), + m_Value(), + m_TransitionStartTicks(), + m_TransitionStartValue() +{ +} + +/* +** The destructor +** +*/ +MeterBitmap::~MeterBitmap() +{ +} + +/* +** Load the image and get the dimensions of the meter from it. +** +*/ +void MeterBitmap::Initialize() +{ + Meter::Initialize(); + + // Load the bitmaps if defined + if (!m_ImageName.empty()) + { + m_Image.LoadImage(m_ImageName, m_NeedsReload); + + if (m_Image.IsLoaded()) + { + Bitmap* bitmap = m_Image.GetImage(); + + m_W = bitmap->GetWidth(); + m_H = bitmap->GetHeight(); + + if (m_H > m_W) + { + m_H = m_H / m_FrameCount; + } + else + { + m_W = m_W / m_FrameCount; + } + + m_W += GetWidthPadding(); + m_H += GetHeightPadding(); + } + } + else if (m_Image.IsLoaded()) + { + m_Image.DisposeImage(); + } +} + +/* +** Checks if the given point is inside the meter. +** +*/ +bool MeterBitmap::HitTest(int x, int y) +{ + if (m_Extend) + { + // Calc the number of numbers + int numOfNums = 0; + + if (m_Digits > 0) + { + numOfNums = m_Digits; + } + else + { + int tmpValue = (int)m_Value; + tmpValue = max(0, tmpValue); // Only positive integers are supported + + int realFrames = (m_FrameCount / (m_TransitionFrameCount + 1)); + do + { + ++numOfNums; + if (realFrames == 1) + { + tmpValue /= 2; + } + else + { + tmpValue /= realFrames; + } + } + while (tmpValue > 0); + } + + Rect rect(GetX(), GetY(), m_W * numOfNums + (numOfNums - 1) * m_Separation, m_H); + + if (m_Align == ALIGN_CENTER) + { + rect.Offset(-rect.Width / 2, 0); + } + else if (m_Align == ALIGN_RIGHT) + { + rect.Offset(-rect.Width, 0); + } + + if (rect.Contains(x, y)) + { + return true; + } + return false; + } + else + { + return Meter::HitTest(x, y); + } +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeterBitmap::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + // Store the current values so we know if the image needs to be updated + std::wstring oldImageName = m_ImageName; + int oldW = m_W; + int oldH = m_H; + + Meter::ReadOptions(parser, section); + + m_ImageName = parser.ReadString(section, L"BitmapImage", L""); + if (!m_ImageName.empty()) + { + // Read tinting options + m_Image.ReadOptions(parser, section); + } + else + { + m_Image.ClearOptionFlags(); + } + + m_FrameCount = parser.ReadInt(section, L"BitmapFrames", 1); + m_ZeroFrame = parser.ReadBool(section, L"BitmapZeroFrame", false); + + m_Separation = parser.ReadInt(section, L"BitmapSeparation", 0); + m_Extend = parser.ReadBool(section, L"BitmapExtend", false); + m_Digits = parser.ReadInt(section, L"BitmapDigits", 0); + + m_TransitionFrameCount = parser.ReadInt(section, L"BitmapTransitionFrames", 0); + + const WCHAR* align = parser.ReadString(section, L"BitmapAlign", L"LEFT").c_str(); + if (_wcsicmp(align, L"LEFT") == 0) + { + m_Align = ALIGN_LEFT; + } + else if (_wcsicmp(align, L"RIGHT") == 0) + { + m_Align = ALIGN_RIGHT; + } + else if (_wcsicmp(align, L"CENTER") == 0) + { + m_Align = ALIGN_CENTER; + } + else + { + LogErrorF(this, L"BitmapAlign=%s is not valid", align); + } + + if (m_Initialized) + { + m_NeedsReload = (wcscmp(oldImageName.c_str(), m_ImageName.c_str()) != 0); + + if (m_NeedsReload || + m_Image.IsOptionsChanged()) + { + Initialize(); // Reload the image + } + else + { + // Reset to old dimensions + m_W = oldW; + m_H = oldH; + } + } +} + +/* +** Updates the value(s) from the measures. +** +*/ +bool MeterBitmap::Update() +{ + if (Meter::Update() && !m_Measures.empty()) + { + Measure* measure = m_Measures[0]; + double value = (m_Extend) ? measure->GetValue() : measure->GetRelativeValue(); + + if (m_TransitionFrameCount > 0) + { + int realFrames = m_FrameCount / (m_TransitionFrameCount + 1); + if ((int)(value * realFrames) != (int)(m_Value * realFrames)) + { + m_TransitionStartValue = m_Value; + m_TransitionStartTicks = System::GetTickCount64(); + } + else + { + m_TransitionStartTicks = 0; + } + } + + m_Value = value; + + return true; + } + return false; +} + +/* +** Returns true if the meter has active transition animation. +** +*/ +bool MeterBitmap::HasActiveTransition() +{ + if (m_TransitionStartTicks > 0) + { + return true; + } + return false; +} + +/* +** Draws the meter on the double buffer +** +*/ +bool MeterBitmap::Draw(Gfx::Canvas& canvas) +{ + if (!Meter::Draw(canvas)) return false; + + int newY, newX; + + if (m_FrameCount == 0 || !m_Image.IsLoaded()) return false; // Unable to continue + + Bitmap* bitmap = m_Image.GetImage(); + + Gdiplus::Rect meterRect = GetMeterRectPadding(); + + if (m_Extend) + { + int value = (int)m_Value; + value = max(0, value); // Only positive integers are supported + + int transitionValue = (int)m_TransitionStartValue; + transitionValue = max(0, transitionValue); // Only positive integers are supported + + // Calc the number of numbers + int numOfNums = 0; + + if (m_Digits > 0) + { + numOfNums = m_Digits; + } + else + { + int tmpValue = value; + + do + { + ++numOfNums; + if (m_FrameCount == 1) + { + tmpValue /= 2; + } + else + { + tmpValue /= m_FrameCount; + } + } + while (tmpValue > 0); + } + + // Blit the images + int offset; + if (m_Align == ALIGN_RIGHT) + { + offset = 0; + } + else if (m_Align == ALIGN_CENTER) + { + offset = numOfNums * (meterRect.Width + m_Separation) / 2; + } + else + { + offset = numOfNums * (meterRect.Width + m_Separation); + } + + do + { + offset = offset - (meterRect.Width + m_Separation); + + int realFrames = (m_FrameCount / (m_TransitionFrameCount + 1)); + int frame = (value % realFrames) * (m_TransitionFrameCount + 1); + + // If transition is ongoing the pick the correct frame + if (m_TransitionStartTicks > 0) + { + int diffTicks = (int)(System::GetTickCount64() - m_TransitionStartTicks); + + int range = ((value % realFrames) - (transitionValue % realFrames)) * (m_TransitionFrameCount + 1); + if (range < 0) + { + range += m_FrameCount; + } + int frameAdjustment = range * diffTicks / ((m_TransitionFrameCount + 1) * m_MeterWindow->GetTransitionUpdate()); + if (frameAdjustment > range) + { + m_TransitionStartTicks = 0; // The transition is over. Draw with the real value. + } + else + { + frame = (transitionValue % realFrames) * (m_TransitionFrameCount + 1); + frame += frameAdjustment; + frame %= m_FrameCount; + } + } + +// LogDebugF(L"[%u] Value: %f Frame: %i (Transition = %s)", GetTickCount(), m_Value, frame, m_TransitionStartTicks > 0 ? L"true" : L"false"); + + if (bitmap->GetHeight() > bitmap->GetWidth()) + { + newX = 0; + newY = meterRect.Height * frame; + } + else + { + newX = meterRect.Width * frame; + newY = 0; + } + + canvas.DrawBitmap(bitmap, Rect(meterRect.X + offset, meterRect.Y, meterRect.Width, meterRect.Height), Rect(newX, newY, meterRect.Width, meterRect.Height)); + if (m_FrameCount == 1) + { + value /= 2; + transitionValue /= 2; + } + else + { + value /= realFrames; + transitionValue /= realFrames; + } + --numOfNums; + } + while (numOfNums > 0); + } + else + { + int frame = 0; + int realFrames = (m_FrameCount / (m_TransitionFrameCount + 1)); + + if (m_ZeroFrame) + { + // Use the first frame only if the value is zero + if (m_Value > 0) + { + frame = (int)(m_Value * (realFrames - 1)) * (m_TransitionFrameCount + 1); + } + } + else + { + // Select the correct frame linearly + frame = (int)(m_Value * realFrames) * (m_TransitionFrameCount + 1); + } + + // If transition is ongoing the pick the correct frame + if (m_TransitionStartTicks > 0) + { + int diffTicks = (int)(System::GetTickCount64() - m_TransitionStartTicks); + + if (diffTicks > ((m_TransitionFrameCount + 1) * m_MeterWindow->GetTransitionUpdate())) + { + m_TransitionStartTicks = 0; // The transition is over. Draw with the real value. + } + else + { + double range = (m_Value - m_TransitionStartValue); + double adjustment = range * diffTicks / ((m_TransitionFrameCount + 1) * m_MeterWindow->GetTransitionUpdate()); + double frameAdjustment = adjustment * m_FrameCount; + + frame = (int)(m_TransitionStartValue * realFrames) * (m_TransitionFrameCount + 1); + frame += (int)frameAdjustment; + frame %= m_FrameCount; + frame = max(0, frame); + } + } + +// LogDebugF(L"[%u] Value: %f Frame: %i (Transition = %s)", GetTickCount(), m_Value, frame, m_TransitionStartTicks > 0 ? L"true" : L"false"); + + if (bitmap->GetHeight() > bitmap->GetWidth()) + { + newX = 0; + newY = frame * meterRect.Height; + } + else + { + newX = frame * meterRect.Width; + newY = 0; + } + + canvas.DrawBitmap(bitmap, Rect(meterRect.X, meterRect.Y, meterRect.Width, meterRect.Height), Rect(newX, newY, meterRect.Width, m_H)); + } + + return true; +} diff --git a/Library/MeterBitmap.h b/Library/MeterBitmap.h index 555e1a48..20b4e512 100644 --- a/Library/MeterBitmap.h +++ b/Library/MeterBitmap.h @@ -1,64 +1,64 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __METERBITMAP_H__ -#define __METERBITMAP_H__ - -#include "Meter.h" -#include "TintedImage.h" - -class MeterBitmap : public Meter -{ -public: - MeterBitmap(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeterBitmap(); - - MeterBitmap(const MeterBitmap& other) = delete; - MeterBitmap& operator=(MeterBitmap other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - virtual bool HitTest(int x, int y); - - virtual void Initialize(); - virtual bool Update(); - virtual bool Draw(Gfx::Canvas& canvas); - virtual bool HasActiveTransition(); - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - -private: - TintedImage m_Image; - std::wstring m_ImageName; - bool m_NeedsReload; - - bool m_ZeroFrame; // If true, the first frame is only shown when the measured value is zero - int m_FrameCount; - int m_TransitionFrameCount; // Number of transition frames (per one frame) in the bitmap - METER_ALIGNMENT m_Align; - bool m_Extend; // If true, bitmaps extend horizontally and are used like numbers - int m_Separation; - int m_Digits; - double m_Value; - - ULONGLONG m_TransitionStartTicks; - double m_TransitionStartValue; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __METERBITMAP_H__ +#define __METERBITMAP_H__ + +#include "Meter.h" +#include "TintedImage.h" + +class MeterBitmap : public Meter +{ +public: + MeterBitmap(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeterBitmap(); + + MeterBitmap(const MeterBitmap& other) = delete; + MeterBitmap& operator=(MeterBitmap other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + virtual bool HitTest(int x, int y); + + virtual void Initialize(); + virtual bool Update(); + virtual bool Draw(Gfx::Canvas& canvas); + virtual bool HasActiveTransition(); + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + +private: + TintedImage m_Image; + std::wstring m_ImageName; + bool m_NeedsReload; + + bool m_ZeroFrame; // If true, the first frame is only shown when the measured value is zero + int m_FrameCount; + int m_TransitionFrameCount; // Number of transition frames (per one frame) in the bitmap + METER_ALIGNMENT m_Align; + bool m_Extend; // If true, bitmaps extend horizontally and are used like numbers + int m_Separation; + int m_Digits; + double m_Value; + + ULONGLONG m_TransitionStartTicks; + double m_TransitionStartValue; +}; + +#endif diff --git a/Library/MeterButton.cpp b/Library/MeterButton.cpp index 7a7cb687..76568c2d 100644 --- a/Library/MeterButton.cpp +++ b/Library/MeterButton.cpp @@ -1,330 +1,330 @@ -/* - Copyright (C) 2005 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeterButton.h" -#include "Measure.h" -#include "Rainmeter.h" -#include "Error.h" -#include "../Common/Gfx/Canvas.h" - -using namespace Gdiplus; - -enum BUTTON_STATE -{ - BUTTON_STATE_NORMAL, - BUTTON_STATE_DOWN, - BUTTON_STATE_HOVER -}; - -/* -** The constructor -** -*/ -MeterButton::MeterButton(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), - m_Image(L"ButtonImage", nullptr, true, meterWindow), - m_NeedsReload(false), - m_Bitmaps(), - m_State(BUTTON_STATE_NORMAL), - m_Clicked(false), - m_Focus(false) -{ -} - -/* -** The destructor -** -*/ -MeterButton::~MeterButton() -{ - for (int i = 0; i < BUTTON_FRAMES; ++i) - { - delete m_Bitmaps[i]; - } -} - -/* -** Load the image and get the dimensions of the meter from it. -** -*/ -void MeterButton::Initialize() -{ - Meter::Initialize(); - - for (int i = 0; i < BUTTON_FRAMES; ++i) - { - delete m_Bitmaps[i]; - m_Bitmaps[i] = nullptr; - } - - // Load the bitmaps if defined - if (!m_ImageName.empty()) - { - m_Image.LoadImage(m_ImageName, m_NeedsReload); - - if (m_Image.IsLoaded()) - { - Bitmap* bitmap = m_Image.GetImage(); - - int bitmapW = bitmap->GetWidth(); - int bitmapH = bitmap->GetHeight(); - - m_W = bitmapW; - m_H = bitmapH; - - if (m_H > m_W) - { - m_H /= BUTTON_FRAMES; - } - else - { - m_W /= BUTTON_FRAMES; - } - - // Separate the frames - for (int i = 0; i < BUTTON_FRAMES; ++i) - { - Bitmap bitmapPart(m_W, m_H, PixelFormat32bppPARGB); - Graphics graphics(&bitmapPart); - Rect r(0, 0, m_W, m_H); - - if (bitmapH > bitmapW) - { - graphics.DrawImage(bitmap, r, 0, m_H * i, m_W, m_H, UnitPixel); - } - else - { - graphics.DrawImage(bitmap, r, m_W * i, 0, m_W, m_H, UnitPixel); - } - m_Bitmaps[i] = new CachedBitmap(&bitmapPart, &graphics); - } - - m_W += GetWidthPadding(); - m_H += GetHeightPadding(); - } - } - else if (m_Image.IsLoaded()) - { - m_Image.DisposeImage(); - } -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeterButton::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - // Store the current values so we know if the image needs to be updated - std::wstring oldImageName = m_ImageName; - int oldW = m_W; - int oldH = m_H; - - Meter::ReadOptions(parser, section); - - m_ImageName = parser.ReadString(section, L"ButtonImage", L""); - if (!m_ImageName.empty()) - { - // Read tinting options - m_Image.ReadOptions(parser, section); - } - else - { - m_Image.ClearOptionFlags(); - } - - m_Command = parser.ReadString(section, L"ButtonCommand", L"", false); - - if (m_Initialized) - { - m_NeedsReload = (wcscmp(oldImageName.c_str(), m_ImageName.c_str()) != 0); - - if (m_NeedsReload || - m_Image.IsOptionsChanged()) - { - Initialize(); // Reload the image - } - else - { - // Reset to old dimensions - m_W = oldW; - m_H = oldH; - } - } -} - -/* -** Updates the value(s) from the measures. -** -*/ -bool MeterButton::Update() -{ - return Meter::Update(); -} - -/* -** Draws the meter on the double buffer -** -*/ -bool MeterButton::Draw(Gfx::Canvas& canvas) -{ - if (!Meter::Draw(canvas)) return false; - - if (m_Bitmaps[m_State] == nullptr) return false; // Unable to continue - - Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); - - Gdiplus::Rect meterRect = GetMeterRectPadding(); - - // Blit the image - graphics.DrawCachedBitmap(m_Bitmaps[m_State], meterRect.X, meterRect.Y); - - canvas.EndGdiplusContext(); - - return true; -} - -/* -** Overridden method. The meters need not to be bound on anything -** -*/ -void MeterButton::BindMeasures(ConfigParser& parser, const WCHAR* section) -{ - BindPrimaryMeasure(parser, section, true); -} - -/* -** Checks if the given point is inside the button. -** -*/ -bool MeterButton::HitTest2(int px, int py) -{ - int x = GetX(); - int y = GetY(); - - if (m_MouseOver && - px >= x && px < x + m_W && - py >= y && py < y + m_H) - { - if (m_SolidColor.GetA() != 0 || m_SolidColor2.GetA() != 0) - { - return true; - } - - // Check transparent pixels - if (m_Image.IsLoaded()) - { - Rect meterRect = GetMeterRectPadding(); - int ix = meterRect.Width * m_State; - px = px - meterRect.X + ix; - py = py - meterRect.Y; - if (px >= ix && px < ix + meterRect.Width && - py >= 0 && py < meterRect.Height) - { - Color color; - Status status = m_Image.GetImage()->GetPixel(px, py, &color); - if (status != Ok || color.GetA() != 0) - { - return true; - } - } - } - else - { - return true; - } - } - return false; -} - -bool MeterButton::MouseUp(POINT pos, bool execute) -{ - if (m_State == BUTTON_STATE_DOWN) - { - if (execute && m_Clicked && m_Focus && HitTest2(pos.x, pos.y)) - { - Rainmeter::GetInstance().ExecuteCommand(m_Command.c_str(), m_MeterWindow); - } - m_State = BUTTON_STATE_NORMAL; - m_Clicked = false; - return true; - } - m_Clicked = false; - - return false; -} - -bool MeterButton::MouseDown(POINT pos) -{ - if (m_Focus && HitTest2(pos.x, pos.y)) - { - m_State = BUTTON_STATE_DOWN; - m_Clicked = true; - return true; - } - return false; -} - -bool MeterButton::MouseMove(POINT pos) -{ - if (m_Clicked) - { - if (HitTest2(pos.x, pos.y)) - { - if (m_State == BUTTON_STATE_NORMAL) - { - m_State = BUTTON_STATE_DOWN; - return true; - } - } - else - { - // If the left button is not down anymore the clicked state needs to be set false - if (!IsLButtonDown()) - { - m_Clicked = false; - } - - if (m_State == BUTTON_STATE_DOWN) - { - m_State = BUTTON_STATE_NORMAL; - return true; - } - } - } - else - { - if (HitTest2(pos.x, pos.y)) - { - if (m_State == BUTTON_STATE_NORMAL) - { - m_State = BUTTON_STATE_HOVER; - return true; - } - } - else - { - if (m_State == BUTTON_STATE_HOVER) - { - m_State = BUTTON_STATE_NORMAL; - return true; - } - } - } - return false; -} +/* + Copyright (C) 2005 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeterButton.h" +#include "Measure.h" +#include "Rainmeter.h" +#include "Error.h" +#include "../Common/Gfx/Canvas.h" + +using namespace Gdiplus; + +enum BUTTON_STATE +{ + BUTTON_STATE_NORMAL, + BUTTON_STATE_DOWN, + BUTTON_STATE_HOVER +}; + +/* +** The constructor +** +*/ +MeterButton::MeterButton(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), + m_Image(L"ButtonImage", nullptr, true, meterWindow), + m_NeedsReload(false), + m_Bitmaps(), + m_State(BUTTON_STATE_NORMAL), + m_Clicked(false), + m_Focus(false) +{ +} + +/* +** The destructor +** +*/ +MeterButton::~MeterButton() +{ + for (int i = 0; i < BUTTON_FRAMES; ++i) + { + delete m_Bitmaps[i]; + } +} + +/* +** Load the image and get the dimensions of the meter from it. +** +*/ +void MeterButton::Initialize() +{ + Meter::Initialize(); + + for (int i = 0; i < BUTTON_FRAMES; ++i) + { + delete m_Bitmaps[i]; + m_Bitmaps[i] = nullptr; + } + + // Load the bitmaps if defined + if (!m_ImageName.empty()) + { + m_Image.LoadImage(m_ImageName, m_NeedsReload); + + if (m_Image.IsLoaded()) + { + Bitmap* bitmap = m_Image.GetImage(); + + int bitmapW = bitmap->GetWidth(); + int bitmapH = bitmap->GetHeight(); + + m_W = bitmapW; + m_H = bitmapH; + + if (m_H > m_W) + { + m_H /= BUTTON_FRAMES; + } + else + { + m_W /= BUTTON_FRAMES; + } + + // Separate the frames + for (int i = 0; i < BUTTON_FRAMES; ++i) + { + Bitmap bitmapPart(m_W, m_H, PixelFormat32bppPARGB); + Graphics graphics(&bitmapPart); + Rect r(0, 0, m_W, m_H); + + if (bitmapH > bitmapW) + { + graphics.DrawImage(bitmap, r, 0, m_H * i, m_W, m_H, UnitPixel); + } + else + { + graphics.DrawImage(bitmap, r, m_W * i, 0, m_W, m_H, UnitPixel); + } + m_Bitmaps[i] = new CachedBitmap(&bitmapPart, &graphics); + } + + m_W += GetWidthPadding(); + m_H += GetHeightPadding(); + } + } + else if (m_Image.IsLoaded()) + { + m_Image.DisposeImage(); + } +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeterButton::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + // Store the current values so we know if the image needs to be updated + std::wstring oldImageName = m_ImageName; + int oldW = m_W; + int oldH = m_H; + + Meter::ReadOptions(parser, section); + + m_ImageName = parser.ReadString(section, L"ButtonImage", L""); + if (!m_ImageName.empty()) + { + // Read tinting options + m_Image.ReadOptions(parser, section); + } + else + { + m_Image.ClearOptionFlags(); + } + + m_Command = parser.ReadString(section, L"ButtonCommand", L"", false); + + if (m_Initialized) + { + m_NeedsReload = (wcscmp(oldImageName.c_str(), m_ImageName.c_str()) != 0); + + if (m_NeedsReload || + m_Image.IsOptionsChanged()) + { + Initialize(); // Reload the image + } + else + { + // Reset to old dimensions + m_W = oldW; + m_H = oldH; + } + } +} + +/* +** Updates the value(s) from the measures. +** +*/ +bool MeterButton::Update() +{ + return Meter::Update(); +} + +/* +** Draws the meter on the double buffer +** +*/ +bool MeterButton::Draw(Gfx::Canvas& canvas) +{ + if (!Meter::Draw(canvas)) return false; + + if (m_Bitmaps[m_State] == nullptr) return false; // Unable to continue + + Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); + + Gdiplus::Rect meterRect = GetMeterRectPadding(); + + // Blit the image + graphics.DrawCachedBitmap(m_Bitmaps[m_State], meterRect.X, meterRect.Y); + + canvas.EndGdiplusContext(); + + return true; +} + +/* +** Overridden method. The meters need not to be bound on anything +** +*/ +void MeterButton::BindMeasures(ConfigParser& parser, const WCHAR* section) +{ + BindPrimaryMeasure(parser, section, true); +} + +/* +** Checks if the given point is inside the button. +** +*/ +bool MeterButton::HitTest2(int px, int py) +{ + int x = GetX(); + int y = GetY(); + + if (m_MouseOver && + px >= x && px < x + m_W && + py >= y && py < y + m_H) + { + if (m_SolidColor.GetA() != 0 || m_SolidColor2.GetA() != 0) + { + return true; + } + + // Check transparent pixels + if (m_Image.IsLoaded()) + { + Rect meterRect = GetMeterRectPadding(); + int ix = meterRect.Width * m_State; + px = px - meterRect.X + ix; + py = py - meterRect.Y; + if (px >= ix && px < ix + meterRect.Width && + py >= 0 && py < meterRect.Height) + { + Color color; + Status status = m_Image.GetImage()->GetPixel(px, py, &color); + if (status != Ok || color.GetA() != 0) + { + return true; + } + } + } + else + { + return true; + } + } + return false; +} + +bool MeterButton::MouseUp(POINT pos, bool execute) +{ + if (m_State == BUTTON_STATE_DOWN) + { + if (execute && m_Clicked && m_Focus && HitTest2(pos.x, pos.y)) + { + Rainmeter::GetInstance().ExecuteCommand(m_Command.c_str(), m_MeterWindow); + } + m_State = BUTTON_STATE_NORMAL; + m_Clicked = false; + return true; + } + m_Clicked = false; + + return false; +} + +bool MeterButton::MouseDown(POINT pos) +{ + if (m_Focus && HitTest2(pos.x, pos.y)) + { + m_State = BUTTON_STATE_DOWN; + m_Clicked = true; + return true; + } + return false; +} + +bool MeterButton::MouseMove(POINT pos) +{ + if (m_Clicked) + { + if (HitTest2(pos.x, pos.y)) + { + if (m_State == BUTTON_STATE_NORMAL) + { + m_State = BUTTON_STATE_DOWN; + return true; + } + } + else + { + // If the left button is not down anymore the clicked state needs to be set false + if (!IsLButtonDown()) + { + m_Clicked = false; + } + + if (m_State == BUTTON_STATE_DOWN) + { + m_State = BUTTON_STATE_NORMAL; + return true; + } + } + } + else + { + if (HitTest2(pos.x, pos.y)) + { + if (m_State == BUTTON_STATE_NORMAL) + { + m_State = BUTTON_STATE_HOVER; + return true; + } + } + else + { + if (m_State == BUTTON_STATE_HOVER) + { + m_State = BUTTON_STATE_NORMAL; + return true; + } + } + } + return false; +} diff --git a/Library/MeterButton.h b/Library/MeterButton.h index 60995b21..e6d0f94a 100644 --- a/Library/MeterButton.h +++ b/Library/MeterButton.h @@ -1,68 +1,68 @@ -/* - Copyright (C) 2005 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __METERBUTTON_H__ -#define __METERBUTTON_H__ - -#include "Meter.h" -#include "TintedImage.h" - -#define BUTTON_FRAMES 3 - -class MeterButton : public Meter -{ -public: - MeterButton(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeterButton(); - - MeterButton(const MeterButton& other) = delete; - MeterButton& operator=(MeterButton other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - virtual void Initialize(); - virtual bool Update(); - virtual bool Draw(Gfx::Canvas& canvas); - - bool MouseMove(POINT pos); - bool MouseUp(POINT pos, bool execute); - bool MouseDown(POINT pos); - - void SetFocus(bool f) { m_Focus = f; } - - bool HitTest2(int px, int py); - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void BindMeasures(ConfigParser& parser, const WCHAR* section); - - virtual bool IsFixedSize(bool overwrite = false) { return overwrite; } - -private: - TintedImage m_Image; - std::wstring m_ImageName; - bool m_NeedsReload; - - Gdiplus::CachedBitmap* m_Bitmaps[BUTTON_FRAMES]; // Cached bitmaps - std::wstring m_Command; - int m_State; - bool m_Clicked; - bool m_Focus; -}; - -#endif +/* + Copyright (C) 2005 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __METERBUTTON_H__ +#define __METERBUTTON_H__ + +#include "Meter.h" +#include "TintedImage.h" + +#define BUTTON_FRAMES 3 + +class MeterButton : public Meter +{ +public: + MeterButton(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeterButton(); + + MeterButton(const MeterButton& other) = delete; + MeterButton& operator=(MeterButton other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + virtual void Initialize(); + virtual bool Update(); + virtual bool Draw(Gfx::Canvas& canvas); + + bool MouseMove(POINT pos); + bool MouseUp(POINT pos, bool execute); + bool MouseDown(POINT pos); + + void SetFocus(bool f) { m_Focus = f; } + + bool HitTest2(int px, int py); + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void BindMeasures(ConfigParser& parser, const WCHAR* section); + + virtual bool IsFixedSize(bool overwrite = false) { return overwrite; } + +private: + TintedImage m_Image; + std::wstring m_ImageName; + bool m_NeedsReload; + + Gdiplus::CachedBitmap* m_Bitmaps[BUTTON_FRAMES]; // Cached bitmaps + std::wstring m_Command; + int m_State; + bool m_Clicked; + bool m_Focus; +}; + +#endif diff --git a/Library/MeterHistogram.cpp b/Library/MeterHistogram.cpp index 1e764f47..84da59a1 100644 --- a/Library/MeterHistogram.cpp +++ b/Library/MeterHistogram.cpp @@ -1,659 +1,659 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeterHistogram.h" -#include "Measure.h" -#include "Error.h" -#include "Rainmeter.h" -#include "../Common/Gfx/Canvas.h" - -using namespace Gdiplus; - -TintedImageHelper_DefineOptionArray(MeterHistogram::c_PrimaryOptionArray, L"Primary"); -TintedImageHelper_DefineOptionArray(MeterHistogram::c_SecondaryOptionArray, L"Secondary"); -TintedImageHelper_DefineOptionArray(MeterHistogram::c_BothOptionArray, L"Both"); - -/* -** The constructor -** -*/ -MeterHistogram::MeterHistogram(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), - m_PrimaryColor(Color::Green), - m_SecondaryColor(Color::Red), - m_OverlapColor(Color::Yellow), - m_MeterPos(), - m_Autoscale(false), - m_Flip(false), - m_PrimaryImage(L"PrimaryImage", c_PrimaryOptionArray, false, meterWindow), - m_SecondaryImage(L"SecondaryImage", c_SecondaryOptionArray, false, meterWindow), - m_OverlapImage(L"BothImage", c_BothOptionArray, false, meterWindow), - m_PrimaryNeedsReload(false), - m_SecondaryNeedsReload(false), - m_OverlapNeedsReload(false), - m_PrimaryValues(), - m_SecondaryValues(), - m_MaxPrimaryValue(1.0), - m_MinPrimaryValue(), - m_MaxSecondaryValue(1.0), - m_MinSecondaryValue(), - m_SizeChanged(true), - m_GraphStartLeft(false), - m_GraphHorizontalOrientation(false) -{ -} - -/* -** The destructor -** -*/ -MeterHistogram::~MeterHistogram() -{ - DisposeBuffer(); -} - -/* -** Disposes the buffers. -** -*/ -void MeterHistogram::DisposeBuffer() -{ - // Reset current position - m_MeterPos = 0; - - // Delete buffers - delete [] m_PrimaryValues; - m_PrimaryValues = nullptr; - - delete [] m_SecondaryValues; - m_SecondaryValues = nullptr; -} - -/* -** Creates the buffers. -** -*/ -void MeterHistogram::CreateBuffer() -{ - DisposeBuffer(); - - // Create buffers for values - int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; - if (maxSize > 0) - { - m_PrimaryValues = new double[maxSize](); - if (m_Measures.size() >= 2) - { - m_SecondaryValues = new double[maxSize](); - } - } -} - -/* -** Load the images and calculate the dimensions of the meter from them. -** Or create the brushes if solid color histogram is used. -** -*/ -void MeterHistogram::Initialize() -{ - Meter::Initialize(); - - Measure* secondaryMeasure = (m_Measures.size() >= 2) ? m_Measures[1] : nullptr; - - // A sanity check - if (secondaryMeasure && !m_PrimaryImageName.empty() && (m_OverlapImageName.empty() || m_SecondaryImageName.empty())) - { - LogWarningF(this, L"Histogram: SecondaryImage and BothImage not defined"); - - m_PrimaryImage.DisposeImage(); - m_SecondaryImage.DisposeImage(); - m_OverlapImage.DisposeImage(); - } - else - { - // Load the bitmaps if defined - if (!m_PrimaryImageName.empty()) - { - m_PrimaryImage.LoadImage(m_PrimaryImageName, m_PrimaryNeedsReload); - - if (m_PrimaryImage.IsLoaded()) - { - int oldSize = m_GraphHorizontalOrientation ? m_H : m_W; - - Bitmap* bitmap = m_PrimaryImage.GetImage(); - - m_W = bitmap->GetWidth(); - m_H = bitmap->GetHeight(); - - int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; - if (oldSize != maxSize) - { - m_SizeChanged = true; - } - - m_W += GetWidthPadding(); - m_H += GetHeightPadding(); - } - } - else if (m_PrimaryImage.IsLoaded()) - { - m_PrimaryImage.DisposeImage(); - } - - if (!m_SecondaryImageName.empty()) - { - m_SecondaryImage.LoadImage(m_SecondaryImageName, m_SecondaryNeedsReload); - } - else if (m_SecondaryImage.IsLoaded()) - { - m_SecondaryImage.DisposeImage(); - } - - if (!m_OverlapImageName.empty()) - { - m_OverlapImage.LoadImage(m_OverlapImageName, m_OverlapNeedsReload); - } - else if (m_OverlapImage.IsLoaded()) - { - m_OverlapImage.DisposeImage(); - } - } - - if ((!m_PrimaryImageName.empty() && !m_PrimaryImage.IsLoaded()) || - (!m_SecondaryImageName.empty() && !m_SecondaryImage.IsLoaded()) || - (!m_OverlapImageName.empty() && !m_OverlapImage.IsLoaded())) - { - DisposeBuffer(); - - m_SizeChanged = false; - } - else if (m_SizeChanged) - { - CreateBuffer(); - - m_SizeChanged = false; - } -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeterHistogram::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - // Store the current values so we know if the image needs to be updated - std::wstring oldPrimaryImageName = m_PrimaryImageName; - std::wstring oldSecondaryImageName = m_SecondaryImageName; - std::wstring oldBothImageName = m_OverlapImageName; - int oldW = m_W; - int oldH = m_H; - bool oldGraphHorizontalOrientation = m_GraphHorizontalOrientation; - - Meter::ReadOptions(parser, section); - - m_PrimaryColor = parser.ReadColor(section, L"PrimaryColor", Color::Green); - m_SecondaryColor = parser.ReadColor(section, L"SecondaryColor", Color::Red); - m_OverlapColor = parser.ReadColor(section, L"BothColor", Color::Yellow); - - m_PrimaryImageName = parser.ReadString(section, L"PrimaryImage", L""); - if (!m_PrimaryImageName.empty()) - { - // Read tinting options - m_PrimaryImage.ReadOptions(parser, section); - } - else - { - m_PrimaryImage.ClearOptionFlags(); - } - - m_SecondaryImageName = parser.ReadString(section, L"SecondaryImage", L""); - if (!m_SecondaryImageName.empty()) - { - // Read tinting options - m_SecondaryImage.ReadOptions(parser, section); - } - else - { - m_SecondaryImage.ClearOptionFlags(); - } - - m_OverlapImageName = parser.ReadString(section, L"BothImage", L""); - if (!m_OverlapImageName.empty()) - { - // Read tinting options - m_OverlapImage.ReadOptions(parser, section); - } - else - { - m_OverlapImage.ClearOptionFlags(); - } - - m_Autoscale = parser.ReadBool(section, L"AutoScale", false); - m_Flip = parser.ReadBool(section, L"Flip", false); - - const WCHAR* graph = parser.ReadString(section, L"GraphStart", L"RIGHT").c_str(); - if (_wcsicmp(graph, L"RIGHT") == 0) - { - m_GraphStartLeft = false; - } - else if (_wcsicmp(graph, L"LEFT") == 0) - { - m_GraphStartLeft = true; - } - else - { - LogErrorF(this, L"GraphStart=%s is not valid", graph); - } - - graph = parser.ReadString(section, L"GraphOrientation", L"VERTICAL").c_str(); - if (_wcsicmp(graph, L"VERTICAL") == 0) - { - m_GraphHorizontalOrientation = false; - } - else if (_wcsicmp(graph, L"HORIZONTAL") == 0) - { - m_GraphHorizontalOrientation = true; - } - else - { - LogErrorF(this, L"GraphOrientation=%s is not valid", graph); - } - - if (m_Initialized) - { - if (m_PrimaryImageName.empty()) - { - int oldSize = oldGraphHorizontalOrientation ? oldH : oldW; - int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; - if (oldSize != maxSize || oldGraphHorizontalOrientation != m_GraphHorizontalOrientation) - { - m_SizeChanged = true; - Initialize(); // Reload the image - } - } - else - { - // Reset to old dimensions - m_W = oldW; - m_H = oldH; - - m_PrimaryNeedsReload = (wcscmp(oldPrimaryImageName.c_str(), m_PrimaryImageName.c_str()) != 0); - m_SecondaryNeedsReload = (wcscmp(oldSecondaryImageName.c_str(), m_SecondaryImageName.c_str()) != 0); - m_OverlapNeedsReload = (wcscmp(oldBothImageName.c_str(), m_OverlapImageName.c_str()) != 0); - m_SizeChanged = (oldGraphHorizontalOrientation != m_GraphHorizontalOrientation); - - if (m_PrimaryNeedsReload || - m_SecondaryNeedsReload || - m_OverlapNeedsReload || - m_PrimaryImage.IsOptionsChanged() || - m_SecondaryImage.IsOptionsChanged() || - m_OverlapImage.IsOptionsChanged()) - { - Initialize(); // Reload the image - } - else if (m_SizeChanged) - { - CreateBuffer(); - } - } - } -} - -/* -** Updates the value(s) from the measures. -** -*/ -bool MeterHistogram::Update() -{ - if (Meter::Update() && !m_Measures.empty()) - { - int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; - - if (m_PrimaryValues && maxSize > 0) // m_PrimaryValues must not be nullptr - { - Measure* measure = m_Measures[0]; - Measure* secondaryMeasure = (m_Measures.size() >= 2) ? m_Measures[1] : nullptr; - - // Gather values - m_PrimaryValues[m_MeterPos] = measure->GetValue(); - - if (secondaryMeasure && m_SecondaryValues) - { - m_SecondaryValues[m_MeterPos] = secondaryMeasure->GetValue(); - } - - ++m_MeterPos; - m_MeterPos %= maxSize; - - m_MaxPrimaryValue = measure->GetMaxValue(); - m_MinPrimaryValue = measure->GetMinValue(); - m_MaxSecondaryValue = 0.0; - m_MinSecondaryValue = 0.0; - if (secondaryMeasure) - { - m_MaxSecondaryValue = secondaryMeasure->GetMaxValue(); - m_MinSecondaryValue = secondaryMeasure->GetMinValue(); - } - - if (m_Autoscale) - { - // Go through all values and find the max - - double newValue = 0.0; - for (int i = 0; i < maxSize; ++i) - { - newValue = max(newValue, m_PrimaryValues[i]); - } - - // Scale the value up to nearest power of 2 - if (newValue > DBL_MAX / 2.0) - { - m_MaxPrimaryValue = DBL_MAX; - } - else - { - m_MaxPrimaryValue = 2.0; - while (m_MaxPrimaryValue < newValue) - { - m_MaxPrimaryValue *= 2.0; - } - } - - if (secondaryMeasure && m_SecondaryValues) - { - for (int i = 0; i < maxSize; ++i) - { - newValue = max(newValue, m_SecondaryValues[i]); - } - - // Scale the value up to nearest power of 2 - if (newValue > DBL_MAX / 2.0) - { - m_MaxSecondaryValue = DBL_MAX; - } - else - { - m_MaxSecondaryValue = 2.0; - while (m_MaxSecondaryValue < newValue) - { - m_MaxSecondaryValue *= 2.0; - } - } - } - } - } - return true; - } - return false; -} - -/* -** Draws the meter on the double buffer -** -*/ -bool MeterHistogram::Draw(Gfx::Canvas& canvas) -{ - if (!Meter::Draw(canvas) || - (m_Measures.size() >= 1 && !m_PrimaryValues) || - (m_Measures.size() >= 2 && !m_SecondaryValues)) return false; - - Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); - - Measure* secondaryMeasure = (m_Measures.size() >= 2) ? m_Measures[1] : nullptr; - - GraphicsPath primaryPath; - GraphicsPath secondaryPath; - GraphicsPath bothPath; - - Bitmap* primaryBitmap = m_PrimaryImage.GetImage(); - Bitmap* secondaryBitmap = m_SecondaryImage.GetImage(); - Bitmap* bothBitmap = m_OverlapImage.GetImage(); - - Gdiplus::Rect meterRect = GetMeterRectPadding(); - - // Default values (GraphStart=Right, GraphOrientation=Vertical) - int i; - int startValue = 0; - int* endValueLHS = &i; - int* endValueRHS = &meterRect.Width; - int step = 1; - int endValue = -1; //(should be 0, but need to simulate <=) - - // GraphStart=Left, GraphOrientation=Vertical - if (!m_GraphHorizontalOrientation) - { - if (m_GraphStartLeft) - { - startValue = meterRect.Width - 1; - endValueLHS = &endValue; - endValueRHS = &i; - step = -1; - } - } - else - { - if (!m_Flip) - { - endValueRHS = &meterRect.Height; - } - else - { - startValue = meterRect.Height - 1; - endValueLHS = &endValue; - endValueRHS = &i; - step = -1; - } - } - - // Horizontal or Vertical graph - if (m_GraphHorizontalOrientation) - { - for (i = startValue; *endValueLHS < *endValueRHS; i += step) - { - double value = (m_MaxPrimaryValue == 0.0) ? - 0.0 - : m_PrimaryValues[(i + (m_MeterPos % meterRect.Height)) % meterRect.Height] / m_MaxPrimaryValue; - value -= m_MinPrimaryValue; - int primaryBarHeight = (int)(meterRect.Width * value); - primaryBarHeight = min(meterRect.Width, primaryBarHeight); - primaryBarHeight = max(0, primaryBarHeight); - - if (secondaryMeasure) - { - value = (m_MaxSecondaryValue == 0.0) ? - 0.0 - : m_SecondaryValues[(i + m_MeterPos) % meterRect.Height] / m_MaxSecondaryValue; - value -= m_MinSecondaryValue; - int secondaryBarHeight = (int)(meterRect.Width * value); - secondaryBarHeight = min(meterRect.Width, secondaryBarHeight); - secondaryBarHeight = max(0, secondaryBarHeight); - - // Check which measured value is higher - int bothBarHeight = min(primaryBarHeight, secondaryBarHeight); - - // Cache image/color rectangle for the both lines - { - Rect& r = m_GraphStartLeft ? - Rect(meterRect.X, meterRect.Y + startValue + (step * i), bothBarHeight, 1) - : Rect(meterRect.X + meterRect.Width - bothBarHeight, meterRect.Y + startValue + (step * i), bothBarHeight, 1); - - bothPath.AddRectangle(r); // cache - } - - // Cache the image/color rectangle for the rest - if (secondaryBarHeight > primaryBarHeight) - { - Rect& r = m_GraphStartLeft ? - Rect(meterRect.X + bothBarHeight, meterRect.Y + startValue + (step * i), secondaryBarHeight - bothBarHeight, 1) - : Rect(meterRect.X + meterRect.Width - secondaryBarHeight, meterRect.Y + startValue + (step * i), secondaryBarHeight - bothBarHeight, 1); - - secondaryPath.AddRectangle(r); // cache - } - else - { - Rect& r = m_GraphStartLeft ? - Rect(meterRect.X + bothBarHeight, meterRect.Y + startValue + (step * i), primaryBarHeight - bothBarHeight, 1) - : Rect(meterRect.X + meterRect.Width - primaryBarHeight, meterRect.Y + startValue + (step * i), primaryBarHeight - bothBarHeight, 1); - - primaryPath.AddRectangle(r); // cache - } - } - else - { - Rect& r = m_GraphStartLeft ? - Rect(meterRect.X, meterRect.Y + startValue + (step * i), primaryBarHeight, 1) - : Rect(meterRect.X + meterRect.Width - primaryBarHeight, meterRect.Y + startValue + (step * i), primaryBarHeight, 1); - - primaryPath.AddRectangle(r); // cache - } - } - } - else // GraphOrientation=Vertical - { - for (i = startValue; *endValueLHS < *endValueRHS; i += step) - { - double value = (m_MaxPrimaryValue == 0.0) ? - 0.0 - : m_PrimaryValues[(i + m_MeterPos) % meterRect.Width] / m_MaxPrimaryValue; - value -= m_MinPrimaryValue; - int primaryBarHeight = (int)(meterRect.Height * value); - primaryBarHeight = min(meterRect.Height, primaryBarHeight); - primaryBarHeight = max(0, primaryBarHeight); - - if (secondaryMeasure) - { - value = (m_MaxSecondaryValue == 0.0) ? - 0.0 - : m_SecondaryValues[(i + m_MeterPos) % meterRect.Width] / m_MaxSecondaryValue; - value -= m_MinSecondaryValue; - int secondaryBarHeight = (int)(meterRect.Height * value); - secondaryBarHeight = min(meterRect.Height, secondaryBarHeight); - secondaryBarHeight = max(0, secondaryBarHeight); - - // Check which measured value is higher - int bothBarHeight = min(primaryBarHeight, secondaryBarHeight); - - // Cache image/color rectangle for the both lines - { - Rect& r = m_Flip ? - Rect(meterRect.X + startValue + (step * i), meterRect.Y, 1, bothBarHeight) - : Rect(meterRect.X + startValue + (step * i), meterRect.Y + meterRect.Height - bothBarHeight, 1, bothBarHeight); - - bothPath.AddRectangle(r); // cache - } - - // Cache the image/color rectangle for the rest - if (secondaryBarHeight > primaryBarHeight) - { - Rect& r = m_Flip ? - Rect(meterRect.X + startValue + (step * i), meterRect.Y + bothBarHeight, 1, secondaryBarHeight - bothBarHeight) - : Rect(meterRect.X + startValue + (step * i), meterRect.Y + meterRect.Height - secondaryBarHeight, 1, secondaryBarHeight - bothBarHeight); - - secondaryPath.AddRectangle(r); // cache - } - else - { - Rect& r = m_Flip ? - Rect(meterRect.X + startValue + (step * i), meterRect.Y + bothBarHeight, 1, primaryBarHeight - bothBarHeight) - : Rect(meterRect.X + startValue + (step * i), meterRect.Y + meterRect.Height - primaryBarHeight, 1, primaryBarHeight - bothBarHeight); - - primaryPath.AddRectangle(r); // cache - } - } - else - { - Rect& r = m_Flip ? - Rect(meterRect.X + startValue + (step * i), meterRect.Y, 1, primaryBarHeight) - : Rect(meterRect.X + startValue + (step * i), meterRect.Y + meterRect.Height - primaryBarHeight, 1, primaryBarHeight); - - primaryPath.AddRectangle(r); // cache - } - } - } - - // Draw cached rectangles - if (primaryBitmap) - { - Rect r(meterRect.X, meterRect.Y, primaryBitmap->GetWidth(), primaryBitmap->GetHeight()); - - graphics.SetClip(&primaryPath); - graphics.DrawImage(primaryBitmap, r, 0, 0, r.Width, r.Height, UnitPixel); - graphics.ResetClip(); - } - else - { - SolidBrush brush(m_PrimaryColor); - graphics.FillPath(&brush, &primaryPath); - } - if (secondaryMeasure) - { - if (secondaryBitmap) - { - Rect r(meterRect.X, meterRect.Y, secondaryBitmap->GetWidth(), secondaryBitmap->GetHeight()); - - graphics.SetClip(&secondaryPath); - graphics.DrawImage(secondaryBitmap, r, 0, 0, r.Width, r.Height, UnitPixel); - graphics.ResetClip(); - } - else - { - SolidBrush brush(m_SecondaryColor); - graphics.FillPath(&brush, &secondaryPath); - } - if (bothBitmap) - { - Rect r(meterRect.X, meterRect.Y, bothBitmap->GetWidth(), bothBitmap->GetHeight()); - - graphics.SetClip(&bothPath); - graphics.DrawImage(bothBitmap, r, 0, 0, r.Width, r.Height, UnitPixel); - graphics.ResetClip(); - } - else - { - SolidBrush brush(m_OverlapColor); - graphics.FillPath(&brush, &bothPath); - } - } - - canvas.EndGdiplusContext(); - - return true; -} - -/* -** Overwritten method to handle the secondary measure binding. -** -*/ -void MeterHistogram::BindMeasures(ConfigParser& parser, const WCHAR* section) -{ - if (BindPrimaryMeasure(parser, section, false)) - { - const std::wstring* secondaryMeasure = &parser.ReadString(section, L"MeasureName2", L""); - if (secondaryMeasure->empty()) - { - // For backwards compatibility. - secondaryMeasure = &parser.ReadString(section, L"SecondaryMeasureName", L""); - } - - Measure* measure = parser.GetMeasure(*secondaryMeasure); - if (measure) - { - m_Measures.push_back(measure); - } - } -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeterHistogram.h" +#include "Measure.h" +#include "Error.h" +#include "Rainmeter.h" +#include "../Common/Gfx/Canvas.h" + +using namespace Gdiplus; + +TintedImageHelper_DefineOptionArray(MeterHistogram::c_PrimaryOptionArray, L"Primary"); +TintedImageHelper_DefineOptionArray(MeterHistogram::c_SecondaryOptionArray, L"Secondary"); +TintedImageHelper_DefineOptionArray(MeterHistogram::c_BothOptionArray, L"Both"); + +/* +** The constructor +** +*/ +MeterHistogram::MeterHistogram(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), + m_PrimaryColor(Color::Green), + m_SecondaryColor(Color::Red), + m_OverlapColor(Color::Yellow), + m_MeterPos(), + m_Autoscale(false), + m_Flip(false), + m_PrimaryImage(L"PrimaryImage", c_PrimaryOptionArray, false, meterWindow), + m_SecondaryImage(L"SecondaryImage", c_SecondaryOptionArray, false, meterWindow), + m_OverlapImage(L"BothImage", c_BothOptionArray, false, meterWindow), + m_PrimaryNeedsReload(false), + m_SecondaryNeedsReload(false), + m_OverlapNeedsReload(false), + m_PrimaryValues(), + m_SecondaryValues(), + m_MaxPrimaryValue(1.0), + m_MinPrimaryValue(), + m_MaxSecondaryValue(1.0), + m_MinSecondaryValue(), + m_SizeChanged(true), + m_GraphStartLeft(false), + m_GraphHorizontalOrientation(false) +{ +} + +/* +** The destructor +** +*/ +MeterHistogram::~MeterHistogram() +{ + DisposeBuffer(); +} + +/* +** Disposes the buffers. +** +*/ +void MeterHistogram::DisposeBuffer() +{ + // Reset current position + m_MeterPos = 0; + + // Delete buffers + delete [] m_PrimaryValues; + m_PrimaryValues = nullptr; + + delete [] m_SecondaryValues; + m_SecondaryValues = nullptr; +} + +/* +** Creates the buffers. +** +*/ +void MeterHistogram::CreateBuffer() +{ + DisposeBuffer(); + + // Create buffers for values + int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; + if (maxSize > 0) + { + m_PrimaryValues = new double[maxSize](); + if (m_Measures.size() >= 2) + { + m_SecondaryValues = new double[maxSize](); + } + } +} + +/* +** Load the images and calculate the dimensions of the meter from them. +** Or create the brushes if solid color histogram is used. +** +*/ +void MeterHistogram::Initialize() +{ + Meter::Initialize(); + + Measure* secondaryMeasure = (m_Measures.size() >= 2) ? m_Measures[1] : nullptr; + + // A sanity check + if (secondaryMeasure && !m_PrimaryImageName.empty() && (m_OverlapImageName.empty() || m_SecondaryImageName.empty())) + { + LogWarningF(this, L"Histogram: SecondaryImage and BothImage not defined"); + + m_PrimaryImage.DisposeImage(); + m_SecondaryImage.DisposeImage(); + m_OverlapImage.DisposeImage(); + } + else + { + // Load the bitmaps if defined + if (!m_PrimaryImageName.empty()) + { + m_PrimaryImage.LoadImage(m_PrimaryImageName, m_PrimaryNeedsReload); + + if (m_PrimaryImage.IsLoaded()) + { + int oldSize = m_GraphHorizontalOrientation ? m_H : m_W; + + Bitmap* bitmap = m_PrimaryImage.GetImage(); + + m_W = bitmap->GetWidth(); + m_H = bitmap->GetHeight(); + + int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; + if (oldSize != maxSize) + { + m_SizeChanged = true; + } + + m_W += GetWidthPadding(); + m_H += GetHeightPadding(); + } + } + else if (m_PrimaryImage.IsLoaded()) + { + m_PrimaryImage.DisposeImage(); + } + + if (!m_SecondaryImageName.empty()) + { + m_SecondaryImage.LoadImage(m_SecondaryImageName, m_SecondaryNeedsReload); + } + else if (m_SecondaryImage.IsLoaded()) + { + m_SecondaryImage.DisposeImage(); + } + + if (!m_OverlapImageName.empty()) + { + m_OverlapImage.LoadImage(m_OverlapImageName, m_OverlapNeedsReload); + } + else if (m_OverlapImage.IsLoaded()) + { + m_OverlapImage.DisposeImage(); + } + } + + if ((!m_PrimaryImageName.empty() && !m_PrimaryImage.IsLoaded()) || + (!m_SecondaryImageName.empty() && !m_SecondaryImage.IsLoaded()) || + (!m_OverlapImageName.empty() && !m_OverlapImage.IsLoaded())) + { + DisposeBuffer(); + + m_SizeChanged = false; + } + else if (m_SizeChanged) + { + CreateBuffer(); + + m_SizeChanged = false; + } +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeterHistogram::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + // Store the current values so we know if the image needs to be updated + std::wstring oldPrimaryImageName = m_PrimaryImageName; + std::wstring oldSecondaryImageName = m_SecondaryImageName; + std::wstring oldBothImageName = m_OverlapImageName; + int oldW = m_W; + int oldH = m_H; + bool oldGraphHorizontalOrientation = m_GraphHorizontalOrientation; + + Meter::ReadOptions(parser, section); + + m_PrimaryColor = parser.ReadColor(section, L"PrimaryColor", Color::Green); + m_SecondaryColor = parser.ReadColor(section, L"SecondaryColor", Color::Red); + m_OverlapColor = parser.ReadColor(section, L"BothColor", Color::Yellow); + + m_PrimaryImageName = parser.ReadString(section, L"PrimaryImage", L""); + if (!m_PrimaryImageName.empty()) + { + // Read tinting options + m_PrimaryImage.ReadOptions(parser, section); + } + else + { + m_PrimaryImage.ClearOptionFlags(); + } + + m_SecondaryImageName = parser.ReadString(section, L"SecondaryImage", L""); + if (!m_SecondaryImageName.empty()) + { + // Read tinting options + m_SecondaryImage.ReadOptions(parser, section); + } + else + { + m_SecondaryImage.ClearOptionFlags(); + } + + m_OverlapImageName = parser.ReadString(section, L"BothImage", L""); + if (!m_OverlapImageName.empty()) + { + // Read tinting options + m_OverlapImage.ReadOptions(parser, section); + } + else + { + m_OverlapImage.ClearOptionFlags(); + } + + m_Autoscale = parser.ReadBool(section, L"AutoScale", false); + m_Flip = parser.ReadBool(section, L"Flip", false); + + const WCHAR* graph = parser.ReadString(section, L"GraphStart", L"RIGHT").c_str(); + if (_wcsicmp(graph, L"RIGHT") == 0) + { + m_GraphStartLeft = false; + } + else if (_wcsicmp(graph, L"LEFT") == 0) + { + m_GraphStartLeft = true; + } + else + { + LogErrorF(this, L"GraphStart=%s is not valid", graph); + } + + graph = parser.ReadString(section, L"GraphOrientation", L"VERTICAL").c_str(); + if (_wcsicmp(graph, L"VERTICAL") == 0) + { + m_GraphHorizontalOrientation = false; + } + else if (_wcsicmp(graph, L"HORIZONTAL") == 0) + { + m_GraphHorizontalOrientation = true; + } + else + { + LogErrorF(this, L"GraphOrientation=%s is not valid", graph); + } + + if (m_Initialized) + { + if (m_PrimaryImageName.empty()) + { + int oldSize = oldGraphHorizontalOrientation ? oldH : oldW; + int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; + if (oldSize != maxSize || oldGraphHorizontalOrientation != m_GraphHorizontalOrientation) + { + m_SizeChanged = true; + Initialize(); // Reload the image + } + } + else + { + // Reset to old dimensions + m_W = oldW; + m_H = oldH; + + m_PrimaryNeedsReload = (wcscmp(oldPrimaryImageName.c_str(), m_PrimaryImageName.c_str()) != 0); + m_SecondaryNeedsReload = (wcscmp(oldSecondaryImageName.c_str(), m_SecondaryImageName.c_str()) != 0); + m_OverlapNeedsReload = (wcscmp(oldBothImageName.c_str(), m_OverlapImageName.c_str()) != 0); + m_SizeChanged = (oldGraphHorizontalOrientation != m_GraphHorizontalOrientation); + + if (m_PrimaryNeedsReload || + m_SecondaryNeedsReload || + m_OverlapNeedsReload || + m_PrimaryImage.IsOptionsChanged() || + m_SecondaryImage.IsOptionsChanged() || + m_OverlapImage.IsOptionsChanged()) + { + Initialize(); // Reload the image + } + else if (m_SizeChanged) + { + CreateBuffer(); + } + } + } +} + +/* +** Updates the value(s) from the measures. +** +*/ +bool MeterHistogram::Update() +{ + if (Meter::Update() && !m_Measures.empty()) + { + int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; + + if (m_PrimaryValues && maxSize > 0) // m_PrimaryValues must not be nullptr + { + Measure* measure = m_Measures[0]; + Measure* secondaryMeasure = (m_Measures.size() >= 2) ? m_Measures[1] : nullptr; + + // Gather values + m_PrimaryValues[m_MeterPos] = measure->GetValue(); + + if (secondaryMeasure && m_SecondaryValues) + { + m_SecondaryValues[m_MeterPos] = secondaryMeasure->GetValue(); + } + + ++m_MeterPos; + m_MeterPos %= maxSize; + + m_MaxPrimaryValue = measure->GetMaxValue(); + m_MinPrimaryValue = measure->GetMinValue(); + m_MaxSecondaryValue = 0.0; + m_MinSecondaryValue = 0.0; + if (secondaryMeasure) + { + m_MaxSecondaryValue = secondaryMeasure->GetMaxValue(); + m_MinSecondaryValue = secondaryMeasure->GetMinValue(); + } + + if (m_Autoscale) + { + // Go through all values and find the max + + double newValue = 0.0; + for (int i = 0; i < maxSize; ++i) + { + newValue = max(newValue, m_PrimaryValues[i]); + } + + // Scale the value up to nearest power of 2 + if (newValue > DBL_MAX / 2.0) + { + m_MaxPrimaryValue = DBL_MAX; + } + else + { + m_MaxPrimaryValue = 2.0; + while (m_MaxPrimaryValue < newValue) + { + m_MaxPrimaryValue *= 2.0; + } + } + + if (secondaryMeasure && m_SecondaryValues) + { + for (int i = 0; i < maxSize; ++i) + { + newValue = max(newValue, m_SecondaryValues[i]); + } + + // Scale the value up to nearest power of 2 + if (newValue > DBL_MAX / 2.0) + { + m_MaxSecondaryValue = DBL_MAX; + } + else + { + m_MaxSecondaryValue = 2.0; + while (m_MaxSecondaryValue < newValue) + { + m_MaxSecondaryValue *= 2.0; + } + } + } + } + } + return true; + } + return false; +} + +/* +** Draws the meter on the double buffer +** +*/ +bool MeterHistogram::Draw(Gfx::Canvas& canvas) +{ + if (!Meter::Draw(canvas) || + (m_Measures.size() >= 1 && !m_PrimaryValues) || + (m_Measures.size() >= 2 && !m_SecondaryValues)) return false; + + Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); + + Measure* secondaryMeasure = (m_Measures.size() >= 2) ? m_Measures[1] : nullptr; + + GraphicsPath primaryPath; + GraphicsPath secondaryPath; + GraphicsPath bothPath; + + Bitmap* primaryBitmap = m_PrimaryImage.GetImage(); + Bitmap* secondaryBitmap = m_SecondaryImage.GetImage(); + Bitmap* bothBitmap = m_OverlapImage.GetImage(); + + Gdiplus::Rect meterRect = GetMeterRectPadding(); + + // Default values (GraphStart=Right, GraphOrientation=Vertical) + int i; + int startValue = 0; + int* endValueLHS = &i; + int* endValueRHS = &meterRect.Width; + int step = 1; + int endValue = -1; //(should be 0, but need to simulate <=) + + // GraphStart=Left, GraphOrientation=Vertical + if (!m_GraphHorizontalOrientation) + { + if (m_GraphStartLeft) + { + startValue = meterRect.Width - 1; + endValueLHS = &endValue; + endValueRHS = &i; + step = -1; + } + } + else + { + if (!m_Flip) + { + endValueRHS = &meterRect.Height; + } + else + { + startValue = meterRect.Height - 1; + endValueLHS = &endValue; + endValueRHS = &i; + step = -1; + } + } + + // Horizontal or Vertical graph + if (m_GraphHorizontalOrientation) + { + for (i = startValue; *endValueLHS < *endValueRHS; i += step) + { + double value = (m_MaxPrimaryValue == 0.0) ? + 0.0 + : m_PrimaryValues[(i + (m_MeterPos % meterRect.Height)) % meterRect.Height] / m_MaxPrimaryValue; + value -= m_MinPrimaryValue; + int primaryBarHeight = (int)(meterRect.Width * value); + primaryBarHeight = min(meterRect.Width, primaryBarHeight); + primaryBarHeight = max(0, primaryBarHeight); + + if (secondaryMeasure) + { + value = (m_MaxSecondaryValue == 0.0) ? + 0.0 + : m_SecondaryValues[(i + m_MeterPos) % meterRect.Height] / m_MaxSecondaryValue; + value -= m_MinSecondaryValue; + int secondaryBarHeight = (int)(meterRect.Width * value); + secondaryBarHeight = min(meterRect.Width, secondaryBarHeight); + secondaryBarHeight = max(0, secondaryBarHeight); + + // Check which measured value is higher + int bothBarHeight = min(primaryBarHeight, secondaryBarHeight); + + // Cache image/color rectangle for the both lines + { + Rect& r = m_GraphStartLeft ? + Rect(meterRect.X, meterRect.Y + startValue + (step * i), bothBarHeight, 1) + : Rect(meterRect.X + meterRect.Width - bothBarHeight, meterRect.Y + startValue + (step * i), bothBarHeight, 1); + + bothPath.AddRectangle(r); // cache + } + + // Cache the image/color rectangle for the rest + if (secondaryBarHeight > primaryBarHeight) + { + Rect& r = m_GraphStartLeft ? + Rect(meterRect.X + bothBarHeight, meterRect.Y + startValue + (step * i), secondaryBarHeight - bothBarHeight, 1) + : Rect(meterRect.X + meterRect.Width - secondaryBarHeight, meterRect.Y + startValue + (step * i), secondaryBarHeight - bothBarHeight, 1); + + secondaryPath.AddRectangle(r); // cache + } + else + { + Rect& r = m_GraphStartLeft ? + Rect(meterRect.X + bothBarHeight, meterRect.Y + startValue + (step * i), primaryBarHeight - bothBarHeight, 1) + : Rect(meterRect.X + meterRect.Width - primaryBarHeight, meterRect.Y + startValue + (step * i), primaryBarHeight - bothBarHeight, 1); + + primaryPath.AddRectangle(r); // cache + } + } + else + { + Rect& r = m_GraphStartLeft ? + Rect(meterRect.X, meterRect.Y + startValue + (step * i), primaryBarHeight, 1) + : Rect(meterRect.X + meterRect.Width - primaryBarHeight, meterRect.Y + startValue + (step * i), primaryBarHeight, 1); + + primaryPath.AddRectangle(r); // cache + } + } + } + else // GraphOrientation=Vertical + { + for (i = startValue; *endValueLHS < *endValueRHS; i += step) + { + double value = (m_MaxPrimaryValue == 0.0) ? + 0.0 + : m_PrimaryValues[(i + m_MeterPos) % meterRect.Width] / m_MaxPrimaryValue; + value -= m_MinPrimaryValue; + int primaryBarHeight = (int)(meterRect.Height * value); + primaryBarHeight = min(meterRect.Height, primaryBarHeight); + primaryBarHeight = max(0, primaryBarHeight); + + if (secondaryMeasure) + { + value = (m_MaxSecondaryValue == 0.0) ? + 0.0 + : m_SecondaryValues[(i + m_MeterPos) % meterRect.Width] / m_MaxSecondaryValue; + value -= m_MinSecondaryValue; + int secondaryBarHeight = (int)(meterRect.Height * value); + secondaryBarHeight = min(meterRect.Height, secondaryBarHeight); + secondaryBarHeight = max(0, secondaryBarHeight); + + // Check which measured value is higher + int bothBarHeight = min(primaryBarHeight, secondaryBarHeight); + + // Cache image/color rectangle for the both lines + { + Rect& r = m_Flip ? + Rect(meterRect.X + startValue + (step * i), meterRect.Y, 1, bothBarHeight) + : Rect(meterRect.X + startValue + (step * i), meterRect.Y + meterRect.Height - bothBarHeight, 1, bothBarHeight); + + bothPath.AddRectangle(r); // cache + } + + // Cache the image/color rectangle for the rest + if (secondaryBarHeight > primaryBarHeight) + { + Rect& r = m_Flip ? + Rect(meterRect.X + startValue + (step * i), meterRect.Y + bothBarHeight, 1, secondaryBarHeight - bothBarHeight) + : Rect(meterRect.X + startValue + (step * i), meterRect.Y + meterRect.Height - secondaryBarHeight, 1, secondaryBarHeight - bothBarHeight); + + secondaryPath.AddRectangle(r); // cache + } + else + { + Rect& r = m_Flip ? + Rect(meterRect.X + startValue + (step * i), meterRect.Y + bothBarHeight, 1, primaryBarHeight - bothBarHeight) + : Rect(meterRect.X + startValue + (step * i), meterRect.Y + meterRect.Height - primaryBarHeight, 1, primaryBarHeight - bothBarHeight); + + primaryPath.AddRectangle(r); // cache + } + } + else + { + Rect& r = m_Flip ? + Rect(meterRect.X + startValue + (step * i), meterRect.Y, 1, primaryBarHeight) + : Rect(meterRect.X + startValue + (step * i), meterRect.Y + meterRect.Height - primaryBarHeight, 1, primaryBarHeight); + + primaryPath.AddRectangle(r); // cache + } + } + } + + // Draw cached rectangles + if (primaryBitmap) + { + Rect r(meterRect.X, meterRect.Y, primaryBitmap->GetWidth(), primaryBitmap->GetHeight()); + + graphics.SetClip(&primaryPath); + graphics.DrawImage(primaryBitmap, r, 0, 0, r.Width, r.Height, UnitPixel); + graphics.ResetClip(); + } + else + { + SolidBrush brush(m_PrimaryColor); + graphics.FillPath(&brush, &primaryPath); + } + if (secondaryMeasure) + { + if (secondaryBitmap) + { + Rect r(meterRect.X, meterRect.Y, secondaryBitmap->GetWidth(), secondaryBitmap->GetHeight()); + + graphics.SetClip(&secondaryPath); + graphics.DrawImage(secondaryBitmap, r, 0, 0, r.Width, r.Height, UnitPixel); + graphics.ResetClip(); + } + else + { + SolidBrush brush(m_SecondaryColor); + graphics.FillPath(&brush, &secondaryPath); + } + if (bothBitmap) + { + Rect r(meterRect.X, meterRect.Y, bothBitmap->GetWidth(), bothBitmap->GetHeight()); + + graphics.SetClip(&bothPath); + graphics.DrawImage(bothBitmap, r, 0, 0, r.Width, r.Height, UnitPixel); + graphics.ResetClip(); + } + else + { + SolidBrush brush(m_OverlapColor); + graphics.FillPath(&brush, &bothPath); + } + } + + canvas.EndGdiplusContext(); + + return true; +} + +/* +** Overwritten method to handle the secondary measure binding. +** +*/ +void MeterHistogram::BindMeasures(ConfigParser& parser, const WCHAR* section) +{ + if (BindPrimaryMeasure(parser, section, false)) + { + const std::wstring* secondaryMeasure = &parser.ReadString(section, L"MeasureName2", L""); + if (secondaryMeasure->empty()) + { + // For backwards compatibility. + secondaryMeasure = &parser.ReadString(section, L"SecondaryMeasureName", L""); + } + + Measure* measure = parser.GetMeasure(*secondaryMeasure); + if (measure) + { + m_Measures.push_back(measure); + } + } +} diff --git a/Library/MeterHistogram.h b/Library/MeterHistogram.h index 81a6b36e..7ed00b74 100644 --- a/Library/MeterHistogram.h +++ b/Library/MeterHistogram.h @@ -1,88 +1,88 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __METERHISTOGRAM_H__ -#define __METERHISTOGRAM_H__ - -#include "Meter.h" -#include "TintedImage.h" - -class MeterHistogram : public Meter -{ -public: - MeterHistogram(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeterHistogram(); - - MeterHistogram(const MeterHistogram& other) = delete; - MeterHistogram& operator=(MeterHistogram other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - virtual void Initialize(); - virtual bool Update(); - virtual bool Draw(Gfx::Canvas& canvas); - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void BindMeasures(ConfigParser& parser, const WCHAR* section); - - virtual bool IsFixedSize(bool overwrite = false) { return m_PrimaryImageName.empty(); } - -private: - void DisposeBuffer(); - void CreateBuffer(); - - Gdiplus::Color m_PrimaryColor; - Gdiplus::Color m_SecondaryColor; - Gdiplus::Color m_OverlapColor; - - int m_MeterPos; // New value placement position - bool m_Autoscale; - bool m_Flip; - - std::wstring m_PrimaryImageName; - std::wstring m_SecondaryImageName; - std::wstring m_OverlapImageName; - - TintedImage m_PrimaryImage; - TintedImage m_SecondaryImage; - TintedImage m_OverlapImage; - - bool m_PrimaryNeedsReload; - bool m_SecondaryNeedsReload; - bool m_OverlapNeedsReload; - - double* m_PrimaryValues; - double* m_SecondaryValues; - - double m_MaxPrimaryValue; - double m_MinPrimaryValue; - double m_MaxSecondaryValue; - double m_MinSecondaryValue; - - bool m_SizeChanged; - - bool m_GraphStartLeft; - bool m_GraphHorizontalOrientation; - - static const WCHAR* c_PrimaryOptionArray[TintedImage::OptionCount]; - static const WCHAR* c_SecondaryOptionArray[TintedImage::OptionCount]; - static const WCHAR* c_BothOptionArray[TintedImage::OptionCount]; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __METERHISTOGRAM_H__ +#define __METERHISTOGRAM_H__ + +#include "Meter.h" +#include "TintedImage.h" + +class MeterHistogram : public Meter +{ +public: + MeterHistogram(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeterHistogram(); + + MeterHistogram(const MeterHistogram& other) = delete; + MeterHistogram& operator=(MeterHistogram other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + virtual void Initialize(); + virtual bool Update(); + virtual bool Draw(Gfx::Canvas& canvas); + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void BindMeasures(ConfigParser& parser, const WCHAR* section); + + virtual bool IsFixedSize(bool overwrite = false) { return m_PrimaryImageName.empty(); } + +private: + void DisposeBuffer(); + void CreateBuffer(); + + Gdiplus::Color m_PrimaryColor; + Gdiplus::Color m_SecondaryColor; + Gdiplus::Color m_OverlapColor; + + int m_MeterPos; // New value placement position + bool m_Autoscale; + bool m_Flip; + + std::wstring m_PrimaryImageName; + std::wstring m_SecondaryImageName; + std::wstring m_OverlapImageName; + + TintedImage m_PrimaryImage; + TintedImage m_SecondaryImage; + TintedImage m_OverlapImage; + + bool m_PrimaryNeedsReload; + bool m_SecondaryNeedsReload; + bool m_OverlapNeedsReload; + + double* m_PrimaryValues; + double* m_SecondaryValues; + + double m_MaxPrimaryValue; + double m_MinPrimaryValue; + double m_MaxSecondaryValue; + double m_MinSecondaryValue; + + bool m_SizeChanged; + + bool m_GraphStartLeft; + bool m_GraphHorizontalOrientation; + + static const WCHAR* c_PrimaryOptionArray[TintedImage::OptionCount]; + static const WCHAR* c_SecondaryOptionArray[TintedImage::OptionCount]; + static const WCHAR* c_BothOptionArray[TintedImage::OptionCount]; +}; + +#endif diff --git a/Library/MeterImage.cpp b/Library/MeterImage.cpp index 354c6b0b..918bf301 100644 --- a/Library/MeterImage.cpp +++ b/Library/MeterImage.cpp @@ -1,366 +1,366 @@ -/* - Copyright (C) 2002 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeterImage.h" -#include "Measure.h" -#include "Error.h" -#include "Rainmeter.h" -#include "System.h" -#include "../Common/PathUtil.h" -#include "../Common/Gfx/Canvas.h" - -using namespace Gdiplus; - -/* -** The constructor -** -*/ -MeterImage::MeterImage(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), - m_Image(L"ImageName", nullptr, false, meterWindow), - m_NeedsRedraw(false), - m_DrawMode(DRAWMODE_NONE), - m_ScaleMargins() -{ -} - -/* -** The destructor -** -*/ -MeterImage::~MeterImage() -{ -} - -/* -** Load the image and get the dimensions of the meter from it. -** -*/ -void MeterImage::Initialize() -{ - Meter::Initialize(); - - if (m_Measures.empty() && !m_DynamicVariables && !m_ImageName.empty()) - { - m_ImageNameResult = m_ImageName; - LoadImage(m_ImageName, true); - } -} - -/* -** Loads the image from disk -** -*/ -void MeterImage::LoadImage(const std::wstring& imageName, bool bLoadAlways) -{ - m_Image.LoadImage(imageName, bLoadAlways); - - if (m_Image.IsLoaded()) - { - // Calculate size of the meter - Bitmap* bitmap = m_Image.GetImage(); - - int imageW = bitmap->GetWidth(); - int imageH = bitmap->GetHeight(); - - if (m_WDefined) - { - if (!m_HDefined) - { - m_H = (imageW == 0) ? 0 : (m_DrawMode == DRAWMODE_TILE) ? imageH : m_W * imageH / imageW; - m_H += GetHeightPadding(); - } - } - else - { - if (m_HDefined) - { - m_W = (imageH == 0) ? 0 : (m_DrawMode == DRAWMODE_TILE) ? imageW : m_H * imageW / imageH; - m_W += GetWidthPadding(); - } - else - { - m_W = imageW + GetWidthPadding(); - m_H = imageH + GetHeightPadding(); - } - } - } -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeterImage::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - Meter::ReadOptions(parser, section); - - m_ImageName = parser.ReadString(section, L"ImageName", L""); - - int mode = parser.ReadInt(section, L"Tile", 0); - if (mode != 0) - { - m_DrawMode = DRAWMODE_TILE; - } - else - { - mode = parser.ReadInt(section, L"PreserveAspectRatio", 0); - switch (mode) - { - case 0: - m_DrawMode = DRAWMODE_NONE; - break; - case 1: - default: - m_DrawMode = DRAWMODE_KEEPRATIO; - break; - case 2: - m_DrawMode = DRAWMODE_KEEPRATIOANDCROP; - break; - } - } - - static const RECT defMargins = {0}; - m_ScaleMargins = parser.ReadRECT(section, L"ScaleMargins", defMargins); - - // Deprecated! - std::wstring path = parser.ReadString(section, L"Path", L""); - PathUtil::AppendBacklashIfMissing(path); - - // Read tinting options - m_Image.ReadOptions(parser, section, path.c_str()); - - if (m_Initialized && m_Measures.empty() && !m_DynamicVariables) - { - Initialize(); - m_NeedsRedraw = true; - } -} - -/* -** Updates the value(s) from the measures. -** -*/ -bool MeterImage::Update() -{ - if (Meter::Update()) - { - if (!m_Measures.empty() || m_DynamicVariables) - { - // Store the current values so we know if the image needs to be updated - std::wstring oldResult = m_ImageNameResult; - - if (!m_Measures.empty()) // read from the measures - { - if (m_ImageName.empty()) - { - m_ImageNameResult = m_Measures[0]->GetStringOrFormattedValue(AUTOSCALE_OFF, 1, 0, false); - } - else - { - m_ImageNameResult = m_ImageName; - if (!ReplaceMeasures(m_ImageNameResult, AUTOSCALE_OFF)) - { - // ImageName doesn't contain any measures, so use the result of MeasureName. - m_ImageNameResult = m_Measures[0]->GetStringOrFormattedValue(AUTOSCALE_OFF, 1, 0, false); - } - } - } - else // read from the skin - { - m_ImageNameResult = m_ImageName; - } - - LoadImage(m_ImageNameResult, (wcscmp(oldResult.c_str(), m_ImageNameResult.c_str()) != 0)); - return true; - } - else if (m_NeedsRedraw) - { - m_NeedsRedraw = false; - return true; - } - } - return false; -} - -/* -** Draws the meter on the double buffer -** -*/ -bool MeterImage::Draw(Gfx::Canvas& canvas) -{ - if (!Meter::Draw(canvas)) return false; - - if (m_Image.IsLoaded()) - { - // Copy the image over the doublebuffer - Bitmap* drawBitmap = m_Image.GetImage(); - - int imageW = drawBitmap->GetWidth(); - int imageH = drawBitmap->GetHeight(); - - if (imageW == 0 || imageH == 0 || m_W == 0 || m_H == 0) return true; - - Gdiplus::Rect meterRect = GetMeterRectPadding(); - - int drawW = meterRect.Width; - int drawH = meterRect.Height; - - if (drawW == imageW && drawH == imageH && - m_ScaleMargins.left == 0 && m_ScaleMargins.top == 0 && m_ScaleMargins.right == 0 && m_ScaleMargins.bottom == 0) - { - canvas.DrawBitmap(drawBitmap, Rect(meterRect.X, meterRect.Y, drawW, drawH), Rect(0, 0, imageW, imageH)); - } - else if (m_DrawMode == DRAWMODE_TILE) - { - Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); - - ImageAttributes imgAttr; - imgAttr.SetWrapMode(WrapModeTile); - - Rect r(meterRect.X, meterRect.Y, drawW, drawH); - graphics.DrawImage(drawBitmap, r, 0, 0, drawW, drawH, UnitPixel, &imgAttr); - - canvas.EndGdiplusContext(); - } - else if (m_DrawMode == DRAWMODE_KEEPRATIO || m_DrawMode == DRAWMODE_KEEPRATIOANDCROP) - { - int cropX = 0; - int cropY = 0; - int cropW = imageW; - int cropH = imageH; - - if (m_WDefined && m_HDefined) - { - REAL imageRatio = imageW / (REAL)imageH; - REAL meterRatio = meterRect.Width / (REAL)meterRect.Height; - - if (imageRatio != meterRatio) - { - if (m_DrawMode == DRAWMODE_KEEPRATIO) - { - if (imageRatio > meterRatio) - { - drawH = meterRect.Width * imageH / imageW; - meterRect.Y += (meterRect.Height - drawH) / 2; - } - else - { - drawW = meterRect.Height * imageW / imageH; - meterRect.X += (meterRect.Width - drawW) / 2; - } - } - else - { - if (imageRatio > meterRatio) - { - cropW = (int)(imageH * meterRatio); - cropX = (imageW - cropW) / 2; - } - else - { - cropH = (int)(imageW / meterRatio); - cropY = (imageH - cropH) / 2; - } - } - } - } - - Rect r(meterRect.X, meterRect.Y, drawW, drawH); - canvas.DrawBitmap(drawBitmap, r, Rect(cropX, cropY, cropW, cropH)); - } - else - { - const RECT& m = m_ScaleMargins; - - if (m.top > 0) - { - if (m.left > 0) - { - // Top-Left - Rect r(meterRect.X, meterRect.Y, m.left, m.top); - canvas.DrawBitmap(drawBitmap, r, Rect(0, 0, m.left, m.top)); - } - - // Top - Rect r(meterRect.X + m.left, meterRect.Y, drawW - m.left - m.right, m.top); - canvas.DrawBitmap(drawBitmap, r, Rect(m.left, 0, imageW - m.left - m.right, m.top)); - - if (m.right > 0) - { - // Top-Right - Rect r(meterRect.X + drawW - m.right, meterRect.Y, m.right, m.top); - canvas.DrawBitmap(drawBitmap, r, Rect(imageW - m.right, 0, m.right, m.top)); - } - } - - if (m.left > 0) - { - // Left - Rect r(meterRect.X, meterRect.Y + m.top, m.left, drawH - m.top - m.bottom); - canvas.DrawBitmap(drawBitmap, r, Rect(0, m.top, m.left, imageH - m.top - m.bottom)); - } - - // Center - Rect r(meterRect.X + m.left, meterRect.Y + m.top, drawW - m.left - m.right, drawH - m.top - m.bottom); - canvas.DrawBitmap(drawBitmap, r, Rect(m.left, m.top, imageW - m.left - m.right, imageH - m.top - m.bottom)); - - if (m.right > 0) - { - // Right - Rect r(meterRect.X + drawW - m.right, meterRect.Y + m.top, m.right, drawH - m.top - m.bottom); - canvas.DrawBitmap(drawBitmap, r, Rect(imageW - m.right, m.top, m.right, imageH - m.top - m.bottom)); - } - - if (m.bottom > 0) - { - if (m.left > 0) - { - // Bottom-Left - Rect r(meterRect.X, meterRect.Y + drawH - m.bottom, m.left, m.bottom); - canvas.DrawBitmap(drawBitmap, r, Rect(0, imageH - m.bottom, m.left, m.bottom)); - } - - // Bottom - Rect r(meterRect.X + m.left, meterRect.Y + drawH - m.bottom, drawW - m.left - m.right, m.bottom); - canvas.DrawBitmap(drawBitmap, r, Rect(m.left, imageH - m.bottom, imageW - m.left - m.right, m.bottom)); - - if (m.right > 0) - { - // Bottom-Right - Rect r(meterRect.X + drawW - m.right, meterRect.Y + drawH - m.bottom, m.right, m.bottom); - canvas.DrawBitmap(drawBitmap, r, Rect(imageW - m.right, imageH - m.bottom, m.right, m.bottom)); - } - } - } - } - - return true; -} - -/* -** Overridden method. The Image meters need not to be bound on anything -** -*/ -void MeterImage::BindMeasures(ConfigParser& parser, const WCHAR* section) -{ - if (BindPrimaryMeasure(parser, section, true)) - { - BindSecondaryMeasures(parser, section); - } -} +/* + Copyright (C) 2002 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeterImage.h" +#include "Measure.h" +#include "Error.h" +#include "Rainmeter.h" +#include "System.h" +#include "../Common/PathUtil.h" +#include "../Common/Gfx/Canvas.h" + +using namespace Gdiplus; + +/* +** The constructor +** +*/ +MeterImage::MeterImage(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), + m_Image(L"ImageName", nullptr, false, meterWindow), + m_NeedsRedraw(false), + m_DrawMode(DRAWMODE_NONE), + m_ScaleMargins() +{ +} + +/* +** The destructor +** +*/ +MeterImage::~MeterImage() +{ +} + +/* +** Load the image and get the dimensions of the meter from it. +** +*/ +void MeterImage::Initialize() +{ + Meter::Initialize(); + + if (m_Measures.empty() && !m_DynamicVariables && !m_ImageName.empty()) + { + m_ImageNameResult = m_ImageName; + LoadImage(m_ImageName, true); + } +} + +/* +** Loads the image from disk +** +*/ +void MeterImage::LoadImage(const std::wstring& imageName, bool bLoadAlways) +{ + m_Image.LoadImage(imageName, bLoadAlways); + + if (m_Image.IsLoaded()) + { + // Calculate size of the meter + Bitmap* bitmap = m_Image.GetImage(); + + int imageW = bitmap->GetWidth(); + int imageH = bitmap->GetHeight(); + + if (m_WDefined) + { + if (!m_HDefined) + { + m_H = (imageW == 0) ? 0 : (m_DrawMode == DRAWMODE_TILE) ? imageH : m_W * imageH / imageW; + m_H += GetHeightPadding(); + } + } + else + { + if (m_HDefined) + { + m_W = (imageH == 0) ? 0 : (m_DrawMode == DRAWMODE_TILE) ? imageW : m_H * imageW / imageH; + m_W += GetWidthPadding(); + } + else + { + m_W = imageW + GetWidthPadding(); + m_H = imageH + GetHeightPadding(); + } + } + } +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeterImage::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + Meter::ReadOptions(parser, section); + + m_ImageName = parser.ReadString(section, L"ImageName", L""); + + int mode = parser.ReadInt(section, L"Tile", 0); + if (mode != 0) + { + m_DrawMode = DRAWMODE_TILE; + } + else + { + mode = parser.ReadInt(section, L"PreserveAspectRatio", 0); + switch (mode) + { + case 0: + m_DrawMode = DRAWMODE_NONE; + break; + case 1: + default: + m_DrawMode = DRAWMODE_KEEPRATIO; + break; + case 2: + m_DrawMode = DRAWMODE_KEEPRATIOANDCROP; + break; + } + } + + static const RECT defMargins = {0}; + m_ScaleMargins = parser.ReadRECT(section, L"ScaleMargins", defMargins); + + // Deprecated! + std::wstring path = parser.ReadString(section, L"Path", L""); + PathUtil::AppendBacklashIfMissing(path); + + // Read tinting options + m_Image.ReadOptions(parser, section, path.c_str()); + + if (m_Initialized && m_Measures.empty() && !m_DynamicVariables) + { + Initialize(); + m_NeedsRedraw = true; + } +} + +/* +** Updates the value(s) from the measures. +** +*/ +bool MeterImage::Update() +{ + if (Meter::Update()) + { + if (!m_Measures.empty() || m_DynamicVariables) + { + // Store the current values so we know if the image needs to be updated + std::wstring oldResult = m_ImageNameResult; + + if (!m_Measures.empty()) // read from the measures + { + if (m_ImageName.empty()) + { + m_ImageNameResult = m_Measures[0]->GetStringOrFormattedValue(AUTOSCALE_OFF, 1, 0, false); + } + else + { + m_ImageNameResult = m_ImageName; + if (!ReplaceMeasures(m_ImageNameResult, AUTOSCALE_OFF)) + { + // ImageName doesn't contain any measures, so use the result of MeasureName. + m_ImageNameResult = m_Measures[0]->GetStringOrFormattedValue(AUTOSCALE_OFF, 1, 0, false); + } + } + } + else // read from the skin + { + m_ImageNameResult = m_ImageName; + } + + LoadImage(m_ImageNameResult, (wcscmp(oldResult.c_str(), m_ImageNameResult.c_str()) != 0)); + return true; + } + else if (m_NeedsRedraw) + { + m_NeedsRedraw = false; + return true; + } + } + return false; +} + +/* +** Draws the meter on the double buffer +** +*/ +bool MeterImage::Draw(Gfx::Canvas& canvas) +{ + if (!Meter::Draw(canvas)) return false; + + if (m_Image.IsLoaded()) + { + // Copy the image over the doublebuffer + Bitmap* drawBitmap = m_Image.GetImage(); + + int imageW = drawBitmap->GetWidth(); + int imageH = drawBitmap->GetHeight(); + + if (imageW == 0 || imageH == 0 || m_W == 0 || m_H == 0) return true; + + Gdiplus::Rect meterRect = GetMeterRectPadding(); + + int drawW = meterRect.Width; + int drawH = meterRect.Height; + + if (drawW == imageW && drawH == imageH && + m_ScaleMargins.left == 0 && m_ScaleMargins.top == 0 && m_ScaleMargins.right == 0 && m_ScaleMargins.bottom == 0) + { + canvas.DrawBitmap(drawBitmap, Rect(meterRect.X, meterRect.Y, drawW, drawH), Rect(0, 0, imageW, imageH)); + } + else if (m_DrawMode == DRAWMODE_TILE) + { + Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); + + ImageAttributes imgAttr; + imgAttr.SetWrapMode(WrapModeTile); + + Rect r(meterRect.X, meterRect.Y, drawW, drawH); + graphics.DrawImage(drawBitmap, r, 0, 0, drawW, drawH, UnitPixel, &imgAttr); + + canvas.EndGdiplusContext(); + } + else if (m_DrawMode == DRAWMODE_KEEPRATIO || m_DrawMode == DRAWMODE_KEEPRATIOANDCROP) + { + int cropX = 0; + int cropY = 0; + int cropW = imageW; + int cropH = imageH; + + if (m_WDefined && m_HDefined) + { + REAL imageRatio = imageW / (REAL)imageH; + REAL meterRatio = meterRect.Width / (REAL)meterRect.Height; + + if (imageRatio != meterRatio) + { + if (m_DrawMode == DRAWMODE_KEEPRATIO) + { + if (imageRatio > meterRatio) + { + drawH = meterRect.Width * imageH / imageW; + meterRect.Y += (meterRect.Height - drawH) / 2; + } + else + { + drawW = meterRect.Height * imageW / imageH; + meterRect.X += (meterRect.Width - drawW) / 2; + } + } + else + { + if (imageRatio > meterRatio) + { + cropW = (int)(imageH * meterRatio); + cropX = (imageW - cropW) / 2; + } + else + { + cropH = (int)(imageW / meterRatio); + cropY = (imageH - cropH) / 2; + } + } + } + } + + Rect r(meterRect.X, meterRect.Y, drawW, drawH); + canvas.DrawBitmap(drawBitmap, r, Rect(cropX, cropY, cropW, cropH)); + } + else + { + const RECT& m = m_ScaleMargins; + + if (m.top > 0) + { + if (m.left > 0) + { + // Top-Left + Rect r(meterRect.X, meterRect.Y, m.left, m.top); + canvas.DrawBitmap(drawBitmap, r, Rect(0, 0, m.left, m.top)); + } + + // Top + Rect r(meterRect.X + m.left, meterRect.Y, drawW - m.left - m.right, m.top); + canvas.DrawBitmap(drawBitmap, r, Rect(m.left, 0, imageW - m.left - m.right, m.top)); + + if (m.right > 0) + { + // Top-Right + Rect r(meterRect.X + drawW - m.right, meterRect.Y, m.right, m.top); + canvas.DrawBitmap(drawBitmap, r, Rect(imageW - m.right, 0, m.right, m.top)); + } + } + + if (m.left > 0) + { + // Left + Rect r(meterRect.X, meterRect.Y + m.top, m.left, drawH - m.top - m.bottom); + canvas.DrawBitmap(drawBitmap, r, Rect(0, m.top, m.left, imageH - m.top - m.bottom)); + } + + // Center + Rect r(meterRect.X + m.left, meterRect.Y + m.top, drawW - m.left - m.right, drawH - m.top - m.bottom); + canvas.DrawBitmap(drawBitmap, r, Rect(m.left, m.top, imageW - m.left - m.right, imageH - m.top - m.bottom)); + + if (m.right > 0) + { + // Right + Rect r(meterRect.X + drawW - m.right, meterRect.Y + m.top, m.right, drawH - m.top - m.bottom); + canvas.DrawBitmap(drawBitmap, r, Rect(imageW - m.right, m.top, m.right, imageH - m.top - m.bottom)); + } + + if (m.bottom > 0) + { + if (m.left > 0) + { + // Bottom-Left + Rect r(meterRect.X, meterRect.Y + drawH - m.bottom, m.left, m.bottom); + canvas.DrawBitmap(drawBitmap, r, Rect(0, imageH - m.bottom, m.left, m.bottom)); + } + + // Bottom + Rect r(meterRect.X + m.left, meterRect.Y + drawH - m.bottom, drawW - m.left - m.right, m.bottom); + canvas.DrawBitmap(drawBitmap, r, Rect(m.left, imageH - m.bottom, imageW - m.left - m.right, m.bottom)); + + if (m.right > 0) + { + // Bottom-Right + Rect r(meterRect.X + drawW - m.right, meterRect.Y + drawH - m.bottom, m.right, m.bottom); + canvas.DrawBitmap(drawBitmap, r, Rect(imageW - m.right, imageH - m.bottom, m.right, m.bottom)); + } + } + } + } + + return true; +} + +/* +** Overridden method. The Image meters need not to be bound on anything +** +*/ +void MeterImage::BindMeasures(ConfigParser& parser, const WCHAR* section) +{ + if (BindPrimaryMeasure(parser, section, true)) + { + BindSecondaryMeasures(parser, section); + } +} diff --git a/Library/MeterImage.h b/Library/MeterImage.h index bf98bb67..ad4f98ed 100644 --- a/Library/MeterImage.h +++ b/Library/MeterImage.h @@ -1,67 +1,67 @@ -/* - Copyright (C) 2002 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __METERIMAGE_H__ -#define __METERIMAGE_H__ - -#include "Meter.h" -#include "TintedImage.h" - -class MeterImage : public Meter -{ -public: - MeterImage(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeterImage(); - - MeterImage(const MeterImage& other) = delete; - MeterImage& operator=(MeterImage other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - virtual void Initialize(); - virtual bool Update(); - virtual bool Draw(Gfx::Canvas& canvas); - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void BindMeasures(ConfigParser& parser, const WCHAR* section); - - virtual bool IsFixedSize(bool overwrite = false) { return overwrite ? true : m_ImageName.empty(); } - -private: - enum DRAWMODE - { - DRAWMODE_NONE = 0, - DRAWMODE_TILE, - DRAWMODE_KEEPRATIO, - DRAWMODE_KEEPRATIOANDCROP - }; - - void LoadImage(const std::wstring& imageName, bool bLoadAlways); - - TintedImage m_Image; - std::wstring m_ImageName; - std::wstring m_ImageNameResult; - - bool m_NeedsRedraw; - DRAWMODE m_DrawMode; - - RECT m_ScaleMargins; -}; - -#endif +/* + Copyright (C) 2002 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __METERIMAGE_H__ +#define __METERIMAGE_H__ + +#include "Meter.h" +#include "TintedImage.h" + +class MeterImage : public Meter +{ +public: + MeterImage(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeterImage(); + + MeterImage(const MeterImage& other) = delete; + MeterImage& operator=(MeterImage other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + virtual void Initialize(); + virtual bool Update(); + virtual bool Draw(Gfx::Canvas& canvas); + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void BindMeasures(ConfigParser& parser, const WCHAR* section); + + virtual bool IsFixedSize(bool overwrite = false) { return overwrite ? true : m_ImageName.empty(); } + +private: + enum DRAWMODE + { + DRAWMODE_NONE = 0, + DRAWMODE_TILE, + DRAWMODE_KEEPRATIO, + DRAWMODE_KEEPRATIOANDCROP + }; + + void LoadImage(const std::wstring& imageName, bool bLoadAlways); + + TintedImage m_Image; + std::wstring m_ImageName; + std::wstring m_ImageNameResult; + + bool m_NeedsRedraw; + DRAWMODE m_DrawMode; + + RECT m_ScaleMargins; +}; + +#endif diff --git a/Library/MeterLine.cpp b/Library/MeterLine.cpp index bebba731..2a981250 100644 --- a/Library/MeterLine.cpp +++ b/Library/MeterLine.cpp @@ -1,449 +1,449 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeterLine.h" -#include "Measure.h" -#include "Logger.h" -#include "../Common/Gfx/Canvas.h" - -using namespace Gdiplus; - -/* -** The constructor -** -*/ -MeterLine::MeterLine(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), - m_Autoscale(false), - m_HorizontalLines(false), - m_Flip(false), - m_LineWidth(1.0), - m_HorizontalColor(Color::Black), - m_CurrentPos(), - m_GraphStartLeft(false), - m_GraphHorizontalOrientation(false) -{ -} - -/* -** The destructor -** -*/ -MeterLine::~MeterLine() -{ -} - -/* -** create the buffer for the lines -** -*/ -void MeterLine::Initialize() -{ - Meter::Initialize(); - - size_t colorsSize = m_Colors.size(); - size_t allValuesSize = m_AllValues.size(); - size_t num = (allValuesSize > 0) ? m_AllValues[0].size() : 0; - int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; - - if (colorsSize != allValuesSize) - { - if (colorsSize > allValuesSize) - { - for (size_t i = allValuesSize; i < colorsSize; ++i) - { - m_AllValues.push_back(std::vector()); - - if (maxSize > 0) - { - m_AllValues.back().assign(maxSize, 0.0); - } - } - } - else - { - m_AllValues.resize(colorsSize); - } - } - - if (maxSize < 0 || num != (size_t)maxSize) - { - if (m_CurrentPos >= maxSize) m_CurrentPos = 0; - - num = (maxSize < 0) ? 0 : maxSize; - for (size_t i = 0; i < allValuesSize; ++i) - { - if (num != m_AllValues[i].size()) - { - m_AllValues[i].resize(num, 0.0); - } - } - } -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeterLine::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - WCHAR tmpName[64]; - - // Store the current number of lines so we know if the buffer needs to be updated - int oldLineCount = (int)m_Colors.size(); - int oldSize = m_GraphHorizontalOrientation ? m_H : m_W; - bool oldGraphHorizontalOrientation = m_GraphHorizontalOrientation; - - Meter::ReadOptions(parser, section); - - int lineCount = parser.ReadInt(section, L"LineCount", 1); - - m_Colors.clear(); - m_ScaleValues.clear(); - - for (int i = 0; i < lineCount; ++i) - { - if (i == 0) - { - wcsncpy_s(tmpName, L"LineColor", _TRUNCATE); - } - else - { - _snwprintf_s(tmpName, _TRUNCATE, L"LineColor%i", i + 1); - } - - m_Colors.push_back(parser.ReadColor(section, tmpName, Color::White)); - - if (i == 0) - { - wcsncpy_s(tmpName, L"Scale", _TRUNCATE); - } - else - { - _snwprintf_s(tmpName, _TRUNCATE, L"Scale%i", i + 1); - } - - m_ScaleValues.push_back(parser.ReadFloat(section, tmpName, 1.0)); - } - - m_Flip = parser.ReadBool(section, L"Flip", false); - m_Autoscale = parser.ReadBool(section, L"AutoScale", false); - m_LineWidth = parser.ReadFloat(section, L"LineWidth", 1.0); - m_HorizontalLines = parser.ReadBool(section, L"HorizontalLines", false); - ARGB color = parser.ReadColor(section, L"HorizontalColor", Color::Black); // This is left here for backwards compatibility - m_HorizontalColor = parser.ReadColor(section, L"HorizontalLineColor", color); // This is what it should be - - const WCHAR* graph = parser.ReadString(section, L"GraphStart", L"RIGHT").c_str(); - if (_wcsicmp(graph, L"RIGHT") == 0) - { - m_GraphStartLeft = false; - } - else if (_wcsicmp(graph, L"LEFT") == 0) - { - m_GraphStartLeft = true; - } - else - { - LogErrorF(this, L"GraphStart=%s is not valid", graph); - } - - graph = parser.ReadString(section, L"GraphOrientation", L"VERTICAL").c_str(); - if (_wcsicmp(graph, L"VERTICAL") == 0) - { - m_GraphHorizontalOrientation = false; - } - else if (_wcsicmp(graph, L"HORIZONTAL") == 0) - { - m_GraphHorizontalOrientation = true; - } - else - { - LogErrorF(this, L"GraphOrientation=%s is not valid", graph); - } - - if (m_Initialized) - { - int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; - if (oldLineCount != lineCount || oldSize != maxSize || oldGraphHorizontalOrientation != m_GraphHorizontalOrientation) - { - m_AllValues.clear(); - m_CurrentPos = 0; - Initialize(); - } - } -} - -/* -** Updates the value(s) from the measures. -** -*/ -bool MeterLine::Update() -{ - if (Meter::Update() && !m_Measures.empty()) - { - int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; - - if (maxSize > 0) - { - int allValuesSize = (int)m_AllValues.size(); - int counter = 0; - for (auto i = m_Measures.cbegin(); counter < allValuesSize && i != m_Measures.cend(); ++i, ++counter) - { - m_AllValues[counter][m_CurrentPos] = (*i)->GetValue(); - } - - ++m_CurrentPos; - m_CurrentPos %= maxSize; - } - return true; - } - return false; -} - -/* -** Draws the meter on the double buffer -** -*/ -bool MeterLine::Draw(Gfx::Canvas& canvas) -{ - int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; - if (!Meter::Draw(canvas) || maxSize <= 0) return false; - - Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); - - double maxValue = 0.0; - int counter = 0; - - // Find the maximum value - if (m_Autoscale) - { - double newValue = 0; - counter = 0; - for (auto i = m_AllValues.cbegin(); i != m_AllValues.cend(); ++i) - { - double scale = m_ScaleValues[counter]; - for (auto j = (*i).cbegin(); j != (*i).cend(); ++j) - { - double val = (*j) * scale; - newValue = max(newValue, val); - } - ++counter; - } - - // Scale the value up to nearest power of 2 - if (newValue > DBL_MAX / 2.0) - { - maxValue = DBL_MAX; - } - else - { - maxValue = 2.0; - while (maxValue < newValue) - { - maxValue *= 2.0; - } - } - } - else - { - for (auto i = m_Measures.cbegin(); i != m_Measures.cend(); ++i) - { - double val = (*i)->GetMaxValue(); - maxValue = max(maxValue, val); - } - - if (maxValue == 0.0) - { - maxValue = 1.0; - } - } - - Gdiplus::Rect meterRect = GetMeterRectPadding(); - - // Draw the horizontal lines - if (m_HorizontalLines) - { - // Calc the max number of lines we should draw - int maxLines = meterRect.Height / 4; // one line per 4 pixels is max - int numOfLines; - - // Check the highest power of 2 that fits in maxLines - int power = 2; - while (power < maxLines) - { - power *= 2; - } - - numOfLines = ((int)maxValue % power) + 1; - - Pen pen(m_HorizontalColor); - - REAL Y; - for (int j = 0; j < numOfLines; ++j) - { - Y = (REAL)((j + 1) * meterRect.Height / (numOfLines + 1)); - Y = meterRect.Y + meterRect.Height - Y - 1; - graphics.DrawLine(&pen, (REAL)meterRect.X, Y, (REAL)(meterRect.X + meterRect.Width - 1), Y); // GDI+ - } - } - - // Draw all the lines - - if (m_GraphHorizontalOrientation) - { - const REAL W = meterRect.Width - 1.0f; - counter = 0; - for (auto i = m_AllValues.cbegin(); i != m_AllValues.cend(); ++i) - { - // Draw a line - REAL X, oldX; - - const double scale = m_ScaleValues[counter] * W / maxValue; - - int pos = m_CurrentPos; - - auto calcX = [&](REAL& _x) - { - _x = (REAL)((*i)[pos] * scale); - _x = min(_x, W); - _x = max(_x, 0.0f); - _x = meterRect.X + (m_GraphStartLeft ? _x : W - _x); - }; - - calcX(oldX); - - // Cache all lines - GraphicsPath path; - - if (!m_Flip) - { - for (int j = meterRect.Y + 1, R = meterRect.Y + meterRect.Height; j < R; ++j) - { - ++pos; - pos %= meterRect.Height; - - calcX(X); - - path.AddLine(oldX, (REAL)(j - 1), X, (REAL)j); - - oldX = X; - } - } - else - { - for (int j = meterRect.Y + meterRect.Height, R = meterRect.Y + 1; j > R; --j) - { - ++pos; - pos %= meterRect.Height; - - calcX(X); - - path.AddLine(oldX, (REAL)(j - 1), X, (REAL)(j - 2)); - - oldX = X; - } - } - - // Draw cached lines - Pen pen(m_Colors[counter], (REAL)m_LineWidth); - pen.SetLineJoin(LineJoinBevel); - graphics.DrawPath(&pen, &path); - - ++counter; - } - } - else - { - const REAL H = meterRect.Height - 1.0f; - counter = 0; - for (auto i = m_AllValues.cbegin(); i != m_AllValues.cend(); ++i) - { - // Draw a line - REAL Y, oldY; - - const double scale = m_ScaleValues[counter] * H / maxValue; - - int pos = m_CurrentPos; - - auto calcY = [&](REAL& _y) - { - _y = (REAL)((*i)[pos] * scale); - _y = min(_y, H); - _y = max(_y, 0.0f); - _y = meterRect.Y + (m_Flip ? _y : H - _y); - }; - - calcY(oldY); - - // Cache all lines - GraphicsPath path; - - if (!m_GraphStartLeft) - { - for (int j = meterRect.X + 1, R = meterRect.X + meterRect.Width; j < R; ++j) - { - ++pos; - pos %= meterRect.Width; - - calcY(Y); - - path.AddLine((REAL)(j - 1), oldY, (REAL)j, Y); - - oldY = Y; - } - } - else - { - for (int j = meterRect.X + meterRect.Width, R = meterRect.X + 1; j > R; --j) - { - ++pos; - pos %= meterRect.Width; - - calcY(Y); - - path.AddLine((REAL)(j - 1), oldY, (REAL)(j - 2), Y); - - oldY = Y; - } - } - - // Draw cached lines - Pen pen(m_Colors[counter], (REAL)m_LineWidth); - pen.SetLineJoin(LineJoinBevel); - graphics.DrawPath(&pen, &path); - - ++counter; - } - } - - canvas.EndGdiplusContext(); - - return true; -} - -/* -** Overwritten method to handle the other measure bindings. -** -*/ -void MeterLine::BindMeasures(ConfigParser& parser, const WCHAR* section) -{ - if (BindPrimaryMeasure(parser, section, false)) - { - BindSecondaryMeasures(parser, section); - } -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeterLine.h" +#include "Measure.h" +#include "Logger.h" +#include "../Common/Gfx/Canvas.h" + +using namespace Gdiplus; + +/* +** The constructor +** +*/ +MeterLine::MeterLine(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), + m_Autoscale(false), + m_HorizontalLines(false), + m_Flip(false), + m_LineWidth(1.0), + m_HorizontalColor(Color::Black), + m_CurrentPos(), + m_GraphStartLeft(false), + m_GraphHorizontalOrientation(false) +{ +} + +/* +** The destructor +** +*/ +MeterLine::~MeterLine() +{ +} + +/* +** create the buffer for the lines +** +*/ +void MeterLine::Initialize() +{ + Meter::Initialize(); + + size_t colorsSize = m_Colors.size(); + size_t allValuesSize = m_AllValues.size(); + size_t num = (allValuesSize > 0) ? m_AllValues[0].size() : 0; + int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; + + if (colorsSize != allValuesSize) + { + if (colorsSize > allValuesSize) + { + for (size_t i = allValuesSize; i < colorsSize; ++i) + { + m_AllValues.push_back(std::vector()); + + if (maxSize > 0) + { + m_AllValues.back().assign(maxSize, 0.0); + } + } + } + else + { + m_AllValues.resize(colorsSize); + } + } + + if (maxSize < 0 || num != (size_t)maxSize) + { + if (m_CurrentPos >= maxSize) m_CurrentPos = 0; + + num = (maxSize < 0) ? 0 : maxSize; + for (size_t i = 0; i < allValuesSize; ++i) + { + if (num != m_AllValues[i].size()) + { + m_AllValues[i].resize(num, 0.0); + } + } + } +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeterLine::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + WCHAR tmpName[64]; + + // Store the current number of lines so we know if the buffer needs to be updated + int oldLineCount = (int)m_Colors.size(); + int oldSize = m_GraphHorizontalOrientation ? m_H : m_W; + bool oldGraphHorizontalOrientation = m_GraphHorizontalOrientation; + + Meter::ReadOptions(parser, section); + + int lineCount = parser.ReadInt(section, L"LineCount", 1); + + m_Colors.clear(); + m_ScaleValues.clear(); + + for (int i = 0; i < lineCount; ++i) + { + if (i == 0) + { + wcsncpy_s(tmpName, L"LineColor", _TRUNCATE); + } + else + { + _snwprintf_s(tmpName, _TRUNCATE, L"LineColor%i", i + 1); + } + + m_Colors.push_back(parser.ReadColor(section, tmpName, Color::White)); + + if (i == 0) + { + wcsncpy_s(tmpName, L"Scale", _TRUNCATE); + } + else + { + _snwprintf_s(tmpName, _TRUNCATE, L"Scale%i", i + 1); + } + + m_ScaleValues.push_back(parser.ReadFloat(section, tmpName, 1.0)); + } + + m_Flip = parser.ReadBool(section, L"Flip", false); + m_Autoscale = parser.ReadBool(section, L"AutoScale", false); + m_LineWidth = parser.ReadFloat(section, L"LineWidth", 1.0); + m_HorizontalLines = parser.ReadBool(section, L"HorizontalLines", false); + ARGB color = parser.ReadColor(section, L"HorizontalColor", Color::Black); // This is left here for backwards compatibility + m_HorizontalColor = parser.ReadColor(section, L"HorizontalLineColor", color); // This is what it should be + + const WCHAR* graph = parser.ReadString(section, L"GraphStart", L"RIGHT").c_str(); + if (_wcsicmp(graph, L"RIGHT") == 0) + { + m_GraphStartLeft = false; + } + else if (_wcsicmp(graph, L"LEFT") == 0) + { + m_GraphStartLeft = true; + } + else + { + LogErrorF(this, L"GraphStart=%s is not valid", graph); + } + + graph = parser.ReadString(section, L"GraphOrientation", L"VERTICAL").c_str(); + if (_wcsicmp(graph, L"VERTICAL") == 0) + { + m_GraphHorizontalOrientation = false; + } + else if (_wcsicmp(graph, L"HORIZONTAL") == 0) + { + m_GraphHorizontalOrientation = true; + } + else + { + LogErrorF(this, L"GraphOrientation=%s is not valid", graph); + } + + if (m_Initialized) + { + int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; + if (oldLineCount != lineCount || oldSize != maxSize || oldGraphHorizontalOrientation != m_GraphHorizontalOrientation) + { + m_AllValues.clear(); + m_CurrentPos = 0; + Initialize(); + } + } +} + +/* +** Updates the value(s) from the measures. +** +*/ +bool MeterLine::Update() +{ + if (Meter::Update() && !m_Measures.empty()) + { + int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; + + if (maxSize > 0) + { + int allValuesSize = (int)m_AllValues.size(); + int counter = 0; + for (auto i = m_Measures.cbegin(); counter < allValuesSize && i != m_Measures.cend(); ++i, ++counter) + { + m_AllValues[counter][m_CurrentPos] = (*i)->GetValue(); + } + + ++m_CurrentPos; + m_CurrentPos %= maxSize; + } + return true; + } + return false; +} + +/* +** Draws the meter on the double buffer +** +*/ +bool MeterLine::Draw(Gfx::Canvas& canvas) +{ + int maxSize = m_GraphHorizontalOrientation ? m_H : m_W; + if (!Meter::Draw(canvas) || maxSize <= 0) return false; + + Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); + + double maxValue = 0.0; + int counter = 0; + + // Find the maximum value + if (m_Autoscale) + { + double newValue = 0; + counter = 0; + for (auto i = m_AllValues.cbegin(); i != m_AllValues.cend(); ++i) + { + double scale = m_ScaleValues[counter]; + for (auto j = (*i).cbegin(); j != (*i).cend(); ++j) + { + double val = (*j) * scale; + newValue = max(newValue, val); + } + ++counter; + } + + // Scale the value up to nearest power of 2 + if (newValue > DBL_MAX / 2.0) + { + maxValue = DBL_MAX; + } + else + { + maxValue = 2.0; + while (maxValue < newValue) + { + maxValue *= 2.0; + } + } + } + else + { + for (auto i = m_Measures.cbegin(); i != m_Measures.cend(); ++i) + { + double val = (*i)->GetMaxValue(); + maxValue = max(maxValue, val); + } + + if (maxValue == 0.0) + { + maxValue = 1.0; + } + } + + Gdiplus::Rect meterRect = GetMeterRectPadding(); + + // Draw the horizontal lines + if (m_HorizontalLines) + { + // Calc the max number of lines we should draw + int maxLines = meterRect.Height / 4; // one line per 4 pixels is max + int numOfLines; + + // Check the highest power of 2 that fits in maxLines + int power = 2; + while (power < maxLines) + { + power *= 2; + } + + numOfLines = ((int)maxValue % power) + 1; + + Pen pen(m_HorizontalColor); + + REAL Y; + for (int j = 0; j < numOfLines; ++j) + { + Y = (REAL)((j + 1) * meterRect.Height / (numOfLines + 1)); + Y = meterRect.Y + meterRect.Height - Y - 1; + graphics.DrawLine(&pen, (REAL)meterRect.X, Y, (REAL)(meterRect.X + meterRect.Width - 1), Y); // GDI+ + } + } + + // Draw all the lines + + if (m_GraphHorizontalOrientation) + { + const REAL W = meterRect.Width - 1.0f; + counter = 0; + for (auto i = m_AllValues.cbegin(); i != m_AllValues.cend(); ++i) + { + // Draw a line + REAL X, oldX; + + const double scale = m_ScaleValues[counter] * W / maxValue; + + int pos = m_CurrentPos; + + auto calcX = [&](REAL& _x) + { + _x = (REAL)((*i)[pos] * scale); + _x = min(_x, W); + _x = max(_x, 0.0f); + _x = meterRect.X + (m_GraphStartLeft ? _x : W - _x); + }; + + calcX(oldX); + + // Cache all lines + GraphicsPath path; + + if (!m_Flip) + { + for (int j = meterRect.Y + 1, R = meterRect.Y + meterRect.Height; j < R; ++j) + { + ++pos; + pos %= meterRect.Height; + + calcX(X); + + path.AddLine(oldX, (REAL)(j - 1), X, (REAL)j); + + oldX = X; + } + } + else + { + for (int j = meterRect.Y + meterRect.Height, R = meterRect.Y + 1; j > R; --j) + { + ++pos; + pos %= meterRect.Height; + + calcX(X); + + path.AddLine(oldX, (REAL)(j - 1), X, (REAL)(j - 2)); + + oldX = X; + } + } + + // Draw cached lines + Pen pen(m_Colors[counter], (REAL)m_LineWidth); + pen.SetLineJoin(LineJoinBevel); + graphics.DrawPath(&pen, &path); + + ++counter; + } + } + else + { + const REAL H = meterRect.Height - 1.0f; + counter = 0; + for (auto i = m_AllValues.cbegin(); i != m_AllValues.cend(); ++i) + { + // Draw a line + REAL Y, oldY; + + const double scale = m_ScaleValues[counter] * H / maxValue; + + int pos = m_CurrentPos; + + auto calcY = [&](REAL& _y) + { + _y = (REAL)((*i)[pos] * scale); + _y = min(_y, H); + _y = max(_y, 0.0f); + _y = meterRect.Y + (m_Flip ? _y : H - _y); + }; + + calcY(oldY); + + // Cache all lines + GraphicsPath path; + + if (!m_GraphStartLeft) + { + for (int j = meterRect.X + 1, R = meterRect.X + meterRect.Width; j < R; ++j) + { + ++pos; + pos %= meterRect.Width; + + calcY(Y); + + path.AddLine((REAL)(j - 1), oldY, (REAL)j, Y); + + oldY = Y; + } + } + else + { + for (int j = meterRect.X + meterRect.Width, R = meterRect.X + 1; j > R; --j) + { + ++pos; + pos %= meterRect.Width; + + calcY(Y); + + path.AddLine((REAL)(j - 1), oldY, (REAL)(j - 2), Y); + + oldY = Y; + } + } + + // Draw cached lines + Pen pen(m_Colors[counter], (REAL)m_LineWidth); + pen.SetLineJoin(LineJoinBevel); + graphics.DrawPath(&pen, &path); + + ++counter; + } + } + + canvas.EndGdiplusContext(); + + return true; +} + +/* +** Overwritten method to handle the other measure bindings. +** +*/ +void MeterLine::BindMeasures(ConfigParser& parser, const WCHAR* section) +{ + if (BindPrimaryMeasure(parser, section, false)) + { + BindSecondaryMeasures(parser, section); + } +} diff --git a/Library/MeterLine.h b/Library/MeterLine.h index cca32e7c..568c9fdf 100644 --- a/Library/MeterLine.h +++ b/Library/MeterLine.h @@ -1,60 +1,60 @@ -/* - Copyright (C) 2002 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __METERLINE_H__ -#define __METERLINE_H__ - -#include "Meter.h" - -class MeterLine : public Meter -{ -public: - MeterLine(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeterLine(); - - MeterLine(const MeterLine& other) = delete; - MeterLine& operator=(MeterLine other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - virtual void Initialize(); - virtual bool Update(); - virtual bool Draw(Gfx::Canvas& canvas); - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void BindMeasures(ConfigParser& parser, const WCHAR* section); - -private: - std::vector m_Colors; - std::vector m_ScaleValues; - - bool m_Autoscale; - bool m_HorizontalLines; - bool m_Flip; - double m_LineWidth; - Gdiplus::Color m_HorizontalColor; - - std::vector< std::vector > m_AllValues; - int m_CurrentPos; - - bool m_GraphStartLeft; - bool m_GraphHorizontalOrientation; -}; - -#endif +/* + Copyright (C) 2002 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __METERLINE_H__ +#define __METERLINE_H__ + +#include "Meter.h" + +class MeterLine : public Meter +{ +public: + MeterLine(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeterLine(); + + MeterLine(const MeterLine& other) = delete; + MeterLine& operator=(MeterLine other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + virtual void Initialize(); + virtual bool Update(); + virtual bool Draw(Gfx::Canvas& canvas); + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void BindMeasures(ConfigParser& parser, const WCHAR* section); + +private: + std::vector m_Colors; + std::vector m_ScaleValues; + + bool m_Autoscale; + bool m_HorizontalLines; + bool m_Flip; + double m_LineWidth; + Gdiplus::Color m_HorizontalColor; + + std::vector< std::vector > m_AllValues; + int m_CurrentPos; + + bool m_GraphStartLeft; + bool m_GraphHorizontalOrientation; +}; + +#endif diff --git a/Library/MeterRotator.cpp b/Library/MeterRotator.cpp index 83829387..fa6e2e1a 100644 --- a/Library/MeterRotator.cpp +++ b/Library/MeterRotator.cpp @@ -1,183 +1,183 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeterRotator.h" -#include "Measure.h" -#include "Error.h" -#include "Litestep.h" -#include "Rainmeter.h" -#include "../Common/Gfx/Canvas.h" - -using namespace Gdiplus; - -#define PI (3.14159265358979323846) -#define CONVERT_TO_DEGREES(X) ((X) * (180.0 / PI)) - -/* -** The constructor -** -*/ -MeterRotator::MeterRotator(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), - m_Image(L"ImageName", nullptr, false, meterWindow), - m_NeedsReload(false), - m_OffsetX(), - m_OffsetY(), - m_StartAngle(), - m_RotationAngle(PI * 2.0), - m_ValueRemainder(), - m_Value() -{ -} - -/* -** The destructor -** -*/ -MeterRotator::~MeterRotator() -{ -} - -/* -** Load the image. -** -*/ -void MeterRotator::Initialize() -{ - Meter::Initialize(); - - // Load the bitmaps if defined - if (!m_ImageName.empty()) - { - m_Image.LoadImage(m_ImageName, m_NeedsReload); - } - else if (m_Image.IsLoaded()) - { - m_Image.DisposeImage(); - } -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeterRotator::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - // Store the current values so we know if the image needs to be updated - std::wstring oldImageName = m_ImageName; - - Meter::ReadOptions(parser, section); - - m_ImageName = parser.ReadString(section, L"ImageName", L""); - if (!m_ImageName.empty()) - { - // Read tinting options - m_Image.ReadOptions(parser, section); - } - else - { - m_Image.ClearOptionFlags(); - } - - m_OffsetX = parser.ReadFloat(section, L"OffsetX", 0.0); - m_OffsetY = parser.ReadFloat(section, L"OffsetY", 0.0); - m_StartAngle = parser.ReadFloat(section, L"StartAngle", 0.0); - m_RotationAngle = parser.ReadFloat(section, L"RotationAngle", PI * 2.0); - - m_ValueRemainder = parser.ReadInt(section, L"ValueReminder", 0); // Typo - m_ValueRemainder = parser.ReadInt(section, L"ValueRemainder", m_ValueRemainder); - - if (m_Initialized) - { - m_NeedsReload = (wcscmp(oldImageName.c_str(), m_ImageName.c_str()) != 0); - - if (m_NeedsReload || - m_Image.IsOptionsChanged()) - { - Initialize(); // Reload the image - } - } -} - -/* -** Updates the value(s) from the measures. -** -*/ -bool MeterRotator::Update() -{ - if (Meter::Update() && !m_Measures.empty()) - { - Measure* measure = m_Measures[0]; - if (m_ValueRemainder > 0) - { - LONGLONG time = (LONGLONG)measure->GetValue(); - m_Value = (double)(time % m_ValueRemainder); - m_Value /= (double)m_ValueRemainder; - } - else - { - m_Value = measure->GetRelativeValue(); - } - return true; - } - return false; -} - - -/* -** Draws the meter on the double buffer -** -*/ -bool MeterRotator::Draw(Gfx::Canvas& canvas) -{ - if (!Meter::Draw(canvas)) return false; - - Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); - - if (m_Image.IsLoaded()) - { - // Calculate the center for rotation - int x = GetX(); - int y = GetY(); - - REAL cx = (REAL)(x + m_W / 2.0); - REAL cy = (REAL)(y + m_H / 2.0); - - // Calculate the rotation - REAL angle = (REAL)(CONVERT_TO_DEGREES(m_RotationAngle * m_Value + m_StartAngle)); - - // TODO: convert to Canvas: canvas.RotateTransform(angle, cx, cy, (REAL)-m_OffsetX, (REAL)-m_OffsetY); - graphics.TranslateTransform(cx, cy); - graphics.RotateTransform(angle); - graphics.TranslateTransform((REAL)-m_OffsetX, (REAL)-m_OffsetY); - - Bitmap* drawBitmap = m_Image.GetImage(); - - UINT width = drawBitmap->GetWidth(); - UINT height = drawBitmap->GetHeight(); - - // Blit the image - graphics.DrawImage(drawBitmap, 0, 0, width, height); - - graphics.ResetTransform(); - } - - canvas.EndGdiplusContext(); - - return true; -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeterRotator.h" +#include "Measure.h" +#include "Error.h" +#include "Litestep.h" +#include "Rainmeter.h" +#include "../Common/Gfx/Canvas.h" + +using namespace Gdiplus; + +#define PI (3.14159265358979323846) +#define CONVERT_TO_DEGREES(X) ((X) * (180.0 / PI)) + +/* +** The constructor +** +*/ +MeterRotator::MeterRotator(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), + m_Image(L"ImageName", nullptr, false, meterWindow), + m_NeedsReload(false), + m_OffsetX(), + m_OffsetY(), + m_StartAngle(), + m_RotationAngle(PI * 2.0), + m_ValueRemainder(), + m_Value() +{ +} + +/* +** The destructor +** +*/ +MeterRotator::~MeterRotator() +{ +} + +/* +** Load the image. +** +*/ +void MeterRotator::Initialize() +{ + Meter::Initialize(); + + // Load the bitmaps if defined + if (!m_ImageName.empty()) + { + m_Image.LoadImage(m_ImageName, m_NeedsReload); + } + else if (m_Image.IsLoaded()) + { + m_Image.DisposeImage(); + } +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeterRotator::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + // Store the current values so we know if the image needs to be updated + std::wstring oldImageName = m_ImageName; + + Meter::ReadOptions(parser, section); + + m_ImageName = parser.ReadString(section, L"ImageName", L""); + if (!m_ImageName.empty()) + { + // Read tinting options + m_Image.ReadOptions(parser, section); + } + else + { + m_Image.ClearOptionFlags(); + } + + m_OffsetX = parser.ReadFloat(section, L"OffsetX", 0.0); + m_OffsetY = parser.ReadFloat(section, L"OffsetY", 0.0); + m_StartAngle = parser.ReadFloat(section, L"StartAngle", 0.0); + m_RotationAngle = parser.ReadFloat(section, L"RotationAngle", PI * 2.0); + + m_ValueRemainder = parser.ReadInt(section, L"ValueReminder", 0); // Typo + m_ValueRemainder = parser.ReadInt(section, L"ValueRemainder", m_ValueRemainder); + + if (m_Initialized) + { + m_NeedsReload = (wcscmp(oldImageName.c_str(), m_ImageName.c_str()) != 0); + + if (m_NeedsReload || + m_Image.IsOptionsChanged()) + { + Initialize(); // Reload the image + } + } +} + +/* +** Updates the value(s) from the measures. +** +*/ +bool MeterRotator::Update() +{ + if (Meter::Update() && !m_Measures.empty()) + { + Measure* measure = m_Measures[0]; + if (m_ValueRemainder > 0) + { + LONGLONG time = (LONGLONG)measure->GetValue(); + m_Value = (double)(time % m_ValueRemainder); + m_Value /= (double)m_ValueRemainder; + } + else + { + m_Value = measure->GetRelativeValue(); + } + return true; + } + return false; +} + + +/* +** Draws the meter on the double buffer +** +*/ +bool MeterRotator::Draw(Gfx::Canvas& canvas) +{ + if (!Meter::Draw(canvas)) return false; + + Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); + + if (m_Image.IsLoaded()) + { + // Calculate the center for rotation + int x = GetX(); + int y = GetY(); + + REAL cx = (REAL)(x + m_W / 2.0); + REAL cy = (REAL)(y + m_H / 2.0); + + // Calculate the rotation + REAL angle = (REAL)(CONVERT_TO_DEGREES(m_RotationAngle * m_Value + m_StartAngle)); + + // TODO: convert to Canvas: canvas.RotateTransform(angle, cx, cy, (REAL)-m_OffsetX, (REAL)-m_OffsetY); + graphics.TranslateTransform(cx, cy); + graphics.RotateTransform(angle); + graphics.TranslateTransform((REAL)-m_OffsetX, (REAL)-m_OffsetY); + + Bitmap* drawBitmap = m_Image.GetImage(); + + UINT width = drawBitmap->GetWidth(); + UINT height = drawBitmap->GetHeight(); + + // Blit the image + graphics.DrawImage(drawBitmap, 0, 0, width, height); + + graphics.ResetTransform(); + } + + canvas.EndGdiplusContext(); + + return true; +} diff --git a/Library/MeterRotator.h b/Library/MeterRotator.h index 243e12c5..2977bc3f 100644 --- a/Library/MeterRotator.h +++ b/Library/MeterRotator.h @@ -1,56 +1,56 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __METERROTATOR_H__ -#define __METERROTATOR_H__ - -#include "Meter.h" -#include "TintedImage.h" - -class MeterRotator : public Meter -{ -public: - MeterRotator(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeterRotator(); - - MeterRotator(const MeterRotator& other) = delete; - MeterRotator& operator=(MeterRotator other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - virtual void Initialize(); - virtual bool Update(); - virtual bool Draw(Gfx::Canvas& canvas); - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - -private: - TintedImage m_Image; - std::wstring m_ImageName; - bool m_NeedsReload; - - double m_OffsetX; - double m_OffsetY; - double m_StartAngle; - double m_RotationAngle; - UINT m_ValueRemainder; - double m_Value; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __METERROTATOR_H__ +#define __METERROTATOR_H__ + +#include "Meter.h" +#include "TintedImage.h" + +class MeterRotator : public Meter +{ +public: + MeterRotator(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeterRotator(); + + MeterRotator(const MeterRotator& other) = delete; + MeterRotator& operator=(MeterRotator other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + virtual void Initialize(); + virtual bool Update(); + virtual bool Draw(Gfx::Canvas& canvas); + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + +private: + TintedImage m_Image; + std::wstring m_ImageName; + bool m_NeedsReload; + + double m_OffsetX; + double m_OffsetY; + double m_StartAngle; + double m_RotationAngle; + UINT m_ValueRemainder; + double m_Value; +}; + +#endif diff --git a/Library/MeterRoundLine.cpp b/Library/MeterRoundLine.cpp index 08e72e4e..f78574aa 100644 --- a/Library/MeterRoundLine.cpp +++ b/Library/MeterRoundLine.cpp @@ -1,182 +1,182 @@ -/* - Copyright (C) 2009 Kimmo Pekkola, Brian Todoroff - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeterRoundLine.h" -#include "Measure.h" -#include "Error.h" -#include "../Common/Gfx/Canvas.h" - -using namespace Gdiplus; - -#define PI (3.14159265358979323846) -#define CONVERT_TO_DEGREES(X) ((X) * (180.0 / PI)) - -/* -** The constructor -** -*/ -MeterRoundLine::MeterRoundLine(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), - m_Solid(false), - m_LineWidth(1.0), - m_LineLength(20.0), - m_LineStart(-1.0), - m_StartAngle(), - m_RotationAngle(6.2832), - m_CntrlAngle(true), - m_CntrlLineStart(false), - m_CntrlLineLength(false), - m_LineStartShift(), - m_LineLengthShift(), - m_ValueRemainder(), - m_LineColor(Color::Black), - m_Value() -{ -} - -/* -** The destructor -** -*/ -MeterRoundLine::~MeterRoundLine() -{ -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeterRoundLine::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - Meter::ReadOptions(parser, section); - - m_LineWidth = parser.ReadFloat(section, L"LineWidth", 1.0); - m_LineLength = parser.ReadFloat(section, L"LineLength", 20.0); - m_LineStart = parser.ReadFloat(section, L"LineStart", -1.0); - m_StartAngle = parser.ReadFloat(section, L"StartAngle", 0.0); - m_RotationAngle = parser.ReadFloat(section, L"RotationAngle", 6.2832); - m_ValueRemainder = parser.ReadInt(section, L"ValueReminder", 0); // Typo - m_ValueRemainder = parser.ReadInt(section, L"ValueRemainder", m_ValueRemainder); - m_LineColor = parser.ReadColor(section, L"LineColor", Color::Black); - m_Solid = parser.ReadBool(section, L"Solid", false); - m_CntrlAngle = parser.ReadBool(section, L"ControlAngle", true); - m_CntrlLineStart = parser.ReadBool(section, L"ControlStart", false); - m_CntrlLineLength = parser.ReadBool(section, L"ControlLength", false); - m_LineStartShift = parser.ReadFloat(section, L"StartShift", 0.0); - m_LineLengthShift = parser.ReadFloat(section, L"LengthShift", 0.0); -} - -/* -** Updates the value(s) from the measures. -** -*/ -bool MeterRoundLine::Update() -{ - if (Meter::Update()) - { - if (m_Measures.empty()) - { - m_Value = 1.0; - return true; - } - - Measure* measure = m_Measures[0]; - if (m_ValueRemainder > 0) - { - LONGLONG time = (LONGLONG)measure->GetValue(); - m_Value = (double)(time % m_ValueRemainder); - m_Value /= (double)m_ValueRemainder; - } - else - { - m_Value = measure->GetRelativeValue(); - } - return true; - } - - return false; -} - - -/* -** Draws the meter on the double buffer -** -*/ -bool MeterRoundLine::Draw(Gfx::Canvas& canvas) -{ - if (!Meter::Draw(canvas)) return false; - - Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); - - // Calculate the center of for the line - int x = GetX(); - int y = GetY(); - double cx = x + m_W / 2.0; - double cy = y + m_H / 2.0; - - double lineStart = ((m_CntrlLineStart) ? m_LineStartShift * m_Value : 0) + m_LineStart; - double lineLength = ((m_CntrlLineLength) ? m_LineLengthShift * m_Value : 0) + m_LineLength; - - // Calculate the end point of the line - double angle = ((m_CntrlAngle) ? m_RotationAngle * m_Value : m_RotationAngle) + m_StartAngle; - double e_cos = cos(angle); - double e_sin = sin(angle); - - REAL sx = (REAL)(e_cos * lineStart + cx); - REAL sy = (REAL)(e_sin * lineStart + cy); - REAL ex = (REAL)(e_cos * lineLength + cx); - REAL ey = (REAL)(e_sin * lineLength + cy); - - if (m_Solid) - { - REAL startAngle = (REAL)(fmod(CONVERT_TO_DEGREES(m_StartAngle), 360.0)); - REAL sweepAngle = (REAL)(CONVERT_TO_DEGREES(m_RotationAngle * m_Value)); - - // Calculate the start point of the line - double s_cos = cos(m_StartAngle); - double s_sin = sin(m_StartAngle); - - //Create a path to surround the arc - GraphicsPath path; - path.AddArc((REAL)(cx - lineStart), (REAL)(cy - lineStart), (REAL)(lineStart * 2.0), (REAL)(lineStart * 2.0), startAngle, sweepAngle); - path.AddLine((REAL)(lineStart * s_cos + cx), (REAL)(lineStart * s_sin + cy), (REAL)(lineLength * s_cos + cx), (REAL)(lineLength * s_sin + cy)); - path.AddArc((REAL)(cx - lineLength), (REAL)(cy - lineLength), (REAL)(lineLength * 2.0), (REAL)(lineLength * 2.0), startAngle, sweepAngle); - path.AddLine(ex, ey, sx, sy); - - SolidBrush solidBrush(m_LineColor); - graphics.FillPath(&solidBrush, &path); - } - else - { - Pen pen(m_LineColor, (REAL)m_LineWidth); - graphics.DrawLine(&pen, sx, sy, ex, ey); - } - - canvas.EndGdiplusContext(); - - return true; -} - -/* -** Overridden method. The roundline meters need not to be bound on anything -** -*/ -void MeterRoundLine::BindMeasures(ConfigParser& parser, const WCHAR* section) -{ - BindPrimaryMeasure(parser, section, true); -} +/* + Copyright (C) 2009 Kimmo Pekkola, Brian Todoroff + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeterRoundLine.h" +#include "Measure.h" +#include "Error.h" +#include "../Common/Gfx/Canvas.h" + +using namespace Gdiplus; + +#define PI (3.14159265358979323846) +#define CONVERT_TO_DEGREES(X) ((X) * (180.0 / PI)) + +/* +** The constructor +** +*/ +MeterRoundLine::MeterRoundLine(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), + m_Solid(false), + m_LineWidth(1.0), + m_LineLength(20.0), + m_LineStart(-1.0), + m_StartAngle(), + m_RotationAngle(6.2832), + m_CntrlAngle(true), + m_CntrlLineStart(false), + m_CntrlLineLength(false), + m_LineStartShift(), + m_LineLengthShift(), + m_ValueRemainder(), + m_LineColor(Color::Black), + m_Value() +{ +} + +/* +** The destructor +** +*/ +MeterRoundLine::~MeterRoundLine() +{ +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeterRoundLine::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + Meter::ReadOptions(parser, section); + + m_LineWidth = parser.ReadFloat(section, L"LineWidth", 1.0); + m_LineLength = parser.ReadFloat(section, L"LineLength", 20.0); + m_LineStart = parser.ReadFloat(section, L"LineStart", -1.0); + m_StartAngle = parser.ReadFloat(section, L"StartAngle", 0.0); + m_RotationAngle = parser.ReadFloat(section, L"RotationAngle", 6.2832); + m_ValueRemainder = parser.ReadInt(section, L"ValueReminder", 0); // Typo + m_ValueRemainder = parser.ReadInt(section, L"ValueRemainder", m_ValueRemainder); + m_LineColor = parser.ReadColor(section, L"LineColor", Color::Black); + m_Solid = parser.ReadBool(section, L"Solid", false); + m_CntrlAngle = parser.ReadBool(section, L"ControlAngle", true); + m_CntrlLineStart = parser.ReadBool(section, L"ControlStart", false); + m_CntrlLineLength = parser.ReadBool(section, L"ControlLength", false); + m_LineStartShift = parser.ReadFloat(section, L"StartShift", 0.0); + m_LineLengthShift = parser.ReadFloat(section, L"LengthShift", 0.0); +} + +/* +** Updates the value(s) from the measures. +** +*/ +bool MeterRoundLine::Update() +{ + if (Meter::Update()) + { + if (m_Measures.empty()) + { + m_Value = 1.0; + return true; + } + + Measure* measure = m_Measures[0]; + if (m_ValueRemainder > 0) + { + LONGLONG time = (LONGLONG)measure->GetValue(); + m_Value = (double)(time % m_ValueRemainder); + m_Value /= (double)m_ValueRemainder; + } + else + { + m_Value = measure->GetRelativeValue(); + } + return true; + } + + return false; +} + + +/* +** Draws the meter on the double buffer +** +*/ +bool MeterRoundLine::Draw(Gfx::Canvas& canvas) +{ + if (!Meter::Draw(canvas)) return false; + + Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext(); + + // Calculate the center of for the line + int x = GetX(); + int y = GetY(); + double cx = x + m_W / 2.0; + double cy = y + m_H / 2.0; + + double lineStart = ((m_CntrlLineStart) ? m_LineStartShift * m_Value : 0) + m_LineStart; + double lineLength = ((m_CntrlLineLength) ? m_LineLengthShift * m_Value : 0) + m_LineLength; + + // Calculate the end point of the line + double angle = ((m_CntrlAngle) ? m_RotationAngle * m_Value : m_RotationAngle) + m_StartAngle; + double e_cos = cos(angle); + double e_sin = sin(angle); + + REAL sx = (REAL)(e_cos * lineStart + cx); + REAL sy = (REAL)(e_sin * lineStart + cy); + REAL ex = (REAL)(e_cos * lineLength + cx); + REAL ey = (REAL)(e_sin * lineLength + cy); + + if (m_Solid) + { + REAL startAngle = (REAL)(fmod(CONVERT_TO_DEGREES(m_StartAngle), 360.0)); + REAL sweepAngle = (REAL)(CONVERT_TO_DEGREES(m_RotationAngle * m_Value)); + + // Calculate the start point of the line + double s_cos = cos(m_StartAngle); + double s_sin = sin(m_StartAngle); + + //Create a path to surround the arc + GraphicsPath path; + path.AddArc((REAL)(cx - lineStart), (REAL)(cy - lineStart), (REAL)(lineStart * 2.0), (REAL)(lineStart * 2.0), startAngle, sweepAngle); + path.AddLine((REAL)(lineStart * s_cos + cx), (REAL)(lineStart * s_sin + cy), (REAL)(lineLength * s_cos + cx), (REAL)(lineLength * s_sin + cy)); + path.AddArc((REAL)(cx - lineLength), (REAL)(cy - lineLength), (REAL)(lineLength * 2.0), (REAL)(lineLength * 2.0), startAngle, sweepAngle); + path.AddLine(ex, ey, sx, sy); + + SolidBrush solidBrush(m_LineColor); + graphics.FillPath(&solidBrush, &path); + } + else + { + Pen pen(m_LineColor, (REAL)m_LineWidth); + graphics.DrawLine(&pen, sx, sy, ex, ey); + } + + canvas.EndGdiplusContext(); + + return true; +} + +/* +** Overridden method. The roundline meters need not to be bound on anything +** +*/ +void MeterRoundLine::BindMeasures(ConfigParser& parser, const WCHAR* section) +{ + BindPrimaryMeasure(parser, section, true); +} diff --git a/Library/MeterRoundLine.h b/Library/MeterRoundLine.h index 5db244e1..78f6c4ec 100644 --- a/Library/MeterRoundLine.h +++ b/Library/MeterRoundLine.h @@ -1,59 +1,59 @@ -/* - Copyright (C) 2002 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __METERROUNDLINE_H__ -#define __METERROUNDLINE_H__ - -#include "Meter.h" - -class MeterRoundLine : public Meter -{ -public: - MeterRoundLine(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeterRoundLine(); - - MeterRoundLine(const MeterRoundLine& other) = delete; - MeterRoundLine& operator=(MeterRoundLine other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - virtual bool Update(); - virtual bool Draw(Gfx::Canvas& canvas); - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void BindMeasures(ConfigParser& parser, const WCHAR* section); - -private: - bool m_Solid; - double m_LineWidth; - double m_LineLength; - double m_LineStart; - double m_StartAngle; - double m_RotationAngle; - bool m_CntrlAngle; - bool m_CntrlLineStart; - bool m_CntrlLineLength; - double m_LineStartShift; - double m_LineLengthShift; - UINT m_ValueRemainder; - Gdiplus::Color m_LineColor; - double m_Value; -}; - -#endif +/* + Copyright (C) 2002 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __METERROUNDLINE_H__ +#define __METERROUNDLINE_H__ + +#include "Meter.h" + +class MeterRoundLine : public Meter +{ +public: + MeterRoundLine(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeterRoundLine(); + + MeterRoundLine(const MeterRoundLine& other) = delete; + MeterRoundLine& operator=(MeterRoundLine other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + virtual bool Update(); + virtual bool Draw(Gfx::Canvas& canvas); + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void BindMeasures(ConfigParser& parser, const WCHAR* section); + +private: + bool m_Solid; + double m_LineWidth; + double m_LineLength; + double m_LineStart; + double m_StartAngle; + double m_RotationAngle; + bool m_CntrlAngle; + bool m_CntrlLineStart; + bool m_CntrlLineLength; + double m_LineStartShift; + double m_LineLengthShift; + UINT m_ValueRemainder; + Gdiplus::Color m_LineColor; + double m_Value; +}; + +#endif diff --git a/Library/MeterString.cpp b/Library/MeterString.cpp index 62320fd7..72b88440 100644 --- a/Library/MeterString.cpp +++ b/Library/MeterString.cpp @@ -1,682 +1,682 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeterString.h" -#include "Rainmeter.h" -#include "Measure.h" -#include "Error.h" -#include "../Common/Gfx/Canvas.h" - -using namespace Gdiplus; - -#define PI (3.14159265f) -#define CONVERT_TO_DEGREES(X) ((X) * (180.0f / PI)) - -void StringToUpper(std::wstring& str) -{ - WCHAR* srcAndDest = &str[0]; - int strAndDestLen = (int)str.length(); - LCMapString(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE, srcAndDest, strAndDestLen, srcAndDest, strAndDestLen); -} - -void StringToLower(std::wstring& str) -{ - WCHAR* srcAndDest = &str[0]; - int strAndDestLen = (int)str.length(); - LCMapString(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, srcAndDest, strAndDestLen, srcAndDest, strAndDestLen); -} - -void StringToProper(std::wstring& str) -{ - if (!str.empty()) - { - WCHAR* srcAndDest = &str[0]; - LCMapString(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE, srcAndDest, 1, srcAndDest, 1); - - for (size_t i = 1; i < str.length(); ++i) - { - srcAndDest = &str[i]; - LCMapString(LOCALE_USER_DEFAULT, (iswspace(str[i - 1]) > 0) ? LCMAP_UPPERCASE : LCMAP_LOWERCASE, srcAndDest, 1, srcAndDest, 1); - } - } -} - -/* -** The constructor -** -*/ -MeterString::MeterString(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), - m_Color(Color::White), - m_EffectColor(Color::Black), - m_AutoScale(AUTOSCALE_OFF), - m_Style(NORMAL), - m_Effect(EFFECT_NONE), - m_Case(TEXTCASE_NONE), - m_FontSize(10), - m_Scale(1.0), - m_NoDecimals(true), - m_Percentual(true), - m_ClipType(CLIP_OFF), - m_NeedsClipping(false), - m_ClipStringW(-1), - m_ClipStringH(-1), - m_TextFormat(meterWindow->GetCanvas().CreateTextFormat()), - m_NumOfDecimals(-1), - m_Angle() -{ -} - -/* -** The destructor -** -*/ -MeterString::~MeterString() -{ - delete m_TextFormat; - m_TextFormat = nullptr; -} - -/* -** Returns the X-coordinate of the meter -** -*/ -int MeterString::GetX(bool abs) -{ - int x = Meter::GetX(); - - if (!abs) - { - switch (m_TextFormat->GetHorizontalAlignment()) - { - case Gfx::HorizontalAlignment::Center: - x -= m_W / 2; - break; - - case Gfx::HorizontalAlignment::Right: - x -= m_W; - break; - } - } - - return x; -} - -/* -** Returns the Y-coordinate of the meter -** -*/ -int MeterString::GetY(bool abs) -{ - int y = Meter::GetY(); - - if (!abs) - { - switch (m_TextFormat->GetVerticalAlignment()) - { - case Gfx::VerticalAlignment::Center: - y -= m_H / 2; - break; - - case Gfx::VerticalAlignment::Bottom: - y -= m_H; - break; - } - } - - return y; -} - -/* -** Create the font that is used to draw the text. -** -*/ -void MeterString::Initialize() -{ - Meter::Initialize(); - - m_TextFormat->SetProperties( - m_FontFace.c_str(), - m_FontSize, - (m_Style & BOLD) != 0, - (m_Style & ITALIC) != 0, - m_MeterWindow->GetFontCollection()); -} - -/* -** Read the options specified in the ini file. -** -*/ -void MeterString::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - // Store the current font values so we know if the font needs to be updated - std::wstring oldFontFace = m_FontFace; - int oldFontSize = m_FontSize; - TEXTSTYLE oldStyle = m_Style; - - Meter::ReadOptions(parser, section); - - m_Color = parser.ReadColor(section, L"FontColor", Color::Black); - m_EffectColor = parser.ReadColor(section, L"FontEffectColor", Color::Black); - - m_Prefix = parser.ReadString(section, L"Prefix", L""); - m_Postfix = parser.ReadString(section, L"Postfix", L""); - m_Text = parser.ReadString(section, L"Text", L""); - - m_Percentual = parser.ReadBool(section, L"Percentual", false); - - int clipping = parser.ReadInt(section, L"ClipString", 0); - switch (clipping) - { - case 2: - m_ClipType = CLIP_AUTO; - - m_ClipStringW = parser.ReadInt(section, L"ClipStringW", -1); - m_ClipStringH = parser.ReadInt(section, L"ClipStringH", -1); - break; - - case 1: - m_ClipType = CLIP_ON; - break; - - case 0: - m_ClipType = CLIP_OFF; - break; - - default: - LogErrorF(this, L"ClipString=%s is not valid", clipping); - } - - m_FontFace = parser.ReadString(section, L"FontFace", L"Arial"); - if (m_FontFace.empty()) - { - m_FontFace = L"Arial"; - } - - m_FontSize = parser.ReadInt(section, L"FontSize", 10); - if (m_FontSize < 0) - { - m_FontSize = 10; - } - - m_NumOfDecimals = parser.ReadInt(section, L"NumOfDecimals", -1); - - m_Angle = (Gdiplus::REAL)parser.ReadFloat(section, L"Angle", 0.0); - - const std::wstring& autoscale = parser.ReadString(section, L"AutoScale", L"0"); - int autoscaleValue = _wtoi(autoscale.c_str()); - if (autoscaleValue == 0) - { - m_AutoScale = AUTOSCALE_OFF; - } - else - { - if (autoscale.find_last_of(L"kK") == std::wstring::npos) - { - m_AutoScale = (autoscaleValue == 2) ? AUTOSCALE_1000 : AUTOSCALE_1024; - } - else - { - m_AutoScale = (autoscaleValue == 2) ? AUTOSCALE_1000K : AUTOSCALE_1024K; - } - } - - const std::wstring& scale = parser.ReadString(section, L"Scale", L"1"); - m_NoDecimals = (scale.find(L'.') == std::wstring::npos); - m_Scale = parser.ParseDouble(scale.c_str(), 1); - - const WCHAR* hAlign = parser.ReadString(section, L"StringAlign", L"LEFT").c_str(); - const WCHAR* vAlign = nullptr; - if (_wcsnicmp(hAlign, L"LEFT", 4) == 0) - { - m_TextFormat->SetHorizontalAlignment(Gfx::HorizontalAlignment::Left); - vAlign = hAlign + 4; - } - else if (_wcsnicmp(hAlign, L"RIGHT", 5) == 0) - { - m_TextFormat->SetHorizontalAlignment(Gfx::HorizontalAlignment::Right); - vAlign = hAlign + 5; - } - else if (_wcsnicmp(hAlign, L"CENTER", 6) == 0) - { - m_TextFormat->SetHorizontalAlignment(Gfx::HorizontalAlignment::Center); - vAlign = hAlign + 6; - } - - if (!vAlign || _wcsicmp(vAlign, L"TOP") == 0) - { - m_TextFormat->SetVerticalAlignment(Gfx::VerticalAlignment::Top); - } - else if (_wcsicmp(vAlign, L"BOTTOM") == 0) - { - m_TextFormat->SetVerticalAlignment(Gfx::VerticalAlignment::Bottom); - } - else if (_wcsicmp(vAlign, L"CENTER") == 0) - { - m_TextFormat->SetVerticalAlignment(Gfx::VerticalAlignment::Center); - } - - const WCHAR* stringCase = parser.ReadString(section, L"StringCase", L"NONE").c_str(); - if (_wcsicmp(stringCase, L"NONE") == 0) - { - m_Case = TEXTCASE_NONE; - } - else if (_wcsicmp(stringCase, L"UPPER") == 0) - { - m_Case = TEXTCASE_UPPER; - } - else if (_wcsicmp(stringCase, L"LOWER") == 0) - { - m_Case = TEXTCASE_LOWER; - } - else if (_wcsicmp(stringCase, L"PROPER") == 0) - { - m_Case = TEXTCASE_PROPER; - } - else - { - LogErrorF(this, L"StringCase=%s is not valid", stringCase); - } - - const WCHAR* style = parser.ReadString(section, L"StringStyle", L"NORMAL").c_str(); - if (_wcsicmp(style, L"NORMAL") == 0) - { - m_Style = NORMAL; - } - else if (_wcsicmp(style, L"BOLD") == 0) - { - m_Style = BOLD; - } - else if (_wcsicmp(style, L"ITALIC") == 0) - { - m_Style = ITALIC; - } - else if (_wcsicmp(style, L"BOLDITALIC") == 0) - { - m_Style = BOLDITALIC; - } - else - { - LogErrorF(this, L"StringStyle=%s is not valid", style); - } - - const WCHAR* effect = parser.ReadString(section, L"StringEffect", L"NONE").c_str(); - if (_wcsicmp(effect, L"NONE") == 0) - { - m_Effect = EFFECT_NONE; - } - else if (_wcsicmp(effect, L"SHADOW") == 0) - { - m_Effect = EFFECT_SHADOW; - } - else if (_wcsicmp(effect, L"BORDER") == 0) - { - m_Effect = EFFECT_BORDER; - } - else - { - LogErrorF(this, L"StringEffect=%s is not valid", effect); - } - - if (m_Initialized && - (wcscmp(oldFontFace.c_str(), m_FontFace.c_str()) != 0 || - oldFontSize != m_FontSize || - oldStyle != m_Style)) - { - Initialize(); // Recreate the font - } -} - -/* -** Updates the value(s) from the measures. -** -*/ -bool MeterString::Update() -{ - if (Meter::Update()) - { - int decimals = (m_NumOfDecimals != -1) ? m_NumOfDecimals : (m_NoDecimals && (m_Percentual || m_AutoScale == AUTOSCALE_OFF)) ? 0 : 1; - - // Create the text - m_String = m_Prefix; - if (!m_Measures.empty()) - { - if (m_Text.empty()) - { - m_String += m_Measures[0]->GetStringOrFormattedValue( - m_AutoScale, m_Scale, decimals, m_Percentual); - } - else - { - std::wstring tmpText = m_Text; - ReplaceMeasures(tmpText, m_AutoScale, m_Scale, decimals, m_Percentual); - m_String += tmpText; - } - } - else - { - m_String += m_Text; - } - if (!m_Postfix.empty()) m_String += m_Postfix; - - switch (m_Case) - { - case TEXTCASE_UPPER: - StringToUpper(m_String); - break; - case TEXTCASE_LOWER: - StringToLower(m_String); - break; - case TEXTCASE_PROPER: - StringToProper(m_String); - break; - } - - for (size_t i = 0; i < m_String.length(); ++i) - { - if (m_String[i] == L'\u00A0' || // No-Break Space - m_String[i] == L'\u205F') // Medium Mathematical Space - { - // Ugly hack to make D2D render trailing spaces followed by a non-breaking space - // correctly. By default, D2D ignores all trailing whitespace. Both GDI+ and D2D, - // however, acknowledge the presense of the zero-width space (and give it a width - // of 0px), so we append the zero-width space after each non-breaking space. - ++i; - m_String.insert(i, 1, L'\u200B'); - } - else if (m_String[i] == L'\r') - { - // GDI+ seems to ignore carriage returns, so strip it entirely to make it behave - // similarly with D2D as well. - m_String.erase(i, 1); - --i; - } - } - - if (!m_WDefined || !m_HDefined) - { - // Calculate the text size - RectF rect; - if (DrawString(m_MeterWindow->GetCanvas(), &rect)) - { - m_W = (int)rect.Width + GetWidthPadding(); - m_H = (int)rect.Height + GetHeightPadding(); - } - else - { - m_W = 1; - m_H = 1; - } - } - - return true; - } - return false; -} - -/* -** Draws the meter on the double buffer -** -*/ -bool MeterString::Draw(Gfx::Canvas& canvas) -{ - if (!Meter::Draw(canvas)) return false; - - return DrawString(canvas, nullptr); -} - -/* -** Draws the string or calculates it's size -** -*/ -bool MeterString::DrawString(Gfx::Canvas& canvas, RectF* rect) -{ - if (!m_TextFormat->IsInitialized()) return false; - - LPCWSTR string = m_String.c_str(); - UINT stringLen = (UINT)m_String.length(); - - canvas.SetTextAntiAliasing(m_AntiAlias); - - m_TextFormat->SetTrimming( - m_ClipType == CLIP_ON || - (m_ClipType == CLIP_AUTO && (m_NeedsClipping || (m_WDefined && m_HDefined)))); - - Gdiplus::Rect meterRect = GetMeterRectPadding(); - - if (rect) - { - rect->X = (REAL)meterRect.X; - rect->Y = (REAL)meterRect.Y; - if (canvas.MeasureTextW(string, stringLen, *m_TextFormat, *rect) && - m_ClipType == CLIP_AUTO) - { - // Set initial clipping - m_NeedsClipping = false; - - REAL w, h; - bool updateSize = true; - - if (m_WDefined) - { - w = (REAL)meterRect.Width; - h = rect->Height; - m_NeedsClipping = true; - } - else if (m_HDefined) - { - if (m_ClipStringW == -1) - { - // Text does not fit in defined height, clip it - if (rect->Height > (REAL)meterRect.Height) - { - m_NeedsClipping = true; - } - - rect->Height = (REAL)meterRect.Height; - updateSize = false; - - } - else - { - if (rect->Width > (REAL)m_ClipStringW) - { - w = (REAL)m_ClipStringW; - m_NeedsClipping = true; - } - else - { - w = rect->Width; - } - - h = (REAL)meterRect.Height; - } - } - else - { - if (m_ClipStringW == -1) - { - // Clip text if already larger than ClipStringH - if (m_ClipStringH != -1 && rect->Height > (REAL)m_ClipStringH) - { - m_NeedsClipping = true; - rect->Height = (REAL)m_ClipStringH; - } - - updateSize = false; - } - else - { - if (rect->Width > (REAL)m_ClipStringW) - { - w = (REAL)m_ClipStringW; - m_NeedsClipping = true; - } - else - { - w = rect->Width; - } - - h = rect->Height; - } - } - - if (updateSize) - { - UINT lines = 0; - RectF layout((REAL)meterRect.X, (REAL)meterRect.Y, w, h); - if (canvas.MeasureTextLinesW(string, stringLen, *m_TextFormat, layout, lines) && - lines != 0) - { - rect->Width = w; - rect->Height = layout.Height; - - if (m_HDefined || (m_ClipStringH != -1 && rect->Height > (REAL)m_ClipStringH)) - { - rect->Height = m_HDefined ? (REAL)meterRect.Height : (REAL)m_ClipStringH; - } - } - } - } - } - else - { - RectF rcDest((REAL)meterRect.X, (REAL)meterRect.Y, (REAL)meterRect.Width, (REAL)meterRect.Height); - m_Rect = rcDest; - - if (m_Angle != 0.0f) - { - const float baseX = (float)Meter::GetX(); - canvas.RotateTransform(CONVERT_TO_DEGREES(m_Angle), baseX, (REAL)meterRect.Y, -baseX, -(REAL)meterRect.Y); - } - - if (m_Effect != EFFECT_NONE) - { - SolidBrush solidBrush(m_EffectColor); - RectF rcEffect(rcDest); - - if (m_Effect == EFFECT_SHADOW) - { - rcEffect.Offset(1, 1); - canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcEffect, solidBrush); - } - else //if (m_Effect == EFFECT_BORDER) - { - rcEffect.Offset(0, 1); - canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcEffect, solidBrush); - rcEffect.Offset(1, -1); - canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcEffect, solidBrush); - rcEffect.Offset(-1, -1); - canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcEffect, solidBrush); - rcEffect.Offset(-1, 1); - canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcEffect, solidBrush); - } - } - - SolidBrush solidBrush(m_Color); - canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcDest, solidBrush); - - if (m_Angle != 0.0f) - { - canvas.ResetTransform(); - } - } - - return true; -} - -/* -** Overridden method. The string meters need not to be bound on anything -** -*/ -void MeterString::BindMeasures(ConfigParser& parser, const WCHAR* section) -{ - if (BindPrimaryMeasure(parser, section, true)) - { - BindSecondaryMeasures(parser, section); - } -} - -/* -** Static helper to log all installed font families. -** -*/ -void MeterString::EnumerateInstalledFontFamilies() -{ - INT fontCount; - InstalledFontCollection fontCollection; - - if (Ok == fontCollection.GetLastStatus()) - { - fontCount = fontCollection.GetFamilyCount(); - if (fontCount > 0) - { - INT fontFound; - - FontFamily* fontFamilies = new FontFamily[fontCount]; - - if (Ok == fontCollection.GetFamilies(fontCount, fontFamilies, &fontFound)) - { - std::wstring fonts; - for (INT i = 0; i < fontCount; ++i) - { - WCHAR familyName[LF_FACESIZE]; - if (Ok == fontFamilies[i].GetFamilyName(familyName)) - { - fonts += familyName; - } - else - { - fonts += L"***"; - } - fonts += L", "; - } - LogWarning(fonts.c_str()); - } - else - { - LogError(L"Font enumeration: GetFamilies failed"); - } - - delete [] fontFamilies; - } - else - { - LogWarning(L"No installed fonts"); - } - } - else - { - LogError(L"Font enumeration: InstalledFontCollection failed"); - } -} - -void MeterString::InitializeStatic() -{ - if (Rainmeter::GetInstance().GetDebug()) - { - LogDebug(L"------------------------------"); - LogDebug(L"* Font families:"); - EnumerateInstalledFontFamilies(); - LogDebug(L"------------------------------"); - } -} - -void MeterString::FinalizeStatic() -{ -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeterString.h" +#include "Rainmeter.h" +#include "Measure.h" +#include "Error.h" +#include "../Common/Gfx/Canvas.h" + +using namespace Gdiplus; + +#define PI (3.14159265f) +#define CONVERT_TO_DEGREES(X) ((X) * (180.0f / PI)) + +void StringToUpper(std::wstring& str) +{ + WCHAR* srcAndDest = &str[0]; + int strAndDestLen = (int)str.length(); + LCMapString(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE, srcAndDest, strAndDestLen, srcAndDest, strAndDestLen); +} + +void StringToLower(std::wstring& str) +{ + WCHAR* srcAndDest = &str[0]; + int strAndDestLen = (int)str.length(); + LCMapString(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, srcAndDest, strAndDestLen, srcAndDest, strAndDestLen); +} + +void StringToProper(std::wstring& str) +{ + if (!str.empty()) + { + WCHAR* srcAndDest = &str[0]; + LCMapString(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE, srcAndDest, 1, srcAndDest, 1); + + for (size_t i = 1; i < str.length(); ++i) + { + srcAndDest = &str[i]; + LCMapString(LOCALE_USER_DEFAULT, (iswspace(str[i - 1]) > 0) ? LCMAP_UPPERCASE : LCMAP_LOWERCASE, srcAndDest, 1, srcAndDest, 1); + } + } +} + +/* +** The constructor +** +*/ +MeterString::MeterString(MeterWindow* meterWindow, const WCHAR* name) : Meter(meterWindow, name), + m_Color(Color::White), + m_EffectColor(Color::Black), + m_AutoScale(AUTOSCALE_OFF), + m_Style(NORMAL), + m_Effect(EFFECT_NONE), + m_Case(TEXTCASE_NONE), + m_FontSize(10), + m_Scale(1.0), + m_NoDecimals(true), + m_Percentual(true), + m_ClipType(CLIP_OFF), + m_NeedsClipping(false), + m_ClipStringW(-1), + m_ClipStringH(-1), + m_TextFormat(meterWindow->GetCanvas().CreateTextFormat()), + m_NumOfDecimals(-1), + m_Angle() +{ +} + +/* +** The destructor +** +*/ +MeterString::~MeterString() +{ + delete m_TextFormat; + m_TextFormat = nullptr; +} + +/* +** Returns the X-coordinate of the meter +** +*/ +int MeterString::GetX(bool abs) +{ + int x = Meter::GetX(); + + if (!abs) + { + switch (m_TextFormat->GetHorizontalAlignment()) + { + case Gfx::HorizontalAlignment::Center: + x -= m_W / 2; + break; + + case Gfx::HorizontalAlignment::Right: + x -= m_W; + break; + } + } + + return x; +} + +/* +** Returns the Y-coordinate of the meter +** +*/ +int MeterString::GetY(bool abs) +{ + int y = Meter::GetY(); + + if (!abs) + { + switch (m_TextFormat->GetVerticalAlignment()) + { + case Gfx::VerticalAlignment::Center: + y -= m_H / 2; + break; + + case Gfx::VerticalAlignment::Bottom: + y -= m_H; + break; + } + } + + return y; +} + +/* +** Create the font that is used to draw the text. +** +*/ +void MeterString::Initialize() +{ + Meter::Initialize(); + + m_TextFormat->SetProperties( + m_FontFace.c_str(), + m_FontSize, + (m_Style & BOLD) != 0, + (m_Style & ITALIC) != 0, + m_MeterWindow->GetFontCollection()); +} + +/* +** Read the options specified in the ini file. +** +*/ +void MeterString::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + // Store the current font values so we know if the font needs to be updated + std::wstring oldFontFace = m_FontFace; + int oldFontSize = m_FontSize; + TEXTSTYLE oldStyle = m_Style; + + Meter::ReadOptions(parser, section); + + m_Color = parser.ReadColor(section, L"FontColor", Color::Black); + m_EffectColor = parser.ReadColor(section, L"FontEffectColor", Color::Black); + + m_Prefix = parser.ReadString(section, L"Prefix", L""); + m_Postfix = parser.ReadString(section, L"Postfix", L""); + m_Text = parser.ReadString(section, L"Text", L""); + + m_Percentual = parser.ReadBool(section, L"Percentual", false); + + int clipping = parser.ReadInt(section, L"ClipString", 0); + switch (clipping) + { + case 2: + m_ClipType = CLIP_AUTO; + + m_ClipStringW = parser.ReadInt(section, L"ClipStringW", -1); + m_ClipStringH = parser.ReadInt(section, L"ClipStringH", -1); + break; + + case 1: + m_ClipType = CLIP_ON; + break; + + case 0: + m_ClipType = CLIP_OFF; + break; + + default: + LogErrorF(this, L"ClipString=%s is not valid", clipping); + } + + m_FontFace = parser.ReadString(section, L"FontFace", L"Arial"); + if (m_FontFace.empty()) + { + m_FontFace = L"Arial"; + } + + m_FontSize = parser.ReadInt(section, L"FontSize", 10); + if (m_FontSize < 0) + { + m_FontSize = 10; + } + + m_NumOfDecimals = parser.ReadInt(section, L"NumOfDecimals", -1); + + m_Angle = (Gdiplus::REAL)parser.ReadFloat(section, L"Angle", 0.0); + + const std::wstring& autoscale = parser.ReadString(section, L"AutoScale", L"0"); + int autoscaleValue = _wtoi(autoscale.c_str()); + if (autoscaleValue == 0) + { + m_AutoScale = AUTOSCALE_OFF; + } + else + { + if (autoscale.find_last_of(L"kK") == std::wstring::npos) + { + m_AutoScale = (autoscaleValue == 2) ? AUTOSCALE_1000 : AUTOSCALE_1024; + } + else + { + m_AutoScale = (autoscaleValue == 2) ? AUTOSCALE_1000K : AUTOSCALE_1024K; + } + } + + const std::wstring& scale = parser.ReadString(section, L"Scale", L"1"); + m_NoDecimals = (scale.find(L'.') == std::wstring::npos); + m_Scale = parser.ParseDouble(scale.c_str(), 1); + + const WCHAR* hAlign = parser.ReadString(section, L"StringAlign", L"LEFT").c_str(); + const WCHAR* vAlign = nullptr; + if (_wcsnicmp(hAlign, L"LEFT", 4) == 0) + { + m_TextFormat->SetHorizontalAlignment(Gfx::HorizontalAlignment::Left); + vAlign = hAlign + 4; + } + else if (_wcsnicmp(hAlign, L"RIGHT", 5) == 0) + { + m_TextFormat->SetHorizontalAlignment(Gfx::HorizontalAlignment::Right); + vAlign = hAlign + 5; + } + else if (_wcsnicmp(hAlign, L"CENTER", 6) == 0) + { + m_TextFormat->SetHorizontalAlignment(Gfx::HorizontalAlignment::Center); + vAlign = hAlign + 6; + } + + if (!vAlign || _wcsicmp(vAlign, L"TOP") == 0) + { + m_TextFormat->SetVerticalAlignment(Gfx::VerticalAlignment::Top); + } + else if (_wcsicmp(vAlign, L"BOTTOM") == 0) + { + m_TextFormat->SetVerticalAlignment(Gfx::VerticalAlignment::Bottom); + } + else if (_wcsicmp(vAlign, L"CENTER") == 0) + { + m_TextFormat->SetVerticalAlignment(Gfx::VerticalAlignment::Center); + } + + const WCHAR* stringCase = parser.ReadString(section, L"StringCase", L"NONE").c_str(); + if (_wcsicmp(stringCase, L"NONE") == 0) + { + m_Case = TEXTCASE_NONE; + } + else if (_wcsicmp(stringCase, L"UPPER") == 0) + { + m_Case = TEXTCASE_UPPER; + } + else if (_wcsicmp(stringCase, L"LOWER") == 0) + { + m_Case = TEXTCASE_LOWER; + } + else if (_wcsicmp(stringCase, L"PROPER") == 0) + { + m_Case = TEXTCASE_PROPER; + } + else + { + LogErrorF(this, L"StringCase=%s is not valid", stringCase); + } + + const WCHAR* style = parser.ReadString(section, L"StringStyle", L"NORMAL").c_str(); + if (_wcsicmp(style, L"NORMAL") == 0) + { + m_Style = NORMAL; + } + else if (_wcsicmp(style, L"BOLD") == 0) + { + m_Style = BOLD; + } + else if (_wcsicmp(style, L"ITALIC") == 0) + { + m_Style = ITALIC; + } + else if (_wcsicmp(style, L"BOLDITALIC") == 0) + { + m_Style = BOLDITALIC; + } + else + { + LogErrorF(this, L"StringStyle=%s is not valid", style); + } + + const WCHAR* effect = parser.ReadString(section, L"StringEffect", L"NONE").c_str(); + if (_wcsicmp(effect, L"NONE") == 0) + { + m_Effect = EFFECT_NONE; + } + else if (_wcsicmp(effect, L"SHADOW") == 0) + { + m_Effect = EFFECT_SHADOW; + } + else if (_wcsicmp(effect, L"BORDER") == 0) + { + m_Effect = EFFECT_BORDER; + } + else + { + LogErrorF(this, L"StringEffect=%s is not valid", effect); + } + + if (m_Initialized && + (wcscmp(oldFontFace.c_str(), m_FontFace.c_str()) != 0 || + oldFontSize != m_FontSize || + oldStyle != m_Style)) + { + Initialize(); // Recreate the font + } +} + +/* +** Updates the value(s) from the measures. +** +*/ +bool MeterString::Update() +{ + if (Meter::Update()) + { + int decimals = (m_NumOfDecimals != -1) ? m_NumOfDecimals : (m_NoDecimals && (m_Percentual || m_AutoScale == AUTOSCALE_OFF)) ? 0 : 1; + + // Create the text + m_String = m_Prefix; + if (!m_Measures.empty()) + { + if (m_Text.empty()) + { + m_String += m_Measures[0]->GetStringOrFormattedValue( + m_AutoScale, m_Scale, decimals, m_Percentual); + } + else + { + std::wstring tmpText = m_Text; + ReplaceMeasures(tmpText, m_AutoScale, m_Scale, decimals, m_Percentual); + m_String += tmpText; + } + } + else + { + m_String += m_Text; + } + if (!m_Postfix.empty()) m_String += m_Postfix; + + switch (m_Case) + { + case TEXTCASE_UPPER: + StringToUpper(m_String); + break; + case TEXTCASE_LOWER: + StringToLower(m_String); + break; + case TEXTCASE_PROPER: + StringToProper(m_String); + break; + } + + for (size_t i = 0; i < m_String.length(); ++i) + { + if (m_String[i] == L'\u00A0' || // No-Break Space + m_String[i] == L'\u205F') // Medium Mathematical Space + { + // Ugly hack to make D2D render trailing spaces followed by a non-breaking space + // correctly. By default, D2D ignores all trailing whitespace. Both GDI+ and D2D, + // however, acknowledge the presense of the zero-width space (and give it a width + // of 0px), so we append the zero-width space after each non-breaking space. + ++i; + m_String.insert(i, 1, L'\u200B'); + } + else if (m_String[i] == L'\r') + { + // GDI+ seems to ignore carriage returns, so strip it entirely to make it behave + // similarly with D2D as well. + m_String.erase(i, 1); + --i; + } + } + + if (!m_WDefined || !m_HDefined) + { + // Calculate the text size + RectF rect; + if (DrawString(m_MeterWindow->GetCanvas(), &rect)) + { + m_W = (int)rect.Width + GetWidthPadding(); + m_H = (int)rect.Height + GetHeightPadding(); + } + else + { + m_W = 1; + m_H = 1; + } + } + + return true; + } + return false; +} + +/* +** Draws the meter on the double buffer +** +*/ +bool MeterString::Draw(Gfx::Canvas& canvas) +{ + if (!Meter::Draw(canvas)) return false; + + return DrawString(canvas, nullptr); +} + +/* +** Draws the string or calculates it's size +** +*/ +bool MeterString::DrawString(Gfx::Canvas& canvas, RectF* rect) +{ + if (!m_TextFormat->IsInitialized()) return false; + + LPCWSTR string = m_String.c_str(); + UINT stringLen = (UINT)m_String.length(); + + canvas.SetTextAntiAliasing(m_AntiAlias); + + m_TextFormat->SetTrimming( + m_ClipType == CLIP_ON || + (m_ClipType == CLIP_AUTO && (m_NeedsClipping || (m_WDefined && m_HDefined)))); + + Gdiplus::Rect meterRect = GetMeterRectPadding(); + + if (rect) + { + rect->X = (REAL)meterRect.X; + rect->Y = (REAL)meterRect.Y; + if (canvas.MeasureTextW(string, stringLen, *m_TextFormat, *rect) && + m_ClipType == CLIP_AUTO) + { + // Set initial clipping + m_NeedsClipping = false; + + REAL w, h; + bool updateSize = true; + + if (m_WDefined) + { + w = (REAL)meterRect.Width; + h = rect->Height; + m_NeedsClipping = true; + } + else if (m_HDefined) + { + if (m_ClipStringW == -1) + { + // Text does not fit in defined height, clip it + if (rect->Height > (REAL)meterRect.Height) + { + m_NeedsClipping = true; + } + + rect->Height = (REAL)meterRect.Height; + updateSize = false; + + } + else + { + if (rect->Width > (REAL)m_ClipStringW) + { + w = (REAL)m_ClipStringW; + m_NeedsClipping = true; + } + else + { + w = rect->Width; + } + + h = (REAL)meterRect.Height; + } + } + else + { + if (m_ClipStringW == -1) + { + // Clip text if already larger than ClipStringH + if (m_ClipStringH != -1 && rect->Height > (REAL)m_ClipStringH) + { + m_NeedsClipping = true; + rect->Height = (REAL)m_ClipStringH; + } + + updateSize = false; + } + else + { + if (rect->Width > (REAL)m_ClipStringW) + { + w = (REAL)m_ClipStringW; + m_NeedsClipping = true; + } + else + { + w = rect->Width; + } + + h = rect->Height; + } + } + + if (updateSize) + { + UINT lines = 0; + RectF layout((REAL)meterRect.X, (REAL)meterRect.Y, w, h); + if (canvas.MeasureTextLinesW(string, stringLen, *m_TextFormat, layout, lines) && + lines != 0) + { + rect->Width = w; + rect->Height = layout.Height; + + if (m_HDefined || (m_ClipStringH != -1 && rect->Height > (REAL)m_ClipStringH)) + { + rect->Height = m_HDefined ? (REAL)meterRect.Height : (REAL)m_ClipStringH; + } + } + } + } + } + else + { + RectF rcDest((REAL)meterRect.X, (REAL)meterRect.Y, (REAL)meterRect.Width, (REAL)meterRect.Height); + m_Rect = rcDest; + + if (m_Angle != 0.0f) + { + const float baseX = (float)Meter::GetX(); + canvas.RotateTransform(CONVERT_TO_DEGREES(m_Angle), baseX, (REAL)meterRect.Y, -baseX, -(REAL)meterRect.Y); + } + + if (m_Effect != EFFECT_NONE) + { + SolidBrush solidBrush(m_EffectColor); + RectF rcEffect(rcDest); + + if (m_Effect == EFFECT_SHADOW) + { + rcEffect.Offset(1, 1); + canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcEffect, solidBrush); + } + else //if (m_Effect == EFFECT_BORDER) + { + rcEffect.Offset(0, 1); + canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcEffect, solidBrush); + rcEffect.Offset(1, -1); + canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcEffect, solidBrush); + rcEffect.Offset(-1, -1); + canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcEffect, solidBrush); + rcEffect.Offset(-1, 1); + canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcEffect, solidBrush); + } + } + + SolidBrush solidBrush(m_Color); + canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcDest, solidBrush); + + if (m_Angle != 0.0f) + { + canvas.ResetTransform(); + } + } + + return true; +} + +/* +** Overridden method. The string meters need not to be bound on anything +** +*/ +void MeterString::BindMeasures(ConfigParser& parser, const WCHAR* section) +{ + if (BindPrimaryMeasure(parser, section, true)) + { + BindSecondaryMeasures(parser, section); + } +} + +/* +** Static helper to log all installed font families. +** +*/ +void MeterString::EnumerateInstalledFontFamilies() +{ + INT fontCount; + InstalledFontCollection fontCollection; + + if (Ok == fontCollection.GetLastStatus()) + { + fontCount = fontCollection.GetFamilyCount(); + if (fontCount > 0) + { + INT fontFound; + + FontFamily* fontFamilies = new FontFamily[fontCount]; + + if (Ok == fontCollection.GetFamilies(fontCount, fontFamilies, &fontFound)) + { + std::wstring fonts; + for (INT i = 0; i < fontCount; ++i) + { + WCHAR familyName[LF_FACESIZE]; + if (Ok == fontFamilies[i].GetFamilyName(familyName)) + { + fonts += familyName; + } + else + { + fonts += L"***"; + } + fonts += L", "; + } + LogWarning(fonts.c_str()); + } + else + { + LogError(L"Font enumeration: GetFamilies failed"); + } + + delete [] fontFamilies; + } + else + { + LogWarning(L"No installed fonts"); + } + } + else + { + LogError(L"Font enumeration: InstalledFontCollection failed"); + } +} + +void MeterString::InitializeStatic() +{ + if (Rainmeter::GetInstance().GetDebug()) + { + LogDebug(L"------------------------------"); + LogDebug(L"* Font families:"); + EnumerateInstalledFontFamilies(); + LogDebug(L"------------------------------"); + } +} + +void MeterString::FinalizeStatic() +{ +} diff --git a/Library/MeterString.h b/Library/MeterString.h index df8bdd57..bb5cfb04 100644 --- a/Library/MeterString.h +++ b/Library/MeterString.h @@ -1,116 +1,116 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __METERSTRING_H__ -#define __METERSTRING_H__ - -#include "Meter.h" -#include "Measure.h" -#include - -class MeterString : public Meter -{ -public: - MeterString(MeterWindow* meterWindow, const WCHAR* name); - virtual ~MeterString(); - - MeterString(const MeterString& other) = delete; - MeterString& operator=(MeterString other) = delete; - - virtual UINT GetTypeID() { return TypeID(); } - - virtual int GetX(bool abs = false); - virtual int GetY(bool abs = false); - - virtual void Initialize(); - virtual bool Update(); - void SetText(const WCHAR* text) { m_Text = text; } - virtual bool Draw(Gfx::Canvas& canvas); - Gdiplus::RectF GetRect() { return m_Rect; } - - static void EnumerateInstalledFontFamilies(); - - static void InitializeStatic(); - static void FinalizeStatic(); - -protected: - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - virtual void BindMeasures(ConfigParser& parser, const WCHAR* section); - - virtual bool IsFixedSize(bool overwrite = false) { return overwrite; } - -private: - enum TEXTSTYLE - { - NORMAL, - BOLD, - ITALIC, - BOLDITALIC - }; - - enum TEXTEFFECT - { - EFFECT_NONE, - EFFECT_SHADOW, - EFFECT_BORDER - }; - - enum TEXTCASE - { - TEXTCASE_NONE, - TEXTCASE_UPPER, - TEXTCASE_LOWER, - TEXTCASE_PROPER - }; - - enum CLIPTYPE - { - CLIP_OFF, - CLIP_ON, - CLIP_AUTO - }; - - bool DrawString(Gfx::Canvas& canvas, Gdiplus::RectF* rect); - - Gdiplus::Color m_Color; - Gdiplus::Color m_EffectColor; - std::wstring m_Postfix; - std::wstring m_Prefix; - std::wstring m_Text; - std::wstring m_FontFace; - AUTOSCALE m_AutoScale; - TEXTSTYLE m_Style; - TEXTEFFECT m_Effect; - TEXTCASE m_Case; - int m_FontSize; - double m_Scale; - bool m_NoDecimals; - bool m_Percentual; - CLIPTYPE m_ClipType; - bool m_NeedsClipping; - int m_ClipStringW; - int m_ClipStringH; - Gfx::TextFormat* m_TextFormat; - int m_NumOfDecimals; - Gdiplus::REAL m_Angle; - Gdiplus::RectF m_Rect; - - std::wstring m_String; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __METERSTRING_H__ +#define __METERSTRING_H__ + +#include "Meter.h" +#include "Measure.h" +#include + +class MeterString : public Meter +{ +public: + MeterString(MeterWindow* meterWindow, const WCHAR* name); + virtual ~MeterString(); + + MeterString(const MeterString& other) = delete; + MeterString& operator=(MeterString other) = delete; + + virtual UINT GetTypeID() { return TypeID(); } + + virtual int GetX(bool abs = false); + virtual int GetY(bool abs = false); + + virtual void Initialize(); + virtual bool Update(); + void SetText(const WCHAR* text) { m_Text = text; } + virtual bool Draw(Gfx::Canvas& canvas); + Gdiplus::RectF GetRect() { return m_Rect; } + + static void EnumerateInstalledFontFamilies(); + + static void InitializeStatic(); + static void FinalizeStatic(); + +protected: + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + virtual void BindMeasures(ConfigParser& parser, const WCHAR* section); + + virtual bool IsFixedSize(bool overwrite = false) { return overwrite; } + +private: + enum TEXTSTYLE + { + NORMAL, + BOLD, + ITALIC, + BOLDITALIC + }; + + enum TEXTEFFECT + { + EFFECT_NONE, + EFFECT_SHADOW, + EFFECT_BORDER + }; + + enum TEXTCASE + { + TEXTCASE_NONE, + TEXTCASE_UPPER, + TEXTCASE_LOWER, + TEXTCASE_PROPER + }; + + enum CLIPTYPE + { + CLIP_OFF, + CLIP_ON, + CLIP_AUTO + }; + + bool DrawString(Gfx::Canvas& canvas, Gdiplus::RectF* rect); + + Gdiplus::Color m_Color; + Gdiplus::Color m_EffectColor; + std::wstring m_Postfix; + std::wstring m_Prefix; + std::wstring m_Text; + std::wstring m_FontFace; + AUTOSCALE m_AutoScale; + TEXTSTYLE m_Style; + TEXTEFFECT m_Effect; + TEXTCASE m_Case; + int m_FontSize; + double m_Scale; + bool m_NoDecimals; + bool m_Percentual; + CLIPTYPE m_ClipType; + bool m_NeedsClipping; + int m_ClipStringW; + int m_ClipStringH; + Gfx::TextFormat* m_TextFormat; + int m_NumOfDecimals; + Gdiplus::REAL m_Angle; + Gdiplus::RectF m_Rect; + + std::wstring m_String; +}; + +#endif diff --git a/Library/MeterWindow.cpp b/Library/MeterWindow.cpp index 901f488f..096109c7 100644 --- a/Library/MeterWindow.cpp +++ b/Library/MeterWindow.cpp @@ -1,4922 +1,4922 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "MeterWindow.h" -#include "Rainmeter.h" -#include "TrayWindow.h" -#include "System.h" -#include "Error.h" -#include "Meter.h" -#include "Measure.h" -#include "DialogAbout.h" -#include "DialogManage.h" -#include "resource.h" -#include "Litestep.h" -#include "MeasureCalc.h" -#include "MeasureNet.h" -#include "MeasurePlugin.h" -#include "MeterButton.h" -#include "MeterString.h" -#include "TintedImage.h" -#include "MeasureScript.h" -#include "../Version.h" -#include "../Common/PathUtil.h" -#include "../Common/Gfx/Canvas.h" - -using namespace Gdiplus; - -#define SNAPDISTANCE 10 - -#define ZPOS_FLAGS (SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING) - -enum TIMER -{ - TIMER_METER = 1, - TIMER_MOUSE = 2, - TIMER_FADE = 3, - TIMER_TRANSITION = 4, - TIMER_DEACTIVATE = 5 -}; -enum INTERVAL -{ - INTERVAL_METER = 1000, - INTERVAL_MOUSE = 500, - INTERVAL_FADE = 10, - INTERVAL_TRANSITION = 100 -}; - -int MeterWindow::c_InstanceCount = 0; - -HINSTANCE MeterWindow::c_DwmInstance = nullptr; -decltype(DwmEnableBlurBehindWindow)* MeterWindow::c_DwmEnableBlurBehindWindow = nullptr; -decltype(DwmGetColorizationColor)* MeterWindow::c_DwmGetColorizationColor = nullptr; -decltype(DwmSetWindowAttribute)* MeterWindow::c_DwmSetWindowAttribute = nullptr; -decltype(DwmIsCompositionEnabled)* MeterWindow::c_DwmIsCompositionEnabled = nullptr; - -/* -** Constructor -** -*/ -MeterWindow::MeterWindow(const std::wstring& folderPath, const std::wstring& file) : m_FolderPath(folderPath), m_FileName(file), - m_Canvas(), - m_Background(), - m_BackgroundSize(), - m_Window(), - m_Mouse(this), - m_MouseOver(false), - m_MouseInputRegistered(false), - m_HasMouseScrollAction(false), - m_BackgroundMargins(), - m_DragMargins(), - m_WindowX(1, L'0'), - m_WindowY(1, L'0'), - m_WindowXScreen(1), - m_WindowYScreen(1), - m_WindowXScreenDefined(false), - m_WindowYScreenDefined(false), - m_WindowXFromRight(false), - m_WindowYFromBottom(false), - m_WindowXPercentage(false), - m_WindowYPercentage(false), - m_WindowW(), - m_WindowH(), - m_ScreenX(), - m_ScreenY(), - m_AnchorXFromRight(false), - m_AnchorYFromBottom(false), - m_AnchorXPercentage(false), - m_AnchorYPercentage(false), - m_AnchorScreenX(), - m_AnchorScreenY(), - m_WindowDraggable(true), - m_WindowUpdate(INTERVAL_METER), - m_TransitionUpdate(INTERVAL_TRANSITION), - m_ActiveTransition(false), - m_HasNetMeasures(false), - m_HasButtons(false), - m_WindowHide(HIDEMODE_NONE), - m_WindowStartHidden(false), - m_SavePosition(false), // Must be false - m_SnapEdges(true), - m_AlphaValue(255), - m_FadeDuration(250), - m_WindowZPosition(ZPOSITION_NORMAL), - m_DynamicWindowSize(false), - m_ClickThrough(false), - m_KeepOnScreen(true), - m_AutoSelectScreen(false), - m_UseD2D(true), - m_Dragging(false), - m_Dragged(false), - m_BackgroundMode(BGMODE_IMAGE), - m_SolidAngle(), - m_SolidBevel(BEVELTYPE_NONE), - m_Blur(false), - m_BlurMode(BLURMODE_NONE), - m_BlurRegion(), - m_FadeStartTime(), - m_FadeStartValue(), - m_FadeEndValue(), - m_TransparencyValue(), - m_State(STATE_INITIALIZING), - m_Hidden(false), - m_ResizeWindow(RESIZEMODE_NONE), - m_UpdateCounter(), - m_MouseMoveCounter(), - m_FontCollection(), - m_ToolTipHidden(false) -{ - if (!c_DwmInstance && IsWindowsVistaOrGreater() && - (c_DwmInstance = System::RmLoadLibrary(L"dwmapi.dll")) != nullptr) - { - c_DwmEnableBlurBehindWindow = - (decltype(c_DwmEnableBlurBehindWindow))GetProcAddress(c_DwmInstance, "DwmEnableBlurBehindWindow"); - c_DwmGetColorizationColor = - (decltype(c_DwmGetColorizationColor))GetProcAddress(c_DwmInstance, "DwmGetColorizationColor"); - c_DwmSetWindowAttribute = - (decltype(c_DwmSetWindowAttribute))GetProcAddress(c_DwmInstance, "DwmSetWindowAttribute"); - c_DwmIsCompositionEnabled = - (decltype(c_DwmIsCompositionEnabled))GetProcAddress(c_DwmInstance, "DwmIsCompositionEnabled"); - } - - if (c_InstanceCount == 0) - { - WNDCLASSEX wc = {sizeof(WNDCLASSEX)}; - wc.style = CS_NOCLOSE | CS_DBLCLKS; - wc.lpfnWndProc = InitialWndProc; - wc.hInstance = Rainmeter::GetInstance().GetModuleInstance(); - wc.hCursor = nullptr; // The cursor should be controlled by using SetCursor() when needed. - wc.lpszClassName = METERWINDOW_CLASS_NAME; - RegisterClassEx(&wc); - } - - ++c_InstanceCount; -} - -/* -** Destructor -** -*/ -MeterWindow::~MeterWindow() -{ - m_State = STATE_CLOSING; - - if (!m_OnCloseAction.empty()) - { - Rainmeter::GetInstance().ExecuteCommand(m_OnCloseAction.c_str(), this); - } - - Dispose(false); - - --c_InstanceCount; - - if (c_InstanceCount == 0) - { - UnregisterClass(METERWINDOW_CLASS_NAME, Rainmeter::GetInstance().GetModuleInstance()); - - if (c_DwmInstance) - { - FreeLibrary(c_DwmInstance); - c_DwmInstance = nullptr; - - c_DwmEnableBlurBehindWindow = nullptr; - c_DwmGetColorizationColor = nullptr; - c_DwmSetWindowAttribute = nullptr; - c_DwmIsCompositionEnabled = nullptr; - } - } -} - -/* -** Kills timers/hooks and disposes buffers -** -*/ -void MeterWindow::Dispose(bool refresh) -{ - // Kill the timer/hook - KillTimer(m_Window, TIMER_METER); - KillTimer(m_Window, TIMER_MOUSE); - KillTimer(m_Window, TIMER_FADE); - KillTimer(m_Window, TIMER_TRANSITION); - - m_FadeStartTime = 0; - - UnregisterMouseInput(); - m_HasMouseScrollAction = false; - - m_ActiveTransition = false; - - m_MouseOver = false; - SetMouseLeaveEvent(true); - - // Destroy the meters - for (auto j = m_Meters.begin(); j != m_Meters.end(); ++j) - { - delete (*j); - } - m_Meters.clear(); - - // Destroy the measures - for (auto i = m_Measures.begin(); i != m_Measures.end(); ++i) - { - delete (*i); - } - m_Measures.clear(); - - delete m_Background; - m_Background = nullptr; - - m_BackgroundSize.cx = m_BackgroundSize.cy = 0; - m_BackgroundName.clear(); - - if (m_BlurRegion) - { - DeleteObject(m_BlurRegion); - m_BlurRegion = nullptr; - } - - if (m_FontCollection) - { - delete m_FontCollection; - m_FontCollection = nullptr; - } - - if (!refresh) - { - if (m_Window) - { - DestroyWindow(m_Window); - m_Window = nullptr; - } - } - - delete m_Canvas; - m_Canvas = nullptr; -} - -/* -** Initializes the window, creates the class and the window. -** -*/ -void MeterWindow::Initialize() -{ - m_Window = CreateWindowEx( - WS_EX_TOOLWINDOW | WS_EX_LAYERED, - METERWINDOW_CLASS_NAME, - nullptr, - WS_POPUP, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - nullptr, - nullptr, - Rainmeter::GetInstance().GetModuleInstance(), - this); - - setlocale(LC_NUMERIC, "C"); - - // Mark the window to ignore the Aero peek - IgnoreAeroPeek(); - - Refresh(true, true); - if (!m_WindowStartHidden) - { - if (m_WindowHide == HIDEMODE_FADEOUT) - { - FadeWindow(0, 255); - } - else - { - FadeWindow(0, m_AlphaValue); - } - } -} - -/* -** Excludes this window from the Aero Peek. -** -*/ -void MeterWindow::IgnoreAeroPeek() -{ - if (c_DwmSetWindowAttribute) - { - BOOL bValue = TRUE; - c_DwmSetWindowAttribute(m_Window, DWMWA_EXCLUDED_FROM_PEEK, &bValue, sizeof(bValue)); - } -} - -/* -** Registers to receive WM_INPUT for the mouse events. -** -*/ -void MeterWindow::RegisterMouseInput() -{ - if (!m_MouseInputRegistered && m_HasMouseScrollAction) - { - RAWINPUTDEVICE rid; - rid.usUsagePage = 0x01; - rid.usUsage = 0x02; // HID mouse - rid.dwFlags = RIDEV_INPUTSINK; - rid.hwndTarget = m_Window; - if (RegisterRawInputDevices(&rid, 1, sizeof(rid))) - { - m_MouseInputRegistered = true; - } - } -} - -void MeterWindow::UnregisterMouseInput() -{ - if (m_MouseInputRegistered) - { - RAWINPUTDEVICE rid; - rid.usUsagePage = 0x01; - rid.usUsage = 0x02; // HID mouse - rid.dwFlags = RIDEV_REMOVE; - rid.hwndTarget = m_Window; - RegisterRawInputDevices(&rid, 1, sizeof(rid)); - m_MouseInputRegistered = false; - } -} - -void MeterWindow::AddWindowExStyle(LONG_PTR flag) -{ - LONG_PTR style = GetWindowLongPtr(m_Window, GWL_EXSTYLE); - if ((style & flag) == 0) - { - SetWindowLongPtr(m_Window, GWL_EXSTYLE, style | flag); - } -} - -void MeterWindow::RemoveWindowExStyle(LONG_PTR flag) -{ - LONG_PTR style = GetWindowLongPtr(m_Window, GWL_EXSTYLE); - if ((style & flag) != 0) - { - SetWindowLongPtr(m_Window, GWL_EXSTYLE, style & ~flag); - } -} - -/* -** Unloads the skin with delay to avoid crash (and for fade to complete). -** -*/ -void MeterWindow::Deactivate() -{ - if (m_State == STATE_CLOSING) return; - m_State = STATE_CLOSING; - - Rainmeter::GetInstance().RemoveMeterWindow(this); - Rainmeter::GetInstance().AddUnmanagedMeterWindow(this); - - HideFade(); - SetTimer(m_Window, TIMER_DEACTIVATE, m_FadeDuration + 50, nullptr); -} - -/* -** Rebuilds the skin. -** -*/ -void MeterWindow::Refresh(bool init, bool all) -{ - if (m_State == STATE_CLOSING) return; - m_State = STATE_REFRESHING; - - Rainmeter::GetInstance().SetCurrentParser(&m_Parser); - - LogNoticeF(this, L"Refreshing skin"); - - SetResizeWindowMode(RESIZEMODE_RESET); - - if (!init) - { - Dispose(true); - } - - ZPOSITION oldZPos = m_WindowZPosition; - - if (!ReadSkin()) - { - Rainmeter::GetInstance().DeactivateSkin(this, -1); - return; - } - - // Remove transparent flag - RemoveWindowExStyle(WS_EX_TRANSPARENT); - - m_Hidden = m_WindowStartHidden; - m_TransparencyValue = m_AlphaValue; - - Update(true); - - if (m_BlurMode == BLURMODE_NONE) - { - HideBlur(); - } - else - { - ShowBlur(); - } - - if (m_KeepOnScreen) - { - MapCoordsToScreen(m_ScreenX, m_ScreenY, m_WindowW, m_WindowH); - } - - SetWindowPos(m_Window, nullptr, m_ScreenX, m_ScreenY, m_WindowW, m_WindowH, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING); - - ScreenToWindow(); - - if (init) - { - ChangeSingleZPos(m_WindowZPosition, all); - } - else if (all || oldZPos != m_WindowZPosition) - { - ChangeZPos(m_WindowZPosition, all); - } - - // Start the timers - if (m_WindowUpdate >= 0) - { - SetTimer(m_Window, TIMER_METER, m_WindowUpdate, nullptr); - } - - SetTimer(m_Window, TIMER_MOUSE, INTERVAL_MOUSE, nullptr); - - Rainmeter::GetInstance().SetCurrentParser(nullptr); - - m_State = STATE_RUNNING; - - if (!m_OnRefreshAction.empty()) - { - Rainmeter::GetInstance().ExecuteCommand(m_OnRefreshAction.c_str(), this); - } -} - -void MeterWindow::SetMouseLeaveEvent(bool cancel) -{ - if (!cancel && (!m_MouseOver || m_ClickThrough)) return; - - // Check whether the mouse event is set - TRACKMOUSEEVENT tme = {sizeof(TRACKMOUSEEVENT)}; - tme.hwndTrack = m_Window; - tme.dwFlags = TME_QUERY; - - if (TrackMouseEvent(&tme) != 0) - { - if (cancel) - { - if (tme.dwFlags == 0) return; - } - else - { - if (m_WindowDraggable) - { - if (tme.dwFlags == (TME_LEAVE | TME_NONCLIENT)) return; - } - else - { - if (tme.dwFlags == TME_LEAVE) return; - } - } - } - - tme.cbSize = sizeof(TRACKMOUSEEVENT); - tme.hwndTrack = m_Window; - - // Cancel the mouse event set before - tme.dwFlags |= TME_CANCEL; - TrackMouseEvent(&tme); - - if (cancel) return; - - // Set the mouse event - tme.dwFlags = TME_LEAVE; - if (m_WindowDraggable) - { - tme.dwFlags |= TME_NONCLIENT; - } - TrackMouseEvent(&tme); -} - -void MeterWindow::MapCoordsToScreen(int& x, int& y, int w, int h) -{ - const size_t numOfMonitors = System::GetMonitorCount(); // intentional - const std::vector& monitors = System::GetMultiMonitorInfo().monitors; - - // Check that the window is inside the screen area - POINT pt = {x + w / 2, y + h / 2}; - for (int i = 0; i < 5; ++i) - { - switch (i) - { - case 0: - // Use initial value - break; - - case 1: - pt.x = x; - pt.y = y; - break; - - case 2: - pt.x = x + w; - pt.y = y + h; - break; - - case 3: - pt.x = x; - pt.y = y + h; - break; - - case 4: - pt.x = x + w; - pt.y = y; - break; - } - - for (auto iter = monitors.cbegin(); iter != monitors.cend(); ++iter) - { - if (!(*iter).active) continue; - - const RECT r = (*iter).screen; - if (pt.x >= r.left && pt.x < r.right && pt.y >= r.top && pt.y < r.bottom) - { - x = min(x, r.right - w); - x = max(x, r.left); - y = min(y, r.bottom - h); - y = max(y, r.top); - return; - } - } - } - - // No monitor found for the window -> Use the default work area - const RECT r = monitors[System::GetMultiMonitorInfo().primary - 1].work; - x = min(x, r.right - w); - x = max(x, r.left); - y = min(y, r.bottom - h); - y = max(y, r.top); -} - -/* -** Moves the window to a new place (on the virtual screen) -** -*/ -void MeterWindow::MoveWindow(int x, int y) -{ - SetWindowPos(m_Window, nullptr, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); - - SavePositionIfAppropriate(); -} - -/* -** Sets the window's z-position -** -*/ -void MeterWindow::ChangeZPos(ZPOSITION zPos, bool all) -{ - HWND winPos = HWND_NOTOPMOST; - m_WindowZPosition = zPos; - - switch (zPos) - { - case ZPOSITION_ONTOPMOST: - case ZPOSITION_ONTOP: - winPos = HWND_TOPMOST; - break; - - case ZPOSITION_ONBOTTOM: - if (all) - { - if (System::GetShowDesktop()) - { - // Insert after the system window temporarily to keep order - winPos = System::GetWindow(); - } - else - { - // Insert after the helper window - winPos = System::GetHelperWindow(); - } - } - else - { - winPos = HWND_BOTTOM; - } - break; - - case ZPOSITION_NORMAL: - if (all || !Rainmeter::GetInstance().IsNormalStayDesktop()) break; - case ZPOSITION_ONDESKTOP: - if (System::GetShowDesktop()) - { - winPos = System::GetHelperWindow(); - - if (all) - { - // Insert after the helper window - } - else - { - // Find the "backmost" topmost window - while (winPos = ::GetNextWindow(winPos, GW_HWNDPREV)) - { - if (GetWindowLongPtr(winPos, GWL_EXSTYLE) & WS_EX_TOPMOST) - { - // Insert after the found window - if (0 != SetWindowPos(m_Window, winPos, 0, 0, 0, 0, ZPOS_FLAGS)) - { - break; - } - } - } - return; - } - } - else - { - if (all) - { - // Insert after the helper window - winPos = System::GetHelperWindow(); - } - else - { - winPos = HWND_BOTTOM; - } - } - break; - } - - SetWindowPos(m_Window, winPos, 0, 0, 0, 0, ZPOS_FLAGS); -} - -/* -** Sets the window's z-position in proper order. -** -*/ -void MeterWindow::ChangeSingleZPos(ZPOSITION zPos, bool all) -{ - if (zPos == ZPOSITION_NORMAL && Rainmeter::GetInstance().IsNormalStayDesktop() && (!all || System::GetShowDesktop())) - { - m_WindowZPosition = zPos; - - // Set window on top of all other ZPOSITION_ONDESKTOP, ZPOSITION_BOTTOM, and ZPOSITION_NORMAL windows - SetWindowPos(m_Window, System::GetBackmostTopWindow(), 0, 0, 0, 0, ZPOS_FLAGS); - - // Bring window on top of other application windows - BringWindowToTop(m_Window); - } - else - { - ChangeZPos(zPos, all); - } -} - -/* -** Runs the bang command with the given arguments. -** Correct number of arguments must be passed (or use Rainmeter::ExecuteBang). -*/ -void MeterWindow::DoBang(Bang bang, const std::vector& args) -{ - switch (bang) - { - case Bang::Refresh: - // Refresh needs to be delayed since it crashes if done during Update() - PostMessage(m_Window, WM_METERWINDOW_DELAYED_REFRESH, (WPARAM)nullptr, (LPARAM)nullptr); - break; - - case Bang::Redraw: - Redraw(); - break; - - case Bang::Update: - KillTimer(m_Window, TIMER_METER); // Kill timer temporarily - Update(false); - if (m_WindowUpdate >= 0) - { - SetTimer(m_Window, TIMER_METER, m_WindowUpdate, nullptr); - } - break; - - case Bang::ShowBlur: - ShowBlur(); - break; - - case Bang::HideBlur: - HideBlur(); - break; - - case Bang::ToggleBlur: - DoBang(IsBlur() ? Bang::HideBlur : Bang::ShowBlur, args); - break; - - case Bang::AddBlur: - ResizeBlur(args[0], RGN_OR); - if (IsBlur()) ShowBlur(); - break; - - case Bang::RemoveBlur: - ResizeBlur(args[0], RGN_DIFF); - if (IsBlur()) ShowBlur(); - break; - - case Bang::ToggleMeter: - ToggleMeter(args[0]); - break; - - case Bang::ShowMeter: - ShowMeter(args[0]); - break; - - case Bang::HideMeter: - HideMeter(args[0]); - break; - - case Bang::UpdateMeter: - UpdateMeter(args[0]); - break; - - case Bang::ToggleMeterGroup: - ToggleMeter(args[0], true); - break; - - case Bang::ShowMeterGroup: - ShowMeter(args[0], true); - break; - - case Bang::HideMeterGroup: - HideMeter(args[0], true); - break; - - case Bang::UpdateMeterGroup: - UpdateMeter(args[0], true); - break; - - case Bang::ToggleMeasure: - ToggleMeasure(args[0]); - break; - - case Bang::EnableMeasure: - EnableMeasure(args[0]); - break; - - case Bang::DisableMeasure: - DisableMeasure(args[0]); - break; - - case Bang::PauseMeasure: - PauseMeasure(args[0]); - break; - - case Bang::UnpauseMeasure: - UnpauseMeasure(args[0]); - break; - - case Bang::TogglePauseMeasure: - TogglePauseMeasure(args[0]); - break; - - case Bang::UpdateMeasure: - UpdateMeasure(args[0]); - DialogAbout::UpdateMeasures(this); - break; - - case Bang::DisableMeasureGroup: - DisableMeasure(args[0], true); - break; - - case Bang::ToggleMeasureGroup: - ToggleMeasure(args[0], true); - break; - - case Bang::EnableMeasureGroup: - EnableMeasure(args[0], true); - break; - - case Bang::PauseMeasureGroup: - PauseMeasure(args[0], true); - break; - - case Bang::UnpauseMeasureGroup: - UnpauseMeasure(args[0], true); - break; - - case Bang::TogglePauseMeasureGroup: - TogglePauseMeasure(args[0], true); - break; - - case Bang::UpdateMeasureGroup: - UpdateMeasure(args[0], true); - DialogAbout::UpdateMeasures(this); - break; - - case Bang::Show: - m_Hidden = false; - ShowWindow(m_Window, SW_SHOWNOACTIVATE); - UpdateWindowTransparency((m_WindowHide == HIDEMODE_FADEOUT) ? 255 : m_AlphaValue); - break; - - case Bang::Hide: - m_Hidden = true; - ShowWindow(m_Window, SW_HIDE); - break; - - case Bang::Toggle: - DoBang(m_Hidden ? Bang::Show : Bang::Hide, args); - break; - - case Bang::ShowFade: - ShowFade(); - break; - - case Bang::HideFade: - HideFade(); - break; - - case Bang::ToggleFade: - DoBang(m_Hidden ? Bang::ShowFade : Bang::HideFade, args); - break; - - case Bang::Move: - { - int x = m_Parser.ParseInt(args[0].c_str(), 0); - int y = m_Parser.ParseInt(args[1].c_str(), 0); - MoveWindow(x, y); - } - break; - - case Bang::ZPos: - SetWindowZPosition((ZPOSITION)m_Parser.ParseInt(args[0].c_str(), 0)); - break; - - case Bang::ClickThrough: - { - int f = m_Parser.ParseInt(args[0].c_str(), 0); - SetClickThrough((f == -1) ? !m_ClickThrough : f != 0); - } - break; - - case Bang::Draggable: - { - int f = m_Parser.ParseInt(args[0].c_str(), 0); - SetWindowDraggable((f == -1) ? !m_WindowDraggable : f != 0); - } - break; - - case Bang::SnapEdges: - { - int f = m_Parser.ParseInt(args[0].c_str(), 0); - SetSnapEdges((f == -1) ? !m_SnapEdges : f != 0); - } - break; - - case Bang::KeepOnScreen: - { - int f = m_Parser.ParseInt(args[0].c_str(), 0); - SetKeepOnScreen((f == -1) ? !m_KeepOnScreen : f != 0); - } - break; - - case Bang::SetTransparency: - { - const std::wstring& arg = args[0]; - m_AlphaValue = ConfigParser::ParseInt(arg.c_str(), 255); - m_AlphaValue = max(m_AlphaValue, 0); - m_AlphaValue = min(m_AlphaValue, 255); - UpdateWindowTransparency(m_AlphaValue); - } - break; - - case Bang::MoveMeter: - { - int x = m_Parser.ParseInt(args[0].c_str(), 0); - int y = m_Parser.ParseInt(args[1].c_str(), 0); - MoveMeter(args[2], x, y); - } - break; - - case Bang::CommandMeasure: - { - const std::wstring& measure = args[0]; - Measure* m = GetMeasure(measure); - if (m) - { - m->Command(args[1]); - } - else - { - LogWarningF(this, L"!CommandMeasure: [%s] not found", measure.c_str()); - } - } - break; - - case Bang::PluginBang: - { - std::wstring arg = args[0]; - std::wstring::size_type pos; - while ((pos = arg.find(L'"')) != std::wstring::npos) - { - arg.erase(pos, 1); - } - - std::wstring measure; - pos = arg.find(L' '); - if (pos != std::wstring::npos) - { - measure.assign(arg, 0, pos); - ++pos; - } - else - { - measure = arg; - } - arg.erase(0, pos); - - if (!measure.empty()) - { - Measure* m = GetMeasure(measure); - if (m) - { - m->Command(arg); - return; - } - - LogWarningF(this, L"!PluginBang: [%s] not found", measure.c_str()); - } - else - { - LogErrorF(this, L"!PluginBang: Invalid parameters"); - } - } - break; - - case Bang::SetVariable: - SetVariable(args[0], args[1]); - break; - - case Bang::SetOption: - SetOption(args[0], args[1], args[2], false); - break; - - case Bang::SetOptionGroup: - SetOption(args[0], args[1], args[2], true); - break; - - case Bang::SkinCustomMenu: - Rainmeter::GetInstance().ShowSkinCustomContextMenu(System::GetCursorPosition(), this); - break; - } -} - -/* -** Enables blurring of the window background (using Aero) -** -*/ -void MeterWindow::ShowBlur() -{ - if (c_DwmGetColorizationColor && c_DwmIsCompositionEnabled && c_DwmEnableBlurBehindWindow) - { - SetBlur(true); - - // Check that Aero and transparency is enabled - DWORD color; - BOOL opaque, enabled; - if (c_DwmGetColorizationColor(&color, &opaque) != S_OK) - { - opaque = TRUE; - } - if (c_DwmIsCompositionEnabled(&enabled) != S_OK) - { - enabled = FALSE; - } - if (opaque || !enabled) return; - - if (m_BlurMode == BLURMODE_FULL) - { - if (m_BlurRegion) DeleteObject(m_BlurRegion); - m_BlurRegion = CreateRectRgn(0, 0, GetW(), GetH()); - } - - BlurBehindWindow(TRUE); - } -} - -/* -** Disables Aero blur -** -*/ -void MeterWindow::HideBlur() -{ - if (c_DwmEnableBlurBehindWindow) - { - SetBlur(false); - - BlurBehindWindow(FALSE); - } -} - -/* -** Adds to or removes from blur region -** -*/ -void MeterWindow::ResizeBlur(const std::wstring& arg, int mode) -{ - if (IsWindowsVistaOrGreater()) - { - WCHAR* parseSz = _wcsdup(arg.c_str()); - int type, x, y, w = 0, h = 0; - - WCHAR* token = wcstok(parseSz, L","); - if (token) - { - while (token[0] == L' ') ++token; - type = m_Parser.ParseInt(token, 0); - - token = wcstok(nullptr, L","); - if (token) - { - while (token[0] == L' ') ++token; - x = m_Parser.ParseInt(token, 0); - - token = wcstok(nullptr, L","); - if (token) - { - while (token[0] == L' ') ++token; - y = m_Parser.ParseInt(token, 0); - - token = wcstok(nullptr, L","); - if (token) - { - while (token[0] == L' ') ++token; - w = m_Parser.ParseInt(token, 0); - - token = wcstok(nullptr, L","); - if (token) - { - while (token[0] == L' ') ++token; - h = m_Parser.ParseInt(token, 0); - } - } - } - } - } - - if (w && h) - { - HRGN tempRegion; - - switch (type) - { - case 1: - tempRegion = CreateRectRgn(x, y, w, h); - break; - - case 2: - token = wcstok(nullptr, L","); - if (token) - { - while (token[0] == L' ') ++token; - int r = m_Parser.ParseInt(token, 0); - tempRegion = CreateRoundRectRgn(x, y, w, h, r, r); - } - break; - - case 3: - tempRegion = CreateEllipticRgn(x, y, w, h); - break; - - default: // Unknown type - free(parseSz); - return; - } - - CombineRgn(m_BlurRegion, m_BlurRegion, tempRegion, mode); - DeleteObject(tempRegion); - } - free(parseSz); - } -} - -/* -** Helper function that compares the given name to section's name. -** -*/ -bool CompareName(const Section* section, const WCHAR* name, bool group) -{ - return (group) ? section->BelongsToGroup(name) : (_wcsicmp(section->GetName(), name) == 0); -} - -/* -** Shows the given meter -** -*/ -void MeterWindow::ShowMeter(const std::wstring& name, bool group) -{ - const WCHAR* meter = name.c_str(); - - std::vector::const_iterator j = m_Meters.begin(); - for ( ; j != m_Meters.end(); ++j) - { - if (CompareName((*j), meter, group)) - { - (*j)->Show(); - SetResizeWindowMode(RESIZEMODE_CHECK); // Need to recalculate the window size - if (!group) return; - } - } - - if (!group) LogErrorF(this, L"!ShowMeter: [%s] not found", meter); -} - -/* -** Hides the given meter -** -*/ -void MeterWindow::HideMeter(const std::wstring& name, bool group) -{ - const WCHAR* meter = name.c_str(); - - std::vector::const_iterator j = m_Meters.begin(); - for ( ; j != m_Meters.end(); ++j) - { - if (CompareName((*j), meter, group)) - { - (*j)->Hide(); - SetResizeWindowMode(RESIZEMODE_CHECK); // Need to recalculate the window size - if (!group) return; - } - } - - if (!group) LogErrorF(this, L"!HideMeter: [%s] not found", meter); -} - -/* -** Toggles the given meter -** -*/ -void MeterWindow::ToggleMeter(const std::wstring& name, bool group) -{ - const WCHAR* meter = name.c_str(); - - std::vector::const_iterator j = m_Meters.begin(); - for ( ; j != m_Meters.end(); ++j) - { - if (CompareName((*j), meter, group)) - { - if ((*j)->IsHidden()) - { - (*j)->Show(); - } - else - { - (*j)->Hide(); - } - SetResizeWindowMode(RESIZEMODE_CHECK); // Need to recalculate the window size - if (!group) return; - } - } - - if (!group) LogErrorF(this, L"!ToggleMeter: [%s] not found", meter); -} - -/* -** Moves the given meter -** -*/ -void MeterWindow::MoveMeter(const std::wstring& name, int x, int y) -{ - const WCHAR* meter = name.c_str(); - - std::vector::const_iterator j = m_Meters.begin(); - for ( ; j != m_Meters.end(); ++j) - { - if (CompareName((*j), meter, false)) - { - (*j)->SetX(x); - (*j)->SetY(y); - SetResizeWindowMode(RESIZEMODE_CHECK); // Need to recalculate the window size - return; - } - } - - LogErrorF(this, L"!MoveMeter: [%s] not found", meter); -} - -/* -** Updates the given meter -** -*/ -void MeterWindow::UpdateMeter(const std::wstring& name, bool group) -{ - const WCHAR* meter = name.c_str(); - bool all = false; - - if (!group && meter[0] == L'*' && meter[1] == L'\0') // Allow [!UpdateMeter *] - { - all = true; - group = true; - } - - bool bActiveTransition = false; - bool bContinue = true; - for (auto j = m_Meters.cbegin(); j != m_Meters.cend(); ++j) - { - if (all || (bContinue && CompareName((*j), meter, group))) - { - if (UpdateMeter((*j), bActiveTransition, true)) - { - (*j)->DoUpdateAction(); - } - - SetResizeWindowMode(RESIZEMODE_CHECK); // Need to recalculate the window size - if (!group) - { - bContinue = false; - if (bActiveTransition) break; - } - } - else - { - // Check for transitions - if (!bActiveTransition && (*j)->HasActiveTransition()) - { - bActiveTransition = true; - if (!group && !bContinue) break; - } - } - } - - // Post-updates - PostUpdate(bActiveTransition); - - if (!group && bContinue) LogErrorF(this, L"!UpdateMeter: [%s] not found", meter); -} - -/* -** Enables the given measure -** -*/ -void MeterWindow::EnableMeasure(const std::wstring& name, bool group) -{ - const WCHAR* measure = name.c_str(); - - std::vector::const_iterator i = m_Measures.begin(); - for ( ; i != m_Measures.end(); ++i) - { - if (CompareName((*i), measure, group)) - { - (*i)->Enable(); - if (!group) return; - } - } - - if (!group) LogErrorF(this, L"!EnableMeasure: [%s] not found", measure); -} - -/* -** Disables the given measure -** -*/ -void MeterWindow::DisableMeasure(const std::wstring& name, bool group) -{ - const WCHAR* measure = name.c_str(); - - std::vector::const_iterator i = m_Measures.begin(); - for ( ; i != m_Measures.end(); ++i) - { - if (CompareName((*i), measure, group)) - { - (*i)->Disable(); - if (!group) return; - } - } - - if (!group) LogErrorF(this, L"!DisableMeasure: [%s] not found", measure); -} - -/* -** Toggles the given measure -** -*/ -void MeterWindow::ToggleMeasure(const std::wstring& name, bool group) -{ - const WCHAR* measure = name.c_str(); - - std::vector::const_iterator i = m_Measures.begin(); - for ( ; i != m_Measures.end(); ++i) - { - if (CompareName((*i), measure, group)) - { - if ((*i)->IsDisabled()) - { - (*i)->Enable(); - } - else - { - (*i)->Disable(); - } - if (!group) return; - } - } - - if (!group) LogErrorF(this, L"!ToggleMeasure: [%s] not found", measure); -} - -/* -** Pauses the given measure -** -*/ -void MeterWindow::PauseMeasure(const std::wstring& name, bool group) -{ - const WCHAR* measure = name.c_str(); - - std::vector::const_iterator i = m_Measures.begin(); - for ( ; i != m_Measures.end(); ++i) - { - if (CompareName((*i), measure, group)) - { - (*i)->Pause(); - if (!group) return; - } - } - - if (!group) LogErrorF(this, L"!PauseMeasure: [%s] not found", measure); -} - -/* -** Unpauses the given measure -** -*/ -void MeterWindow::UnpauseMeasure(const std::wstring& name, bool group) -{ - const WCHAR* measure = name.c_str(); - - std::vector::const_iterator i = m_Measures.begin(); - for ( ; i != m_Measures.end(); ++i) - { - if (CompareName((*i), measure, group)) - { - (*i)->Unpause(); - if (!group) return; - } - } - - if (!group) LogErrorF(this, L"!UnpauseMeasure: [%s] not found", measure); -} - -/* -** Toggles the pause state of the given measure -** -*/ -void MeterWindow::TogglePauseMeasure(const std::wstring& name, bool group) -{ - const WCHAR* measure = name.c_str(); - - std::vector::const_iterator i = m_Measures.begin(); - for ( ; i != m_Measures.end(); ++i) - { - if (CompareName((*i), measure, group)) - { - if ((*i)->IsPaused()) - { - (*i)->Unpause(); - } - else - { - (*i)->Pause(); - } - if (!group) return; - } - } - - if (!group) LogErrorF(this, L"!TogglePauseMeasure: [%s] not found", measure); -} - -/* -** Updates the given measure -** -*/ -void MeterWindow::UpdateMeasure(const std::wstring& name, bool group) -{ - const WCHAR* measure = name.c_str(); - bool all = false; - - if (!group && measure[0] == L'*' && measure[1] == L'\0') // Allow [!UpdateMeasure *] - { - all = true; - group = true; - } - - bool bNetStats = m_HasNetMeasures; - for (auto i = m_Measures.cbegin(); i != m_Measures.cend(); ++i) - { - if (all || CompareName((*i), measure, group)) - { - if (bNetStats && (*i)->GetTypeID() == TypeID()) - { - MeasureNet::UpdateIFTable(); - MeasureNet::UpdateStats(); - bNetStats = false; - } - - if (UpdateMeasure((*i), true)) - { - (*i)->DoUpdateAction(); - (*i)->DoChangeAction(); - } - - if (!group) return; - } - } - - if (!group) LogErrorF(this, L"!UpdateMeasure: [%s] not found", measure); -} - -/* -** Sets variable to given value. -** -*/ -void MeterWindow::SetVariable(const std::wstring& variable, const std::wstring& value) -{ - double result; - if (m_Parser.ParseFormula(value, &result)) - { - WCHAR buffer[256]; - int len = _snwprintf_s(buffer, _TRUNCATE, L"%.5f", result); - Measure::RemoveTrailingZero(buffer, len); - - const std::wstring& resultString = buffer; - - m_Parser.SetVariable(variable, resultString); - } - else - { - m_Parser.SetVariable(variable, value); - } -} - -/* -** Changes the property of a meter or measure. -** -*/ -void MeterWindow::SetOption(const std::wstring& section, const std::wstring& option, const std::wstring& value, bool group) -{ - auto setValue = [&](Section* section, const std::wstring& option, const std::wstring& value) - { - // Force DynamicVariables temporarily (until next ReadOptions()). - section->SetDynamicVariables(true); - - if (value.empty()) - { - m_Parser.DeleteValue(section->GetOriginalName(), option); - } - else - { - m_Parser.SetValue(section->GetOriginalName(), option, value); - } - }; - - if (group) - { - for (auto j = m_Meters.begin(); j != m_Meters.end(); ++j) - { - if ((*j)->BelongsToGroup(section)) - { - setValue(*j, option, value); - } - } - - for (auto i = m_Measures.begin(); i != m_Measures.end(); ++i) - { - if ((*i)->BelongsToGroup(section)) - { - setValue(*i, option, value); - } - } - } - else - { - Meter* meter = GetMeter(section); - if (meter) - { - setValue(meter, option, value); - return; - } - - Measure* measure = GetMeasure(section); - if (measure) - { - setValue(measure, option, value); - return; - } - - // ContextTitle and ContextAction in [Rainmeter] are dynamic - if (_wcsicmp(section.c_str(), L"Rainmeter") == 0 && - _wcsnicmp(option.c_str(), L"Context", 7) == 0) - { - if (value.empty()) - { - m_Parser.DeleteValue(section, option); - } - else - { - m_Parser.SetValue(section, option, value); - } - } - - // Is it a style? - } -} - -/* -** Calculates the screen cordinates from the WindowX/Y options -** -*/ -void MeterWindow::WindowToScreen() -{ - std::wstring::size_type index, index2; - int pixel = 0; - float num; - int screenx, screeny, screenh, screenw; - - const int numOfMonitors = (int)System::GetMonitorCount(); - const MultiMonitorInfo& monitorsInfo = System::GetMultiMonitorInfo(); - const std::vector& monitors = monitorsInfo.monitors; - - // Clear position flags - m_WindowXScreen = m_WindowYScreen = monitorsInfo.primary; // Default to primary screen - m_WindowXScreenDefined = m_WindowYScreenDefined = false; - m_WindowXFromRight = m_WindowYFromBottom = false; // Default to from left/top - m_WindowXPercentage = m_WindowYPercentage = false; // Default to pixels - m_AnchorXFromRight = m_AnchorYFromBottom = false; - m_AnchorXPercentage = m_AnchorYPercentage = false; - - // --- Calculate AnchorScreenX --- - - index = m_AnchorX.find_first_not_of(L"0123456789."); - num = (float)_wtof(m_AnchorX.substr(0,index).c_str()); - index = m_AnchorX.find_last_of(L'%'); - if (index != std::wstring::npos) m_AnchorXPercentage = true; - index = m_AnchorX.find_last_of(L'R'); - if (index != std::wstring::npos) m_AnchorXFromRight = true; - if (m_AnchorXPercentage) //is a percentage - { - pixel = (int)(m_WindowW * num / 100.0f); - } - else - { - pixel = (int)num; - } - if (m_AnchorXFromRight) //measure from right - { - pixel = m_WindowW - pixel; - } - else - { - //pixel = pixel; - } - m_AnchorScreenX = pixel; - - // --- Calculate AnchorScreenY --- - - index = m_AnchorY.find_first_not_of(L"0123456789."); - num = (float)_wtof(m_AnchorY.substr(0,index).c_str()); - index = m_AnchorY.find_last_of(L'%'); - if (index != std::wstring::npos) m_AnchorYPercentage = true; - index = m_AnchorY.find_last_of(L'R'); - if (index != std::wstring::npos) m_AnchorYFromBottom = true; - if (m_AnchorYPercentage) //is a percentage - { - pixel = (int)(m_WindowH * num / 100.0f); - } - else - { - pixel = (int)num; - } - if (m_AnchorYFromBottom) //measure from bottom - { - pixel = m_WindowH - pixel; - } - else - { - //pixel = pixel; - } - m_AnchorScreenY = pixel; - - // --- Calculate ScreenX --- - - index = m_WindowX.find_first_not_of(L"-0123456789."); - num = (float)_wtof(m_WindowX.substr(0,index).c_str()); - index = m_WindowX.find_last_of(L'%'); - index2 = m_WindowX.find_last_of(L'#'); // for ignoring the non-replaced variables such as "#WORKAREAX@n#" - if (index != std::wstring::npos && (index2 == std::wstring::npos || index2 < index)) - { - m_WindowXPercentage = true; - } - index = m_WindowX.find_last_of(L'R'); - if (index != std::wstring::npos && (index2 == std::wstring::npos || index2 < index)) - { - m_WindowXFromRight = true; - } - index = m_WindowX.find_last_of(L'@'); - if (index != std::wstring::npos && (index2 == std::wstring::npos || index2 < index)) - { - index = index + 1; - index2 = m_WindowX.find_first_not_of(L"0123456789", index); - - std::wstring screenStr = m_WindowX.substr(index, (index2 != std::wstring::npos) ? index2 - index : std::wstring::npos); - if (!screenStr.empty()) - { - int screenIndex = _wtoi(screenStr.c_str()); - if (screenIndex >= 0 && (screenIndex == 0 || screenIndex <= numOfMonitors && monitors[screenIndex - 1].active)) - { - m_WindowXScreen = screenIndex; - m_WindowXScreenDefined = true; - m_WindowYScreen = m_WindowXScreen; //Default to X and Y on same screen if not overridden on WindowY - m_WindowYScreenDefined = true; - } - } - } - if (m_WindowXScreen == 0) - { - screenx = monitorsInfo.vsL; - screenw = monitorsInfo.vsW; - } - else - { - screenx = monitors[m_WindowXScreen - 1].screen.left; - screenw = monitors[m_WindowXScreen - 1].screen.right - monitors[m_WindowXScreen - 1].screen.left; - } - if (m_WindowXPercentage) //is a percentage - { - pixel = (int)(screenw * num / 100.0f); - } - else - { - pixel = (int)num; - } - if (m_WindowXFromRight) //measure from right - { - pixel = screenx + (screenw - pixel); - } - else - { - pixel = screenx + pixel; - } - m_ScreenX = pixel - m_AnchorScreenX; - - // --- Calculate ScreenY --- - - index = m_WindowY.find_first_not_of(L"-0123456789."); - num = (float)_wtof(m_WindowY.substr(0,index).c_str()); - index = m_WindowY.find_last_of(L'%'); - index2 = m_WindowX.find_last_of(L'#'); // for ignoring the non-replaced variables such as "#WORKAREAY@n#" - if (index != std::wstring::npos && (index2 == std::wstring::npos || index2 < index)) - { - m_WindowYPercentage = true; - } - index = m_WindowY.find_last_of(L'B'); - if (index != std::wstring::npos && (index2 == std::wstring::npos || index2 < index)) - { - m_WindowYFromBottom = true; - } - index = m_WindowY.find_last_of(L'@'); - if (index != std::wstring::npos && (index2 == std::wstring::npos || index2 < index)) - { - index = index + 1; - index2 = m_WindowY.find_first_not_of(L"0123456789", index); - - std::wstring screenStr = m_WindowY.substr(index, (index2 != std::wstring::npos) ? index2 - index : std::wstring::npos); - if (!screenStr.empty()) - { - int screenIndex = _wtoi(screenStr.c_str()); - if (screenIndex >= 0 && (screenIndex == 0 || screenIndex <= numOfMonitors && monitors[screenIndex - 1].active)) - { - m_WindowYScreen = screenIndex; - m_WindowYScreenDefined = true; - } - } - } - if (m_WindowYScreen == 0) - { - screeny = monitorsInfo.vsT; - screenh = monitorsInfo.vsH; - } - else - { - screeny = monitors[m_WindowYScreen - 1].screen.top; - screenh = monitors[m_WindowYScreen - 1].screen.bottom - monitors[m_WindowYScreen - 1].screen.top; - } - if (m_WindowYPercentage) //is a percentage - { - pixel = (int)(screenh * num / 100.0f); - } - else - { - pixel = (int)num; - } - if (m_WindowYFromBottom) //measure from right - { - pixel = screeny + (screenh - pixel); - } - else - { - pixel = screeny + pixel; - } - m_ScreenY = pixel - m_AnchorScreenY; -} - -/* ScreenToWindow -** -** Calculates the WindowX/Y cordinates from the ScreenX/Y -** -*/ -void MeterWindow::ScreenToWindow() -{ - WCHAR buffer[256]; - int pixel = 0; - float num; - int screenx, screeny, screenh, screenw; - - const size_t numOfMonitors = System::GetMonitorCount(); - const MultiMonitorInfo& monitorsInfo = System::GetMultiMonitorInfo(); - const std::vector& monitors = monitorsInfo.monitors; - - // Correct to auto-selected screen - if (m_AutoSelectScreen) - { - RECT rect = {m_ScreenX, m_ScreenY, m_ScreenX + m_WindowW, m_ScreenY + m_WindowH}; - HMONITOR hMonitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST); - - if (hMonitor != nullptr) - { - int screenIndex = 1; - for (auto iter = monitors.cbegin(); iter != monitors.cend(); ++iter, ++screenIndex) - { - if ((*iter).active && (*iter).handle == hMonitor) - { - bool reset = (!m_WindowXScreenDefined || !m_WindowYScreenDefined || - m_WindowXScreen != screenIndex || m_WindowYScreen != screenIndex); - - m_WindowXScreen = m_WindowYScreen = screenIndex; - m_WindowXScreenDefined = m_WindowYScreenDefined = true; - - if (reset) - { - m_Parser.ResetMonitorVariables(this); // Set present monitor variables - } - break; - } - } - } - } - - // --- Calculate WindowX --- - - if (m_WindowXScreen == 0) - { - screenx = monitorsInfo.vsL; - screenw = monitorsInfo.vsW; - } - else - { - screenx = monitors[m_WindowXScreen - 1].screen.left; - screenw = monitors[m_WindowXScreen - 1].screen.right - monitors[m_WindowXScreen - 1].screen.left; - } - if (m_WindowXFromRight) - { - pixel = (screenx + screenw) - m_ScreenX; - pixel -= m_AnchorScreenX; - } - else - { - pixel = m_ScreenX - screenx; - pixel += m_AnchorScreenX; - } - if (m_WindowXPercentage) - { - num = 100.0f * (float)pixel / (float)screenw; - _snwprintf_s(buffer, _TRUNCATE, L"%.5f%%", num); - } - else - { - _itow_s(pixel, buffer, 10); - } - if (m_WindowXFromRight) - { - wcscat_s(buffer, L"R"); - } - if (m_WindowXScreenDefined) - { - _snwprintf_s(buffer, _TRUNCATE, L"%s@%i", buffer, m_WindowXScreen); - } - m_WindowX = buffer; - - // --- Calculate WindowY --- - - if (m_WindowYScreen == 0) - { - screeny = monitorsInfo.vsT; - screenh = monitorsInfo.vsH; - } - else - { - screeny = monitors[m_WindowYScreen - 1].screen.top; - screenh = monitors[m_WindowYScreen - 1].screen.bottom - monitors[m_WindowYScreen - 1].screen.top; - } - if (m_WindowYFromBottom) - { - pixel = (screeny + screenh) - m_ScreenY; - pixel -= m_AnchorScreenY; - } - else - { - pixel = m_ScreenY - screeny; - pixel += m_AnchorScreenY; - } - if (m_WindowYPercentage) - { - num = 100.0f * (float)pixel / (float)screenh; - _snwprintf_s(buffer, _TRUNCATE, L"%.5f%%", num); - } - else - { - _itow_s(pixel, buffer, 10); - } - if (m_WindowYFromBottom) - { - wcscat_s(buffer, L"B"); - } - if (m_WindowYScreenDefined) - { - _snwprintf_s(buffer, _TRUNCATE, L"%s@%i", buffer, m_WindowYScreen); - } - m_WindowY = buffer; -} - -/* -** Reads the skin options from Rainmeter.ini -** -*/ -void MeterWindow::ReadOptions() -{ - WCHAR buffer[32]; - - const WCHAR* section = m_FolderPath.c_str(); - ConfigParser parser; - parser.Initialize(Rainmeter::GetInstance().GetIniFile(), nullptr, section); - - INT writeFlags = 0; - auto addWriteFlag = [&](INT flag) - { - if (parser.GetLastDefaultUsed()) - { - writeFlags |= flag; - } - }; - - // Check if the window position should be read as a formula - double value; - m_WindowX = parser.ReadString(section, L"WindowX", L"0"); - addWriteFlag(OPTION_POSITION); - if (parser.ParseFormula(m_WindowX, &value)) - { - _itow_s((int)value, buffer, 10); - m_WindowX = buffer; - } - m_WindowY = parser.ReadString(section, L"WindowY", L"0"); - addWriteFlag(OPTION_POSITION); - if (parser.ParseFormula(m_WindowY, &value)) - { - _itow_s((int)value, buffer, 10); - m_WindowY = buffer; - } - - m_AnchorX = parser.ReadString(section, L"AnchorX", L"0"); - m_AnchorY = parser.ReadString(section, L"AnchorY", L"0"); - - int zPos = parser.ReadInt(section, L"AlwaysOnTop", ZPOSITION_NORMAL); - addWriteFlag(OPTION_ALWAYSONTOP); - m_WindowZPosition = (zPos >= ZPOSITION_ONDESKTOP && zPos <= ZPOSITION_ONTOPMOST) ? (ZPOSITION)zPos : ZPOSITION_NORMAL; - - int hideMode = parser.ReadInt(section, L"HideOnMouseOver", HIDEMODE_NONE); - m_WindowHide = (hideMode >= HIDEMODE_NONE && hideMode <= HIDEMODE_FADEOUT) ? (HIDEMODE)hideMode : HIDEMODE_NONE; - - m_WindowDraggable = parser.ReadBool(section, L"Draggable", true); - addWriteFlag(OPTION_DRAGGABLE); - - m_SnapEdges = parser.ReadBool(section, L"SnapEdges", true); - addWriteFlag(OPTION_SNAPEDGES); - - m_ClickThrough = parser.ReadBool(section, L"ClickThrough", false); - addWriteFlag(OPTION_CLICKTHROUGH); - - m_KeepOnScreen = parser.ReadBool(section, L"KeepOnScreen", true); - addWriteFlag(OPTION_KEEPONSCREEN); - - m_UseD2D = parser.ReadBool(section, L"UseD2D", true); - m_SavePosition = parser.ReadBool(section, L"SavePosition", true); - m_WindowStartHidden = parser.ReadBool(section, L"StartHidden", false); - m_AutoSelectScreen = parser.ReadBool(section, L"AutoSelectScreen", false); - - m_AlphaValue = parser.ReadInt(section, L"AlphaValue", 255); - m_AlphaValue = max(m_AlphaValue, 0); - m_AlphaValue = min(m_AlphaValue, 255); - - m_FadeDuration = parser.ReadInt(section, L"FadeDuration", 250); - - m_SkinGroup = parser.ReadString(section, L"Group", L""); - - if (writeFlags != 0) - { - WriteOptions(writeFlags); - } - - // Set WindowXScreen/WindowYScreen temporarily - WindowToScreen(); -} - -/* -** Writes the specified options to Rainmeter.ini -** -*/ -void MeterWindow::WriteOptions(INT setting) -{ - const WCHAR* iniFile = Rainmeter::GetInstance().GetIniFile().c_str(); - - if (*iniFile) - { - WCHAR buffer[32]; - const WCHAR* section = m_FolderPath.c_str(); - - if (setting != OPTION_ALL) - { - DialogManage::UpdateSkins(this); - } - - if (setting & OPTION_POSITION) - { - ScreenToWindow(); - - // If position needs to be save, do so. - if (m_SavePosition) - { - WritePrivateProfileString(section, L"WindowX", m_WindowX.c_str(), iniFile); - WritePrivateProfileString(section, L"WindowY", m_WindowY.c_str(), iniFile); - } - - if (setting == OPTION_POSITION) return; - } - - if (setting & OPTION_ALPHAVALUE) - { - _itow_s(m_AlphaValue, buffer, 10); - WritePrivateProfileString(section, L"AlphaValue", buffer, iniFile); - } - - if (setting & OPTION_FADEDURATION) - { - _itow_s(m_FadeDuration, buffer, 10); - WritePrivateProfileString(section, L"FadeDuration", buffer, iniFile); - } - - if (setting & OPTION_CLICKTHROUGH) - { - WritePrivateProfileString(section, L"ClickThrough", m_ClickThrough ? L"1" : L"0", iniFile); - } - - if (setting & OPTION_DRAGGABLE) - { - WritePrivateProfileString(section, L"Draggable", m_WindowDraggable ? L"1" : L"0", iniFile); - } - - if (setting & OPTION_HIDEONMOUSEOVER) - { - _itow_s(m_WindowHide, buffer, 10); - WritePrivateProfileString(section, L"HideOnMouseOver", buffer, iniFile); - } - - if (setting & OPTION_SAVEPOSITION) - { - WritePrivateProfileString(section, L"SavePosition", m_SavePosition ? L"1" : L"0", iniFile); - } - - if (setting & OPTION_SNAPEDGES) - { - WritePrivateProfileString(section, L"SnapEdges", m_SnapEdges ? L"1" : L"0", iniFile); - } - - if (setting & OPTION_KEEPONSCREEN) - { - WritePrivateProfileString(section, L"KeepOnScreen", m_KeepOnScreen ? L"1" : L"0", iniFile); - } - - if (setting & OPTION_AUTOSELECTSCREEN) - { - WritePrivateProfileString(section, L"AutoSelectScreen", m_AutoSelectScreen ? L"1" : L"0", iniFile); - } - - if (setting & OPTION_ALWAYSONTOP) - { - _itow_s(m_WindowZPosition, buffer, 10); - WritePrivateProfileString(section, L"AlwaysOnTop", buffer, iniFile); - } - - if (setting & OPTION_USED2D) - { - WritePrivateProfileString(section, L"UseD2D", m_UseD2D ? L"1" : L"0", iniFile); - } - } -} - -/* -** Reads the skin file and creates the meters and measures. -** -*/ -bool MeterWindow::ReadSkin() -{ - WCHAR buffer[128]; - - std::wstring iniFile = GetFilePath(); - - // Verify whether the file exists - if (_waccess(iniFile.c_str(), 0) == -1) - { - std::wstring message = GetFormattedString(ID_STR_UNABLETOREFRESHSKIN, m_FolderPath.c_str(), m_FileName.c_str()); - Rainmeter::GetInstance().ShowMessage(m_Window, message.c_str(), MB_OK | MB_ICONEXCLAMATION); - return false; - } - - std::wstring resourcePath = GetResourcesPath(); - bool hasResourcesFolder = (_waccess(resourcePath.c_str(), 0) == 0); - - // Read options from Rainmeter.ini. - ReadOptions(); - - m_Parser.Initialize(iniFile, this, nullptr, &resourcePath); - - m_Canvas = Gfx::Canvas::Create( - m_UseD2D && Rainmeter::GetInstance().GetUseD2D() ? Gfx::Renderer::PreferD2D : Gfx::Renderer::GDIP); - m_Canvas->SetAccurateText(m_Parser.ReadBool(L"Rainmeter", L"AccurateText", false)); - - // Gotta have some kind of buffer during initialization - CreateDoubleBuffer(1, 1); - - // Check the version - UINT appVersion = m_Parser.ReadUInt(L"Rainmeter", L"AppVersion", 0); - if (appVersion > RAINMETER_VERSION) - { - if (appVersion % 1000 != 0) - { - _snwprintf_s(buffer, _TRUNCATE, L"%u.%u.%u", appVersion / 1000000, (appVersion / 1000) % 1000, appVersion % 1000); - } - else - { - _snwprintf_s(buffer, _TRUNCATE, L"%u.%u", appVersion / 1000000, (appVersion / 1000) % 1000); - } - - std::wstring text = GetFormattedString(ID_STR_NEWVERSIONREQUIRED, m_FolderPath.c_str(), m_FileName.c_str(), buffer); - Rainmeter::GetInstance().ShowMessage(m_Window, text.c_str(), MB_OK | MB_ICONEXCLAMATION); - return false; - } - - // Initialize window variables - SetWindowPositionVariables(m_ScreenX, m_ScreenY); - SetWindowSizeVariables(0, 0); - - // Global settings - const std::wstring& group = m_Parser.ReadString(L"Rainmeter", L"Group", L""); - if (!group.empty()) - { - m_SkinGroup += L'|'; - m_SkinGroup += group; - } - InitializeGroup(m_SkinGroup); - - static const RECT defMargins = {0}; - m_BackgroundMargins = m_Parser.ReadRECT(L"Rainmeter", L"BackgroundMargins", defMargins); - m_DragMargins = m_Parser.ReadRECT(L"Rainmeter", L"DragMargins", defMargins); - - m_BackgroundMode = (BGMODE)m_Parser.ReadInt(L"Rainmeter", L"BackgroundMode", BGMODE_IMAGE); - m_SolidBevel = (BEVELTYPE)m_Parser.ReadInt(L"Rainmeter", L"BevelType", BEVELTYPE_NONE); - - m_SolidColor = m_Parser.ReadColor(L"Rainmeter", L"SolidColor", Color::Gray); - m_SolidColor2 = m_Parser.ReadColor(L"Rainmeter", L"SolidColor2", m_SolidColor.GetValue()); - m_SolidAngle = (Gdiplus::REAL)m_Parser.ReadFloat(L"Rainmeter", L"GradientAngle", 0.0); - - m_DynamicWindowSize = m_Parser.ReadBool(L"Rainmeter", L"DynamicWindowSize", false); - - if (m_BackgroundMode == BGMODE_IMAGE || m_BackgroundMode == BGMODE_SCALED_IMAGE || m_BackgroundMode == BGMODE_TILED_IMAGE) - { - m_BackgroundName = m_Parser.ReadString(L"Rainmeter", L"Background", L""); - if (!m_BackgroundName.empty()) - { - MakePathAbsolute(m_BackgroundName); - } - else - { - m_BackgroundMode = BGMODE_COPY; - } - } - - m_Mouse.ReadOptions(m_Parser, L"Rainmeter"); - - m_OnRefreshAction = m_Parser.ReadString(L"Rainmeter", L"OnRefreshAction", L"", false); - m_OnCloseAction = m_Parser.ReadString(L"Rainmeter", L"OnCloseAction", L"", false); - m_OnFocusAction = m_Parser.ReadString(L"Rainmeter", L"OnFocusAction", L"", false); - m_OnUnfocusAction = m_Parser.ReadString(L"Rainmeter", L"OnUnfocusAction", L"", false); - m_OnUpdateAction = m_Parser.ReadString(L"Rainmeter", L"OnUpdateAction", L"", false); - m_OnWakeAction = m_Parser.ReadString(L"Rainmeter", L"OnWakeAction", L"", false); - - m_WindowUpdate = m_Parser.ReadInt(L"Rainmeter", L"Update", INTERVAL_METER); - m_TransitionUpdate = m_Parser.ReadInt(L"Rainmeter", L"TransitionUpdate", INTERVAL_TRANSITION); - m_ToolTipHidden = m_Parser.ReadBool(L"Rainmeter", L"ToolTipHidden", false); - - if (IsWindowsVistaOrGreater()) - { - if (m_Parser.ReadBool(L"Rainmeter", L"Blur", false)) - { - const WCHAR* blurRegion = m_Parser.ReadString(L"Rainmeter", L"BlurRegion", L"", false).c_str(); - - if (*blurRegion) - { - m_BlurMode = BLURMODE_REGION; - m_BlurRegion = CreateRectRgn(0, 0, 0, 0); // Create empty region - int i = 1; - - do - { - ResizeBlur(blurRegion, RGN_OR); - - // Check for BlurRegion2, BlurRegion3, etc. - _snwprintf_s(buffer, _TRUNCATE, L"BlurRegion%i", ++i); - blurRegion = m_Parser.ReadString(L"Rainmeter", buffer, L"").c_str(); - } - while (*blurRegion); - } - else - { - m_BlurMode = BLURMODE_FULL; - } - } - else - { - m_BlurMode = BLURMODE_NONE; - } - } - - // Load fonts in Resources folder - if (hasResourcesFolder) - { - WIN32_FIND_DATA fd; - resourcePath += L"Fonts\\*"; - - HANDLE find = FindFirstFileEx( - resourcePath.c_str(), - (IsWindows7OrGreater()) ? FindExInfoBasic : FindExInfoStandard, - &fd, - FindExSearchNameMatch, - nullptr, - 0); - - if (find != INVALID_HANDLE_VALUE) - { - m_FontCollection = m_Canvas->CreateFontCollection(); - - do - { - if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - { - std::wstring file(resourcePath, 0, resourcePath.length() - 1); - file += fd.cFileName; - if (!m_FontCollection->AddFile(file.c_str())) - { - LogErrorF(this, L"Unable to load font: %s", file.c_str()); - } - } - } - while (FindNextFile(find, &fd)); - - FindClose(find); - } - } - - // Load local fonts - const WCHAR* localFont = m_Parser.ReadString(L"Rainmeter", L"LocalFont", L"").c_str(); - if (*localFont) - { - if (!m_FontCollection) - { - m_FontCollection = m_Canvas->CreateFontCollection(); - } - - int i = 1; - do - { - // Try program folder first - std::wstring szFontFile = Rainmeter::GetInstance().GetPath() + L"Fonts\\"; - szFontFile += localFont; - if (!m_FontCollection->AddFile(szFontFile.c_str())) - { - szFontFile = localFont; - MakePathAbsolute(szFontFile); - if (!m_FontCollection->AddFile(szFontFile.c_str())) - { - LogErrorF(this, L"Unable to load font: %s", localFont); - } - } - - // Check for LocalFont2, LocalFont3, etc. - _snwprintf_s(buffer, _TRUNCATE, L"LocalFont%i", ++i); - localFont = m_Parser.ReadString(L"Rainmeter", buffer, L"").c_str(); - } - while (*localFont); - } - - // Create all meters and measures. The meters and measures are not initialized in this loop - // to avoid errors caused by referencing nonexistent [sections] in the options. - m_HasNetMeasures = false; - m_HasButtons = false; - Meter* prevMeter = nullptr; - for (auto iter = m_Parser.GetSections().cbegin(); iter != m_Parser.GetSections().cend(); ++iter) - { - const WCHAR* section = (*iter).c_str(); - - if (_wcsicmp(L"Rainmeter", section) != 0 && - _wcsicmp(L"Variables", section) != 0 && - _wcsicmp(L"Metadata", section) != 0) - { - const std::wstring& measureName = m_Parser.ReadString(section, L"Measure", L"", false); - if (!measureName.empty()) - { - Measure* measure = Measure::Create(measureName.c_str(), this, section); - if (measure) - { - m_Measures.push_back(measure); - m_Parser.AddMeasure(measure); - - if (measure->GetTypeID() == TypeID()) - { - m_HasNetMeasures = true; - } - } - - continue; - } - - const std::wstring& meterName = m_Parser.ReadString(section, L"Meter", L"", false); - if (!meterName.empty()) - { - // It's a meter - Meter* meter = Meter::Create(meterName.c_str(), this, section); - if (meter) - { - m_Meters.push_back(meter); - meter->SetRelativeMeter(prevMeter); - - if (meter->GetTypeID() == TypeID()) - { - m_HasButtons = true; - } - - prevMeter = meter; - } - - continue; - } - } - } - - if (m_Meters.empty()) - { - std::wstring text = GetFormattedString(ID_STR_NOMETERSINSKIN, m_FolderPath.c_str(), m_FileName.c_str()); - Rainmeter::GetInstance().ShowMessage(m_Window, text.c_str(), MB_OK | MB_ICONEXCLAMATION); - return false; - } - - // Read measure options. This is done before the meters to ensure that e.g. Substitute is used - // when the meters get the value of the measure. The measures cannot be initialized yet as som - // measures (e.g. Script) except that the meters are ready when calling Initialize(). - for (auto iter = m_Measures.cbegin(); iter != m_Measures.cend(); ++iter) - { - Measure* measure = *iter; - measure->ReadOptions(m_Parser); - } - - // Initialize meters. - for (auto iter = m_Meters.cbegin(); iter != m_Meters.cend(); ++iter) - { - Meter* meter = *iter; - meter->ReadOptions(m_Parser); - meter->Initialize(); - - if (!meter->GetToolTipText().empty()) - { - meter->CreateToolTip(this); - } - } - - // Initialize measures. - for (auto iter = m_Measures.cbegin(); iter != m_Measures.cend(); ++iter) - { - Measure* measure = *iter; - measure->Initialize(); - } - - // Set window size (and CURRENTCONFIGWIDTH/HEIGHT) temporarily - for (auto iter = m_Meters.cbegin(); iter != m_Meters.cend(); ++iter) - { - bool bActiveTransition = true; // Do not track the change of ActiveTransition - UpdateMeter(*iter, bActiveTransition, true); - } - ResizeWindow(true); - - return true; -} - -/* -** Changes the size of the window and re-adjusts the background -*/ -bool MeterWindow::ResizeWindow(bool reset) -{ - int w = m_BackgroundMargins.left; - int h = m_BackgroundMargins.top; - - // Get the largest meter point - std::vector::const_iterator j = m_Meters.begin(); - for ( ; j != m_Meters.end(); ++j) - { - int mr = (*j)->GetX() + (*j)->GetW(); - w = max(w, mr); - int mb = (*j)->GetY() + (*j)->GetH(); - h = max(h, mb); - } - - w += m_BackgroundMargins.right; - h += m_BackgroundMargins.bottom; - - w = max(w, m_BackgroundSize.cx); - h = max(h, m_BackgroundSize.cy); - - if (!reset && m_WindowW == w && m_WindowH == h) - { - WindowToScreen(); - return false; // The window is already correct size - } - - // Reset size (this is calculated below) - - delete m_Background; - m_Background = nullptr; - - if ((m_BackgroundMode == BGMODE_IMAGE || m_BackgroundMode == BGMODE_SCALED_IMAGE || m_BackgroundMode == BGMODE_TILED_IMAGE) && !m_BackgroundName.empty()) - { - // Load the background - TintedImage* tintedBackground = new TintedImage(L"Background"); - tintedBackground->ReadOptions(m_Parser, L"Rainmeter"); - tintedBackground->LoadImage(m_BackgroundName, true); - - if (!tintedBackground->IsLoaded()) - { - m_BackgroundSize.cx = 0; - m_BackgroundSize.cy = 0; - - m_WindowW = 0; - m_WindowH = 0; - } - else - { - Bitmap* tempBackground = tintedBackground->GetImage(); - - // Calculate the window dimensions - m_BackgroundSize.cx = tempBackground->GetWidth(); - m_BackgroundSize.cy = tempBackground->GetHeight(); - - if (m_BackgroundMode == BGMODE_IMAGE) - { - w = m_BackgroundSize.cx; - h = m_BackgroundSize.cy; - } - else - { - w = max(w, m_BackgroundSize.cx); - h = max(h, m_BackgroundSize.cy); - } - - Bitmap* background = new Bitmap(w, h, PixelFormat32bppPARGB); - Graphics graphics(background); - - if (m_BackgroundMode == BGMODE_IMAGE) - { - Rect r(0, 0, w, h); - graphics.DrawImage(tempBackground, r, 0, 0, w, h, UnitPixel); - } - else - { - // Scale the background to fill the whole window - if (m_BackgroundMode == BGMODE_SCALED_IMAGE) - { - const RECT m = m_BackgroundMargins; - - if (m.top > 0) - { - if (m.left > 0) - { - // Top-Left - Rect r(0, 0, m.left, m.top); - graphics.DrawImage(tempBackground, r, 0, 0, m.left, m.top, UnitPixel); - } - - // Top - Rect r(m.left, 0, w - m.left - m.right, m.top); - graphics.DrawImage(tempBackground, r, m.left, 0, m_BackgroundSize.cx - m.left - m.right, m.top, UnitPixel); - - if (m.right > 0) - { - // Top-Right - Rect r(w - m.right, 0, m.right, m.top); - graphics.DrawImage(tempBackground, r, m_BackgroundSize.cx - m.right, 0, m.right, m.top, UnitPixel); - } - } - - if (m.left > 0) - { - // Left - Rect r(0, m.top, m.left, h - m.top - m.bottom); - graphics.DrawImage(tempBackground, r, 0, m.top, m.left, m_BackgroundSize.cy - m.top - m.bottom, UnitPixel); - } - - // Center - Rect r(m.left, m.top, w - m.left - m.right, h - m.top - m.bottom); - graphics.DrawImage(tempBackground, r, m.left, m.top, m_BackgroundSize.cx - m.left - m.right, m_BackgroundSize.cy - m.top - m.bottom, UnitPixel); - - if (m.right > 0) - { - // Right - Rect r(w - m.right, m.top, m.right, h - m.top - m.bottom); - graphics.DrawImage(tempBackground, r, m_BackgroundSize.cx - m.right, m.top, m.right, m_BackgroundSize.cy - m.top - m.bottom, UnitPixel); - } - - if (m.bottom > 0) - { - if (m.left > 0) - { - // Bottom-Left - Rect r(0, h - m.bottom, m.left, m.bottom); - graphics.DrawImage(tempBackground, r, 0, m_BackgroundSize.cy - m.bottom, m.left, m.bottom, UnitPixel); - } - - // Bottom - Rect r(m.left, h - m.bottom, w - m.left - m.right, m.bottom); - graphics.DrawImage(tempBackground, r, m.left, m_BackgroundSize.cy - m.bottom, m_BackgroundSize.cx - m.left - m.right, m.bottom, UnitPixel); - - if (m.right > 0) - { - // Bottom-Right - Rect r(w - m.right, h - m.bottom, m.right, m.bottom); - graphics.DrawImage(tempBackground, r, m_BackgroundSize.cx - m.right, m_BackgroundSize.cy - m.bottom, m.right, m.bottom, UnitPixel); - } - } - } - else - { - ImageAttributes imgAttr; - imgAttr.SetWrapMode(WrapModeTile); - - Rect r(0, 0, w, h); - graphics.DrawImage(tempBackground, r, 0, 0, w, h, UnitPixel, &imgAttr); - } - } - - m_Background = background; - - // Get the size form the background bitmap - m_WindowW = m_Background->GetWidth(); - m_WindowH = m_Background->GetHeight(); - - WindowToScreen(); - } - - delete tintedBackground; - } - else - { - m_WindowW = w; - m_WindowH = h; - WindowToScreen(); - } - - SetWindowSizeVariables(m_WindowW, m_WindowH); - - return true; -} - -/* -** Creates the back buffer bitmap. -** -*/ -void MeterWindow::CreateDoubleBuffer(int cx, int cy) -{ - m_Canvas->Resize(cx, cy); -} - -/* -** Redraws the meters and paints the window -** -*/ -void MeterWindow::Redraw() -{ - if (m_ResizeWindow) - { - ResizeWindow(m_ResizeWindow == RESIZEMODE_RESET); - SetResizeWindowMode(RESIZEMODE_NONE); - } - - // Create or clear the doublebuffer - { - int cx = m_WindowW; - int cy = m_WindowH; - - if (cx == 0 || cy == 0) - { - // Set dummy size to avoid invalid state - cx = 1; - cy = 1; - } - - if (cx != m_Canvas->GetW() || cy != m_Canvas->GetH()) - { - CreateDoubleBuffer(cx, cy); - } - } - - if (!m_Canvas->BeginDraw()) - { - return; - } - - m_Canvas->Clear(); - - if (m_WindowW != 0 && m_WindowH != 0) - { - if (m_Background) - { - const Rect dst(0, 0, m_WindowW, m_WindowH); - const Rect src(0, 0, m_Background->GetWidth(), m_Background->GetHeight()); - m_Canvas->DrawBitmap(m_Background, dst, src); - } - else if (m_BackgroundMode == BGMODE_SOLID) - { - // Draw the solid color background - Rect r(0, 0, m_WindowW, m_WindowH); - - if (m_SolidColor.GetA() != 0 || m_SolidColor2.GetA() != 0) - { - if (m_SolidColor.GetValue() == m_SolidColor2.GetValue()) - { - m_Canvas->Clear(m_SolidColor); - } - else - { - Gdiplus::Graphics& graphics = m_Canvas->BeginGdiplusContext(); - LinearGradientBrush gradient(r, m_SolidColor, m_SolidColor2, m_SolidAngle, TRUE); - graphics.FillRectangle(&gradient, r); - m_Canvas->EndGdiplusContext(); - } - } - - if (m_SolidBevel != BEVELTYPE_NONE) - { - Color lightColor(255, 255, 255, 255); - Color darkColor(255, 0, 0, 0); - - if (m_SolidBevel == BEVELTYPE_DOWN) - { - lightColor.SetValue(Color::MakeARGB(255, 0, 0, 0)); - darkColor.SetValue(Color::MakeARGB(255, 255, 255, 255)); - } - - Pen light(lightColor); - Pen dark(darkColor); - - Gdiplus::Graphics& graphics = m_Canvas->BeginGdiplusContext(); - Meter::DrawBevel(graphics, r, light, dark); - m_Canvas->EndGdiplusContext(); - } - } - - // Draw the meters - std::vector::const_iterator j = m_Meters.begin(); - for ( ; j != m_Meters.end(); ++j) - { - const Matrix* matrix = (*j)->GetTransformationMatrix(); - if (matrix && !matrix->IsIdentity()) - { - m_Canvas->SetTransform(*matrix); - (*j)->Draw(*m_Canvas); - m_Canvas->ResetTransform(); - } - else - { - (*j)->Draw(*m_Canvas); - } - } - } - - UpdateWindow(m_TransparencyValue, true); - - m_Canvas->EndDraw(); -} - -/* -** Updates the transition state -** -*/ -void MeterWindow::PostUpdate(bool bActiveTransition) -{ - // Start/stop the transition timer if necessary - if (bActiveTransition && !m_ActiveTransition) - { - SetTimer(m_Window, TIMER_TRANSITION, m_TransitionUpdate, nullptr); - m_ActiveTransition = true; - } - else if (m_ActiveTransition && !bActiveTransition) - { - KillTimer(m_Window, TIMER_TRANSITION); - m_ActiveTransition = false; - } -} - -/* -** Updates the given measure -** -*/ -bool MeterWindow::UpdateMeasure(Measure* measure, bool force) -{ - bool bUpdate = false; - - if (force) - { - measure->ResetUpdateCounter(); - } - - int updateDivider = measure->GetUpdateDivider(); - if (updateDivider >= 0 || force) - { - const bool rereadOptions = - measure->HasDynamicVariables() && (measure->GetUpdateCounter() + 1) >= updateDivider; - bUpdate = measure->Update(rereadOptions); - } - - return bUpdate; -} - -/* -** Updates the given meter -** -*/ -bool MeterWindow::UpdateMeter(Meter* meter, bool& bActiveTransition, bool force) -{ - bool bUpdate = false; - - if (force) - { - meter->ResetUpdateCounter(); - } - - int updateDivider = meter->GetUpdateDivider(); - if (updateDivider >= 0 || force) - { - if (meter->HasDynamicVariables() && - (meter->GetUpdateCounter() + 1) >= updateDivider) - { - meter->ReadOptions(m_Parser); - } - - bUpdate = meter->Update(); - } - - // Update tooltips - if (!meter->HasToolTip()) - { - if (!meter->GetToolTipText().empty()) - { - meter->CreateToolTip(this); - } - } - else - { - meter->UpdateToolTip(); - } - - // Check for transitions - if (!bActiveTransition && meter->HasActiveTransition()) - { - bActiveTransition = true; - } - - return bUpdate; -} - -/* -** Updates all the measures and redraws the meters -** -*/ -void MeterWindow::Update(bool refresh) -{ - ++m_UpdateCounter; - - if (!m_Measures.empty()) - { - // Pre-updates - if (m_HasNetMeasures) - { - MeasureNet::UpdateIFTable(); - MeasureNet::UpdateStats(); - } - - // Update all measures - std::vector::const_iterator i = m_Measures.begin(); - for ( ; i != m_Measures.end(); ++i) - { - if (UpdateMeasure((*i), refresh)) - { - (*i)->DoUpdateAction(); - (*i)->DoChangeAction(); - } - } - } - - DialogAbout::UpdateMeasures(this); - - // Update all meters - bool bActiveTransition = false; - bool bUpdate = false; - std::vector::const_iterator j = m_Meters.begin(); - for ( ; j != m_Meters.end(); ++j) - { - if (UpdateMeter((*j), bActiveTransition, refresh)) - { - bUpdate = true; - - (*j)->DoUpdateAction(); - } - } - - // Redraw all meters - if (bUpdate || m_ResizeWindow || refresh) - { - if (m_DynamicWindowSize) - { - // Resize the window - SetResizeWindowMode(RESIZEMODE_CHECK); - } - - // If our option is to disable when in an RDP session, then check if in an RDP session. - // Only redraw if we are not in a remote session - if (Rainmeter::GetInstance().IsRedrawable()) - { - Redraw(); - } - } - - // Post-updates - PostUpdate(bActiveTransition); - - if (!m_OnUpdateAction.empty()) - { - Rainmeter::GetInstance().ExecuteCommand(m_OnUpdateAction.c_str(), this); - } -} - -/* -** Updates the window contents -** -*/ -void MeterWindow::UpdateWindow(int alpha, bool canvasBeginDrawCalled) -{ - BLENDFUNCTION blendPixelFunction = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA}; - POINT ptWindowScreenPosition = {m_ScreenX, m_ScreenY}; - POINT ptSrc = {0, 0}; - SIZE szWindow = {m_Canvas->GetW(), m_Canvas->GetH()}; - - if (!canvasBeginDrawCalled) m_Canvas->BeginDraw(); - - HDC dcMemory = m_Canvas->GetDC(); - if (!UpdateLayeredWindow(m_Window, nullptr, &ptWindowScreenPosition, &szWindow, dcMemory, &ptSrc, 0, &blendPixelFunction, ULW_ALPHA)) - { - // Retry after resetting WS_EX_LAYERED flag. - RemoveWindowExStyle(WS_EX_LAYERED); - AddWindowExStyle(WS_EX_LAYERED); - UpdateLayeredWindow(m_Window, nullptr, &ptWindowScreenPosition, &szWindow, dcMemory, &ptSrc, 0, &blendPixelFunction, ULW_ALPHA); - } - m_Canvas->ReleaseDC(dcMemory); - - if (!canvasBeginDrawCalled) m_Canvas->EndDraw(); - - m_TransparencyValue = alpha; -} - -/* -** Updates the window transparency (using existing contents). -** -*/ -void MeterWindow::UpdateWindowTransparency(int alpha) -{ - BLENDFUNCTION blendPixelFunction = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA}; - UpdateLayeredWindow(m_Window, nullptr, nullptr, nullptr, nullptr, nullptr, 0, &blendPixelFunction, ULW_ALPHA); - m_TransparencyValue = alpha; -} - -/* -** Handles the timers. The METERTIMER updates all the measures -** MOUSETIMER is used to hide/show the window. -** -*/ -LRESULT MeterWindow::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (wParam) - { - case TIMER_METER: - Update(false); - break; - - case TIMER_MOUSE: - if (!Rainmeter::GetInstance().IsMenuActive() && !m_Dragging) - { - ShowWindowIfAppropriate(); - - if (m_WindowZPosition == ZPOSITION_ONTOPMOST) - { - ChangeZPos(ZPOSITION_ONTOPMOST); - } - - if (m_MouseOver) - { - POINT pos = System::GetCursorPosition(); - - if (!m_ClickThrough) - { - if (WindowFromPoint(pos) == m_Window) - { - SetMouseLeaveEvent(false); - } - else - { - // Run all mouse leave actions - OnMouseLeave(m_WindowDraggable ? WM_NCMOUSELEAVE : WM_MOUSELEAVE, 0, 0); - } - } - else - { - bool keyDown = IsCtrlKeyDown() || IsShiftKeyDown() || IsAltKeyDown(); - - if (!keyDown || GetWindowFromPoint(pos) != m_Window) - { - // Run all mouse leave actions - OnMouseLeave(m_WindowDraggable ? WM_NCMOUSELEAVE : WM_MOUSELEAVE, 0, 0); - } - } - } - } - break; - - case TIMER_TRANSITION: - { - // Redraw only if there is active transition still going - bool bActiveTransition = false; - std::vector::const_iterator j = m_Meters.begin(); - for ( ; j != m_Meters.end(); ++j) - { - if ((*j)->HasActiveTransition()) - { - bActiveTransition = true; - break; - } - } - - if (bActiveTransition) - { - Redraw(); - } - else - { - // Stop the transition timer - KillTimer(m_Window, TIMER_TRANSITION); - m_ActiveTransition = false; - } - } - break; - - case TIMER_FADE: - { - ULONGLONG ticks = System::GetTickCount64(); - if (m_FadeStartTime == 0) - { - m_FadeStartTime = ticks; - } - - if (ticks - m_FadeStartTime > (ULONGLONG)m_FadeDuration) - { - KillTimer(m_Window, TIMER_FADE); - m_FadeStartTime = 0; - if (m_FadeEndValue == 0) - { - ShowWindow(m_Window, SW_HIDE); - } - else - { - UpdateWindowTransparency(m_FadeEndValue); - } - } - else - { - double value = (double)(__int64)(ticks - m_FadeStartTime); - value /= m_FadeDuration; - value *= m_FadeEndValue - m_FadeStartValue; - value += m_FadeStartValue; - value = min(value, 255); - value = max(value, 0); - - UpdateWindowTransparency((int)value); - } - } - break; - - case TIMER_DEACTIVATE: - if (m_FadeStartTime == 0) - { - KillTimer(m_Window, TIMER_DEACTIVATE); - Rainmeter::GetInstance().RemoveUnmanagedMeterWindow(this); - delete this; - } - break; - } - - return 0; -} - -void MeterWindow::FadeWindow(int from, int to) -{ - if (m_FadeDuration == 0) - { - if (to == 0) - { - ShowWindow(m_Window, SW_HIDE); - } - else - { - if (m_FadeDuration == 0) - { - UpdateWindowTransparency(to); - } - if (from == 0) - { - if (!m_Hidden) - { - ShowWindow(m_Window, SW_SHOWNOACTIVATE); - } - } - } - } - else - { - m_FadeStartValue = from; - m_FadeEndValue = to; - UpdateWindowTransparency(from); - if (from == 0) - { - if (!m_Hidden) - { - ShowWindow(m_Window, SW_SHOWNOACTIVATE); - } - } - - SetTimer(m_Window, TIMER_FADE, INTERVAL_FADE, nullptr); - } -} - -void MeterWindow::HideFade() -{ - m_Hidden = true; - if (IsWindowVisible(m_Window)) - { - FadeWindow(m_AlphaValue, 0); - } -} - -void MeterWindow::ShowFade() -{ - m_Hidden = false; - if (!IsWindowVisible(m_Window)) - { - FadeWindow(0, (m_WindowHide == HIDEMODE_FADEOUT) ? 255 : m_AlphaValue); - } -} - -/* -** Show the window if it is temporarily hidden. -** -*/ -void MeterWindow::ShowWindowIfAppropriate() -{ - bool keyDown = IsCtrlKeyDown() || IsShiftKeyDown() || IsAltKeyDown(); - - POINT pos = System::GetCursorPosition(); - POINT posScr = pos; - - MapWindowPoints(nullptr, m_Window, &pos, 1); - bool inside = HitTest(pos.x, pos.y); - - if (inside) - { - inside = (GetWindowFromPoint(posScr) == m_Window); - } - - if (m_ClickThrough) - { - if (!inside || keyDown) - { - // If Alt, shift or control is down, remove the transparent flag - RemoveWindowExStyle(WS_EX_TRANSPARENT); - } - } - - if (m_WindowHide) - { - if (!m_Hidden && !inside && !keyDown) - { - switch (m_WindowHide) - { - case HIDEMODE_HIDE: - if (m_TransparencyValue == 0 || !IsWindowVisible(m_Window)) - { - ShowWindow(m_Window, SW_SHOWNOACTIVATE); - FadeWindow(0, m_AlphaValue); - } - break; - - case HIDEMODE_FADEIN: - if (m_AlphaValue != 255 && m_TransparencyValue == 255) - { - FadeWindow(255, m_AlphaValue); - } - break; - - case HIDEMODE_FADEOUT: - if (m_AlphaValue != 255 && m_TransparencyValue == m_AlphaValue) - { - FadeWindow(m_AlphaValue, 255); - } - break; - } - } - } - else - { - if (!m_Hidden) - { - if (m_TransparencyValue == 0 || !IsWindowVisible(m_Window)) - { - ShowWindow(m_Window, SW_SHOWNOACTIVATE); - FadeWindow(0, m_AlphaValue); - } - } - } -} - -/* -** Retrieves a handle to the window that contains the specified point. -** -*/ -HWND MeterWindow::GetWindowFromPoint(POINT pos) -{ - HWND hwndPos = WindowFromPoint(pos); - - if (hwndPos == m_Window || (!m_ClickThrough && m_WindowHide != HIDEMODE_HIDE)) - { - return hwndPos; - } - - MapWindowPoints(nullptr, m_Window, &pos, 1); - - if (HitTest(pos.x, pos.y)) - { - if (hwndPos) - { - HWND hWnd = GetAncestor(hwndPos, GA_ROOT); - while (hWnd = FindWindowEx(nullptr, hWnd, METERWINDOW_CLASS_NAME, nullptr)) - { - if (hWnd == m_Window) - { - return hwndPos; - } - } - } - return m_Window; - } - - return hwndPos; -} - -/* -** Checks if the given point is inside the window. -** -*/ -bool MeterWindow::HitTest(int x, int y) -{ - return m_Canvas->IsTransparentPixel(x, y); -} - -/* -** Handles all buttons and cursor. -** -*/ -void MeterWindow::HandleButtons(POINT pos, BUTTONPROC proc, bool execute) -{ - bool redraw = false; - HCURSOR cursor = nullptr; - - std::vector::const_reverse_iterator j = m_Meters.rbegin(); - for ( ; j != m_Meters.rend(); ++j) - { - // Hidden meters are ignored - if ((*j)->IsHidden()) continue; - - MeterButton* button = nullptr; - if (m_HasButtons && (*j)->GetTypeID() == TypeID()) - { - button = (MeterButton*)(*j); - if (button) - { - switch (proc) - { - case BUTTONPROC_DOWN: - redraw |= button->MouseDown(pos); - break; - - case BUTTONPROC_UP: - redraw |= button->MouseUp(pos, execute); - break; - - case BUTTONPROC_MOVE: - default: - redraw |= button->MouseMove(pos); - break; - } - } - } - - // Get cursor if required - if (!cursor && (*j)->GetMouse().GetCursorState()) - { - if ((*j)->HasMouseAction()) - { - if ((*j)->HitTest(pos.x, pos.y)) - { - cursor = (*j)->GetMouse().GetCursor(); - } - } - else - { - // Special case for Button meter: reacts only on valid pixel in button image - if (button && button->HitTest2(pos.x, pos.y)) - { - cursor = (*j)->GetMouse().GetCursor(); - } - } - } - } - - if (redraw) - { - Redraw(); - } - - if (!cursor) - { - cursor = LoadCursor(nullptr, IDC_ARROW); - } - - SetCursor(cursor); -} - -/* -** During setting the cursor do nothing. -** -*/ -LRESULT MeterWindow::OnSetCursor(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - return 0; -} - -/* -** Enters context menu loop. -** -*/ -LRESULT MeterWindow::OnEnterMenuLoop(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - // Set cursor to default - SetCursor(LoadCursor(nullptr, IDC_ARROW)); - - return 0; -} - -/* -** When we get WM_MOUSEMOVE messages, hide the window as the mouse is over it. -** -*/ -LRESULT MeterWindow::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - bool keyDown = IsCtrlKeyDown() || IsShiftKeyDown() || IsAltKeyDown(); - - if (!keyDown) - { - if (m_ClickThrough) - { - AddWindowExStyle(WS_EX_TRANSPARENT); - } - - if (!m_Hidden) - { - // If Alt, shift or control is down, do not hide the window - switch (m_WindowHide) - { - case HIDEMODE_HIDE: - if (m_TransparencyValue == m_AlphaValue) - { - FadeWindow(m_AlphaValue, 0); - } - break; - - case HIDEMODE_FADEIN: - if (m_AlphaValue != 255 && m_TransparencyValue == m_AlphaValue) - { - FadeWindow(m_AlphaValue, 255); - } - break; - - case HIDEMODE_FADEOUT: - if (m_AlphaValue != 255 && m_TransparencyValue == 255) - { - FadeWindow(255, m_AlphaValue); - } - break; - } - } - } - - if (!m_ClickThrough || keyDown) - { - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - if (uMsg == WM_NCMOUSEMOVE) - { - // Map to local window - MapWindowPoints(nullptr, m_Window, &pos, 1); - } - - ++m_MouseMoveCounter; - - while (DoMoveAction(pos.x, pos.y, MOUSE_LEAVE)) ; - while (DoMoveAction(pos.x, pos.y, MOUSE_OVER)) ; - - // Handle buttons - HandleButtons(pos, BUTTONPROC_MOVE); - } - - return 0; -} - -/* -** When we get WM_MOUSELEAVE messages, run all leave actions. -** -*/ -LRESULT MeterWindow::OnMouseLeave(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pos = System::GetCursorPosition(); - HWND hWnd = WindowFromPoint(pos); - if (!hWnd || (hWnd != m_Window && GetParent(hWnd) != m_Window)) // ignore tooltips - { - ++m_MouseMoveCounter; - - POINT pos = {SHRT_MIN, SHRT_MIN}; - while (DoMoveAction(pos.x, pos.y, MOUSE_LEAVE)) ; // Leave all forcibly - - // Handle buttons - HandleButtons(pos, BUTTONPROC_MOVE); - } - - return 0; -} - -/* -** When we get WM_MOUSEWHEEL messages. -** -*/ -LRESULT MeterWindow::OnMouseScrollMove(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (uMsg == WM_MOUSEWHEEL) // If sent through WM_INPUT, uMsg is WM_INPUT. - { - // Fix for Notepad++, which sends WM_MOUSEWHEEL to unfocused windows. - if (m_Window != GetFocus()) - { - return 0; - } - } - - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - MapWindowPoints(nullptr, m_Window, &pos, 1); - - // Handle buttons - HandleButtons(pos, BUTTONPROC_MOVE); - - const int delta = GET_WHEEL_DELTA_WPARAM(wParam); - DoAction(pos.x, pos.y, (delta < 0) ? MOUSE_MW_DOWN : MOUSE_MW_UP, false); - - return 0; -} - -/* -** When we get WM_MOUSEHWHEEL messages. -** -*/ -LRESULT MeterWindow::OnMouseHScrollMove(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - MapWindowPoints(nullptr, m_Window, &pos, 1); - - // Handle buttons - HandleButtons(pos, BUTTONPROC_MOVE); - - const int delta = GET_WHEEL_DELTA_WPARAM(wParam); - DoAction(pos.x, pos.y, (delta < 0) ? MOUSE_MW_LEFT : MOUSE_MW_RIGHT, false); - - return 0; -} - -/* -** Handle the menu commands. -** -*/ -LRESULT MeterWindow::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (wParam) - { - case IDM_SKIN_EDITSKIN: - Rainmeter::GetInstance().EditSkinFile(m_FolderPath, m_FileName); - break; - - case IDM_SKIN_REFRESH: - Refresh(false); - break; - - case IDM_SKIN_OPENSKINSFOLDER: - Rainmeter::GetInstance().OpenSkinFolder(m_FolderPath); - break; - - case IDM_SKIN_MANAGESKIN: - DialogManage::OpenSkin(this); - break; - - case IDM_SKIN_VERYTOPMOST: - SetWindowZPosition(ZPOSITION_ONTOPMOST); - break; - - case IDM_SKIN_TOPMOST: - SetWindowZPosition(ZPOSITION_ONTOP); - break; - - case IDM_SKIN_BOTTOM: - SetWindowZPosition(ZPOSITION_ONBOTTOM); - break; - - case IDM_SKIN_NORMAL: - SetWindowZPosition(ZPOSITION_NORMAL); - break; - - case IDM_SKIN_ONDESKTOP: - SetWindowZPosition(ZPOSITION_ONDESKTOP); - break; - - case IDM_SKIN_KEEPONSCREEN: - SetKeepOnScreen(!m_KeepOnScreen); - break; - - case IDM_SKIN_USED2D: - SetUseD2D(!m_UseD2D); - break; - - case IDM_SKIN_CLICKTHROUGH: - SetClickThrough(!m_ClickThrough); - break; - - case IDM_SKIN_DRAGGABLE: - SetWindowDraggable(!m_WindowDraggable); - break; - - case IDM_SKIN_HIDEONMOUSE: - SetWindowHide((m_WindowHide == HIDEMODE_NONE) ? HIDEMODE_HIDE : HIDEMODE_NONE); - break; - - case IDM_SKIN_TRANSPARENCY_FADEIN: - SetWindowHide((m_WindowHide == HIDEMODE_NONE) ? HIDEMODE_FADEIN : HIDEMODE_NONE); - break; - - case IDM_SKIN_TRANSPARENCY_FADEOUT: - SetWindowHide((m_WindowHide == HIDEMODE_NONE) ? HIDEMODE_FADEOUT : HIDEMODE_NONE); - break; - - case IDM_SKIN_REMEMBERPOSITION: - SetSavePosition(!m_SavePosition); - break; - - case IDM_SKIN_SNAPTOEDGES: - SetSnapEdges(!m_SnapEdges); - break; - - case IDM_CLOSESKIN: - if (m_State != STATE_CLOSING) - { - Rainmeter::GetInstance().DeactivateSkin(this, -1); - } - break; - - case IDM_SKIN_FROMRIGHT: - m_WindowXFromRight = !m_WindowXFromRight; - - SavePositionIfAppropriate(); - break; - - case IDM_SKIN_FROMBOTTOM: - m_WindowYFromBottom = !m_WindowYFromBottom; - - SavePositionIfAppropriate(); - break; - - case IDM_SKIN_XPERCENTAGE: - m_WindowXPercentage = !m_WindowXPercentage; - - SavePositionIfAppropriate(); - break; - - case IDM_SKIN_YPERCENTAGE: - m_WindowYPercentage = !m_WindowYPercentage; - - SavePositionIfAppropriate(); - break; - - case IDM_SKIN_MONITOR_AUTOSELECT: - m_AutoSelectScreen = !m_AutoSelectScreen; - - WriteOptions(OPTION_POSITION | OPTION_AUTOSELECTSCREEN); - break; - - default: - if (wParam >= IDM_SKIN_TRANSPARENCY_0 && wParam <= IDM_SKIN_TRANSPARENCY_90) - { - m_AlphaValue = (int)(255.0 - (wParam - IDM_SKIN_TRANSPARENCY_0) * (230.0 / (IDM_SKIN_TRANSPARENCY_90 - IDM_SKIN_TRANSPARENCY_0))); - UpdateWindowTransparency(m_AlphaValue); - WriteOptions(OPTION_ALPHAVALUE); - } - else if (wParam == IDM_SKIN_MONITOR_PRIMARY || wParam >= ID_MONITOR_FIRST && wParam <= ID_MONITOR_LAST) - { - const int numOfMonitors = (int)System::GetMonitorCount(); - const MultiMonitorInfo& monitorsInfo = System::GetMultiMonitorInfo(); - const std::vector& monitors = monitorsInfo.monitors; - - int screenIndex; - bool screenDefined; - if (wParam == IDM_SKIN_MONITOR_PRIMARY) - { - screenIndex = monitorsInfo.primary; - screenDefined = false; - } - else - { - screenIndex = (wParam & 0x0ffff) - ID_MONITOR_FIRST; - screenDefined = true; - } - - if (screenIndex >= 0 && (screenIndex == 0 || screenIndex <= numOfMonitors && monitors[screenIndex - 1].active)) - { - m_AutoSelectScreen = false; - - m_WindowXScreen = m_WindowYScreen = screenIndex; - m_WindowXScreenDefined = m_WindowYScreenDefined = screenDefined; - - m_Parser.ResetMonitorVariables(this); // Set present monitor variables - WriteOptions(OPTION_POSITION | OPTION_AUTOSELECTSCREEN); - } - } - else if (wParam >= IDM_SKIN_CUSTOMCONTEXTMENU_FIRST && wParam <= IDM_SKIN_CUSTOMCONTEXTMENU_LAST) - { - std::wstring action; - - int position = (int)wParam - IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + 1; - if (position == 1) - { - action = m_Parser.ReadString(L"Rainmeter", L"ContextAction", L"", false); - } - else - { - WCHAR buffer[128]; - - _snwprintf_s(buffer, _TRUNCATE, L"ContextAction%i", position); - action = m_Parser.ReadString(L"Rainmeter", buffer, L"", false); - } - - if (!action.empty()) - { - Rainmeter::GetInstance().ExecuteCommand(action.c_str(), this); - } - } - else - { - // Forward to tray window, which handles all the other commands - HWND tray = Rainmeter::GetInstance().GetTrayWindow()->GetWindow(); - - if (wParam == IDM_QUIT) - { - PostMessage(tray, WM_COMMAND, wParam, lParam); - } - else - { - SendMessage(tray, WM_COMMAND, wParam, lParam); - } - } - break; - } - - return 0; -} - -/* -** Helper function for setting ClickThrough -** -*/ -void MeterWindow::SetClickThrough(bool b) -{ - m_ClickThrough = b; - WriteOptions(OPTION_CLICKTHROUGH); - - if (!m_ClickThrough) - { - // Remove transparent flag - RemoveWindowExStyle(WS_EX_TRANSPARENT); - } - - if (m_MouseOver) - { - SetMouseLeaveEvent(m_ClickThrough); - } -} - -/* -** Helper function for setting KeepOnScreen -** -*/ -void MeterWindow::SetKeepOnScreen(bool b) -{ - m_KeepOnScreen = b; - WriteOptions(OPTION_KEEPONSCREEN); - - if (m_KeepOnScreen) - { - int x = m_ScreenX; - int y = m_ScreenY; - - MapCoordsToScreen(x, y, m_WindowW, m_WindowH); - - if (x != m_ScreenX || y != m_ScreenY) - { - MoveWindow(x, y); - } - } -} - -/* -** Helper function for setting UseD2D -** -*/ -void MeterWindow::SetUseD2D(bool b) -{ - m_UseD2D = b; - WriteOptions(OPTION_USED2D); - Refresh(false); -} - -/* -** Helper function for setting WindowDraggable -** -*/ -void MeterWindow::SetWindowDraggable(bool b) -{ - m_WindowDraggable = b; - WriteOptions(OPTION_DRAGGABLE); -} - -/* -** Helper function for setting SavePosition -** -*/ -void MeterWindow::SetSavePosition(bool b) -{ - m_SavePosition = b; - WriteOptions(OPTION_POSITION | OPTION_SAVEPOSITION); -} - -/* -** Helper function for setting SavePosition -** -*/ -void MeterWindow::SavePositionIfAppropriate() -{ - if (m_SavePosition) - { - WriteOptions(OPTION_POSITION); - } - else - { - ScreenToWindow(); - DialogManage::UpdateSkins(this); - } -} - -/* -** Helper function for setting SnapEdges -** -*/ -void MeterWindow::SetSnapEdges(bool b) -{ - m_SnapEdges = b; - WriteOptions(OPTION_SNAPEDGES); -} - -/* -** Helper function for setting WindowHide -** -*/ -void MeterWindow::SetWindowHide(HIDEMODE hide) -{ - m_WindowHide = hide; - UpdateWindowTransparency(m_AlphaValue); - WriteOptions(OPTION_HIDEONMOUSEOVER); -} - -/* -** Helper function for setting Position -** -*/ -void MeterWindow::SetWindowZPosition(ZPOSITION zpos) -{ - ChangeSingleZPos(zpos); - WriteOptions(OPTION_ALWAYSONTOP); -} - -/* -** Handle dragging the window -** -*/ -LRESULT MeterWindow::OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if ((wParam & 0xFFF0) != SC_MOVE) - { - return DefWindowProc(m_Window, uMsg, wParam, lParam); - } - - // --- SC_MOVE --- - - // Prepare the dragging flags - m_Dragging = true; - m_Dragged = false; - - // Run the DefWindowProc so the dragging works - LRESULT result = DefWindowProc(m_Window, uMsg, wParam, lParam); - - if (m_Dragged) - { - SavePositionIfAppropriate(); - - POINT pos = System::GetCursorPosition(); - MapWindowPoints(nullptr, m_Window, &pos, 1); - - // Handle buttons - HandleButtons(pos, BUTTONPROC_UP, false); // redraw only - } - else // not dragged - { - if ((wParam & 0x000F) == 2) // triggered by mouse - { - // Post the WM_NCLBUTTONUP message so the LeftMouseUpAction works - PostMessage(m_Window, WM_NCLBUTTONUP, (WPARAM)HTCAPTION, lParam); - } - } - - // Clear the dragging flags - m_Dragging = false; - m_Dragged = false; - - return result; -} - -/* -** Starts dragging -** -*/ -LRESULT MeterWindow::OnEnterSizeMove(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (m_Dragging) - { - m_Dragged = true; // Don't post the WM_NCLBUTTONUP message! - - // Set cursor to default - SetCursor(LoadCursor(nullptr, IDC_ARROW)); - } - - return 0; -} - -/* -** Ends dragging -** -*/ -LRESULT MeterWindow::OnExitSizeMove(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - return 0; -} - -/* -** This is overwritten so that the window can be dragged -** -*/ -LRESULT MeterWindow::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (m_WindowDraggable && !Rainmeter::GetInstance().GetDisableDragging()) - { - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - MapWindowPoints(nullptr, m_Window, &pos, 1); - - int x1 = m_DragMargins.left; - if (x1 < 0) x1 += m_WindowW; - - int x2 = m_WindowW - m_DragMargins.right; - if (x2 > m_WindowW) x2 -= m_WindowW; - - if (pos.x >= x1 && pos.x < x2) - { - int y1 = m_DragMargins.top; - if (y1 < 0) y1 += m_WindowH; - - int y2 = m_WindowH - m_DragMargins.bottom; - if (y2 > m_WindowH) y2 -= m_WindowH; - - if (pos.y >= y1 && pos.y < y2) - { - return HTCAPTION; - } - } - } - return HTCLIENT; -} - -/* -** Called when windows position is about to change -** -*/ -LRESULT MeterWindow::OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - LPWINDOWPOS wp = (LPWINDOWPOS)lParam; - - if (m_State != STATE_REFRESHING) - { - if (m_WindowZPosition == ZPOSITION_NORMAL && Rainmeter::GetInstance().IsNormalStayDesktop() && System::GetShowDesktop()) - { - if (!(wp->flags & (SWP_NOOWNERZORDER | SWP_NOACTIVATE))) - { - // Set window on top of all other ZPOSITION_ONDESKTOP, ZPOSITION_BOTTOM, and ZPOSITION_NORMAL windows - wp->hwndInsertAfter = System::GetBackmostTopWindow(); - } - } - else if (m_WindowZPosition == ZPOSITION_ONDESKTOP || m_WindowZPosition == ZPOSITION_ONBOTTOM) - { - // Do not change the z-order. This keeps the window on bottom. - wp->flags |= SWP_NOZORDER; - } - } - - if ((wp->flags & SWP_NOMOVE) == 0) - { - if (m_SnapEdges && !(IsCtrlKeyDown() || IsShiftKeyDown())) - { - // only process movement (ignore anything without winpos values) - if (wp->cx != 0 && wp->cy != 0) - { - // Search display monitor that has the largest area of intersection with the window - const size_t numOfMonitors = System::GetMonitorCount(); // intentional - const std::vector& monitors = System::GetMultiMonitorInfo().monitors; - - const RECT windowRect = {wp->x, wp->y, wp->x + (m_WindowW ? m_WindowW : 1), wp->y + (m_WindowH ? m_WindowH : 1)}; - const RECT* workArea = nullptr; - - size_t maxSize = 0; - for (auto iter = monitors.cbegin(); iter != monitors.cend(); ++iter) - { - RECT r; - if ((*iter).active && IntersectRect(&r, &windowRect, &(*iter).screen)) - { - size_t size = (r.right - r.left) * (r.bottom - r.top); - if (size > maxSize) - { - workArea = &(*iter).work; - maxSize = size; - } - } - } - - // Snap to other windows - for (auto iter = Rainmeter::GetInstance().GetAllMeterWindows().cbegin(); iter != Rainmeter::GetInstance().GetAllMeterWindows().cend(); ++iter) - { - if ((*iter).second != this) - { - SnapToWindow((*iter).second, wp); - } - } - - // Snap to work area if window is on the appropriate screen - if (workArea) - { - int w = workArea->right - m_WindowW; - int h = workArea->bottom - m_WindowH; - - if ((wp->x < SNAPDISTANCE + workArea->left) && (wp->x > workArea->left - SNAPDISTANCE)) wp->x = workArea->left; - if ((wp->y < SNAPDISTANCE + workArea->top) && (wp->y > workArea->top - SNAPDISTANCE)) wp->y = workArea->top; - if ((wp->x < SNAPDISTANCE + w) && (wp->x > -SNAPDISTANCE + w)) wp->x = w; - if ((wp->y < SNAPDISTANCE + h) && (wp->y > -SNAPDISTANCE + h)) wp->y = h; - } - } - } - - if (m_KeepOnScreen) - { - MapCoordsToScreen(wp->x, wp->y, m_WindowW, m_WindowH); - } - } - - return 0; -} - -void MeterWindow::SnapToWindow(MeterWindow* window, LPWINDOWPOS wp) -{ - int x = window->m_ScreenX; - int y = window->m_ScreenY; - int w = window->m_WindowW; - int h = window->m_WindowH; - - if (wp->y < y + h && wp->y + m_WindowH > y) - { - if ((wp->x < SNAPDISTANCE + x) && (wp->x > x - SNAPDISTANCE)) wp->x = x; - if ((wp->x < SNAPDISTANCE + x + w) && (wp->x > x + w - SNAPDISTANCE)) wp->x = x + w; - - if ((wp->x + m_WindowW < SNAPDISTANCE + x) && (wp->x + m_WindowW > x - SNAPDISTANCE)) wp->x = x - m_WindowW; - if ((wp->x + m_WindowW < SNAPDISTANCE + x + w) && (wp->x + m_WindowW > x + w - SNAPDISTANCE)) wp->x = x + w - m_WindowW; - } - - if (wp->x < x + w && wp->x + m_WindowW > x) - { - if ((wp->y < SNAPDISTANCE + y) && (wp->y > y - SNAPDISTANCE)) wp->y = y; - if ((wp->y < SNAPDISTANCE + y + h) && (wp->y > y + h - SNAPDISTANCE)) wp->y = y + h; - - if ((wp->y + m_WindowH < SNAPDISTANCE + y) && (wp->y + m_WindowH > y - SNAPDISTANCE)) wp->y = y - m_WindowH; - if ((wp->y + m_WindowH < SNAPDISTANCE + y + h) && (wp->y + m_WindowH > y + h - SNAPDISTANCE)) wp->y = y + h - m_WindowH; - } -} - -/* -** Disables blur when Aero transparency is disabled -** -*/ -LRESULT MeterWindow::OnDwmColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (m_BlurMode != BLURMODE_NONE && IsBlur() && c_DwmGetColorizationColor && c_DwmEnableBlurBehindWindow) - { - DWORD color; - BOOL opaque; - if (c_DwmGetColorizationColor(&color, &opaque) != S_OK) - { - opaque = TRUE; - } - - BlurBehindWindow(!opaque); - } - - return 0; -} - -/* -** Disables blur when desktop composition is disabled -** -*/ -LRESULT MeterWindow::OnDwmCompositionChange(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (m_BlurMode != BLURMODE_NONE && IsBlur() && c_DwmIsCompositionEnabled && c_DwmEnableBlurBehindWindow) - { - BOOL enabled; - if (c_DwmIsCompositionEnabled(&enabled) != S_OK) - { - enabled = FALSE; - } - - BlurBehindWindow(enabled); - } - - return 0; -} - -/* -** Adds the blur region to the window -** -*/ -void MeterWindow::BlurBehindWindow(BOOL fEnable) -{ - if (c_DwmEnableBlurBehindWindow) - { - DWM_BLURBEHIND bb = {0}; - bb.fEnable = fEnable; - - if (fEnable) - { - // Restore blur with whatever the region was prior to disabling - bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; - bb.hRgnBlur = m_BlurRegion; - c_DwmEnableBlurBehindWindow(m_Window, &bb); - } - else - { - // Disable blur - bb.dwFlags = DWM_BB_ENABLE; - c_DwmEnableBlurBehindWindow(m_Window, &bb); - } - } -} - -/* -** During resolution changes do nothing. -** (OnDelayedMove function is used instead.) -** -*/ -LRESULT MeterWindow::OnDisplayChange(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - return 0; -} - -/* -** During setting changes do nothing. -** (OnDelayedMove function is used instead.) -** -*/ -LRESULT MeterWindow::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - return 0; -} - -/* -** Runs the action when left mouse button is down -** -*/ -LRESULT MeterWindow::OnLeftButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - if (uMsg == WM_NCLBUTTONDOWN) - { - // Transform the point to client rect - MapWindowPoints(nullptr, m_Window, &pos, 1); - } - - // Handle buttons - HandleButtons(pos, BUTTONPROC_DOWN); - - if (IsCtrlKeyDown() || // Ctrl is pressed, so only run default action - (!DoAction(pos.x, pos.y, MOUSE_LMB_DOWN, false) && m_WindowDraggable)) - { - // Cancel the mouse event beforehand - SetMouseLeaveEvent(true); - - // Run the DefWindowProc so the dragging works - return DefWindowProc(m_Window, uMsg, wParam, lParam); - } - - return 0; -} - -/* -** Runs the action when left mouse button is up -** -*/ -LRESULT MeterWindow::OnLeftButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - if (uMsg == WM_NCLBUTTONUP) - { - // Transform the point to client rect - MapWindowPoints(nullptr, m_Window, &pos, 1); - } - - // Handle buttons - HandleButtons(pos, BUTTONPROC_UP); - - DoAction(pos.x, pos.y, MOUSE_LMB_UP, false); - - return 0; -} - -/* -** Runs the action when left mouse button is double-clicked -** -*/ -LRESULT MeterWindow::OnLeftButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - if (uMsg == WM_NCLBUTTONDBLCLK) - { - // Transform the point to client rect - MapWindowPoints(nullptr, m_Window, &pos, 1); - } - - // Handle buttons - HandleButtons(pos, BUTTONPROC_DOWN); - - if (!DoAction(pos.x, pos.y, MOUSE_LMB_DBLCLK, false)) - { - DoAction(pos.x, pos.y, MOUSE_LMB_DOWN, false); - } - - return 0; -} - -/* -** Runs the action when right mouse button is down -** -*/ -LRESULT MeterWindow::OnRightButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - if (uMsg == WM_NCRBUTTONDOWN) - { - // Transform the point to client rect - MapWindowPoints(nullptr, m_Window, &pos, 1); - } - - // Handle buttons - HandleButtons(pos, BUTTONPROC_MOVE); - - DoAction(pos.x, pos.y, MOUSE_RMB_DOWN, false); - - return 0; -} - -/* -** Runs the action when right mouse button is up -** -*/ -LRESULT MeterWindow::OnRightButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - // Handle buttons - HandleButtons(pos, BUTTONPROC_MOVE); - - if (IsCtrlKeyDown() || // Ctrl is pressed, so only run default action - !DoAction(pos.x, pos.y, MOUSE_RMB_UP, false)) - { - // Run the DefWindowProc so the context menu works - return DefWindowProc(m_Window, WM_RBUTTONUP, wParam, lParam); - } - - return 0; -} - -/* -** Runs the action when right mouse button is double-clicked -** -*/ -LRESULT MeterWindow::OnRightButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - if (uMsg == WM_NCRBUTTONDBLCLK) - { - // Transform the point to client rect - MapWindowPoints(nullptr, m_Window, &pos, 1); - } - - // Handle buttons - HandleButtons(pos, BUTTONPROC_MOVE); - - if (!DoAction(pos.x, pos.y, MOUSE_RMB_DBLCLK, false)) - { - DoAction(pos.x, pos.y, MOUSE_RMB_DOWN, false); - } - - return 0; -} - -/* -** Runs the action when middle mouse button is down -** -*/ -LRESULT MeterWindow::OnMiddleButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - if (uMsg == WM_NCMBUTTONDOWN) - { - // Transform the point to client rect - MapWindowPoints(nullptr, m_Window, &pos, 1); - } - - // Handle buttons - HandleButtons(pos, BUTTONPROC_MOVE); - - DoAction(pos.x, pos.y, MOUSE_MMB_DOWN, false); - - return 0; -} - -/* -** Runs the action when middle mouse button is up -** -*/ -LRESULT MeterWindow::OnMiddleButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - if (uMsg == WM_NCMBUTTONUP) - { - // Transform the point to client rect - MapWindowPoints(nullptr, m_Window, &pos, 1); - } - - // Handle buttons - HandleButtons(pos, BUTTONPROC_MOVE); - - DoAction(pos.x, pos.y, MOUSE_MMB_UP, false); - - return 0; -} - -/* -** Runs the action when middle mouse button is double-clicked -** -*/ -LRESULT MeterWindow::OnMiddleButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - if (uMsg == WM_NCMBUTTONDBLCLK) - { - // Transform the point to client rect - MapWindowPoints(nullptr, m_Window, &pos, 1); - } - - // Handle buttons - HandleButtons(pos, BUTTONPROC_MOVE); - - if (!DoAction(pos.x, pos.y, MOUSE_MMB_DBLCLK, false)) - { - DoAction(pos.x, pos.y, MOUSE_MMB_DOWN, false); - } - - return 0; -} - -/* -** Runs the action when a X mouse button is down -** -*/ -LRESULT MeterWindow::OnXButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - if (uMsg == WM_NCXBUTTONDOWN) - { - // Transform the point to client rect - MapWindowPoints(nullptr, m_Window, &pos, 1); - } - - // Handle buttons - HandleButtons(pos, BUTTONPROC_MOVE); - - if (GET_XBUTTON_WPARAM (wParam) == XBUTTON1) - { - DoAction(pos.x, pos.y, MOUSE_X1MB_DOWN, false); - } - else if (GET_XBUTTON_WPARAM (wParam) == XBUTTON2) - { - DoAction(pos.x, pos.y, MOUSE_X2MB_DOWN, false); - } - - return 0; -} - -/* -** Runs the action when a X mouse button is up -** -*/ -LRESULT MeterWindow::OnXButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - if (uMsg == WM_NCXBUTTONUP) - { - // Transform the point to client rect - MapWindowPoints(nullptr, m_Window, &pos, 1); - } - - // Handle buttons - HandleButtons(pos, BUTTONPROC_MOVE); - - if (GET_XBUTTON_WPARAM (wParam) == XBUTTON1) - { - DoAction(pos.x, pos.y, MOUSE_X1MB_UP, false); - } - else if (GET_XBUTTON_WPARAM (wParam) == XBUTTON2) - { - DoAction(pos.x, pos.y, MOUSE_X2MB_UP, false); - } - - return 0; -} - -/* -** Runs the action when a X mouse button is double-clicked -** -*/ -LRESULT MeterWindow::OnXButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pos; - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - if (uMsg == WM_NCXBUTTONDBLCLK) - { - // Transform the point to client rect - MapWindowPoints(nullptr, m_Window, &pos, 1); - } - - // Handle buttons - HandleButtons(pos, BUTTONPROC_MOVE); - - if (GET_XBUTTON_WPARAM (wParam) == XBUTTON1 && - !DoAction(pos.x, pos.y, MOUSE_X1MB_DBLCLK, false)) - { - DoAction(pos.x, pos.y, MOUSE_X1MB_DOWN, false); - } - else if (GET_XBUTTON_WPARAM (wParam) == XBUTTON2 && - !DoAction(pos.x, pos.y, MOUSE_X2MB_DBLCLK, false)) - { - DoAction(pos.x, pos.y, MOUSE_X2MB_DOWN, false); - } - - return 0; -} - -/* -** Runs the action when the MeterWindow gets or loses focus -** -*/ -LRESULT MeterWindow::OnSetWindowFocus(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_SETFOCUS: - if (!m_OnFocusAction.empty()) - { - Rainmeter::GetInstance().ExecuteCommand(m_OnFocusAction.c_str(), this); - } - break; - - case WM_KILLFOCUS: - if (!m_OnUnfocusAction.empty()) - { - Rainmeter::GetInstance().ExecuteCommand(m_OnUnfocusAction.c_str(), this); - } - break; - } - - return 0; -} - -/* -** Handles the context menu. The menu is recreated every time it is shown. -** -*/ -LRESULT MeterWindow::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pos; - RECT rect; - GetWindowRect(m_Window, &rect); - - if ((lParam & 0xFFFFFFFF) == 0xFFFFFFFF) // WM_CONTEXTMENU is generated from the keyboard (Shift+F10/VK_APPS) - { - // Set menu position to (0,0) on the window - pos.x = rect.left; - pos.y = rect.top; - } - else - { - pos.x = GET_X_LPARAM(lParam); - pos.y = GET_Y_LPARAM(lParam); - - // Transform the point to client rect - POINT posc = {pos.x - rect.left, pos.y - rect.top}; - - // Handle buttons - HandleButtons(posc, BUTTONPROC_MOVE); - - // If RMB up or RMB down or double-click cause actions, do not show the menu! - if (!IsCtrlKeyDown() && // Ctrl is pressed, so ignore any actions - (DoAction(posc.x, posc.y, MOUSE_RMB_UP, false) || DoAction(posc.x, posc.y, MOUSE_RMB_DOWN, true) || DoAction(posc.x, posc.y, MOUSE_RMB_DBLCLK, true))) - { - return 0; - } - } - - Rainmeter::GetInstance().ShowContextMenu(pos, this); - - return 0; -} - -/* -** Executes the action if such are defined. Returns true, if action was executed. -** If the test is true, the action is not executed. -** -*/ -bool MeterWindow::DoAction(int x, int y, MOUSEACTION action, bool test) -{ - std::wstring command; - - // Check if the hitpoint was over some meter - std::vector::const_reverse_iterator j = m_Meters.rbegin(); - for ( ; j != m_Meters.rend(); ++j) - { - // Hidden meters are ignored - if ((*j)->IsHidden()) continue; - - const Mouse& mouse = (*j)->GetMouse(); - if (mouse.HasActionCommand(action) && (*j)->HitTest(x, y)) - { - command = mouse.GetActionCommand(action); - break; - } - } - - if (command.empty()) - { - if (m_Mouse.HasActionCommand(action) && HitTest(x, y)) - { - command = m_Mouse.GetActionCommand(action); - } - } - - if (!command.empty()) - { - if (!test) - { - Rainmeter::GetInstance().ExecuteCommand(command.c_str(), this); - } - - return true; - } - - return false; -} - -/* -** Executes the action if such are defined. Returns true, if meter/window which should be processed still may exist. -** -*/ -bool MeterWindow::DoMoveAction(int x, int y, MOUSEACTION action) -{ - bool buttonFound = false; - - // Check if the hitpoint was over some meter - std::vector::const_reverse_iterator j = m_Meters.rbegin(); - for ( ; j != m_Meters.rend(); ++j) - { - if (!(*j)->IsHidden() && (*j)->HitTest(x, y)) - { - if (action == MOUSE_OVER) - { - if (!m_MouseOver) - { - // If the mouse is over a meter it's also over the main window - //LogDebugF(L"@Enter: %s", m_FolderPath.c_str()); - m_MouseOver = true; - SetMouseLeaveEvent(false); - RegisterMouseInput(); - - if (!m_Mouse.GetOverAction().empty()) - { - UINT currCounter = m_MouseMoveCounter; - Rainmeter::GetInstance().ExecuteCommand(m_Mouse.GetOverAction().c_str(), this); - return (currCounter == m_MouseMoveCounter); - } - } - - // Handle button - MeterButton* button = nullptr; - if (m_HasButtons && (*j)->GetTypeID() == TypeID()) - { - button = (MeterButton*)(*j); - if (button) - { - if (!buttonFound) - { - button->SetFocus(true); - buttonFound = true; - } - else - { - button->SetFocus(false); - } - } - } - - if (!(*j)->IsMouseOver()) - { - const Mouse& mouse = (*j)->GetMouse(); - if (!mouse.GetOverAction().empty() || - !mouse.GetLeaveAction().empty() || - button) - { - //LogDebugF(L"MeterEnter: %s - [%s]", m_FolderPath.c_str(), (*j)->GetName()); - (*j)->SetMouseOver(true); - - if (!mouse.GetOverAction().empty()) - { - UINT currCounter = m_MouseMoveCounter; - Rainmeter::GetInstance().ExecuteCommand(mouse.GetOverAction().c_str(), this); - return (currCounter == m_MouseMoveCounter); - } - } - } - } - } - else - { - if (action == MOUSE_LEAVE) - { - if ((*j)->IsMouseOver()) - { - // Handle button - if (m_HasButtons && (*j)->GetTypeID() == TypeID()) - { - MeterButton* button = (MeterButton*)(*j); - button->SetFocus(false); - } - - //LogDebugF(L"MeterLeave: %s - [%s]", m_FolderPath.c_str(), (*j)->GetName()); - (*j)->SetMouseOver(false); - - const Mouse& mouse = (*j)->GetMouse(); - if (!mouse.GetLeaveAction().empty()) - { - Rainmeter::GetInstance().ExecuteCommand(mouse.GetLeaveAction().c_str(), this); - return true; - } - } - } - } - } - - if (HitTest(x, y)) - { - // If no meters caused actions, do the default actions - if (action == MOUSE_OVER) - { - if (!m_MouseOver) - { - //LogDebugF(L"Enter: %s", m_FolderPath.c_str()); - m_MouseOver = true; - SetMouseLeaveEvent(false); - RegisterMouseInput(); - - if (!m_Mouse.GetOverAction().empty()) - { - UINT currCounter = m_MouseMoveCounter; - Rainmeter::GetInstance().ExecuteCommand(m_Mouse.GetOverAction().c_str(), this); - return (currCounter == m_MouseMoveCounter); - } - } - } - } - else - { - if (action == MOUSE_LEAVE) - { - // Mouse leave happens when the mouse is outside the window - if (m_MouseOver) - { - //LogDebugF(L"Leave: %s", m_FolderPath.c_str()); - m_MouseOver = false; - SetMouseLeaveEvent(true); - UnregisterMouseInput(); - - if (!m_Mouse.GetLeaveAction().empty()) - { - Rainmeter::GetInstance().ExecuteCommand(m_Mouse.GetLeaveAction().c_str(), this); - return true; - } - } - } - } - - return false; -} - -/* -** Sends mouse wheel messages to the window if the window does not have focus. -** -*/ -LRESULT MeterWindow::OnMouseInput(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - const POINT pos = System::GetCursorPosition(); - - // Only process for unfocused skin window. - if (m_Window == WindowFromPoint(pos) && m_Window != GetFocus()) - { - RAWINPUT ri; - UINT riSize = sizeof(ri); - const UINT dataSize = GetRawInputData( - (HRAWINPUT)lParam, RID_INPUT, &ri, &riSize, sizeof(RAWINPUTHEADER)); - if (dataSize != (UINT)-1 && - ri.header.dwType == RIM_TYPEMOUSE) - { - const WPARAM wheelDelta = MAKEWPARAM(0, HIWORD((short)ri.data.mouse.usButtonData)); - const LPARAM wheelPos = MAKELPARAM(pos.x, pos.y); - if (ri.data.mouse.usButtonFlags == RI_MOUSE_WHEEL) - { - OnMouseScrollMove(WM_INPUT, wheelDelta, wheelPos); - } - else if (ri.data.mouse.usButtonFlags == RI_MOUSE_HORIZONTAL_WHEEL) - { - OnMouseHScrollMove(WM_MOUSEHWHEEL, wheelDelta, wheelPos); - } - } - } - - // DefWindowProc must be called after processing WM_INPUT. - DefWindowProc(m_Window, uMsg, wParam, lParam); - return 0; -} - -/* -** Stores the new place of the window, in screen coordinates. -** -*/ -LRESULT MeterWindow::OnMove(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - // The lParam's x/y parameters are given in screen coordinates for overlapped and pop-up windows - // and in parent-client coordinates for child windows. - - // Store the new window position - m_ScreenX = GET_X_LPARAM(lParam); - m_ScreenY = GET_Y_LPARAM(lParam); - - SetWindowPositionVariables(m_ScreenX, m_ScreenY); - - if (m_Dragging) - { - ScreenToWindow(); - } - - return 0; -} - -/* -** Performs an action when returning from sleep -** -*/ -LRESULT MeterWindow::OnWake(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (wParam == PBT_APMRESUMEAUTOMATIC && !m_OnWakeAction.empty()) - { - Rainmeter::GetInstance().ExecuteCommand(m_OnWakeAction.c_str(), this); - } - - return 0; -} - -/* -** The main window procedure for the meter window. -** -*/ -LRESULT CALLBACK MeterWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - MeterWindow* window = (MeterWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA); - - BEGIN_MESSAGEPROC - MESSAGE(OnMouseInput, WM_INPUT) - MESSAGE(OnMove, WM_MOVE) - MESSAGE(OnTimer, WM_TIMER) - MESSAGE(OnCommand, WM_COMMAND) - MESSAGE(OnSysCommand, WM_SYSCOMMAND) - MESSAGE(OnEnterSizeMove, WM_ENTERSIZEMOVE) - MESSAGE(OnExitSizeMove, WM_EXITSIZEMOVE) - MESSAGE(OnNcHitTest, WM_NCHITTEST) - MESSAGE(OnSetCursor, WM_SETCURSOR) - MESSAGE(OnEnterMenuLoop, WM_ENTERMENULOOP) - MESSAGE(OnMouseMove, WM_MOUSEMOVE) - MESSAGE(OnMouseMove, WM_NCMOUSEMOVE) - MESSAGE(OnMouseLeave, WM_MOUSELEAVE) - MESSAGE(OnMouseLeave, WM_NCMOUSELEAVE) - MESSAGE(OnMouseScrollMove, WM_MOUSEWHEEL) - MESSAGE(OnMouseHScrollMove, WM_MOUSEHWHEEL) - MESSAGE(OnContextMenu, WM_CONTEXTMENU) - MESSAGE(OnRightButtonDown, WM_NCRBUTTONDOWN) - MESSAGE(OnRightButtonDown, WM_RBUTTONDOWN) - MESSAGE(OnRightButtonUp, WM_RBUTTONUP) - MESSAGE(OnContextMenu, WM_NCRBUTTONUP) - MESSAGE(OnRightButtonDoubleClick, WM_RBUTTONDBLCLK) - MESSAGE(OnRightButtonDoubleClick, WM_NCRBUTTONDBLCLK) - MESSAGE(OnLeftButtonDown, WM_NCLBUTTONDOWN) - MESSAGE(OnLeftButtonDown, WM_LBUTTONDOWN) - MESSAGE(OnLeftButtonUp, WM_LBUTTONUP) - MESSAGE(OnLeftButtonUp, WM_NCLBUTTONUP) - MESSAGE(OnLeftButtonDoubleClick, WM_LBUTTONDBLCLK) - MESSAGE(OnLeftButtonDoubleClick, WM_NCLBUTTONDBLCLK) - MESSAGE(OnMiddleButtonDown, WM_NCMBUTTONDOWN) - MESSAGE(OnMiddleButtonDown, WM_MBUTTONDOWN) - MESSAGE(OnMiddleButtonUp, WM_MBUTTONUP) - MESSAGE(OnMiddleButtonUp, WM_NCMBUTTONUP) - MESSAGE(OnMiddleButtonDoubleClick, WM_MBUTTONDBLCLK) - MESSAGE(OnMiddleButtonDoubleClick, WM_NCMBUTTONDBLCLK) - MESSAGE(OnXButtonDown, WM_XBUTTONDOWN); - MESSAGE(OnXButtonDown, WM_NCXBUTTONDOWN); - MESSAGE(OnXButtonUp, WM_XBUTTONUP); - MESSAGE(OnXButtonUp, WM_NCXBUTTONUP); - MESSAGE(OnXButtonDoubleClick, WM_XBUTTONDBLCLK); - MESSAGE(OnXButtonDoubleClick, WM_NCXBUTTONDBLCLK); - MESSAGE(OnWindowPosChanging, WM_WINDOWPOSCHANGING) - MESSAGE(OnCopyData, WM_COPYDATA) - MESSAGE(OnDelayedRefresh, WM_METERWINDOW_DELAYED_REFRESH) - MESSAGE(OnDelayedMove, WM_METERWINDOW_DELAYED_MOVE) - MESSAGE(OnDwmColorChange, WM_DWMCOLORIZATIONCOLORCHANGED) - MESSAGE(OnDwmCompositionChange, WM_DWMCOMPOSITIONCHANGED) - MESSAGE(OnSettingChange, WM_SETTINGCHANGE) - MESSAGE(OnDisplayChange, WM_DISPLAYCHANGE) - MESSAGE(OnSetWindowFocus, WM_SETFOCUS) - MESSAGE(OnSetWindowFocus, WM_KILLFOCUS) - MESSAGE(OnWake, WM_POWERBROADCAST) - END_MESSAGEPROC -} - -/* -** The initial window procedure for the meter window. Passes control to WndProc after initial setup. -** -*/ -LRESULT CALLBACK MeterWindow::InitialWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (uMsg == WM_NCCREATE) - { - MeterWindow* window = (MeterWindow*)((LPCREATESTRUCT)lParam)->lpCreateParams; - SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)window); - - // Change the window procedure over to MainWndProc now that GWLP_USERDATA is set - SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)WndProc); - return TRUE; - } - - return DefWindowProc(hWnd, uMsg, wParam, lParam); -} - -/* -** Handles delayed refresh -** -*/ -LRESULT MeterWindow::OnDelayedRefresh(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - Refresh(false); - return 0; -} - -/* -** Handles delayed move. -** Do not save the position in this handler for the sake of preventing move by temporal resolution/workarea change. -** -*/ -LRESULT MeterWindow::OnDelayedMove(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - m_Parser.ResetMonitorVariables(this); - - // Move the window temporarily - ResizeWindow(false); - SetWindowPos(m_Window, nullptr, m_ScreenX, m_ScreenY, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); - - return 0; -} - -/* -** Handles bangs from the exe -** -*/ -LRESULT MeterWindow::OnCopyData(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - COPYDATASTRUCT* pCopyDataStruct = (COPYDATASTRUCT*)lParam; - - if (pCopyDataStruct && (pCopyDataStruct->dwData == 1) && (pCopyDataStruct->cbData > 0)) - { - if (Rainmeter::GetInstance().HasMeterWindow(this)) - { - const WCHAR* command = (const WCHAR*)pCopyDataStruct->lpData; - Rainmeter::GetInstance().ExecuteCommand(command, this); - } - else - { - // This meterwindow has been deactivated - LogWarning(L"Unable to bang unloaded skin"); - } - - return TRUE; - } - - return FALSE; -} - -/* -** Sets up the window position variables. -** -*/ -void MeterWindow::SetWindowPositionVariables(int x, int y) -{ - WCHAR buffer[32]; - - _itow_s(x, buffer, 10); - m_Parser.SetBuiltInVariable(L"CURRENTCONFIGX", buffer); - _itow_s(y, buffer, 10); - m_Parser.SetBuiltInVariable(L"CURRENTCONFIGY", buffer); -} - -/* -** Sets up the window size variables. -** -*/ -void MeterWindow::SetWindowSizeVariables(int w, int h) -{ - WCHAR buffer[32]; - - _itow_s(w, buffer, 10); - m_Parser.SetBuiltInVariable(L"CURRENTCONFIGWIDTH", buffer); - _itow_s(h, buffer, 10); - m_Parser.SetBuiltInVariable(L"CURRENTCONFIGHEIGHT", buffer); -} - -/* -** Converts the path to absolute by adding the skin's path to it (unless it already is absolute). -** -*/ -void MeterWindow::MakePathAbsolute(std::wstring& path) -{ - if (path.empty() || PathUtil::IsAbsolute(path)) - { - return; // It's already absolute path (or it's empty) - } - else - { - std::wstring absolute; - absolute.reserve(Rainmeter::GetInstance().GetSkinPath().size() + m_FolderPath.size() + 1 + path.size()); - absolute = Rainmeter::GetInstance().GetSkinPath(); - absolute += m_FolderPath; - absolute += L'\\'; - absolute += path; - absolute.swap(path); - } -} - -std::wstring MeterWindow::GetFilePath() -{ - std::wstring file = Rainmeter::GetInstance().GetSkinPath() + m_FolderPath; - file += L'\\'; - file += m_FileName; - return file; -} - -std::wstring MeterWindow::GetRootName() -{ - std::wstring::size_type loc; - if ((loc = m_FolderPath.find_first_of(L'\\')) != std::wstring::npos) - { - return m_FolderPath.substr(0, loc); - } - - return m_FolderPath; -} - -std::wstring MeterWindow::GetRootPath() -{ - std::wstring path = Rainmeter::GetInstance().GetSkinPath(); - - std::wstring::size_type loc; - if ((loc = m_FolderPath.find_first_of(L'\\')) != std::wstring::npos) - { - path.append(m_FolderPath, 0, loc + 1); - } - else - { - path += m_FolderPath; - path += L'\\'; - } - - return path; -} - -std::wstring MeterWindow::GetResourcesPath() -{ - std::wstring path = GetRootPath(); - path += L"@Resources\\"; - return path; -} - -std::wstring MeterWindow::GetSkinPath() -{ - std::wstring path; - if (!m_FolderPath.empty()) - { - path += m_FolderPath; - path += L"\\"; - } - - path += m_FileName; - return path; -} - -Meter* MeterWindow::GetMeter(const std::wstring& meterName) -{ - const WCHAR* name = meterName.c_str(); - std::vector::const_iterator j = m_Meters.begin(); - for ( ; j != m_Meters.end(); ++j) - { - if (_wcsicmp((*j)->GetName(), name) == 0) - { - return (*j); - } - } - return nullptr; -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "MeterWindow.h" +#include "Rainmeter.h" +#include "TrayWindow.h" +#include "System.h" +#include "Error.h" +#include "Meter.h" +#include "Measure.h" +#include "DialogAbout.h" +#include "DialogManage.h" +#include "resource.h" +#include "Litestep.h" +#include "MeasureCalc.h" +#include "MeasureNet.h" +#include "MeasurePlugin.h" +#include "MeterButton.h" +#include "MeterString.h" +#include "TintedImage.h" +#include "MeasureScript.h" +#include "../Version.h" +#include "../Common/PathUtil.h" +#include "../Common/Gfx/Canvas.h" + +using namespace Gdiplus; + +#define SNAPDISTANCE 10 + +#define ZPOS_FLAGS (SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING) + +enum TIMER +{ + TIMER_METER = 1, + TIMER_MOUSE = 2, + TIMER_FADE = 3, + TIMER_TRANSITION = 4, + TIMER_DEACTIVATE = 5 +}; +enum INTERVAL +{ + INTERVAL_METER = 1000, + INTERVAL_MOUSE = 500, + INTERVAL_FADE = 10, + INTERVAL_TRANSITION = 100 +}; + +int MeterWindow::c_InstanceCount = 0; + +HINSTANCE MeterWindow::c_DwmInstance = nullptr; +decltype(DwmEnableBlurBehindWindow)* MeterWindow::c_DwmEnableBlurBehindWindow = nullptr; +decltype(DwmGetColorizationColor)* MeterWindow::c_DwmGetColorizationColor = nullptr; +decltype(DwmSetWindowAttribute)* MeterWindow::c_DwmSetWindowAttribute = nullptr; +decltype(DwmIsCompositionEnabled)* MeterWindow::c_DwmIsCompositionEnabled = nullptr; + +/* +** Constructor +** +*/ +MeterWindow::MeterWindow(const std::wstring& folderPath, const std::wstring& file) : m_FolderPath(folderPath), m_FileName(file), + m_Canvas(), + m_Background(), + m_BackgroundSize(), + m_Window(), + m_Mouse(this), + m_MouseOver(false), + m_MouseInputRegistered(false), + m_HasMouseScrollAction(false), + m_BackgroundMargins(), + m_DragMargins(), + m_WindowX(1, L'0'), + m_WindowY(1, L'0'), + m_WindowXScreen(1), + m_WindowYScreen(1), + m_WindowXScreenDefined(false), + m_WindowYScreenDefined(false), + m_WindowXFromRight(false), + m_WindowYFromBottom(false), + m_WindowXPercentage(false), + m_WindowYPercentage(false), + m_WindowW(), + m_WindowH(), + m_ScreenX(), + m_ScreenY(), + m_AnchorXFromRight(false), + m_AnchorYFromBottom(false), + m_AnchorXPercentage(false), + m_AnchorYPercentage(false), + m_AnchorScreenX(), + m_AnchorScreenY(), + m_WindowDraggable(true), + m_WindowUpdate(INTERVAL_METER), + m_TransitionUpdate(INTERVAL_TRANSITION), + m_ActiveTransition(false), + m_HasNetMeasures(false), + m_HasButtons(false), + m_WindowHide(HIDEMODE_NONE), + m_WindowStartHidden(false), + m_SavePosition(false), // Must be false + m_SnapEdges(true), + m_AlphaValue(255), + m_FadeDuration(250), + m_WindowZPosition(ZPOSITION_NORMAL), + m_DynamicWindowSize(false), + m_ClickThrough(false), + m_KeepOnScreen(true), + m_AutoSelectScreen(false), + m_UseD2D(true), + m_Dragging(false), + m_Dragged(false), + m_BackgroundMode(BGMODE_IMAGE), + m_SolidAngle(), + m_SolidBevel(BEVELTYPE_NONE), + m_Blur(false), + m_BlurMode(BLURMODE_NONE), + m_BlurRegion(), + m_FadeStartTime(), + m_FadeStartValue(), + m_FadeEndValue(), + m_TransparencyValue(), + m_State(STATE_INITIALIZING), + m_Hidden(false), + m_ResizeWindow(RESIZEMODE_NONE), + m_UpdateCounter(), + m_MouseMoveCounter(), + m_FontCollection(), + m_ToolTipHidden(false) +{ + if (!c_DwmInstance && IsWindowsVistaOrGreater() && + (c_DwmInstance = System::RmLoadLibrary(L"dwmapi.dll")) != nullptr) + { + c_DwmEnableBlurBehindWindow = + (decltype(c_DwmEnableBlurBehindWindow))GetProcAddress(c_DwmInstance, "DwmEnableBlurBehindWindow"); + c_DwmGetColorizationColor = + (decltype(c_DwmGetColorizationColor))GetProcAddress(c_DwmInstance, "DwmGetColorizationColor"); + c_DwmSetWindowAttribute = + (decltype(c_DwmSetWindowAttribute))GetProcAddress(c_DwmInstance, "DwmSetWindowAttribute"); + c_DwmIsCompositionEnabled = + (decltype(c_DwmIsCompositionEnabled))GetProcAddress(c_DwmInstance, "DwmIsCompositionEnabled"); + } + + if (c_InstanceCount == 0) + { + WNDCLASSEX wc = {sizeof(WNDCLASSEX)}; + wc.style = CS_NOCLOSE | CS_DBLCLKS; + wc.lpfnWndProc = InitialWndProc; + wc.hInstance = Rainmeter::GetInstance().GetModuleInstance(); + wc.hCursor = nullptr; // The cursor should be controlled by using SetCursor() when needed. + wc.lpszClassName = METERWINDOW_CLASS_NAME; + RegisterClassEx(&wc); + } + + ++c_InstanceCount; +} + +/* +** Destructor +** +*/ +MeterWindow::~MeterWindow() +{ + m_State = STATE_CLOSING; + + if (!m_OnCloseAction.empty()) + { + Rainmeter::GetInstance().ExecuteCommand(m_OnCloseAction.c_str(), this); + } + + Dispose(false); + + --c_InstanceCount; + + if (c_InstanceCount == 0) + { + UnregisterClass(METERWINDOW_CLASS_NAME, Rainmeter::GetInstance().GetModuleInstance()); + + if (c_DwmInstance) + { + FreeLibrary(c_DwmInstance); + c_DwmInstance = nullptr; + + c_DwmEnableBlurBehindWindow = nullptr; + c_DwmGetColorizationColor = nullptr; + c_DwmSetWindowAttribute = nullptr; + c_DwmIsCompositionEnabled = nullptr; + } + } +} + +/* +** Kills timers/hooks and disposes buffers +** +*/ +void MeterWindow::Dispose(bool refresh) +{ + // Kill the timer/hook + KillTimer(m_Window, TIMER_METER); + KillTimer(m_Window, TIMER_MOUSE); + KillTimer(m_Window, TIMER_FADE); + KillTimer(m_Window, TIMER_TRANSITION); + + m_FadeStartTime = 0; + + UnregisterMouseInput(); + m_HasMouseScrollAction = false; + + m_ActiveTransition = false; + + m_MouseOver = false; + SetMouseLeaveEvent(true); + + // Destroy the meters + for (auto j = m_Meters.begin(); j != m_Meters.end(); ++j) + { + delete (*j); + } + m_Meters.clear(); + + // Destroy the measures + for (auto i = m_Measures.begin(); i != m_Measures.end(); ++i) + { + delete (*i); + } + m_Measures.clear(); + + delete m_Background; + m_Background = nullptr; + + m_BackgroundSize.cx = m_BackgroundSize.cy = 0; + m_BackgroundName.clear(); + + if (m_BlurRegion) + { + DeleteObject(m_BlurRegion); + m_BlurRegion = nullptr; + } + + if (m_FontCollection) + { + delete m_FontCollection; + m_FontCollection = nullptr; + } + + if (!refresh) + { + if (m_Window) + { + DestroyWindow(m_Window); + m_Window = nullptr; + } + } + + delete m_Canvas; + m_Canvas = nullptr; +} + +/* +** Initializes the window, creates the class and the window. +** +*/ +void MeterWindow::Initialize() +{ + m_Window = CreateWindowEx( + WS_EX_TOOLWINDOW | WS_EX_LAYERED, + METERWINDOW_CLASS_NAME, + nullptr, + WS_POPUP, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + nullptr, + nullptr, + Rainmeter::GetInstance().GetModuleInstance(), + this); + + setlocale(LC_NUMERIC, "C"); + + // Mark the window to ignore the Aero peek + IgnoreAeroPeek(); + + Refresh(true, true); + if (!m_WindowStartHidden) + { + if (m_WindowHide == HIDEMODE_FADEOUT) + { + FadeWindow(0, 255); + } + else + { + FadeWindow(0, m_AlphaValue); + } + } +} + +/* +** Excludes this window from the Aero Peek. +** +*/ +void MeterWindow::IgnoreAeroPeek() +{ + if (c_DwmSetWindowAttribute) + { + BOOL bValue = TRUE; + c_DwmSetWindowAttribute(m_Window, DWMWA_EXCLUDED_FROM_PEEK, &bValue, sizeof(bValue)); + } +} + +/* +** Registers to receive WM_INPUT for the mouse events. +** +*/ +void MeterWindow::RegisterMouseInput() +{ + if (!m_MouseInputRegistered && m_HasMouseScrollAction) + { + RAWINPUTDEVICE rid; + rid.usUsagePage = 0x01; + rid.usUsage = 0x02; // HID mouse + rid.dwFlags = RIDEV_INPUTSINK; + rid.hwndTarget = m_Window; + if (RegisterRawInputDevices(&rid, 1, sizeof(rid))) + { + m_MouseInputRegistered = true; + } + } +} + +void MeterWindow::UnregisterMouseInput() +{ + if (m_MouseInputRegistered) + { + RAWINPUTDEVICE rid; + rid.usUsagePage = 0x01; + rid.usUsage = 0x02; // HID mouse + rid.dwFlags = RIDEV_REMOVE; + rid.hwndTarget = m_Window; + RegisterRawInputDevices(&rid, 1, sizeof(rid)); + m_MouseInputRegistered = false; + } +} + +void MeterWindow::AddWindowExStyle(LONG_PTR flag) +{ + LONG_PTR style = GetWindowLongPtr(m_Window, GWL_EXSTYLE); + if ((style & flag) == 0) + { + SetWindowLongPtr(m_Window, GWL_EXSTYLE, style | flag); + } +} + +void MeterWindow::RemoveWindowExStyle(LONG_PTR flag) +{ + LONG_PTR style = GetWindowLongPtr(m_Window, GWL_EXSTYLE); + if ((style & flag) != 0) + { + SetWindowLongPtr(m_Window, GWL_EXSTYLE, style & ~flag); + } +} + +/* +** Unloads the skin with delay to avoid crash (and for fade to complete). +** +*/ +void MeterWindow::Deactivate() +{ + if (m_State == STATE_CLOSING) return; + m_State = STATE_CLOSING; + + Rainmeter::GetInstance().RemoveMeterWindow(this); + Rainmeter::GetInstance().AddUnmanagedMeterWindow(this); + + HideFade(); + SetTimer(m_Window, TIMER_DEACTIVATE, m_FadeDuration + 50, nullptr); +} + +/* +** Rebuilds the skin. +** +*/ +void MeterWindow::Refresh(bool init, bool all) +{ + if (m_State == STATE_CLOSING) return; + m_State = STATE_REFRESHING; + + Rainmeter::GetInstance().SetCurrentParser(&m_Parser); + + LogNoticeF(this, L"Refreshing skin"); + + SetResizeWindowMode(RESIZEMODE_RESET); + + if (!init) + { + Dispose(true); + } + + ZPOSITION oldZPos = m_WindowZPosition; + + if (!ReadSkin()) + { + Rainmeter::GetInstance().DeactivateSkin(this, -1); + return; + } + + // Remove transparent flag + RemoveWindowExStyle(WS_EX_TRANSPARENT); + + m_Hidden = m_WindowStartHidden; + m_TransparencyValue = m_AlphaValue; + + Update(true); + + if (m_BlurMode == BLURMODE_NONE) + { + HideBlur(); + } + else + { + ShowBlur(); + } + + if (m_KeepOnScreen) + { + MapCoordsToScreen(m_ScreenX, m_ScreenY, m_WindowW, m_WindowH); + } + + SetWindowPos(m_Window, nullptr, m_ScreenX, m_ScreenY, m_WindowW, m_WindowH, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + + ScreenToWindow(); + + if (init) + { + ChangeSingleZPos(m_WindowZPosition, all); + } + else if (all || oldZPos != m_WindowZPosition) + { + ChangeZPos(m_WindowZPosition, all); + } + + // Start the timers + if (m_WindowUpdate >= 0) + { + SetTimer(m_Window, TIMER_METER, m_WindowUpdate, nullptr); + } + + SetTimer(m_Window, TIMER_MOUSE, INTERVAL_MOUSE, nullptr); + + Rainmeter::GetInstance().SetCurrentParser(nullptr); + + m_State = STATE_RUNNING; + + if (!m_OnRefreshAction.empty()) + { + Rainmeter::GetInstance().ExecuteCommand(m_OnRefreshAction.c_str(), this); + } +} + +void MeterWindow::SetMouseLeaveEvent(bool cancel) +{ + if (!cancel && (!m_MouseOver || m_ClickThrough)) return; + + // Check whether the mouse event is set + TRACKMOUSEEVENT tme = {sizeof(TRACKMOUSEEVENT)}; + tme.hwndTrack = m_Window; + tme.dwFlags = TME_QUERY; + + if (TrackMouseEvent(&tme) != 0) + { + if (cancel) + { + if (tme.dwFlags == 0) return; + } + else + { + if (m_WindowDraggable) + { + if (tme.dwFlags == (TME_LEAVE | TME_NONCLIENT)) return; + } + else + { + if (tme.dwFlags == TME_LEAVE) return; + } + } + } + + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.hwndTrack = m_Window; + + // Cancel the mouse event set before + tme.dwFlags |= TME_CANCEL; + TrackMouseEvent(&tme); + + if (cancel) return; + + // Set the mouse event + tme.dwFlags = TME_LEAVE; + if (m_WindowDraggable) + { + tme.dwFlags |= TME_NONCLIENT; + } + TrackMouseEvent(&tme); +} + +void MeterWindow::MapCoordsToScreen(int& x, int& y, int w, int h) +{ + const size_t numOfMonitors = System::GetMonitorCount(); // intentional + const std::vector& monitors = System::GetMultiMonitorInfo().monitors; + + // Check that the window is inside the screen area + POINT pt = {x + w / 2, y + h / 2}; + for (int i = 0; i < 5; ++i) + { + switch (i) + { + case 0: + // Use initial value + break; + + case 1: + pt.x = x; + pt.y = y; + break; + + case 2: + pt.x = x + w; + pt.y = y + h; + break; + + case 3: + pt.x = x; + pt.y = y + h; + break; + + case 4: + pt.x = x + w; + pt.y = y; + break; + } + + for (auto iter = monitors.cbegin(); iter != monitors.cend(); ++iter) + { + if (!(*iter).active) continue; + + const RECT r = (*iter).screen; + if (pt.x >= r.left && pt.x < r.right && pt.y >= r.top && pt.y < r.bottom) + { + x = min(x, r.right - w); + x = max(x, r.left); + y = min(y, r.bottom - h); + y = max(y, r.top); + return; + } + } + } + + // No monitor found for the window -> Use the default work area + const RECT r = monitors[System::GetMultiMonitorInfo().primary - 1].work; + x = min(x, r.right - w); + x = max(x, r.left); + y = min(y, r.bottom - h); + y = max(y, r.top); +} + +/* +** Moves the window to a new place (on the virtual screen) +** +*/ +void MeterWindow::MoveWindow(int x, int y) +{ + SetWindowPos(m_Window, nullptr, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); + + SavePositionIfAppropriate(); +} + +/* +** Sets the window's z-position +** +*/ +void MeterWindow::ChangeZPos(ZPOSITION zPos, bool all) +{ + HWND winPos = HWND_NOTOPMOST; + m_WindowZPosition = zPos; + + switch (zPos) + { + case ZPOSITION_ONTOPMOST: + case ZPOSITION_ONTOP: + winPos = HWND_TOPMOST; + break; + + case ZPOSITION_ONBOTTOM: + if (all) + { + if (System::GetShowDesktop()) + { + // Insert after the system window temporarily to keep order + winPos = System::GetWindow(); + } + else + { + // Insert after the helper window + winPos = System::GetHelperWindow(); + } + } + else + { + winPos = HWND_BOTTOM; + } + break; + + case ZPOSITION_NORMAL: + if (all || !Rainmeter::GetInstance().IsNormalStayDesktop()) break; + case ZPOSITION_ONDESKTOP: + if (System::GetShowDesktop()) + { + winPos = System::GetHelperWindow(); + + if (all) + { + // Insert after the helper window + } + else + { + // Find the "backmost" topmost window + while (winPos = ::GetNextWindow(winPos, GW_HWNDPREV)) + { + if (GetWindowLongPtr(winPos, GWL_EXSTYLE) & WS_EX_TOPMOST) + { + // Insert after the found window + if (0 != SetWindowPos(m_Window, winPos, 0, 0, 0, 0, ZPOS_FLAGS)) + { + break; + } + } + } + return; + } + } + else + { + if (all) + { + // Insert after the helper window + winPos = System::GetHelperWindow(); + } + else + { + winPos = HWND_BOTTOM; + } + } + break; + } + + SetWindowPos(m_Window, winPos, 0, 0, 0, 0, ZPOS_FLAGS); +} + +/* +** Sets the window's z-position in proper order. +** +*/ +void MeterWindow::ChangeSingleZPos(ZPOSITION zPos, bool all) +{ + if (zPos == ZPOSITION_NORMAL && Rainmeter::GetInstance().IsNormalStayDesktop() && (!all || System::GetShowDesktop())) + { + m_WindowZPosition = zPos; + + // Set window on top of all other ZPOSITION_ONDESKTOP, ZPOSITION_BOTTOM, and ZPOSITION_NORMAL windows + SetWindowPos(m_Window, System::GetBackmostTopWindow(), 0, 0, 0, 0, ZPOS_FLAGS); + + // Bring window on top of other application windows + BringWindowToTop(m_Window); + } + else + { + ChangeZPos(zPos, all); + } +} + +/* +** Runs the bang command with the given arguments. +** Correct number of arguments must be passed (or use Rainmeter::ExecuteBang). +*/ +void MeterWindow::DoBang(Bang bang, const std::vector& args) +{ + switch (bang) + { + case Bang::Refresh: + // Refresh needs to be delayed since it crashes if done during Update() + PostMessage(m_Window, WM_METERWINDOW_DELAYED_REFRESH, (WPARAM)nullptr, (LPARAM)nullptr); + break; + + case Bang::Redraw: + Redraw(); + break; + + case Bang::Update: + KillTimer(m_Window, TIMER_METER); // Kill timer temporarily + Update(false); + if (m_WindowUpdate >= 0) + { + SetTimer(m_Window, TIMER_METER, m_WindowUpdate, nullptr); + } + break; + + case Bang::ShowBlur: + ShowBlur(); + break; + + case Bang::HideBlur: + HideBlur(); + break; + + case Bang::ToggleBlur: + DoBang(IsBlur() ? Bang::HideBlur : Bang::ShowBlur, args); + break; + + case Bang::AddBlur: + ResizeBlur(args[0], RGN_OR); + if (IsBlur()) ShowBlur(); + break; + + case Bang::RemoveBlur: + ResizeBlur(args[0], RGN_DIFF); + if (IsBlur()) ShowBlur(); + break; + + case Bang::ToggleMeter: + ToggleMeter(args[0]); + break; + + case Bang::ShowMeter: + ShowMeter(args[0]); + break; + + case Bang::HideMeter: + HideMeter(args[0]); + break; + + case Bang::UpdateMeter: + UpdateMeter(args[0]); + break; + + case Bang::ToggleMeterGroup: + ToggleMeter(args[0], true); + break; + + case Bang::ShowMeterGroup: + ShowMeter(args[0], true); + break; + + case Bang::HideMeterGroup: + HideMeter(args[0], true); + break; + + case Bang::UpdateMeterGroup: + UpdateMeter(args[0], true); + break; + + case Bang::ToggleMeasure: + ToggleMeasure(args[0]); + break; + + case Bang::EnableMeasure: + EnableMeasure(args[0]); + break; + + case Bang::DisableMeasure: + DisableMeasure(args[0]); + break; + + case Bang::PauseMeasure: + PauseMeasure(args[0]); + break; + + case Bang::UnpauseMeasure: + UnpauseMeasure(args[0]); + break; + + case Bang::TogglePauseMeasure: + TogglePauseMeasure(args[0]); + break; + + case Bang::UpdateMeasure: + UpdateMeasure(args[0]); + DialogAbout::UpdateMeasures(this); + break; + + case Bang::DisableMeasureGroup: + DisableMeasure(args[0], true); + break; + + case Bang::ToggleMeasureGroup: + ToggleMeasure(args[0], true); + break; + + case Bang::EnableMeasureGroup: + EnableMeasure(args[0], true); + break; + + case Bang::PauseMeasureGroup: + PauseMeasure(args[0], true); + break; + + case Bang::UnpauseMeasureGroup: + UnpauseMeasure(args[0], true); + break; + + case Bang::TogglePauseMeasureGroup: + TogglePauseMeasure(args[0], true); + break; + + case Bang::UpdateMeasureGroup: + UpdateMeasure(args[0], true); + DialogAbout::UpdateMeasures(this); + break; + + case Bang::Show: + m_Hidden = false; + ShowWindow(m_Window, SW_SHOWNOACTIVATE); + UpdateWindowTransparency((m_WindowHide == HIDEMODE_FADEOUT) ? 255 : m_AlphaValue); + break; + + case Bang::Hide: + m_Hidden = true; + ShowWindow(m_Window, SW_HIDE); + break; + + case Bang::Toggle: + DoBang(m_Hidden ? Bang::Show : Bang::Hide, args); + break; + + case Bang::ShowFade: + ShowFade(); + break; + + case Bang::HideFade: + HideFade(); + break; + + case Bang::ToggleFade: + DoBang(m_Hidden ? Bang::ShowFade : Bang::HideFade, args); + break; + + case Bang::Move: + { + int x = m_Parser.ParseInt(args[0].c_str(), 0); + int y = m_Parser.ParseInt(args[1].c_str(), 0); + MoveWindow(x, y); + } + break; + + case Bang::ZPos: + SetWindowZPosition((ZPOSITION)m_Parser.ParseInt(args[0].c_str(), 0)); + break; + + case Bang::ClickThrough: + { + int f = m_Parser.ParseInt(args[0].c_str(), 0); + SetClickThrough((f == -1) ? !m_ClickThrough : f != 0); + } + break; + + case Bang::Draggable: + { + int f = m_Parser.ParseInt(args[0].c_str(), 0); + SetWindowDraggable((f == -1) ? !m_WindowDraggable : f != 0); + } + break; + + case Bang::SnapEdges: + { + int f = m_Parser.ParseInt(args[0].c_str(), 0); + SetSnapEdges((f == -1) ? !m_SnapEdges : f != 0); + } + break; + + case Bang::KeepOnScreen: + { + int f = m_Parser.ParseInt(args[0].c_str(), 0); + SetKeepOnScreen((f == -1) ? !m_KeepOnScreen : f != 0); + } + break; + + case Bang::SetTransparency: + { + const std::wstring& arg = args[0]; + m_AlphaValue = ConfigParser::ParseInt(arg.c_str(), 255); + m_AlphaValue = max(m_AlphaValue, 0); + m_AlphaValue = min(m_AlphaValue, 255); + UpdateWindowTransparency(m_AlphaValue); + } + break; + + case Bang::MoveMeter: + { + int x = m_Parser.ParseInt(args[0].c_str(), 0); + int y = m_Parser.ParseInt(args[1].c_str(), 0); + MoveMeter(args[2], x, y); + } + break; + + case Bang::CommandMeasure: + { + const std::wstring& measure = args[0]; + Measure* m = GetMeasure(measure); + if (m) + { + m->Command(args[1]); + } + else + { + LogWarningF(this, L"!CommandMeasure: [%s] not found", measure.c_str()); + } + } + break; + + case Bang::PluginBang: + { + std::wstring arg = args[0]; + std::wstring::size_type pos; + while ((pos = arg.find(L'"')) != std::wstring::npos) + { + arg.erase(pos, 1); + } + + std::wstring measure; + pos = arg.find(L' '); + if (pos != std::wstring::npos) + { + measure.assign(arg, 0, pos); + ++pos; + } + else + { + measure = arg; + } + arg.erase(0, pos); + + if (!measure.empty()) + { + Measure* m = GetMeasure(measure); + if (m) + { + m->Command(arg); + return; + } + + LogWarningF(this, L"!PluginBang: [%s] not found", measure.c_str()); + } + else + { + LogErrorF(this, L"!PluginBang: Invalid parameters"); + } + } + break; + + case Bang::SetVariable: + SetVariable(args[0], args[1]); + break; + + case Bang::SetOption: + SetOption(args[0], args[1], args[2], false); + break; + + case Bang::SetOptionGroup: + SetOption(args[0], args[1], args[2], true); + break; + + case Bang::SkinCustomMenu: + Rainmeter::GetInstance().ShowSkinCustomContextMenu(System::GetCursorPosition(), this); + break; + } +} + +/* +** Enables blurring of the window background (using Aero) +** +*/ +void MeterWindow::ShowBlur() +{ + if (c_DwmGetColorizationColor && c_DwmIsCompositionEnabled && c_DwmEnableBlurBehindWindow) + { + SetBlur(true); + + // Check that Aero and transparency is enabled + DWORD color; + BOOL opaque, enabled; + if (c_DwmGetColorizationColor(&color, &opaque) != S_OK) + { + opaque = TRUE; + } + if (c_DwmIsCompositionEnabled(&enabled) != S_OK) + { + enabled = FALSE; + } + if (opaque || !enabled) return; + + if (m_BlurMode == BLURMODE_FULL) + { + if (m_BlurRegion) DeleteObject(m_BlurRegion); + m_BlurRegion = CreateRectRgn(0, 0, GetW(), GetH()); + } + + BlurBehindWindow(TRUE); + } +} + +/* +** Disables Aero blur +** +*/ +void MeterWindow::HideBlur() +{ + if (c_DwmEnableBlurBehindWindow) + { + SetBlur(false); + + BlurBehindWindow(FALSE); + } +} + +/* +** Adds to or removes from blur region +** +*/ +void MeterWindow::ResizeBlur(const std::wstring& arg, int mode) +{ + if (IsWindowsVistaOrGreater()) + { + WCHAR* parseSz = _wcsdup(arg.c_str()); + int type, x, y, w = 0, h = 0; + + WCHAR* token = wcstok(parseSz, L","); + if (token) + { + while (token[0] == L' ') ++token; + type = m_Parser.ParseInt(token, 0); + + token = wcstok(nullptr, L","); + if (token) + { + while (token[0] == L' ') ++token; + x = m_Parser.ParseInt(token, 0); + + token = wcstok(nullptr, L","); + if (token) + { + while (token[0] == L' ') ++token; + y = m_Parser.ParseInt(token, 0); + + token = wcstok(nullptr, L","); + if (token) + { + while (token[0] == L' ') ++token; + w = m_Parser.ParseInt(token, 0); + + token = wcstok(nullptr, L","); + if (token) + { + while (token[0] == L' ') ++token; + h = m_Parser.ParseInt(token, 0); + } + } + } + } + } + + if (w && h) + { + HRGN tempRegion; + + switch (type) + { + case 1: + tempRegion = CreateRectRgn(x, y, w, h); + break; + + case 2: + token = wcstok(nullptr, L","); + if (token) + { + while (token[0] == L' ') ++token; + int r = m_Parser.ParseInt(token, 0); + tempRegion = CreateRoundRectRgn(x, y, w, h, r, r); + } + break; + + case 3: + tempRegion = CreateEllipticRgn(x, y, w, h); + break; + + default: // Unknown type + free(parseSz); + return; + } + + CombineRgn(m_BlurRegion, m_BlurRegion, tempRegion, mode); + DeleteObject(tempRegion); + } + free(parseSz); + } +} + +/* +** Helper function that compares the given name to section's name. +** +*/ +bool CompareName(const Section* section, const WCHAR* name, bool group) +{ + return (group) ? section->BelongsToGroup(name) : (_wcsicmp(section->GetName(), name) == 0); +} + +/* +** Shows the given meter +** +*/ +void MeterWindow::ShowMeter(const std::wstring& name, bool group) +{ + const WCHAR* meter = name.c_str(); + + std::vector::const_iterator j = m_Meters.begin(); + for ( ; j != m_Meters.end(); ++j) + { + if (CompareName((*j), meter, group)) + { + (*j)->Show(); + SetResizeWindowMode(RESIZEMODE_CHECK); // Need to recalculate the window size + if (!group) return; + } + } + + if (!group) LogErrorF(this, L"!ShowMeter: [%s] not found", meter); +} + +/* +** Hides the given meter +** +*/ +void MeterWindow::HideMeter(const std::wstring& name, bool group) +{ + const WCHAR* meter = name.c_str(); + + std::vector::const_iterator j = m_Meters.begin(); + for ( ; j != m_Meters.end(); ++j) + { + if (CompareName((*j), meter, group)) + { + (*j)->Hide(); + SetResizeWindowMode(RESIZEMODE_CHECK); // Need to recalculate the window size + if (!group) return; + } + } + + if (!group) LogErrorF(this, L"!HideMeter: [%s] not found", meter); +} + +/* +** Toggles the given meter +** +*/ +void MeterWindow::ToggleMeter(const std::wstring& name, bool group) +{ + const WCHAR* meter = name.c_str(); + + std::vector::const_iterator j = m_Meters.begin(); + for ( ; j != m_Meters.end(); ++j) + { + if (CompareName((*j), meter, group)) + { + if ((*j)->IsHidden()) + { + (*j)->Show(); + } + else + { + (*j)->Hide(); + } + SetResizeWindowMode(RESIZEMODE_CHECK); // Need to recalculate the window size + if (!group) return; + } + } + + if (!group) LogErrorF(this, L"!ToggleMeter: [%s] not found", meter); +} + +/* +** Moves the given meter +** +*/ +void MeterWindow::MoveMeter(const std::wstring& name, int x, int y) +{ + const WCHAR* meter = name.c_str(); + + std::vector::const_iterator j = m_Meters.begin(); + for ( ; j != m_Meters.end(); ++j) + { + if (CompareName((*j), meter, false)) + { + (*j)->SetX(x); + (*j)->SetY(y); + SetResizeWindowMode(RESIZEMODE_CHECK); // Need to recalculate the window size + return; + } + } + + LogErrorF(this, L"!MoveMeter: [%s] not found", meter); +} + +/* +** Updates the given meter +** +*/ +void MeterWindow::UpdateMeter(const std::wstring& name, bool group) +{ + const WCHAR* meter = name.c_str(); + bool all = false; + + if (!group && meter[0] == L'*' && meter[1] == L'\0') // Allow [!UpdateMeter *] + { + all = true; + group = true; + } + + bool bActiveTransition = false; + bool bContinue = true; + for (auto j = m_Meters.cbegin(); j != m_Meters.cend(); ++j) + { + if (all || (bContinue && CompareName((*j), meter, group))) + { + if (UpdateMeter((*j), bActiveTransition, true)) + { + (*j)->DoUpdateAction(); + } + + SetResizeWindowMode(RESIZEMODE_CHECK); // Need to recalculate the window size + if (!group) + { + bContinue = false; + if (bActiveTransition) break; + } + } + else + { + // Check for transitions + if (!bActiveTransition && (*j)->HasActiveTransition()) + { + bActiveTransition = true; + if (!group && !bContinue) break; + } + } + } + + // Post-updates + PostUpdate(bActiveTransition); + + if (!group && bContinue) LogErrorF(this, L"!UpdateMeter: [%s] not found", meter); +} + +/* +** Enables the given measure +** +*/ +void MeterWindow::EnableMeasure(const std::wstring& name, bool group) +{ + const WCHAR* measure = name.c_str(); + + std::vector::const_iterator i = m_Measures.begin(); + for ( ; i != m_Measures.end(); ++i) + { + if (CompareName((*i), measure, group)) + { + (*i)->Enable(); + if (!group) return; + } + } + + if (!group) LogErrorF(this, L"!EnableMeasure: [%s] not found", measure); +} + +/* +** Disables the given measure +** +*/ +void MeterWindow::DisableMeasure(const std::wstring& name, bool group) +{ + const WCHAR* measure = name.c_str(); + + std::vector::const_iterator i = m_Measures.begin(); + for ( ; i != m_Measures.end(); ++i) + { + if (CompareName((*i), measure, group)) + { + (*i)->Disable(); + if (!group) return; + } + } + + if (!group) LogErrorF(this, L"!DisableMeasure: [%s] not found", measure); +} + +/* +** Toggles the given measure +** +*/ +void MeterWindow::ToggleMeasure(const std::wstring& name, bool group) +{ + const WCHAR* measure = name.c_str(); + + std::vector::const_iterator i = m_Measures.begin(); + for ( ; i != m_Measures.end(); ++i) + { + if (CompareName((*i), measure, group)) + { + if ((*i)->IsDisabled()) + { + (*i)->Enable(); + } + else + { + (*i)->Disable(); + } + if (!group) return; + } + } + + if (!group) LogErrorF(this, L"!ToggleMeasure: [%s] not found", measure); +} + +/* +** Pauses the given measure +** +*/ +void MeterWindow::PauseMeasure(const std::wstring& name, bool group) +{ + const WCHAR* measure = name.c_str(); + + std::vector::const_iterator i = m_Measures.begin(); + for ( ; i != m_Measures.end(); ++i) + { + if (CompareName((*i), measure, group)) + { + (*i)->Pause(); + if (!group) return; + } + } + + if (!group) LogErrorF(this, L"!PauseMeasure: [%s] not found", measure); +} + +/* +** Unpauses the given measure +** +*/ +void MeterWindow::UnpauseMeasure(const std::wstring& name, bool group) +{ + const WCHAR* measure = name.c_str(); + + std::vector::const_iterator i = m_Measures.begin(); + for ( ; i != m_Measures.end(); ++i) + { + if (CompareName((*i), measure, group)) + { + (*i)->Unpause(); + if (!group) return; + } + } + + if (!group) LogErrorF(this, L"!UnpauseMeasure: [%s] not found", measure); +} + +/* +** Toggles the pause state of the given measure +** +*/ +void MeterWindow::TogglePauseMeasure(const std::wstring& name, bool group) +{ + const WCHAR* measure = name.c_str(); + + std::vector::const_iterator i = m_Measures.begin(); + for ( ; i != m_Measures.end(); ++i) + { + if (CompareName((*i), measure, group)) + { + if ((*i)->IsPaused()) + { + (*i)->Unpause(); + } + else + { + (*i)->Pause(); + } + if (!group) return; + } + } + + if (!group) LogErrorF(this, L"!TogglePauseMeasure: [%s] not found", measure); +} + +/* +** Updates the given measure +** +*/ +void MeterWindow::UpdateMeasure(const std::wstring& name, bool group) +{ + const WCHAR* measure = name.c_str(); + bool all = false; + + if (!group && measure[0] == L'*' && measure[1] == L'\0') // Allow [!UpdateMeasure *] + { + all = true; + group = true; + } + + bool bNetStats = m_HasNetMeasures; + for (auto i = m_Measures.cbegin(); i != m_Measures.cend(); ++i) + { + if (all || CompareName((*i), measure, group)) + { + if (bNetStats && (*i)->GetTypeID() == TypeID()) + { + MeasureNet::UpdateIFTable(); + MeasureNet::UpdateStats(); + bNetStats = false; + } + + if (UpdateMeasure((*i), true)) + { + (*i)->DoUpdateAction(); + (*i)->DoChangeAction(); + } + + if (!group) return; + } + } + + if (!group) LogErrorF(this, L"!UpdateMeasure: [%s] not found", measure); +} + +/* +** Sets variable to given value. +** +*/ +void MeterWindow::SetVariable(const std::wstring& variable, const std::wstring& value) +{ + double result; + if (m_Parser.ParseFormula(value, &result)) + { + WCHAR buffer[256]; + int len = _snwprintf_s(buffer, _TRUNCATE, L"%.5f", result); + Measure::RemoveTrailingZero(buffer, len); + + const std::wstring& resultString = buffer; + + m_Parser.SetVariable(variable, resultString); + } + else + { + m_Parser.SetVariable(variable, value); + } +} + +/* +** Changes the property of a meter or measure. +** +*/ +void MeterWindow::SetOption(const std::wstring& section, const std::wstring& option, const std::wstring& value, bool group) +{ + auto setValue = [&](Section* section, const std::wstring& option, const std::wstring& value) + { + // Force DynamicVariables temporarily (until next ReadOptions()). + section->SetDynamicVariables(true); + + if (value.empty()) + { + m_Parser.DeleteValue(section->GetOriginalName(), option); + } + else + { + m_Parser.SetValue(section->GetOriginalName(), option, value); + } + }; + + if (group) + { + for (auto j = m_Meters.begin(); j != m_Meters.end(); ++j) + { + if ((*j)->BelongsToGroup(section)) + { + setValue(*j, option, value); + } + } + + for (auto i = m_Measures.begin(); i != m_Measures.end(); ++i) + { + if ((*i)->BelongsToGroup(section)) + { + setValue(*i, option, value); + } + } + } + else + { + Meter* meter = GetMeter(section); + if (meter) + { + setValue(meter, option, value); + return; + } + + Measure* measure = GetMeasure(section); + if (measure) + { + setValue(measure, option, value); + return; + } + + // ContextTitle and ContextAction in [Rainmeter] are dynamic + if (_wcsicmp(section.c_str(), L"Rainmeter") == 0 && + _wcsnicmp(option.c_str(), L"Context", 7) == 0) + { + if (value.empty()) + { + m_Parser.DeleteValue(section, option); + } + else + { + m_Parser.SetValue(section, option, value); + } + } + + // Is it a style? + } +} + +/* +** Calculates the screen cordinates from the WindowX/Y options +** +*/ +void MeterWindow::WindowToScreen() +{ + std::wstring::size_type index, index2; + int pixel = 0; + float num; + int screenx, screeny, screenh, screenw; + + const int numOfMonitors = (int)System::GetMonitorCount(); + const MultiMonitorInfo& monitorsInfo = System::GetMultiMonitorInfo(); + const std::vector& monitors = monitorsInfo.monitors; + + // Clear position flags + m_WindowXScreen = m_WindowYScreen = monitorsInfo.primary; // Default to primary screen + m_WindowXScreenDefined = m_WindowYScreenDefined = false; + m_WindowXFromRight = m_WindowYFromBottom = false; // Default to from left/top + m_WindowXPercentage = m_WindowYPercentage = false; // Default to pixels + m_AnchorXFromRight = m_AnchorYFromBottom = false; + m_AnchorXPercentage = m_AnchorYPercentage = false; + + // --- Calculate AnchorScreenX --- + + index = m_AnchorX.find_first_not_of(L"0123456789."); + num = (float)_wtof(m_AnchorX.substr(0,index).c_str()); + index = m_AnchorX.find_last_of(L'%'); + if (index != std::wstring::npos) m_AnchorXPercentage = true; + index = m_AnchorX.find_last_of(L'R'); + if (index != std::wstring::npos) m_AnchorXFromRight = true; + if (m_AnchorXPercentage) //is a percentage + { + pixel = (int)(m_WindowW * num / 100.0f); + } + else + { + pixel = (int)num; + } + if (m_AnchorXFromRight) //measure from right + { + pixel = m_WindowW - pixel; + } + else + { + //pixel = pixel; + } + m_AnchorScreenX = pixel; + + // --- Calculate AnchorScreenY --- + + index = m_AnchorY.find_first_not_of(L"0123456789."); + num = (float)_wtof(m_AnchorY.substr(0,index).c_str()); + index = m_AnchorY.find_last_of(L'%'); + if (index != std::wstring::npos) m_AnchorYPercentage = true; + index = m_AnchorY.find_last_of(L'R'); + if (index != std::wstring::npos) m_AnchorYFromBottom = true; + if (m_AnchorYPercentage) //is a percentage + { + pixel = (int)(m_WindowH * num / 100.0f); + } + else + { + pixel = (int)num; + } + if (m_AnchorYFromBottom) //measure from bottom + { + pixel = m_WindowH - pixel; + } + else + { + //pixel = pixel; + } + m_AnchorScreenY = pixel; + + // --- Calculate ScreenX --- + + index = m_WindowX.find_first_not_of(L"-0123456789."); + num = (float)_wtof(m_WindowX.substr(0,index).c_str()); + index = m_WindowX.find_last_of(L'%'); + index2 = m_WindowX.find_last_of(L'#'); // for ignoring the non-replaced variables such as "#WORKAREAX@n#" + if (index != std::wstring::npos && (index2 == std::wstring::npos || index2 < index)) + { + m_WindowXPercentage = true; + } + index = m_WindowX.find_last_of(L'R'); + if (index != std::wstring::npos && (index2 == std::wstring::npos || index2 < index)) + { + m_WindowXFromRight = true; + } + index = m_WindowX.find_last_of(L'@'); + if (index != std::wstring::npos && (index2 == std::wstring::npos || index2 < index)) + { + index = index + 1; + index2 = m_WindowX.find_first_not_of(L"0123456789", index); + + std::wstring screenStr = m_WindowX.substr(index, (index2 != std::wstring::npos) ? index2 - index : std::wstring::npos); + if (!screenStr.empty()) + { + int screenIndex = _wtoi(screenStr.c_str()); + if (screenIndex >= 0 && (screenIndex == 0 || screenIndex <= numOfMonitors && monitors[screenIndex - 1].active)) + { + m_WindowXScreen = screenIndex; + m_WindowXScreenDefined = true; + m_WindowYScreen = m_WindowXScreen; //Default to X and Y on same screen if not overridden on WindowY + m_WindowYScreenDefined = true; + } + } + } + if (m_WindowXScreen == 0) + { + screenx = monitorsInfo.vsL; + screenw = monitorsInfo.vsW; + } + else + { + screenx = monitors[m_WindowXScreen - 1].screen.left; + screenw = monitors[m_WindowXScreen - 1].screen.right - monitors[m_WindowXScreen - 1].screen.left; + } + if (m_WindowXPercentage) //is a percentage + { + pixel = (int)(screenw * num / 100.0f); + } + else + { + pixel = (int)num; + } + if (m_WindowXFromRight) //measure from right + { + pixel = screenx + (screenw - pixel); + } + else + { + pixel = screenx + pixel; + } + m_ScreenX = pixel - m_AnchorScreenX; + + // --- Calculate ScreenY --- + + index = m_WindowY.find_first_not_of(L"-0123456789."); + num = (float)_wtof(m_WindowY.substr(0,index).c_str()); + index = m_WindowY.find_last_of(L'%'); + index2 = m_WindowX.find_last_of(L'#'); // for ignoring the non-replaced variables such as "#WORKAREAY@n#" + if (index != std::wstring::npos && (index2 == std::wstring::npos || index2 < index)) + { + m_WindowYPercentage = true; + } + index = m_WindowY.find_last_of(L'B'); + if (index != std::wstring::npos && (index2 == std::wstring::npos || index2 < index)) + { + m_WindowYFromBottom = true; + } + index = m_WindowY.find_last_of(L'@'); + if (index != std::wstring::npos && (index2 == std::wstring::npos || index2 < index)) + { + index = index + 1; + index2 = m_WindowY.find_first_not_of(L"0123456789", index); + + std::wstring screenStr = m_WindowY.substr(index, (index2 != std::wstring::npos) ? index2 - index : std::wstring::npos); + if (!screenStr.empty()) + { + int screenIndex = _wtoi(screenStr.c_str()); + if (screenIndex >= 0 && (screenIndex == 0 || screenIndex <= numOfMonitors && monitors[screenIndex - 1].active)) + { + m_WindowYScreen = screenIndex; + m_WindowYScreenDefined = true; + } + } + } + if (m_WindowYScreen == 0) + { + screeny = monitorsInfo.vsT; + screenh = monitorsInfo.vsH; + } + else + { + screeny = monitors[m_WindowYScreen - 1].screen.top; + screenh = monitors[m_WindowYScreen - 1].screen.bottom - monitors[m_WindowYScreen - 1].screen.top; + } + if (m_WindowYPercentage) //is a percentage + { + pixel = (int)(screenh * num / 100.0f); + } + else + { + pixel = (int)num; + } + if (m_WindowYFromBottom) //measure from right + { + pixel = screeny + (screenh - pixel); + } + else + { + pixel = screeny + pixel; + } + m_ScreenY = pixel - m_AnchorScreenY; +} + +/* ScreenToWindow +** +** Calculates the WindowX/Y cordinates from the ScreenX/Y +** +*/ +void MeterWindow::ScreenToWindow() +{ + WCHAR buffer[256]; + int pixel = 0; + float num; + int screenx, screeny, screenh, screenw; + + const size_t numOfMonitors = System::GetMonitorCount(); + const MultiMonitorInfo& monitorsInfo = System::GetMultiMonitorInfo(); + const std::vector& monitors = monitorsInfo.monitors; + + // Correct to auto-selected screen + if (m_AutoSelectScreen) + { + RECT rect = {m_ScreenX, m_ScreenY, m_ScreenX + m_WindowW, m_ScreenY + m_WindowH}; + HMONITOR hMonitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST); + + if (hMonitor != nullptr) + { + int screenIndex = 1; + for (auto iter = monitors.cbegin(); iter != monitors.cend(); ++iter, ++screenIndex) + { + if ((*iter).active && (*iter).handle == hMonitor) + { + bool reset = (!m_WindowXScreenDefined || !m_WindowYScreenDefined || + m_WindowXScreen != screenIndex || m_WindowYScreen != screenIndex); + + m_WindowXScreen = m_WindowYScreen = screenIndex; + m_WindowXScreenDefined = m_WindowYScreenDefined = true; + + if (reset) + { + m_Parser.ResetMonitorVariables(this); // Set present monitor variables + } + break; + } + } + } + } + + // --- Calculate WindowX --- + + if (m_WindowXScreen == 0) + { + screenx = monitorsInfo.vsL; + screenw = monitorsInfo.vsW; + } + else + { + screenx = monitors[m_WindowXScreen - 1].screen.left; + screenw = monitors[m_WindowXScreen - 1].screen.right - monitors[m_WindowXScreen - 1].screen.left; + } + if (m_WindowXFromRight) + { + pixel = (screenx + screenw) - m_ScreenX; + pixel -= m_AnchorScreenX; + } + else + { + pixel = m_ScreenX - screenx; + pixel += m_AnchorScreenX; + } + if (m_WindowXPercentage) + { + num = 100.0f * (float)pixel / (float)screenw; + _snwprintf_s(buffer, _TRUNCATE, L"%.5f%%", num); + } + else + { + _itow_s(pixel, buffer, 10); + } + if (m_WindowXFromRight) + { + wcscat_s(buffer, L"R"); + } + if (m_WindowXScreenDefined) + { + _snwprintf_s(buffer, _TRUNCATE, L"%s@%i", buffer, m_WindowXScreen); + } + m_WindowX = buffer; + + // --- Calculate WindowY --- + + if (m_WindowYScreen == 0) + { + screeny = monitorsInfo.vsT; + screenh = monitorsInfo.vsH; + } + else + { + screeny = monitors[m_WindowYScreen - 1].screen.top; + screenh = monitors[m_WindowYScreen - 1].screen.bottom - monitors[m_WindowYScreen - 1].screen.top; + } + if (m_WindowYFromBottom) + { + pixel = (screeny + screenh) - m_ScreenY; + pixel -= m_AnchorScreenY; + } + else + { + pixel = m_ScreenY - screeny; + pixel += m_AnchorScreenY; + } + if (m_WindowYPercentage) + { + num = 100.0f * (float)pixel / (float)screenh; + _snwprintf_s(buffer, _TRUNCATE, L"%.5f%%", num); + } + else + { + _itow_s(pixel, buffer, 10); + } + if (m_WindowYFromBottom) + { + wcscat_s(buffer, L"B"); + } + if (m_WindowYScreenDefined) + { + _snwprintf_s(buffer, _TRUNCATE, L"%s@%i", buffer, m_WindowYScreen); + } + m_WindowY = buffer; +} + +/* +** Reads the skin options from Rainmeter.ini +** +*/ +void MeterWindow::ReadOptions() +{ + WCHAR buffer[32]; + + const WCHAR* section = m_FolderPath.c_str(); + ConfigParser parser; + parser.Initialize(Rainmeter::GetInstance().GetIniFile(), nullptr, section); + + INT writeFlags = 0; + auto addWriteFlag = [&](INT flag) + { + if (parser.GetLastDefaultUsed()) + { + writeFlags |= flag; + } + }; + + // Check if the window position should be read as a formula + double value; + m_WindowX = parser.ReadString(section, L"WindowX", L"0"); + addWriteFlag(OPTION_POSITION); + if (parser.ParseFormula(m_WindowX, &value)) + { + _itow_s((int)value, buffer, 10); + m_WindowX = buffer; + } + m_WindowY = parser.ReadString(section, L"WindowY", L"0"); + addWriteFlag(OPTION_POSITION); + if (parser.ParseFormula(m_WindowY, &value)) + { + _itow_s((int)value, buffer, 10); + m_WindowY = buffer; + } + + m_AnchorX = parser.ReadString(section, L"AnchorX", L"0"); + m_AnchorY = parser.ReadString(section, L"AnchorY", L"0"); + + int zPos = parser.ReadInt(section, L"AlwaysOnTop", ZPOSITION_NORMAL); + addWriteFlag(OPTION_ALWAYSONTOP); + m_WindowZPosition = (zPos >= ZPOSITION_ONDESKTOP && zPos <= ZPOSITION_ONTOPMOST) ? (ZPOSITION)zPos : ZPOSITION_NORMAL; + + int hideMode = parser.ReadInt(section, L"HideOnMouseOver", HIDEMODE_NONE); + m_WindowHide = (hideMode >= HIDEMODE_NONE && hideMode <= HIDEMODE_FADEOUT) ? (HIDEMODE)hideMode : HIDEMODE_NONE; + + m_WindowDraggable = parser.ReadBool(section, L"Draggable", true); + addWriteFlag(OPTION_DRAGGABLE); + + m_SnapEdges = parser.ReadBool(section, L"SnapEdges", true); + addWriteFlag(OPTION_SNAPEDGES); + + m_ClickThrough = parser.ReadBool(section, L"ClickThrough", false); + addWriteFlag(OPTION_CLICKTHROUGH); + + m_KeepOnScreen = parser.ReadBool(section, L"KeepOnScreen", true); + addWriteFlag(OPTION_KEEPONSCREEN); + + m_UseD2D = parser.ReadBool(section, L"UseD2D", true); + m_SavePosition = parser.ReadBool(section, L"SavePosition", true); + m_WindowStartHidden = parser.ReadBool(section, L"StartHidden", false); + m_AutoSelectScreen = parser.ReadBool(section, L"AutoSelectScreen", false); + + m_AlphaValue = parser.ReadInt(section, L"AlphaValue", 255); + m_AlphaValue = max(m_AlphaValue, 0); + m_AlphaValue = min(m_AlphaValue, 255); + + m_FadeDuration = parser.ReadInt(section, L"FadeDuration", 250); + + m_SkinGroup = parser.ReadString(section, L"Group", L""); + + if (writeFlags != 0) + { + WriteOptions(writeFlags); + } + + // Set WindowXScreen/WindowYScreen temporarily + WindowToScreen(); +} + +/* +** Writes the specified options to Rainmeter.ini +** +*/ +void MeterWindow::WriteOptions(INT setting) +{ + const WCHAR* iniFile = Rainmeter::GetInstance().GetIniFile().c_str(); + + if (*iniFile) + { + WCHAR buffer[32]; + const WCHAR* section = m_FolderPath.c_str(); + + if (setting != OPTION_ALL) + { + DialogManage::UpdateSkins(this); + } + + if (setting & OPTION_POSITION) + { + ScreenToWindow(); + + // If position needs to be save, do so. + if (m_SavePosition) + { + WritePrivateProfileString(section, L"WindowX", m_WindowX.c_str(), iniFile); + WritePrivateProfileString(section, L"WindowY", m_WindowY.c_str(), iniFile); + } + + if (setting == OPTION_POSITION) return; + } + + if (setting & OPTION_ALPHAVALUE) + { + _itow_s(m_AlphaValue, buffer, 10); + WritePrivateProfileString(section, L"AlphaValue", buffer, iniFile); + } + + if (setting & OPTION_FADEDURATION) + { + _itow_s(m_FadeDuration, buffer, 10); + WritePrivateProfileString(section, L"FadeDuration", buffer, iniFile); + } + + if (setting & OPTION_CLICKTHROUGH) + { + WritePrivateProfileString(section, L"ClickThrough", m_ClickThrough ? L"1" : L"0", iniFile); + } + + if (setting & OPTION_DRAGGABLE) + { + WritePrivateProfileString(section, L"Draggable", m_WindowDraggable ? L"1" : L"0", iniFile); + } + + if (setting & OPTION_HIDEONMOUSEOVER) + { + _itow_s(m_WindowHide, buffer, 10); + WritePrivateProfileString(section, L"HideOnMouseOver", buffer, iniFile); + } + + if (setting & OPTION_SAVEPOSITION) + { + WritePrivateProfileString(section, L"SavePosition", m_SavePosition ? L"1" : L"0", iniFile); + } + + if (setting & OPTION_SNAPEDGES) + { + WritePrivateProfileString(section, L"SnapEdges", m_SnapEdges ? L"1" : L"0", iniFile); + } + + if (setting & OPTION_KEEPONSCREEN) + { + WritePrivateProfileString(section, L"KeepOnScreen", m_KeepOnScreen ? L"1" : L"0", iniFile); + } + + if (setting & OPTION_AUTOSELECTSCREEN) + { + WritePrivateProfileString(section, L"AutoSelectScreen", m_AutoSelectScreen ? L"1" : L"0", iniFile); + } + + if (setting & OPTION_ALWAYSONTOP) + { + _itow_s(m_WindowZPosition, buffer, 10); + WritePrivateProfileString(section, L"AlwaysOnTop", buffer, iniFile); + } + + if (setting & OPTION_USED2D) + { + WritePrivateProfileString(section, L"UseD2D", m_UseD2D ? L"1" : L"0", iniFile); + } + } +} + +/* +** Reads the skin file and creates the meters and measures. +** +*/ +bool MeterWindow::ReadSkin() +{ + WCHAR buffer[128]; + + std::wstring iniFile = GetFilePath(); + + // Verify whether the file exists + if (_waccess(iniFile.c_str(), 0) == -1) + { + std::wstring message = GetFormattedString(ID_STR_UNABLETOREFRESHSKIN, m_FolderPath.c_str(), m_FileName.c_str()); + Rainmeter::GetInstance().ShowMessage(m_Window, message.c_str(), MB_OK | MB_ICONEXCLAMATION); + return false; + } + + std::wstring resourcePath = GetResourcesPath(); + bool hasResourcesFolder = (_waccess(resourcePath.c_str(), 0) == 0); + + // Read options from Rainmeter.ini. + ReadOptions(); + + m_Parser.Initialize(iniFile, this, nullptr, &resourcePath); + + m_Canvas = Gfx::Canvas::Create( + m_UseD2D && Rainmeter::GetInstance().GetUseD2D() ? Gfx::Renderer::PreferD2D : Gfx::Renderer::GDIP); + m_Canvas->SetAccurateText(m_Parser.ReadBool(L"Rainmeter", L"AccurateText", false)); + + // Gotta have some kind of buffer during initialization + CreateDoubleBuffer(1, 1); + + // Check the version + UINT appVersion = m_Parser.ReadUInt(L"Rainmeter", L"AppVersion", 0); + if (appVersion > RAINMETER_VERSION) + { + if (appVersion % 1000 != 0) + { + _snwprintf_s(buffer, _TRUNCATE, L"%u.%u.%u", appVersion / 1000000, (appVersion / 1000) % 1000, appVersion % 1000); + } + else + { + _snwprintf_s(buffer, _TRUNCATE, L"%u.%u", appVersion / 1000000, (appVersion / 1000) % 1000); + } + + std::wstring text = GetFormattedString(ID_STR_NEWVERSIONREQUIRED, m_FolderPath.c_str(), m_FileName.c_str(), buffer); + Rainmeter::GetInstance().ShowMessage(m_Window, text.c_str(), MB_OK | MB_ICONEXCLAMATION); + return false; + } + + // Initialize window variables + SetWindowPositionVariables(m_ScreenX, m_ScreenY); + SetWindowSizeVariables(0, 0); + + // Global settings + const std::wstring& group = m_Parser.ReadString(L"Rainmeter", L"Group", L""); + if (!group.empty()) + { + m_SkinGroup += L'|'; + m_SkinGroup += group; + } + InitializeGroup(m_SkinGroup); + + static const RECT defMargins = {0}; + m_BackgroundMargins = m_Parser.ReadRECT(L"Rainmeter", L"BackgroundMargins", defMargins); + m_DragMargins = m_Parser.ReadRECT(L"Rainmeter", L"DragMargins", defMargins); + + m_BackgroundMode = (BGMODE)m_Parser.ReadInt(L"Rainmeter", L"BackgroundMode", BGMODE_IMAGE); + m_SolidBevel = (BEVELTYPE)m_Parser.ReadInt(L"Rainmeter", L"BevelType", BEVELTYPE_NONE); + + m_SolidColor = m_Parser.ReadColor(L"Rainmeter", L"SolidColor", Color::Gray); + m_SolidColor2 = m_Parser.ReadColor(L"Rainmeter", L"SolidColor2", m_SolidColor.GetValue()); + m_SolidAngle = (Gdiplus::REAL)m_Parser.ReadFloat(L"Rainmeter", L"GradientAngle", 0.0); + + m_DynamicWindowSize = m_Parser.ReadBool(L"Rainmeter", L"DynamicWindowSize", false); + + if (m_BackgroundMode == BGMODE_IMAGE || m_BackgroundMode == BGMODE_SCALED_IMAGE || m_BackgroundMode == BGMODE_TILED_IMAGE) + { + m_BackgroundName = m_Parser.ReadString(L"Rainmeter", L"Background", L""); + if (!m_BackgroundName.empty()) + { + MakePathAbsolute(m_BackgroundName); + } + else + { + m_BackgroundMode = BGMODE_COPY; + } + } + + m_Mouse.ReadOptions(m_Parser, L"Rainmeter"); + + m_OnRefreshAction = m_Parser.ReadString(L"Rainmeter", L"OnRefreshAction", L"", false); + m_OnCloseAction = m_Parser.ReadString(L"Rainmeter", L"OnCloseAction", L"", false); + m_OnFocusAction = m_Parser.ReadString(L"Rainmeter", L"OnFocusAction", L"", false); + m_OnUnfocusAction = m_Parser.ReadString(L"Rainmeter", L"OnUnfocusAction", L"", false); + m_OnUpdateAction = m_Parser.ReadString(L"Rainmeter", L"OnUpdateAction", L"", false); + m_OnWakeAction = m_Parser.ReadString(L"Rainmeter", L"OnWakeAction", L"", false); + + m_WindowUpdate = m_Parser.ReadInt(L"Rainmeter", L"Update", INTERVAL_METER); + m_TransitionUpdate = m_Parser.ReadInt(L"Rainmeter", L"TransitionUpdate", INTERVAL_TRANSITION); + m_ToolTipHidden = m_Parser.ReadBool(L"Rainmeter", L"ToolTipHidden", false); + + if (IsWindowsVistaOrGreater()) + { + if (m_Parser.ReadBool(L"Rainmeter", L"Blur", false)) + { + const WCHAR* blurRegion = m_Parser.ReadString(L"Rainmeter", L"BlurRegion", L"", false).c_str(); + + if (*blurRegion) + { + m_BlurMode = BLURMODE_REGION; + m_BlurRegion = CreateRectRgn(0, 0, 0, 0); // Create empty region + int i = 1; + + do + { + ResizeBlur(blurRegion, RGN_OR); + + // Check for BlurRegion2, BlurRegion3, etc. + _snwprintf_s(buffer, _TRUNCATE, L"BlurRegion%i", ++i); + blurRegion = m_Parser.ReadString(L"Rainmeter", buffer, L"").c_str(); + } + while (*blurRegion); + } + else + { + m_BlurMode = BLURMODE_FULL; + } + } + else + { + m_BlurMode = BLURMODE_NONE; + } + } + + // Load fonts in Resources folder + if (hasResourcesFolder) + { + WIN32_FIND_DATA fd; + resourcePath += L"Fonts\\*"; + + HANDLE find = FindFirstFileEx( + resourcePath.c_str(), + (IsWindows7OrGreater()) ? FindExInfoBasic : FindExInfoStandard, + &fd, + FindExSearchNameMatch, + nullptr, + 0); + + if (find != INVALID_HANDLE_VALUE) + { + m_FontCollection = m_Canvas->CreateFontCollection(); + + do + { + if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + std::wstring file(resourcePath, 0, resourcePath.length() - 1); + file += fd.cFileName; + if (!m_FontCollection->AddFile(file.c_str())) + { + LogErrorF(this, L"Unable to load font: %s", file.c_str()); + } + } + } + while (FindNextFile(find, &fd)); + + FindClose(find); + } + } + + // Load local fonts + const WCHAR* localFont = m_Parser.ReadString(L"Rainmeter", L"LocalFont", L"").c_str(); + if (*localFont) + { + if (!m_FontCollection) + { + m_FontCollection = m_Canvas->CreateFontCollection(); + } + + int i = 1; + do + { + // Try program folder first + std::wstring szFontFile = Rainmeter::GetInstance().GetPath() + L"Fonts\\"; + szFontFile += localFont; + if (!m_FontCollection->AddFile(szFontFile.c_str())) + { + szFontFile = localFont; + MakePathAbsolute(szFontFile); + if (!m_FontCollection->AddFile(szFontFile.c_str())) + { + LogErrorF(this, L"Unable to load font: %s", localFont); + } + } + + // Check for LocalFont2, LocalFont3, etc. + _snwprintf_s(buffer, _TRUNCATE, L"LocalFont%i", ++i); + localFont = m_Parser.ReadString(L"Rainmeter", buffer, L"").c_str(); + } + while (*localFont); + } + + // Create all meters and measures. The meters and measures are not initialized in this loop + // to avoid errors caused by referencing nonexistent [sections] in the options. + m_HasNetMeasures = false; + m_HasButtons = false; + Meter* prevMeter = nullptr; + for (auto iter = m_Parser.GetSections().cbegin(); iter != m_Parser.GetSections().cend(); ++iter) + { + const WCHAR* section = (*iter).c_str(); + + if (_wcsicmp(L"Rainmeter", section) != 0 && + _wcsicmp(L"Variables", section) != 0 && + _wcsicmp(L"Metadata", section) != 0) + { + const std::wstring& measureName = m_Parser.ReadString(section, L"Measure", L"", false); + if (!measureName.empty()) + { + Measure* measure = Measure::Create(measureName.c_str(), this, section); + if (measure) + { + m_Measures.push_back(measure); + m_Parser.AddMeasure(measure); + + if (measure->GetTypeID() == TypeID()) + { + m_HasNetMeasures = true; + } + } + + continue; + } + + const std::wstring& meterName = m_Parser.ReadString(section, L"Meter", L"", false); + if (!meterName.empty()) + { + // It's a meter + Meter* meter = Meter::Create(meterName.c_str(), this, section); + if (meter) + { + m_Meters.push_back(meter); + meter->SetRelativeMeter(prevMeter); + + if (meter->GetTypeID() == TypeID()) + { + m_HasButtons = true; + } + + prevMeter = meter; + } + + continue; + } + } + } + + if (m_Meters.empty()) + { + std::wstring text = GetFormattedString(ID_STR_NOMETERSINSKIN, m_FolderPath.c_str(), m_FileName.c_str()); + Rainmeter::GetInstance().ShowMessage(m_Window, text.c_str(), MB_OK | MB_ICONEXCLAMATION); + return false; + } + + // Read measure options. This is done before the meters to ensure that e.g. Substitute is used + // when the meters get the value of the measure. The measures cannot be initialized yet as som + // measures (e.g. Script) except that the meters are ready when calling Initialize(). + for (auto iter = m_Measures.cbegin(); iter != m_Measures.cend(); ++iter) + { + Measure* measure = *iter; + measure->ReadOptions(m_Parser); + } + + // Initialize meters. + for (auto iter = m_Meters.cbegin(); iter != m_Meters.cend(); ++iter) + { + Meter* meter = *iter; + meter->ReadOptions(m_Parser); + meter->Initialize(); + + if (!meter->GetToolTipText().empty()) + { + meter->CreateToolTip(this); + } + } + + // Initialize measures. + for (auto iter = m_Measures.cbegin(); iter != m_Measures.cend(); ++iter) + { + Measure* measure = *iter; + measure->Initialize(); + } + + // Set window size (and CURRENTCONFIGWIDTH/HEIGHT) temporarily + for (auto iter = m_Meters.cbegin(); iter != m_Meters.cend(); ++iter) + { + bool bActiveTransition = true; // Do not track the change of ActiveTransition + UpdateMeter(*iter, bActiveTransition, true); + } + ResizeWindow(true); + + return true; +} + +/* +** Changes the size of the window and re-adjusts the background +*/ +bool MeterWindow::ResizeWindow(bool reset) +{ + int w = m_BackgroundMargins.left; + int h = m_BackgroundMargins.top; + + // Get the largest meter point + std::vector::const_iterator j = m_Meters.begin(); + for ( ; j != m_Meters.end(); ++j) + { + int mr = (*j)->GetX() + (*j)->GetW(); + w = max(w, mr); + int mb = (*j)->GetY() + (*j)->GetH(); + h = max(h, mb); + } + + w += m_BackgroundMargins.right; + h += m_BackgroundMargins.bottom; + + w = max(w, m_BackgroundSize.cx); + h = max(h, m_BackgroundSize.cy); + + if (!reset && m_WindowW == w && m_WindowH == h) + { + WindowToScreen(); + return false; // The window is already correct size + } + + // Reset size (this is calculated below) + + delete m_Background; + m_Background = nullptr; + + if ((m_BackgroundMode == BGMODE_IMAGE || m_BackgroundMode == BGMODE_SCALED_IMAGE || m_BackgroundMode == BGMODE_TILED_IMAGE) && !m_BackgroundName.empty()) + { + // Load the background + TintedImage* tintedBackground = new TintedImage(L"Background"); + tintedBackground->ReadOptions(m_Parser, L"Rainmeter"); + tintedBackground->LoadImage(m_BackgroundName, true); + + if (!tintedBackground->IsLoaded()) + { + m_BackgroundSize.cx = 0; + m_BackgroundSize.cy = 0; + + m_WindowW = 0; + m_WindowH = 0; + } + else + { + Bitmap* tempBackground = tintedBackground->GetImage(); + + // Calculate the window dimensions + m_BackgroundSize.cx = tempBackground->GetWidth(); + m_BackgroundSize.cy = tempBackground->GetHeight(); + + if (m_BackgroundMode == BGMODE_IMAGE) + { + w = m_BackgroundSize.cx; + h = m_BackgroundSize.cy; + } + else + { + w = max(w, m_BackgroundSize.cx); + h = max(h, m_BackgroundSize.cy); + } + + Bitmap* background = new Bitmap(w, h, PixelFormat32bppPARGB); + Graphics graphics(background); + + if (m_BackgroundMode == BGMODE_IMAGE) + { + Rect r(0, 0, w, h); + graphics.DrawImage(tempBackground, r, 0, 0, w, h, UnitPixel); + } + else + { + // Scale the background to fill the whole window + if (m_BackgroundMode == BGMODE_SCALED_IMAGE) + { + const RECT m = m_BackgroundMargins; + + if (m.top > 0) + { + if (m.left > 0) + { + // Top-Left + Rect r(0, 0, m.left, m.top); + graphics.DrawImage(tempBackground, r, 0, 0, m.left, m.top, UnitPixel); + } + + // Top + Rect r(m.left, 0, w - m.left - m.right, m.top); + graphics.DrawImage(tempBackground, r, m.left, 0, m_BackgroundSize.cx - m.left - m.right, m.top, UnitPixel); + + if (m.right > 0) + { + // Top-Right + Rect r(w - m.right, 0, m.right, m.top); + graphics.DrawImage(tempBackground, r, m_BackgroundSize.cx - m.right, 0, m.right, m.top, UnitPixel); + } + } + + if (m.left > 0) + { + // Left + Rect r(0, m.top, m.left, h - m.top - m.bottom); + graphics.DrawImage(tempBackground, r, 0, m.top, m.left, m_BackgroundSize.cy - m.top - m.bottom, UnitPixel); + } + + // Center + Rect r(m.left, m.top, w - m.left - m.right, h - m.top - m.bottom); + graphics.DrawImage(tempBackground, r, m.left, m.top, m_BackgroundSize.cx - m.left - m.right, m_BackgroundSize.cy - m.top - m.bottom, UnitPixel); + + if (m.right > 0) + { + // Right + Rect r(w - m.right, m.top, m.right, h - m.top - m.bottom); + graphics.DrawImage(tempBackground, r, m_BackgroundSize.cx - m.right, m.top, m.right, m_BackgroundSize.cy - m.top - m.bottom, UnitPixel); + } + + if (m.bottom > 0) + { + if (m.left > 0) + { + // Bottom-Left + Rect r(0, h - m.bottom, m.left, m.bottom); + graphics.DrawImage(tempBackground, r, 0, m_BackgroundSize.cy - m.bottom, m.left, m.bottom, UnitPixel); + } + + // Bottom + Rect r(m.left, h - m.bottom, w - m.left - m.right, m.bottom); + graphics.DrawImage(tempBackground, r, m.left, m_BackgroundSize.cy - m.bottom, m_BackgroundSize.cx - m.left - m.right, m.bottom, UnitPixel); + + if (m.right > 0) + { + // Bottom-Right + Rect r(w - m.right, h - m.bottom, m.right, m.bottom); + graphics.DrawImage(tempBackground, r, m_BackgroundSize.cx - m.right, m_BackgroundSize.cy - m.bottom, m.right, m.bottom, UnitPixel); + } + } + } + else + { + ImageAttributes imgAttr; + imgAttr.SetWrapMode(WrapModeTile); + + Rect r(0, 0, w, h); + graphics.DrawImage(tempBackground, r, 0, 0, w, h, UnitPixel, &imgAttr); + } + } + + m_Background = background; + + // Get the size form the background bitmap + m_WindowW = m_Background->GetWidth(); + m_WindowH = m_Background->GetHeight(); + + WindowToScreen(); + } + + delete tintedBackground; + } + else + { + m_WindowW = w; + m_WindowH = h; + WindowToScreen(); + } + + SetWindowSizeVariables(m_WindowW, m_WindowH); + + return true; +} + +/* +** Creates the back buffer bitmap. +** +*/ +void MeterWindow::CreateDoubleBuffer(int cx, int cy) +{ + m_Canvas->Resize(cx, cy); +} + +/* +** Redraws the meters and paints the window +** +*/ +void MeterWindow::Redraw() +{ + if (m_ResizeWindow) + { + ResizeWindow(m_ResizeWindow == RESIZEMODE_RESET); + SetResizeWindowMode(RESIZEMODE_NONE); + } + + // Create or clear the doublebuffer + { + int cx = m_WindowW; + int cy = m_WindowH; + + if (cx == 0 || cy == 0) + { + // Set dummy size to avoid invalid state + cx = 1; + cy = 1; + } + + if (cx != m_Canvas->GetW() || cy != m_Canvas->GetH()) + { + CreateDoubleBuffer(cx, cy); + } + } + + if (!m_Canvas->BeginDraw()) + { + return; + } + + m_Canvas->Clear(); + + if (m_WindowW != 0 && m_WindowH != 0) + { + if (m_Background) + { + const Rect dst(0, 0, m_WindowW, m_WindowH); + const Rect src(0, 0, m_Background->GetWidth(), m_Background->GetHeight()); + m_Canvas->DrawBitmap(m_Background, dst, src); + } + else if (m_BackgroundMode == BGMODE_SOLID) + { + // Draw the solid color background + Rect r(0, 0, m_WindowW, m_WindowH); + + if (m_SolidColor.GetA() != 0 || m_SolidColor2.GetA() != 0) + { + if (m_SolidColor.GetValue() == m_SolidColor2.GetValue()) + { + m_Canvas->Clear(m_SolidColor); + } + else + { + Gdiplus::Graphics& graphics = m_Canvas->BeginGdiplusContext(); + LinearGradientBrush gradient(r, m_SolidColor, m_SolidColor2, m_SolidAngle, TRUE); + graphics.FillRectangle(&gradient, r); + m_Canvas->EndGdiplusContext(); + } + } + + if (m_SolidBevel != BEVELTYPE_NONE) + { + Color lightColor(255, 255, 255, 255); + Color darkColor(255, 0, 0, 0); + + if (m_SolidBevel == BEVELTYPE_DOWN) + { + lightColor.SetValue(Color::MakeARGB(255, 0, 0, 0)); + darkColor.SetValue(Color::MakeARGB(255, 255, 255, 255)); + } + + Pen light(lightColor); + Pen dark(darkColor); + + Gdiplus::Graphics& graphics = m_Canvas->BeginGdiplusContext(); + Meter::DrawBevel(graphics, r, light, dark); + m_Canvas->EndGdiplusContext(); + } + } + + // Draw the meters + std::vector::const_iterator j = m_Meters.begin(); + for ( ; j != m_Meters.end(); ++j) + { + const Matrix* matrix = (*j)->GetTransformationMatrix(); + if (matrix && !matrix->IsIdentity()) + { + m_Canvas->SetTransform(*matrix); + (*j)->Draw(*m_Canvas); + m_Canvas->ResetTransform(); + } + else + { + (*j)->Draw(*m_Canvas); + } + } + } + + UpdateWindow(m_TransparencyValue, true); + + m_Canvas->EndDraw(); +} + +/* +** Updates the transition state +** +*/ +void MeterWindow::PostUpdate(bool bActiveTransition) +{ + // Start/stop the transition timer if necessary + if (bActiveTransition && !m_ActiveTransition) + { + SetTimer(m_Window, TIMER_TRANSITION, m_TransitionUpdate, nullptr); + m_ActiveTransition = true; + } + else if (m_ActiveTransition && !bActiveTransition) + { + KillTimer(m_Window, TIMER_TRANSITION); + m_ActiveTransition = false; + } +} + +/* +** Updates the given measure +** +*/ +bool MeterWindow::UpdateMeasure(Measure* measure, bool force) +{ + bool bUpdate = false; + + if (force) + { + measure->ResetUpdateCounter(); + } + + int updateDivider = measure->GetUpdateDivider(); + if (updateDivider >= 0 || force) + { + const bool rereadOptions = + measure->HasDynamicVariables() && (measure->GetUpdateCounter() + 1) >= updateDivider; + bUpdate = measure->Update(rereadOptions); + } + + return bUpdate; +} + +/* +** Updates the given meter +** +*/ +bool MeterWindow::UpdateMeter(Meter* meter, bool& bActiveTransition, bool force) +{ + bool bUpdate = false; + + if (force) + { + meter->ResetUpdateCounter(); + } + + int updateDivider = meter->GetUpdateDivider(); + if (updateDivider >= 0 || force) + { + if (meter->HasDynamicVariables() && + (meter->GetUpdateCounter() + 1) >= updateDivider) + { + meter->ReadOptions(m_Parser); + } + + bUpdate = meter->Update(); + } + + // Update tooltips + if (!meter->HasToolTip()) + { + if (!meter->GetToolTipText().empty()) + { + meter->CreateToolTip(this); + } + } + else + { + meter->UpdateToolTip(); + } + + // Check for transitions + if (!bActiveTransition && meter->HasActiveTransition()) + { + bActiveTransition = true; + } + + return bUpdate; +} + +/* +** Updates all the measures and redraws the meters +** +*/ +void MeterWindow::Update(bool refresh) +{ + ++m_UpdateCounter; + + if (!m_Measures.empty()) + { + // Pre-updates + if (m_HasNetMeasures) + { + MeasureNet::UpdateIFTable(); + MeasureNet::UpdateStats(); + } + + // Update all measures + std::vector::const_iterator i = m_Measures.begin(); + for ( ; i != m_Measures.end(); ++i) + { + if (UpdateMeasure((*i), refresh)) + { + (*i)->DoUpdateAction(); + (*i)->DoChangeAction(); + } + } + } + + DialogAbout::UpdateMeasures(this); + + // Update all meters + bool bActiveTransition = false; + bool bUpdate = false; + std::vector::const_iterator j = m_Meters.begin(); + for ( ; j != m_Meters.end(); ++j) + { + if (UpdateMeter((*j), bActiveTransition, refresh)) + { + bUpdate = true; + + (*j)->DoUpdateAction(); + } + } + + // Redraw all meters + if (bUpdate || m_ResizeWindow || refresh) + { + if (m_DynamicWindowSize) + { + // Resize the window + SetResizeWindowMode(RESIZEMODE_CHECK); + } + + // If our option is to disable when in an RDP session, then check if in an RDP session. + // Only redraw if we are not in a remote session + if (Rainmeter::GetInstance().IsRedrawable()) + { + Redraw(); + } + } + + // Post-updates + PostUpdate(bActiveTransition); + + if (!m_OnUpdateAction.empty()) + { + Rainmeter::GetInstance().ExecuteCommand(m_OnUpdateAction.c_str(), this); + } +} + +/* +** Updates the window contents +** +*/ +void MeterWindow::UpdateWindow(int alpha, bool canvasBeginDrawCalled) +{ + BLENDFUNCTION blendPixelFunction = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA}; + POINT ptWindowScreenPosition = {m_ScreenX, m_ScreenY}; + POINT ptSrc = {0, 0}; + SIZE szWindow = {m_Canvas->GetW(), m_Canvas->GetH()}; + + if (!canvasBeginDrawCalled) m_Canvas->BeginDraw(); + + HDC dcMemory = m_Canvas->GetDC(); + if (!UpdateLayeredWindow(m_Window, nullptr, &ptWindowScreenPosition, &szWindow, dcMemory, &ptSrc, 0, &blendPixelFunction, ULW_ALPHA)) + { + // Retry after resetting WS_EX_LAYERED flag. + RemoveWindowExStyle(WS_EX_LAYERED); + AddWindowExStyle(WS_EX_LAYERED); + UpdateLayeredWindow(m_Window, nullptr, &ptWindowScreenPosition, &szWindow, dcMemory, &ptSrc, 0, &blendPixelFunction, ULW_ALPHA); + } + m_Canvas->ReleaseDC(dcMemory); + + if (!canvasBeginDrawCalled) m_Canvas->EndDraw(); + + m_TransparencyValue = alpha; +} + +/* +** Updates the window transparency (using existing contents). +** +*/ +void MeterWindow::UpdateWindowTransparency(int alpha) +{ + BLENDFUNCTION blendPixelFunction = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA}; + UpdateLayeredWindow(m_Window, nullptr, nullptr, nullptr, nullptr, nullptr, 0, &blendPixelFunction, ULW_ALPHA); + m_TransparencyValue = alpha; +} + +/* +** Handles the timers. The METERTIMER updates all the measures +** MOUSETIMER is used to hide/show the window. +** +*/ +LRESULT MeterWindow::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (wParam) + { + case TIMER_METER: + Update(false); + break; + + case TIMER_MOUSE: + if (!Rainmeter::GetInstance().IsMenuActive() && !m_Dragging) + { + ShowWindowIfAppropriate(); + + if (m_WindowZPosition == ZPOSITION_ONTOPMOST) + { + ChangeZPos(ZPOSITION_ONTOPMOST); + } + + if (m_MouseOver) + { + POINT pos = System::GetCursorPosition(); + + if (!m_ClickThrough) + { + if (WindowFromPoint(pos) == m_Window) + { + SetMouseLeaveEvent(false); + } + else + { + // Run all mouse leave actions + OnMouseLeave(m_WindowDraggable ? WM_NCMOUSELEAVE : WM_MOUSELEAVE, 0, 0); + } + } + else + { + bool keyDown = IsCtrlKeyDown() || IsShiftKeyDown() || IsAltKeyDown(); + + if (!keyDown || GetWindowFromPoint(pos) != m_Window) + { + // Run all mouse leave actions + OnMouseLeave(m_WindowDraggable ? WM_NCMOUSELEAVE : WM_MOUSELEAVE, 0, 0); + } + } + } + } + break; + + case TIMER_TRANSITION: + { + // Redraw only if there is active transition still going + bool bActiveTransition = false; + std::vector::const_iterator j = m_Meters.begin(); + for ( ; j != m_Meters.end(); ++j) + { + if ((*j)->HasActiveTransition()) + { + bActiveTransition = true; + break; + } + } + + if (bActiveTransition) + { + Redraw(); + } + else + { + // Stop the transition timer + KillTimer(m_Window, TIMER_TRANSITION); + m_ActiveTransition = false; + } + } + break; + + case TIMER_FADE: + { + ULONGLONG ticks = System::GetTickCount64(); + if (m_FadeStartTime == 0) + { + m_FadeStartTime = ticks; + } + + if (ticks - m_FadeStartTime > (ULONGLONG)m_FadeDuration) + { + KillTimer(m_Window, TIMER_FADE); + m_FadeStartTime = 0; + if (m_FadeEndValue == 0) + { + ShowWindow(m_Window, SW_HIDE); + } + else + { + UpdateWindowTransparency(m_FadeEndValue); + } + } + else + { + double value = (double)(__int64)(ticks - m_FadeStartTime); + value /= m_FadeDuration; + value *= m_FadeEndValue - m_FadeStartValue; + value += m_FadeStartValue; + value = min(value, 255); + value = max(value, 0); + + UpdateWindowTransparency((int)value); + } + } + break; + + case TIMER_DEACTIVATE: + if (m_FadeStartTime == 0) + { + KillTimer(m_Window, TIMER_DEACTIVATE); + Rainmeter::GetInstance().RemoveUnmanagedMeterWindow(this); + delete this; + } + break; + } + + return 0; +} + +void MeterWindow::FadeWindow(int from, int to) +{ + if (m_FadeDuration == 0) + { + if (to == 0) + { + ShowWindow(m_Window, SW_HIDE); + } + else + { + if (m_FadeDuration == 0) + { + UpdateWindowTransparency(to); + } + if (from == 0) + { + if (!m_Hidden) + { + ShowWindow(m_Window, SW_SHOWNOACTIVATE); + } + } + } + } + else + { + m_FadeStartValue = from; + m_FadeEndValue = to; + UpdateWindowTransparency(from); + if (from == 0) + { + if (!m_Hidden) + { + ShowWindow(m_Window, SW_SHOWNOACTIVATE); + } + } + + SetTimer(m_Window, TIMER_FADE, INTERVAL_FADE, nullptr); + } +} + +void MeterWindow::HideFade() +{ + m_Hidden = true; + if (IsWindowVisible(m_Window)) + { + FadeWindow(m_AlphaValue, 0); + } +} + +void MeterWindow::ShowFade() +{ + m_Hidden = false; + if (!IsWindowVisible(m_Window)) + { + FadeWindow(0, (m_WindowHide == HIDEMODE_FADEOUT) ? 255 : m_AlphaValue); + } +} + +/* +** Show the window if it is temporarily hidden. +** +*/ +void MeterWindow::ShowWindowIfAppropriate() +{ + bool keyDown = IsCtrlKeyDown() || IsShiftKeyDown() || IsAltKeyDown(); + + POINT pos = System::GetCursorPosition(); + POINT posScr = pos; + + MapWindowPoints(nullptr, m_Window, &pos, 1); + bool inside = HitTest(pos.x, pos.y); + + if (inside) + { + inside = (GetWindowFromPoint(posScr) == m_Window); + } + + if (m_ClickThrough) + { + if (!inside || keyDown) + { + // If Alt, shift or control is down, remove the transparent flag + RemoveWindowExStyle(WS_EX_TRANSPARENT); + } + } + + if (m_WindowHide) + { + if (!m_Hidden && !inside && !keyDown) + { + switch (m_WindowHide) + { + case HIDEMODE_HIDE: + if (m_TransparencyValue == 0 || !IsWindowVisible(m_Window)) + { + ShowWindow(m_Window, SW_SHOWNOACTIVATE); + FadeWindow(0, m_AlphaValue); + } + break; + + case HIDEMODE_FADEIN: + if (m_AlphaValue != 255 && m_TransparencyValue == 255) + { + FadeWindow(255, m_AlphaValue); + } + break; + + case HIDEMODE_FADEOUT: + if (m_AlphaValue != 255 && m_TransparencyValue == m_AlphaValue) + { + FadeWindow(m_AlphaValue, 255); + } + break; + } + } + } + else + { + if (!m_Hidden) + { + if (m_TransparencyValue == 0 || !IsWindowVisible(m_Window)) + { + ShowWindow(m_Window, SW_SHOWNOACTIVATE); + FadeWindow(0, m_AlphaValue); + } + } + } +} + +/* +** Retrieves a handle to the window that contains the specified point. +** +*/ +HWND MeterWindow::GetWindowFromPoint(POINT pos) +{ + HWND hwndPos = WindowFromPoint(pos); + + if (hwndPos == m_Window || (!m_ClickThrough && m_WindowHide != HIDEMODE_HIDE)) + { + return hwndPos; + } + + MapWindowPoints(nullptr, m_Window, &pos, 1); + + if (HitTest(pos.x, pos.y)) + { + if (hwndPos) + { + HWND hWnd = GetAncestor(hwndPos, GA_ROOT); + while (hWnd = FindWindowEx(nullptr, hWnd, METERWINDOW_CLASS_NAME, nullptr)) + { + if (hWnd == m_Window) + { + return hwndPos; + } + } + } + return m_Window; + } + + return hwndPos; +} + +/* +** Checks if the given point is inside the window. +** +*/ +bool MeterWindow::HitTest(int x, int y) +{ + return m_Canvas->IsTransparentPixel(x, y); +} + +/* +** Handles all buttons and cursor. +** +*/ +void MeterWindow::HandleButtons(POINT pos, BUTTONPROC proc, bool execute) +{ + bool redraw = false; + HCURSOR cursor = nullptr; + + std::vector::const_reverse_iterator j = m_Meters.rbegin(); + for ( ; j != m_Meters.rend(); ++j) + { + // Hidden meters are ignored + if ((*j)->IsHidden()) continue; + + MeterButton* button = nullptr; + if (m_HasButtons && (*j)->GetTypeID() == TypeID()) + { + button = (MeterButton*)(*j); + if (button) + { + switch (proc) + { + case BUTTONPROC_DOWN: + redraw |= button->MouseDown(pos); + break; + + case BUTTONPROC_UP: + redraw |= button->MouseUp(pos, execute); + break; + + case BUTTONPROC_MOVE: + default: + redraw |= button->MouseMove(pos); + break; + } + } + } + + // Get cursor if required + if (!cursor && (*j)->GetMouse().GetCursorState()) + { + if ((*j)->HasMouseAction()) + { + if ((*j)->HitTest(pos.x, pos.y)) + { + cursor = (*j)->GetMouse().GetCursor(); + } + } + else + { + // Special case for Button meter: reacts only on valid pixel in button image + if (button && button->HitTest2(pos.x, pos.y)) + { + cursor = (*j)->GetMouse().GetCursor(); + } + } + } + } + + if (redraw) + { + Redraw(); + } + + if (!cursor) + { + cursor = LoadCursor(nullptr, IDC_ARROW); + } + + SetCursor(cursor); +} + +/* +** During setting the cursor do nothing. +** +*/ +LRESULT MeterWindow::OnSetCursor(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return 0; +} + +/* +** Enters context menu loop. +** +*/ +LRESULT MeterWindow::OnEnterMenuLoop(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + // Set cursor to default + SetCursor(LoadCursor(nullptr, IDC_ARROW)); + + return 0; +} + +/* +** When we get WM_MOUSEMOVE messages, hide the window as the mouse is over it. +** +*/ +LRESULT MeterWindow::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + bool keyDown = IsCtrlKeyDown() || IsShiftKeyDown() || IsAltKeyDown(); + + if (!keyDown) + { + if (m_ClickThrough) + { + AddWindowExStyle(WS_EX_TRANSPARENT); + } + + if (!m_Hidden) + { + // If Alt, shift or control is down, do not hide the window + switch (m_WindowHide) + { + case HIDEMODE_HIDE: + if (m_TransparencyValue == m_AlphaValue) + { + FadeWindow(m_AlphaValue, 0); + } + break; + + case HIDEMODE_FADEIN: + if (m_AlphaValue != 255 && m_TransparencyValue == m_AlphaValue) + { + FadeWindow(m_AlphaValue, 255); + } + break; + + case HIDEMODE_FADEOUT: + if (m_AlphaValue != 255 && m_TransparencyValue == 255) + { + FadeWindow(255, m_AlphaValue); + } + break; + } + } + } + + if (!m_ClickThrough || keyDown) + { + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + if (uMsg == WM_NCMOUSEMOVE) + { + // Map to local window + MapWindowPoints(nullptr, m_Window, &pos, 1); + } + + ++m_MouseMoveCounter; + + while (DoMoveAction(pos.x, pos.y, MOUSE_LEAVE)) ; + while (DoMoveAction(pos.x, pos.y, MOUSE_OVER)) ; + + // Handle buttons + HandleButtons(pos, BUTTONPROC_MOVE); + } + + return 0; +} + +/* +** When we get WM_MOUSELEAVE messages, run all leave actions. +** +*/ +LRESULT MeterWindow::OnMouseLeave(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pos = System::GetCursorPosition(); + HWND hWnd = WindowFromPoint(pos); + if (!hWnd || (hWnd != m_Window && GetParent(hWnd) != m_Window)) // ignore tooltips + { + ++m_MouseMoveCounter; + + POINT pos = {SHRT_MIN, SHRT_MIN}; + while (DoMoveAction(pos.x, pos.y, MOUSE_LEAVE)) ; // Leave all forcibly + + // Handle buttons + HandleButtons(pos, BUTTONPROC_MOVE); + } + + return 0; +} + +/* +** When we get WM_MOUSEWHEEL messages. +** +*/ +LRESULT MeterWindow::OnMouseScrollMove(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_MOUSEWHEEL) // If sent through WM_INPUT, uMsg is WM_INPUT. + { + // Fix for Notepad++, which sends WM_MOUSEWHEEL to unfocused windows. + if (m_Window != GetFocus()) + { + return 0; + } + } + + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + MapWindowPoints(nullptr, m_Window, &pos, 1); + + // Handle buttons + HandleButtons(pos, BUTTONPROC_MOVE); + + const int delta = GET_WHEEL_DELTA_WPARAM(wParam); + DoAction(pos.x, pos.y, (delta < 0) ? MOUSE_MW_DOWN : MOUSE_MW_UP, false); + + return 0; +} + +/* +** When we get WM_MOUSEHWHEEL messages. +** +*/ +LRESULT MeterWindow::OnMouseHScrollMove(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + MapWindowPoints(nullptr, m_Window, &pos, 1); + + // Handle buttons + HandleButtons(pos, BUTTONPROC_MOVE); + + const int delta = GET_WHEEL_DELTA_WPARAM(wParam); + DoAction(pos.x, pos.y, (delta < 0) ? MOUSE_MW_LEFT : MOUSE_MW_RIGHT, false); + + return 0; +} + +/* +** Handle the menu commands. +** +*/ +LRESULT MeterWindow::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (wParam) + { + case IDM_SKIN_EDITSKIN: + Rainmeter::GetInstance().EditSkinFile(m_FolderPath, m_FileName); + break; + + case IDM_SKIN_REFRESH: + Refresh(false); + break; + + case IDM_SKIN_OPENSKINSFOLDER: + Rainmeter::GetInstance().OpenSkinFolder(m_FolderPath); + break; + + case IDM_SKIN_MANAGESKIN: + DialogManage::OpenSkin(this); + break; + + case IDM_SKIN_VERYTOPMOST: + SetWindowZPosition(ZPOSITION_ONTOPMOST); + break; + + case IDM_SKIN_TOPMOST: + SetWindowZPosition(ZPOSITION_ONTOP); + break; + + case IDM_SKIN_BOTTOM: + SetWindowZPosition(ZPOSITION_ONBOTTOM); + break; + + case IDM_SKIN_NORMAL: + SetWindowZPosition(ZPOSITION_NORMAL); + break; + + case IDM_SKIN_ONDESKTOP: + SetWindowZPosition(ZPOSITION_ONDESKTOP); + break; + + case IDM_SKIN_KEEPONSCREEN: + SetKeepOnScreen(!m_KeepOnScreen); + break; + + case IDM_SKIN_USED2D: + SetUseD2D(!m_UseD2D); + break; + + case IDM_SKIN_CLICKTHROUGH: + SetClickThrough(!m_ClickThrough); + break; + + case IDM_SKIN_DRAGGABLE: + SetWindowDraggable(!m_WindowDraggable); + break; + + case IDM_SKIN_HIDEONMOUSE: + SetWindowHide((m_WindowHide == HIDEMODE_NONE) ? HIDEMODE_HIDE : HIDEMODE_NONE); + break; + + case IDM_SKIN_TRANSPARENCY_FADEIN: + SetWindowHide((m_WindowHide == HIDEMODE_NONE) ? HIDEMODE_FADEIN : HIDEMODE_NONE); + break; + + case IDM_SKIN_TRANSPARENCY_FADEOUT: + SetWindowHide((m_WindowHide == HIDEMODE_NONE) ? HIDEMODE_FADEOUT : HIDEMODE_NONE); + break; + + case IDM_SKIN_REMEMBERPOSITION: + SetSavePosition(!m_SavePosition); + break; + + case IDM_SKIN_SNAPTOEDGES: + SetSnapEdges(!m_SnapEdges); + break; + + case IDM_CLOSESKIN: + if (m_State != STATE_CLOSING) + { + Rainmeter::GetInstance().DeactivateSkin(this, -1); + } + break; + + case IDM_SKIN_FROMRIGHT: + m_WindowXFromRight = !m_WindowXFromRight; + + SavePositionIfAppropriate(); + break; + + case IDM_SKIN_FROMBOTTOM: + m_WindowYFromBottom = !m_WindowYFromBottom; + + SavePositionIfAppropriate(); + break; + + case IDM_SKIN_XPERCENTAGE: + m_WindowXPercentage = !m_WindowXPercentage; + + SavePositionIfAppropriate(); + break; + + case IDM_SKIN_YPERCENTAGE: + m_WindowYPercentage = !m_WindowYPercentage; + + SavePositionIfAppropriate(); + break; + + case IDM_SKIN_MONITOR_AUTOSELECT: + m_AutoSelectScreen = !m_AutoSelectScreen; + + WriteOptions(OPTION_POSITION | OPTION_AUTOSELECTSCREEN); + break; + + default: + if (wParam >= IDM_SKIN_TRANSPARENCY_0 && wParam <= IDM_SKIN_TRANSPARENCY_90) + { + m_AlphaValue = (int)(255.0 - (wParam - IDM_SKIN_TRANSPARENCY_0) * (230.0 / (IDM_SKIN_TRANSPARENCY_90 - IDM_SKIN_TRANSPARENCY_0))); + UpdateWindowTransparency(m_AlphaValue); + WriteOptions(OPTION_ALPHAVALUE); + } + else if (wParam == IDM_SKIN_MONITOR_PRIMARY || wParam >= ID_MONITOR_FIRST && wParam <= ID_MONITOR_LAST) + { + const int numOfMonitors = (int)System::GetMonitorCount(); + const MultiMonitorInfo& monitorsInfo = System::GetMultiMonitorInfo(); + const std::vector& monitors = monitorsInfo.monitors; + + int screenIndex; + bool screenDefined; + if (wParam == IDM_SKIN_MONITOR_PRIMARY) + { + screenIndex = monitorsInfo.primary; + screenDefined = false; + } + else + { + screenIndex = (wParam & 0x0ffff) - ID_MONITOR_FIRST; + screenDefined = true; + } + + if (screenIndex >= 0 && (screenIndex == 0 || screenIndex <= numOfMonitors && monitors[screenIndex - 1].active)) + { + m_AutoSelectScreen = false; + + m_WindowXScreen = m_WindowYScreen = screenIndex; + m_WindowXScreenDefined = m_WindowYScreenDefined = screenDefined; + + m_Parser.ResetMonitorVariables(this); // Set present monitor variables + WriteOptions(OPTION_POSITION | OPTION_AUTOSELECTSCREEN); + } + } + else if (wParam >= IDM_SKIN_CUSTOMCONTEXTMENU_FIRST && wParam <= IDM_SKIN_CUSTOMCONTEXTMENU_LAST) + { + std::wstring action; + + int position = (int)wParam - IDM_SKIN_CUSTOMCONTEXTMENU_FIRST + 1; + if (position == 1) + { + action = m_Parser.ReadString(L"Rainmeter", L"ContextAction", L"", false); + } + else + { + WCHAR buffer[128]; + + _snwprintf_s(buffer, _TRUNCATE, L"ContextAction%i", position); + action = m_Parser.ReadString(L"Rainmeter", buffer, L"", false); + } + + if (!action.empty()) + { + Rainmeter::GetInstance().ExecuteCommand(action.c_str(), this); + } + } + else + { + // Forward to tray window, which handles all the other commands + HWND tray = Rainmeter::GetInstance().GetTrayWindow()->GetWindow(); + + if (wParam == IDM_QUIT) + { + PostMessage(tray, WM_COMMAND, wParam, lParam); + } + else + { + SendMessage(tray, WM_COMMAND, wParam, lParam); + } + } + break; + } + + return 0; +} + +/* +** Helper function for setting ClickThrough +** +*/ +void MeterWindow::SetClickThrough(bool b) +{ + m_ClickThrough = b; + WriteOptions(OPTION_CLICKTHROUGH); + + if (!m_ClickThrough) + { + // Remove transparent flag + RemoveWindowExStyle(WS_EX_TRANSPARENT); + } + + if (m_MouseOver) + { + SetMouseLeaveEvent(m_ClickThrough); + } +} + +/* +** Helper function for setting KeepOnScreen +** +*/ +void MeterWindow::SetKeepOnScreen(bool b) +{ + m_KeepOnScreen = b; + WriteOptions(OPTION_KEEPONSCREEN); + + if (m_KeepOnScreen) + { + int x = m_ScreenX; + int y = m_ScreenY; + + MapCoordsToScreen(x, y, m_WindowW, m_WindowH); + + if (x != m_ScreenX || y != m_ScreenY) + { + MoveWindow(x, y); + } + } +} + +/* +** Helper function for setting UseD2D +** +*/ +void MeterWindow::SetUseD2D(bool b) +{ + m_UseD2D = b; + WriteOptions(OPTION_USED2D); + Refresh(false); +} + +/* +** Helper function for setting WindowDraggable +** +*/ +void MeterWindow::SetWindowDraggable(bool b) +{ + m_WindowDraggable = b; + WriteOptions(OPTION_DRAGGABLE); +} + +/* +** Helper function for setting SavePosition +** +*/ +void MeterWindow::SetSavePosition(bool b) +{ + m_SavePosition = b; + WriteOptions(OPTION_POSITION | OPTION_SAVEPOSITION); +} + +/* +** Helper function for setting SavePosition +** +*/ +void MeterWindow::SavePositionIfAppropriate() +{ + if (m_SavePosition) + { + WriteOptions(OPTION_POSITION); + } + else + { + ScreenToWindow(); + DialogManage::UpdateSkins(this); + } +} + +/* +** Helper function for setting SnapEdges +** +*/ +void MeterWindow::SetSnapEdges(bool b) +{ + m_SnapEdges = b; + WriteOptions(OPTION_SNAPEDGES); +} + +/* +** Helper function for setting WindowHide +** +*/ +void MeterWindow::SetWindowHide(HIDEMODE hide) +{ + m_WindowHide = hide; + UpdateWindowTransparency(m_AlphaValue); + WriteOptions(OPTION_HIDEONMOUSEOVER); +} + +/* +** Helper function for setting Position +** +*/ +void MeterWindow::SetWindowZPosition(ZPOSITION zpos) +{ + ChangeSingleZPos(zpos); + WriteOptions(OPTION_ALWAYSONTOP); +} + +/* +** Handle dragging the window +** +*/ +LRESULT MeterWindow::OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if ((wParam & 0xFFF0) != SC_MOVE) + { + return DefWindowProc(m_Window, uMsg, wParam, lParam); + } + + // --- SC_MOVE --- + + // Prepare the dragging flags + m_Dragging = true; + m_Dragged = false; + + // Run the DefWindowProc so the dragging works + LRESULT result = DefWindowProc(m_Window, uMsg, wParam, lParam); + + if (m_Dragged) + { + SavePositionIfAppropriate(); + + POINT pos = System::GetCursorPosition(); + MapWindowPoints(nullptr, m_Window, &pos, 1); + + // Handle buttons + HandleButtons(pos, BUTTONPROC_UP, false); // redraw only + } + else // not dragged + { + if ((wParam & 0x000F) == 2) // triggered by mouse + { + // Post the WM_NCLBUTTONUP message so the LeftMouseUpAction works + PostMessage(m_Window, WM_NCLBUTTONUP, (WPARAM)HTCAPTION, lParam); + } + } + + // Clear the dragging flags + m_Dragging = false; + m_Dragged = false; + + return result; +} + +/* +** Starts dragging +** +*/ +LRESULT MeterWindow::OnEnterSizeMove(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (m_Dragging) + { + m_Dragged = true; // Don't post the WM_NCLBUTTONUP message! + + // Set cursor to default + SetCursor(LoadCursor(nullptr, IDC_ARROW)); + } + + return 0; +} + +/* +** Ends dragging +** +*/ +LRESULT MeterWindow::OnExitSizeMove(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return 0; +} + +/* +** This is overwritten so that the window can be dragged +** +*/ +LRESULT MeterWindow::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (m_WindowDraggable && !Rainmeter::GetInstance().GetDisableDragging()) + { + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + MapWindowPoints(nullptr, m_Window, &pos, 1); + + int x1 = m_DragMargins.left; + if (x1 < 0) x1 += m_WindowW; + + int x2 = m_WindowW - m_DragMargins.right; + if (x2 > m_WindowW) x2 -= m_WindowW; + + if (pos.x >= x1 && pos.x < x2) + { + int y1 = m_DragMargins.top; + if (y1 < 0) y1 += m_WindowH; + + int y2 = m_WindowH - m_DragMargins.bottom; + if (y2 > m_WindowH) y2 -= m_WindowH; + + if (pos.y >= y1 && pos.y < y2) + { + return HTCAPTION; + } + } + } + return HTCLIENT; +} + +/* +** Called when windows position is about to change +** +*/ +LRESULT MeterWindow::OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + LPWINDOWPOS wp = (LPWINDOWPOS)lParam; + + if (m_State != STATE_REFRESHING) + { + if (m_WindowZPosition == ZPOSITION_NORMAL && Rainmeter::GetInstance().IsNormalStayDesktop() && System::GetShowDesktop()) + { + if (!(wp->flags & (SWP_NOOWNERZORDER | SWP_NOACTIVATE))) + { + // Set window on top of all other ZPOSITION_ONDESKTOP, ZPOSITION_BOTTOM, and ZPOSITION_NORMAL windows + wp->hwndInsertAfter = System::GetBackmostTopWindow(); + } + } + else if (m_WindowZPosition == ZPOSITION_ONDESKTOP || m_WindowZPosition == ZPOSITION_ONBOTTOM) + { + // Do not change the z-order. This keeps the window on bottom. + wp->flags |= SWP_NOZORDER; + } + } + + if ((wp->flags & SWP_NOMOVE) == 0) + { + if (m_SnapEdges && !(IsCtrlKeyDown() || IsShiftKeyDown())) + { + // only process movement (ignore anything without winpos values) + if (wp->cx != 0 && wp->cy != 0) + { + // Search display monitor that has the largest area of intersection with the window + const size_t numOfMonitors = System::GetMonitorCount(); // intentional + const std::vector& monitors = System::GetMultiMonitorInfo().monitors; + + const RECT windowRect = {wp->x, wp->y, wp->x + (m_WindowW ? m_WindowW : 1), wp->y + (m_WindowH ? m_WindowH : 1)}; + const RECT* workArea = nullptr; + + size_t maxSize = 0; + for (auto iter = monitors.cbegin(); iter != monitors.cend(); ++iter) + { + RECT r; + if ((*iter).active && IntersectRect(&r, &windowRect, &(*iter).screen)) + { + size_t size = (r.right - r.left) * (r.bottom - r.top); + if (size > maxSize) + { + workArea = &(*iter).work; + maxSize = size; + } + } + } + + // Snap to other windows + for (auto iter = Rainmeter::GetInstance().GetAllMeterWindows().cbegin(); iter != Rainmeter::GetInstance().GetAllMeterWindows().cend(); ++iter) + { + if ((*iter).second != this) + { + SnapToWindow((*iter).second, wp); + } + } + + // Snap to work area if window is on the appropriate screen + if (workArea) + { + int w = workArea->right - m_WindowW; + int h = workArea->bottom - m_WindowH; + + if ((wp->x < SNAPDISTANCE + workArea->left) && (wp->x > workArea->left - SNAPDISTANCE)) wp->x = workArea->left; + if ((wp->y < SNAPDISTANCE + workArea->top) && (wp->y > workArea->top - SNAPDISTANCE)) wp->y = workArea->top; + if ((wp->x < SNAPDISTANCE + w) && (wp->x > -SNAPDISTANCE + w)) wp->x = w; + if ((wp->y < SNAPDISTANCE + h) && (wp->y > -SNAPDISTANCE + h)) wp->y = h; + } + } + } + + if (m_KeepOnScreen) + { + MapCoordsToScreen(wp->x, wp->y, m_WindowW, m_WindowH); + } + } + + return 0; +} + +void MeterWindow::SnapToWindow(MeterWindow* window, LPWINDOWPOS wp) +{ + int x = window->m_ScreenX; + int y = window->m_ScreenY; + int w = window->m_WindowW; + int h = window->m_WindowH; + + if (wp->y < y + h && wp->y + m_WindowH > y) + { + if ((wp->x < SNAPDISTANCE + x) && (wp->x > x - SNAPDISTANCE)) wp->x = x; + if ((wp->x < SNAPDISTANCE + x + w) && (wp->x > x + w - SNAPDISTANCE)) wp->x = x + w; + + if ((wp->x + m_WindowW < SNAPDISTANCE + x) && (wp->x + m_WindowW > x - SNAPDISTANCE)) wp->x = x - m_WindowW; + if ((wp->x + m_WindowW < SNAPDISTANCE + x + w) && (wp->x + m_WindowW > x + w - SNAPDISTANCE)) wp->x = x + w - m_WindowW; + } + + if (wp->x < x + w && wp->x + m_WindowW > x) + { + if ((wp->y < SNAPDISTANCE + y) && (wp->y > y - SNAPDISTANCE)) wp->y = y; + if ((wp->y < SNAPDISTANCE + y + h) && (wp->y > y + h - SNAPDISTANCE)) wp->y = y + h; + + if ((wp->y + m_WindowH < SNAPDISTANCE + y) && (wp->y + m_WindowH > y - SNAPDISTANCE)) wp->y = y - m_WindowH; + if ((wp->y + m_WindowH < SNAPDISTANCE + y + h) && (wp->y + m_WindowH > y + h - SNAPDISTANCE)) wp->y = y + h - m_WindowH; + } +} + +/* +** Disables blur when Aero transparency is disabled +** +*/ +LRESULT MeterWindow::OnDwmColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (m_BlurMode != BLURMODE_NONE && IsBlur() && c_DwmGetColorizationColor && c_DwmEnableBlurBehindWindow) + { + DWORD color; + BOOL opaque; + if (c_DwmGetColorizationColor(&color, &opaque) != S_OK) + { + opaque = TRUE; + } + + BlurBehindWindow(!opaque); + } + + return 0; +} + +/* +** Disables blur when desktop composition is disabled +** +*/ +LRESULT MeterWindow::OnDwmCompositionChange(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (m_BlurMode != BLURMODE_NONE && IsBlur() && c_DwmIsCompositionEnabled && c_DwmEnableBlurBehindWindow) + { + BOOL enabled; + if (c_DwmIsCompositionEnabled(&enabled) != S_OK) + { + enabled = FALSE; + } + + BlurBehindWindow(enabled); + } + + return 0; +} + +/* +** Adds the blur region to the window +** +*/ +void MeterWindow::BlurBehindWindow(BOOL fEnable) +{ + if (c_DwmEnableBlurBehindWindow) + { + DWM_BLURBEHIND bb = {0}; + bb.fEnable = fEnable; + + if (fEnable) + { + // Restore blur with whatever the region was prior to disabling + bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; + bb.hRgnBlur = m_BlurRegion; + c_DwmEnableBlurBehindWindow(m_Window, &bb); + } + else + { + // Disable blur + bb.dwFlags = DWM_BB_ENABLE; + c_DwmEnableBlurBehindWindow(m_Window, &bb); + } + } +} + +/* +** During resolution changes do nothing. +** (OnDelayedMove function is used instead.) +** +*/ +LRESULT MeterWindow::OnDisplayChange(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return 0; +} + +/* +** During setting changes do nothing. +** (OnDelayedMove function is used instead.) +** +*/ +LRESULT MeterWindow::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return 0; +} + +/* +** Runs the action when left mouse button is down +** +*/ +LRESULT MeterWindow::OnLeftButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + if (uMsg == WM_NCLBUTTONDOWN) + { + // Transform the point to client rect + MapWindowPoints(nullptr, m_Window, &pos, 1); + } + + // Handle buttons + HandleButtons(pos, BUTTONPROC_DOWN); + + if (IsCtrlKeyDown() || // Ctrl is pressed, so only run default action + (!DoAction(pos.x, pos.y, MOUSE_LMB_DOWN, false) && m_WindowDraggable)) + { + // Cancel the mouse event beforehand + SetMouseLeaveEvent(true); + + // Run the DefWindowProc so the dragging works + return DefWindowProc(m_Window, uMsg, wParam, lParam); + } + + return 0; +} + +/* +** Runs the action when left mouse button is up +** +*/ +LRESULT MeterWindow::OnLeftButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + if (uMsg == WM_NCLBUTTONUP) + { + // Transform the point to client rect + MapWindowPoints(nullptr, m_Window, &pos, 1); + } + + // Handle buttons + HandleButtons(pos, BUTTONPROC_UP); + + DoAction(pos.x, pos.y, MOUSE_LMB_UP, false); + + return 0; +} + +/* +** Runs the action when left mouse button is double-clicked +** +*/ +LRESULT MeterWindow::OnLeftButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + if (uMsg == WM_NCLBUTTONDBLCLK) + { + // Transform the point to client rect + MapWindowPoints(nullptr, m_Window, &pos, 1); + } + + // Handle buttons + HandleButtons(pos, BUTTONPROC_DOWN); + + if (!DoAction(pos.x, pos.y, MOUSE_LMB_DBLCLK, false)) + { + DoAction(pos.x, pos.y, MOUSE_LMB_DOWN, false); + } + + return 0; +} + +/* +** Runs the action when right mouse button is down +** +*/ +LRESULT MeterWindow::OnRightButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + if (uMsg == WM_NCRBUTTONDOWN) + { + // Transform the point to client rect + MapWindowPoints(nullptr, m_Window, &pos, 1); + } + + // Handle buttons + HandleButtons(pos, BUTTONPROC_MOVE); + + DoAction(pos.x, pos.y, MOUSE_RMB_DOWN, false); + + return 0; +} + +/* +** Runs the action when right mouse button is up +** +*/ +LRESULT MeterWindow::OnRightButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + // Handle buttons + HandleButtons(pos, BUTTONPROC_MOVE); + + if (IsCtrlKeyDown() || // Ctrl is pressed, so only run default action + !DoAction(pos.x, pos.y, MOUSE_RMB_UP, false)) + { + // Run the DefWindowProc so the context menu works + return DefWindowProc(m_Window, WM_RBUTTONUP, wParam, lParam); + } + + return 0; +} + +/* +** Runs the action when right mouse button is double-clicked +** +*/ +LRESULT MeterWindow::OnRightButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + if (uMsg == WM_NCRBUTTONDBLCLK) + { + // Transform the point to client rect + MapWindowPoints(nullptr, m_Window, &pos, 1); + } + + // Handle buttons + HandleButtons(pos, BUTTONPROC_MOVE); + + if (!DoAction(pos.x, pos.y, MOUSE_RMB_DBLCLK, false)) + { + DoAction(pos.x, pos.y, MOUSE_RMB_DOWN, false); + } + + return 0; +} + +/* +** Runs the action when middle mouse button is down +** +*/ +LRESULT MeterWindow::OnMiddleButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + if (uMsg == WM_NCMBUTTONDOWN) + { + // Transform the point to client rect + MapWindowPoints(nullptr, m_Window, &pos, 1); + } + + // Handle buttons + HandleButtons(pos, BUTTONPROC_MOVE); + + DoAction(pos.x, pos.y, MOUSE_MMB_DOWN, false); + + return 0; +} + +/* +** Runs the action when middle mouse button is up +** +*/ +LRESULT MeterWindow::OnMiddleButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + if (uMsg == WM_NCMBUTTONUP) + { + // Transform the point to client rect + MapWindowPoints(nullptr, m_Window, &pos, 1); + } + + // Handle buttons + HandleButtons(pos, BUTTONPROC_MOVE); + + DoAction(pos.x, pos.y, MOUSE_MMB_UP, false); + + return 0; +} + +/* +** Runs the action when middle mouse button is double-clicked +** +*/ +LRESULT MeterWindow::OnMiddleButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + if (uMsg == WM_NCMBUTTONDBLCLK) + { + // Transform the point to client rect + MapWindowPoints(nullptr, m_Window, &pos, 1); + } + + // Handle buttons + HandleButtons(pos, BUTTONPROC_MOVE); + + if (!DoAction(pos.x, pos.y, MOUSE_MMB_DBLCLK, false)) + { + DoAction(pos.x, pos.y, MOUSE_MMB_DOWN, false); + } + + return 0; +} + +/* +** Runs the action when a X mouse button is down +** +*/ +LRESULT MeterWindow::OnXButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + if (uMsg == WM_NCXBUTTONDOWN) + { + // Transform the point to client rect + MapWindowPoints(nullptr, m_Window, &pos, 1); + } + + // Handle buttons + HandleButtons(pos, BUTTONPROC_MOVE); + + if (GET_XBUTTON_WPARAM (wParam) == XBUTTON1) + { + DoAction(pos.x, pos.y, MOUSE_X1MB_DOWN, false); + } + else if (GET_XBUTTON_WPARAM (wParam) == XBUTTON2) + { + DoAction(pos.x, pos.y, MOUSE_X2MB_DOWN, false); + } + + return 0; +} + +/* +** Runs the action when a X mouse button is up +** +*/ +LRESULT MeterWindow::OnXButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + if (uMsg == WM_NCXBUTTONUP) + { + // Transform the point to client rect + MapWindowPoints(nullptr, m_Window, &pos, 1); + } + + // Handle buttons + HandleButtons(pos, BUTTONPROC_MOVE); + + if (GET_XBUTTON_WPARAM (wParam) == XBUTTON1) + { + DoAction(pos.x, pos.y, MOUSE_X1MB_UP, false); + } + else if (GET_XBUTTON_WPARAM (wParam) == XBUTTON2) + { + DoAction(pos.x, pos.y, MOUSE_X2MB_UP, false); + } + + return 0; +} + +/* +** Runs the action when a X mouse button is double-clicked +** +*/ +LRESULT MeterWindow::OnXButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pos; + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + if (uMsg == WM_NCXBUTTONDBLCLK) + { + // Transform the point to client rect + MapWindowPoints(nullptr, m_Window, &pos, 1); + } + + // Handle buttons + HandleButtons(pos, BUTTONPROC_MOVE); + + if (GET_XBUTTON_WPARAM (wParam) == XBUTTON1 && + !DoAction(pos.x, pos.y, MOUSE_X1MB_DBLCLK, false)) + { + DoAction(pos.x, pos.y, MOUSE_X1MB_DOWN, false); + } + else if (GET_XBUTTON_WPARAM (wParam) == XBUTTON2 && + !DoAction(pos.x, pos.y, MOUSE_X2MB_DBLCLK, false)) + { + DoAction(pos.x, pos.y, MOUSE_X2MB_DOWN, false); + } + + return 0; +} + +/* +** Runs the action when the MeterWindow gets or loses focus +** +*/ +LRESULT MeterWindow::OnSetWindowFocus(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_SETFOCUS: + if (!m_OnFocusAction.empty()) + { + Rainmeter::GetInstance().ExecuteCommand(m_OnFocusAction.c_str(), this); + } + break; + + case WM_KILLFOCUS: + if (!m_OnUnfocusAction.empty()) + { + Rainmeter::GetInstance().ExecuteCommand(m_OnUnfocusAction.c_str(), this); + } + break; + } + + return 0; +} + +/* +** Handles the context menu. The menu is recreated every time it is shown. +** +*/ +LRESULT MeterWindow::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + POINT pos; + RECT rect; + GetWindowRect(m_Window, &rect); + + if ((lParam & 0xFFFFFFFF) == 0xFFFFFFFF) // WM_CONTEXTMENU is generated from the keyboard (Shift+F10/VK_APPS) + { + // Set menu position to (0,0) on the window + pos.x = rect.left; + pos.y = rect.top; + } + else + { + pos.x = GET_X_LPARAM(lParam); + pos.y = GET_Y_LPARAM(lParam); + + // Transform the point to client rect + POINT posc = {pos.x - rect.left, pos.y - rect.top}; + + // Handle buttons + HandleButtons(posc, BUTTONPROC_MOVE); + + // If RMB up or RMB down or double-click cause actions, do not show the menu! + if (!IsCtrlKeyDown() && // Ctrl is pressed, so ignore any actions + (DoAction(posc.x, posc.y, MOUSE_RMB_UP, false) || DoAction(posc.x, posc.y, MOUSE_RMB_DOWN, true) || DoAction(posc.x, posc.y, MOUSE_RMB_DBLCLK, true))) + { + return 0; + } + } + + Rainmeter::GetInstance().ShowContextMenu(pos, this); + + return 0; +} + +/* +** Executes the action if such are defined. Returns true, if action was executed. +** If the test is true, the action is not executed. +** +*/ +bool MeterWindow::DoAction(int x, int y, MOUSEACTION action, bool test) +{ + std::wstring command; + + // Check if the hitpoint was over some meter + std::vector::const_reverse_iterator j = m_Meters.rbegin(); + for ( ; j != m_Meters.rend(); ++j) + { + // Hidden meters are ignored + if ((*j)->IsHidden()) continue; + + const Mouse& mouse = (*j)->GetMouse(); + if (mouse.HasActionCommand(action) && (*j)->HitTest(x, y)) + { + command = mouse.GetActionCommand(action); + break; + } + } + + if (command.empty()) + { + if (m_Mouse.HasActionCommand(action) && HitTest(x, y)) + { + command = m_Mouse.GetActionCommand(action); + } + } + + if (!command.empty()) + { + if (!test) + { + Rainmeter::GetInstance().ExecuteCommand(command.c_str(), this); + } + + return true; + } + + return false; +} + +/* +** Executes the action if such are defined. Returns true, if meter/window which should be processed still may exist. +** +*/ +bool MeterWindow::DoMoveAction(int x, int y, MOUSEACTION action) +{ + bool buttonFound = false; + + // Check if the hitpoint was over some meter + std::vector::const_reverse_iterator j = m_Meters.rbegin(); + for ( ; j != m_Meters.rend(); ++j) + { + if (!(*j)->IsHidden() && (*j)->HitTest(x, y)) + { + if (action == MOUSE_OVER) + { + if (!m_MouseOver) + { + // If the mouse is over a meter it's also over the main window + //LogDebugF(L"@Enter: %s", m_FolderPath.c_str()); + m_MouseOver = true; + SetMouseLeaveEvent(false); + RegisterMouseInput(); + + if (!m_Mouse.GetOverAction().empty()) + { + UINT currCounter = m_MouseMoveCounter; + Rainmeter::GetInstance().ExecuteCommand(m_Mouse.GetOverAction().c_str(), this); + return (currCounter == m_MouseMoveCounter); + } + } + + // Handle button + MeterButton* button = nullptr; + if (m_HasButtons && (*j)->GetTypeID() == TypeID()) + { + button = (MeterButton*)(*j); + if (button) + { + if (!buttonFound) + { + button->SetFocus(true); + buttonFound = true; + } + else + { + button->SetFocus(false); + } + } + } + + if (!(*j)->IsMouseOver()) + { + const Mouse& mouse = (*j)->GetMouse(); + if (!mouse.GetOverAction().empty() || + !mouse.GetLeaveAction().empty() || + button) + { + //LogDebugF(L"MeterEnter: %s - [%s]", m_FolderPath.c_str(), (*j)->GetName()); + (*j)->SetMouseOver(true); + + if (!mouse.GetOverAction().empty()) + { + UINT currCounter = m_MouseMoveCounter; + Rainmeter::GetInstance().ExecuteCommand(mouse.GetOverAction().c_str(), this); + return (currCounter == m_MouseMoveCounter); + } + } + } + } + } + else + { + if (action == MOUSE_LEAVE) + { + if ((*j)->IsMouseOver()) + { + // Handle button + if (m_HasButtons && (*j)->GetTypeID() == TypeID()) + { + MeterButton* button = (MeterButton*)(*j); + button->SetFocus(false); + } + + //LogDebugF(L"MeterLeave: %s - [%s]", m_FolderPath.c_str(), (*j)->GetName()); + (*j)->SetMouseOver(false); + + const Mouse& mouse = (*j)->GetMouse(); + if (!mouse.GetLeaveAction().empty()) + { + Rainmeter::GetInstance().ExecuteCommand(mouse.GetLeaveAction().c_str(), this); + return true; + } + } + } + } + } + + if (HitTest(x, y)) + { + // If no meters caused actions, do the default actions + if (action == MOUSE_OVER) + { + if (!m_MouseOver) + { + //LogDebugF(L"Enter: %s", m_FolderPath.c_str()); + m_MouseOver = true; + SetMouseLeaveEvent(false); + RegisterMouseInput(); + + if (!m_Mouse.GetOverAction().empty()) + { + UINT currCounter = m_MouseMoveCounter; + Rainmeter::GetInstance().ExecuteCommand(m_Mouse.GetOverAction().c_str(), this); + return (currCounter == m_MouseMoveCounter); + } + } + } + } + else + { + if (action == MOUSE_LEAVE) + { + // Mouse leave happens when the mouse is outside the window + if (m_MouseOver) + { + //LogDebugF(L"Leave: %s", m_FolderPath.c_str()); + m_MouseOver = false; + SetMouseLeaveEvent(true); + UnregisterMouseInput(); + + if (!m_Mouse.GetLeaveAction().empty()) + { + Rainmeter::GetInstance().ExecuteCommand(m_Mouse.GetLeaveAction().c_str(), this); + return true; + } + } + } + } + + return false; +} + +/* +** Sends mouse wheel messages to the window if the window does not have focus. +** +*/ +LRESULT MeterWindow::OnMouseInput(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + const POINT pos = System::GetCursorPosition(); + + // Only process for unfocused skin window. + if (m_Window == WindowFromPoint(pos) && m_Window != GetFocus()) + { + RAWINPUT ri; + UINT riSize = sizeof(ri); + const UINT dataSize = GetRawInputData( + (HRAWINPUT)lParam, RID_INPUT, &ri, &riSize, sizeof(RAWINPUTHEADER)); + if (dataSize != (UINT)-1 && + ri.header.dwType == RIM_TYPEMOUSE) + { + const WPARAM wheelDelta = MAKEWPARAM(0, HIWORD((short)ri.data.mouse.usButtonData)); + const LPARAM wheelPos = MAKELPARAM(pos.x, pos.y); + if (ri.data.mouse.usButtonFlags == RI_MOUSE_WHEEL) + { + OnMouseScrollMove(WM_INPUT, wheelDelta, wheelPos); + } + else if (ri.data.mouse.usButtonFlags == RI_MOUSE_HORIZONTAL_WHEEL) + { + OnMouseHScrollMove(WM_MOUSEHWHEEL, wheelDelta, wheelPos); + } + } + } + + // DefWindowProc must be called after processing WM_INPUT. + DefWindowProc(m_Window, uMsg, wParam, lParam); + return 0; +} + +/* +** Stores the new place of the window, in screen coordinates. +** +*/ +LRESULT MeterWindow::OnMove(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + // The lParam's x/y parameters are given in screen coordinates for overlapped and pop-up windows + // and in parent-client coordinates for child windows. + + // Store the new window position + m_ScreenX = GET_X_LPARAM(lParam); + m_ScreenY = GET_Y_LPARAM(lParam); + + SetWindowPositionVariables(m_ScreenX, m_ScreenY); + + if (m_Dragging) + { + ScreenToWindow(); + } + + return 0; +} + +/* +** Performs an action when returning from sleep +** +*/ +LRESULT MeterWindow::OnWake(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (wParam == PBT_APMRESUMEAUTOMATIC && !m_OnWakeAction.empty()) + { + Rainmeter::GetInstance().ExecuteCommand(m_OnWakeAction.c_str(), this); + } + + return 0; +} + +/* +** The main window procedure for the meter window. +** +*/ +LRESULT CALLBACK MeterWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + MeterWindow* window = (MeterWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + BEGIN_MESSAGEPROC + MESSAGE(OnMouseInput, WM_INPUT) + MESSAGE(OnMove, WM_MOVE) + MESSAGE(OnTimer, WM_TIMER) + MESSAGE(OnCommand, WM_COMMAND) + MESSAGE(OnSysCommand, WM_SYSCOMMAND) + MESSAGE(OnEnterSizeMove, WM_ENTERSIZEMOVE) + MESSAGE(OnExitSizeMove, WM_EXITSIZEMOVE) + MESSAGE(OnNcHitTest, WM_NCHITTEST) + MESSAGE(OnSetCursor, WM_SETCURSOR) + MESSAGE(OnEnterMenuLoop, WM_ENTERMENULOOP) + MESSAGE(OnMouseMove, WM_MOUSEMOVE) + MESSAGE(OnMouseMove, WM_NCMOUSEMOVE) + MESSAGE(OnMouseLeave, WM_MOUSELEAVE) + MESSAGE(OnMouseLeave, WM_NCMOUSELEAVE) + MESSAGE(OnMouseScrollMove, WM_MOUSEWHEEL) + MESSAGE(OnMouseHScrollMove, WM_MOUSEHWHEEL) + MESSAGE(OnContextMenu, WM_CONTEXTMENU) + MESSAGE(OnRightButtonDown, WM_NCRBUTTONDOWN) + MESSAGE(OnRightButtonDown, WM_RBUTTONDOWN) + MESSAGE(OnRightButtonUp, WM_RBUTTONUP) + MESSAGE(OnContextMenu, WM_NCRBUTTONUP) + MESSAGE(OnRightButtonDoubleClick, WM_RBUTTONDBLCLK) + MESSAGE(OnRightButtonDoubleClick, WM_NCRBUTTONDBLCLK) + MESSAGE(OnLeftButtonDown, WM_NCLBUTTONDOWN) + MESSAGE(OnLeftButtonDown, WM_LBUTTONDOWN) + MESSAGE(OnLeftButtonUp, WM_LBUTTONUP) + MESSAGE(OnLeftButtonUp, WM_NCLBUTTONUP) + MESSAGE(OnLeftButtonDoubleClick, WM_LBUTTONDBLCLK) + MESSAGE(OnLeftButtonDoubleClick, WM_NCLBUTTONDBLCLK) + MESSAGE(OnMiddleButtonDown, WM_NCMBUTTONDOWN) + MESSAGE(OnMiddleButtonDown, WM_MBUTTONDOWN) + MESSAGE(OnMiddleButtonUp, WM_MBUTTONUP) + MESSAGE(OnMiddleButtonUp, WM_NCMBUTTONUP) + MESSAGE(OnMiddleButtonDoubleClick, WM_MBUTTONDBLCLK) + MESSAGE(OnMiddleButtonDoubleClick, WM_NCMBUTTONDBLCLK) + MESSAGE(OnXButtonDown, WM_XBUTTONDOWN); + MESSAGE(OnXButtonDown, WM_NCXBUTTONDOWN); + MESSAGE(OnXButtonUp, WM_XBUTTONUP); + MESSAGE(OnXButtonUp, WM_NCXBUTTONUP); + MESSAGE(OnXButtonDoubleClick, WM_XBUTTONDBLCLK); + MESSAGE(OnXButtonDoubleClick, WM_NCXBUTTONDBLCLK); + MESSAGE(OnWindowPosChanging, WM_WINDOWPOSCHANGING) + MESSAGE(OnCopyData, WM_COPYDATA) + MESSAGE(OnDelayedRefresh, WM_METERWINDOW_DELAYED_REFRESH) + MESSAGE(OnDelayedMove, WM_METERWINDOW_DELAYED_MOVE) + MESSAGE(OnDwmColorChange, WM_DWMCOLORIZATIONCOLORCHANGED) + MESSAGE(OnDwmCompositionChange, WM_DWMCOMPOSITIONCHANGED) + MESSAGE(OnSettingChange, WM_SETTINGCHANGE) + MESSAGE(OnDisplayChange, WM_DISPLAYCHANGE) + MESSAGE(OnSetWindowFocus, WM_SETFOCUS) + MESSAGE(OnSetWindowFocus, WM_KILLFOCUS) + MESSAGE(OnWake, WM_POWERBROADCAST) + END_MESSAGEPROC +} + +/* +** The initial window procedure for the meter window. Passes control to WndProc after initial setup. +** +*/ +LRESULT CALLBACK MeterWindow::InitialWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_NCCREATE) + { + MeterWindow* window = (MeterWindow*)((LPCREATESTRUCT)lParam)->lpCreateParams; + SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)window); + + // Change the window procedure over to MainWndProc now that GWLP_USERDATA is set + SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)WndProc); + return TRUE; + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + +/* +** Handles delayed refresh +** +*/ +LRESULT MeterWindow::OnDelayedRefresh(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + Refresh(false); + return 0; +} + +/* +** Handles delayed move. +** Do not save the position in this handler for the sake of preventing move by temporal resolution/workarea change. +** +*/ +LRESULT MeterWindow::OnDelayedMove(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + m_Parser.ResetMonitorVariables(this); + + // Move the window temporarily + ResizeWindow(false); + SetWindowPos(m_Window, nullptr, m_ScreenX, m_ScreenY, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); + + return 0; +} + +/* +** Handles bangs from the exe +** +*/ +LRESULT MeterWindow::OnCopyData(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + COPYDATASTRUCT* pCopyDataStruct = (COPYDATASTRUCT*)lParam; + + if (pCopyDataStruct && (pCopyDataStruct->dwData == 1) && (pCopyDataStruct->cbData > 0)) + { + if (Rainmeter::GetInstance().HasMeterWindow(this)) + { + const WCHAR* command = (const WCHAR*)pCopyDataStruct->lpData; + Rainmeter::GetInstance().ExecuteCommand(command, this); + } + else + { + // This meterwindow has been deactivated + LogWarning(L"Unable to bang unloaded skin"); + } + + return TRUE; + } + + return FALSE; +} + +/* +** Sets up the window position variables. +** +*/ +void MeterWindow::SetWindowPositionVariables(int x, int y) +{ + WCHAR buffer[32]; + + _itow_s(x, buffer, 10); + m_Parser.SetBuiltInVariable(L"CURRENTCONFIGX", buffer); + _itow_s(y, buffer, 10); + m_Parser.SetBuiltInVariable(L"CURRENTCONFIGY", buffer); +} + +/* +** Sets up the window size variables. +** +*/ +void MeterWindow::SetWindowSizeVariables(int w, int h) +{ + WCHAR buffer[32]; + + _itow_s(w, buffer, 10); + m_Parser.SetBuiltInVariable(L"CURRENTCONFIGWIDTH", buffer); + _itow_s(h, buffer, 10); + m_Parser.SetBuiltInVariable(L"CURRENTCONFIGHEIGHT", buffer); +} + +/* +** Converts the path to absolute by adding the skin's path to it (unless it already is absolute). +** +*/ +void MeterWindow::MakePathAbsolute(std::wstring& path) +{ + if (path.empty() || PathUtil::IsAbsolute(path)) + { + return; // It's already absolute path (or it's empty) + } + else + { + std::wstring absolute; + absolute.reserve(Rainmeter::GetInstance().GetSkinPath().size() + m_FolderPath.size() + 1 + path.size()); + absolute = Rainmeter::GetInstance().GetSkinPath(); + absolute += m_FolderPath; + absolute += L'\\'; + absolute += path; + absolute.swap(path); + } +} + +std::wstring MeterWindow::GetFilePath() +{ + std::wstring file = Rainmeter::GetInstance().GetSkinPath() + m_FolderPath; + file += L'\\'; + file += m_FileName; + return file; +} + +std::wstring MeterWindow::GetRootName() +{ + std::wstring::size_type loc; + if ((loc = m_FolderPath.find_first_of(L'\\')) != std::wstring::npos) + { + return m_FolderPath.substr(0, loc); + } + + return m_FolderPath; +} + +std::wstring MeterWindow::GetRootPath() +{ + std::wstring path = Rainmeter::GetInstance().GetSkinPath(); + + std::wstring::size_type loc; + if ((loc = m_FolderPath.find_first_of(L'\\')) != std::wstring::npos) + { + path.append(m_FolderPath, 0, loc + 1); + } + else + { + path += m_FolderPath; + path += L'\\'; + } + + return path; +} + +std::wstring MeterWindow::GetResourcesPath() +{ + std::wstring path = GetRootPath(); + path += L"@Resources\\"; + return path; +} + +std::wstring MeterWindow::GetSkinPath() +{ + std::wstring path; + if (!m_FolderPath.empty()) + { + path += m_FolderPath; + path += L"\\"; + } + + path += m_FileName; + return path; +} + +Meter* MeterWindow::GetMeter(const std::wstring& meterName) +{ + const WCHAR* name = meterName.c_str(); + std::vector::const_iterator j = m_Meters.begin(); + for ( ; j != m_Meters.end(); ++j) + { + if (_wcsicmp((*j)->GetName(), name) == 0) + { + return (*j); + } + } + return nullptr; +} diff --git a/Library/MeterWindow.h b/Library/MeterWindow.h index 0ba924e2..ce8a58ba 100644 --- a/Library/MeterWindow.h +++ b/Library/MeterWindow.h @@ -1,438 +1,438 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __METERWINDOW_H__ -#define __METERWINDOW_H__ - -#include -#include -#include -#include -#include "CommandHandler.h" -#include "ConfigParser.h" -#include "Group.h" -#include "Mouse.h" - -#define BEGIN_MESSAGEPROC switch (uMsg) { -#define MESSAGE(handler, msg) case msg: return window->handler(uMsg, wParam, lParam); -#define REJECT_MESSAGE(msg) case msg: return 0; -#define END_MESSAGEPROC } return DefWindowProc(hWnd, uMsg, wParam, lParam); - -#define WM_METERWINDOW_DELAYED_REFRESH WM_APP + 1 -#define WM_METERWINDOW_DELAYED_MOVE WM_APP + 3 - -#define METERWINDOW_CLASS_NAME L"RainmeterMeterWindow" - -#define RI_MOUSE_HORIZONTAL_WHEEL 0x0800 - -enum BUTTONPROC -{ - BUTTONPROC_DOWN, - BUTTONPROC_UP, - BUTTONPROC_MOVE -}; - -enum ZPOSITION -{ - ZPOSITION_ONDESKTOP = -2, - ZPOSITION_ONBOTTOM = -1, - ZPOSITION_NORMAL = 0, - ZPOSITION_ONTOP = 1, - ZPOSITION_ONTOPMOST = 2 -}; - -enum BLURMODE -{ - BLURMODE_NONE = 0, - BLURMODE_FULL, - BLURMODE_REGION -}; - -enum BGMODE -{ - BGMODE_IMAGE = 0, - BGMODE_COPY, - BGMODE_SOLID, - BGMODE_SCALED_IMAGE, - BGMODE_TILED_IMAGE -}; - -enum HIDEMODE -{ - HIDEMODE_NONE = 0, - HIDEMODE_HIDE, - HIDEMODE_FADEIN, - HIDEMODE_FADEOUT -}; - -enum BEVELTYPE -{ - BEVELTYPE_NONE, - BEVELTYPE_UP, - BEVELTYPE_DOWN -}; - -enum RESIZEMODE -{ - RESIZEMODE_NONE = 0, - RESIZEMODE_CHECK, - RESIZEMODE_RESET -}; - -class Rainmeter; -class Measure; -class Meter; - -namespace Gfx { -class Canvas; -class FontCollection; -class TextFormat; -} - -class MeterWindow : public Group -{ -public: - MeterWindow(const std::wstring& folderPath, const std::wstring& file); - ~MeterWindow(); - - MeterWindow(const MeterWindow& other) = delete; - MeterWindow& operator=(MeterWindow other) = delete; - - void Initialize(); - - void DoBang(Bang bang, const std::vector& args); - - void HideMeter(const std::wstring& name, bool group = false); - void ShowMeter(const std::wstring& name, bool group = false); - void ToggleMeter(const std::wstring& name, bool group = false); - void MoveMeter(const std::wstring& name, int x, int y); - void UpdateMeter(const std::wstring& name, bool group = false); - void DisableMeasure(const std::wstring& name, bool group = false); - void EnableMeasure(const std::wstring& name, bool group = false); - void ToggleMeasure(const std::wstring& name, bool group = false); - void PauseMeasure(const std::wstring& name, bool group = false); - void UnpauseMeasure(const std::wstring& name, bool group = false); - void TogglePauseMeasure(const std::wstring& name, bool group = false); - void UpdateMeasure(const std::wstring& name, bool group = false); - void Deactivate(); - void Refresh(bool init, bool all = false); - void Redraw(); - void RedrawWindow() { UpdateWindow(m_TransparencyValue); } - void SetVariable(const std::wstring& variable, const std::wstring& value); - void SetOption(const std::wstring& section, const std::wstring& option, const std::wstring& value, bool group); - - void SetMouseLeaveEvent(bool cancel); - void SetHasMouseScrollAction() { m_HasMouseScrollAction = true; } - - void MoveWindow(int x, int y); - void ChangeZPos(ZPOSITION zPos, bool all = false); - void ChangeSingleZPos(ZPOSITION zPos, bool all = false); - void FadeWindow(int from, int to); - void HideFade(); - void ShowFade(); - - void ResizeBlur(const std::wstring& arg, int mode); - bool IsBlur() { return m_Blur; } - void SetBlur(bool b) { m_Blur = b; } - - void SetResizeWindowMode(RESIZEMODE mode) { if (m_ResizeWindow != RESIZEMODE_RESET || mode != RESIZEMODE_CHECK) m_ResizeWindow = mode; } - - Gfx::Canvas& GetCanvas() { return *m_Canvas; } - HWND GetWindow() { return m_Window; } - - ConfigParser& GetParser() { return m_Parser; } - - const std::wstring& GetFolderPath() { return m_FolderPath; } - const std::wstring& GetFileName() { return m_FileName; } - std::wstring GetFilePath(); - std::wstring GetRootName(); - std::wstring GetRootPath(); - std::wstring GetResourcesPath(); - std::wstring GetSkinPath(); - - const std::vector& GetMeasures() { return m_Measures; } - const std::vector& GetMeters() { return m_Meters; } - - ZPOSITION GetWindowZPosition() { return m_WindowZPosition; } - bool GetXPercentage() { return m_WindowXPercentage; } - bool GetYPercentage() { return m_WindowYPercentage; } - bool GetXFromRight() { return m_WindowXFromRight; } - bool GetYFromBottom() { return m_WindowYFromBottom; } - - int GetW() { return m_WindowW; } - int GetH() { return m_WindowH; } - int GetX() { return m_ScreenX; } - int GetY() { return m_ScreenY; } - - bool GetXScreenDefined() { return m_WindowXScreenDefined; } - bool GetYScreenDefined() { return m_WindowYScreenDefined; } - int GetXScreen() { return m_WindowXScreen; } - int GetYScreen() { return m_WindowYScreen; } - - bool GetClickThrough() { return m_ClickThrough; } - bool GetKeepOnScreen() { return m_KeepOnScreen; } - bool GetUseD2D() { return m_UseD2D; } - bool GetAutoSelectScreen() { return m_AutoSelectScreen; } - bool GetWindowDraggable() { return m_WindowDraggable; } - bool GetSavePosition() { return m_SavePosition; } - bool GetSnapEdges() { return m_SnapEdges; } - HIDEMODE GetWindowHide() { return m_WindowHide; } - int GetAlphaValue() { return m_AlphaValue; } - int GetUpdateCounter() { return m_UpdateCounter; } - int GetTransitionUpdate() { return m_TransitionUpdate; } - - bool GetMeterToolTipHidden() { return m_ToolTipHidden; } - - bool IsClosing() { return m_State == STATE_CLOSING; } - - const Mouse& GetMouse() { return m_Mouse; } - - void MakePathAbsolute(std::wstring& path); - - Gfx::FontCollection* GetFontCollection() { return m_FontCollection; } - - Meter* GetMeter(const std::wstring& meterName); - Measure* GetMeasure(const std::wstring& measureName) { return m_Parser.GetMeasure(measureName); } - - friend class DialogManage; - -protected: - static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - static LRESULT CALLBACK InitialWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - - LRESULT OnMouseInput(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnMove(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnEnterSizeMove(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnExitSizeMove(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnSetCursor(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnEnterMenuLoop(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnMouseLeave(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnMouseScrollMove(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnMouseHScrollMove(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnLeftButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnRightButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnMiddleButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnLeftButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnRightButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnMiddleButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnLeftButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnRightButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnMiddleButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnXButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnXButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnXButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnDelayedRefresh(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnDelayedMove(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnCopyData(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnDwmColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnDwmCompositionChange(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnDisplayChange(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnSetWindowFocus(UINT uMsg, WPARAM wParam, LPARAM lParam); - LRESULT OnWake(UINT uMsg, WPARAM wParam, LPARAM lParam); - -private: - enum STATE - { - STATE_INITIALIZING, - STATE_REFRESHING, - STATE_RUNNING, - STATE_CLOSING - }; - - enum OPTION - { - OPTION_POSITION = 0x00000001, - OPTION_ALPHAVALUE = 0x00000002, - OPTION_FADEDURATION = 0x00000004, - OPTION_CLICKTHROUGH = 0x00000008, - OPTION_DRAGGABLE = 0x00000010, - OPTION_HIDEONMOUSEOVER = 0x00000020, - OPTION_SAVEPOSITION = 0x00000040, - OPTION_SNAPEDGES = 0x00000080, - OPTION_KEEPONSCREEN = 0x00000100, - OPTION_AUTOSELECTSCREEN = 0x00000200, - OPTION_ALWAYSONTOP = 0x00000400, - OPTION_USED2D = 0x00000800, - - OPTION_ALL = 0xFFFFFFFF - }; - - bool HitTest(int x, int y); - - void SnapToWindow(MeterWindow* window, LPWINDOWPOS wp); - void MapCoordsToScreen(int& x, int& y, int w, int h); - void WindowToScreen(); - void ScreenToWindow(); - void PostUpdate(bool bActiveTransition); - bool UpdateMeasure(Measure* measure, bool force); - bool UpdateMeter(Meter* meter, bool& bActiveTransition, bool force); - void Update(bool refresh); - void UpdateWindow(int alpha, bool canvasBeginDrawCalled = false); - void UpdateWindowTransparency(int alpha); - void ReadOptions(); - void WriteOptions(INT setting = OPTION_ALL); - bool ReadSkin(); - void ShowWindowIfAppropriate(); - HWND GetWindowFromPoint(POINT pos); - void HandleButtons(POINT pos, BUTTONPROC proc, bool execute = true); - void SetClickThrough(bool b); - void SetKeepOnScreen(bool b); - void SetUseD2D(bool b); - void SetWindowDraggable(bool b); - void SetSavePosition(bool b); - void SavePositionIfAppropriate(); - void SetSnapEdges(bool b); - void SetWindowHide(HIDEMODE hide); - void SetWindowZPosition(ZPOSITION zpos); - bool DoAction(int x, int y, MOUSEACTION action, bool test); - bool DoMoveAction(int x, int y, MOUSEACTION action); - bool ResizeWindow(bool reset); - void IgnoreAeroPeek(); - void RegisterMouseInput(); - void UnregisterMouseInput(); - void AddWindowExStyle(LONG_PTR flag); - void RemoveWindowExStyle(LONG_PTR flag); - void BlurBehindWindow(BOOL fEnable); - void SetWindowPositionVariables(int x, int y); - void SetWindowSizeVariables(int w, int h); - - void ShowBlur(); - void HideBlur(); - - void Dispose(bool refresh); - void CreateDoubleBuffer(int cx, int cy); - - Gfx::Canvas* m_Canvas; - - ConfigParser m_Parser; - - Gdiplus::Bitmap* m_Background; - SIZE m_BackgroundSize; - - HWND m_Window; - - Mouse m_Mouse; - bool m_MouseOver; - bool m_MouseInputRegistered; - bool m_HasMouseScrollAction; - - std::wstring m_OnRefreshAction; - std::wstring m_OnCloseAction; - std::wstring m_OnFocusAction; - std::wstring m_OnUnfocusAction; - std::wstring m_OnUpdateAction; - std::wstring m_OnWakeAction; - - std::wstring m_SkinGroup; - std::wstring m_BackgroundName; - RECT m_BackgroundMargins; - RECT m_DragMargins; - std::wstring m_WindowX; - std::wstring m_WindowY; - std::wstring m_AnchorX; - std::wstring m_AnchorY; - int m_WindowXScreen; - int m_WindowYScreen; - bool m_WindowXScreenDefined; - bool m_WindowYScreenDefined; - bool m_WindowXFromRight; - bool m_WindowYFromBottom; - bool m_WindowXPercentage; - bool m_WindowYPercentage; - int m_WindowW; - int m_WindowH; - int m_ScreenX; // X-postion on the virtual screen - int m_ScreenY; // Y-postion on the virtual screen - bool m_AnchorXFromRight; - bool m_AnchorYFromBottom; - bool m_AnchorXPercentage; - bool m_AnchorYPercentage; - int m_AnchorScreenX; - int m_AnchorScreenY; - bool m_WindowDraggable; - int m_WindowUpdate; - int m_TransitionUpdate; - bool m_ActiveTransition; - bool m_HasNetMeasures; - bool m_HasButtons; - HIDEMODE m_WindowHide; - bool m_WindowStartHidden; - bool m_SavePosition; - bool m_SnapEdges; - int m_AlphaValue; - int m_FadeDuration; - ZPOSITION m_WindowZPosition; - bool m_DynamicWindowSize; - bool m_ClickThrough; - bool m_KeepOnScreen; - bool m_UseD2D; - bool m_AutoSelectScreen; - bool m_Dragging; - bool m_Dragged; - BGMODE m_BackgroundMode; - Gdiplus::Color m_SolidColor; - Gdiplus::Color m_SolidColor2; - Gdiplus::REAL m_SolidAngle; - BEVELTYPE m_SolidBevel; - - bool m_Blur; - BLURMODE m_BlurMode; - HRGN m_BlurRegion; - - ULONGLONG m_FadeStartTime; - int m_FadeStartValue; - int m_FadeEndValue; - int m_TransparencyValue; - - STATE m_State; - - bool m_Hidden; - RESIZEMODE m_ResizeWindow; - - std::vector m_Measures; - std::vector m_Meters; - - const std::wstring m_FolderPath; - const std::wstring m_FileName; - - int m_UpdateCounter; - UINT m_MouseMoveCounter; - - Gfx::FontCollection* m_FontCollection; - - bool m_ToolTipHidden; - - static int c_InstanceCount; - - static HINSTANCE c_DwmInstance; - - static decltype(DwmEnableBlurBehindWindow)* c_DwmEnableBlurBehindWindow; - static decltype(DwmGetColorizationColor)* c_DwmGetColorizationColor; - static decltype(DwmSetWindowAttribute)* c_DwmSetWindowAttribute; - static decltype(DwmIsCompositionEnabled)* c_DwmIsCompositionEnabled; -}; - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __METERWINDOW_H__ +#define __METERWINDOW_H__ + +#include +#include +#include +#include +#include "CommandHandler.h" +#include "ConfigParser.h" +#include "Group.h" +#include "Mouse.h" + +#define BEGIN_MESSAGEPROC switch (uMsg) { +#define MESSAGE(handler, msg) case msg: return window->handler(uMsg, wParam, lParam); +#define REJECT_MESSAGE(msg) case msg: return 0; +#define END_MESSAGEPROC } return DefWindowProc(hWnd, uMsg, wParam, lParam); + +#define WM_METERWINDOW_DELAYED_REFRESH WM_APP + 1 +#define WM_METERWINDOW_DELAYED_MOVE WM_APP + 3 + +#define METERWINDOW_CLASS_NAME L"RainmeterMeterWindow" + +#define RI_MOUSE_HORIZONTAL_WHEEL 0x0800 + +enum BUTTONPROC +{ + BUTTONPROC_DOWN, + BUTTONPROC_UP, + BUTTONPROC_MOVE +}; + +enum ZPOSITION +{ + ZPOSITION_ONDESKTOP = -2, + ZPOSITION_ONBOTTOM = -1, + ZPOSITION_NORMAL = 0, + ZPOSITION_ONTOP = 1, + ZPOSITION_ONTOPMOST = 2 +}; + +enum BLURMODE +{ + BLURMODE_NONE = 0, + BLURMODE_FULL, + BLURMODE_REGION +}; + +enum BGMODE +{ + BGMODE_IMAGE = 0, + BGMODE_COPY, + BGMODE_SOLID, + BGMODE_SCALED_IMAGE, + BGMODE_TILED_IMAGE +}; + +enum HIDEMODE +{ + HIDEMODE_NONE = 0, + HIDEMODE_HIDE, + HIDEMODE_FADEIN, + HIDEMODE_FADEOUT +}; + +enum BEVELTYPE +{ + BEVELTYPE_NONE, + BEVELTYPE_UP, + BEVELTYPE_DOWN +}; + +enum RESIZEMODE +{ + RESIZEMODE_NONE = 0, + RESIZEMODE_CHECK, + RESIZEMODE_RESET +}; + +class Rainmeter; +class Measure; +class Meter; + +namespace Gfx { +class Canvas; +class FontCollection; +class TextFormat; +} + +class MeterWindow : public Group +{ +public: + MeterWindow(const std::wstring& folderPath, const std::wstring& file); + ~MeterWindow(); + + MeterWindow(const MeterWindow& other) = delete; + MeterWindow& operator=(MeterWindow other) = delete; + + void Initialize(); + + void DoBang(Bang bang, const std::vector& args); + + void HideMeter(const std::wstring& name, bool group = false); + void ShowMeter(const std::wstring& name, bool group = false); + void ToggleMeter(const std::wstring& name, bool group = false); + void MoveMeter(const std::wstring& name, int x, int y); + void UpdateMeter(const std::wstring& name, bool group = false); + void DisableMeasure(const std::wstring& name, bool group = false); + void EnableMeasure(const std::wstring& name, bool group = false); + void ToggleMeasure(const std::wstring& name, bool group = false); + void PauseMeasure(const std::wstring& name, bool group = false); + void UnpauseMeasure(const std::wstring& name, bool group = false); + void TogglePauseMeasure(const std::wstring& name, bool group = false); + void UpdateMeasure(const std::wstring& name, bool group = false); + void Deactivate(); + void Refresh(bool init, bool all = false); + void Redraw(); + void RedrawWindow() { UpdateWindow(m_TransparencyValue); } + void SetVariable(const std::wstring& variable, const std::wstring& value); + void SetOption(const std::wstring& section, const std::wstring& option, const std::wstring& value, bool group); + + void SetMouseLeaveEvent(bool cancel); + void SetHasMouseScrollAction() { m_HasMouseScrollAction = true; } + + void MoveWindow(int x, int y); + void ChangeZPos(ZPOSITION zPos, bool all = false); + void ChangeSingleZPos(ZPOSITION zPos, bool all = false); + void FadeWindow(int from, int to); + void HideFade(); + void ShowFade(); + + void ResizeBlur(const std::wstring& arg, int mode); + bool IsBlur() { return m_Blur; } + void SetBlur(bool b) { m_Blur = b; } + + void SetResizeWindowMode(RESIZEMODE mode) { if (m_ResizeWindow != RESIZEMODE_RESET || mode != RESIZEMODE_CHECK) m_ResizeWindow = mode; } + + Gfx::Canvas& GetCanvas() { return *m_Canvas; } + HWND GetWindow() { return m_Window; } + + ConfigParser& GetParser() { return m_Parser; } + + const std::wstring& GetFolderPath() { return m_FolderPath; } + const std::wstring& GetFileName() { return m_FileName; } + std::wstring GetFilePath(); + std::wstring GetRootName(); + std::wstring GetRootPath(); + std::wstring GetResourcesPath(); + std::wstring GetSkinPath(); + + const std::vector& GetMeasures() { return m_Measures; } + const std::vector& GetMeters() { return m_Meters; } + + ZPOSITION GetWindowZPosition() { return m_WindowZPosition; } + bool GetXPercentage() { return m_WindowXPercentage; } + bool GetYPercentage() { return m_WindowYPercentage; } + bool GetXFromRight() { return m_WindowXFromRight; } + bool GetYFromBottom() { return m_WindowYFromBottom; } + + int GetW() { return m_WindowW; } + int GetH() { return m_WindowH; } + int GetX() { return m_ScreenX; } + int GetY() { return m_ScreenY; } + + bool GetXScreenDefined() { return m_WindowXScreenDefined; } + bool GetYScreenDefined() { return m_WindowYScreenDefined; } + int GetXScreen() { return m_WindowXScreen; } + int GetYScreen() { return m_WindowYScreen; } + + bool GetClickThrough() { return m_ClickThrough; } + bool GetKeepOnScreen() { return m_KeepOnScreen; } + bool GetUseD2D() { return m_UseD2D; } + bool GetAutoSelectScreen() { return m_AutoSelectScreen; } + bool GetWindowDraggable() { return m_WindowDraggable; } + bool GetSavePosition() { return m_SavePosition; } + bool GetSnapEdges() { return m_SnapEdges; } + HIDEMODE GetWindowHide() { return m_WindowHide; } + int GetAlphaValue() { return m_AlphaValue; } + int GetUpdateCounter() { return m_UpdateCounter; } + int GetTransitionUpdate() { return m_TransitionUpdate; } + + bool GetMeterToolTipHidden() { return m_ToolTipHidden; } + + bool IsClosing() { return m_State == STATE_CLOSING; } + + const Mouse& GetMouse() { return m_Mouse; } + + void MakePathAbsolute(std::wstring& path); + + Gfx::FontCollection* GetFontCollection() { return m_FontCollection; } + + Meter* GetMeter(const std::wstring& meterName); + Measure* GetMeasure(const std::wstring& measureName) { return m_Parser.GetMeasure(measureName); } + + friend class DialogManage; + +protected: + static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + static LRESULT CALLBACK InitialWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + LRESULT OnMouseInput(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnMove(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnEnterSizeMove(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnExitSizeMove(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnSetCursor(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnEnterMenuLoop(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnMouseLeave(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnMouseScrollMove(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnMouseHScrollMove(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnLeftButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnRightButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnMiddleButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnLeftButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnRightButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnMiddleButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnLeftButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnRightButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnMiddleButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnXButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnXButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnXButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnDelayedRefresh(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnDelayedMove(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnCopyData(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnDwmColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnDwmCompositionChange(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnDisplayChange(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnSetWindowFocus(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnWake(UINT uMsg, WPARAM wParam, LPARAM lParam); + +private: + enum STATE + { + STATE_INITIALIZING, + STATE_REFRESHING, + STATE_RUNNING, + STATE_CLOSING + }; + + enum OPTION + { + OPTION_POSITION = 0x00000001, + OPTION_ALPHAVALUE = 0x00000002, + OPTION_FADEDURATION = 0x00000004, + OPTION_CLICKTHROUGH = 0x00000008, + OPTION_DRAGGABLE = 0x00000010, + OPTION_HIDEONMOUSEOVER = 0x00000020, + OPTION_SAVEPOSITION = 0x00000040, + OPTION_SNAPEDGES = 0x00000080, + OPTION_KEEPONSCREEN = 0x00000100, + OPTION_AUTOSELECTSCREEN = 0x00000200, + OPTION_ALWAYSONTOP = 0x00000400, + OPTION_USED2D = 0x00000800, + + OPTION_ALL = 0xFFFFFFFF + }; + + bool HitTest(int x, int y); + + void SnapToWindow(MeterWindow* window, LPWINDOWPOS wp); + void MapCoordsToScreen(int& x, int& y, int w, int h); + void WindowToScreen(); + void ScreenToWindow(); + void PostUpdate(bool bActiveTransition); + bool UpdateMeasure(Measure* measure, bool force); + bool UpdateMeter(Meter* meter, bool& bActiveTransition, bool force); + void Update(bool refresh); + void UpdateWindow(int alpha, bool canvasBeginDrawCalled = false); + void UpdateWindowTransparency(int alpha); + void ReadOptions(); + void WriteOptions(INT setting = OPTION_ALL); + bool ReadSkin(); + void ShowWindowIfAppropriate(); + HWND GetWindowFromPoint(POINT pos); + void HandleButtons(POINT pos, BUTTONPROC proc, bool execute = true); + void SetClickThrough(bool b); + void SetKeepOnScreen(bool b); + void SetUseD2D(bool b); + void SetWindowDraggable(bool b); + void SetSavePosition(bool b); + void SavePositionIfAppropriate(); + void SetSnapEdges(bool b); + void SetWindowHide(HIDEMODE hide); + void SetWindowZPosition(ZPOSITION zpos); + bool DoAction(int x, int y, MOUSEACTION action, bool test); + bool DoMoveAction(int x, int y, MOUSEACTION action); + bool ResizeWindow(bool reset); + void IgnoreAeroPeek(); + void RegisterMouseInput(); + void UnregisterMouseInput(); + void AddWindowExStyle(LONG_PTR flag); + void RemoveWindowExStyle(LONG_PTR flag); + void BlurBehindWindow(BOOL fEnable); + void SetWindowPositionVariables(int x, int y); + void SetWindowSizeVariables(int w, int h); + + void ShowBlur(); + void HideBlur(); + + void Dispose(bool refresh); + void CreateDoubleBuffer(int cx, int cy); + + Gfx::Canvas* m_Canvas; + + ConfigParser m_Parser; + + Gdiplus::Bitmap* m_Background; + SIZE m_BackgroundSize; + + HWND m_Window; + + Mouse m_Mouse; + bool m_MouseOver; + bool m_MouseInputRegistered; + bool m_HasMouseScrollAction; + + std::wstring m_OnRefreshAction; + std::wstring m_OnCloseAction; + std::wstring m_OnFocusAction; + std::wstring m_OnUnfocusAction; + std::wstring m_OnUpdateAction; + std::wstring m_OnWakeAction; + + std::wstring m_SkinGroup; + std::wstring m_BackgroundName; + RECT m_BackgroundMargins; + RECT m_DragMargins; + std::wstring m_WindowX; + std::wstring m_WindowY; + std::wstring m_AnchorX; + std::wstring m_AnchorY; + int m_WindowXScreen; + int m_WindowYScreen; + bool m_WindowXScreenDefined; + bool m_WindowYScreenDefined; + bool m_WindowXFromRight; + bool m_WindowYFromBottom; + bool m_WindowXPercentage; + bool m_WindowYPercentage; + int m_WindowW; + int m_WindowH; + int m_ScreenX; // X-postion on the virtual screen + int m_ScreenY; // Y-postion on the virtual screen + bool m_AnchorXFromRight; + bool m_AnchorYFromBottom; + bool m_AnchorXPercentage; + bool m_AnchorYPercentage; + int m_AnchorScreenX; + int m_AnchorScreenY; + bool m_WindowDraggable; + int m_WindowUpdate; + int m_TransitionUpdate; + bool m_ActiveTransition; + bool m_HasNetMeasures; + bool m_HasButtons; + HIDEMODE m_WindowHide; + bool m_WindowStartHidden; + bool m_SavePosition; + bool m_SnapEdges; + int m_AlphaValue; + int m_FadeDuration; + ZPOSITION m_WindowZPosition; + bool m_DynamicWindowSize; + bool m_ClickThrough; + bool m_KeepOnScreen; + bool m_UseD2D; + bool m_AutoSelectScreen; + bool m_Dragging; + bool m_Dragged; + BGMODE m_BackgroundMode; + Gdiplus::Color m_SolidColor; + Gdiplus::Color m_SolidColor2; + Gdiplus::REAL m_SolidAngle; + BEVELTYPE m_SolidBevel; + + bool m_Blur; + BLURMODE m_BlurMode; + HRGN m_BlurRegion; + + ULONGLONG m_FadeStartTime; + int m_FadeStartValue; + int m_FadeEndValue; + int m_TransparencyValue; + + STATE m_State; + + bool m_Hidden; + RESIZEMODE m_ResizeWindow; + + std::vector m_Measures; + std::vector m_Meters; + + const std::wstring m_FolderPath; + const std::wstring m_FileName; + + int m_UpdateCounter; + UINT m_MouseMoveCounter; + + Gfx::FontCollection* m_FontCollection; + + bool m_ToolTipHidden; + + static int c_InstanceCount; + + static HINSTANCE c_DwmInstance; + + static decltype(DwmEnableBlurBehindWindow)* c_DwmEnableBlurBehindWindow; + static decltype(DwmGetColorizationColor)* c_DwmGetColorizationColor; + static decltype(DwmSetWindowAttribute)* c_DwmSetWindowAttribute; + static decltype(DwmIsCompositionEnabled)* c_DwmIsCompositionEnabled; +}; + +#endif diff --git a/Library/Mouse.cpp b/Library/Mouse.cpp index e42b9dba..6f0095f7 100644 --- a/Library/Mouse.cpp +++ b/Library/Mouse.cpp @@ -1,290 +1,290 @@ -/* - Copyright (C) 2012 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "ConfigParser.h" -#include "MeterWindow.h" -#include "Meter.h" -#include "Logger.h" -#include "Mouse.h" - -Mouse::Mouse(MeterWindow* meterWindow, Meter* meter) : m_MeterWindow(meterWindow), m_Meter(meter), - m_CursorType(MOUSECURSOR_HAND), - m_CustomCursor(), - m_CursorState(true) -{ -} - -Mouse::~Mouse() -{ - DestroyCustomCursor(); -} - -void Mouse::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - DestroyCustomCursor(); - - m_MouseActions[MOUSE_LMB_UP] = parser.ReadString(section, L"LeftMouseUpAction", L"", false); - m_MouseActions[MOUSE_LMB_DOWN] = parser.ReadString(section, L"LeftMouseDownAction", L"", false); - m_MouseActions[MOUSE_LMB_DBLCLK] = parser.ReadString(section, L"LeftMouseDoubleClickAction", L"", false); - m_MouseActions[MOUSE_MMB_UP] = parser.ReadString(section, L"MiddleMouseUpAction", L"", false); - m_MouseActions[MOUSE_MMB_DOWN] = parser.ReadString(section, L"MiddleMouseDownAction", L"", false); - m_MouseActions[MOUSE_MMB_DBLCLK] = parser.ReadString(section, L"MiddleMouseDoubleClickAction", L"", false); - m_MouseActions[MOUSE_RMB_UP] = parser.ReadString(section, L"RightMouseUpAction", L"", false); - m_MouseActions[MOUSE_RMB_DOWN] = parser.ReadString(section, L"RightMouseDownAction", L"", false); - m_MouseActions[MOUSE_RMB_DBLCLK] = parser.ReadString(section, L"RightMouseDoubleClickAction", L"", false); - m_MouseActions[MOUSE_X1MB_UP] = parser.ReadString(section, L"X1MouseUpAction", L"", false); - m_MouseActions[MOUSE_X1MB_DOWN] = parser.ReadString(section, L"X1MouseDownAction", L"", false); - m_MouseActions[MOUSE_X1MB_DBLCLK] = parser.ReadString(section, L"X1MouseDoubleClickAction", L"", false); - m_MouseActions[MOUSE_X2MB_UP] = parser.ReadString(section, L"X2MouseUpAction", L"", false); - m_MouseActions[MOUSE_X2MB_DOWN] = parser.ReadString(section, L"X2MouseDownAction", L"", false); - m_MouseActions[MOUSE_X2MB_DBLCLK] = parser.ReadString(section, L"X2MouseDoubleClickAction", L"", false); - - m_MouseActions[MOUSE_MW_UP] = parser.ReadString(section, L"MouseScrollUpAction", L"", false); - m_MouseActions[MOUSE_MW_DOWN] = parser.ReadString(section, L"MouseScrollDownAction", L"", false); - m_MouseActions[MOUSE_MW_LEFT] = parser.ReadString(section, L"MouseScrollLeftAction", L"", false); - m_MouseActions[MOUSE_MW_RIGHT] = parser.ReadString(section, L"MouseScrollRightAction", L"", false); - - m_MouseActions[MOUSE_OVER] = parser.ReadString(section, L"MouseOverAction", L"", false); - m_MouseActions[MOUSE_LEAVE] = parser.ReadString(section, L"MouseLeaveAction", L"", false); - - if (HasScrollAction()) - { - m_MeterWindow->SetHasMouseScrollAction(); - } - - const bool defaultState = (section == L"Rainmeter") ? true : m_MeterWindow->GetMouse().GetCursorState(); - m_CursorState = parser.ReadBool(section, L"MouseActionCursor", defaultState); - - const WCHAR* defaultMouseCursor = (section == L"Rainmeter") ? L"HAND" : L""; - const WCHAR* mouseCursor = parser.ReadString(section, L"MouseActionCursorName", defaultMouseCursor).c_str(); - - auto inheritSkinDefault = [&]() - { - // Inherit from [Rainmeter]. - m_CursorType = m_MeterWindow->GetMouse().GetCursorType(); - if (m_CursorType == MOUSECURSOR_CUSTOM) - { - mouseCursor = m_MeterWindow->GetParser().ReadString(L"Rainmeter", L"MouseActionCursorName", L"").c_str(); - } - }; - - if (*mouseCursor == L'\0') // meters' default - { - inheritSkinDefault(); - } - else if (_wcsicmp(mouseCursor, L"HAND") == 0) // skin's default - { - m_CursorType = MOUSECURSOR_HAND; - } - else if (_wcsicmp(mouseCursor, L"TEXT") == 0) - { - m_CursorType = MOUSECURSOR_TEXT; - } - else if (_wcsicmp(mouseCursor, L"HELP") == 0) - { - m_CursorType = MOUSECURSOR_HELP; - } - else if (_wcsicmp(mouseCursor, L"BUSY") == 0) - { - m_CursorType = MOUSECURSOR_BUSY; - } - else if (_wcsicmp(mouseCursor, L"CROSS") == 0) - { - m_CursorType = MOUSECURSOR_CROSS; - } - else if (_wcsicmp(mouseCursor, L"PEN") == 0) - { - m_CursorType = MOUSECURSOR_PEN; - } - else if (wcschr(mouseCursor, L'.')) - { - m_CursorType = MOUSECURSOR_CUSTOM; - } - else - { - inheritSkinDefault(); - } - - if (m_CursorType == MOUSECURSOR_CUSTOM) - { - std::wstring cursorPath = m_MeterWindow->GetResourcesPath(); - cursorPath += L"Cursors\\"; - cursorPath += mouseCursor; - m_CustomCursor = LoadCursorFromFile(cursorPath.c_str()); - if (!m_CustomCursor) - { - m_CursorType = MOUSECURSOR_ARROW; - LogErrorF(m_MeterWindow, L"Invalid cursor: %s", cursorPath.c_str()); - } - } -} - -HCURSOR Mouse::GetCursor() const -{ - LPCWSTR name = IDC_ARROW; - switch (m_CursorType) - { - case MOUSECURSOR_HAND: - name = IDC_HAND; - break; - - case MOUSECURSOR_TEXT: - name = IDC_IBEAM; - break; - - case MOUSECURSOR_HELP: - name = IDC_HELP; - break; - - case MOUSECURSOR_BUSY: - name = IDC_APPSTARTING; - break; - - case MOUSECURSOR_CROSS: - name = IDC_CROSS; - break; - - case MOUSECURSOR_PEN: - name = MAKEINTRESOURCE(32631); - break; - - case MOUSECURSOR_CUSTOM: - { - if (m_CustomCursor) - { - return m_CustomCursor; - } - } - break; - } - - return LoadCursor(nullptr, name); -} - -std::wstring Mouse::GetActionCommand(MOUSEACTION action) const -{ - std::wstring command = m_MouseActions[action]; - ReplaceMouseVariables(command); - return command; -} - -void Mouse::DestroyCustomCursor() -{ - if (m_CustomCursor) - { - DestroyCursor(m_CustomCursor); - m_CustomCursor = nullptr; - } -} - -void Mouse::ReplaceMouseVariables(std::wstring& result) const -{ - // Check for variables ($VAR$) - size_t start = 0, end; - bool loop = true; - - do - { - start = result.find(L'$', start); - if (start != std::wstring::npos) - { - size_t si = start + 1; - end = result.find(L'$', si); - if (end != std::wstring::npos) - { - size_t ei = end - 1; - if (si != ei && result[si] == L'*' && result[ei] == L'*') - { - result.erase(ei, 1); - result.erase(si, 1); - start = ei; - } - else - { - std::wstring strVariable = result.substr(si, end - si); - std::wstring value = GetMouseVariable(strVariable); - if (!value.empty()) - { - // Variable found, replace it with the value - result.replace(start, end - start + 1, value); - start += value.length(); - } - else - { - start = end; - } - } - } - else - { - loop = false; - } - } - else - { - loop = false; - } - } - while (loop); -} - -std::wstring Mouse::GetMouseVariable(const std::wstring& variable) const -{ - std::wstring result; - LPCWSTR var = variable.c_str(); - WCHAR buffer[32]; - - POINT pt; - GetCursorPos(&pt); - - if (_wcsnicmp(var, L"MOUSEX", 6) == 0) - { - var += 6; - int xOffset = m_MeterWindow->GetX() + (m_Meter ? m_Meter->GetX() : 0); - if (wcscmp(var, L":%") == 0) // $MOUSEX:%$ - { - xOffset = (int)(((pt.x - xOffset + 1) / (double)(m_Meter ? m_Meter->GetW() : m_MeterWindow->GetW())) * 100); - _itow_s(xOffset, buffer, 10); - result = buffer; - } - else if (*var == L'\0') // $MOUSEX$ - { - _itow_s(pt.x - xOffset, buffer, 10); - result = buffer; - } - } - else if (_wcsnicmp(var, L"MOUSEY", 6) == 0) - { - var += 6; - int yOffset = m_MeterWindow->GetY() + (m_Meter ? m_Meter->GetY() : 0); - if (wcscmp(var, L":%") == 0) // $MOUSEY:%$ - { - yOffset = (int)(((pt.y - yOffset + 1) / (double)(m_Meter ? m_Meter->GetH() : m_MeterWindow->GetH())) * 100); - _itow_s(yOffset, buffer, 10); - result = buffer; - } - else if (*var == L'\0') // $MOUSEY$ - { - _itow_s(pt.y - yOffset, buffer, 10); - result = buffer; - } - } - - return result; +/* + Copyright (C) 2012 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "ConfigParser.h" +#include "MeterWindow.h" +#include "Meter.h" +#include "Logger.h" +#include "Mouse.h" + +Mouse::Mouse(MeterWindow* meterWindow, Meter* meter) : m_MeterWindow(meterWindow), m_Meter(meter), + m_CursorType(MOUSECURSOR_HAND), + m_CustomCursor(), + m_CursorState(true) +{ +} + +Mouse::~Mouse() +{ + DestroyCustomCursor(); +} + +void Mouse::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + DestroyCustomCursor(); + + m_MouseActions[MOUSE_LMB_UP] = parser.ReadString(section, L"LeftMouseUpAction", L"", false); + m_MouseActions[MOUSE_LMB_DOWN] = parser.ReadString(section, L"LeftMouseDownAction", L"", false); + m_MouseActions[MOUSE_LMB_DBLCLK] = parser.ReadString(section, L"LeftMouseDoubleClickAction", L"", false); + m_MouseActions[MOUSE_MMB_UP] = parser.ReadString(section, L"MiddleMouseUpAction", L"", false); + m_MouseActions[MOUSE_MMB_DOWN] = parser.ReadString(section, L"MiddleMouseDownAction", L"", false); + m_MouseActions[MOUSE_MMB_DBLCLK] = parser.ReadString(section, L"MiddleMouseDoubleClickAction", L"", false); + m_MouseActions[MOUSE_RMB_UP] = parser.ReadString(section, L"RightMouseUpAction", L"", false); + m_MouseActions[MOUSE_RMB_DOWN] = parser.ReadString(section, L"RightMouseDownAction", L"", false); + m_MouseActions[MOUSE_RMB_DBLCLK] = parser.ReadString(section, L"RightMouseDoubleClickAction", L"", false); + m_MouseActions[MOUSE_X1MB_UP] = parser.ReadString(section, L"X1MouseUpAction", L"", false); + m_MouseActions[MOUSE_X1MB_DOWN] = parser.ReadString(section, L"X1MouseDownAction", L"", false); + m_MouseActions[MOUSE_X1MB_DBLCLK] = parser.ReadString(section, L"X1MouseDoubleClickAction", L"", false); + m_MouseActions[MOUSE_X2MB_UP] = parser.ReadString(section, L"X2MouseUpAction", L"", false); + m_MouseActions[MOUSE_X2MB_DOWN] = parser.ReadString(section, L"X2MouseDownAction", L"", false); + m_MouseActions[MOUSE_X2MB_DBLCLK] = parser.ReadString(section, L"X2MouseDoubleClickAction", L"", false); + + m_MouseActions[MOUSE_MW_UP] = parser.ReadString(section, L"MouseScrollUpAction", L"", false); + m_MouseActions[MOUSE_MW_DOWN] = parser.ReadString(section, L"MouseScrollDownAction", L"", false); + m_MouseActions[MOUSE_MW_LEFT] = parser.ReadString(section, L"MouseScrollLeftAction", L"", false); + m_MouseActions[MOUSE_MW_RIGHT] = parser.ReadString(section, L"MouseScrollRightAction", L"", false); + + m_MouseActions[MOUSE_OVER] = parser.ReadString(section, L"MouseOverAction", L"", false); + m_MouseActions[MOUSE_LEAVE] = parser.ReadString(section, L"MouseLeaveAction", L"", false); + + if (HasScrollAction()) + { + m_MeterWindow->SetHasMouseScrollAction(); + } + + const bool defaultState = (section == L"Rainmeter") ? true : m_MeterWindow->GetMouse().GetCursorState(); + m_CursorState = parser.ReadBool(section, L"MouseActionCursor", defaultState); + + const WCHAR* defaultMouseCursor = (section == L"Rainmeter") ? L"HAND" : L""; + const WCHAR* mouseCursor = parser.ReadString(section, L"MouseActionCursorName", defaultMouseCursor).c_str(); + + auto inheritSkinDefault = [&]() + { + // Inherit from [Rainmeter]. + m_CursorType = m_MeterWindow->GetMouse().GetCursorType(); + if (m_CursorType == MOUSECURSOR_CUSTOM) + { + mouseCursor = m_MeterWindow->GetParser().ReadString(L"Rainmeter", L"MouseActionCursorName", L"").c_str(); + } + }; + + if (*mouseCursor == L'\0') // meters' default + { + inheritSkinDefault(); + } + else if (_wcsicmp(mouseCursor, L"HAND") == 0) // skin's default + { + m_CursorType = MOUSECURSOR_HAND; + } + else if (_wcsicmp(mouseCursor, L"TEXT") == 0) + { + m_CursorType = MOUSECURSOR_TEXT; + } + else if (_wcsicmp(mouseCursor, L"HELP") == 0) + { + m_CursorType = MOUSECURSOR_HELP; + } + else if (_wcsicmp(mouseCursor, L"BUSY") == 0) + { + m_CursorType = MOUSECURSOR_BUSY; + } + else if (_wcsicmp(mouseCursor, L"CROSS") == 0) + { + m_CursorType = MOUSECURSOR_CROSS; + } + else if (_wcsicmp(mouseCursor, L"PEN") == 0) + { + m_CursorType = MOUSECURSOR_PEN; + } + else if (wcschr(mouseCursor, L'.')) + { + m_CursorType = MOUSECURSOR_CUSTOM; + } + else + { + inheritSkinDefault(); + } + + if (m_CursorType == MOUSECURSOR_CUSTOM) + { + std::wstring cursorPath = m_MeterWindow->GetResourcesPath(); + cursorPath += L"Cursors\\"; + cursorPath += mouseCursor; + m_CustomCursor = LoadCursorFromFile(cursorPath.c_str()); + if (!m_CustomCursor) + { + m_CursorType = MOUSECURSOR_ARROW; + LogErrorF(m_MeterWindow, L"Invalid cursor: %s", cursorPath.c_str()); + } + } +} + +HCURSOR Mouse::GetCursor() const +{ + LPCWSTR name = IDC_ARROW; + switch (m_CursorType) + { + case MOUSECURSOR_HAND: + name = IDC_HAND; + break; + + case MOUSECURSOR_TEXT: + name = IDC_IBEAM; + break; + + case MOUSECURSOR_HELP: + name = IDC_HELP; + break; + + case MOUSECURSOR_BUSY: + name = IDC_APPSTARTING; + break; + + case MOUSECURSOR_CROSS: + name = IDC_CROSS; + break; + + case MOUSECURSOR_PEN: + name = MAKEINTRESOURCE(32631); + break; + + case MOUSECURSOR_CUSTOM: + { + if (m_CustomCursor) + { + return m_CustomCursor; + } + } + break; + } + + return LoadCursor(nullptr, name); +} + +std::wstring Mouse::GetActionCommand(MOUSEACTION action) const +{ + std::wstring command = m_MouseActions[action]; + ReplaceMouseVariables(command); + return command; +} + +void Mouse::DestroyCustomCursor() +{ + if (m_CustomCursor) + { + DestroyCursor(m_CustomCursor); + m_CustomCursor = nullptr; + } +} + +void Mouse::ReplaceMouseVariables(std::wstring& result) const +{ + // Check for variables ($VAR$) + size_t start = 0, end; + bool loop = true; + + do + { + start = result.find(L'$', start); + if (start != std::wstring::npos) + { + size_t si = start + 1; + end = result.find(L'$', si); + if (end != std::wstring::npos) + { + size_t ei = end - 1; + if (si != ei && result[si] == L'*' && result[ei] == L'*') + { + result.erase(ei, 1); + result.erase(si, 1); + start = ei; + } + else + { + std::wstring strVariable = result.substr(si, end - si); + std::wstring value = GetMouseVariable(strVariable); + if (!value.empty()) + { + // Variable found, replace it with the value + result.replace(start, end - start + 1, value); + start += value.length(); + } + else + { + start = end; + } + } + } + else + { + loop = false; + } + } + else + { + loop = false; + } + } + while (loop); +} + +std::wstring Mouse::GetMouseVariable(const std::wstring& variable) const +{ + std::wstring result; + LPCWSTR var = variable.c_str(); + WCHAR buffer[32]; + + POINT pt; + GetCursorPos(&pt); + + if (_wcsnicmp(var, L"MOUSEX", 6) == 0) + { + var += 6; + int xOffset = m_MeterWindow->GetX() + (m_Meter ? m_Meter->GetX() : 0); + if (wcscmp(var, L":%") == 0) // $MOUSEX:%$ + { + xOffset = (int)(((pt.x - xOffset + 1) / (double)(m_Meter ? m_Meter->GetW() : m_MeterWindow->GetW())) * 100); + _itow_s(xOffset, buffer, 10); + result = buffer; + } + else if (*var == L'\0') // $MOUSEX$ + { + _itow_s(pt.x - xOffset, buffer, 10); + result = buffer; + } + } + else if (_wcsnicmp(var, L"MOUSEY", 6) == 0) + { + var += 6; + int yOffset = m_MeterWindow->GetY() + (m_Meter ? m_Meter->GetY() : 0); + if (wcscmp(var, L":%") == 0) // $MOUSEY:%$ + { + yOffset = (int)(((pt.y - yOffset + 1) / (double)(m_Meter ? m_Meter->GetH() : m_MeterWindow->GetH())) * 100); + _itow_s(yOffset, buffer, 10); + result = buffer; + } + else if (*var == L'\0') // $MOUSEY$ + { + _itow_s(pt.y - yOffset, buffer, 10); + result = buffer; + } + } + + return result; } \ No newline at end of file diff --git a/Library/Mouse.h b/Library/Mouse.h index d6deb23d..82c4fcac 100644 --- a/Library/Mouse.h +++ b/Library/Mouse.h @@ -1,152 +1,152 @@ -/* - Copyright (C) 2012 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MOUSE_H__ -#define __MOUSE_H__ - -enum MOUSEACTION -{ - MOUSE_LMB_UP = 0, - MOUSE_LMB_DOWN, - MOUSE_LMB_DBLCLK, - MOUSE_MMB_UP, - MOUSE_MMB_DOWN, - MOUSE_MMB_DBLCLK, - MOUSE_RMB_UP, - MOUSE_RMB_DOWN, - MOUSE_RMB_DBLCLK, - MOUSE_X1MB_UP, - MOUSE_X1MB_DOWN, - MOUSE_X1MB_DBLCLK, - MOUSE_X2MB_UP, - MOUSE_X2MB_DOWN, - MOUSE_X2MB_DBLCLK, - - MOUSE_MW_UP, - MOUSE_MW_DOWN, - MOUSE_MW_LEFT, - MOUSE_MW_RIGHT, - - MOUSE_OVER, - MOUSE_LEAVE, - - MOUSEACTION_COUNT -}; - -enum MOUSECURSOR -{ - MOUSECURSOR_ARROW, - MOUSECURSOR_HAND, - MOUSECURSOR_TEXT, - MOUSECURSOR_HELP, - MOUSECURSOR_BUSY, - MOUSECURSOR_CROSS, - MOUSECURSOR_PEN, - MOUSECURSOR_CUSTOM -}; - -class Mouse -{ -public: - Mouse(MeterWindow* meterWindow, Meter* meter = nullptr); - ~Mouse(); - - Mouse(const Mouse& other) = delete; - Mouse& operator=(Mouse other) = delete; - - void ReadOptions(ConfigParser& parser, const WCHAR* section); - - MOUSECURSOR GetCursorType() const { return m_CursorType; } - HCURSOR GetCursor() const; - bool GetCursorState() const {return m_CursorState; } - - void DestroyCustomCursor(); - - bool HasActionCommand(MOUSEACTION action) const { return !m_MouseActions[action].empty(); } - std::wstring GetActionCommand(MOUSEACTION action) const; - - bool HasButtonAction() const - { - return !( - GetLeftUpAction().empty() && - GetLeftDownAction().empty() && - GetLeftDoubleClickAction().empty() && - GetMiddleUpAction().empty() && - GetMiddleDownAction().empty() && - GetMiddleDoubleClickAction().empty() && - GetRightUpAction().empty() && - GetRightDownAction().empty() && - GetRightDoubleClickAction().empty() && - GetX1UpAction().empty() && - GetX1DownAction().empty() && - GetX1DoubleClickAction().empty() && - GetX2UpAction().empty() && - GetX2DownAction().empty() && - GetX2DoubleClickAction().empty() - ); - } - - bool HasScrollAction() const - { - return !( - GetMouseScrollUpAction().empty() && - GetMouseScrollDownAction().empty() && - GetMouseScrollLeftAction().empty() && - GetMouseScrollRightAction().empty() - ); - } - - const std::wstring& GetLeftUpAction() const { return m_MouseActions[MOUSE_LMB_UP]; } - const std::wstring& GetLeftDownAction() const { return m_MouseActions[MOUSE_LMB_DOWN]; } - const std::wstring& GetLeftDoubleClickAction() const { return m_MouseActions[MOUSE_LMB_DBLCLK]; } - const std::wstring& GetMiddleUpAction() const { return m_MouseActions[MOUSE_MMB_UP]; } - const std::wstring& GetMiddleDownAction() const { return m_MouseActions[MOUSE_MMB_DOWN]; } - const std::wstring& GetMiddleDoubleClickAction() const { return m_MouseActions[MOUSE_MMB_DBLCLK]; } - const std::wstring& GetRightUpAction() const { return m_MouseActions[MOUSE_RMB_UP]; } - const std::wstring& GetRightDownAction() const { return m_MouseActions[MOUSE_RMB_DOWN]; } - const std::wstring& GetRightDoubleClickAction() const { return m_MouseActions[MOUSE_RMB_DBLCLK]; } - const std::wstring& GetX1UpAction() const { return m_MouseActions[MOUSE_X1MB_UP]; } - const std::wstring& GetX1DownAction() const { return m_MouseActions[MOUSE_X1MB_DOWN]; } - const std::wstring& GetX1DoubleClickAction() const { return m_MouseActions[MOUSE_X1MB_DBLCLK]; } - const std::wstring& GetX2UpAction() const { return m_MouseActions[MOUSE_X2MB_UP]; } - const std::wstring& GetX2DownAction() const { return m_MouseActions[MOUSE_X2MB_DOWN]; } - const std::wstring& GetX2DoubleClickAction() const { return m_MouseActions[MOUSE_X2MB_DBLCLK]; } - - const std::wstring& GetMouseScrollUpAction() const { return m_MouseActions[MOUSE_MW_UP]; } - const std::wstring& GetMouseScrollDownAction() const { return m_MouseActions[MOUSE_MW_DOWN]; } - const std::wstring& GetMouseScrollLeftAction() const { return m_MouseActions[MOUSE_MW_LEFT]; } - const std::wstring& GetMouseScrollRightAction() const { return m_MouseActions[MOUSE_MW_RIGHT]; } - - const std::wstring& GetOverAction() const { return m_MouseActions[MOUSE_OVER]; } - const std::wstring& GetLeaveAction() const { return m_MouseActions[MOUSE_LEAVE]; } - -private: - void ReplaceMouseVariables(std::wstring& result) const; - std::wstring GetMouseVariable(const std::wstring& variable) const; - - std::wstring m_MouseActions[MOUSEACTION_COUNT]; - - MOUSECURSOR m_CursorType; - HCURSOR m_CustomCursor; - bool m_CursorState; - - MeterWindow* m_MeterWindow; - Meter* m_Meter; -}; - -#endif +/* + Copyright (C) 2012 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __MOUSE_H__ +#define __MOUSE_H__ + +enum MOUSEACTION +{ + MOUSE_LMB_UP = 0, + MOUSE_LMB_DOWN, + MOUSE_LMB_DBLCLK, + MOUSE_MMB_UP, + MOUSE_MMB_DOWN, + MOUSE_MMB_DBLCLK, + MOUSE_RMB_UP, + MOUSE_RMB_DOWN, + MOUSE_RMB_DBLCLK, + MOUSE_X1MB_UP, + MOUSE_X1MB_DOWN, + MOUSE_X1MB_DBLCLK, + MOUSE_X2MB_UP, + MOUSE_X2MB_DOWN, + MOUSE_X2MB_DBLCLK, + + MOUSE_MW_UP, + MOUSE_MW_DOWN, + MOUSE_MW_LEFT, + MOUSE_MW_RIGHT, + + MOUSE_OVER, + MOUSE_LEAVE, + + MOUSEACTION_COUNT +}; + +enum MOUSECURSOR +{ + MOUSECURSOR_ARROW, + MOUSECURSOR_HAND, + MOUSECURSOR_TEXT, + MOUSECURSOR_HELP, + MOUSECURSOR_BUSY, + MOUSECURSOR_CROSS, + MOUSECURSOR_PEN, + MOUSECURSOR_CUSTOM +}; + +class Mouse +{ +public: + Mouse(MeterWindow* meterWindow, Meter* meter = nullptr); + ~Mouse(); + + Mouse(const Mouse& other) = delete; + Mouse& operator=(Mouse other) = delete; + + void ReadOptions(ConfigParser& parser, const WCHAR* section); + + MOUSECURSOR GetCursorType() const { return m_CursorType; } + HCURSOR GetCursor() const; + bool GetCursorState() const {return m_CursorState; } + + void DestroyCustomCursor(); + + bool HasActionCommand(MOUSEACTION action) const { return !m_MouseActions[action].empty(); } + std::wstring GetActionCommand(MOUSEACTION action) const; + + bool HasButtonAction() const + { + return !( + GetLeftUpAction().empty() && + GetLeftDownAction().empty() && + GetLeftDoubleClickAction().empty() && + GetMiddleUpAction().empty() && + GetMiddleDownAction().empty() && + GetMiddleDoubleClickAction().empty() && + GetRightUpAction().empty() && + GetRightDownAction().empty() && + GetRightDoubleClickAction().empty() && + GetX1UpAction().empty() && + GetX1DownAction().empty() && + GetX1DoubleClickAction().empty() && + GetX2UpAction().empty() && + GetX2DownAction().empty() && + GetX2DoubleClickAction().empty() + ); + } + + bool HasScrollAction() const + { + return !( + GetMouseScrollUpAction().empty() && + GetMouseScrollDownAction().empty() && + GetMouseScrollLeftAction().empty() && + GetMouseScrollRightAction().empty() + ); + } + + const std::wstring& GetLeftUpAction() const { return m_MouseActions[MOUSE_LMB_UP]; } + const std::wstring& GetLeftDownAction() const { return m_MouseActions[MOUSE_LMB_DOWN]; } + const std::wstring& GetLeftDoubleClickAction() const { return m_MouseActions[MOUSE_LMB_DBLCLK]; } + const std::wstring& GetMiddleUpAction() const { return m_MouseActions[MOUSE_MMB_UP]; } + const std::wstring& GetMiddleDownAction() const { return m_MouseActions[MOUSE_MMB_DOWN]; } + const std::wstring& GetMiddleDoubleClickAction() const { return m_MouseActions[MOUSE_MMB_DBLCLK]; } + const std::wstring& GetRightUpAction() const { return m_MouseActions[MOUSE_RMB_UP]; } + const std::wstring& GetRightDownAction() const { return m_MouseActions[MOUSE_RMB_DOWN]; } + const std::wstring& GetRightDoubleClickAction() const { return m_MouseActions[MOUSE_RMB_DBLCLK]; } + const std::wstring& GetX1UpAction() const { return m_MouseActions[MOUSE_X1MB_UP]; } + const std::wstring& GetX1DownAction() const { return m_MouseActions[MOUSE_X1MB_DOWN]; } + const std::wstring& GetX1DoubleClickAction() const { return m_MouseActions[MOUSE_X1MB_DBLCLK]; } + const std::wstring& GetX2UpAction() const { return m_MouseActions[MOUSE_X2MB_UP]; } + const std::wstring& GetX2DownAction() const { return m_MouseActions[MOUSE_X2MB_DOWN]; } + const std::wstring& GetX2DoubleClickAction() const { return m_MouseActions[MOUSE_X2MB_DBLCLK]; } + + const std::wstring& GetMouseScrollUpAction() const { return m_MouseActions[MOUSE_MW_UP]; } + const std::wstring& GetMouseScrollDownAction() const { return m_MouseActions[MOUSE_MW_DOWN]; } + const std::wstring& GetMouseScrollLeftAction() const { return m_MouseActions[MOUSE_MW_LEFT]; } + const std::wstring& GetMouseScrollRightAction() const { return m_MouseActions[MOUSE_MW_RIGHT]; } + + const std::wstring& GetOverAction() const { return m_MouseActions[MOUSE_OVER]; } + const std::wstring& GetLeaveAction() const { return m_MouseActions[MOUSE_LEAVE]; } + +private: + void ReplaceMouseVariables(std::wstring& result) const; + std::wstring GetMouseVariable(const std::wstring& variable) const; + + std::wstring m_MouseActions[MOUSEACTION_COUNT]; + + MOUSECURSOR m_CursorType; + HCURSOR m_CustomCursor; + bool m_CursorState; + + MeterWindow* m_MeterWindow; + Meter* m_Meter; +}; + +#endif diff --git a/Library/Rainmeter.cpp b/Library/Rainmeter.cpp index ae7b8720..e92be98d 100644 --- a/Library/Rainmeter.cpp +++ b/Library/Rainmeter.cpp @@ -1,1690 +1,1690 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../Common/PathUtil.h" -#include "Rainmeter.h" -#include "TrayWindow.h" -#include "System.h" -#include "Error.h" -#include "DialogAbout.h" -#include "DialogManage.h" -#include "MeasureNet.h" -#include "MeasureCPU.h" -#include "MeterString.h" -#include "UpdateCheck.h" -#include "../Version.h" - -using namespace Gdiplus; - -enum TIMER -{ - TIMER_NETSTATS = 1 -}; -enum INTERVAL -{ - INTERVAL_NETSTATS = 120000 -}; - -/* -** Initializes Rainmeter. -** -*/ -int RainmeterMain(LPWSTR cmdLine) -{ - auto& rainmeter = Rainmeter::GetInstance(); - int ret = rainmeter.Initialize(nullptr, nullptr); - if (ret == 0) - { - ret = rainmeter.MessagePump(); - } - rainmeter.Finalize(); - - return ret; -} - -/* -** Initializes Rainmeter. -** -*/ -void* Rainmeter_Initialize() -{ - int res = Rainmeter::GetInstance().Initialize(nullptr, nullptr); - - // Success? - if (res == 0) - return &Rainmeter::GetInstance(); - - return nullptr; -} - -/* -** Finalizes Rainmeter. -** -*/ -void Rainmeter_Finalize(void* ptr) -{ - Rainmeter* rainmeter = (Rainmeter*)ptr; - rainmeter->Finalize(); -} - -/* -** Constructor -** -*/ -Rainmeter::Rainmeter() : - m_TrayWindow(), - m_UseD2D(true), - m_Debug(false), - m_DisableVersionCheck(false), - m_NewVersion(false), - m_DesktopWorkAreaChanged(false), - m_DesktopWorkAreaType(false), - m_NormalStayDesktop(true), - m_DisableRDP(false), - m_DisableDragging(false), - m_CurrentParser(), - m_Window(), - m_Mutex(), - m_Instance(), - m_ResourceInstance(), - m_ResourceLCID(), - m_GDIplusToken(), - m_GlobalOptions() -{ - CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); - - InitCommonControls(); - - // Initialize GDI+. - GdiplusStartupInput gdiplusStartupInput; - GdiplusStartup(&m_GDIplusToken, &gdiplusStartupInput, nullptr); -} - -/* -** Destructor -** -*/ -Rainmeter::~Rainmeter() -{ - CoUninitialize(); - - GdiplusShutdown(m_GDIplusToken); -} - -Rainmeter& Rainmeter::GetInstance() -{ - static Rainmeter s_Rainmeter; - return s_Rainmeter; -} - -/* -** The main initialization function for the module. -** -*/ -int Rainmeter::Initialize(LPCWSTR iniPath, LPCWSTR layout) -{ - m_Instance = GetModuleHandle(L"Rainmeter"); - - WCHAR* buffer = new WCHAR[MAX_LINE_LENGTH]; - GetModuleFileName(m_Instance, buffer, MAX_LINE_LENGTH); - - // Remove the module's name from the path - WCHAR* pos = wcsrchr(buffer, L'\\'); - m_Path.assign(buffer, pos ? pos - buffer + 1 : 0); - m_Drive = PathUtil::GetVolume(m_Path); - - bool bDefaultIniLocation = false; - if (iniPath) - { - // The command line defines the location of Rainmeter.ini (or whatever it calls it). - std::wstring iniFile = iniPath; - PathUtil::ExpandEnvironmentVariables(iniFile); - - if (iniFile.empty() || PathUtil::IsSeparator(iniFile[iniFile.length() - 1])) - { - iniFile += L"Rainmeter.ini"; - } - else if (iniFile.length() <= 4 || _wcsicmp(iniFile.c_str() + (iniFile.length() - 4), L".ini") != 0) - { - iniFile += L"\\Rainmeter.ini"; - } - - if (!PathUtil::IsSeparator(iniFile[0]) && iniFile.find_first_of(L':') == std::wstring::npos) - { - // Make absolute path - iniFile.insert(0, m_Path); - } - - m_IniFile = iniFile; - bDefaultIniLocation = true; - } - else - { - m_IniFile = m_Path; - m_IniFile += L"Rainmeter.ini"; - - // If the ini file doesn't exist in the program folder store it to the %APPDATA% instead so that things work better in Vista/Win7 - if (_waccess(m_IniFile.c_str(), 0) == -1) - { - m_IniFile = L"%APPDATA%\\Rainmeter\\Rainmeter.ini"; - PathUtil::ExpandEnvironmentVariables(m_IniFile); - bDefaultIniLocation = true; - } - } - - WNDCLASS wc = {0}; - wc.lpfnWndProc = (WNDPROC)MainWndProc; - wc.hInstance = m_Instance; - wc.lpszClassName = RAINMETER_CLASS_NAME; - ATOM className = RegisterClass(&wc); - - m_Window = CreateWindowEx( - WS_EX_TOOLWINDOW, - MAKEINTATOM(className), - RAINMETER_WINDOW_NAME, - WS_POPUP | WS_DISABLED, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - nullptr, - nullptr, - m_Instance, - nullptr); - - if (!m_Window) return 1; - - Logger& logger = GetLogger(); - const WCHAR* iniFile = m_IniFile.c_str(); - - // Set file locations - { - m_SettingsPath = PathUtil::GetFolderFromFilePath(m_IniFile); - - size_t len = m_IniFile.length(); - if (len > 4 && _wcsicmp(iniFile + (len - 4), L".ini") == 0) - { - len -= 4; - } - - std::wstring logFile(m_IniFile, 0, len); - m_DataFile = m_StatsFile = logFile; - logFile += L".log"; - m_StatsFile += L".stats"; - m_DataFile += L".data"; - - logger.SetLogFilePath(logFile); - } - - // Create a default Rainmeter.ini file if needed - if (_waccess(iniFile, 0) == -1) - { - CreateOptionsFile(); - } - - bool dataFileCreated = false; - if (_waccess(m_DataFile.c_str(), 0) == -1) - { - dataFileCreated = true; - CreateDataFile(); - } - - // Reset log file - System::RemoveFile(logger.GetLogFilePath()); - - m_Debug = 0!=GetPrivateProfileInt(L"Rainmeter", L"Debug", 0, iniFile); - - const bool logging = GetPrivateProfileInt(L"Rainmeter", L"Logging", 0, iniFile) != 0; - logger.SetLogToFile(logging); - if (logging) - { - logger.StartLogFile(); - } - - // Determine the language resource to load - std::wstring resource = m_Path + L"Languages\\"; - if (GetPrivateProfileString(L"Rainmeter", L"Language", L"", buffer, MAX_LINE_LENGTH, iniFile) == 0) - { - // Use whatever the user selected for the installer - DWORD size = MAX_LINE_LENGTH; - HKEY hKey; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Rainmeter", 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &hKey) == ERROR_SUCCESS) - { - DWORD type = 0; - if (RegQueryValueEx(hKey, L"Language", nullptr, &type, (LPBYTE)buffer, (LPDWORD)&size) != ERROR_SUCCESS || - type != REG_SZ) - { - buffer[0] = L'\0'; - } - RegCloseKey(hKey); - } - } - if (buffer[0] != L'\0') - { - // Try selected language - m_ResourceLCID = wcstoul(buffer, nullptr, 10); - resource += buffer; - resource += L".dll"; - - m_ResourceInstance = LoadLibraryEx(resource.c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); - } - if (!m_ResourceInstance) - { - // Try English - resource = m_Path; - resource += L"Languages\\1033.dll"; - m_ResourceInstance = LoadLibraryEx(resource.c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); - m_ResourceLCID = 1033; - if (!m_ResourceInstance) - { - MessageBox(nullptr, L"Unable to load language library", APPNAME, MB_OK | MB_TOPMOST | MB_ICONERROR); - return 1; - } - } - - // Get skin folder path - size_t len = GetPrivateProfileString(L"Rainmeter", L"SkinPath", L"", buffer, MAX_LINE_LENGTH, iniFile); - if (len > 0 && - _waccess(buffer, 0) != -1) // Temporary fix - { - // Try Rainmeter.ini first - m_SkinPath.assign(buffer, len); - PathUtil::ExpandEnvironmentVariables(m_SkinPath); - PathUtil::AppendBacklashIfMissing(m_SkinPath); - } - else if (bDefaultIniLocation && - SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_MYDOCUMENTS, nullptr, SHGFP_TYPE_CURRENT, buffer))) - { - // Use My Documents/Rainmeter/Skins - m_SkinPath = buffer; - m_SkinPath += L"\\Rainmeter\\"; - CreateDirectory(m_SkinPath.c_str(), nullptr); - m_SkinPath += L"Skins\\"; - - WritePrivateProfileString(L"Rainmeter", L"SkinPath", m_SkinPath.c_str(), iniFile); - } - else - { - m_SkinPath = m_Path + L"Skins\\"; - } - - // Create user skins, layouts, addons, and plugins folders if needed - CreateComponentFolders(bDefaultIniLocation); - - delete [] buffer; - buffer = nullptr; - - LogNoticeF(L"Path: %s", m_Path.c_str()); - LogNoticeF(L"IniFile: %s", iniFile); - LogNoticeF(L"SkinPath: %s", m_SkinPath.c_str()); - - // Test that the Rainmeter.ini file is writable - TestSettingsFile(bDefaultIniLocation); - - System::Initialize(m_Instance); - - MeasureNet::InitializeStatic(); - MeasureCPU::InitializeStatic(); - MeterString::InitializeStatic(); - - // Tray must exist before skins are read - m_TrayWindow = new TrayWindow(); - m_TrayWindow->Initialize(); - - ReloadSettings(); - - if (m_SkinRegistry.IsEmpty()) - { - std::wstring error = GetFormattedString(ID_STR_NOAVAILABLESKINS, m_SkinPath.c_str()); - ShowMessage(nullptr, error.c_str(), MB_OK | MB_ICONERROR); - } - - ResetStats(); - ReadStats(); - - // Change the work area if necessary - if (m_DesktopWorkAreaChanged) - { - UpdateDesktopWorkArea(false); - } - - bool layoutLoaded = false; - if (layout) - { - std::vector args = CommandHandler::ParseString(layout); - layoutLoaded = (args.size() == 1 && LoadLayout(args[0])); - } - - if (!layoutLoaded) - { - ActivateActiveSkins(); - } - - if (dataFileCreated) - { - m_TrayWindow->ShowWelcomeNotification(); - } - else if (!m_DisableVersionCheck) - { - CheckUpdate(); - } - - return 0; // All is OK -} - -void Rainmeter::Finalize() -{ - KillTimer(m_Window, TIMER_NETSTATS); - - DeleteAllUnmanagedMeterWindows(); - DeleteAllMeterWindows(); - DeleteAllUnmanagedMeterWindows(); // Redelete unmanaged windows caused by OnCloseAction - - delete m_TrayWindow; - - System::Finalize(); - - MeasureNet::UpdateIFTable(); - MeasureNet::UpdateStats(); - WriteStats(true); - - MeasureNet::FinalizeStatic(); - MeasureCPU::FinalizeStatic(); - MeterString::FinalizeStatic(); - - // Change the work area back - if (m_DesktopWorkAreaChanged) - { - UpdateDesktopWorkArea(true); - } - - if (m_ResourceInstance) FreeLibrary(m_ResourceInstance); - if (m_Mutex) ReleaseMutex(m_Mutex); -} - -int Rainmeter::MessagePump() -{ - MSG msg; - BOOL ret; - - // Run the standard window message loop - while ((ret = GetMessage(&msg, nullptr, 0, 0)) != 0) - { - if (ret == -1) - { - break; - } - - if (!Dialog::HandleMessage(msg)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - return (int)msg.wParam; -} - -LRESULT CALLBACK Rainmeter::MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_DESTROY: - PostQuitMessage(0); - break; - - case WM_COPYDATA: - { - COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam; - if (cds) - { - const WCHAR* data = (const WCHAR*)cds->lpData; - if (cds->dwData == 1 && (cds->cbData > 0)) - { - Rainmeter::GetInstance().DelayedExecuteCommand(data); - } - } - } - break; - - case WM_TIMER: - if (wParam == TIMER_NETSTATS) - { - MeasureNet::UpdateIFTable(); - MeasureNet::UpdateStats(); - Rainmeter::GetInstance().WriteStats(false); - } - break; - - case WM_RAINMETER_DELAYED_REFRESH_ALL: - Rainmeter::GetInstance().RefreshAll(); - break; - - case WM_RAINMETER_DELAYED_EXECUTE: - if (lParam) - { - // Execute bang - WCHAR* bang = (WCHAR*)lParam; - Rainmeter::GetInstance().ExecuteCommand(bang, nullptr); - free(bang); // _wcsdup() - } - break; - - case WM_RAINMETER_EXECUTE: - if (Rainmeter::GetInstance().HasMeterWindow((MeterWindow*)wParam)) - { - Rainmeter::GetInstance().ExecuteCommand((const WCHAR*)lParam, (MeterWindow*)wParam); - } - break; - - default: - return DefWindowProc(hWnd, uMsg, wParam, lParam); - } - - return 0; -} - -void Rainmeter::SetNetworkStatisticsTimer() -{ - static bool set = SetTimer(m_Window, TIMER_NETSTATS, INTERVAL_NETSTATS, nullptr) != 0; -} - -void Rainmeter::CreateOptionsFile() -{ - CreateDirectory(m_SettingsPath.c_str(), nullptr); - - std::wstring defaultIni = GetDefaultLayoutPath(); - defaultIni += L"illustro default\\Rainmeter.ini"; - System::CopyFiles(defaultIni, m_IniFile); -} - -void Rainmeter::CreateDataFile() -{ - std::wstring tmpSz = m_SettingsPath + L"Plugins.ini"; - - const WCHAR* pluginsFile = tmpSz.c_str(); - const WCHAR* dataFile = m_DataFile.c_str(); - - if (_waccess(pluginsFile, 0) == 0) - { - MoveFile(pluginsFile, dataFile); - } - else - { - // Create empty file - HANDLE file = CreateFile(dataFile, GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr); - if (file != INVALID_HANDLE_VALUE) - { - CloseHandle(file); - } - } -} - -void Rainmeter::CreateComponentFolders(bool defaultIniLocation) -{ - std::wstring path; - - if (CreateDirectory(m_SkinPath.c_str(), nullptr)) - { - // Folder just created, so copy default skins there - std::wstring from = GetDefaultSkinPath(); - from += L"*.*"; - System::CopyFiles(from, m_SkinPath); - } - else - { - path = m_SkinPath; - path += L"Backup"; - if (_waccess(path.c_str(), 0) != -1) - { - std::wstring newPath = m_SkinPath + L"@Backup"; - MoveFile(path.c_str(), newPath.c_str()); - } - } - - path = GetLayoutPath(); - if (_waccess(path.c_str(), 0) == -1) - { - std::wstring themesPath = m_SettingsPath + L"Themes"; - if (_waccess(themesPath.c_str(), 0) != -1) - { - // Migrate Themes into Layouts for backwards compatibility and rename - // Rainmeter.thm to Rainmeter.ini and RainThemes.bmp to Wallpaper.bmp. - MoveFile(themesPath.c_str(), path.c_str()); - - path += L'*'; // For FindFirstFile. - WIN32_FIND_DATA fd; - HANDLE hFind = FindFirstFile(path.c_str(), &fd); - path.pop_back(); // Remove '*'. - - if (hFind != INVALID_HANDLE_VALUE) - { - do - { - if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && - PathUtil::IsDotOrDotDot(fd.cFileName)) - { - std::wstring layoutFolder = path + fd.cFileName; - layoutFolder += L'\\'; - - std::wstring file = layoutFolder + L"Rainmeter.thm"; - if (_waccess(file.c_str(), 0) != -1) - { - std::wstring newFile = layoutFolder + L"Rainmeter.ini"; - MoveFile(file.c_str(), newFile.c_str()); - } - - file = layoutFolder + L"RainThemes.bmp"; - if (_waccess(file.c_str(), 0) != -1) - { - std::wstring newFile = layoutFolder + L"Wallpaper.bmp"; - MoveFile(file.c_str(), newFile.c_str()); - } - } - } - while (FindNextFile(hFind, &fd)); - - FindClose(hFind); - } - } - else - { - std::wstring from = GetDefaultLayoutPath(); - if (_waccess(from.c_str(), 0) != -1) - { - System::CopyFiles(from, m_SettingsPath); - } - } - } - else - { - path += L"Backup"; - if (_waccess(path.c_str(), 0) != -1) - { - std::wstring newPath = GetLayoutPath(); - newPath += L"@Backup"; - MoveFile(path.c_str(), newPath.c_str()); - } - } - - if (defaultIniLocation) - { - path = GetUserPluginPath(); - if (_waccess(path.c_str(), 0) == -1) - { - std::wstring from = GetDefaultPluginPath(); - if (_waccess(from.c_str(), 0) != -1) - { - System::CopyFiles(from, m_SettingsPath); - } - } - - path = GetAddonPath(); - if (_waccess(path.c_str(), 0) == -1) - { - std::wstring from = GetDefaultAddonPath(); - if (_waccess(from.c_str(), 0) != -1) - { - System::CopyFiles(from, m_SettingsPath); - } - } - - path = m_SettingsPath; - path += L"Rainmeter.exe"; - const WCHAR* pathSz = path.c_str(); - if (_waccess(pathSz, 0) == -1) - { - // Create a hidden stub Rainmeter.exe into SettingsPath for old addon - // using relative path to Rainmeter.exe - std::wstring from = m_Path + L"Rainmeter.exe"; - System::CopyFiles(from, path); - - // Get rid of all resources from the stub executable - HANDLE stub = BeginUpdateResource(pathSz, TRUE); - - // Add the manifest of Rainmeter.dll to the stub - HRSRC manifest = FindResource(m_Instance, MAKEINTRESOURCE(2), RT_MANIFEST); - DWORD manifestSize = SizeofResource(m_Instance, manifest); - HGLOBAL manifestLoad = LoadResource(m_Instance, manifest); - void* manifestLoadData = LockResource(manifestLoad); - if (manifestLoadData) - { - LANGID langID = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); - UpdateResource(stub, RT_MANIFEST, MAKEINTRESOURCE(1), langID, manifestLoadData, manifestSize); - } - - EndUpdateResource(stub, FALSE); - SetFileAttributes(pathSz, FILE_ATTRIBUTE_HIDDEN); - } - } -} - -void Rainmeter::ReloadSettings() -{ - ScanForSkins(); - ScanForLayouts(); - ReadGeneralSettings(m_IniFile); -} - -void Rainmeter::EditSettings() -{ - std::wstring file = L'"' + m_IniFile; - file += L'"'; - CommandHandler::RunFile(m_SkinEditor.c_str(), file.c_str()); -} - -void Rainmeter::EditSkinFile(const std::wstring& name, const std::wstring& iniFile) -{ - std::wstring args = L'"' + m_SkinPath; - args += name; - args += L'\\'; - args += iniFile; - args += L'"'; - CommandHandler::RunFile(m_SkinEditor.c_str(), args.c_str()); -} - -void Rainmeter::OpenSkinFolder(const std::wstring& name) -{ - std::wstring folderPath = m_SkinPath + name; - CommandHandler::RunFile(folderPath.c_str()); -} - -void Rainmeter::ActivateActiveSkins() -{ - std::multimap::const_iterator iter = m_SkinOrders.begin(); - for ( ; iter != m_SkinOrders.end(); ++iter) - { - const SkinRegistry::Folder& skinFolder = m_SkinRegistry.GetFolder((*iter).second); - if (skinFolder.active > 0 && skinFolder.active <= (uint16_t)skinFolder.files.size()) - { - ActivateSkin((*iter).second, skinFolder.active - 1); - } - } -} - -/* -** Activates the skin, or, if it is already active, the next variant of the skin. Returns true -** if the skin was activated (or was already active). -*/ -bool Rainmeter::ActivateSkin(const std::wstring& folderPath) -{ - const int index = m_SkinRegistry.FindFolderIndex(folderPath); - if (index != -1) - { - const SkinRegistry::Folder& skinFolder = m_SkinRegistry.GetFolder(index); - if (!(skinFolder.active == 1 && skinFolder.files.size() == 1)) - { - // Activate the next index. - ActivateSkin( - index, (skinFolder.active < skinFolder.files.size()) ? skinFolder.active : 0); - } - - return true; - } - - return false; -} - -/* -** Activates the skin, or, if it is already active, the next variant of the skin. Returns true -** if the skin was activated (or was already active). -*/ -bool Rainmeter::ActivateSkin(const std::wstring& folderPath, const std::wstring& file) -{ - const SkinRegistry::Indexes indexes = m_SkinRegistry.FindIndexes(folderPath, file); - if (indexes.IsValid()) - { - ActivateSkin(indexes.folder, indexes.file); - return true; - } - - return false; -} - -void Rainmeter::ActivateSkin(int folderIndex, int fileIndex) -{ - if (folderIndex >= 0 && folderIndex < m_SkinRegistry.GetFolderCount() && - fileIndex >= 0 && fileIndex < m_SkinRegistry.GetFolder(folderIndex).files.size()) - { - auto& skinFolder = m_SkinRegistry.GetFolder(folderIndex); - const std::wstring& file = skinFolder.files[fileIndex]; - const WCHAR* fileSz = file.c_str(); - - std::wstring folderPath = m_SkinRegistry.GetFolderPath(folderIndex); - - // Verify that the skin is not already active - std::map::const_iterator iter = m_MeterWindows.find(folderPath); - if (iter != m_MeterWindows.end()) - { - if (wcscmp(((*iter).second)->GetFileName().c_str(), fileSz) == 0) - { - LogWarningF((*iter).second, L"!ActivateConfig: \"%s\" already active", folderPath.c_str()); - return; - } - else - { - // Deactivate the existing skin - DeactivateSkin((*iter).second, folderIndex); - } - } - - // Verify whether the ini-file exists - std::wstring skinIniPath = m_SkinPath + folderPath; - skinIniPath += L'\\'; - skinIniPath += file; - - if (_waccess(skinIniPath.c_str(), 0) == -1) - { - std::wstring message = GetFormattedString(ID_STR_UNABLETOACTIVATESKIN, folderPath.c_str(), fileSz); - ShowMessage(nullptr, message.c_str(), MB_OK | MB_ICONEXCLAMATION); - return; - } - - if (skinFolder.active != fileIndex + 1) - { - // Write only if changed. - skinFolder.active = fileIndex + 1; - WriteActive(folderPath, fileIndex); - } - - CreateMeterWindow(folderPath, file); - } -} - -void Rainmeter::DeactivateSkin(MeterWindow* meterWindow, int folderIndex, bool save) -{ - if (folderIndex >= 0 && folderIndex < m_SkinRegistry.GetFolderCount()) - { - m_SkinRegistry.GetFolder(folderIndex).active = 0; // Deactivate the skin - } - else if (folderIndex == -1 && meterWindow) - { - SkinRegistry::Folder* folder = m_SkinRegistry.FindFolder(meterWindow->GetFolderPath()); - if (folder) - { - folder->active = 0; - } - } - - if (meterWindow) - { - if (save) - { - // Disable the skin in the ini-file - WriteActive(meterWindow->GetFolderPath(), -1); - } - - meterWindow->Deactivate(); - } -} - -void Rainmeter::ToggleSkin(int folderIndex, int fileIndex) -{ - if (folderIndex >= 0 && folderIndex < m_SkinRegistry.GetFolderCount() && - fileIndex >= 0 && fileIndex < m_SkinRegistry.GetFolder(folderIndex).files.size()) - { - if (m_SkinRegistry.GetFolder(folderIndex).active == fileIndex + 1) - { - MeterWindow* meterWindow = GetMeterWindow(m_SkinRegistry.GetFolderPath(folderIndex)); - DeactivateSkin(meterWindow, folderIndex); - } - else - { - ActivateSkin(folderIndex, fileIndex); - } - } -} - -void Rainmeter::ToggleSkinWithID(UINT id) -{ - const SkinRegistry::Indexes indexes = m_SkinRegistry.FindIndexesForID(id); - if (indexes.IsValid()) - { - ToggleSkin(indexes.folder, indexes.file); - } -} - -void Rainmeter::SetSkinPath(const std::wstring& skinPath) -{ - WritePrivateProfileString(L"Rainmeter", L"SkinPath", skinPath.c_str(), m_IniFile.c_str()); -} - -void Rainmeter::SetSkinEditor(const std::wstring& path) -{ - if (!path.empty()) - { - m_SkinEditor = path; - WritePrivateProfileString(L"Rainmeter", L"ConfigEditor", path.c_str(), m_IniFile.c_str()); - } -} - -void Rainmeter::WriteActive(const std::wstring& folderPath, int fileIndex) -{ - WCHAR buffer[32]; - _itow_s(fileIndex + 1, buffer, 10); - WritePrivateProfileString(folderPath.c_str(), L"Active", buffer, m_IniFile.c_str()); -} - -void Rainmeter::CreateMeterWindow(const std::wstring& folderPath, const std::wstring& file) -{ - MeterWindow* mw = new MeterWindow(folderPath, file); - - // Note: May modify existing key - m_MeterWindows[folderPath] = mw; - - mw->Initialize(); - - DialogAbout::UpdateSkins(); - DialogManage::UpdateSkins(mw); -} - -void Rainmeter::DeleteAllMeterWindows() -{ - auto it = m_MeterWindows.cbegin(); - while (it != m_MeterWindows.cend()) - { - MeterWindow* mw = (*it).second; - m_MeterWindows.erase(it); // Remove before deleting MeterWindow - - DialogManage::UpdateSkins(mw, true); - delete mw; - - // Get next valid iterator (Fix for iterator invalidation caused by OnCloseAction) - it = m_MeterWindows.cbegin(); - } - - m_MeterWindows.clear(); - DialogAbout::UpdateSkins(); -} - -void Rainmeter::DeleteAllUnmanagedMeterWindows() -{ - for (auto it = m_UnmanagedMeterWindows.cbegin(); it != m_UnmanagedMeterWindows.cend(); ++it) - { - delete (*it); - } - - m_UnmanagedMeterWindows.clear(); -} - -/* -** Removes the skin from m_MeterWindows. The skin should delete itself. -** -*/ -void Rainmeter::RemoveMeterWindow(MeterWindow* meterWindow) -{ - for (auto it = m_MeterWindows.cbegin(); it != m_MeterWindows.cend(); ++it) - { - if ((*it).second == meterWindow) - { - m_MeterWindows.erase(it); - DialogManage::UpdateSkins(meterWindow, true); - DialogAbout::UpdateSkins(); - break; - } - } -} - -/* -** Adds the skin to m_UnmanagedMeterWindows. The skin should remove itself by calling RemoveUnmanagedMeterWindow(). -** -*/ -void Rainmeter::AddUnmanagedMeterWindow(MeterWindow* meterWindow) -{ - for (auto it = m_UnmanagedMeterWindows.cbegin(); it != m_UnmanagedMeterWindows.cend(); ++it) - { - if ((*it) == meterWindow) // already added - { - return; - } - } - - m_UnmanagedMeterWindows.push_back(meterWindow); -} - -void Rainmeter::RemoveUnmanagedMeterWindow(MeterWindow* meterWindow) -{ - for (auto it = m_UnmanagedMeterWindows.cbegin(); it != m_UnmanagedMeterWindows.cend(); ++it) - { - if ((*it) == meterWindow) - { - m_UnmanagedMeterWindows.erase(it); - break; - } - } -} - -bool Rainmeter::HasMeterWindow(const MeterWindow* meterWindow) const -{ - for (auto it = m_MeterWindows.begin(); it != m_MeterWindows.end(); ++it) - { - if ((*it).second == meterWindow) - { - return true; - } - } - - return false; -} - -MeterWindow* Rainmeter::GetMeterWindow(const std::wstring& folderPath) -{ - const WCHAR* folderSz = folderPath.c_str(); - std::map::const_iterator iter = m_MeterWindows.begin(); - for (; iter != m_MeterWindows.end(); ++iter) - { - if (_wcsicmp((*iter).first.c_str(), folderSz) == 0) - { - return (*iter).second; - } - } - - return nullptr; -} - -MeterWindow* Rainmeter::GetMeterWindowByINI(const std::wstring& ini_searching) -{ - if (_wcsnicmp(m_SkinPath.c_str(), ini_searching.c_str(), m_SkinPath.length()) == 0) - { - const std::wstring config_searching = ini_searching.substr(m_SkinPath.length()); - - std::map::const_iterator iter = m_MeterWindows.begin(); - for (; iter != m_MeterWindows.end(); ++iter) - { - std::wstring config_current = (*iter).second->GetFolderPath() + L'\\'; - config_current += (*iter).second->GetFileName(); - - if (_wcsicmp(config_current.c_str(), config_searching.c_str()) == 0) - { - return (*iter).second; - } - } - } - - return nullptr; -} - -MeterWindow* Rainmeter::GetMeterWindow(HWND hwnd) -{ - std::map::const_iterator iter = m_MeterWindows.begin(); - for (; iter != m_MeterWindows.end(); ++iter) - { - if ((*iter).second->GetWindow() == hwnd) - { - return (*iter).second; - } - } - - return nullptr; -} - -void Rainmeter::GetMeterWindowsByLoadOrder(std::multimap& windows, const std::wstring& group) -{ - std::map::const_iterator iter = m_MeterWindows.begin(); - for (; iter != m_MeterWindows.end(); ++iter) - { - MeterWindow* mw = (*iter).second; - if (mw && (group.empty() || mw->BelongsToGroup(group))) - { - windows.insert(std::pair(GetLoadOrder((*iter).first), mw)); - } - } -} - -void Rainmeter::SetLoadOrder(int folderIndex, int order) -{ - std::multimap::iterator iter = m_SkinOrders.begin(); - for ( ; iter != m_SkinOrders.end(); ++iter) - { - if ((*iter).second == folderIndex) // already exists - { - if ((*iter).first != order) - { - m_SkinOrders.erase(iter); - break; - } - else - { - return; - } - } - } - - m_SkinOrders.insert(std::pair(order, folderIndex)); -} - -int Rainmeter::GetLoadOrder(const std::wstring& folderPath) -{ - const int index = m_SkinRegistry.FindFolderIndex(folderPath); - if (index != -1) - { - std::multimap::const_iterator iter = m_SkinOrders.begin(); - for ( ; iter != m_SkinOrders.end(); ++iter) - { - if ((*iter).second == index) - { - return (*iter).first; - } - } - } - - // LoadOrder not specified - return 0; -} - -/* -** Scans all the subfolders and locates the ini-files. -*/ -void Rainmeter::ScanForSkins() -{ - m_SkinRegistry.Populate(m_SkinPath); - m_SkinOrders.clear(); -} - -/* -** Scans the given folder for layouts -*/ -void Rainmeter::ScanForLayouts() -{ - m_Layouts.clear(); - - WIN32_FIND_DATA fileData; // Data structure describes the file found - HANDLE hSearch; // Search handle returned by FindFirstFile - - // Scan for folders - std::wstring folders = GetLayoutPath(); - folders += L'*'; - - hSearch = FindFirstFileEx( - folders.c_str(), - (IsWindows7OrGreater()) ? FindExInfoBasic : FindExInfoStandard, - &fileData, - FindExSearchNameMatch, - nullptr, - 0); - - if (hSearch != INVALID_HANDLE_VALUE) - { - do - { - if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && - !PathUtil::IsDotOrDotDot(fileData.cFileName)) - { - m_Layouts.push_back(fileData.cFileName); - } - } - while (FindNextFile(hSearch, &fileData)); - - FindClose(hSearch); - } - - DialogManage::UpdateLayouts(); -} - -void Rainmeter::ExecuteBang(const WCHAR* bang, std::vector& args, MeterWindow* meterWindow) -{ - m_CommandHandler.ExecuteBang(bang, args, meterWindow); -} - -/* -** Runs the given command or bang -** -*/ -void Rainmeter::ExecuteCommand(const WCHAR* command, MeterWindow* meterWindow, bool multi) -{ - m_CommandHandler.ExecuteCommand(command, meterWindow, multi); -} - -/* -** Executes command when current processing is done. -** -*/ -void Rainmeter::DelayedExecuteCommand(const WCHAR* command) -{ - WCHAR* bang = _wcsdup(command); - PostMessage(m_Window, WM_RAINMETER_DELAYED_EXECUTE, (WPARAM)nullptr, (LPARAM)bang); -} - -/* -** Reads the general settings from the Rainmeter.ini file -** -*/ -void Rainmeter::ReadGeneralSettings(const std::wstring& iniFile) -{ - WCHAR buffer[MAX_PATH]; - - // Clear old settings - m_DesktopWorkAreas.clear(); - - ConfigParser parser; - parser.Initialize(iniFile, nullptr, nullptr); - - m_UseD2D = parser.ReadBool(L"Rainmeter", L"UseD2D", true); - - m_Debug = parser.ReadBool(L"Rainmeter", L"Debug", false); - - // Read Logging settings - Logger& logger = GetLogger(); - const bool logging = parser.ReadBool(L"Rainmeter", L"Logging", false); - logger.SetLogToFile(logging); - if (logging) - { - logger.StartLogFile(); - } - - if (m_TrayWindow) - { - m_TrayWindow->ReadOptions(parser); - } - - m_GlobalOptions.netInSpeed = parser.ReadFloat(L"Rainmeter", L"NetInSpeed", 0.0); - m_GlobalOptions.netOutSpeed = parser.ReadFloat(L"Rainmeter", L"NetOutSpeed", 0.0); - - m_DisableDragging = parser.ReadBool(L"Rainmeter", L"DisableDragging", false); - m_DisableRDP = parser.ReadBool(L"Rainmeter", L"DisableRDP", false); - - m_SkinEditor = parser.ReadString(L"Rainmeter", L"ConfigEditor", L""); - if (m_SkinEditor.empty()) - { - // Get the program path associated with .ini files - DWORD cchOut = MAX_PATH; - HRESULT hr = AssocQueryString(ASSOCF_NOTRUNCATE, ASSOCSTR_EXECUTABLE, L".ini", L"open", buffer, &cchOut); - m_SkinEditor = (SUCCEEDED(hr) && cchOut > 0) ? buffer : L"Notepad"; - } - - if (m_Debug) - { - LogNoticeF(L"ConfigEditor: %s", m_SkinEditor.c_str()); - } - - m_TrayExecuteR = parser.ReadString(L"Rainmeter", L"TrayExecuteR", L"", false); - m_TrayExecuteM = parser.ReadString(L"Rainmeter", L"TrayExecuteM", L"", false); - m_TrayExecuteDR = parser.ReadString(L"Rainmeter", L"TrayExecuteDR", L"", false); - m_TrayExecuteDM = parser.ReadString(L"Rainmeter", L"TrayExecuteDM", L"", false); - - m_DisableVersionCheck = parser.ReadBool(L"Rainmeter", L"DisableVersionCheck", false); - - const std::wstring& area = parser.ReadString(L"Rainmeter", L"DesktopWorkArea", L""); - if (!area.empty()) - { - m_DesktopWorkAreas[0] = parser.ParseRECT(area.c_str()); - m_DesktopWorkAreaChanged = true; - } - - const size_t monitorCount = System::GetMonitorCount(); - for (UINT i = 1; i <= monitorCount; ++i) - { - _snwprintf_s(buffer, _TRUNCATE, L"DesktopWorkArea@%i", (int)i); - const std::wstring& area = parser.ReadString(L"Rainmeter", buffer, L""); - if (!area.empty()) - { - m_DesktopWorkAreas[i] = parser.ParseRECT(area.c_str()); - m_DesktopWorkAreaChanged = true; - } - } - - m_DesktopWorkAreaType = parser.ReadBool(L"Rainmeter", L"DesktopWorkAreaType", false); - - m_NormalStayDesktop = parser.ReadBool(L"Rainmeter", L"NormalStayDesktop", true); - - for (auto iter = parser.GetSections().cbegin(); iter != parser.GetSections().end(); ++iter) - { - const WCHAR* section = (*iter).c_str(); - - if (wcscmp(section, L"Rainmeter") == 0 || - wcscmp(section, L"TrayMeasure") == 0) - { - continue; - } - - const int index = m_SkinRegistry.FindFolderIndex(*iter); - if (index == -1) - { - continue; - } - - SkinRegistry::Folder& skinFolder = m_SkinRegistry.GetFolder(index); - - // Make sure there is a ini file available - int active = parser.ReadInt(section, L"Active", 0); - if (active > 0 && active <= (int)skinFolder.files.size()) - { - skinFolder.active = active; - } - - int order = parser.ReadInt(section, L"LoadOrder", 0); - SetLoadOrder(index, order); - } -} - -/* -** Refreshes all active meter windows. -** Note: This function calls MeterWindow::Refresh() directly for synchronization. Be careful about crash. -** -*/ -void Rainmeter::RefreshAll() -{ - // Read skins and settings - ReloadSettings(); - - // Change the work area if necessary - if (m_DesktopWorkAreaChanged) - { - UpdateDesktopWorkArea(false); - } - - // Make the sending order by using LoadOrder - std::multimap windows; - GetMeterWindowsByLoadOrder(windows); - - // Prepare the helper window - System::PrepareHelperWindow(); - - // Refresh all - std::multimap::const_iterator iter = windows.begin(); - for ( ; iter != windows.end(); ++iter) - { - MeterWindow* mw = (*iter).second; - if (mw) - { - // Verify whether the cached information is valid - const int index = m_SkinRegistry.FindFolderIndex(mw->GetFolderPath()); - if (index != -1) - { - SkinRegistry::Folder& skinFolder = m_SkinRegistry.GetFolder(index); - const WCHAR* skinIniFile = mw->GetFileName().c_str(); - - bool found = false; - for (int i = 0, isize = (int)skinFolder.files.size(); i < isize; ++i) - { - if (_wcsicmp(skinIniFile, skinFolder.files[i].c_str()) == 0) - { - found = true; - if (skinFolder.active != i + 1) - { - // Switch to new ini-file order - skinFolder.active = i + 1; - WriteActive(mw->GetFolderPath(), i); - } - break; - } - } - - if (!found) - { - const WCHAR* skinFolderPath = mw->GetFolderPath().c_str(); - std::wstring error = GetFormattedString(ID_STR_UNABLETOREFRESHSKIN, skinFolderPath, skinIniFile); - - DeactivateSkin(mw, index); - - ShowMessage(nullptr, error.c_str(), MB_OK | MB_ICONEXCLAMATION); - continue; - } - } - else - { - const WCHAR* skinFolderPath = mw->GetFolderPath().c_str(); - std::wstring error = GetFormattedString(ID_STR_UNABLETOREFRESHSKIN, skinFolderPath, L""); - - DeactivateSkin(mw, -2); // -2 = Force deactivate - - ShowMessage(nullptr, error.c_str(), MB_OK | MB_ICONEXCLAMATION); - continue; - } - - mw->Refresh(false, true); - } - } - - DialogAbout::UpdateSkins(); - DialogManage::UpdateSkins(nullptr); -} - -bool Rainmeter::LoadLayout(const std::wstring& name) -{ - // Replace Rainmeter.ini with layout - std::wstring layout = GetLayoutPath(); - layout += name; - std::wstring wallpaper = layout + L"\\Wallpaper.bmp"; - layout += L"\\Rainmeter.ini"; - - if (_waccess(layout.c_str(), 0) == -1) - { - return false; - } - - DeleteAllUnmanagedMeterWindows(); - DeleteAllMeterWindows(); - - std::wstring backup = GetLayoutPath(); - backup += L"@Backup"; - CreateDirectory(backup.c_str(), nullptr); - backup += L"\\Rainmeter.ini"; - - bool backupLayout = (_wcsicmp(name.c_str(), L"@Backup") == 0); - if (!backupLayout) - { - // Make a copy of current Rainmeter.ini - System::CopyFiles(m_IniFile, backup); - } - - System::CopyFiles(layout, m_IniFile); - - if (!backupLayout) - { - PreserveSetting(backup, L"SkinPath"); - PreserveSetting(backup, L"ConfigEditor"); - PreserveSetting(backup, L"LogViewer"); - PreserveSetting(backup, L"Logging"); - PreserveSetting(backup, L"DisableVersionCheck"); - PreserveSetting(backup, L"Language"); - PreserveSetting(backup, L"NormalStayDesktop"); - PreserveSetting(backup, L"TrayExecuteM", false); - PreserveSetting(backup, L"TrayExecuteR", false); - PreserveSetting(backup, L"TrayExecuteDM", false); - PreserveSetting(backup, L"TrayExecuteDR", false); - PreserveSetting(backup, L"UseD2D"); - - // Set wallpaper if it exists - if (_waccess(wallpaper.c_str(), 0) != -1) - { - SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)wallpaper.c_str(), SPIF_UPDATEINIFILE); - } - } - - ReloadSettings(); - - // Create meter windows for active skins - ActivateActiveSkins(); - - return true; -} - -void Rainmeter::PreserveSetting(const std::wstring& from, LPCTSTR key, bool replace) -{ - WCHAR* buffer = new WCHAR[MAX_LINE_LENGTH]; - - if ((replace || GetPrivateProfileString(L"Rainmeter", key, L"", buffer, 4, m_IniFile.c_str()) == 0) && - GetPrivateProfileString(L"Rainmeter", key, L"", buffer, MAX_LINE_LENGTH, from.c_str()) > 0) - { - WritePrivateProfileString(L"Rainmeter", key, buffer, m_IniFile.c_str()); - } - - delete [] buffer; -} - -/* -** Applies given DesktopWorkArea and DesktopWorkArea@n. -** -*/ -void Rainmeter::UpdateDesktopWorkArea(bool reset) -{ - bool changed = false; - - if (reset) - { - if (!m_OldDesktopWorkAreas.empty()) - { - int i = 1; - for (auto iter = m_OldDesktopWorkAreas.cbegin(); iter != m_OldDesktopWorkAreas.cend(); ++iter, ++i) - { - RECT r = (*iter); - - BOOL result = SystemParametersInfo(SPI_SETWORKAREA, 0, &r, 0); - - if (m_Debug) - { - std::wstring format = L"Resetting WorkArea@%i: L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)"; - if (!result) - { - format += L" => FAIL"; - } - LogDebugF(format.c_str(), i, r.left, r.top, r.right, r.bottom, r.right - r.left, r.bottom - r.top); - } - } - changed = true; - } - } - else - { - const size_t numOfMonitors = System::GetMonitorCount(); - const MultiMonitorInfo& monitorsInfo = System::GetMultiMonitorInfo(); - const std::vector& monitors = monitorsInfo.monitors; - - if (m_OldDesktopWorkAreas.empty()) - { - // Store old work areas for changing them back - for (size_t i = 0; i < numOfMonitors; ++i) - { - m_OldDesktopWorkAreas.push_back(monitors[i].work); - } - } - - if (m_Debug) - { - LogDebugF(L"DesktopWorkAreaType: %s", m_DesktopWorkAreaType ? L"Margin" : L"Default"); - } - - for (UINT i = 0; i <= numOfMonitors; ++i) - { - std::map::const_iterator it = m_DesktopWorkAreas.find(i); - if (it != m_DesktopWorkAreas.end()) - { - RECT r = (*it).second; - - // Move rect to correct offset - if (m_DesktopWorkAreaType) - { - RECT margin = r; - r = (i == 0) ? monitors[monitorsInfo.primary - 1].screen : monitors[i - 1].screen; - r.left += margin.left; - r.top += margin.top; - r.right -= margin.right; - r.bottom -= margin.bottom; - } - else - { - if (i != 0) - { - const RECT screenRect = monitors[i - 1].screen; - r.left += screenRect.left; - r.top += screenRect.top; - r.right += screenRect.left; - r.bottom += screenRect.top; - } - } - - BOOL result = SystemParametersInfo(SPI_SETWORKAREA, 0, &r, 0); - if (result) - { - changed = true; - } - - if (m_Debug) - { - std::wstring format = L"Applying DesktopWorkArea"; - if (i != 0) - { - WCHAR buffer[64]; - size_t len = _snwprintf_s(buffer, _TRUNCATE, L"@%i", i); - format.append(buffer, len); - } - format += L": L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)"; - if (!result) - { - format += L" => FAIL"; - } - LogDebugF(format.c_str(), r.left, r.top, r.right, r.bottom, r.right - r.left, r.bottom - r.top); - } - } - } - } - - if (changed && System::GetWindow()) - { - // Update System::MultiMonitorInfo for for work area variables - SendMessageTimeout(System::GetWindow(), WM_SETTINGCHANGE, SPI_SETWORKAREA, 0, SMTO_ABORTIFHUNG, 1000, nullptr); - } -} - -/* -** Reads the statistics from the ini-file -** -*/ -void Rainmeter::ReadStats() -{ - const WCHAR* statsFile = m_StatsFile.c_str(); - - // If m_StatsFile doesn't exist, create it and copy the stats section from m_IniFile - if (_waccess(statsFile, 0) == -1) - { - const WCHAR* iniFile = m_IniFile.c_str(); - WCHAR* tmpSz = new WCHAR[SHRT_MAX]; // Max size returned by GetPrivateProfileSection() - - if (GetPrivateProfileSection(L"Statistics", tmpSz, SHRT_MAX, iniFile) > 0) - { - WritePrivateProfileString(L"Statistics", nullptr, nullptr, iniFile); - } - else - { - tmpSz[0] = tmpSz[1] = L'\0'; - } - WritePrivateProfileSection(L"Statistics", tmpSz, statsFile); - - delete [] tmpSz; - } - - // Only Net measure has stats at the moment - MeasureNet::ReadStats(m_StatsFile, m_StatsDate); -} - -/* -** Writes the statistics to the ini-file. If bForce is false the stats are written only once per an appropriate interval. -** -*/ -void Rainmeter::WriteStats(bool bForce) -{ - static ULONGLONG lastWrite = 0; - - ULONGLONG ticks = System::GetTickCount64(); - - if (bForce || (lastWrite + INTERVAL_NETSTATS < ticks)) - { - lastWrite = ticks; - - // Only Net measure has stats at the moment - const WCHAR* statsFile = m_StatsFile.c_str(); - MeasureNet::WriteStats(statsFile, m_StatsDate); - - WritePrivateProfileString(nullptr, nullptr, nullptr, statsFile); - } -} - -/* -** Clears the statistics -** -*/ -void Rainmeter::ResetStats() -{ - // Set the stats-date string - tm* newtime; - time_t long_time; - time(&long_time); - newtime = localtime(&long_time); - m_StatsDate = _wasctime(newtime); - m_StatsDate.erase(m_StatsDate.size() - 1); - - // Only Net measure has stats at the moment - MeasureNet::ResetStats(); -} - -/* -** Wraps MessageBox(). Sets RTL flag if necessary. -** -*/ -int Rainmeter::ShowMessage(HWND parent, const WCHAR* text, UINT type) -{ - type |= MB_TOPMOST; - - if (*GetString(ID_STR_ISRTL) == L'1') - { - type |= MB_RTLREADING; - } - - return MessageBox(parent, text, APPNAME, type); -}; - -void Rainmeter::ShowLogFile() -{ - std::wstring logFile = L'"' + GetLogger().GetLogFilePath(); - logFile += L'"'; - - CommandHandler::RunFile(m_SkinEditor.c_str(), logFile.c_str()); -} - -void Rainmeter::SetDebug(bool debug) -{ - m_Debug = debug; - WritePrivateProfileString(L"Rainmeter", L"Debug", debug ? L"1" : L"0", m_IniFile.c_str()); -} - -void Rainmeter::SetDisableDragging(bool dragging) -{ - m_DisableDragging = dragging; - WritePrivateProfileString(L"Rainmeter", L"DisableDragging", dragging ? L"1" : L"0", m_IniFile.c_str()); -} - -void Rainmeter::SetDisableVersionCheck(bool check) -{ - m_DisableVersionCheck = check; - WritePrivateProfileString(L"Rainmeter", L"DisableVersionCheck", check ? L"1" : L"0" , m_IniFile.c_str()); -} - -void Rainmeter::TestSettingsFile(bool bDefaultIniLocation) -{ - const WCHAR* iniFile = m_IniFile.c_str(); - if (!System::IsFileWritable(iniFile)) - { - std::wstring error = GetString(ID_STR_SETTINGSNOTWRITABLE); - - if (!bDefaultIniLocation) - { - std::wstring strTarget = L"%APPDATA%\\Rainmeter\\"; - PathUtil::ExpandEnvironmentVariables(strTarget); - - error += GetFormattedString(ID_STR_SETTINGSMOVEFILE, iniFile, strTarget.c_str()); - } - else - { - error += GetFormattedString(ID_STR_SETTINGSREADONLY, iniFile); - } - - ShowMessage(nullptr, error.c_str(), MB_OK | MB_ICONERROR); - } -} - -void Rainmeter::SetUseD2D(bool enabled) -{ - m_UseD2D = enabled; - - // Save to Rainmeter.ini - WritePrivateProfileString(L"Rainmeter", L"UseD2D", enabled ? L"1" : L"0", m_IniFile.c_str()); - - RefreshAll(); -} +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../Common/PathUtil.h" +#include "Rainmeter.h" +#include "TrayWindow.h" +#include "System.h" +#include "Error.h" +#include "DialogAbout.h" +#include "DialogManage.h" +#include "MeasureNet.h" +#include "MeasureCPU.h" +#include "MeterString.h" +#include "UpdateCheck.h" +#include "../Version.h" + +using namespace Gdiplus; + +enum TIMER +{ + TIMER_NETSTATS = 1 +}; +enum INTERVAL +{ + INTERVAL_NETSTATS = 120000 +}; + +/* +** Initializes Rainmeter. +** +*/ +int RainmeterMain(LPWSTR cmdLine) +{ + auto& rainmeter = Rainmeter::GetInstance(); + int ret = rainmeter.Initialize(nullptr, nullptr); + if (ret == 0) + { + ret = rainmeter.MessagePump(); + } + rainmeter.Finalize(); + + return ret; +} + +/* +** Initializes Rainmeter. +** +*/ +void* Rainmeter_Initialize() +{ + int res = Rainmeter::GetInstance().Initialize(nullptr, nullptr); + + // Success? + if (res == 0) + return &Rainmeter::GetInstance(); + + return nullptr; +} + +/* +** Finalizes Rainmeter. +** +*/ +void Rainmeter_Finalize(void* ptr) +{ + Rainmeter* rainmeter = (Rainmeter*)ptr; + rainmeter->Finalize(); +} + +/* +** Constructor +** +*/ +Rainmeter::Rainmeter() : + m_TrayWindow(), + m_UseD2D(true), + m_Debug(false), + m_DisableVersionCheck(false), + m_NewVersion(false), + m_DesktopWorkAreaChanged(false), + m_DesktopWorkAreaType(false), + m_NormalStayDesktop(true), + m_DisableRDP(false), + m_DisableDragging(false), + m_CurrentParser(), + m_Window(), + m_Mutex(), + m_Instance(), + m_ResourceInstance(), + m_ResourceLCID(), + m_GDIplusToken(), + m_GlobalOptions() +{ + CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + + InitCommonControls(); + + // Initialize GDI+. + GdiplusStartupInput gdiplusStartupInput; + GdiplusStartup(&m_GDIplusToken, &gdiplusStartupInput, nullptr); +} + +/* +** Destructor +** +*/ +Rainmeter::~Rainmeter() +{ + CoUninitialize(); + + GdiplusShutdown(m_GDIplusToken); +} + +Rainmeter& Rainmeter::GetInstance() +{ + static Rainmeter s_Rainmeter; + return s_Rainmeter; +} + +/* +** The main initialization function for the module. +** +*/ +int Rainmeter::Initialize(LPCWSTR iniPath, LPCWSTR layout) +{ + m_Instance = GetModuleHandle(L"Rainmeter"); + + WCHAR* buffer = new WCHAR[MAX_LINE_LENGTH]; + GetModuleFileName(m_Instance, buffer, MAX_LINE_LENGTH); + + // Remove the module's name from the path + WCHAR* pos = wcsrchr(buffer, L'\\'); + m_Path.assign(buffer, pos ? pos - buffer + 1 : 0); + m_Drive = PathUtil::GetVolume(m_Path); + + bool bDefaultIniLocation = false; + if (iniPath) + { + // The command line defines the location of Rainmeter.ini (or whatever it calls it). + std::wstring iniFile = iniPath; + PathUtil::ExpandEnvironmentVariables(iniFile); + + if (iniFile.empty() || PathUtil::IsSeparator(iniFile[iniFile.length() - 1])) + { + iniFile += L"Rainmeter.ini"; + } + else if (iniFile.length() <= 4 || _wcsicmp(iniFile.c_str() + (iniFile.length() - 4), L".ini") != 0) + { + iniFile += L"\\Rainmeter.ini"; + } + + if (!PathUtil::IsSeparator(iniFile[0]) && iniFile.find_first_of(L':') == std::wstring::npos) + { + // Make absolute path + iniFile.insert(0, m_Path); + } + + m_IniFile = iniFile; + bDefaultIniLocation = true; + } + else + { + m_IniFile = m_Path; + m_IniFile += L"Rainmeter.ini"; + + // If the ini file doesn't exist in the program folder store it to the %APPDATA% instead so that things work better in Vista/Win7 + if (_waccess(m_IniFile.c_str(), 0) == -1) + { + m_IniFile = L"%APPDATA%\\Rainmeter\\Rainmeter.ini"; + PathUtil::ExpandEnvironmentVariables(m_IniFile); + bDefaultIniLocation = true; + } + } + + WNDCLASS wc = {0}; + wc.lpfnWndProc = (WNDPROC)MainWndProc; + wc.hInstance = m_Instance; + wc.lpszClassName = RAINMETER_CLASS_NAME; + ATOM className = RegisterClass(&wc); + + m_Window = CreateWindowEx( + WS_EX_TOOLWINDOW, + MAKEINTATOM(className), + RAINMETER_WINDOW_NAME, + WS_POPUP | WS_DISABLED, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + nullptr, + nullptr, + m_Instance, + nullptr); + + if (!m_Window) return 1; + + Logger& logger = GetLogger(); + const WCHAR* iniFile = m_IniFile.c_str(); + + // Set file locations + { + m_SettingsPath = PathUtil::GetFolderFromFilePath(m_IniFile); + + size_t len = m_IniFile.length(); + if (len > 4 && _wcsicmp(iniFile + (len - 4), L".ini") == 0) + { + len -= 4; + } + + std::wstring logFile(m_IniFile, 0, len); + m_DataFile = m_StatsFile = logFile; + logFile += L".log"; + m_StatsFile += L".stats"; + m_DataFile += L".data"; + + logger.SetLogFilePath(logFile); + } + + // Create a default Rainmeter.ini file if needed + if (_waccess(iniFile, 0) == -1) + { + CreateOptionsFile(); + } + + bool dataFileCreated = false; + if (_waccess(m_DataFile.c_str(), 0) == -1) + { + dataFileCreated = true; + CreateDataFile(); + } + + // Reset log file + System::RemoveFile(logger.GetLogFilePath()); + + m_Debug = 0!=GetPrivateProfileInt(L"Rainmeter", L"Debug", 0, iniFile); + + const bool logging = GetPrivateProfileInt(L"Rainmeter", L"Logging", 0, iniFile) != 0; + logger.SetLogToFile(logging); + if (logging) + { + logger.StartLogFile(); + } + + // Determine the language resource to load + std::wstring resource = m_Path + L"Languages\\"; + if (GetPrivateProfileString(L"Rainmeter", L"Language", L"", buffer, MAX_LINE_LENGTH, iniFile) == 0) + { + // Use whatever the user selected for the installer + DWORD size = MAX_LINE_LENGTH; + HKEY hKey; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Rainmeter", 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &hKey) == ERROR_SUCCESS) + { + DWORD type = 0; + if (RegQueryValueEx(hKey, L"Language", nullptr, &type, (LPBYTE)buffer, (LPDWORD)&size) != ERROR_SUCCESS || + type != REG_SZ) + { + buffer[0] = L'\0'; + } + RegCloseKey(hKey); + } + } + if (buffer[0] != L'\0') + { + // Try selected language + m_ResourceLCID = wcstoul(buffer, nullptr, 10); + resource += buffer; + resource += L".dll"; + + m_ResourceInstance = LoadLibraryEx(resource.c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); + } + if (!m_ResourceInstance) + { + // Try English + resource = m_Path; + resource += L"Languages\\1033.dll"; + m_ResourceInstance = LoadLibraryEx(resource.c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); + m_ResourceLCID = 1033; + if (!m_ResourceInstance) + { + MessageBox(nullptr, L"Unable to load language library", APPNAME, MB_OK | MB_TOPMOST | MB_ICONERROR); + return 1; + } + } + + // Get skin folder path + size_t len = GetPrivateProfileString(L"Rainmeter", L"SkinPath", L"", buffer, MAX_LINE_LENGTH, iniFile); + if (len > 0 && + _waccess(buffer, 0) != -1) // Temporary fix + { + // Try Rainmeter.ini first + m_SkinPath.assign(buffer, len); + PathUtil::ExpandEnvironmentVariables(m_SkinPath); + PathUtil::AppendBacklashIfMissing(m_SkinPath); + } + else if (bDefaultIniLocation && + SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_MYDOCUMENTS, nullptr, SHGFP_TYPE_CURRENT, buffer))) + { + // Use My Documents/Rainmeter/Skins + m_SkinPath = buffer; + m_SkinPath += L"\\Rainmeter\\"; + CreateDirectory(m_SkinPath.c_str(), nullptr); + m_SkinPath += L"Skins\\"; + + WritePrivateProfileString(L"Rainmeter", L"SkinPath", m_SkinPath.c_str(), iniFile); + } + else + { + m_SkinPath = m_Path + L"Skins\\"; + } + + // Create user skins, layouts, addons, and plugins folders if needed + CreateComponentFolders(bDefaultIniLocation); + + delete [] buffer; + buffer = nullptr; + + LogNoticeF(L"Path: %s", m_Path.c_str()); + LogNoticeF(L"IniFile: %s", iniFile); + LogNoticeF(L"SkinPath: %s", m_SkinPath.c_str()); + + // Test that the Rainmeter.ini file is writable + TestSettingsFile(bDefaultIniLocation); + + System::Initialize(m_Instance); + + MeasureNet::InitializeStatic(); + MeasureCPU::InitializeStatic(); + MeterString::InitializeStatic(); + + // Tray must exist before skins are read + m_TrayWindow = new TrayWindow(); + m_TrayWindow->Initialize(); + + ReloadSettings(); + + if (m_SkinRegistry.IsEmpty()) + { + std::wstring error = GetFormattedString(ID_STR_NOAVAILABLESKINS, m_SkinPath.c_str()); + ShowMessage(nullptr, error.c_str(), MB_OK | MB_ICONERROR); + } + + ResetStats(); + ReadStats(); + + // Change the work area if necessary + if (m_DesktopWorkAreaChanged) + { + UpdateDesktopWorkArea(false); + } + + bool layoutLoaded = false; + if (layout) + { + std::vector args = CommandHandler::ParseString(layout); + layoutLoaded = (args.size() == 1 && LoadLayout(args[0])); + } + + if (!layoutLoaded) + { + ActivateActiveSkins(); + } + + if (dataFileCreated) + { + m_TrayWindow->ShowWelcomeNotification(); + } + else if (!m_DisableVersionCheck) + { + CheckUpdate(); + } + + return 0; // All is OK +} + +void Rainmeter::Finalize() +{ + KillTimer(m_Window, TIMER_NETSTATS); + + DeleteAllUnmanagedMeterWindows(); + DeleteAllMeterWindows(); + DeleteAllUnmanagedMeterWindows(); // Redelete unmanaged windows caused by OnCloseAction + + delete m_TrayWindow; + + System::Finalize(); + + MeasureNet::UpdateIFTable(); + MeasureNet::UpdateStats(); + WriteStats(true); + + MeasureNet::FinalizeStatic(); + MeasureCPU::FinalizeStatic(); + MeterString::FinalizeStatic(); + + // Change the work area back + if (m_DesktopWorkAreaChanged) + { + UpdateDesktopWorkArea(true); + } + + if (m_ResourceInstance) FreeLibrary(m_ResourceInstance); + if (m_Mutex) ReleaseMutex(m_Mutex); +} + +int Rainmeter::MessagePump() +{ + MSG msg; + BOOL ret; + + // Run the standard window message loop + while ((ret = GetMessage(&msg, nullptr, 0, 0)) != 0) + { + if (ret == -1) + { + break; + } + + if (!Dialog::HandleMessage(msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return (int)msg.wParam; +} + +LRESULT CALLBACK Rainmeter::MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_DESTROY: + PostQuitMessage(0); + break; + + case WM_COPYDATA: + { + COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam; + if (cds) + { + const WCHAR* data = (const WCHAR*)cds->lpData; + if (cds->dwData == 1 && (cds->cbData > 0)) + { + Rainmeter::GetInstance().DelayedExecuteCommand(data); + } + } + } + break; + + case WM_TIMER: + if (wParam == TIMER_NETSTATS) + { + MeasureNet::UpdateIFTable(); + MeasureNet::UpdateStats(); + Rainmeter::GetInstance().WriteStats(false); + } + break; + + case WM_RAINMETER_DELAYED_REFRESH_ALL: + Rainmeter::GetInstance().RefreshAll(); + break; + + case WM_RAINMETER_DELAYED_EXECUTE: + if (lParam) + { + // Execute bang + WCHAR* bang = (WCHAR*)lParam; + Rainmeter::GetInstance().ExecuteCommand(bang, nullptr); + free(bang); // _wcsdup() + } + break; + + case WM_RAINMETER_EXECUTE: + if (Rainmeter::GetInstance().HasMeterWindow((MeterWindow*)wParam)) + { + Rainmeter::GetInstance().ExecuteCommand((const WCHAR*)lParam, (MeterWindow*)wParam); + } + break; + + default: + return DefWindowProc(hWnd, uMsg, wParam, lParam); + } + + return 0; +} + +void Rainmeter::SetNetworkStatisticsTimer() +{ + static bool set = SetTimer(m_Window, TIMER_NETSTATS, INTERVAL_NETSTATS, nullptr) != 0; +} + +void Rainmeter::CreateOptionsFile() +{ + CreateDirectory(m_SettingsPath.c_str(), nullptr); + + std::wstring defaultIni = GetDefaultLayoutPath(); + defaultIni += L"illustro default\\Rainmeter.ini"; + System::CopyFiles(defaultIni, m_IniFile); +} + +void Rainmeter::CreateDataFile() +{ + std::wstring tmpSz = m_SettingsPath + L"Plugins.ini"; + + const WCHAR* pluginsFile = tmpSz.c_str(); + const WCHAR* dataFile = m_DataFile.c_str(); + + if (_waccess(pluginsFile, 0) == 0) + { + MoveFile(pluginsFile, dataFile); + } + else + { + // Create empty file + HANDLE file = CreateFile(dataFile, GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr); + if (file != INVALID_HANDLE_VALUE) + { + CloseHandle(file); + } + } +} + +void Rainmeter::CreateComponentFolders(bool defaultIniLocation) +{ + std::wstring path; + + if (CreateDirectory(m_SkinPath.c_str(), nullptr)) + { + // Folder just created, so copy default skins there + std::wstring from = GetDefaultSkinPath(); + from += L"*.*"; + System::CopyFiles(from, m_SkinPath); + } + else + { + path = m_SkinPath; + path += L"Backup"; + if (_waccess(path.c_str(), 0) != -1) + { + std::wstring newPath = m_SkinPath + L"@Backup"; + MoveFile(path.c_str(), newPath.c_str()); + } + } + + path = GetLayoutPath(); + if (_waccess(path.c_str(), 0) == -1) + { + std::wstring themesPath = m_SettingsPath + L"Themes"; + if (_waccess(themesPath.c_str(), 0) != -1) + { + // Migrate Themes into Layouts for backwards compatibility and rename + // Rainmeter.thm to Rainmeter.ini and RainThemes.bmp to Wallpaper.bmp. + MoveFile(themesPath.c_str(), path.c_str()); + + path += L'*'; // For FindFirstFile. + WIN32_FIND_DATA fd; + HANDLE hFind = FindFirstFile(path.c_str(), &fd); + path.pop_back(); // Remove '*'. + + if (hFind != INVALID_HANDLE_VALUE) + { + do + { + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && + PathUtil::IsDotOrDotDot(fd.cFileName)) + { + std::wstring layoutFolder = path + fd.cFileName; + layoutFolder += L'\\'; + + std::wstring file = layoutFolder + L"Rainmeter.thm"; + if (_waccess(file.c_str(), 0) != -1) + { + std::wstring newFile = layoutFolder + L"Rainmeter.ini"; + MoveFile(file.c_str(), newFile.c_str()); + } + + file = layoutFolder + L"RainThemes.bmp"; + if (_waccess(file.c_str(), 0) != -1) + { + std::wstring newFile = layoutFolder + L"Wallpaper.bmp"; + MoveFile(file.c_str(), newFile.c_str()); + } + } + } + while (FindNextFile(hFind, &fd)); + + FindClose(hFind); + } + } + else + { + std::wstring from = GetDefaultLayoutPath(); + if (_waccess(from.c_str(), 0) != -1) + { + System::CopyFiles(from, m_SettingsPath); + } + } + } + else + { + path += L"Backup"; + if (_waccess(path.c_str(), 0) != -1) + { + std::wstring newPath = GetLayoutPath(); + newPath += L"@Backup"; + MoveFile(path.c_str(), newPath.c_str()); + } + } + + if (defaultIniLocation) + { + path = GetUserPluginPath(); + if (_waccess(path.c_str(), 0) == -1) + { + std::wstring from = GetDefaultPluginPath(); + if (_waccess(from.c_str(), 0) != -1) + { + System::CopyFiles(from, m_SettingsPath); + } + } + + path = GetAddonPath(); + if (_waccess(path.c_str(), 0) == -1) + { + std::wstring from = GetDefaultAddonPath(); + if (_waccess(from.c_str(), 0) != -1) + { + System::CopyFiles(from, m_SettingsPath); + } + } + + path = m_SettingsPath; + path += L"Rainmeter.exe"; + const WCHAR* pathSz = path.c_str(); + if (_waccess(pathSz, 0) == -1) + { + // Create a hidden stub Rainmeter.exe into SettingsPath for old addon + // using relative path to Rainmeter.exe + std::wstring from = m_Path + L"Rainmeter.exe"; + System::CopyFiles(from, path); + + // Get rid of all resources from the stub executable + HANDLE stub = BeginUpdateResource(pathSz, TRUE); + + // Add the manifest of Rainmeter.dll to the stub + HRSRC manifest = FindResource(m_Instance, MAKEINTRESOURCE(2), RT_MANIFEST); + DWORD manifestSize = SizeofResource(m_Instance, manifest); + HGLOBAL manifestLoad = LoadResource(m_Instance, manifest); + void* manifestLoadData = LockResource(manifestLoad); + if (manifestLoadData) + { + LANGID langID = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); + UpdateResource(stub, RT_MANIFEST, MAKEINTRESOURCE(1), langID, manifestLoadData, manifestSize); + } + + EndUpdateResource(stub, FALSE); + SetFileAttributes(pathSz, FILE_ATTRIBUTE_HIDDEN); + } + } +} + +void Rainmeter::ReloadSettings() +{ + ScanForSkins(); + ScanForLayouts(); + ReadGeneralSettings(m_IniFile); +} + +void Rainmeter::EditSettings() +{ + std::wstring file = L'"' + m_IniFile; + file += L'"'; + CommandHandler::RunFile(m_SkinEditor.c_str(), file.c_str()); +} + +void Rainmeter::EditSkinFile(const std::wstring& name, const std::wstring& iniFile) +{ + std::wstring args = L'"' + m_SkinPath; + args += name; + args += L'\\'; + args += iniFile; + args += L'"'; + CommandHandler::RunFile(m_SkinEditor.c_str(), args.c_str()); +} + +void Rainmeter::OpenSkinFolder(const std::wstring& name) +{ + std::wstring folderPath = m_SkinPath + name; + CommandHandler::RunFile(folderPath.c_str()); +} + +void Rainmeter::ActivateActiveSkins() +{ + std::multimap::const_iterator iter = m_SkinOrders.begin(); + for ( ; iter != m_SkinOrders.end(); ++iter) + { + const SkinRegistry::Folder& skinFolder = m_SkinRegistry.GetFolder((*iter).second); + if (skinFolder.active > 0 && skinFolder.active <= (uint16_t)skinFolder.files.size()) + { + ActivateSkin((*iter).second, skinFolder.active - 1); + } + } +} + +/* +** Activates the skin, or, if it is already active, the next variant of the skin. Returns true +** if the skin was activated (or was already active). +*/ +bool Rainmeter::ActivateSkin(const std::wstring& folderPath) +{ + const int index = m_SkinRegistry.FindFolderIndex(folderPath); + if (index != -1) + { + const SkinRegistry::Folder& skinFolder = m_SkinRegistry.GetFolder(index); + if (!(skinFolder.active == 1 && skinFolder.files.size() == 1)) + { + // Activate the next index. + ActivateSkin( + index, (skinFolder.active < skinFolder.files.size()) ? skinFolder.active : 0); + } + + return true; + } + + return false; +} + +/* +** Activates the skin, or, if it is already active, the next variant of the skin. Returns true +** if the skin was activated (or was already active). +*/ +bool Rainmeter::ActivateSkin(const std::wstring& folderPath, const std::wstring& file) +{ + const SkinRegistry::Indexes indexes = m_SkinRegistry.FindIndexes(folderPath, file); + if (indexes.IsValid()) + { + ActivateSkin(indexes.folder, indexes.file); + return true; + } + + return false; +} + +void Rainmeter::ActivateSkin(int folderIndex, int fileIndex) +{ + if (folderIndex >= 0 && folderIndex < m_SkinRegistry.GetFolderCount() && + fileIndex >= 0 && fileIndex < m_SkinRegistry.GetFolder(folderIndex).files.size()) + { + auto& skinFolder = m_SkinRegistry.GetFolder(folderIndex); + const std::wstring& file = skinFolder.files[fileIndex]; + const WCHAR* fileSz = file.c_str(); + + std::wstring folderPath = m_SkinRegistry.GetFolderPath(folderIndex); + + // Verify that the skin is not already active + std::map::const_iterator iter = m_MeterWindows.find(folderPath); + if (iter != m_MeterWindows.end()) + { + if (wcscmp(((*iter).second)->GetFileName().c_str(), fileSz) == 0) + { + LogWarningF((*iter).second, L"!ActivateConfig: \"%s\" already active", folderPath.c_str()); + return; + } + else + { + // Deactivate the existing skin + DeactivateSkin((*iter).second, folderIndex); + } + } + + // Verify whether the ini-file exists + std::wstring skinIniPath = m_SkinPath + folderPath; + skinIniPath += L'\\'; + skinIniPath += file; + + if (_waccess(skinIniPath.c_str(), 0) == -1) + { + std::wstring message = GetFormattedString(ID_STR_UNABLETOACTIVATESKIN, folderPath.c_str(), fileSz); + ShowMessage(nullptr, message.c_str(), MB_OK | MB_ICONEXCLAMATION); + return; + } + + if (skinFolder.active != fileIndex + 1) + { + // Write only if changed. + skinFolder.active = fileIndex + 1; + WriteActive(folderPath, fileIndex); + } + + CreateMeterWindow(folderPath, file); + } +} + +void Rainmeter::DeactivateSkin(MeterWindow* meterWindow, int folderIndex, bool save) +{ + if (folderIndex >= 0 && folderIndex < m_SkinRegistry.GetFolderCount()) + { + m_SkinRegistry.GetFolder(folderIndex).active = 0; // Deactivate the skin + } + else if (folderIndex == -1 && meterWindow) + { + SkinRegistry::Folder* folder = m_SkinRegistry.FindFolder(meterWindow->GetFolderPath()); + if (folder) + { + folder->active = 0; + } + } + + if (meterWindow) + { + if (save) + { + // Disable the skin in the ini-file + WriteActive(meterWindow->GetFolderPath(), -1); + } + + meterWindow->Deactivate(); + } +} + +void Rainmeter::ToggleSkin(int folderIndex, int fileIndex) +{ + if (folderIndex >= 0 && folderIndex < m_SkinRegistry.GetFolderCount() && + fileIndex >= 0 && fileIndex < m_SkinRegistry.GetFolder(folderIndex).files.size()) + { + if (m_SkinRegistry.GetFolder(folderIndex).active == fileIndex + 1) + { + MeterWindow* meterWindow = GetMeterWindow(m_SkinRegistry.GetFolderPath(folderIndex)); + DeactivateSkin(meterWindow, folderIndex); + } + else + { + ActivateSkin(folderIndex, fileIndex); + } + } +} + +void Rainmeter::ToggleSkinWithID(UINT id) +{ + const SkinRegistry::Indexes indexes = m_SkinRegistry.FindIndexesForID(id); + if (indexes.IsValid()) + { + ToggleSkin(indexes.folder, indexes.file); + } +} + +void Rainmeter::SetSkinPath(const std::wstring& skinPath) +{ + WritePrivateProfileString(L"Rainmeter", L"SkinPath", skinPath.c_str(), m_IniFile.c_str()); +} + +void Rainmeter::SetSkinEditor(const std::wstring& path) +{ + if (!path.empty()) + { + m_SkinEditor = path; + WritePrivateProfileString(L"Rainmeter", L"ConfigEditor", path.c_str(), m_IniFile.c_str()); + } +} + +void Rainmeter::WriteActive(const std::wstring& folderPath, int fileIndex) +{ + WCHAR buffer[32]; + _itow_s(fileIndex + 1, buffer, 10); + WritePrivateProfileString(folderPath.c_str(), L"Active", buffer, m_IniFile.c_str()); +} + +void Rainmeter::CreateMeterWindow(const std::wstring& folderPath, const std::wstring& file) +{ + MeterWindow* mw = new MeterWindow(folderPath, file); + + // Note: May modify existing key + m_MeterWindows[folderPath] = mw; + + mw->Initialize(); + + DialogAbout::UpdateSkins(); + DialogManage::UpdateSkins(mw); +} + +void Rainmeter::DeleteAllMeterWindows() +{ + auto it = m_MeterWindows.cbegin(); + while (it != m_MeterWindows.cend()) + { + MeterWindow* mw = (*it).second; + m_MeterWindows.erase(it); // Remove before deleting MeterWindow + + DialogManage::UpdateSkins(mw, true); + delete mw; + + // Get next valid iterator (Fix for iterator invalidation caused by OnCloseAction) + it = m_MeterWindows.cbegin(); + } + + m_MeterWindows.clear(); + DialogAbout::UpdateSkins(); +} + +void Rainmeter::DeleteAllUnmanagedMeterWindows() +{ + for (auto it = m_UnmanagedMeterWindows.cbegin(); it != m_UnmanagedMeterWindows.cend(); ++it) + { + delete (*it); + } + + m_UnmanagedMeterWindows.clear(); +} + +/* +** Removes the skin from m_MeterWindows. The skin should delete itself. +** +*/ +void Rainmeter::RemoveMeterWindow(MeterWindow* meterWindow) +{ + for (auto it = m_MeterWindows.cbegin(); it != m_MeterWindows.cend(); ++it) + { + if ((*it).second == meterWindow) + { + m_MeterWindows.erase(it); + DialogManage::UpdateSkins(meterWindow, true); + DialogAbout::UpdateSkins(); + break; + } + } +} + +/* +** Adds the skin to m_UnmanagedMeterWindows. The skin should remove itself by calling RemoveUnmanagedMeterWindow(). +** +*/ +void Rainmeter::AddUnmanagedMeterWindow(MeterWindow* meterWindow) +{ + for (auto it = m_UnmanagedMeterWindows.cbegin(); it != m_UnmanagedMeterWindows.cend(); ++it) + { + if ((*it) == meterWindow) // already added + { + return; + } + } + + m_UnmanagedMeterWindows.push_back(meterWindow); +} + +void Rainmeter::RemoveUnmanagedMeterWindow(MeterWindow* meterWindow) +{ + for (auto it = m_UnmanagedMeterWindows.cbegin(); it != m_UnmanagedMeterWindows.cend(); ++it) + { + if ((*it) == meterWindow) + { + m_UnmanagedMeterWindows.erase(it); + break; + } + } +} + +bool Rainmeter::HasMeterWindow(const MeterWindow* meterWindow) const +{ + for (auto it = m_MeterWindows.begin(); it != m_MeterWindows.end(); ++it) + { + if ((*it).second == meterWindow) + { + return true; + } + } + + return false; +} + +MeterWindow* Rainmeter::GetMeterWindow(const std::wstring& folderPath) +{ + const WCHAR* folderSz = folderPath.c_str(); + std::map::const_iterator iter = m_MeterWindows.begin(); + for (; iter != m_MeterWindows.end(); ++iter) + { + if (_wcsicmp((*iter).first.c_str(), folderSz) == 0) + { + return (*iter).second; + } + } + + return nullptr; +} + +MeterWindow* Rainmeter::GetMeterWindowByINI(const std::wstring& ini_searching) +{ + if (_wcsnicmp(m_SkinPath.c_str(), ini_searching.c_str(), m_SkinPath.length()) == 0) + { + const std::wstring config_searching = ini_searching.substr(m_SkinPath.length()); + + std::map::const_iterator iter = m_MeterWindows.begin(); + for (; iter != m_MeterWindows.end(); ++iter) + { + std::wstring config_current = (*iter).second->GetFolderPath() + L'\\'; + config_current += (*iter).second->GetFileName(); + + if (_wcsicmp(config_current.c_str(), config_searching.c_str()) == 0) + { + return (*iter).second; + } + } + } + + return nullptr; +} + +MeterWindow* Rainmeter::GetMeterWindow(HWND hwnd) +{ + std::map::const_iterator iter = m_MeterWindows.begin(); + for (; iter != m_MeterWindows.end(); ++iter) + { + if ((*iter).second->GetWindow() == hwnd) + { + return (*iter).second; + } + } + + return nullptr; +} + +void Rainmeter::GetMeterWindowsByLoadOrder(std::multimap& windows, const std::wstring& group) +{ + std::map::const_iterator iter = m_MeterWindows.begin(); + for (; iter != m_MeterWindows.end(); ++iter) + { + MeterWindow* mw = (*iter).second; + if (mw && (group.empty() || mw->BelongsToGroup(group))) + { + windows.insert(std::pair(GetLoadOrder((*iter).first), mw)); + } + } +} + +void Rainmeter::SetLoadOrder(int folderIndex, int order) +{ + std::multimap::iterator iter = m_SkinOrders.begin(); + for ( ; iter != m_SkinOrders.end(); ++iter) + { + if ((*iter).second == folderIndex) // already exists + { + if ((*iter).first != order) + { + m_SkinOrders.erase(iter); + break; + } + else + { + return; + } + } + } + + m_SkinOrders.insert(std::pair(order, folderIndex)); +} + +int Rainmeter::GetLoadOrder(const std::wstring& folderPath) +{ + const int index = m_SkinRegistry.FindFolderIndex(folderPath); + if (index != -1) + { + std::multimap::const_iterator iter = m_SkinOrders.begin(); + for ( ; iter != m_SkinOrders.end(); ++iter) + { + if ((*iter).second == index) + { + return (*iter).first; + } + } + } + + // LoadOrder not specified + return 0; +} + +/* +** Scans all the subfolders and locates the ini-files. +*/ +void Rainmeter::ScanForSkins() +{ + m_SkinRegistry.Populate(m_SkinPath); + m_SkinOrders.clear(); +} + +/* +** Scans the given folder for layouts +*/ +void Rainmeter::ScanForLayouts() +{ + m_Layouts.clear(); + + WIN32_FIND_DATA fileData; // Data structure describes the file found + HANDLE hSearch; // Search handle returned by FindFirstFile + + // Scan for folders + std::wstring folders = GetLayoutPath(); + folders += L'*'; + + hSearch = FindFirstFileEx( + folders.c_str(), + (IsWindows7OrGreater()) ? FindExInfoBasic : FindExInfoStandard, + &fileData, + FindExSearchNameMatch, + nullptr, + 0); + + if (hSearch != INVALID_HANDLE_VALUE) + { + do + { + if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && + !PathUtil::IsDotOrDotDot(fileData.cFileName)) + { + m_Layouts.push_back(fileData.cFileName); + } + } + while (FindNextFile(hSearch, &fileData)); + + FindClose(hSearch); + } + + DialogManage::UpdateLayouts(); +} + +void Rainmeter::ExecuteBang(const WCHAR* bang, std::vector& args, MeterWindow* meterWindow) +{ + m_CommandHandler.ExecuteBang(bang, args, meterWindow); +} + +/* +** Runs the given command or bang +** +*/ +void Rainmeter::ExecuteCommand(const WCHAR* command, MeterWindow* meterWindow, bool multi) +{ + m_CommandHandler.ExecuteCommand(command, meterWindow, multi); +} + +/* +** Executes command when current processing is done. +** +*/ +void Rainmeter::DelayedExecuteCommand(const WCHAR* command) +{ + WCHAR* bang = _wcsdup(command); + PostMessage(m_Window, WM_RAINMETER_DELAYED_EXECUTE, (WPARAM)nullptr, (LPARAM)bang); +} + +/* +** Reads the general settings from the Rainmeter.ini file +** +*/ +void Rainmeter::ReadGeneralSettings(const std::wstring& iniFile) +{ + WCHAR buffer[MAX_PATH]; + + // Clear old settings + m_DesktopWorkAreas.clear(); + + ConfigParser parser; + parser.Initialize(iniFile, nullptr, nullptr); + + m_UseD2D = parser.ReadBool(L"Rainmeter", L"UseD2D", true); + + m_Debug = parser.ReadBool(L"Rainmeter", L"Debug", false); + + // Read Logging settings + Logger& logger = GetLogger(); + const bool logging = parser.ReadBool(L"Rainmeter", L"Logging", false); + logger.SetLogToFile(logging); + if (logging) + { + logger.StartLogFile(); + } + + if (m_TrayWindow) + { + m_TrayWindow->ReadOptions(parser); + } + + m_GlobalOptions.netInSpeed = parser.ReadFloat(L"Rainmeter", L"NetInSpeed", 0.0); + m_GlobalOptions.netOutSpeed = parser.ReadFloat(L"Rainmeter", L"NetOutSpeed", 0.0); + + m_DisableDragging = parser.ReadBool(L"Rainmeter", L"DisableDragging", false); + m_DisableRDP = parser.ReadBool(L"Rainmeter", L"DisableRDP", false); + + m_SkinEditor = parser.ReadString(L"Rainmeter", L"ConfigEditor", L""); + if (m_SkinEditor.empty()) + { + // Get the program path associated with .ini files + DWORD cchOut = MAX_PATH; + HRESULT hr = AssocQueryString(ASSOCF_NOTRUNCATE, ASSOCSTR_EXECUTABLE, L".ini", L"open", buffer, &cchOut); + m_SkinEditor = (SUCCEEDED(hr) && cchOut > 0) ? buffer : L"Notepad"; + } + + if (m_Debug) + { + LogNoticeF(L"ConfigEditor: %s", m_SkinEditor.c_str()); + } + + m_TrayExecuteR = parser.ReadString(L"Rainmeter", L"TrayExecuteR", L"", false); + m_TrayExecuteM = parser.ReadString(L"Rainmeter", L"TrayExecuteM", L"", false); + m_TrayExecuteDR = parser.ReadString(L"Rainmeter", L"TrayExecuteDR", L"", false); + m_TrayExecuteDM = parser.ReadString(L"Rainmeter", L"TrayExecuteDM", L"", false); + + m_DisableVersionCheck = parser.ReadBool(L"Rainmeter", L"DisableVersionCheck", false); + + const std::wstring& area = parser.ReadString(L"Rainmeter", L"DesktopWorkArea", L""); + if (!area.empty()) + { + m_DesktopWorkAreas[0] = parser.ParseRECT(area.c_str()); + m_DesktopWorkAreaChanged = true; + } + + const size_t monitorCount = System::GetMonitorCount(); + for (UINT i = 1; i <= monitorCount; ++i) + { + _snwprintf_s(buffer, _TRUNCATE, L"DesktopWorkArea@%i", (int)i); + const std::wstring& area = parser.ReadString(L"Rainmeter", buffer, L""); + if (!area.empty()) + { + m_DesktopWorkAreas[i] = parser.ParseRECT(area.c_str()); + m_DesktopWorkAreaChanged = true; + } + } + + m_DesktopWorkAreaType = parser.ReadBool(L"Rainmeter", L"DesktopWorkAreaType", false); + + m_NormalStayDesktop = parser.ReadBool(L"Rainmeter", L"NormalStayDesktop", true); + + for (auto iter = parser.GetSections().cbegin(); iter != parser.GetSections().end(); ++iter) + { + const WCHAR* section = (*iter).c_str(); + + if (wcscmp(section, L"Rainmeter") == 0 || + wcscmp(section, L"TrayMeasure") == 0) + { + continue; + } + + const int index = m_SkinRegistry.FindFolderIndex(*iter); + if (index == -1) + { + continue; + } + + SkinRegistry::Folder& skinFolder = m_SkinRegistry.GetFolder(index); + + // Make sure there is a ini file available + int active = parser.ReadInt(section, L"Active", 0); + if (active > 0 && active <= (int)skinFolder.files.size()) + { + skinFolder.active = active; + } + + int order = parser.ReadInt(section, L"LoadOrder", 0); + SetLoadOrder(index, order); + } +} + +/* +** Refreshes all active meter windows. +** Note: This function calls MeterWindow::Refresh() directly for synchronization. Be careful about crash. +** +*/ +void Rainmeter::RefreshAll() +{ + // Read skins and settings + ReloadSettings(); + + // Change the work area if necessary + if (m_DesktopWorkAreaChanged) + { + UpdateDesktopWorkArea(false); + } + + // Make the sending order by using LoadOrder + std::multimap windows; + GetMeterWindowsByLoadOrder(windows); + + // Prepare the helper window + System::PrepareHelperWindow(); + + // Refresh all + std::multimap::const_iterator iter = windows.begin(); + for ( ; iter != windows.end(); ++iter) + { + MeterWindow* mw = (*iter).second; + if (mw) + { + // Verify whether the cached information is valid + const int index = m_SkinRegistry.FindFolderIndex(mw->GetFolderPath()); + if (index != -1) + { + SkinRegistry::Folder& skinFolder = m_SkinRegistry.GetFolder(index); + const WCHAR* skinIniFile = mw->GetFileName().c_str(); + + bool found = false; + for (int i = 0, isize = (int)skinFolder.files.size(); i < isize; ++i) + { + if (_wcsicmp(skinIniFile, skinFolder.files[i].c_str()) == 0) + { + found = true; + if (skinFolder.active != i + 1) + { + // Switch to new ini-file order + skinFolder.active = i + 1; + WriteActive(mw->GetFolderPath(), i); + } + break; + } + } + + if (!found) + { + const WCHAR* skinFolderPath = mw->GetFolderPath().c_str(); + std::wstring error = GetFormattedString(ID_STR_UNABLETOREFRESHSKIN, skinFolderPath, skinIniFile); + + DeactivateSkin(mw, index); + + ShowMessage(nullptr, error.c_str(), MB_OK | MB_ICONEXCLAMATION); + continue; + } + } + else + { + const WCHAR* skinFolderPath = mw->GetFolderPath().c_str(); + std::wstring error = GetFormattedString(ID_STR_UNABLETOREFRESHSKIN, skinFolderPath, L""); + + DeactivateSkin(mw, -2); // -2 = Force deactivate + + ShowMessage(nullptr, error.c_str(), MB_OK | MB_ICONEXCLAMATION); + continue; + } + + mw->Refresh(false, true); + } + } + + DialogAbout::UpdateSkins(); + DialogManage::UpdateSkins(nullptr); +} + +bool Rainmeter::LoadLayout(const std::wstring& name) +{ + // Replace Rainmeter.ini with layout + std::wstring layout = GetLayoutPath(); + layout += name; + std::wstring wallpaper = layout + L"\\Wallpaper.bmp"; + layout += L"\\Rainmeter.ini"; + + if (_waccess(layout.c_str(), 0) == -1) + { + return false; + } + + DeleteAllUnmanagedMeterWindows(); + DeleteAllMeterWindows(); + + std::wstring backup = GetLayoutPath(); + backup += L"@Backup"; + CreateDirectory(backup.c_str(), nullptr); + backup += L"\\Rainmeter.ini"; + + bool backupLayout = (_wcsicmp(name.c_str(), L"@Backup") == 0); + if (!backupLayout) + { + // Make a copy of current Rainmeter.ini + System::CopyFiles(m_IniFile, backup); + } + + System::CopyFiles(layout, m_IniFile); + + if (!backupLayout) + { + PreserveSetting(backup, L"SkinPath"); + PreserveSetting(backup, L"ConfigEditor"); + PreserveSetting(backup, L"LogViewer"); + PreserveSetting(backup, L"Logging"); + PreserveSetting(backup, L"DisableVersionCheck"); + PreserveSetting(backup, L"Language"); + PreserveSetting(backup, L"NormalStayDesktop"); + PreserveSetting(backup, L"TrayExecuteM", false); + PreserveSetting(backup, L"TrayExecuteR", false); + PreserveSetting(backup, L"TrayExecuteDM", false); + PreserveSetting(backup, L"TrayExecuteDR", false); + PreserveSetting(backup, L"UseD2D"); + + // Set wallpaper if it exists + if (_waccess(wallpaper.c_str(), 0) != -1) + { + SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)wallpaper.c_str(), SPIF_UPDATEINIFILE); + } + } + + ReloadSettings(); + + // Create meter windows for active skins + ActivateActiveSkins(); + + return true; +} + +void Rainmeter::PreserveSetting(const std::wstring& from, LPCTSTR key, bool replace) +{ + WCHAR* buffer = new WCHAR[MAX_LINE_LENGTH]; + + if ((replace || GetPrivateProfileString(L"Rainmeter", key, L"", buffer, 4, m_IniFile.c_str()) == 0) && + GetPrivateProfileString(L"Rainmeter", key, L"", buffer, MAX_LINE_LENGTH, from.c_str()) > 0) + { + WritePrivateProfileString(L"Rainmeter", key, buffer, m_IniFile.c_str()); + } + + delete [] buffer; +} + +/* +** Applies given DesktopWorkArea and DesktopWorkArea@n. +** +*/ +void Rainmeter::UpdateDesktopWorkArea(bool reset) +{ + bool changed = false; + + if (reset) + { + if (!m_OldDesktopWorkAreas.empty()) + { + int i = 1; + for (auto iter = m_OldDesktopWorkAreas.cbegin(); iter != m_OldDesktopWorkAreas.cend(); ++iter, ++i) + { + RECT r = (*iter); + + BOOL result = SystemParametersInfo(SPI_SETWORKAREA, 0, &r, 0); + + if (m_Debug) + { + std::wstring format = L"Resetting WorkArea@%i: L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)"; + if (!result) + { + format += L" => FAIL"; + } + LogDebugF(format.c_str(), i, r.left, r.top, r.right, r.bottom, r.right - r.left, r.bottom - r.top); + } + } + changed = true; + } + } + else + { + const size_t numOfMonitors = System::GetMonitorCount(); + const MultiMonitorInfo& monitorsInfo = System::GetMultiMonitorInfo(); + const std::vector& monitors = monitorsInfo.monitors; + + if (m_OldDesktopWorkAreas.empty()) + { + // Store old work areas for changing them back + for (size_t i = 0; i < numOfMonitors; ++i) + { + m_OldDesktopWorkAreas.push_back(monitors[i].work); + } + } + + if (m_Debug) + { + LogDebugF(L"DesktopWorkAreaType: %s", m_DesktopWorkAreaType ? L"Margin" : L"Default"); + } + + for (UINT i = 0; i <= numOfMonitors; ++i) + { + std::map::const_iterator it = m_DesktopWorkAreas.find(i); + if (it != m_DesktopWorkAreas.end()) + { + RECT r = (*it).second; + + // Move rect to correct offset + if (m_DesktopWorkAreaType) + { + RECT margin = r; + r = (i == 0) ? monitors[monitorsInfo.primary - 1].screen : monitors[i - 1].screen; + r.left += margin.left; + r.top += margin.top; + r.right -= margin.right; + r.bottom -= margin.bottom; + } + else + { + if (i != 0) + { + const RECT screenRect = monitors[i - 1].screen; + r.left += screenRect.left; + r.top += screenRect.top; + r.right += screenRect.left; + r.bottom += screenRect.top; + } + } + + BOOL result = SystemParametersInfo(SPI_SETWORKAREA, 0, &r, 0); + if (result) + { + changed = true; + } + + if (m_Debug) + { + std::wstring format = L"Applying DesktopWorkArea"; + if (i != 0) + { + WCHAR buffer[64]; + size_t len = _snwprintf_s(buffer, _TRUNCATE, L"@%i", i); + format.append(buffer, len); + } + format += L": L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)"; + if (!result) + { + format += L" => FAIL"; + } + LogDebugF(format.c_str(), r.left, r.top, r.right, r.bottom, r.right - r.left, r.bottom - r.top); + } + } + } + } + + if (changed && System::GetWindow()) + { + // Update System::MultiMonitorInfo for for work area variables + SendMessageTimeout(System::GetWindow(), WM_SETTINGCHANGE, SPI_SETWORKAREA, 0, SMTO_ABORTIFHUNG, 1000, nullptr); + } +} + +/* +** Reads the statistics from the ini-file +** +*/ +void Rainmeter::ReadStats() +{ + const WCHAR* statsFile = m_StatsFile.c_str(); + + // If m_StatsFile doesn't exist, create it and copy the stats section from m_IniFile + if (_waccess(statsFile, 0) == -1) + { + const WCHAR* iniFile = m_IniFile.c_str(); + WCHAR* tmpSz = new WCHAR[SHRT_MAX]; // Max size returned by GetPrivateProfileSection() + + if (GetPrivateProfileSection(L"Statistics", tmpSz, SHRT_MAX, iniFile) > 0) + { + WritePrivateProfileString(L"Statistics", nullptr, nullptr, iniFile); + } + else + { + tmpSz[0] = tmpSz[1] = L'\0'; + } + WritePrivateProfileSection(L"Statistics", tmpSz, statsFile); + + delete [] tmpSz; + } + + // Only Net measure has stats at the moment + MeasureNet::ReadStats(m_StatsFile, m_StatsDate); +} + +/* +** Writes the statistics to the ini-file. If bForce is false the stats are written only once per an appropriate interval. +** +*/ +void Rainmeter::WriteStats(bool bForce) +{ + static ULONGLONG lastWrite = 0; + + ULONGLONG ticks = System::GetTickCount64(); + + if (bForce || (lastWrite + INTERVAL_NETSTATS < ticks)) + { + lastWrite = ticks; + + // Only Net measure has stats at the moment + const WCHAR* statsFile = m_StatsFile.c_str(); + MeasureNet::WriteStats(statsFile, m_StatsDate); + + WritePrivateProfileString(nullptr, nullptr, nullptr, statsFile); + } +} + +/* +** Clears the statistics +** +*/ +void Rainmeter::ResetStats() +{ + // Set the stats-date string + tm* newtime; + time_t long_time; + time(&long_time); + newtime = localtime(&long_time); + m_StatsDate = _wasctime(newtime); + m_StatsDate.erase(m_StatsDate.size() - 1); + + // Only Net measure has stats at the moment + MeasureNet::ResetStats(); +} + +/* +** Wraps MessageBox(). Sets RTL flag if necessary. +** +*/ +int Rainmeter::ShowMessage(HWND parent, const WCHAR* text, UINT type) +{ + type |= MB_TOPMOST; + + if (*GetString(ID_STR_ISRTL) == L'1') + { + type |= MB_RTLREADING; + } + + return MessageBox(parent, text, APPNAME, type); +}; + +void Rainmeter::ShowLogFile() +{ + std::wstring logFile = L'"' + GetLogger().GetLogFilePath(); + logFile += L'"'; + + CommandHandler::RunFile(m_SkinEditor.c_str(), logFile.c_str()); +} + +void Rainmeter::SetDebug(bool debug) +{ + m_Debug = debug; + WritePrivateProfileString(L"Rainmeter", L"Debug", debug ? L"1" : L"0", m_IniFile.c_str()); +} + +void Rainmeter::SetDisableDragging(bool dragging) +{ + m_DisableDragging = dragging; + WritePrivateProfileString(L"Rainmeter", L"DisableDragging", dragging ? L"1" : L"0", m_IniFile.c_str()); +} + +void Rainmeter::SetDisableVersionCheck(bool check) +{ + m_DisableVersionCheck = check; + WritePrivateProfileString(L"Rainmeter", L"DisableVersionCheck", check ? L"1" : L"0" , m_IniFile.c_str()); +} + +void Rainmeter::TestSettingsFile(bool bDefaultIniLocation) +{ + const WCHAR* iniFile = m_IniFile.c_str(); + if (!System::IsFileWritable(iniFile)) + { + std::wstring error = GetString(ID_STR_SETTINGSNOTWRITABLE); + + if (!bDefaultIniLocation) + { + std::wstring strTarget = L"%APPDATA%\\Rainmeter\\"; + PathUtil::ExpandEnvironmentVariables(strTarget); + + error += GetFormattedString(ID_STR_SETTINGSMOVEFILE, iniFile, strTarget.c_str()); + } + else + { + error += GetFormattedString(ID_STR_SETTINGSREADONLY, iniFile); + } + + ShowMessage(nullptr, error.c_str(), MB_OK | MB_ICONERROR); + } +} + +void Rainmeter::SetUseD2D(bool enabled) +{ + m_UseD2D = enabled; + + // Save to Rainmeter.ini + WritePrivateProfileString(L"Rainmeter", L"UseD2D", enabled ? L"1" : L"0", m_IniFile.c_str()); + + RefreshAll(); +} diff --git a/Library/Rainmeter.h b/Library/Rainmeter.h index ace6a09b..cd32cd13 100644 --- a/Library/Rainmeter.h +++ b/Library/Rainmeter.h @@ -1,285 +1,285 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __RAINMETER_H__ -#define __RAINMETER_H__ - -#include -#include -#include -#include -#include -#include "CommandHandler.h" -#include "ContextMenu.h" -#include "Logger.h" -#include "MeterWindow.h" -#include "SkinRegistry.h" - -#define MAX_LINE_LENGTH 4096 - -#define APPNAME L"Rainmeter" -#ifdef _WIN64 -#define APPBITS L"64-bit" -#else -#define APPBITS L"32-bit" -#endif -#define WIDEN2(x) L ## x -#define WIDEN(x) WIDEN2(x) -#define APPDATE WIDEN(__DATE__) - -#define RAINMETER_CLASS_NAME L"DummyRainWClass" -#define RAINMETER_WINDOW_NAME L"Rainmeter control window" - -#define WM_RAINMETER_DELAYED_REFRESH_ALL WM_APP + 0 -#define WM_RAINMETER_DELAYED_EXECUTE WM_APP + 1 -#define WM_RAINMETER_EXECUTE WM_APP + 2 - -struct GlobalOptions -{ - double netInSpeed; - double netOutSpeed; -}; - -class ConfigParser; -class TrayWindow; - -class Rainmeter -{ -public: - static Rainmeter& GetInstance(); - - int Initialize(LPCWSTR iniPath, LPCWSTR layout); - void Finalize(); - - int MessagePump(); - - void SetNetworkStatisticsTimer(); - - ConfigParser* GetCurrentParser() { return m_CurrentParser; } - void SetCurrentParser(ConfigParser* parser) { m_CurrentParser = parser; } - - TrayWindow* GetTrayWindow() { return m_TrayWindow; } - - bool HasMeterWindow(const MeterWindow* meterWindow) const; - - MeterWindow* GetMeterWindow(const std::wstring& folderPath); - MeterWindow* GetMeterWindowByINI(const std::wstring& ini_searching); - - MeterWindow* GetMeterWindow(HWND hwnd); - void GetMeterWindowsByLoadOrder(std::multimap& windows, const std::wstring& group = std::wstring()); - std::map& GetAllMeterWindows() { return m_MeterWindows; } - - const std::vector& GetAllLayouts() { return m_Layouts; } - - void RemoveMeterWindow(MeterWindow* meterWindow); - void AddUnmanagedMeterWindow(MeterWindow* meterWindow); - void RemoveUnmanagedMeterWindow(MeterWindow* meterWindow); - - bool ActivateSkin(const std::wstring& folderPath); - bool ActivateSkin(const std::wstring& folderPath, const std::wstring& file); - void ActivateSkin(int folderIndex, int fileIndex); - void DeactivateSkin(MeterWindow* meterWindow, int folderIndex, bool save = true); - void ToggleSkin(int folderIndex, int fileIndex); - void ToggleSkinWithID(UINT id); - - const std::wstring& GetPath() { return m_Path; } - const std::wstring& GetIniFile() { return m_IniFile; } - const std::wstring& GetDataFile() { return m_DataFile; } - const std::wstring& GetSettingsPath() { return m_SettingsPath; } - const std::wstring& GetSkinPath() { return m_SkinPath; } - void SetSkinPath(const std::wstring& skinPath); - std::wstring GetLayoutPath() { return m_SettingsPath + L"Layouts\\"; } - std::wstring GetPluginPath() { return m_Path + L"Plugins\\"; } - std::wstring GetUserPluginPath() { return m_SettingsPath + L"Plugins\\"; } - std::wstring GetAddonPath() { return m_SettingsPath + L"Addons\\"; } - - bool HasUserPluginPath() { return (_wcsicmp(m_Path.c_str(), m_SettingsPath.c_str()) != 0); } - - std::wstring GetDefaultSkinPath() { return m_Path + L"Defaults\\Skins\\"; } - std::wstring GetDefaultLayoutPath() { return m_Path + L"Defaults\\Layouts\\"; } - std::wstring GetDefaultPluginPath() { return m_Path + L"Defaults\\Plugins\\"; } - std::wstring GetDefaultAddonPath() { return m_Path + L"Defaults\\Addons\\"; } - - const std::wstring& GetDrive() { return m_Drive; } - - const std::wstring& GetSkinEditor() { return m_SkinEditor; } - void SetSkinEditor(const std::wstring& path); - const std::wstring& GetStatsDate() { return m_StatsDate; } - - HWND GetWindow() { return m_Window; } - - HINSTANCE GetModuleInstance() { return m_Instance; } - HINSTANCE GetResourceInstance() { return m_ResourceInstance; } - LCID GetResourceLCID() { return m_ResourceLCID; } - - bool GetUseD2D() const { return m_UseD2D; } - void SetUseD2D(bool enabled); - - bool GetDebug() { return m_Debug; } - - GlobalOptions& GetGlobalOptions() { return m_GlobalOptions; } - - void ReloadSettings(); - void EditSettings(); - void EditSkinFile(const std::wstring& name, const std::wstring& iniFile); - void OpenSkinFolder(const std::wstring& name = std::wstring()); - - void UpdateStats(); - void ReadStats(); - void WriteStats(bool bForce); - void ResetStats(); - - bool GetDisableVersionCheck() { return m_DisableVersionCheck; } - void SetDisableVersionCheck(bool check); - bool GetNewVersion() { return m_NewVersion; } - void SetNewVersion() { m_NewVersion = true; } - - void ShowLogFile(); - - bool GetDisableRDP() { return m_DisableRDP; } - bool IsRedrawable() { return (!GetDisableRDP() || !GetSystemMetrics(SM_REMOTESESSION)); } - - bool GetDisableDragging() { return m_DisableDragging; } - void SetDisableDragging(bool dragging); - - bool IsNormalStayDesktop() { return m_NormalStayDesktop; } - - void SetDebug(bool debug); - - int ShowMessage(HWND parent, const WCHAR* text, UINT type); - - bool IsMenuActive() { return m_ContextMenu.IsMenuActive(); } - void ShowContextMenu(POINT pos, MeterWindow* mw) { return m_ContextMenu.ShowMenu(pos, mw); } - void ShowSkinCustomContextMenu(POINT pos, MeterWindow* mw) { return m_ContextMenu.ShowSkinCustomMenu(pos, mw); } - - const std::wstring& GetTrayExecuteR() { return m_TrayExecuteR; } - const std::wstring& GetTrayExecuteM() { return m_TrayExecuteM; } - const std::wstring& GetTrayExecuteDR() { return m_TrayExecuteDR; } - const std::wstring& GetTrayExecuteDM() { return m_TrayExecuteDM; } - - void ExecuteBang(const WCHAR* bang, std::vector& args, MeterWindow* meterWindow); - void ExecuteCommand(const WCHAR* command, MeterWindow* meterWindow, bool multi = true); - void DelayedExecuteCommand(const WCHAR* command); - - void RefreshAll(); - - bool LoadLayout(const std::wstring& name); - void PreserveSetting(const std::wstring& from, LPCTSTR key, bool replace = true); - - friend class CommandHandler; - friend class ContextMenu; - friend class DialogManage; - -private: - Rainmeter(); - ~Rainmeter(); - - Rainmeter(const Rainmeter& other) = delete; - Rainmeter& operator=(Rainmeter other) = delete; - - static LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - - void ActivateActiveSkins(); - void CreateMeterWindow(const std::wstring& folderPath, const std::wstring& file); - void DeleteAllMeterWindows(); - void DeleteAllUnmanagedMeterWindows(); - void WriteActive(const std::wstring& folderPath, int fileIndex); - void ScanForSkins(); - void ScanForLayouts(); - void ReadGeneralSettings(const std::wstring& iniFile); - void SetLoadOrder(int folderIndex, int order); - int GetLoadOrder(const std::wstring& folderPath); - void UpdateDesktopWorkArea(bool reset); - - void CreateOptionsFile(); - void CreateDataFile(); - void CreateComponentFolders(bool defaultIniLocation); - void TestSettingsFile(bool bDefaultIniLocation); - - TrayWindow* m_TrayWindow; - - std::multimap m_SkinOrders; - std::map m_MeterWindows; - std::list m_UnmanagedMeterWindows; - std::vector m_Layouts; - - std::wstring m_Path; - std::wstring m_IniFile; - std::wstring m_DataFile; - std::wstring m_StatsFile; - std::wstring m_SettingsPath; - std::wstring m_SkinPath; - - std::wstring m_Drive; - - std::wstring m_StatsDate; - - std::wstring m_TrayExecuteR; - std::wstring m_TrayExecuteM; - std::wstring m_TrayExecuteDR; - std::wstring m_TrayExecuteDM; - - bool m_UseD2D; - - bool m_Debug; - - bool m_DisableVersionCheck; - bool m_NewVersion; - - bool m_DesktopWorkAreaChanged; - bool m_DesktopWorkAreaType; - std::map m_DesktopWorkAreas; - std::vector m_OldDesktopWorkAreas; - - bool m_NormalStayDesktop; - - bool m_DisableRDP; - - bool m_DisableDragging; - - std::wstring m_SkinEditor; - - CommandHandler m_CommandHandler; - ContextMenu m_ContextMenu; - SkinRegistry m_SkinRegistry; - - ConfigParser* m_CurrentParser; - - HWND m_Window; - - HANDLE m_Mutex; - HINSTANCE m_Instance; - HMODULE m_ResourceInstance; - LCID m_ResourceLCID; - - ULONG_PTR m_GDIplusToken; - - GlobalOptions m_GlobalOptions; -}; - -#ifdef LIBRARY_EXPORTS -#define EXPORT_PLUGIN EXTERN_C __declspec(dllexport) -#else -#define EXPORT_PLUGIN EXTERN_C __declspec(dllimport) -#endif - -EXPORT_PLUGIN int RainmeterMain(LPWSTR cmdLine); -EXPORT_PLUGIN void* Rainmeter_Initialize(); -EXPORT_PLUGIN void Rainmeter_Finalize(void* ptr); - -#endif +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __RAINMETER_H__ +#define __RAINMETER_H__ + +#include +#include +#include +#include +#include +#include "CommandHandler.h" +#include "ContextMenu.h" +#include "Logger.h" +#include "MeterWindow.h" +#include "SkinRegistry.h" + +#define MAX_LINE_LENGTH 4096 + +#define APPNAME L"Rainmeter" +#ifdef _WIN64 +#define APPBITS L"64-bit" +#else +#define APPBITS L"32-bit" +#endif +#define WIDEN2(x) L ## x +#define WIDEN(x) WIDEN2(x) +#define APPDATE WIDEN(__DATE__) + +#define RAINMETER_CLASS_NAME L"DummyRainWClass" +#define RAINMETER_WINDOW_NAME L"Rainmeter control window" + +#define WM_RAINMETER_DELAYED_REFRESH_ALL WM_APP + 0 +#define WM_RAINMETER_DELAYED_EXECUTE WM_APP + 1 +#define WM_RAINMETER_EXECUTE WM_APP + 2 + +struct GlobalOptions +{ + double netInSpeed; + double netOutSpeed; +}; + +class ConfigParser; +class TrayWindow; + +class Rainmeter +{ +public: + static Rainmeter& GetInstance(); + + int Initialize(LPCWSTR iniPath, LPCWSTR layout); + void Finalize(); + + int MessagePump(); + + void SetNetworkStatisticsTimer(); + + ConfigParser* GetCurrentParser() { return m_CurrentParser; } + void SetCurrentParser(ConfigParser* parser) { m_CurrentParser = parser; } + + TrayWindow* GetTrayWindow() { return m_TrayWindow; } + + bool HasMeterWindow(const MeterWindow* meterWindow) const; + + MeterWindow* GetMeterWindow(const std::wstring& folderPath); + MeterWindow* GetMeterWindowByINI(const std::wstring& ini_searching); + + MeterWindow* GetMeterWindow(HWND hwnd); + void GetMeterWindowsByLoadOrder(std::multimap& windows, const std::wstring& group = std::wstring()); + std::map& GetAllMeterWindows() { return m_MeterWindows; } + + const std::vector& GetAllLayouts() { return m_Layouts; } + + void RemoveMeterWindow(MeterWindow* meterWindow); + void AddUnmanagedMeterWindow(MeterWindow* meterWindow); + void RemoveUnmanagedMeterWindow(MeterWindow* meterWindow); + + bool ActivateSkin(const std::wstring& folderPath); + bool ActivateSkin(const std::wstring& folderPath, const std::wstring& file); + void ActivateSkin(int folderIndex, int fileIndex); + void DeactivateSkin(MeterWindow* meterWindow, int folderIndex, bool save = true); + void ToggleSkin(int folderIndex, int fileIndex); + void ToggleSkinWithID(UINT id); + + const std::wstring& GetPath() { return m_Path; } + const std::wstring& GetIniFile() { return m_IniFile; } + const std::wstring& GetDataFile() { return m_DataFile; } + const std::wstring& GetSettingsPath() { return m_SettingsPath; } + const std::wstring& GetSkinPath() { return m_SkinPath; } + void SetSkinPath(const std::wstring& skinPath); + std::wstring GetLayoutPath() { return m_SettingsPath + L"Layouts\\"; } + std::wstring GetPluginPath() { return m_Path + L"Plugins\\"; } + std::wstring GetUserPluginPath() { return m_SettingsPath + L"Plugins\\"; } + std::wstring GetAddonPath() { return m_SettingsPath + L"Addons\\"; } + + bool HasUserPluginPath() { return (_wcsicmp(m_Path.c_str(), m_SettingsPath.c_str()) != 0); } + + std::wstring GetDefaultSkinPath() { return m_Path + L"Defaults\\Skins\\"; } + std::wstring GetDefaultLayoutPath() { return m_Path + L"Defaults\\Layouts\\"; } + std::wstring GetDefaultPluginPath() { return m_Path + L"Defaults\\Plugins\\"; } + std::wstring GetDefaultAddonPath() { return m_Path + L"Defaults\\Addons\\"; } + + const std::wstring& GetDrive() { return m_Drive; } + + const std::wstring& GetSkinEditor() { return m_SkinEditor; } + void SetSkinEditor(const std::wstring& path); + const std::wstring& GetStatsDate() { return m_StatsDate; } + + HWND GetWindow() { return m_Window; } + + HINSTANCE GetModuleInstance() { return m_Instance; } + HINSTANCE GetResourceInstance() { return m_ResourceInstance; } + LCID GetResourceLCID() { return m_ResourceLCID; } + + bool GetUseD2D() const { return m_UseD2D; } + void SetUseD2D(bool enabled); + + bool GetDebug() { return m_Debug; } + + GlobalOptions& GetGlobalOptions() { return m_GlobalOptions; } + + void ReloadSettings(); + void EditSettings(); + void EditSkinFile(const std::wstring& name, const std::wstring& iniFile); + void OpenSkinFolder(const std::wstring& name = std::wstring()); + + void UpdateStats(); + void ReadStats(); + void WriteStats(bool bForce); + void ResetStats(); + + bool GetDisableVersionCheck() { return m_DisableVersionCheck; } + void SetDisableVersionCheck(bool check); + bool GetNewVersion() { return m_NewVersion; } + void SetNewVersion() { m_NewVersion = true; } + + void ShowLogFile(); + + bool GetDisableRDP() { return m_DisableRDP; } + bool IsRedrawable() { return (!GetDisableRDP() || !GetSystemMetrics(SM_REMOTESESSION)); } + + bool GetDisableDragging() { return m_DisableDragging; } + void SetDisableDragging(bool dragging); + + bool IsNormalStayDesktop() { return m_NormalStayDesktop; } + + void SetDebug(bool debug); + + int ShowMessage(HWND parent, const WCHAR* text, UINT type); + + bool IsMenuActive() { return m_ContextMenu.IsMenuActive(); } + void ShowContextMenu(POINT pos, MeterWindow* mw) { return m_ContextMenu.ShowMenu(pos, mw); } + void ShowSkinCustomContextMenu(POINT pos, MeterWindow* mw) { return m_ContextMenu.ShowSkinCustomMenu(pos, mw); } + + const std::wstring& GetTrayExecuteR() { return m_TrayExecuteR; } + const std::wstring& GetTrayExecuteM() { return m_TrayExecuteM; } + const std::wstring& GetTrayExecuteDR() { return m_TrayExecuteDR; } + const std::wstring& GetTrayExecuteDM() { return m_TrayExecuteDM; } + + void ExecuteBang(const WCHAR* bang, std::vector& args, MeterWindow* meterWindow); + void ExecuteCommand(const WCHAR* command, MeterWindow* meterWindow, bool multi = true); + void DelayedExecuteCommand(const WCHAR* command); + + void RefreshAll(); + + bool LoadLayout(const std::wstring& name); + void PreserveSetting(const std::wstring& from, LPCTSTR key, bool replace = true); + + friend class CommandHandler; + friend class ContextMenu; + friend class DialogManage; + +private: + Rainmeter(); + ~Rainmeter(); + + Rainmeter(const Rainmeter& other) = delete; + Rainmeter& operator=(Rainmeter other) = delete; + + static LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + void ActivateActiveSkins(); + void CreateMeterWindow(const std::wstring& folderPath, const std::wstring& file); + void DeleteAllMeterWindows(); + void DeleteAllUnmanagedMeterWindows(); + void WriteActive(const std::wstring& folderPath, int fileIndex); + void ScanForSkins(); + void ScanForLayouts(); + void ReadGeneralSettings(const std::wstring& iniFile); + void SetLoadOrder(int folderIndex, int order); + int GetLoadOrder(const std::wstring& folderPath); + void UpdateDesktopWorkArea(bool reset); + + void CreateOptionsFile(); + void CreateDataFile(); + void CreateComponentFolders(bool defaultIniLocation); + void TestSettingsFile(bool bDefaultIniLocation); + + TrayWindow* m_TrayWindow; + + std::multimap m_SkinOrders; + std::map m_MeterWindows; + std::list m_UnmanagedMeterWindows; + std::vector m_Layouts; + + std::wstring m_Path; + std::wstring m_IniFile; + std::wstring m_DataFile; + std::wstring m_StatsFile; + std::wstring m_SettingsPath; + std::wstring m_SkinPath; + + std::wstring m_Drive; + + std::wstring m_StatsDate; + + std::wstring m_TrayExecuteR; + std::wstring m_TrayExecuteM; + std::wstring m_TrayExecuteDR; + std::wstring m_TrayExecuteDM; + + bool m_UseD2D; + + bool m_Debug; + + bool m_DisableVersionCheck; + bool m_NewVersion; + + bool m_DesktopWorkAreaChanged; + bool m_DesktopWorkAreaType; + std::map m_DesktopWorkAreas; + std::vector m_OldDesktopWorkAreas; + + bool m_NormalStayDesktop; + + bool m_DisableRDP; + + bool m_DisableDragging; + + std::wstring m_SkinEditor; + + CommandHandler m_CommandHandler; + ContextMenu m_ContextMenu; + SkinRegistry m_SkinRegistry; + + ConfigParser* m_CurrentParser; + + HWND m_Window; + + HANDLE m_Mutex; + HINSTANCE m_Instance; + HMODULE m_ResourceInstance; + LCID m_ResourceLCID; + + ULONG_PTR m_GDIplusToken; + + GlobalOptions m_GlobalOptions; +}; + +#ifdef LIBRARY_EXPORTS +#define EXPORT_PLUGIN EXTERN_C __declspec(dllexport) +#else +#define EXPORT_PLUGIN EXTERN_C __declspec(dllimport) +#endif + +EXPORT_PLUGIN int RainmeterMain(LPWSTR cmdLine); +EXPORT_PLUGIN void* Rainmeter_Initialize(); +EXPORT_PLUGIN void Rainmeter_Finalize(void* ptr); + +#endif diff --git a/Library/RainmeterQuery.h b/Library/RainmeterQuery.h index ae48650b..0f112bc2 100644 --- a/Library/RainmeterQuery.h +++ b/Library/RainmeterQuery.h @@ -1,125 +1,125 @@ -/* - Copyright (C) 2010 JamesAC, spx - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/* -Rainmeter query interface based on Window Message - -The majority of the queries work as detailed below, other queries are explained along with their definitions. -Usage: -1) Post the query to Rainmeter (E.g. QueryRainmeterSkinsPath function) - * target window : Rainmeter(TrayWindow) - * message : WM_QUERY_RAINMETER - * wParam : QUERY ID (RAINMETER_QUERY_ID_XXXXX) - * lParam : window handle which receives WM_COPYDATA - -2) Retrieve the data received from Rainmeter, on WM_COPYDATA - * COPYDATASTRUCT->dwData : QUERY ID (RAINMETER_QUERY_ID_XXXXX) - * COPYDATASTRUCT->lpData : requested information. Form depends on you request. - * COPYDATASTRUCT->cbData : size of lpData - ------ -#include -#include -#include "RainmeterQuery.h" - -void QueryRainmeterSkinsPath(HWND hWndSelf) -{ - HWND hWndRainmeter = FindWindow(RAINMETER_QUERY_CLASS_NAME, RAINMETER_QUERY_WINDOW_NAME); - if (hWndRainmeter) - { - PostMessage(hWndRainmeter, WM_QUERY_RAINMETER, RAINMETER_QUERY_ID_SKINS_PATH, (LPARAM)hWndSelf); - } -} - -LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - case WM_COPYDATA: - { - COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam; - - // Copy ID and string to local - DWORD id = cds->dwData; // contains QUERY ID (RAINMETER_QUERY_ID_XXXXX) - std::wstring string = (WCHAR*)cds->lpData; // contains requested string in wide char - - // - ... - } - break; - - default: - return DefWindowProc(hWnd, message, wParam, lParam); - } - return 0; -} ------ -*/ - -#ifndef __RAINMETER_QUERY_H__ -#define __RAINMETER_QUERY_H__ - -#include - -#define RAINMETER_QUERY_CLASS_NAME TEXT("RainmeterTrayClass") -#define RAINMETER_QUERY_WINDOW_NAME nullptr - -#define WM_QUERY_RAINMETER WM_APP + 1000 -#define WM_QUERY_RAINMETER_RETURN WM_APP + 1001 - -/* -QUERY IDs -These Queries return a string in a wide char format -*/ -#define RAINMETER_QUERY_ID_SKINS_PATH 4101 -#define RAINMETER_QUERY_ID_SETTINGS_PATH 4102 -#define RAINMETER_QUERY_ID_PLUGINS_PATH 4103 -#define RAINMETER_QUERY_ID_PROGRAM_PATH 4104 -#define RAINMETER_QUERY_ID_LOG_PATH 4105 -#define RAINMETER_QUERY_ID_CONFIG_EDITOR 4106 - -/* -These Queries return a numerical value in a direct message, the data -is stored in the lParam of the message sent to your window, and the msg section -will contain WM_QUERY_RAINMETER_RETURN -*/ -#define RAINMETER_QUERY_ID_IS_DEBUGGING 4116 - -/*QUERY IDs used with WM_COPYDATA -Usage: Send a WM_COPYDATA message to rainmeter via SendMessage(). -Rainmeter will set the return value depending on the contents -of the COPYDATASTRUCT. -*/ -#define RAINMETER_QUERY_ID_SKIN_WINDOWHANDLE 5101 - -/* -This Retuns the Window Handle of the active skin requested by config name in cds.lpData, -or nullptr if the config is not loaded. Currently, the config name is Case-Sensitive. - -To requst the data, send a message to Rainmeter in a way similar to this example. -COPYDATASTRUCT cds; -LPWSTR SkinName = L"Gnometer\\Clock"; - -cds.dwData = 5101; -cds.lpData = SkinName; -cds.cbData = (wcslen(SkinName) + 1) * 2; - -HWND hWndMeter = (HWND) SendMessage(hWndRainmeter, WM_COPYDATA, (WPARAM) hWndYourWindow, (LPARAM) &cds); -*/ - -#endif +/* + Copyright (C) 2010 JamesAC, spx + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* +Rainmeter query interface based on Window Message + +The majority of the queries work as detailed below, other queries are explained along with their definitions. +Usage: +1) Post the query to Rainmeter (E.g. QueryRainmeterSkinsPath function) + * target window : Rainmeter(TrayWindow) + * message : WM_QUERY_RAINMETER + * wParam : QUERY ID (RAINMETER_QUERY_ID_XXXXX) + * lParam : window handle which receives WM_COPYDATA + +2) Retrieve the data received from Rainmeter, on WM_COPYDATA + * COPYDATASTRUCT->dwData : QUERY ID (RAINMETER_QUERY_ID_XXXXX) + * COPYDATASTRUCT->lpData : requested information. Form depends on you request. + * COPYDATASTRUCT->cbData : size of lpData + +----- +#include +#include +#include "RainmeterQuery.h" + +void QueryRainmeterSkinsPath(HWND hWndSelf) +{ + HWND hWndRainmeter = FindWindow(RAINMETER_QUERY_CLASS_NAME, RAINMETER_QUERY_WINDOW_NAME); + if (hWndRainmeter) + { + PostMessage(hWndRainmeter, WM_QUERY_RAINMETER, RAINMETER_QUERY_ID_SKINS_PATH, (LPARAM)hWndSelf); + } +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_COPYDATA: + { + COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam; + + // Copy ID and string to local + DWORD id = cds->dwData; // contains QUERY ID (RAINMETER_QUERY_ID_XXXXX) + std::wstring string = (WCHAR*)cds->lpData; // contains requested string in wide char + + // + ... + } + break; + + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} +----- +*/ + +#ifndef __RAINMETER_QUERY_H__ +#define __RAINMETER_QUERY_H__ + +#include + +#define RAINMETER_QUERY_CLASS_NAME TEXT("RainmeterTrayClass") +#define RAINMETER_QUERY_WINDOW_NAME nullptr + +#define WM_QUERY_RAINMETER WM_APP + 1000 +#define WM_QUERY_RAINMETER_RETURN WM_APP + 1001 + +/* +QUERY IDs +These Queries return a string in a wide char format +*/ +#define RAINMETER_QUERY_ID_SKINS_PATH 4101 +#define RAINMETER_QUERY_ID_SETTINGS_PATH 4102 +#define RAINMETER_QUERY_ID_PLUGINS_PATH 4103 +#define RAINMETER_QUERY_ID_PROGRAM_PATH 4104 +#define RAINMETER_QUERY_ID_LOG_PATH 4105 +#define RAINMETER_QUERY_ID_CONFIG_EDITOR 4106 + +/* +These Queries return a numerical value in a direct message, the data +is stored in the lParam of the message sent to your window, and the msg section +will contain WM_QUERY_RAINMETER_RETURN +*/ +#define RAINMETER_QUERY_ID_IS_DEBUGGING 4116 + +/*QUERY IDs used with WM_COPYDATA +Usage: Send a WM_COPYDATA message to rainmeter via SendMessage(). +Rainmeter will set the return value depending on the contents +of the COPYDATASTRUCT. +*/ +#define RAINMETER_QUERY_ID_SKIN_WINDOWHANDLE 5101 + +/* +This Retuns the Window Handle of the active skin requested by config name in cds.lpData, +or nullptr if the config is not loaded. Currently, the config name is Case-Sensitive. + +To requst the data, send a message to Rainmeter in a way similar to this example. +COPYDATASTRUCT cds; +LPWSTR SkinName = L"Gnometer\\Clock"; + +cds.dwData = 5101; +cds.lpData = SkinName; +cds.cbData = (wcslen(SkinName) + 1) * 2; + +HWND hWndMeter = (HWND) SendMessage(hWndRainmeter, WM_COPYDATA, (WPARAM) hWndYourWindow, (LPARAM) &cds); +*/ + +#endif diff --git a/Library/Section.cpp b/Library/Section.cpp index fc3013e3..10373ea0 100644 --- a/Library/Section.cpp +++ b/Library/Section.cpp @@ -1,87 +1,87 @@ -/* - Copyright (C) 2013 spx - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Section.h" -#include "ConfigParser.h" -#include "Rainmeter.h" - -/* -** The constructor -** -*/ -Section::Section(MeterWindow* meterWindow, const WCHAR* name) : m_MeterWindow(meterWindow), m_Name(name), - m_DynamicVariables(false), - m_UpdateDivider(1), - m_UpdateCounter(1) -{ -} - -/* -** The destructor -** -*/ -Section::~Section() -{ -} - -/* -** Read the common options specified in the ini file. The inherited classes must -** call this base implementation if they overwrite this method. -** -*/ -void Section::ReadOptions(ConfigParser& parser, const WCHAR* section) -{ - int updateDivider = parser.ReadInt(section, L"UpdateDivider", 1); - if (updateDivider != m_UpdateDivider) - { - m_UpdateCounter = m_UpdateDivider = updateDivider; - } - - m_DynamicVariables = parser.ReadBool(section, L"DynamicVariables", false); - - m_OnUpdateAction = parser.ReadString(section, L"OnUpdateAction", L"", false); - - const std::wstring& group = parser.ReadString(section, L"Group", L""); - InitializeGroup(group); -} - -/* -** Updates the counter value -** -*/ -bool Section::UpdateCounter() -{ - ++m_UpdateCounter; - if (m_UpdateCounter < m_UpdateDivider) return false; - m_UpdateCounter = 0; - - return true; -} - -/* -** Execute OnUpdateAction if action is set -** -*/ -void Section::DoUpdateAction() -{ - if (!m_OnUpdateAction.empty()) - { - Rainmeter::GetInstance().ExecuteCommand(m_OnUpdateAction.c_str(), m_MeterWindow); - } -} +/* + Copyright (C) 2013 spx + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Section.h" +#include "ConfigParser.h" +#include "Rainmeter.h" + +/* +** The constructor +** +*/ +Section::Section(MeterWindow* meterWindow, const WCHAR* name) : m_MeterWindow(meterWindow), m_Name(name), + m_DynamicVariables(false), + m_UpdateDivider(1), + m_UpdateCounter(1) +{ +} + +/* +** The destructor +** +*/ +Section::~Section() +{ +} + +/* +** Read the common options specified in the ini file. The inherited classes must +** call this base implementation if they overwrite this method. +** +*/ +void Section::ReadOptions(ConfigParser& parser, const WCHAR* section) +{ + int updateDivider = parser.ReadInt(section, L"UpdateDivider", 1); + if (updateDivider != m_UpdateDivider) + { + m_UpdateCounter = m_UpdateDivider = updateDivider; + } + + m_DynamicVariables = parser.ReadBool(section, L"DynamicVariables", false); + + m_OnUpdateAction = parser.ReadString(section, L"OnUpdateAction", L"", false); + + const std::wstring& group = parser.ReadString(section, L"Group", L""); + InitializeGroup(group); +} + +/* +** Updates the counter value +** +*/ +bool Section::UpdateCounter() +{ + ++m_UpdateCounter; + if (m_UpdateCounter < m_UpdateDivider) return false; + m_UpdateCounter = 0; + + return true; +} + +/* +** Execute OnUpdateAction if action is set +** +*/ +void Section::DoUpdateAction() +{ + if (!m_OnUpdateAction.empty()) + { + Rainmeter::GetInstance().ExecuteCommand(m_OnUpdateAction.c_str(), m_MeterWindow); + } +} diff --git a/Library/Section.h b/Library/Section.h index 1d22d41a..c56d4171 100644 --- a/Library/Section.h +++ b/Library/Section.h @@ -1,73 +1,73 @@ -/* - Copyright (C) 2012 spx - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __SECTION_H__ -#define __SECTION_H__ - -#include -#include -#include "Group.h" - -class MeterWindow; -class ConfigParser; - -class __declspec(novtable) Section : public Group -{ -public: - virtual ~Section(); - - Section(const Section& other) = delete; - - virtual UINT GetTypeID() = 0; - - const WCHAR* GetName() const { return m_Name.c_str(); } - const std::wstring& GetOriginalName() const { return m_Name; } - - bool HasDynamicVariables() const { return m_DynamicVariables; } - void SetDynamicVariables(bool b) { m_DynamicVariables = b; } - - void ResetUpdateCounter() { m_UpdateCounter = m_UpdateDivider; } - int GetUpdateCounter() const { return m_UpdateCounter; } - int GetUpdateDivider() const { return m_UpdateDivider; } - - const std::wstring& GetOnUpdateAction() { return m_OnUpdateAction; } - void DoUpdateAction(); - - MeterWindow* GetMeterWindow() { return m_MeterWindow; } - -protected: - Section(MeterWindow* meterWindow, const WCHAR* name); - - virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); - - bool UpdateCounter(); - - // Plugins may access this string through RmGetMeasureName(). This should never be modified to - // ensure thread-safety. - const std::wstring m_Name; - - bool m_DynamicVariables; // If true, the section contains dynamic variables - int m_UpdateDivider; // Divider for the update - int m_UpdateCounter; // Current update counter - - std::wstring m_OnUpdateAction; - - MeterWindow* m_MeterWindow; -}; - -#endif +/* + Copyright (C) 2012 spx + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __SECTION_H__ +#define __SECTION_H__ + +#include +#include +#include "Group.h" + +class MeterWindow; +class ConfigParser; + +class __declspec(novtable) Section : public Group +{ +public: + virtual ~Section(); + + Section(const Section& other) = delete; + + virtual UINT GetTypeID() = 0; + + const WCHAR* GetName() const { return m_Name.c_str(); } + const std::wstring& GetOriginalName() const { return m_Name; } + + bool HasDynamicVariables() const { return m_DynamicVariables; } + void SetDynamicVariables(bool b) { m_DynamicVariables = b; } + + void ResetUpdateCounter() { m_UpdateCounter = m_UpdateDivider; } + int GetUpdateCounter() const { return m_UpdateCounter; } + int GetUpdateDivider() const { return m_UpdateDivider; } + + const std::wstring& GetOnUpdateAction() { return m_OnUpdateAction; } + void DoUpdateAction(); + + MeterWindow* GetMeterWindow() { return m_MeterWindow; } + +protected: + Section(MeterWindow* meterWindow, const WCHAR* name); + + virtual void ReadOptions(ConfigParser& parser, const WCHAR* section); + + bool UpdateCounter(); + + // Plugins may access this string through RmGetMeasureName(). This should never be modified to + // ensure thread-safety. + const std::wstring m_Name; + + bool m_DynamicVariables; // If true, the section contains dynamic variables + int m_UpdateDivider; // Divider for the update + int m_UpdateCounter; // Current update counter + + std::wstring m_OnUpdateAction; + + MeterWindow* m_MeterWindow; +}; + +#endif diff --git a/Library/SkinRegistry.cpp b/Library/SkinRegistry.cpp index d97d4973..764ec33d 100644 --- a/Library/SkinRegistry.cpp +++ b/Library/SkinRegistry.cpp @@ -1,242 +1,242 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../Common/PathUtil.h" -#include "SkinRegistry.h" -#include "resource.h" - -/* -** Returns the skin folder path relative to the skin folder (e.g. illustro\Clock). -*/ -std::wstring SkinRegistry::GetFolderPath(int folderIndex) const -{ - // Traverse |m_Folders| backwards until level 1 is reached. - const auto& skinFolder = m_Folders[folderIndex]; - std::wstring path = skinFolder.name; - for (int i = skinFolder.level - 1, index = folderIndex; i >= 1; --i) - { - while (m_Folders[index].level != i) - { - --index; - } - - path.insert(0, L"\\"); - path.insert(0, m_Folders[index].name); - } - return path; -} - -/* -** Finds the skin index for the specified skin folder path. -*/ -int SkinRegistry::FindFolderIndex(const std::wstring& folderPath) const -{ - if (folderPath.empty()) return -1; - - const WCHAR* path = folderPath.c_str(); - int len = 0; - while (path[len] && path[len] != L'\\') ++len; - - int level = 1; - for (int i = 0, isize = (int)m_Folders.size(); i < isize; ++i) - { - const auto& skinFolder = m_Folders[i]; - if (skinFolder.level == level) - { - if (skinFolder.name.length() == len && _wcsnicmp(skinFolder.name.c_str(), path, len) == 0) - { - path += len; - if (*path) - { - ++path; // Skip backslash - len = 0; - while (path[len] && path[len] != L'\\') ++len; - } - else - { - // Match found - return i; - } - - ++level; - } - } - else if (skinFolder.level < level) - { - break; - } - } - - return -1; -} - -SkinRegistry::Folder* SkinRegistry::FindFolder(const std::wstring& folderPath) -{ - const int folderIndex = FindFolderIndex(folderPath); - return (folderIndex != -1) ? &m_Folders[folderIndex] : nullptr; -} - -SkinRegistry::Indexes SkinRegistry::FindIndexes(const std::wstring& folderPath, const std::wstring& file) -{ - const int folderIndex = FindFolderIndex(folderPath); - if (folderIndex != -1) - { - const Folder& skinFolder = m_Folders[folderIndex]; - const WCHAR* fileSz = file.c_str(); - for (size_t i = 0, isize = skinFolder.files.size(); i < isize; ++i) - { - if (_wcsicmp(skinFolder.files[i].c_str(), fileSz) == 0) - { - return Indexes(folderIndex, (int)i); - } - } - } - - return Indexes::Invalid(); // Not found. -} - -SkinRegistry::Indexes SkinRegistry::FindIndexesForID(UINT id) -{ - if (id >= ID_CONFIG_FIRST && id <= ID_CONFIG_LAST) - { - // Check which skin was selected - for (size_t i = 0, isize = m_Folders.size(); i < isize; ++i) - { - const Folder& skinFolder = m_Folders[i]; - if (id >= skinFolder.baseID && - id < (skinFolder.baseID + skinFolder.files.size())) - { - return Indexes((int)i, (int)(id - skinFolder.baseID)); - } - } - } - - return Indexes::Invalid(); // Not found. -} - -/* -** Re-scans all the subfolders of |path| for .ini files and populates |m_Folders|. -*/ -void SkinRegistry::Populate(const std::wstring& path) -{ - m_Folders.clear(); - PopulateRecursive(path, L"", 0, 0); -} - -int SkinRegistry::PopulateRecursive(const std::wstring& path, std::wstring base, int index, UINT level) -{ - WIN32_FIND_DATA fileData; // Data structure describes the file found - HANDLE hSearch; // Search handle returned by FindFirstFile - std::list subfolders; - - // Find all .ini files and subfolders - std::wstring filter = path + base; - filter += L"\\*"; - - hSearch = FindFirstFileEx( - filter.c_str(), - (IsWindows7OrGreater()) ? FindExInfoBasic : FindExInfoStandard, - &fileData, - FindExSearchNameMatch, - nullptr, - 0); - - bool foundFiles = false; - if (hSearch != INVALID_HANDLE_VALUE) - { - Folder folder; - folder.baseID = ID_CONFIG_FIRST + index; - folder.active = 0; - folder.level = level; - - do - { - const std::wstring filename = fileData.cFileName; - - if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - if (!PathUtil::IsDotOrDotDot(fileData.cFileName) && - !(level == 0 && wcscmp(L"@Backup", fileData.cFileName) == 0) && - !(level == 0 && wcscmp(L"Backup", fileData.cFileName) == 0) && - !(level == 1 && wcscmp(L"@Resources", fileData.cFileName) == 0)) - { - subfolders.push_back(filename); - } - } - else if (level != 0) - { - // Check whether the extension is ".ini" - size_t filenameLen = filename.size(); - if (filenameLen >= 4 && _wcsicmp(fileData.cFileName + (filenameLen - 4), L".ini") == 0) - { - foundFiles = true; - folder.files.push_back(filename); - ++index; - } - } - } - while (FindNextFile(hSearch, &fileData)); - - FindClose(hSearch); - - if (level > 0 && (foundFiles || !subfolders.empty())) - { - if (level == 1) - { - folder.name = base; - } - else - { - std::wstring::size_type pos = base.rfind(L'\\') + 1; - folder.name.assign(base, pos, base.length() - pos); - } - - m_Folders.push_back(std::move(folder)); - } - } - - if (level != 0) - { - base += L'\\'; - } - - if (!subfolders.empty()) - { - bool popFolder = !foundFiles; - - std::list::const_iterator iter = subfolders.begin(); - for ( ; iter != subfolders.end(); ++iter) - { - int newIndex = PopulateRecursive(path, base + (*iter), index, level + 1); - if (newIndex != index) - { - popFolder = false; - } - - index = newIndex; - } - - if (popFolder) - { - m_Folders.pop_back(); - } - } - - return index; -} +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../Common/PathUtil.h" +#include "SkinRegistry.h" +#include "resource.h" + +/* +** Returns the skin folder path relative to the skin folder (e.g. illustro\Clock). +*/ +std::wstring SkinRegistry::GetFolderPath(int folderIndex) const +{ + // Traverse |m_Folders| backwards until level 1 is reached. + const auto& skinFolder = m_Folders[folderIndex]; + std::wstring path = skinFolder.name; + for (int i = skinFolder.level - 1, index = folderIndex; i >= 1; --i) + { + while (m_Folders[index].level != i) + { + --index; + } + + path.insert(0, L"\\"); + path.insert(0, m_Folders[index].name); + } + return path; +} + +/* +** Finds the skin index for the specified skin folder path. +*/ +int SkinRegistry::FindFolderIndex(const std::wstring& folderPath) const +{ + if (folderPath.empty()) return -1; + + const WCHAR* path = folderPath.c_str(); + int len = 0; + while (path[len] && path[len] != L'\\') ++len; + + int level = 1; + for (int i = 0, isize = (int)m_Folders.size(); i < isize; ++i) + { + const auto& skinFolder = m_Folders[i]; + if (skinFolder.level == level) + { + if (skinFolder.name.length() == len && _wcsnicmp(skinFolder.name.c_str(), path, len) == 0) + { + path += len; + if (*path) + { + ++path; // Skip backslash + len = 0; + while (path[len] && path[len] != L'\\') ++len; + } + else + { + // Match found + return i; + } + + ++level; + } + } + else if (skinFolder.level < level) + { + break; + } + } + + return -1; +} + +SkinRegistry::Folder* SkinRegistry::FindFolder(const std::wstring& folderPath) +{ + const int folderIndex = FindFolderIndex(folderPath); + return (folderIndex != -1) ? &m_Folders[folderIndex] : nullptr; +} + +SkinRegistry::Indexes SkinRegistry::FindIndexes(const std::wstring& folderPath, const std::wstring& file) +{ + const int folderIndex = FindFolderIndex(folderPath); + if (folderIndex != -1) + { + const Folder& skinFolder = m_Folders[folderIndex]; + const WCHAR* fileSz = file.c_str(); + for (size_t i = 0, isize = skinFolder.files.size(); i < isize; ++i) + { + if (_wcsicmp(skinFolder.files[i].c_str(), fileSz) == 0) + { + return Indexes(folderIndex, (int)i); + } + } + } + + return Indexes::Invalid(); // Not found. +} + +SkinRegistry::Indexes SkinRegistry::FindIndexesForID(UINT id) +{ + if (id >= ID_CONFIG_FIRST && id <= ID_CONFIG_LAST) + { + // Check which skin was selected + for (size_t i = 0, isize = m_Folders.size(); i < isize; ++i) + { + const Folder& skinFolder = m_Folders[i]; + if (id >= skinFolder.baseID && + id < (skinFolder.baseID + skinFolder.files.size())) + { + return Indexes((int)i, (int)(id - skinFolder.baseID)); + } + } + } + + return Indexes::Invalid(); // Not found. +} + +/* +** Re-scans all the subfolders of |path| for .ini files and populates |m_Folders|. +*/ +void SkinRegistry::Populate(const std::wstring& path) +{ + m_Folders.clear(); + PopulateRecursive(path, L"", 0, 0); +} + +int SkinRegistry::PopulateRecursive(const std::wstring& path, std::wstring base, int index, UINT level) +{ + WIN32_FIND_DATA fileData; // Data structure describes the file found + HANDLE hSearch; // Search handle returned by FindFirstFile + std::list subfolders; + + // Find all .ini files and subfolders + std::wstring filter = path + base; + filter += L"\\*"; + + hSearch = FindFirstFileEx( + filter.c_str(), + (IsWindows7OrGreater()) ? FindExInfoBasic : FindExInfoStandard, + &fileData, + FindExSearchNameMatch, + nullptr, + 0); + + bool foundFiles = false; + if (hSearch != INVALID_HANDLE_VALUE) + { + Folder folder; + folder.baseID = ID_CONFIG_FIRST + index; + folder.active = 0; + folder.level = level; + + do + { + const std::wstring filename = fileData.cFileName; + + if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (!PathUtil::IsDotOrDotDot(fileData.cFileName) && + !(level == 0 && wcscmp(L"@Backup", fileData.cFileName) == 0) && + !(level == 0 && wcscmp(L"Backup", fileData.cFileName) == 0) && + !(level == 1 && wcscmp(L"@Resources", fileData.cFileName) == 0)) + { + subfolders.push_back(filename); + } + } + else if (level != 0) + { + // Check whether the extension is ".ini" + size_t filenameLen = filename.size(); + if (filenameLen >= 4 && _wcsicmp(fileData.cFileName + (filenameLen - 4), L".ini") == 0) + { + foundFiles = true; + folder.files.push_back(filename); + ++index; + } + } + } + while (FindNextFile(hSearch, &fileData)); + + FindClose(hSearch); + + if (level > 0 && (foundFiles || !subfolders.empty())) + { + if (level == 1) + { + folder.name = base; + } + else + { + std::wstring::size_type pos = base.rfind(L'\\') + 1; + folder.name.assign(base, pos, base.length() - pos); + } + + m_Folders.push_back(std::move(folder)); + } + } + + if (level != 0) + { + base += L'\\'; + } + + if (!subfolders.empty()) + { + bool popFolder = !foundFiles; + + std::list::const_iterator iter = subfolders.begin(); + for ( ; iter != subfolders.end(); ++iter) + { + int newIndex = PopulateRecursive(path, base + (*iter), index, level + 1); + if (newIndex != index) + { + popFolder = false; + } + + index = newIndex; + } + + if (popFolder) + { + m_Folders.pop_back(); + } + } + + return index; +} diff --git a/Library/SkinRegistry.h b/Library/SkinRegistry.h index 85ecd305..1e09bb0d 100644 --- a/Library/SkinRegistry.h +++ b/Library/SkinRegistry.h @@ -1,105 +1,105 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef RM_LIBRARY_SKINDIRECTORY_H_ -#define RM_LIBRARY_SKINDIRECTORY_H_ - -#include -#include -#include -#include - -// Reprsents a hierarchy of skin folders (reprsented by the Folder struct) and the names of their -// respective files. -class SkinRegistry -{ -public: - SkinRegistry() = default; - SkinRegistry(const SkinRegistry& other) = delete; - SkinRegistry& operator=(SkinRegistry other) = delete; - - struct Folder - { - std::wstring name; - std::vector files; - UINT baseID; - - int16_t active; - int16_t level; - - Folder() {} - ~Folder() {} - - Folder(Folder&& r) : - name(std::move(r.name)), - files(std::move(r.files)), - baseID(r.baseID), - active(r.active), - level(r.level) - { - } - - Folder& operator=(Folder&& r) - { - name = std::move(r.name); - files = std::move(r.files); - baseID = r.baseID; - active = r.active; - level = r.level; - return *this; - } - }; - - struct Indexes - { - int folder; - int file; - - Indexes(int folderIndex = 0, int fileIndex = 0) : folder(folderIndex), file(fileIndex) {} - - bool IsValid() const { return folder != -1; } - - static Indexes Invalid() { return Indexes(-1, 0); } - }; - - int FindFolderIndex(const std::wstring& folderPath) const; - Folder* FindFolder(const std::wstring& folderPath); - - Indexes FindIndexes(const std::wstring& folderPath, const std::wstring& file); - Indexes FindIndexesForID(UINT id); - - std::wstring GetFolderPath(int folderIndex) const; - - Folder& GetFolder(int index) { return m_Folders[index]; } - int GetFolderCount() const { return (int)m_Folders.size(); } - bool IsEmpty() const { return m_Folders.empty(); } - - void Populate(const std::wstring& path); - -private: - int PopulateRecursive(const std::wstring& path, std::wstring base, int index, UINT level); - - // Contains a sequential list of Folders. The folders are arranged as follows: - // A (index: 0, level: 1) - // B (index: 1, level: 2) - // C (index: 2, level: 3) - // D (index: 3, level: 2) - std::vector m_Folders; -}; - -#endif +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef RM_LIBRARY_SKINDIRECTORY_H_ +#define RM_LIBRARY_SKINDIRECTORY_H_ + +#include +#include +#include +#include + +// Reprsents a hierarchy of skin folders (reprsented by the Folder struct) and the names of their +// respective files. +class SkinRegistry +{ +public: + SkinRegistry() = default; + SkinRegistry(const SkinRegistry& other) = delete; + SkinRegistry& operator=(SkinRegistry other) = delete; + + struct Folder + { + std::wstring name; + std::vector files; + UINT baseID; + + int16_t active; + int16_t level; + + Folder() {} + ~Folder() {} + + Folder(Folder&& r) : + name(std::move(r.name)), + files(std::move(r.files)), + baseID(r.baseID), + active(r.active), + level(r.level) + { + } + + Folder& operator=(Folder&& r) + { + name = std::move(r.name); + files = std::move(r.files); + baseID = r.baseID; + active = r.active; + level = r.level; + return *this; + } + }; + + struct Indexes + { + int folder; + int file; + + Indexes(int folderIndex = 0, int fileIndex = 0) : folder(folderIndex), file(fileIndex) {} + + bool IsValid() const { return folder != -1; } + + static Indexes Invalid() { return Indexes(-1, 0); } + }; + + int FindFolderIndex(const std::wstring& folderPath) const; + Folder* FindFolder(const std::wstring& folderPath); + + Indexes FindIndexes(const std::wstring& folderPath, const std::wstring& file); + Indexes FindIndexesForID(UINT id); + + std::wstring GetFolderPath(int folderIndex) const; + + Folder& GetFolder(int index) { return m_Folders[index]; } + int GetFolderCount() const { return (int)m_Folders.size(); } + bool IsEmpty() const { return m_Folders.empty(); } + + void Populate(const std::wstring& path); + +private: + int PopulateRecursive(const std::wstring& path, std::wstring base, int index, UINT level); + + // Contains a sequential list of Folders. The folders are arranged as follows: + // A (index: 0, level: 1) + // B (index: 1, level: 2) + // C (index: 2, level: 3) + // D (index: 3, level: 2) + std::vector m_Folders; +}; + +#endif diff --git a/Library/SkinRegistry_Test.cpp b/Library/SkinRegistry_Test.cpp index 86649798..83c5627b 100644 --- a/Library/SkinRegistry_Test.cpp +++ b/Library/SkinRegistry_Test.cpp @@ -1,104 +1,104 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "SkinRegistry.h" -#include "../Common/UnitTest.h" - -TEST_CLASS(Library_SkinRegistry_Test) -{ -public: - Library_SkinRegistry_Test() - { - m_SkinRegistry.Populate(L"..\\..\\..\\Library\\Test\\SkinRegistry\\"); - } - - TEST_METHOD(TestContents) - { - std::vector files1; - files1.push_back(L"1.ini"); - - std::vector files3; - files3.push_back(L"1.ini"); - files3.push_back(L"2.ini"); - files3.push_back(L"3.ini"); - - Assert::AreEqual(5, m_SkinRegistry.GetFolderCount()); - - const auto& folderA1 = m_SkinRegistry.GetFolder(0); - Assert::AreEqual(L"A1", folderA1.name.c_str()); - Assert::AreEqual((int16_t)1, folderA1.level); - Assert::IsTrue(folderA1.files.empty()); - - const auto& folderA1_B1 = m_SkinRegistry.GetFolder(1); - Assert::AreEqual(L"B1", folderA1_B1.name.c_str()); - Assert::AreEqual((int16_t)2, folderA1_B1.level); - Assert::IsTrue(files1 == folderA1_B1.files); - - const auto& folderA1_B2 = m_SkinRegistry.GetFolder(2); - Assert::AreEqual(L"B2", folderA1_B2.name.c_str()); - Assert::AreEqual((int16_t)2, folderA1_B2.level); - Assert::IsTrue(files1 == folderA1_B2.files); - - const auto& folderA1_B2_C1 = m_SkinRegistry.GetFolder(3); - Assert::AreEqual(L"C1", folderA1_B2_C1.name.c_str()); - Assert::AreEqual((int16_t)3, folderA1_B2_C1.level); - Assert::IsTrue(files1 == folderA1_B2_C1.files); - - const auto& folderA2 = m_SkinRegistry.GetFolder(4); - Assert::AreEqual(L"A2", folderA2.name.c_str()); - Assert::AreEqual((int16_t)1, folderA2.level); - Assert::IsTrue(files3 == folderA2.files); - } - - TEST_METHOD(TestFindFolderIndex) - { - Assert::AreEqual(3, m_SkinRegistry.FindFolderIndex(L"A1\\B2\\C1")); - Assert::AreEqual(-1, m_SkinRegistry.FindFolderIndex(L"A1\\B5\\C1")); - } - - TEST_METHOD(TestFindIndexes) - { - const auto indexes1 = m_SkinRegistry.FindIndexes(L"A1\\B2", L"1.ini"); - Assert::IsTrue(indexes1.folder == 2 && indexes1.file == 0); - - const auto indexes2 = m_SkinRegistry.FindIndexes(L"A2", L"2.ini"); - Assert::IsTrue(indexes2.folder == 4 && indexes2.file == 1); - - const auto indexes3 = m_SkinRegistry.FindIndexes(L"A3", L"1.ini"); - Assert::IsFalse(indexes3.IsValid()); - } - - TEST_METHOD(TestFindIndexesForID) - { - const auto indexes1 = m_SkinRegistry.FindIndexesForID(30002); - Assert::IsTrue(indexes1.folder == 2 && indexes1.file == 0); - - const auto indexes2 = m_SkinRegistry.FindIndexesForID(30005); - Assert::IsTrue(indexes2.folder == 4 && indexes2.file == 1); - } - - TEST_METHOD(TestGetFolderPath) - { - Assert::AreEqual(L"A1\\B2\\C1", m_SkinRegistry.GetFolderPath(3).c_str()); - Assert::AreEqual(L"A2", m_SkinRegistry.GetFolderPath(4).c_str()); - } - -private: - SkinRegistry m_SkinRegistry; -}; +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "SkinRegistry.h" +#include "../Common/UnitTest.h" + +TEST_CLASS(Library_SkinRegistry_Test) +{ +public: + Library_SkinRegistry_Test() + { + m_SkinRegistry.Populate(L"..\\..\\..\\Library\\Test\\SkinRegistry\\"); + } + + TEST_METHOD(TestContents) + { + std::vector files1; + files1.push_back(L"1.ini"); + + std::vector files3; + files3.push_back(L"1.ini"); + files3.push_back(L"2.ini"); + files3.push_back(L"3.ini"); + + Assert::AreEqual(5, m_SkinRegistry.GetFolderCount()); + + const auto& folderA1 = m_SkinRegistry.GetFolder(0); + Assert::AreEqual(L"A1", folderA1.name.c_str()); + Assert::AreEqual((int16_t)1, folderA1.level); + Assert::IsTrue(folderA1.files.empty()); + + const auto& folderA1_B1 = m_SkinRegistry.GetFolder(1); + Assert::AreEqual(L"B1", folderA1_B1.name.c_str()); + Assert::AreEqual((int16_t)2, folderA1_B1.level); + Assert::IsTrue(files1 == folderA1_B1.files); + + const auto& folderA1_B2 = m_SkinRegistry.GetFolder(2); + Assert::AreEqual(L"B2", folderA1_B2.name.c_str()); + Assert::AreEqual((int16_t)2, folderA1_B2.level); + Assert::IsTrue(files1 == folderA1_B2.files); + + const auto& folderA1_B2_C1 = m_SkinRegistry.GetFolder(3); + Assert::AreEqual(L"C1", folderA1_B2_C1.name.c_str()); + Assert::AreEqual((int16_t)3, folderA1_B2_C1.level); + Assert::IsTrue(files1 == folderA1_B2_C1.files); + + const auto& folderA2 = m_SkinRegistry.GetFolder(4); + Assert::AreEqual(L"A2", folderA2.name.c_str()); + Assert::AreEqual((int16_t)1, folderA2.level); + Assert::IsTrue(files3 == folderA2.files); + } + + TEST_METHOD(TestFindFolderIndex) + { + Assert::AreEqual(3, m_SkinRegistry.FindFolderIndex(L"A1\\B2\\C1")); + Assert::AreEqual(-1, m_SkinRegistry.FindFolderIndex(L"A1\\B5\\C1")); + } + + TEST_METHOD(TestFindIndexes) + { + const auto indexes1 = m_SkinRegistry.FindIndexes(L"A1\\B2", L"1.ini"); + Assert::IsTrue(indexes1.folder == 2 && indexes1.file == 0); + + const auto indexes2 = m_SkinRegistry.FindIndexes(L"A2", L"2.ini"); + Assert::IsTrue(indexes2.folder == 4 && indexes2.file == 1); + + const auto indexes3 = m_SkinRegistry.FindIndexes(L"A3", L"1.ini"); + Assert::IsFalse(indexes3.IsValid()); + } + + TEST_METHOD(TestFindIndexesForID) + { + const auto indexes1 = m_SkinRegistry.FindIndexesForID(30002); + Assert::IsTrue(indexes1.folder == 2 && indexes1.file == 0); + + const auto indexes2 = m_SkinRegistry.FindIndexesForID(30005); + Assert::IsTrue(indexes2.folder == 4 && indexes2.file == 1); + } + + TEST_METHOD(TestGetFolderPath) + { + Assert::AreEqual(L"A1\\B2\\C1", m_SkinRegistry.GetFolderPath(3).c_str()); + Assert::AreEqual(L"A2", m_SkinRegistry.GetFolderPath(4).c_str()); + } + +private: + SkinRegistry m_SkinRegistry; +}; diff --git a/Library/StdAfx.cpp b/Library/StdAfx.cpp index 8ff49aab..dfe2dcad 100644 --- a/Library/StdAfx.cpp +++ b/Library/StdAfx.cpp @@ -1,19 +1,19 @@ -/* - Copyright (C) 2001 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" +/* + Copyright (C) 2001 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" diff --git a/Library/StdAfx.h b/Library/StdAfx.h index eb117b76..5159a5ed 100644 --- a/Library/StdAfx.h +++ b/Library/StdAfx.h @@ -1,67 +1,67 @@ -/* - Copyright (C) 2009 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __STDAFX_H__ -#define __STDAFX_H__ - -#define _CRTDBG_MAP_ALLOC -#include - -// WINAPI -#include -#include -#include -#include // For Gdiplus.h. -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// STL -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// RUNTIME -#include - -// ADDITIONAL MACRO -#define IsCtrlKeyDown() (GetKeyState(VK_CONTROL) < 0) -#define IsShiftKeyDown() (GetKeyState(VK_SHIFT) < 0) -#define IsAltKeyDown() (GetKeyState(VK_MENU) < 0) - -#endif +/* + Copyright (C) 2009 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __STDAFX_H__ +#define __STDAFX_H__ + +#define _CRTDBG_MAP_ALLOC +#include + +// WINAPI +#include +#include +#include +#include // For Gdiplus.h. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// STL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// RUNTIME +#include + +// ADDITIONAL MACRO +#define IsCtrlKeyDown() (GetKeyState(VK_CONTROL) < 0) +#define IsShiftKeyDown() (GetKeyState(VK_SHIFT) < 0) +#define IsAltKeyDown() (GetKeyState(VK_MENU) < 0) + +#endif diff --git a/Library/System.cpp b/Library/System.cpp index 7de52d9b..3dab216e 100644 --- a/Library/System.cpp +++ b/Library/System.cpp @@ -1,1406 +1,1406 @@ -/* - Copyright (C) 2010 spx - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "System.h" -#include "Litestep.h" -#include "Rainmeter.h" -#include "MeterWindow.h" -#include "MeasureNet.h" -#include "Error.h" -#include "../Common/PathUtil.h" - -using namespace Gdiplus; - -#define DEBUG_VERBOSE (0) // Set 1 if you need verbose logging. - -#define ZPOS_FLAGS (SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING) - -enum TIMER -{ - TIMER_SHOWDESKTOP = 1, - TIMER_RESUME = 2 -}; -enum INTERVAL -{ - INTERVAL_SHOWDESKTOP = 250, - INTERVAL_RESTOREWINDOWS = 100, - INTERVAL_RESUME = 1000 -}; - -MultiMonitorInfo System::c_Monitors = { 0 }; - -HWND System::c_Window = nullptr; -HWND System::c_HelperWindow = nullptr; - -HWINEVENTHOOK System::c_WinEventHook = nullptr; - -bool System::c_ShowDesktop = false; - -std::wstring System::c_WorkingDirectory; - -std::vector System::c_IniFileMappings; - -/* -** Creates a helper window to detect changes in the system. -** -*/ -void System::Initialize(HINSTANCE instance) -{ - WNDCLASS wc = {0}; - wc.lpfnWndProc = (WNDPROC)WndProc; - wc.hInstance = instance; - wc.lpszClassName = L"RainmeterSystem"; - ATOM className = RegisterClass(&wc); - - c_Window = CreateWindowEx( - WS_EX_TOOLWINDOW, - MAKEINTATOM(className), - L"System", - WS_POPUP | WS_DISABLED, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - nullptr, - nullptr, - instance, - nullptr); - - c_HelperWindow = CreateWindowEx( - WS_EX_TOOLWINDOW, - MAKEINTATOM(className), - L"PositioningHelper", - WS_POPUP | WS_DISABLED, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - nullptr, - nullptr, - instance, - nullptr); - - SetWindowPos(c_Window, HWND_BOTTOM, 0, 0, 0, 0, ZPOS_FLAGS); - SetWindowPos(c_HelperWindow, HWND_BOTTOM, 0, 0, 0, 0, ZPOS_FLAGS); - - c_Monitors.monitors.reserve(4); - SetMultiMonitorInfo(); - - WCHAR directory[MAX_PATH]; - DWORD len = GetCurrentDirectory(MAX_PATH, directory); - c_WorkingDirectory.assign(directory, len <= MAX_PATH ? len : 0); - - c_WinEventHook = SetWinEventHook( - EVENT_SYSTEM_FOREGROUND, - EVENT_SYSTEM_FOREGROUND, - nullptr, - MyWinEventProc, - 0, - 0, - WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); - - SetTimer(c_Window, TIMER_SHOWDESKTOP, INTERVAL_SHOWDESKTOP, nullptr); -} - -/* -** Destroys a window. -** -*/ -void System::Finalize() -{ - KillTimer(c_Window, TIMER_SHOWDESKTOP); - KillTimer(c_Window, TIMER_RESUME); - - if (c_WinEventHook) - { - UnhookWinEvent(c_WinEventHook); - c_WinEventHook = nullptr; - } - - if (c_HelperWindow) - { - DestroyWindow(c_HelperWindow); - c_HelperWindow = nullptr; - } - - if (c_Window) - { - DestroyWindow(c_Window); - c_Window = nullptr; - } -} - -/* -** Retrieves the multi-monitor information. -** -*/ -BOOL CALLBACK MyInfoEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -{ - MultiMonitorInfo* m = (MultiMonitorInfo*)dwData; - - MONITORINFOEX info; - info.cbSize = sizeof(MONITORINFOEX); - GetMonitorInfo(hMonitor, &info); - - if (Rainmeter::GetInstance().GetDebug()) - { - LogDebug(info.szDevice); - LogDebugF(L" Flags : %s(0x%08X)", (info.dwFlags & MONITORINFOF_PRIMARY) ? L"PRIMARY " : L"", info.dwFlags); - LogDebugF(L" Handle : 0x%p", hMonitor); - LogDebugF(L" ScrArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", - lprcMonitor->left, lprcMonitor->top, lprcMonitor->right, lprcMonitor->bottom, - lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top); - LogDebugF(L" WorkArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", - info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom, - info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); - } - if (m == nullptr) return TRUE; - - if (m->useEnumDisplayDevices) - { - for (auto iter = m->monitors.begin(); iter != m->monitors.end(); ++iter) - { - if ((*iter).handle == nullptr && _wcsicmp(info.szDevice, (*iter).deviceName.c_str()) == 0) - { - (*iter).handle = hMonitor; - (*iter).screen = *lprcMonitor; - (*iter).work = info.rcWork; - break; - } - } - } - else // use only EnumDisplayMonitors - { - MonitorInfo monitor; - monitor.active = true; - - monitor.handle = hMonitor; - monitor.screen = *lprcMonitor; - monitor.work = info.rcWork; - - monitor.deviceName = info.szDevice; // E.g. "\\.\DISPLAY1" - - // Get the monitor name (E.g. "Generic Non-PnP Monitor") - DISPLAY_DEVICE ddm = {sizeof(DISPLAY_DEVICE)}; - DWORD dwMon = 0; - while (EnumDisplayDevices(info.szDevice, dwMon++, &ddm, 0)) - { - if (ddm.StateFlags & DISPLAY_DEVICE_ACTIVE && ddm.StateFlags & DISPLAY_DEVICE_ATTACHED) - { - monitor.monitorName.assign(ddm.DeviceString, wcsnlen(ddm.DeviceString, _countof(ddm.DeviceString))); - break; - } - } - - m->monitors.push_back(monitor); - - if (info.dwFlags & MONITORINFOF_PRIMARY) - { - // It's primary monitor! - m->primary = (int)m->monitors.size(); - } - } - - return TRUE; -} - -/* -** Returns the number of monitors. -** -*/ -size_t System::GetMonitorCount() -{ - if (c_Monitors.monitors.empty()) - { - SetMultiMonitorInfo(); - } - return c_Monitors.monitors.size(); -} - -/* -** Sets the multi-monitor information. -** -*/ -void System::SetMultiMonitorInfo() -{ - std::vector& monitors = c_Monitors.monitors; - bool logging = Rainmeter::GetInstance().GetDebug(); - - c_Monitors.vsT = GetSystemMetrics(SM_YVIRTUALSCREEN); - c_Monitors.vsL = GetSystemMetrics(SM_XVIRTUALSCREEN); - c_Monitors.vsH = GetSystemMetrics(SM_CYVIRTUALSCREEN); - c_Monitors.vsW = GetSystemMetrics(SM_CXVIRTUALSCREEN); - - c_Monitors.primary = 1; // If primary screen is not found, 1st screen is assumed as primary screen. - - c_Monitors.useEnumDisplayDevices = true; - c_Monitors.useEnumDisplayMonitors = false; - - if (logging) - { - LogDebug(L"------------------------------"); - LogDebug(L"* EnumDisplayDevices / EnumDisplaySettings API"); - } - - DISPLAY_DEVICE dd = {sizeof(DISPLAY_DEVICE)}; - - if (EnumDisplayDevices(nullptr, 0, &dd, 0)) - { - DWORD dwDevice = 0; - - do - { - std::wstring msg; - - std::wstring deviceName(dd.DeviceName, wcsnlen(dd.DeviceName, _countof(dd.DeviceName))); - std::wstring deviceString; - - if (logging) - { - deviceString.assign(dd.DeviceString, wcsnlen(dd.DeviceString, _countof(dd.DeviceString))); - - LogDebug(deviceName.c_str()); - - if (dd.StateFlags & DISPLAY_DEVICE_ACTIVE) - { - msg += L"ACTIVE "; - } - if (dd.StateFlags & DISPLAY_DEVICE_MULTI_DRIVER) - { - msg += L"MULTI "; - } - if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) - { - msg += L"PRIMARY "; - } - if (dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) - { - msg += L"MIRROR "; - } - if (dd.StateFlags & DISPLAY_DEVICE_VGA_COMPATIBLE) - { - msg += L"VGA "; - } - if (dd.StateFlags & DISPLAY_DEVICE_REMOVABLE) - { - msg += L"REMOVABLE "; - } - if (dd.StateFlags & DISPLAY_DEVICE_MODESPRUNED) - { - msg += L"PRUNED "; - } - if (dd.StateFlags & DISPLAY_DEVICE_REMOTE) - { - msg += L"REMOTE "; - } - if (dd.StateFlags & DISPLAY_DEVICE_DISCONNECT) - { - msg += L"DISCONNECT "; - } - } - - if ((dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) == 0) - { - MonitorInfo monitor = {0}; - - monitor.handle = nullptr; - monitor.deviceName = deviceName; // E.g. "\\.\DISPLAY1" - - // Get the monitor name (E.g. "Generic Non-PnP Monitor") - DISPLAY_DEVICE ddm = {sizeof(DISPLAY_DEVICE)}; - DWORD dwMon = 0; - while (EnumDisplayDevices(deviceName.c_str(), dwMon++, &ddm, 0)) - { - if (ddm.StateFlags & DISPLAY_DEVICE_ACTIVE && ddm.StateFlags & DISPLAY_DEVICE_ATTACHED) - { - monitor.monitorName.assign(ddm.DeviceString, wcsnlen(ddm.DeviceString, _countof(ddm.DeviceString))); - - if (logging) - { - LogDebugF(L" Name : %s", monitor.monitorName.c_str()); - } - break; - } - } - - if (logging) - { - LogDebugF(L" Adapter : %s", deviceString.c_str()); - LogDebugF(L" Flags : %s(0x%08X)", msg.c_str(), dd.StateFlags); - } - - if (dd.StateFlags & DISPLAY_DEVICE_ACTIVE) - { - monitor.active = true; - - DEVMODE dm = {0}; - dm.dmSize = sizeof(DEVMODE); - - if (EnumDisplaySettings(deviceName.c_str(), ENUM_CURRENT_SETTINGS, &dm)) - { - POINT pos = {dm.dmPosition.x, dm.dmPosition.y}; - monitor.handle = MonitorFromPoint(pos, MONITOR_DEFAULTTONULL); - - if (logging) - { - LogDebugF(L" Handle : 0x%p", monitor.handle); - } - } - - if (monitor.handle != nullptr) - { - MONITORINFO info = {sizeof(MONITORINFO)}; - GetMonitorInfo(monitor.handle, &info); - - monitor.screen = info.rcMonitor; - monitor.work = info.rcWork; - - if (logging) - { - LogDebugF(L" ScrArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", - info.rcMonitor.left, info.rcMonitor.top, info.rcMonitor.right, info.rcMonitor.bottom, - info.rcMonitor.right - info.rcMonitor.left, info.rcMonitor.bottom - info.rcMonitor.top); - LogDebugF(L" WorkArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", - info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom, - info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); - } - } - else // monitor not found - { - c_Monitors.useEnumDisplayMonitors = true; - } - } - else - { - monitor.active = false; - } - - monitors.push_back(monitor); - - if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) - { - // It's primary monitor! - c_Monitors.primary = (int)monitors.size(); - } - } - else - { - if (logging) - { - LogDebugF(L" Adapter : %s", deviceString.c_str()); - LogDebugF(L" Flags : %s(0x%08X)", msg.c_str(), dd.StateFlags); - } - } - ++dwDevice; - } - while (EnumDisplayDevices(nullptr, dwDevice, &dd, 0)); - } - - if (monitors.empty()) // Failed to enumerate the non-mirroring monitors - { - LogWarning(L"Failed to enumerate the non-mirroring monitors. Only EnumDisplayMonitors is used instead."); - c_Monitors.useEnumDisplayDevices = false; - c_Monitors.useEnumDisplayMonitors = true; - } - - if (logging) - { - LogDebug(L"------------------------------"); - LogDebug(L"* EnumDisplayMonitors API"); - } - - if (c_Monitors.useEnumDisplayMonitors) - { - EnumDisplayMonitors(nullptr, nullptr, MyInfoEnumProc, (LPARAM)(&c_Monitors)); - - if (monitors.empty()) // Failed to enumerate the monitors - { - LogWarning(L"Failed to enumerate monitors. Using dummy monitor info."); - c_Monitors.useEnumDisplayMonitors = false; - - MonitorInfo monitor; - monitor.active = true; - - POINT pos = {0, 0}; - monitor.handle = MonitorFromPoint(pos, MONITOR_DEFAULTTOPRIMARY); - monitor.screen.left = 0; - monitor.screen.top = 0; - monitor.screen.right = GetSystemMetrics(SM_CXSCREEN); - monitor.screen.bottom = GetSystemMetrics(SM_CYSCREEN); - if (SystemParametersInfo(SPI_GETWORKAREA, 0, &(monitor.work), 0) == 0) // failed - { - monitor.work = monitor.screen; - } - - monitor.deviceName = L"DUMMY"; - - monitors.push_back(monitor); - - c_Monitors.primary = 1; - } - } - else - { - if (logging) - { - EnumDisplayMonitors(nullptr, nullptr, MyInfoEnumProc, (LPARAM)nullptr); // Only logging - } - } - - if (logging) - { - LogDebug(L"------------------------------"); - - std::wstring method = L"* METHOD: "; - if (c_Monitors.useEnumDisplayDevices) - { - method += L"EnumDisplayDevices + "; - method += c_Monitors.useEnumDisplayMonitors ? L"EnumDisplayMonitors Mode" : L"EnumDisplaySettings Mode"; - } - else - { - method += c_Monitors.useEnumDisplayMonitors ? L"EnumDisplayMonitors Mode" : L"Dummy Mode"; - } - LogDebug(method.c_str()); - - LogDebugF(L"* MONITORS: Count=%i, Primary=@%i", (int)monitors.size(), c_Monitors.primary); - LogDebug(L"@0: Virtual screen"); - LogDebugF(L" L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", - c_Monitors.vsL, c_Monitors.vsT, c_Monitors.vsL + c_Monitors.vsW, c_Monitors.vsT + c_Monitors.vsH, - c_Monitors.vsW, c_Monitors.vsH); - - int i = 1; - for (auto iter = monitors.cbegin(); iter != monitors.cend(); ++iter, ++i) - { - if ((*iter).active) - { - LogDebugF(L"@%i: %s (active), MonitorName: %s", i, (*iter).deviceName.c_str(), (*iter).monitorName.c_str()); - LogDebugF(L" L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", - (*iter).screen.left, (*iter).screen.top, (*iter).screen.right, (*iter).screen.bottom, - (*iter).screen.right - (*iter).screen.left, (*iter).screen.bottom - (*iter).screen.top); - } - else - { - LogDebugF(L"@%i: %s (inactive), MonitorName: %s", i, (*iter).deviceName.c_str(), (*iter).monitorName.c_str()); - } - } - LogDebug(L"------------------------------"); - } -} - -/* -** Updates the workarea information. -** -*/ -void System::UpdateWorkareaInfo() -{ - std::vector& monitors = c_Monitors.monitors; - - if (monitors.empty()) - { - SetMultiMonitorInfo(); - return; - } - - int i = 1; - for (auto iter = monitors.begin(); iter != monitors.end(); ++iter, ++i) - { - if ((*iter).active && (*iter).handle != nullptr) - { - MONITORINFO info = {sizeof(MONITORINFO)}; - GetMonitorInfo((*iter).handle, &info); - - (*iter).work = info.rcWork; - - if (Rainmeter::GetInstance().GetDebug()) - { - LogDebugF(L"WorkArea@%i : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", - i, - info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom, - info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); - } - } - } -} - -/* -** Finds the Default Shell's window. -** -*/ -HWND System::GetDefaultShellWindow() -{ - static HWND c_ShellW = nullptr; // cache - HWND ShellW = GetShellWindow(); - - if (ShellW) - { - if (ShellW == c_ShellW) - { - return ShellW; - } - else - { - const int classLen = _countof(L"Progman") + 1; - WCHAR className[classLen]; - if (!(GetClassName(ShellW, className, classLen) > 0 && - wcscmp(className, L"Progman") == 0)) - { - ShellW = nullptr; - } - } - } - - c_ShellW = ShellW; - return ShellW; -} - -/* -** Finds the WorkerW window. -** If the WorkerW window is not active, returns nullptr. -** -*/ -HWND System::GetWorkerW() -{ - static HWND c_DefView = nullptr; // cache - HWND ShellW = GetDefaultShellWindow(); - if (!ShellW) return nullptr; // Default Shell (Explorer) not running - - if (c_DefView && IsWindow(c_DefView)) - { - HWND parent = GetAncestor(c_DefView, GA_PARENT); - if (parent) - { - if (parent == ShellW) - { - return nullptr; - } - else - { - const int classLen = _countof(L"WorkerW") + 1; - WCHAR className[classLen]; - if (GetClassName(parent, className, classLen) > 0 && - wcscmp(className, L"WorkerW") == 0) - { - return parent; - } - } - } - } - - HWND WorkerW = nullptr, DefView = FindWindowEx(ShellW, nullptr, L"SHELLDLL_DefView", L""); - if (DefView == nullptr) - { - while (WorkerW = FindWindowEx(nullptr, WorkerW, L"WorkerW", L"")) - { - if (IsWindowVisible(WorkerW) && - BelongToSameProcess(ShellW, WorkerW) && - (DefView = FindWindowEx(WorkerW, nullptr, L"SHELLDLL_DefView", L""))) - { - break; - } - } - } - - c_DefView = DefView; - return WorkerW; -} - -/* -** Returns the first window whose position is not ZPOSITION_ONDESKTOP, -** ZPOSITION_BOTTOM, or ZPOSITION_NORMAL. -** -*/ -HWND System::GetBackmostTopWindow() -{ - HWND winPos = c_HelperWindow; - - // Skip all ZPOSITION_ONDESKTOP, ZPOSITION_BOTTOM, and ZPOSITION_NORMAL windows - while (winPos = ::GetNextWindow(winPos, GW_HWNDPREV)) - { - MeterWindow* wnd = Rainmeter::GetInstance().GetMeterWindow(winPos); - if (!wnd || - (wnd->GetWindowZPosition() != ZPOSITION_NORMAL && - wnd->GetWindowZPosition() != ZPOSITION_ONDESKTOP && - wnd->GetWindowZPosition() != ZPOSITION_ONBOTTOM)) - { - break; - } - } - - return winPos; -} - -/* -** Checks whether the given windows belong to the same process. -** -*/ -bool System::BelongToSameProcess(HWND hwndA, HWND hwndB) -{ - DWORD procAId = 0, procBId = 0; - - GetWindowThreadProcessId(hwndA, &procAId); - GetWindowThreadProcessId(hwndB, &procBId); - - return (procAId == procBId); -} - -/* -** Retrieves the Rainmeter's meter windows in Z-order. -** -*/ -BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM lParam) -{ - bool logging = Rainmeter::GetInstance().GetDebug() && DEBUG_VERBOSE; - const int classLen = _countof(METERWINDOW_CLASS_NAME) + (DEBUG_VERBOSE ? 32 : 1); - WCHAR className[classLen]; - MeterWindow* Window; - WCHAR flag; - - if (GetClassName(hwnd, className, classLen) > 0 && - wcscmp(className, METERWINDOW_CLASS_NAME) == 0 && - (Window = Rainmeter::GetInstance().GetMeterWindow(hwnd))) - { - ZPOSITION zPos = Window->GetWindowZPosition(); - if (zPos == ZPOSITION_ONDESKTOP || - (zPos == ZPOSITION_NORMAL && Rainmeter::GetInstance().IsNormalStayDesktop()) || - zPos == ZPOSITION_ONBOTTOM) - { - if (lParam) - { - ((std::vector*)lParam)->push_back(Window); - } - - if (logging) flag = L'+'; - } - else - { - if (logging) flag = L'-'; - } - - if (logging) - { - LogDebugF(L"%c [%c] 0x%p : %s (Name: \"%s\", zPos=%i)", - flag, IsWindowVisible(hwnd) ? L'V' : L'H', hwnd, className, Window->GetFolderPath().c_str(), (int)zPos); - } - } - else - { - if (logging) - { - flag = (hwnd == System::GetHelperWindow()) ? L'o' : ' '; - LogDebugF(L"%c [%c] 0x%p : %s", flag, IsWindowVisible(hwnd) ? L'V' : L'H', hwnd, className); - } - } - - return TRUE; -} - -/* -** Arranges the meter window in Z-order. -** -*/ -void System::ChangeZPosInOrder() -{ - bool logging = Rainmeter::GetInstance().GetDebug() && DEBUG_VERBOSE; - std::vector windowsInZOrder; - - if (logging) LogDebug(L"1: ----- BEFORE -----"); - - // Retrieve the Rainmeter's meter windows in Z-order - EnumWindows(MyEnumWindowsProc, (LPARAM)(&windowsInZOrder)); - - auto resetZPos = [&](ZPOSITION zpos) - { - // Reset ZPos in Z-order (Bottom) - std::vector::const_iterator iter = windowsInZOrder.begin(); - for ( ; iter != windowsInZOrder.end(); ++iter) - { - if ((*iter)->GetWindowZPosition() == zpos) - { - (*iter)->ChangeZPos(zpos); // reset - } - } - }; - - if (Rainmeter::GetInstance().IsNormalStayDesktop()) - { - resetZPos(ZPOSITION_NORMAL); - } - - if (!c_ShowDesktop) - { - resetZPos(ZPOSITION_ONBOTTOM); - } - - resetZPos(ZPOSITION_ONDESKTOP); - - if (logging) - { - LogDebug(L"2: ----- AFTER -----"); - - // Log all windows in Z-order - EnumWindows(MyEnumWindowsProc, (LPARAM)nullptr); - } -} - -/* -** Moves the helper window to the reference position. -** -*/ -void System::PrepareHelperWindow(HWND WorkerW) -{ - bool logging = Rainmeter::GetInstance().GetDebug() && DEBUG_VERBOSE; - - SetWindowPos(c_Window, HWND_BOTTOM, 0, 0, 0, 0, ZPOS_FLAGS); // always on bottom - - if (c_ShowDesktop && WorkerW) - { - // Set WS_EX_TOPMOST flag - SetWindowPos(c_HelperWindow, HWND_TOPMOST, 0, 0, 0, 0, ZPOS_FLAGS); - - // Find the "backmost" topmost window - HWND hwnd = WorkerW; - while (hwnd = ::GetNextWindow(hwnd, GW_HWNDPREV)) - { - if (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) - { - WCHAR className[64], windowText[64]; - - if (logging) - { - GetClassName(hwnd, className, 64); - GetWindowText(hwnd, windowText, 64); - - SetLastError(ERROR_SUCCESS); - } - - // Insert the helper window after the found window - if (0 != SetWindowPos(c_HelperWindow, hwnd, 0, 0, 0, 0, ZPOS_FLAGS)) - { - if (logging) - { - LogDebugF(L"System: HelperWindow: hwnd=0x%p (WorkerW=0x%p), hwndInsertAfter=0x%p (\"%s\" %s) - %s", - c_HelperWindow, WorkerW, hwnd, windowText, className, (GetWindowLongPtr(c_HelperWindow, GWL_EXSTYLE) & WS_EX_TOPMOST) ? L"TOPMOST" : L"NORMAL"); - } - return; - } - - if (logging) - { - DWORD err = GetLastError(); - LogDebugF(L"System: HelperWindow: hwnd=0x%p (WorkerW=0x%p), hwndInsertAfter=0x%p (\"%s\" %s) - FAILED (ErrorCode=0x%08X)", - c_HelperWindow, WorkerW, hwnd, windowText, className, err); - } - } - } - - if (logging) - { - LogDebugF(L"System: HelperWindow: hwnd=0x%p (WorkerW=0x%p), hwndInsertAfter=HWND_TOPMOST - %s", - c_HelperWindow, WorkerW, (GetWindowLongPtr(c_HelperWindow, GWL_EXSTYLE) & WS_EX_TOPMOST) ? L"TOPMOST" : L"NORMAL"); - } - } - else - { - // Insert the helper window to the bottom - SetWindowPos(c_HelperWindow, HWND_BOTTOM, 0, 0, 0, 0, ZPOS_FLAGS); - - if (logging) - { - LogDebugF(L"System: HelperWindow: hwnd=0x%p (WorkerW=0x%p), hwndInsertAfter=HWND_BOTTOM - %s", - c_HelperWindow, WorkerW, (GetWindowLongPtr(c_HelperWindow, GWL_EXSTYLE) & WS_EX_TOPMOST) ? L"TOPMOST" : L"NORMAL"); - } - } -} - -/* -** Changes the "Show Desktop" state. -** -*/ -bool System::CheckDesktopState(HWND WorkerW) -{ - HWND hwnd = nullptr; - - if (WorkerW && IsWindowVisible(WorkerW)) - { - hwnd = FindWindowEx(nullptr, WorkerW, L"RainmeterSystem", L"System"); - } - - bool stateChanged = (hwnd && !c_ShowDesktop) || (!hwnd && c_ShowDesktop); - - if (stateChanged) - { - c_ShowDesktop = !c_ShowDesktop; - - if (Rainmeter::GetInstance().GetDebug()) - { - LogDebugF(L"System: \"Show %s\" has been detected.", - c_ShowDesktop ? L"desktop" : L"open windows"); - } - - PrepareHelperWindow(WorkerW); - - ChangeZPosInOrder(); - - if (c_ShowDesktop) - { - SetTimer(c_Window, TIMER_SHOWDESKTOP, INTERVAL_RESTOREWINDOWS, nullptr); - } - else - { - SetTimer(c_Window, TIMER_SHOWDESKTOP, INTERVAL_SHOWDESKTOP, nullptr); - } - } - - return stateChanged; -} - -/* -** The event hook procedure -** -*/ -void CALLBACK System::MyWinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime) -{ - if (event == EVENT_SYSTEM_FOREGROUND) - { - if (!c_ShowDesktop) - { - const int classLen = _countof(L"WorkerW") + 1; - WCHAR className[classLen]; - if (GetClassName(hwnd, className, classLen) > 0 && - wcscmp(className, L"WorkerW") == 0 && - BelongToSameProcess(GetDefaultShellWindow(), hwnd)) - { - const int max = 5; - int loop = 0; - while (loop < max && FindWindowEx(hwnd, nullptr, L"SHELLDLL_DefView", L"") == nullptr) - { - Sleep(2); // Wait for 2-16 ms before retrying - ++loop; - } - - if (loop < max) - { - loop = 0; - while (loop < max && !CheckDesktopState(hwnd)) - { - Sleep(2); // Wait for 2-16 ms before retrying - ++loop; - } - } - } - } - } -} - -/* -** The window procedure -** -*/ -LRESULT CALLBACK System::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (hWnd != c_Window) - { - if (uMsg == WM_WINDOWPOSCHANGING) - { - ((LPWINDOWPOS)lParam)->flags |= SWP_NOZORDER; - return 0; - } - return DefWindowProc(hWnd, uMsg, wParam, lParam); - } - - switch (uMsg) - { - case WM_WINDOWPOSCHANGING: - ((LPWINDOWPOS)lParam)->flags |= SWP_NOZORDER; - break; - - case WM_TIMER: - switch (wParam) - { - case TIMER_SHOWDESKTOP: - if (wParam == TIMER_SHOWDESKTOP) - { - CheckDesktopState(GetWorkerW()); - } - break; - - case TIMER_RESUME: - KillTimer(hWnd, TIMER_RESUME); - if (Rainmeter::GetInstance().IsRedrawable()) - { - std::map::const_iterator iter = Rainmeter::GetInstance().GetAllMeterWindows().begin(); - for ( ; iter != Rainmeter::GetInstance().GetAllMeterWindows().end(); ++iter) - { - (*iter).second->RedrawWindow(); - } - } - break; - } - break; - - case WM_DISPLAYCHANGE: - LogNotice(L"System: Display settings changed"); - ClearMultiMonitorInfo(); - ConfigParser::ClearMultiMonitorVariables(); - case WM_SETTINGCHANGE: - if (uMsg == WM_DISPLAYCHANGE || (/*uMsg == WM_SETTINGCHANGE &&*/ wParam == SPI_SETWORKAREA)) - { - if (uMsg == WM_SETTINGCHANGE) // SPI_SETWORKAREA - { - LogNotice(L"System: Work area changed"); - UpdateWorkareaInfo(); - ConfigParser::UpdateWorkareaVariables(); - } - - // Deliver WM_DISPLAYCHANGE / WM_SETTINGCHANGE message to all meter windows - std::map::const_iterator iter = Rainmeter::GetInstance().GetAllMeterWindows().begin(); - for ( ; iter != Rainmeter::GetInstance().GetAllMeterWindows().end(); ++iter) - { - PostMessage((*iter).second->GetWindow(), WM_METERWINDOW_DELAYED_MOVE, (WPARAM)uMsg, (LPARAM)0); - } - } - break; - - case WM_POWERBROADCAST: - if (wParam == PBT_APMRESUMESUSPEND) - { - // Deliver PBT_APMRESUMESUSPEND event to all meter windows - SetTimer(hWnd, TIMER_RESUME, INTERVAL_RESUME, nullptr); - } - return TRUE; - - default: - return DefWindowProc(hWnd, uMsg, wParam, lParam); - } - - return 0; -} - -/* -** Retrieves the number of milliseconds that have elapsed since the system was started. -** In XP, returns the predictive value due to the 32bit limitation. -** -*/ -ULONGLONG System::GetTickCount64() -{ - static auto s_GetTickCount64 = - (decltype(GetTickCount64)*)GetProcAddress(GetModuleHandle(L"kernel32"), "GetTickCount64"); - - if (s_GetTickCount64) - { - return s_GetTickCount64(); - } - else - { - static ULONGLONG lastTicks = 0; - ULONGLONG ticks = GetTickCount(); - while (ticks < lastTicks) ticks += 0x100000000; - lastTicks = ticks; - return ticks; - } -} - -/* -** Gets the cursor position in last message retrieved by GetMessage(). -** -*/ -POINT System::GetCursorPosition() -{ - DWORD pos = GetMessagePos(); - POINT pt = { GET_X_LPARAM(pos), GET_Y_LPARAM(pos) }; - return pt; -} - -/* -** Checks if file is writable. -** -*/ -bool System::IsFileWritable(LPCWSTR file) -{ - HANDLE hFile = CreateFile(file, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); - if (hFile == INVALID_HANDLE_VALUE) - { - return false; - } - - CloseHandle(hFile); - return true; -} - -/* -** This function is a wrapper function for LoadLibrary(). -** -** Avoids loading a DLL from current directory. -** -*/ -HMODULE System::RmLoadLibrary(LPCWSTR lpLibFileName, DWORD* dwError) -{ - // Remove current directory from DLL search path - SetDllDirectory(L""); - - SetLastError(ERROR_SUCCESS); - HMODULE hLib = LoadLibrary(lpLibFileName); - - if (dwError) - { - *dwError = GetLastError(); - } - - return hLib; -} - -/* -** Resets working directory to default. -** -*/ -void System::ResetWorkingDirectory() -{ - WCHAR directory[MAX_PATH] = {0}; - GetCurrentDirectory(MAX_PATH, directory); - - const WCHAR* workDir = c_WorkingDirectory.c_str(); - if (_wcsicmp(directory, workDir) != 0) - { - SetCurrentDirectory(workDir); - } -} - -/* -** Initializes a critical section object by using InitializeCriticalSectionEx function with CRITICAL_SECTION_NO_DEBUG_INFO flag. -** For more details: http://stackoverflow.com/questions/804848/critical-sections-leaking-memory-on-vista-win2008/ -** -*/ -void System::InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) -{ - static auto s_InitializeCriticalSectionEx = IsWindowsVistaOrGreater() ? - (decltype(InitializeCriticalSectionEx)*)GetProcAddress(GetModuleHandle(L"kernel32"), "InitializeCriticalSectionEx") : nullptr; - - if (s_InitializeCriticalSectionEx && - s_InitializeCriticalSectionEx(lpCriticalSection, 0, CRITICAL_SECTION_NO_DEBUG_INFO)) - { - return; - } - - InitializeCriticalSectionAndSpinCount(lpCriticalSection, 0); -} - -/* -** Sets clipboard text to given string. -** -*/ -void System::SetClipboardText(const std::wstring& text) -{ - if (OpenClipboard(nullptr)) - { - // Include terminating null char - size_t len = text.length() + 1; - - HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len * sizeof(WCHAR)); - if (hMem) - { - LPVOID data = GlobalLock(hMem); - memcpy(data, text.c_str(), len * sizeof(WCHAR)); - GlobalUnlock(hMem); - - EmptyClipboard(); - if (!SetClipboardData(CF_UNICODETEXT, hMem)) - { - GlobalFree(hMem); - } - } - - CloseClipboard(); - } -} - -/* -** Sets the system wallpapar. -** -*/ -void System::SetWallpaper(const std::wstring& wallpaper, const std::wstring& style) -{ - if (!wallpaper.empty()) - { - if (_waccess(wallpaper.c_str(), 0) == -1) - { - LogErrorF(L"!SetWallpaper: Unable to read file: %s", wallpaper.c_str()); - return; - } - - Bitmap bitmap(wallpaper.c_str()); - if (bitmap.GetLastStatus() == Ok) - { - std::wstring file = Rainmeter::GetInstance().GetSettingsPath() + L"Wallpaper.bmp"; - - const CLSID bmpClsid = { 0x557cf400, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }; - if (bitmap.Save(file.c_str(), &bmpClsid) == Ok) - { - if (!style.empty()) - { - HKEY hKey; - if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Control Panel\\Desktop", 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) - { - const WCHAR* wallStyle = nullptr; - const WCHAR* wallTile = L"0"; - - const WCHAR* option = style.c_str(); - if (_wcsicmp(option, L"CENTER") == 0) - { - wallStyle = L"0"; - } - else if (_wcsicmp(option, L"TILE") == 0) - { - wallStyle = L"0"; - wallTile = L"1"; - } - else if (_wcsicmp(option, L"STRETCH") == 0) - { - wallStyle = L"2"; - } - else if (IsWindows7OrGreater()) - { - if (_wcsicmp(option, L"FIT") == 0) - { - wallStyle = L"6"; - } - else if (_wcsicmp(option, L"FILL") == 0) - { - wallStyle = L"10"; - } - } - - if (wallStyle) - { - RegSetValueEx(hKey, L"WallpaperStyle", 0, REG_SZ, (const BYTE*)wallStyle, sizeof(WCHAR) * 2); - RegSetValueEx(hKey, L"TileWallpaper", 0, REG_SZ, (const BYTE*)wallTile, sizeof(WCHAR) * 2); - } - else - { - LogError(L"!SetWallpaper: Invalid style"); - } - - RegCloseKey(hKey); - } - } - - SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)file.c_str(), SPIF_UPDATEINIFILE); - } - } - } -} - -/* -** Copies files and folders from one location to another. -** -*/ -bool System::CopyFiles(std::wstring from, std::wstring to, bool bMove) -{ - // If given "from" path ends with path separator, remove it (Workaround for XP: error code 1026) - size_t len; - while (len = from.size(), len > 0 && PathUtil::IsSeparator(from[len - 1])) - { - from.resize(len - 1); - } - - // The strings must end with double \0 - from.append(1, L'\0'); - to.append(1, L'\0'); - - SHFILEOPSTRUCT fo = - { - nullptr, - bMove ? FO_MOVE : FO_COPY, - from.c_str(), - to.c_str(), - FOF_NO_UI | FOF_NOCONFIRMATION | FOF_ALLOWUNDO - }; - - int result = SHFileOperation(&fo); - if (result != 0) - { - LogErrorF(L"Copy error: From %s to %s (%i)", from.c_str(), to.c_str(), result); - return false; - } - return true; -} - -/* -** Removes a file even if a file is read-only. -** -*/ -bool System::RemoveFile(const std::wstring& file) -{ - DWORD attr = GetFileAttributes(file.c_str()); - if (attr == -1 || (attr & FILE_ATTRIBUTE_READONLY)) - { - // Unset read-only - SetFileAttributes(file.c_str(), (attr == -1) ? FILE_ATTRIBUTE_NORMAL : attr - FILE_ATTRIBUTE_READONLY); - } - - return (DeleteFile(file.c_str()) != 0); -} - -/* -** Recursively removes folder. -** -*/ -bool System::RemoveFolder(std::wstring folder) -{ - // The strings must end with double nul - folder.append(1, L'\0'); - - SHFILEOPSTRUCT fo = - { - nullptr, - FO_DELETE, - folder.c_str(), - nullptr, - FOF_NO_UI | FOF_NOCONFIRMATION | FOF_ALLOWUNDO - }; - - int result = SHFileOperation(&fo); - if (result != 0) - { - LogErrorF(L"Unable to delete folder %s (%i)", folder.c_str(), result); - return false; - } - return true; -} - -/* -** Retrieves the "IniFileMapping" entries from Registry. -** -*/ -void System::UpdateIniFileMappingList() -{ - static ULONGLONG s_LastWriteTime = 0; - - HKEY hKey; - LONG ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping", 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey); - if (ret == ERROR_SUCCESS) - { - DWORD numSubKeys; - ULONGLONG ftLastWriteTime; - bool changed = false; - - ret = RegQueryInfoKey(hKey, nullptr, nullptr, nullptr, &numSubKeys, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, (LPFILETIME)&ftLastWriteTime); - if (ret == ERROR_SUCCESS) - { - //LogDebugF(L"IniFileMapping: numSubKeys=%u, ftLastWriteTime=%llu", numSubKeys, ftLastWriteTime); - - if (ftLastWriteTime != s_LastWriteTime || - numSubKeys != c_IniFileMappings.size()) - { - s_LastWriteTime = ftLastWriteTime; - if (numSubKeys > c_IniFileMappings.capacity()) - { - c_IniFileMappings.reserve(numSubKeys); - } - changed = true; - } - } - else - { - s_LastWriteTime = 0; - changed = true; - } - - if (changed) - { - if (!c_IniFileMappings.empty()) - { - c_IniFileMappings.clear(); - } - - WCHAR* buffer = new WCHAR[MAX_PATH]; - DWORD index = 0, cch = MAX_PATH; - - while ((ret = RegEnumKeyEx(hKey, index++, buffer, &cch, nullptr, nullptr, nullptr, nullptr)) != ERROR_NO_MORE_ITEMS) - { - if (ret == ERROR_SUCCESS) - { - c_IniFileMappings.push_back(buffer); - } - cch = MAX_PATH; - } - - delete [] buffer; - } - - RegCloseKey(hKey); - } -} - -/* -** Prepares a temporary file if iniFile is included in the "IniFileMapping" entries. -** If iniFile is not included, returns a empty string. If error occurred, returns "?". -** Note that a temporary file must be deleted by caller. -** -*/ -std::wstring System::GetTemporaryFile(const std::wstring& iniFile) -{ - std::wstring temporary; - - if (!c_IniFileMappings.empty()) - { - std::wstring::size_type pos = iniFile.find_last_of(L"\\/"); - const WCHAR* filename = iniFile.c_str() + ((pos != std::wstring::npos) ? pos + 1 : 0); - - std::vector::const_iterator iter = c_IniFileMappings.begin(); - for ( ; iter != c_IniFileMappings.end(); ++iter) - { - if (_wcsicmp((*iter).c_str(), filename) == 0) - { - WCHAR* buffer = new WCHAR[MAX_PATH]; - - if (GetTempPath(MAX_PATH, buffer) != 0 && - GetTempFileName(buffer, L"cfg", 0, buffer) != 0) - { - temporary = buffer; - - std::wstring tmp = GetTemporaryFile(temporary); - if (!tmp.empty() || !CopyFiles(iniFile, temporary)) // temporary is reserved or failed - { - RemoveFile(temporary); - - if (tmp.empty()) - { - temporary = L"?"; - } - else - { - temporary.swap(tmp); - } - } - } - else // failed - { - LogErrorF(L"Unable to create temporary file to: %s", temporary.c_str()); - temporary = L"?"; - } - - delete [] buffer; - break; - } - } - } - - return temporary; -} +/* + Copyright (C) 2010 spx + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "System.h" +#include "Litestep.h" +#include "Rainmeter.h" +#include "MeterWindow.h" +#include "MeasureNet.h" +#include "Error.h" +#include "../Common/PathUtil.h" + +using namespace Gdiplus; + +#define DEBUG_VERBOSE (0) // Set 1 if you need verbose logging. + +#define ZPOS_FLAGS (SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING) + +enum TIMER +{ + TIMER_SHOWDESKTOP = 1, + TIMER_RESUME = 2 +}; +enum INTERVAL +{ + INTERVAL_SHOWDESKTOP = 250, + INTERVAL_RESTOREWINDOWS = 100, + INTERVAL_RESUME = 1000 +}; + +MultiMonitorInfo System::c_Monitors = { 0 }; + +HWND System::c_Window = nullptr; +HWND System::c_HelperWindow = nullptr; + +HWINEVENTHOOK System::c_WinEventHook = nullptr; + +bool System::c_ShowDesktop = false; + +std::wstring System::c_WorkingDirectory; + +std::vector System::c_IniFileMappings; + +/* +** Creates a helper window to detect changes in the system. +** +*/ +void System::Initialize(HINSTANCE instance) +{ + WNDCLASS wc = {0}; + wc.lpfnWndProc = (WNDPROC)WndProc; + wc.hInstance = instance; + wc.lpszClassName = L"RainmeterSystem"; + ATOM className = RegisterClass(&wc); + + c_Window = CreateWindowEx( + WS_EX_TOOLWINDOW, + MAKEINTATOM(className), + L"System", + WS_POPUP | WS_DISABLED, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + nullptr, + nullptr, + instance, + nullptr); + + c_HelperWindow = CreateWindowEx( + WS_EX_TOOLWINDOW, + MAKEINTATOM(className), + L"PositioningHelper", + WS_POPUP | WS_DISABLED, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + nullptr, + nullptr, + instance, + nullptr); + + SetWindowPos(c_Window, HWND_BOTTOM, 0, 0, 0, 0, ZPOS_FLAGS); + SetWindowPos(c_HelperWindow, HWND_BOTTOM, 0, 0, 0, 0, ZPOS_FLAGS); + + c_Monitors.monitors.reserve(4); + SetMultiMonitorInfo(); + + WCHAR directory[MAX_PATH]; + DWORD len = GetCurrentDirectory(MAX_PATH, directory); + c_WorkingDirectory.assign(directory, len <= MAX_PATH ? len : 0); + + c_WinEventHook = SetWinEventHook( + EVENT_SYSTEM_FOREGROUND, + EVENT_SYSTEM_FOREGROUND, + nullptr, + MyWinEventProc, + 0, + 0, + WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); + + SetTimer(c_Window, TIMER_SHOWDESKTOP, INTERVAL_SHOWDESKTOP, nullptr); +} + +/* +** Destroys a window. +** +*/ +void System::Finalize() +{ + KillTimer(c_Window, TIMER_SHOWDESKTOP); + KillTimer(c_Window, TIMER_RESUME); + + if (c_WinEventHook) + { + UnhookWinEvent(c_WinEventHook); + c_WinEventHook = nullptr; + } + + if (c_HelperWindow) + { + DestroyWindow(c_HelperWindow); + c_HelperWindow = nullptr; + } + + if (c_Window) + { + DestroyWindow(c_Window); + c_Window = nullptr; + } +} + +/* +** Retrieves the multi-monitor information. +** +*/ +BOOL CALLBACK MyInfoEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) +{ + MultiMonitorInfo* m = (MultiMonitorInfo*)dwData; + + MONITORINFOEX info; + info.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(hMonitor, &info); + + if (Rainmeter::GetInstance().GetDebug()) + { + LogDebug(info.szDevice); + LogDebugF(L" Flags : %s(0x%08X)", (info.dwFlags & MONITORINFOF_PRIMARY) ? L"PRIMARY " : L"", info.dwFlags); + LogDebugF(L" Handle : 0x%p", hMonitor); + LogDebugF(L" ScrArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", + lprcMonitor->left, lprcMonitor->top, lprcMonitor->right, lprcMonitor->bottom, + lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top); + LogDebugF(L" WorkArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", + info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom, + info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); + } + if (m == nullptr) return TRUE; + + if (m->useEnumDisplayDevices) + { + for (auto iter = m->monitors.begin(); iter != m->monitors.end(); ++iter) + { + if ((*iter).handle == nullptr && _wcsicmp(info.szDevice, (*iter).deviceName.c_str()) == 0) + { + (*iter).handle = hMonitor; + (*iter).screen = *lprcMonitor; + (*iter).work = info.rcWork; + break; + } + } + } + else // use only EnumDisplayMonitors + { + MonitorInfo monitor; + monitor.active = true; + + monitor.handle = hMonitor; + monitor.screen = *lprcMonitor; + monitor.work = info.rcWork; + + monitor.deviceName = info.szDevice; // E.g. "\\.\DISPLAY1" + + // Get the monitor name (E.g. "Generic Non-PnP Monitor") + DISPLAY_DEVICE ddm = {sizeof(DISPLAY_DEVICE)}; + DWORD dwMon = 0; + while (EnumDisplayDevices(info.szDevice, dwMon++, &ddm, 0)) + { + if (ddm.StateFlags & DISPLAY_DEVICE_ACTIVE && ddm.StateFlags & DISPLAY_DEVICE_ATTACHED) + { + monitor.monitorName.assign(ddm.DeviceString, wcsnlen(ddm.DeviceString, _countof(ddm.DeviceString))); + break; + } + } + + m->monitors.push_back(monitor); + + if (info.dwFlags & MONITORINFOF_PRIMARY) + { + // It's primary monitor! + m->primary = (int)m->monitors.size(); + } + } + + return TRUE; +} + +/* +** Returns the number of monitors. +** +*/ +size_t System::GetMonitorCount() +{ + if (c_Monitors.monitors.empty()) + { + SetMultiMonitorInfo(); + } + return c_Monitors.monitors.size(); +} + +/* +** Sets the multi-monitor information. +** +*/ +void System::SetMultiMonitorInfo() +{ + std::vector& monitors = c_Monitors.monitors; + bool logging = Rainmeter::GetInstance().GetDebug(); + + c_Monitors.vsT = GetSystemMetrics(SM_YVIRTUALSCREEN); + c_Monitors.vsL = GetSystemMetrics(SM_XVIRTUALSCREEN); + c_Monitors.vsH = GetSystemMetrics(SM_CYVIRTUALSCREEN); + c_Monitors.vsW = GetSystemMetrics(SM_CXVIRTUALSCREEN); + + c_Monitors.primary = 1; // If primary screen is not found, 1st screen is assumed as primary screen. + + c_Monitors.useEnumDisplayDevices = true; + c_Monitors.useEnumDisplayMonitors = false; + + if (logging) + { + LogDebug(L"------------------------------"); + LogDebug(L"* EnumDisplayDevices / EnumDisplaySettings API"); + } + + DISPLAY_DEVICE dd = {sizeof(DISPLAY_DEVICE)}; + + if (EnumDisplayDevices(nullptr, 0, &dd, 0)) + { + DWORD dwDevice = 0; + + do + { + std::wstring msg; + + std::wstring deviceName(dd.DeviceName, wcsnlen(dd.DeviceName, _countof(dd.DeviceName))); + std::wstring deviceString; + + if (logging) + { + deviceString.assign(dd.DeviceString, wcsnlen(dd.DeviceString, _countof(dd.DeviceString))); + + LogDebug(deviceName.c_str()); + + if (dd.StateFlags & DISPLAY_DEVICE_ACTIVE) + { + msg += L"ACTIVE "; + } + if (dd.StateFlags & DISPLAY_DEVICE_MULTI_DRIVER) + { + msg += L"MULTI "; + } + if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) + { + msg += L"PRIMARY "; + } + if (dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) + { + msg += L"MIRROR "; + } + if (dd.StateFlags & DISPLAY_DEVICE_VGA_COMPATIBLE) + { + msg += L"VGA "; + } + if (dd.StateFlags & DISPLAY_DEVICE_REMOVABLE) + { + msg += L"REMOVABLE "; + } + if (dd.StateFlags & DISPLAY_DEVICE_MODESPRUNED) + { + msg += L"PRUNED "; + } + if (dd.StateFlags & DISPLAY_DEVICE_REMOTE) + { + msg += L"REMOTE "; + } + if (dd.StateFlags & DISPLAY_DEVICE_DISCONNECT) + { + msg += L"DISCONNECT "; + } + } + + if ((dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) == 0) + { + MonitorInfo monitor = {0}; + + monitor.handle = nullptr; + monitor.deviceName = deviceName; // E.g. "\\.\DISPLAY1" + + // Get the monitor name (E.g. "Generic Non-PnP Monitor") + DISPLAY_DEVICE ddm = {sizeof(DISPLAY_DEVICE)}; + DWORD dwMon = 0; + while (EnumDisplayDevices(deviceName.c_str(), dwMon++, &ddm, 0)) + { + if (ddm.StateFlags & DISPLAY_DEVICE_ACTIVE && ddm.StateFlags & DISPLAY_DEVICE_ATTACHED) + { + monitor.monitorName.assign(ddm.DeviceString, wcsnlen(ddm.DeviceString, _countof(ddm.DeviceString))); + + if (logging) + { + LogDebugF(L" Name : %s", monitor.monitorName.c_str()); + } + break; + } + } + + if (logging) + { + LogDebugF(L" Adapter : %s", deviceString.c_str()); + LogDebugF(L" Flags : %s(0x%08X)", msg.c_str(), dd.StateFlags); + } + + if (dd.StateFlags & DISPLAY_DEVICE_ACTIVE) + { + monitor.active = true; + + DEVMODE dm = {0}; + dm.dmSize = sizeof(DEVMODE); + + if (EnumDisplaySettings(deviceName.c_str(), ENUM_CURRENT_SETTINGS, &dm)) + { + POINT pos = {dm.dmPosition.x, dm.dmPosition.y}; + monitor.handle = MonitorFromPoint(pos, MONITOR_DEFAULTTONULL); + + if (logging) + { + LogDebugF(L" Handle : 0x%p", monitor.handle); + } + } + + if (monitor.handle != nullptr) + { + MONITORINFO info = {sizeof(MONITORINFO)}; + GetMonitorInfo(monitor.handle, &info); + + monitor.screen = info.rcMonitor; + monitor.work = info.rcWork; + + if (logging) + { + LogDebugF(L" ScrArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", + info.rcMonitor.left, info.rcMonitor.top, info.rcMonitor.right, info.rcMonitor.bottom, + info.rcMonitor.right - info.rcMonitor.left, info.rcMonitor.bottom - info.rcMonitor.top); + LogDebugF(L" WorkArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", + info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom, + info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); + } + } + else // monitor not found + { + c_Monitors.useEnumDisplayMonitors = true; + } + } + else + { + monitor.active = false; + } + + monitors.push_back(monitor); + + if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) + { + // It's primary monitor! + c_Monitors.primary = (int)monitors.size(); + } + } + else + { + if (logging) + { + LogDebugF(L" Adapter : %s", deviceString.c_str()); + LogDebugF(L" Flags : %s(0x%08X)", msg.c_str(), dd.StateFlags); + } + } + ++dwDevice; + } + while (EnumDisplayDevices(nullptr, dwDevice, &dd, 0)); + } + + if (monitors.empty()) // Failed to enumerate the non-mirroring monitors + { + LogWarning(L"Failed to enumerate the non-mirroring monitors. Only EnumDisplayMonitors is used instead."); + c_Monitors.useEnumDisplayDevices = false; + c_Monitors.useEnumDisplayMonitors = true; + } + + if (logging) + { + LogDebug(L"------------------------------"); + LogDebug(L"* EnumDisplayMonitors API"); + } + + if (c_Monitors.useEnumDisplayMonitors) + { + EnumDisplayMonitors(nullptr, nullptr, MyInfoEnumProc, (LPARAM)(&c_Monitors)); + + if (monitors.empty()) // Failed to enumerate the monitors + { + LogWarning(L"Failed to enumerate monitors. Using dummy monitor info."); + c_Monitors.useEnumDisplayMonitors = false; + + MonitorInfo monitor; + monitor.active = true; + + POINT pos = {0, 0}; + monitor.handle = MonitorFromPoint(pos, MONITOR_DEFAULTTOPRIMARY); + monitor.screen.left = 0; + monitor.screen.top = 0; + monitor.screen.right = GetSystemMetrics(SM_CXSCREEN); + monitor.screen.bottom = GetSystemMetrics(SM_CYSCREEN); + if (SystemParametersInfo(SPI_GETWORKAREA, 0, &(monitor.work), 0) == 0) // failed + { + monitor.work = monitor.screen; + } + + monitor.deviceName = L"DUMMY"; + + monitors.push_back(monitor); + + c_Monitors.primary = 1; + } + } + else + { + if (logging) + { + EnumDisplayMonitors(nullptr, nullptr, MyInfoEnumProc, (LPARAM)nullptr); // Only logging + } + } + + if (logging) + { + LogDebug(L"------------------------------"); + + std::wstring method = L"* METHOD: "; + if (c_Monitors.useEnumDisplayDevices) + { + method += L"EnumDisplayDevices + "; + method += c_Monitors.useEnumDisplayMonitors ? L"EnumDisplayMonitors Mode" : L"EnumDisplaySettings Mode"; + } + else + { + method += c_Monitors.useEnumDisplayMonitors ? L"EnumDisplayMonitors Mode" : L"Dummy Mode"; + } + LogDebug(method.c_str()); + + LogDebugF(L"* MONITORS: Count=%i, Primary=@%i", (int)monitors.size(), c_Monitors.primary); + LogDebug(L"@0: Virtual screen"); + LogDebugF(L" L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", + c_Monitors.vsL, c_Monitors.vsT, c_Monitors.vsL + c_Monitors.vsW, c_Monitors.vsT + c_Monitors.vsH, + c_Monitors.vsW, c_Monitors.vsH); + + int i = 1; + for (auto iter = monitors.cbegin(); iter != monitors.cend(); ++iter, ++i) + { + if ((*iter).active) + { + LogDebugF(L"@%i: %s (active), MonitorName: %s", i, (*iter).deviceName.c_str(), (*iter).monitorName.c_str()); + LogDebugF(L" L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", + (*iter).screen.left, (*iter).screen.top, (*iter).screen.right, (*iter).screen.bottom, + (*iter).screen.right - (*iter).screen.left, (*iter).screen.bottom - (*iter).screen.top); + } + else + { + LogDebugF(L"@%i: %s (inactive), MonitorName: %s", i, (*iter).deviceName.c_str(), (*iter).monitorName.c_str()); + } + } + LogDebug(L"------------------------------"); + } +} + +/* +** Updates the workarea information. +** +*/ +void System::UpdateWorkareaInfo() +{ + std::vector& monitors = c_Monitors.monitors; + + if (monitors.empty()) + { + SetMultiMonitorInfo(); + return; + } + + int i = 1; + for (auto iter = monitors.begin(); iter != monitors.end(); ++iter, ++i) + { + if ((*iter).active && (*iter).handle != nullptr) + { + MONITORINFO info = {sizeof(MONITORINFO)}; + GetMonitorInfo((*iter).handle, &info); + + (*iter).work = info.rcWork; + + if (Rainmeter::GetInstance().GetDebug()) + { + LogDebugF(L"WorkArea@%i : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", + i, + info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom, + info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); + } + } + } +} + +/* +** Finds the Default Shell's window. +** +*/ +HWND System::GetDefaultShellWindow() +{ + static HWND c_ShellW = nullptr; // cache + HWND ShellW = GetShellWindow(); + + if (ShellW) + { + if (ShellW == c_ShellW) + { + return ShellW; + } + else + { + const int classLen = _countof(L"Progman") + 1; + WCHAR className[classLen]; + if (!(GetClassName(ShellW, className, classLen) > 0 && + wcscmp(className, L"Progman") == 0)) + { + ShellW = nullptr; + } + } + } + + c_ShellW = ShellW; + return ShellW; +} + +/* +** Finds the WorkerW window. +** If the WorkerW window is not active, returns nullptr. +** +*/ +HWND System::GetWorkerW() +{ + static HWND c_DefView = nullptr; // cache + HWND ShellW = GetDefaultShellWindow(); + if (!ShellW) return nullptr; // Default Shell (Explorer) not running + + if (c_DefView && IsWindow(c_DefView)) + { + HWND parent = GetAncestor(c_DefView, GA_PARENT); + if (parent) + { + if (parent == ShellW) + { + return nullptr; + } + else + { + const int classLen = _countof(L"WorkerW") + 1; + WCHAR className[classLen]; + if (GetClassName(parent, className, classLen) > 0 && + wcscmp(className, L"WorkerW") == 0) + { + return parent; + } + } + } + } + + HWND WorkerW = nullptr, DefView = FindWindowEx(ShellW, nullptr, L"SHELLDLL_DefView", L""); + if (DefView == nullptr) + { + while (WorkerW = FindWindowEx(nullptr, WorkerW, L"WorkerW", L"")) + { + if (IsWindowVisible(WorkerW) && + BelongToSameProcess(ShellW, WorkerW) && + (DefView = FindWindowEx(WorkerW, nullptr, L"SHELLDLL_DefView", L""))) + { + break; + } + } + } + + c_DefView = DefView; + return WorkerW; +} + +/* +** Returns the first window whose position is not ZPOSITION_ONDESKTOP, +** ZPOSITION_BOTTOM, or ZPOSITION_NORMAL. +** +*/ +HWND System::GetBackmostTopWindow() +{ + HWND winPos = c_HelperWindow; + + // Skip all ZPOSITION_ONDESKTOP, ZPOSITION_BOTTOM, and ZPOSITION_NORMAL windows + while (winPos = ::GetNextWindow(winPos, GW_HWNDPREV)) + { + MeterWindow* wnd = Rainmeter::GetInstance().GetMeterWindow(winPos); + if (!wnd || + (wnd->GetWindowZPosition() != ZPOSITION_NORMAL && + wnd->GetWindowZPosition() != ZPOSITION_ONDESKTOP && + wnd->GetWindowZPosition() != ZPOSITION_ONBOTTOM)) + { + break; + } + } + + return winPos; +} + +/* +** Checks whether the given windows belong to the same process. +** +*/ +bool System::BelongToSameProcess(HWND hwndA, HWND hwndB) +{ + DWORD procAId = 0, procBId = 0; + + GetWindowThreadProcessId(hwndA, &procAId); + GetWindowThreadProcessId(hwndB, &procBId); + + return (procAId == procBId); +} + +/* +** Retrieves the Rainmeter's meter windows in Z-order. +** +*/ +BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM lParam) +{ + bool logging = Rainmeter::GetInstance().GetDebug() && DEBUG_VERBOSE; + const int classLen = _countof(METERWINDOW_CLASS_NAME) + (DEBUG_VERBOSE ? 32 : 1); + WCHAR className[classLen]; + MeterWindow* Window; + WCHAR flag; + + if (GetClassName(hwnd, className, classLen) > 0 && + wcscmp(className, METERWINDOW_CLASS_NAME) == 0 && + (Window = Rainmeter::GetInstance().GetMeterWindow(hwnd))) + { + ZPOSITION zPos = Window->GetWindowZPosition(); + if (zPos == ZPOSITION_ONDESKTOP || + (zPos == ZPOSITION_NORMAL && Rainmeter::GetInstance().IsNormalStayDesktop()) || + zPos == ZPOSITION_ONBOTTOM) + { + if (lParam) + { + ((std::vector*)lParam)->push_back(Window); + } + + if (logging) flag = L'+'; + } + else + { + if (logging) flag = L'-'; + } + + if (logging) + { + LogDebugF(L"%c [%c] 0x%p : %s (Name: \"%s\", zPos=%i)", + flag, IsWindowVisible(hwnd) ? L'V' : L'H', hwnd, className, Window->GetFolderPath().c_str(), (int)zPos); + } + } + else + { + if (logging) + { + flag = (hwnd == System::GetHelperWindow()) ? L'o' : ' '; + LogDebugF(L"%c [%c] 0x%p : %s", flag, IsWindowVisible(hwnd) ? L'V' : L'H', hwnd, className); + } + } + + return TRUE; +} + +/* +** Arranges the meter window in Z-order. +** +*/ +void System::ChangeZPosInOrder() +{ + bool logging = Rainmeter::GetInstance().GetDebug() && DEBUG_VERBOSE; + std::vector windowsInZOrder; + + if (logging) LogDebug(L"1: ----- BEFORE -----"); + + // Retrieve the Rainmeter's meter windows in Z-order + EnumWindows(MyEnumWindowsProc, (LPARAM)(&windowsInZOrder)); + + auto resetZPos = [&](ZPOSITION zpos) + { + // Reset ZPos in Z-order (Bottom) + std::vector::const_iterator iter = windowsInZOrder.begin(); + for ( ; iter != windowsInZOrder.end(); ++iter) + { + if ((*iter)->GetWindowZPosition() == zpos) + { + (*iter)->ChangeZPos(zpos); // reset + } + } + }; + + if (Rainmeter::GetInstance().IsNormalStayDesktop()) + { + resetZPos(ZPOSITION_NORMAL); + } + + if (!c_ShowDesktop) + { + resetZPos(ZPOSITION_ONBOTTOM); + } + + resetZPos(ZPOSITION_ONDESKTOP); + + if (logging) + { + LogDebug(L"2: ----- AFTER -----"); + + // Log all windows in Z-order + EnumWindows(MyEnumWindowsProc, (LPARAM)nullptr); + } +} + +/* +** Moves the helper window to the reference position. +** +*/ +void System::PrepareHelperWindow(HWND WorkerW) +{ + bool logging = Rainmeter::GetInstance().GetDebug() && DEBUG_VERBOSE; + + SetWindowPos(c_Window, HWND_BOTTOM, 0, 0, 0, 0, ZPOS_FLAGS); // always on bottom + + if (c_ShowDesktop && WorkerW) + { + // Set WS_EX_TOPMOST flag + SetWindowPos(c_HelperWindow, HWND_TOPMOST, 0, 0, 0, 0, ZPOS_FLAGS); + + // Find the "backmost" topmost window + HWND hwnd = WorkerW; + while (hwnd = ::GetNextWindow(hwnd, GW_HWNDPREV)) + { + if (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) + { + WCHAR className[64], windowText[64]; + + if (logging) + { + GetClassName(hwnd, className, 64); + GetWindowText(hwnd, windowText, 64); + + SetLastError(ERROR_SUCCESS); + } + + // Insert the helper window after the found window + if (0 != SetWindowPos(c_HelperWindow, hwnd, 0, 0, 0, 0, ZPOS_FLAGS)) + { + if (logging) + { + LogDebugF(L"System: HelperWindow: hwnd=0x%p (WorkerW=0x%p), hwndInsertAfter=0x%p (\"%s\" %s) - %s", + c_HelperWindow, WorkerW, hwnd, windowText, className, (GetWindowLongPtr(c_HelperWindow, GWL_EXSTYLE) & WS_EX_TOPMOST) ? L"TOPMOST" : L"NORMAL"); + } + return; + } + + if (logging) + { + DWORD err = GetLastError(); + LogDebugF(L"System: HelperWindow: hwnd=0x%p (WorkerW=0x%p), hwndInsertAfter=0x%p (\"%s\" %s) - FAILED (ErrorCode=0x%08X)", + c_HelperWindow, WorkerW, hwnd, windowText, className, err); + } + } + } + + if (logging) + { + LogDebugF(L"System: HelperWindow: hwnd=0x%p (WorkerW=0x%p), hwndInsertAfter=HWND_TOPMOST - %s", + c_HelperWindow, WorkerW, (GetWindowLongPtr(c_HelperWindow, GWL_EXSTYLE) & WS_EX_TOPMOST) ? L"TOPMOST" : L"NORMAL"); + } + } + else + { + // Insert the helper window to the bottom + SetWindowPos(c_HelperWindow, HWND_BOTTOM, 0, 0, 0, 0, ZPOS_FLAGS); + + if (logging) + { + LogDebugF(L"System: HelperWindow: hwnd=0x%p (WorkerW=0x%p), hwndInsertAfter=HWND_BOTTOM - %s", + c_HelperWindow, WorkerW, (GetWindowLongPtr(c_HelperWindow, GWL_EXSTYLE) & WS_EX_TOPMOST) ? L"TOPMOST" : L"NORMAL"); + } + } +} + +/* +** Changes the "Show Desktop" state. +** +*/ +bool System::CheckDesktopState(HWND WorkerW) +{ + HWND hwnd = nullptr; + + if (WorkerW && IsWindowVisible(WorkerW)) + { + hwnd = FindWindowEx(nullptr, WorkerW, L"RainmeterSystem", L"System"); + } + + bool stateChanged = (hwnd && !c_ShowDesktop) || (!hwnd && c_ShowDesktop); + + if (stateChanged) + { + c_ShowDesktop = !c_ShowDesktop; + + if (Rainmeter::GetInstance().GetDebug()) + { + LogDebugF(L"System: \"Show %s\" has been detected.", + c_ShowDesktop ? L"desktop" : L"open windows"); + } + + PrepareHelperWindow(WorkerW); + + ChangeZPosInOrder(); + + if (c_ShowDesktop) + { + SetTimer(c_Window, TIMER_SHOWDESKTOP, INTERVAL_RESTOREWINDOWS, nullptr); + } + else + { + SetTimer(c_Window, TIMER_SHOWDESKTOP, INTERVAL_SHOWDESKTOP, nullptr); + } + } + + return stateChanged; +} + +/* +** The event hook procedure +** +*/ +void CALLBACK System::MyWinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime) +{ + if (event == EVENT_SYSTEM_FOREGROUND) + { + if (!c_ShowDesktop) + { + const int classLen = _countof(L"WorkerW") + 1; + WCHAR className[classLen]; + if (GetClassName(hwnd, className, classLen) > 0 && + wcscmp(className, L"WorkerW") == 0 && + BelongToSameProcess(GetDefaultShellWindow(), hwnd)) + { + const int max = 5; + int loop = 0; + while (loop < max && FindWindowEx(hwnd, nullptr, L"SHELLDLL_DefView", L"") == nullptr) + { + Sleep(2); // Wait for 2-16 ms before retrying + ++loop; + } + + if (loop < max) + { + loop = 0; + while (loop < max && !CheckDesktopState(hwnd)) + { + Sleep(2); // Wait for 2-16 ms before retrying + ++loop; + } + } + } + } + } +} + +/* +** The window procedure +** +*/ +LRESULT CALLBACK System::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (hWnd != c_Window) + { + if (uMsg == WM_WINDOWPOSCHANGING) + { + ((LPWINDOWPOS)lParam)->flags |= SWP_NOZORDER; + return 0; + } + return DefWindowProc(hWnd, uMsg, wParam, lParam); + } + + switch (uMsg) + { + case WM_WINDOWPOSCHANGING: + ((LPWINDOWPOS)lParam)->flags |= SWP_NOZORDER; + break; + + case WM_TIMER: + switch (wParam) + { + case TIMER_SHOWDESKTOP: + if (wParam == TIMER_SHOWDESKTOP) + { + CheckDesktopState(GetWorkerW()); + } + break; + + case TIMER_RESUME: + KillTimer(hWnd, TIMER_RESUME); + if (Rainmeter::GetInstance().IsRedrawable()) + { + std::map::const_iterator iter = Rainmeter::GetInstance().GetAllMeterWindows().begin(); + for ( ; iter != Rainmeter::GetInstance().GetAllMeterWindows().end(); ++iter) + { + (*iter).second->RedrawWindow(); + } + } + break; + } + break; + + case WM_DISPLAYCHANGE: + LogNotice(L"System: Display settings changed"); + ClearMultiMonitorInfo(); + ConfigParser::ClearMultiMonitorVariables(); + case WM_SETTINGCHANGE: + if (uMsg == WM_DISPLAYCHANGE || (/*uMsg == WM_SETTINGCHANGE &&*/ wParam == SPI_SETWORKAREA)) + { + if (uMsg == WM_SETTINGCHANGE) // SPI_SETWORKAREA + { + LogNotice(L"System: Work area changed"); + UpdateWorkareaInfo(); + ConfigParser::UpdateWorkareaVariables(); + } + + // Deliver WM_DISPLAYCHANGE / WM_SETTINGCHANGE message to all meter windows + std::map::const_iterator iter = Rainmeter::GetInstance().GetAllMeterWindows().begin(); + for ( ; iter != Rainmeter::GetInstance().GetAllMeterWindows().end(); ++iter) + { + PostMessage((*iter).second->GetWindow(), WM_METERWINDOW_DELAYED_MOVE, (WPARAM)uMsg, (LPARAM)0); + } + } + break; + + case WM_POWERBROADCAST: + if (wParam == PBT_APMRESUMESUSPEND) + { + // Deliver PBT_APMRESUMESUSPEND event to all meter windows + SetTimer(hWnd, TIMER_RESUME, INTERVAL_RESUME, nullptr); + } + return TRUE; + + default: + return DefWindowProc(hWnd, uMsg, wParam, lParam); + } + + return 0; +} + +/* +** Retrieves the number of milliseconds that have elapsed since the system was started. +** In XP, returns the predictive value due to the 32bit limitation. +** +*/ +ULONGLONG System::GetTickCount64() +{ + static auto s_GetTickCount64 = + (decltype(GetTickCount64)*)GetProcAddress(GetModuleHandle(L"kernel32"), "GetTickCount64"); + + if (s_GetTickCount64) + { + return s_GetTickCount64(); + } + else + { + static ULONGLONG lastTicks = 0; + ULONGLONG ticks = GetTickCount(); + while (ticks < lastTicks) ticks += 0x100000000; + lastTicks = ticks; + return ticks; + } +} + +/* +** Gets the cursor position in last message retrieved by GetMessage(). +** +*/ +POINT System::GetCursorPosition() +{ + DWORD pos = GetMessagePos(); + POINT pt = { GET_X_LPARAM(pos), GET_Y_LPARAM(pos) }; + return pt; +} + +/* +** Checks if file is writable. +** +*/ +bool System::IsFileWritable(LPCWSTR file) +{ + HANDLE hFile = CreateFile(file, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); + if (hFile == INVALID_HANDLE_VALUE) + { + return false; + } + + CloseHandle(hFile); + return true; +} + +/* +** This function is a wrapper function for LoadLibrary(). +** +** Avoids loading a DLL from current directory. +** +*/ +HMODULE System::RmLoadLibrary(LPCWSTR lpLibFileName, DWORD* dwError) +{ + // Remove current directory from DLL search path + SetDllDirectory(L""); + + SetLastError(ERROR_SUCCESS); + HMODULE hLib = LoadLibrary(lpLibFileName); + + if (dwError) + { + *dwError = GetLastError(); + } + + return hLib; +} + +/* +** Resets working directory to default. +** +*/ +void System::ResetWorkingDirectory() +{ + WCHAR directory[MAX_PATH] = {0}; + GetCurrentDirectory(MAX_PATH, directory); + + const WCHAR* workDir = c_WorkingDirectory.c_str(); + if (_wcsicmp(directory, workDir) != 0) + { + SetCurrentDirectory(workDir); + } +} + +/* +** Initializes a critical section object by using InitializeCriticalSectionEx function with CRITICAL_SECTION_NO_DEBUG_INFO flag. +** For more details: http://stackoverflow.com/questions/804848/critical-sections-leaking-memory-on-vista-win2008/ +** +*/ +void System::InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) +{ + static auto s_InitializeCriticalSectionEx = IsWindowsVistaOrGreater() ? + (decltype(InitializeCriticalSectionEx)*)GetProcAddress(GetModuleHandle(L"kernel32"), "InitializeCriticalSectionEx") : nullptr; + + if (s_InitializeCriticalSectionEx && + s_InitializeCriticalSectionEx(lpCriticalSection, 0, CRITICAL_SECTION_NO_DEBUG_INFO)) + { + return; + } + + InitializeCriticalSectionAndSpinCount(lpCriticalSection, 0); +} + +/* +** Sets clipboard text to given string. +** +*/ +void System::SetClipboardText(const std::wstring& text) +{ + if (OpenClipboard(nullptr)) + { + // Include terminating null char + size_t len = text.length() + 1; + + HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len * sizeof(WCHAR)); + if (hMem) + { + LPVOID data = GlobalLock(hMem); + memcpy(data, text.c_str(), len * sizeof(WCHAR)); + GlobalUnlock(hMem); + + EmptyClipboard(); + if (!SetClipboardData(CF_UNICODETEXT, hMem)) + { + GlobalFree(hMem); + } + } + + CloseClipboard(); + } +} + +/* +** Sets the system wallpapar. +** +*/ +void System::SetWallpaper(const std::wstring& wallpaper, const std::wstring& style) +{ + if (!wallpaper.empty()) + { + if (_waccess(wallpaper.c_str(), 0) == -1) + { + LogErrorF(L"!SetWallpaper: Unable to read file: %s", wallpaper.c_str()); + return; + } + + Bitmap bitmap(wallpaper.c_str()); + if (bitmap.GetLastStatus() == Ok) + { + std::wstring file = Rainmeter::GetInstance().GetSettingsPath() + L"Wallpaper.bmp"; + + const CLSID bmpClsid = { 0x557cf400, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } }; + if (bitmap.Save(file.c_str(), &bmpClsid) == Ok) + { + if (!style.empty()) + { + HKEY hKey; + if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Control Panel\\Desktop", 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) + { + const WCHAR* wallStyle = nullptr; + const WCHAR* wallTile = L"0"; + + const WCHAR* option = style.c_str(); + if (_wcsicmp(option, L"CENTER") == 0) + { + wallStyle = L"0"; + } + else if (_wcsicmp(option, L"TILE") == 0) + { + wallStyle = L"0"; + wallTile = L"1"; + } + else if (_wcsicmp(option, L"STRETCH") == 0) + { + wallStyle = L"2"; + } + else if (IsWindows7OrGreater()) + { + if (_wcsicmp(option, L"FIT") == 0) + { + wallStyle = L"6"; + } + else if (_wcsicmp(option, L"FILL") == 0) + { + wallStyle = L"10"; + } + } + + if (wallStyle) + { + RegSetValueEx(hKey, L"WallpaperStyle", 0, REG_SZ, (const BYTE*)wallStyle, sizeof(WCHAR) * 2); + RegSetValueEx(hKey, L"TileWallpaper", 0, REG_SZ, (const BYTE*)wallTile, sizeof(WCHAR) * 2); + } + else + { + LogError(L"!SetWallpaper: Invalid style"); + } + + RegCloseKey(hKey); + } + } + + SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)file.c_str(), SPIF_UPDATEINIFILE); + } + } + } +} + +/* +** Copies files and folders from one location to another. +** +*/ +bool System::CopyFiles(std::wstring from, std::wstring to, bool bMove) +{ + // If given "from" path ends with path separator, remove it (Workaround for XP: error code 1026) + size_t len; + while (len = from.size(), len > 0 && PathUtil::IsSeparator(from[len - 1])) + { + from.resize(len - 1); + } + + // The strings must end with double \0 + from.append(1, L'\0'); + to.append(1, L'\0'); + + SHFILEOPSTRUCT fo = + { + nullptr, + bMove ? FO_MOVE : FO_COPY, + from.c_str(), + to.c_str(), + FOF_NO_UI | FOF_NOCONFIRMATION | FOF_ALLOWUNDO + }; + + int result = SHFileOperation(&fo); + if (result != 0) + { + LogErrorF(L"Copy error: From %s to %s (%i)", from.c_str(), to.c_str(), result); + return false; + } + return true; +} + +/* +** Removes a file even if a file is read-only. +** +*/ +bool System::RemoveFile(const std::wstring& file) +{ + DWORD attr = GetFileAttributes(file.c_str()); + if (attr == -1 || (attr & FILE_ATTRIBUTE_READONLY)) + { + // Unset read-only + SetFileAttributes(file.c_str(), (attr == -1) ? FILE_ATTRIBUTE_NORMAL : attr - FILE_ATTRIBUTE_READONLY); + } + + return (DeleteFile(file.c_str()) != 0); +} + +/* +** Recursively removes folder. +** +*/ +bool System::RemoveFolder(std::wstring folder) +{ + // The strings must end with double nul + folder.append(1, L'\0'); + + SHFILEOPSTRUCT fo = + { + nullptr, + FO_DELETE, + folder.c_str(), + nullptr, + FOF_NO_UI | FOF_NOCONFIRMATION | FOF_ALLOWUNDO + }; + + int result = SHFileOperation(&fo); + if (result != 0) + { + LogErrorF(L"Unable to delete folder %s (%i)", folder.c_str(), result); + return false; + } + return true; +} + +/* +** Retrieves the "IniFileMapping" entries from Registry. +** +*/ +void System::UpdateIniFileMappingList() +{ + static ULONGLONG s_LastWriteTime = 0; + + HKEY hKey; + LONG ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping", 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey); + if (ret == ERROR_SUCCESS) + { + DWORD numSubKeys; + ULONGLONG ftLastWriteTime; + bool changed = false; + + ret = RegQueryInfoKey(hKey, nullptr, nullptr, nullptr, &numSubKeys, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, (LPFILETIME)&ftLastWriteTime); + if (ret == ERROR_SUCCESS) + { + //LogDebugF(L"IniFileMapping: numSubKeys=%u, ftLastWriteTime=%llu", numSubKeys, ftLastWriteTime); + + if (ftLastWriteTime != s_LastWriteTime || + numSubKeys != c_IniFileMappings.size()) + { + s_LastWriteTime = ftLastWriteTime; + if (numSubKeys > c_IniFileMappings.capacity()) + { + c_IniFileMappings.reserve(numSubKeys); + } + changed = true; + } + } + else + { + s_LastWriteTime = 0; + changed = true; + } + + if (changed) + { + if (!c_IniFileMappings.empty()) + { + c_IniFileMappings.clear(); + } + + WCHAR* buffer = new WCHAR[MAX_PATH]; + DWORD index = 0, cch = MAX_PATH; + + while ((ret = RegEnumKeyEx(hKey, index++, buffer, &cch, nullptr, nullptr, nullptr, nullptr)) != ERROR_NO_MORE_ITEMS) + { + if (ret == ERROR_SUCCESS) + { + c_IniFileMappings.push_back(buffer); + } + cch = MAX_PATH; + } + + delete [] buffer; + } + + RegCloseKey(hKey); + } +} + +/* +** Prepares a temporary file if iniFile is included in the "IniFileMapping" entries. +** If iniFile is not included, returns a empty string. If error occurred, returns "?". +** Note that a temporary file must be deleted by caller. +** +*/ +std::wstring System::GetTemporaryFile(const std::wstring& iniFile) +{ + std::wstring temporary; + + if (!c_IniFileMappings.empty()) + { + std::wstring::size_type pos = iniFile.find_last_of(L"\\/"); + const WCHAR* filename = iniFile.c_str() + ((pos != std::wstring::npos) ? pos + 1 : 0); + + std::vector::const_iterator iter = c_IniFileMappings.begin(); + for ( ; iter != c_IniFileMappings.end(); ++iter) + { + if (_wcsicmp((*iter).c_str(), filename) == 0) + { + WCHAR* buffer = new WCHAR[MAX_PATH]; + + if (GetTempPath(MAX_PATH, buffer) != 0 && + GetTempFileName(buffer, L"cfg", 0, buffer) != 0) + { + temporary = buffer; + + std::wstring tmp = GetTemporaryFile(temporary); + if (!tmp.empty() || !CopyFiles(iniFile, temporary)) // temporary is reserved or failed + { + RemoveFile(temporary); + + if (tmp.empty()) + { + temporary = L"?"; + } + else + { + temporary.swap(tmp); + } + } + } + else // failed + { + LogErrorF(L"Unable to create temporary file to: %s", temporary.c_str()); + temporary = L"?"; + } + + delete [] buffer; + break; + } + } + } + + return temporary; +} diff --git a/Library/System.h b/Library/System.h index 0c84bd61..876fa569 100644 --- a/Library/System.h +++ b/Library/System.h @@ -1,113 +1,113 @@ -/* - Copyright (C) 2010 spx - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __RAINMETER_SYSTEM_H__ -#define __RAINMETER_SYSTEM_H__ - -#include -#include - -struct MonitorInfo -{ - bool active; - HMONITOR handle; - RECT screen; - RECT work; - std::wstring deviceName; // Device name (E.g. "\\.\DISPLAY1") - std::wstring monitorName; // Monitor name (E.g. "Generic Non-PnP Monitor") -}; - -struct MultiMonitorInfo -{ - bool useEnumDisplayDevices; // If true, use EnumDisplayDevices function to obtain the multi-monitor information - bool useEnumDisplayMonitors; // If true, use EnumDisplayMonitors function to obtain the multi-monitor information - - int vsT, vsL, vsH, vsW; // Coordinates of the top-left corner (vsT,vsL) and size (vsH,vsW) of the virtual screen - int primary; // Index of the primary monitor - std::vector monitors; -}; - -class System -{ -public: - System(const System& other) = delete; - System& operator=(System other) = delete; - - static void Initialize(HINSTANCE instance); - static void Finalize(); - - static const MultiMonitorInfo& GetMultiMonitorInfo() { return c_Monitors; } - static size_t GetMonitorCount(); - - static bool GetShowDesktop() { return c_ShowDesktop; } - - static HWND GetWindow() { return c_Window; } - static HWND GetBackmostTopWindow(); - - static HWND GetHelperWindow() { return c_HelperWindow; } - static void PrepareHelperWindow(HWND WorkerW = GetWorkerW()); - - static ULONGLONG GetTickCount64(); - static POINT GetCursorPosition(); - - static bool IsFileWritable(LPCWSTR file); - - static HMODULE RmLoadLibrary(LPCWSTR lpLibFileName, DWORD* dwError = nullptr); - static void ResetWorkingDirectory(); - static void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); - - static void SetClipboardText(const std::wstring& text); - static void SetWallpaper(const std::wstring& wallpaper, const std::wstring& style); - - static bool CopyFiles(std::wstring from, std::wstring to, bool bMove = false); - static bool RemoveFile(const std::wstring& file); - static bool RemoveFolder(std::wstring folder); - - static void UpdateIniFileMappingList(); - static std::wstring GetTemporaryFile(const std::wstring& iniFile); - -private: - static void CALLBACK MyWinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime); - static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - - static void SetMultiMonitorInfo(); - static void ClearMultiMonitorInfo() { c_Monitors.monitors.clear(); } - static void UpdateWorkareaInfo(); - - static HWND GetDefaultShellWindow(); - static HWND GetWorkerW(); - static void ChangeZPosInOrder(); - - static bool CheckDesktopState(HWND WorkerW); - static bool BelongToSameProcess(HWND hwndA, HWND hwndB); - - static HWND c_Window; - static HWND c_HelperWindow; - - static HWINEVENTHOOK c_WinEventHook; - - static MultiMonitorInfo c_Monitors; - - static bool c_ShowDesktop; - - static std::wstring c_WorkingDirectory; - - static std::vector c_IniFileMappings; -}; - -#endif +/* + Copyright (C) 2010 spx + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __RAINMETER_SYSTEM_H__ +#define __RAINMETER_SYSTEM_H__ + +#include +#include + +struct MonitorInfo +{ + bool active; + HMONITOR handle; + RECT screen; + RECT work; + std::wstring deviceName; // Device name (E.g. "\\.\DISPLAY1") + std::wstring monitorName; // Monitor name (E.g. "Generic Non-PnP Monitor") +}; + +struct MultiMonitorInfo +{ + bool useEnumDisplayDevices; // If true, use EnumDisplayDevices function to obtain the multi-monitor information + bool useEnumDisplayMonitors; // If true, use EnumDisplayMonitors function to obtain the multi-monitor information + + int vsT, vsL, vsH, vsW; // Coordinates of the top-left corner (vsT,vsL) and size (vsH,vsW) of the virtual screen + int primary; // Index of the primary monitor + std::vector monitors; +}; + +class System +{ +public: + System(const System& other) = delete; + System& operator=(System other) = delete; + + static void Initialize(HINSTANCE instance); + static void Finalize(); + + static const MultiMonitorInfo& GetMultiMonitorInfo() { return c_Monitors; } + static size_t GetMonitorCount(); + + static bool GetShowDesktop() { return c_ShowDesktop; } + + static HWND GetWindow() { return c_Window; } + static HWND GetBackmostTopWindow(); + + static HWND GetHelperWindow() { return c_HelperWindow; } + static void PrepareHelperWindow(HWND WorkerW = GetWorkerW()); + + static ULONGLONG GetTickCount64(); + static POINT GetCursorPosition(); + + static bool IsFileWritable(LPCWSTR file); + + static HMODULE RmLoadLibrary(LPCWSTR lpLibFileName, DWORD* dwError = nullptr); + static void ResetWorkingDirectory(); + static void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); + + static void SetClipboardText(const std::wstring& text); + static void SetWallpaper(const std::wstring& wallpaper, const std::wstring& style); + + static bool CopyFiles(std::wstring from, std::wstring to, bool bMove = false); + static bool RemoveFile(const std::wstring& file); + static bool RemoveFolder(std::wstring folder); + + static void UpdateIniFileMappingList(); + static std::wstring GetTemporaryFile(const std::wstring& iniFile); + +private: + static void CALLBACK MyWinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime); + static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + static void SetMultiMonitorInfo(); + static void ClearMultiMonitorInfo() { c_Monitors.monitors.clear(); } + static void UpdateWorkareaInfo(); + + static HWND GetDefaultShellWindow(); + static HWND GetWorkerW(); + static void ChangeZPosInOrder(); + + static bool CheckDesktopState(HWND WorkerW); + static bool BelongToSameProcess(HWND hwndA, HWND hwndB); + + static HWND c_Window; + static HWND c_HelperWindow; + + static HWINEVENTHOOK c_WinEventHook; + + static MultiMonitorInfo c_Monitors; + + static bool c_ShowDesktop; + + static std::wstring c_WorkingDirectory; + + static std::vector c_IniFileMappings; +}; + +#endif diff --git a/Library/TintedImage.cpp b/Library/TintedImage.cpp index d1acc7bb..ac68481e 100644 --- a/Library/TintedImage.cpp +++ b/Library/TintedImage.cpp @@ -1,819 +1,819 @@ -/* - Copyright (C) 2010 Kimmo Pekkola, Matt King, spx - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../Common/PathUtil.h" -#include "TintedImage.h" -#include "ConfigParser.h" -#include "System.h" -#include "Error.h" -#include "Logger.h" - -using namespace Gdiplus; - - -class ImageCachePool -{ -public: - static std::wstring CreateKey(const std::wstring& name, ULONGLONG time, DWORD size, WCHAR* exifOrientation) - { - std::wstring key; - - WCHAR buffer[MAX_PATH]; - if (PathCanonicalize(buffer, name.c_str())) - { - key = buffer; - } - else - { - key = name; - } - _wcsupr(&key[0]); - - size_t len = _snwprintf_s(buffer, _TRUNCATE, L":%llx:%x:%s", time, size, exifOrientation); - key.append(buffer, len); - - return key; - } - - static Bitmap* GetCache(const std::wstring& key) - { - std::unordered_map::const_iterator iter = c_CacheMap.find(key); - if (iter != c_CacheMap.end()) - { - return (*iter).second->GetCache(); - } - return nullptr; - } - - static void AddCache(const std::wstring& key, Bitmap* bitmap, HGLOBAL hBuffer) - { - std::unordered_map::const_iterator iter = c_CacheMap.find(key); - if (iter != c_CacheMap.end()) - { - (*iter).second->AddRef(); - //LogDebugF(L"* ADD: key=%s, ref=%i", key.c_str(), (*iter).second->GetRef()); - } - else - { - c_CacheMap[key] = new ImageCache(bitmap, hBuffer); - //LogDebugF(L"* ADD: key=%s, ref=new", key.c_str()); - } - } - - static void RemoveCache(const std::wstring& key) - { - std::unordered_map::const_iterator iter = c_CacheMap.find(key); - if (iter != c_CacheMap.end()) - { - ImageCache* cache = (*iter).second; - cache->Release(); - //LogDebugF(L"* REMOVE: key=%s, ref=%i", key.c_str(), cache->GetRef()); - - if (cache->IsInvalid()) - { - //LogDebugF(L"* EMPTY-ERASE: key=%s", key.c_str()); - c_CacheMap.erase(iter); - delete cache; - } - } - } - -private: - class ImageCache - { - public: - ImageCache(Bitmap* bitmap, HGLOBAL hBuffer) : m_Bitmap(bitmap), m_hBuffer(hBuffer), m_Ref(1) {} - ~ImageCache() { Dispose(); } - - void AddRef() { ++m_Ref; } - void Release() { if (m_Ref > 0) { --m_Ref; } if (m_Ref == 0) { Dispose(); } } - - bool IsInvalid() { return m_Ref == 0; } - //int GetRef() { return m_Ref; } - Bitmap* GetCache() { return m_Bitmap; } - - private: - ImageCache() {} - ImageCache(const ImageCache& cache) {} - - void Dispose() { delete m_Bitmap; m_Bitmap = nullptr; if (m_hBuffer) { ::GlobalFree(m_hBuffer); m_hBuffer = nullptr; } } - - Bitmap* m_Bitmap; - HGLOBAL m_hBuffer; - int m_Ref; - }; - - static std::unordered_map c_CacheMap; -}; -std::unordered_map ImageCachePool::c_CacheMap; - - -#define PI (3.14159265f) -#define CONVERT_TO_RADIANS(X) ((X) * (PI / 180.0f)) - -// GrayScale Matrix -const Gdiplus::ColorMatrix TintedImage::c_GreyScaleMatrix = { - 0.299f, 0.299f, 0.299f, 0.0f, 0.0f, - 0.587f, 0.587f, 0.587f, 0.0f, 0.0f, - 0.114f, 0.114f, 0.114f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 1.0f -}; - -const Gdiplus::ColorMatrix TintedImage::c_IdentityMatrix = { - 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 1.0f -}; - -TintedImageHelper_DefineOptionArray(TintedImage::c_DefaultOptionArray, L""); - -/* -** The constructor. -** -** If disableTransform is true, ImageCrop and ImageRotate are ignored. -** -*/ -TintedImage::TintedImage(const WCHAR* name, const WCHAR** optionArray, bool disableTransform, MeterWindow* meterWindow) : m_DisableTransform(disableTransform), - m_Name(name ? name : L"ImageName"), - m_OptionArray(optionArray ? optionArray : c_DefaultOptionArray), - m_Bitmap(), - m_BitmapTint(), - m_NeedsCrop(false), - m_NeedsTinting(false), - m_NeedsTransform(false), - m_Crop(-1, -1, -1, -1), - m_CropMode(CROPMODE_TL), - m_GreyScale(false), - m_ColorMatrix(new ColorMatrix(c_IdentityMatrix)), - m_Flip(RotateNoneFlipNone), - m_Rotate(), - m_UseExifOrientation(false), - m_MeterWindow(meterWindow), - m_HasPathChanged(false) -{ -} - -/* -** The destructor -** -*/ -TintedImage::~TintedImage() -{ - DisposeImage(); - - delete m_ColorMatrix; -} - -/* -** Disposes the image buffers. -** -*/ -void TintedImage::DisposeImage() -{ - delete m_BitmapTint; - m_BitmapTint = nullptr; - - m_Bitmap = nullptr; - - if (!m_CacheKey.empty()) - { - ImageCachePool::RemoveCache(m_CacheKey); - m_CacheKey.clear(); - } -} - -/* -** Loads the image from file handle -** -*/ -Bitmap* TintedImage::LoadImageFromFileHandle(HANDLE fileHandle, DWORD fileSize, HGLOBAL* phBuffer) -{ - HGLOBAL hBuffer = ::GlobalAlloc(GMEM_MOVEABLE, fileSize); - if (hBuffer) - { - void* pBuffer = ::GlobalLock(hBuffer); - if (pBuffer) - { - DWORD readBytes; - ReadFile(fileHandle, pBuffer, fileSize, &readBytes, nullptr); - ::GlobalUnlock(hBuffer); - - IStream* pStream = nullptr; - if (::CreateStreamOnHGlobal(hBuffer, FALSE, &pStream) == S_OK) - { - Bitmap* bitmap = Bitmap::FromStream(pStream); - pStream->Release(); - - if (Ok == bitmap->GetLastStatus()) - { - GUID guid; - if (Ok == bitmap->GetRawFormat(&guid) && guid != ImageFormatIcon) - { - // Gather EXIF orientation information - if (m_UseExifOrientation) - { - UINT size = bitmap->GetPropertyItemSize(PropertyTagOrientation); - if (size) - { - RotateFlipType flip = RotateNoneFlipNone; - PropertyItem* orientation = (PropertyItem*)new BYTE[size]; - bitmap->GetPropertyItem(PropertyTagOrientation, size, orientation); - if (orientation) - { - switch(*(short*)orientation->value) - { - case 8: - flip = Rotate270FlipNone; - break; - - case 7: - flip = Rotate270FlipX; - break; - - case 6: - flip = Rotate90FlipNone; - break; - - case 5: - flip = Rotate90FlipX; - break; - - case 4: - flip = Rotate180FlipX; - break; - - case 3: - flip = Rotate180FlipNone; - break; - - case 2: - flip = RotateNoneFlipX; - break; - - default: - flip = RotateNoneFlipNone; - } - - bitmap->RotateFlip(flip); - } - delete [] orientation; - } - } - - //////////////////////////////////////////// - // Convert loaded image to faster blittable bitmap (may increase memory usage slightly) - Rect r(0, 0, bitmap->GetWidth(), bitmap->GetHeight()); - Bitmap* clone = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); - { - Graphics graphics(clone); - graphics.DrawImage(bitmap, r, 0, 0, r.Width, r.Height, UnitPixel); - } - delete bitmap; - bitmap = clone; - - ::GlobalFree(hBuffer); - hBuffer = nullptr; - //////////////////////////////////////////// - } - *phBuffer = hBuffer; - return bitmap; - } - - delete bitmap; - } - } - - ::GlobalFree(hBuffer); - } - - *phBuffer = nullptr; - return nullptr; -} - -/* -** Loads the image from disk -** -*/ -void TintedImage::LoadImage(const std::wstring& imageName, bool bLoadAlways) -{ - // Load the bitmap if defined - if (!imageName.empty()) - { - std::wstring filename = m_Path + imageName; - if (m_MeterWindow) m_MeterWindow->MakePathAbsolute(filename); - m_HasPathChanged = false; - - // Check extension and if it is missing, add .png - size_t pos = filename.rfind(L'\\'); - if (filename.find(L'.', (pos == std::wstring::npos) ? 0 : pos + 1) == std::wstring::npos) - { - filename += L".png"; - } - - // Read the bitmap to memory so that it's not locked by GDI+ - DWORD fileSize; - HANDLE fileHandle = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, nullptr); - if (fileHandle != INVALID_HANDLE_VALUE && (fileSize = GetFileSize(fileHandle, nullptr)) != INVALID_FILE_SIZE) - { - // Compare the filename/timestamp/filesize to check if the file has been changed (don't load if it's not) - ULONGLONG fileTime; - GetFileTime(fileHandle, nullptr, nullptr, (LPFILETIME)&fileTime); - std::wstring key = ImageCachePool::CreateKey(filename, fileTime, fileSize, m_UseExifOrientation ? L"EXIF" : L"NONE"); - - if (bLoadAlways || wcscmp(key.c_str(), m_CacheKey.c_str()) != 0) - { - DisposeImage(); - - Bitmap* bitmap = ImageCachePool::GetCache(key); - HGLOBAL hBuffer = nullptr; - - m_Bitmap = (bitmap) ? - bitmap : - LoadImageFromFileHandle(fileHandle, fileSize, &hBuffer); - - if (m_Bitmap) - { - m_CacheKey = key; - ImageCachePool::AddCache(key, m_Bitmap, hBuffer); - - // Check whether the new image needs tinting (or cropping, flipping, rotating) - if (!m_NeedsCrop) - { - if (m_Crop.Width >= 0 || m_Crop.Height >= 0) - { - m_NeedsCrop = true; - } - } - if (!m_NeedsTinting) - { - if (m_GreyScale || !CompareColorMatrix(m_ColorMatrix, &c_IdentityMatrix)) - { - m_NeedsTinting = true; - } - } - if (!m_NeedsTransform) - { - if (m_Flip != RotateNoneFlipNone || m_Rotate != 0.0f) - { - m_NeedsTransform = true; - } - } - } - else - { - LogErrorF(m_MeterWindow, L"%s: Unable to load: %s", m_Name, filename.c_str()); - } - } - CloseHandle(fileHandle); - - if (m_Bitmap) - { - // We need a copy of the image if has tinting (or flipping, rotating) - if (m_NeedsCrop || m_NeedsTinting || m_NeedsTransform) - { - delete m_BitmapTint; - m_BitmapTint = nullptr; - - if (m_Bitmap->GetWidth() > 0 && m_Bitmap->GetHeight() > 0) - { - ApplyCrop(); - - if (!m_BitmapTint || (m_BitmapTint->GetWidth() > 0 && m_BitmapTint->GetHeight() > 0)) - { - ApplyTint(); - ApplyTransform(); - } - } - - m_NeedsCrop = false; - m_NeedsTinting = false; - m_NeedsTransform = false; - } - } - } - else - { - LogErrorF(m_MeterWindow, L"%s: Unable to open: %s", m_Name, filename.c_str()); - - if (fileHandle != INVALID_HANDLE_VALUE) - { - CloseHandle(fileHandle); - } - DisposeImage(); - } - } - else if (IsLoaded()) - { - DisposeImage(); - } -} - -/* -** This will apply the cropping. -** -*/ -void TintedImage::ApplyCrop() -{ - if (m_Crop.Width >= 0 && m_Crop.Height >= 0) - { - if (m_Crop.Width == 0 || m_Crop.Height == 0) - { - m_BitmapTint = new Bitmap(0, 0, PixelFormat32bppPARGB); // create dummy bitmap - } - else - { - int imageW = m_Bitmap->GetWidth(); - int imageH = m_Bitmap->GetHeight(); - - int x, y; - - switch (m_CropMode) - { - case CROPMODE_TL: - default: - x = m_Crop.X; - y = m_Crop.Y; - break; - - case CROPMODE_TR: - x = m_Crop.X + imageW; - y = m_Crop.Y; - break; - - case CROPMODE_BR: - x = m_Crop.X + imageW; - y = m_Crop.Y + imageH; - break; - - case CROPMODE_BL: - x = m_Crop.X; - y = m_Crop.Y + imageH; - break; - - case CROPMODE_C: - x = m_Crop.X + (imageW / 2); - y = m_Crop.Y + (imageH / 2); - break; - } - - Rect r(0, 0, m_Crop.Width, m_Crop.Height); - m_BitmapTint = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); - - Graphics graphics(m_BitmapTint); - graphics.DrawImage(m_Bitmap, r, x, y, r.Width, r.Height, UnitPixel); - } - } -} - -/* -** This will apply the Greyscale matrix and the color tinting. -** -*/ -void TintedImage::ApplyTint() -{ - bool useColorMatrix = !CompareColorMatrix(m_ColorMatrix, &c_IdentityMatrix); - - if (m_GreyScale || useColorMatrix) - { - Bitmap* original = GetImage(); - Bitmap* tint; - - if (m_GreyScale && !useColorMatrix) - { - tint = TurnGreyscale(original); - } - else - { - ImageAttributes ImgAttr; - ImgAttr.SetColorMatrix(m_ColorMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap); - - Rect r(0, 0, original->GetWidth(), original->GetHeight()); - - tint = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); - - Graphics graphics(tint); - - if (m_GreyScale) - { - Bitmap* gray = TurnGreyscale(original); - graphics.DrawImage(gray, r, 0, 0, r.Width, r.Height, UnitPixel, &ImgAttr); - delete gray; - } - else - { - graphics.DrawImage(original, r, 0, 0, r.Width, r.Height, UnitPixel, &ImgAttr); - } - } - - delete m_BitmapTint; - m_BitmapTint = tint; - } -} - -/* -** Turns the image greyscale by applying a greyscale color matrix. -** Note that the returned bitmap image must be freed by caller. -** -*/ -Bitmap* TintedImage::TurnGreyscale(Bitmap* source) -{ - ImageAttributes ImgAttr; - ImgAttr.SetColorMatrix(&c_GreyScaleMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap); - - // We need a blank bitmap to paint our greyscale to in case of alpha - Rect r(0, 0, source->GetWidth(), source->GetHeight()); - Bitmap* bitmap = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); - - Graphics graphics(bitmap); - graphics.DrawImage(source, r, 0, 0, r.Width, r.Height, UnitPixel, &ImgAttr); - - return bitmap; -} - -/* -** This will apply the flipping and rotating. -** -*/ -void TintedImage::ApplyTransform() -{ - if (m_Rotate != 0.0f) - { - Bitmap* original = GetImage(); - - REAL originalW = (REAL)original->GetWidth(); - REAL originalH = (REAL)original->GetHeight(); - - REAL cos_f = cos(CONVERT_TO_RADIANS(m_Rotate)), sin_f = sin(CONVERT_TO_RADIANS(m_Rotate)); - - REAL transformW = fabs(originalW * cos_f) + fabs(originalH * sin_f); - REAL transformH = fabs(originalW * sin_f) + fabs(originalH * cos_f); - - Bitmap* transform = new Bitmap((int)(transformW + 0.5f), (int)(transformH + 0.5f), PixelFormat32bppPARGB); - - Graphics graphics(transform); - graphics.SetPixelOffsetMode(PixelOffsetModeHighQuality); - - REAL cx = transformW / 2.0f; - REAL cy = transformH / 2.0f; - - Matrix rotateMatrix; - rotateMatrix.RotateAt(m_Rotate, PointF(cx, cy)); - - graphics.SetTransform(&rotateMatrix); - - if (m_Flip != RotateNoneFlipNone) - { - original->RotateFlip(m_Flip); - } - - RectF r(cx - originalW / 2.0f, cy - originalH / 2.0f, originalW, originalH); - graphics.DrawImage(original, r, -0.5f, -0.5f, originalW + 1.0f, originalH + 1.0f, UnitPixel); // Makes the anti-aliased edge - - if (m_Flip != RotateNoneFlipNone) - { - original->RotateFlip(m_Flip); - } - - delete m_BitmapTint; - m_BitmapTint = transform; - } - else if (m_Flip != RotateNoneFlipNone) - { - Bitmap* original = GetImage(); - - Rect r(0, 0, original->GetWidth(), original->GetHeight()); - Bitmap* transform = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); - - Graphics graphics(transform); - - original->RotateFlip(m_Flip); - - graphics.DrawImage(original, r, 0, 0, r.Width, r.Height, UnitPixel); - - original->RotateFlip(m_Flip); - - delete m_BitmapTint; - m_BitmapTint = transform; - } -} - -/* -** Read the meter-specific options from the ini-file. -** -*/ -void TintedImage::ReadOptions(ConfigParser& parser, const WCHAR* section, const WCHAR* imagePath) -{ - // Store the current values so we know if the image needs to be tinted or transformed - Rect oldCrop = m_Crop; - CROPMODE oldCropMode = m_CropMode; - bool oldGreyScale = m_GreyScale; - ColorMatrix oldColorMatrix = *m_ColorMatrix; - RotateFlipType oldFlip = m_Flip; - REAL oldRotate = m_Rotate; - std::wstring oldPath = m_Path; - - m_Path = parser.ReadString(section, m_OptionArray[OptionIndexImagePath], imagePath); - PathUtil::AppendBacklashIfMissing(m_Path); - - m_HasPathChanged = (oldPath != m_Path); - - if (!m_DisableTransform) - { - m_Crop.X = m_Crop.Y = m_Crop.Width = m_Crop.Height = -1; - m_CropMode = CROPMODE_TL; - - const std::wstring& crop = parser.ReadString(section, m_OptionArray[OptionIndexImageCrop], L""); - if (!crop.empty()) - { - if (wcschr(crop.c_str(), L',')) - { - WCHAR* parseSz = _wcsdup(crop.c_str()); - WCHAR* token; - - token = wcstok(parseSz, L","); - if (token) - { - m_Crop.X = parser.ParseInt(token, 0); - - token = wcstok(nullptr, L","); - if (token) - { - m_Crop.Y = parser.ParseInt(token, 0); - - token = wcstok(nullptr, L","); - if (token) - { - m_Crop.Width = parser.ParseInt(token, 0); - - token = wcstok(nullptr, L","); - if (token) - { - m_Crop.Height = parser.ParseInt(token, 0); - - token = wcstok(nullptr, L","); - if (token) - { - m_CropMode = (CROPMODE)parser.ParseInt(token, 0); - } - } - } - } - } - free(parseSz); - } - - if (m_CropMode < CROPMODE_TL || m_CropMode > CROPMODE_C) - { - m_CropMode = CROPMODE_TL; - LogErrorF(m_MeterWindow, L"%s=%s (origin) is not valid in [%s]", m_OptionArray[OptionIndexImageCrop], crop, section); - } - } - } - - m_NeedsCrop = (oldCrop.X != m_Crop.X || oldCrop.Y != m_Crop.Y || oldCrop.Width != m_Crop.Width || oldCrop.Height != m_Crop.Height || oldCropMode != m_CropMode); - - m_GreyScale = parser.ReadBool(section, m_OptionArray[OptionIndexGreyscale], false); - - Color tint = parser.ReadColor(section, m_OptionArray[OptionIndexImageTint], Color::White); - int alpha = parser.ReadInt(section, m_OptionArray[OptionIndexImageAlpha], tint.GetAlpha()); // for backwards compatibility - alpha = min(255, alpha); - alpha = max(0, alpha); - - *m_ColorMatrix = c_IdentityMatrix; - - // Read in the Color Matrix - // It has to be read in like this because it crashes when reading over 17 floats - // at one time. The parser does it fine, but after putting the returned values - // into the Color Matrix the next time the parser is used it crashes. - std::vector matrix1 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix1]); - if (matrix1.size() == 5) - { - for (int i = 0; i < 4; ++i) // The fifth column must be 0. - { - m_ColorMatrix->m[0][i] = matrix1[i]; - } - } - else - { - m_ColorMatrix->m[0][0] = (REAL)tint.GetRed() / 255.0f; - } - - std::vector matrix2 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix2]); - if (matrix2.size() == 5) - { - for (int i = 0; i < 4; ++i) // The fifth column must be 0. - { - m_ColorMatrix->m[1][i] = matrix2[i]; - } - } - else - { - m_ColorMatrix->m[1][1] = (REAL)tint.GetGreen() / 255.0f; - } - - std::vector matrix3 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix3]); - if (matrix3.size() == 5) - { - for (int i = 0; i < 4; ++i) // The fifth column must be 0. - { - m_ColorMatrix->m[2][i] = matrix3[i]; - } - } - else - { - m_ColorMatrix->m[2][2] = (REAL)tint.GetBlue() / 255.0f; - } - - std::vector matrix4 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix4]); - if (matrix4.size() == 5) - { - for (int i = 0; i < 4; ++i) // The fifth column must be 0. - { - m_ColorMatrix->m[3][i] = matrix4[i]; - } - } - else - { - m_ColorMatrix->m[3][3] = (REAL)alpha / 255.0f; - } - - std::vector matrix5 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix5]); - if (matrix5.size() == 5) - { - for (int i = 0; i < 4; ++i) // The fifth column must be 1. - { - m_ColorMatrix->m[4][i] = matrix5[i]; - } - } - - m_NeedsTinting = (oldGreyScale != m_GreyScale || !CompareColorMatrix(&oldColorMatrix, m_ColorMatrix)); - - m_UseExifOrientation = parser.ReadBool(section, m_OptionArray[OptionIndexUseExifOrientation], false); - - const WCHAR* flip = parser.ReadString(section, m_OptionArray[OptionIndexImageFlip], L"NONE").c_str(); - if (_wcsicmp(flip, L"NONE") == 0) - { - m_Flip = RotateNoneFlipNone; - } - else if (_wcsicmp(flip, L"HORIZONTAL") == 0) - { - m_Flip = RotateNoneFlipX; - } - else if (_wcsicmp(flip, L"VERTICAL") == 0) - { - m_Flip = RotateNoneFlipY; - } - else if (_wcsicmp(flip, L"BOTH") == 0) - { - m_Flip = RotateNoneFlipXY; - } - else - { - LogErrorF(m_MeterWindow, L"%s=%s (origin) is not valid in [%s]", m_OptionArray[OptionIndexImageFlip], flip, section); - } - - if (!m_DisableTransform) - { - m_Rotate = (REAL)parser.ReadFloat(section, m_OptionArray[OptionIndexImageRotate], 0.0); - } - - m_NeedsTransform = (oldFlip != m_Flip || oldRotate != m_Rotate); -} - -/* -** Compares the two given color matrices. -** -*/ -bool TintedImage::CompareColorMatrix(const Gdiplus::ColorMatrix* a, const Gdiplus::ColorMatrix* b) -{ - for (int i = 0; i < 5; ++i) - { - for (int j = 0; j < 4; ++j) // The fifth column is reserved. - { - if (a->m[i][j] != b->m[i][j]) - { - return false; - } - } - } - return true; -} +/* + Copyright (C) 2010 Kimmo Pekkola, Matt King, spx + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../Common/PathUtil.h" +#include "TintedImage.h" +#include "ConfigParser.h" +#include "System.h" +#include "Error.h" +#include "Logger.h" + +using namespace Gdiplus; + + +class ImageCachePool +{ +public: + static std::wstring CreateKey(const std::wstring& name, ULONGLONG time, DWORD size, WCHAR* exifOrientation) + { + std::wstring key; + + WCHAR buffer[MAX_PATH]; + if (PathCanonicalize(buffer, name.c_str())) + { + key = buffer; + } + else + { + key = name; + } + _wcsupr(&key[0]); + + size_t len = _snwprintf_s(buffer, _TRUNCATE, L":%llx:%x:%s", time, size, exifOrientation); + key.append(buffer, len); + + return key; + } + + static Bitmap* GetCache(const std::wstring& key) + { + std::unordered_map::const_iterator iter = c_CacheMap.find(key); + if (iter != c_CacheMap.end()) + { + return (*iter).second->GetCache(); + } + return nullptr; + } + + static void AddCache(const std::wstring& key, Bitmap* bitmap, HGLOBAL hBuffer) + { + std::unordered_map::const_iterator iter = c_CacheMap.find(key); + if (iter != c_CacheMap.end()) + { + (*iter).second->AddRef(); + //LogDebugF(L"* ADD: key=%s, ref=%i", key.c_str(), (*iter).second->GetRef()); + } + else + { + c_CacheMap[key] = new ImageCache(bitmap, hBuffer); + //LogDebugF(L"* ADD: key=%s, ref=new", key.c_str()); + } + } + + static void RemoveCache(const std::wstring& key) + { + std::unordered_map::const_iterator iter = c_CacheMap.find(key); + if (iter != c_CacheMap.end()) + { + ImageCache* cache = (*iter).second; + cache->Release(); + //LogDebugF(L"* REMOVE: key=%s, ref=%i", key.c_str(), cache->GetRef()); + + if (cache->IsInvalid()) + { + //LogDebugF(L"* EMPTY-ERASE: key=%s", key.c_str()); + c_CacheMap.erase(iter); + delete cache; + } + } + } + +private: + class ImageCache + { + public: + ImageCache(Bitmap* bitmap, HGLOBAL hBuffer) : m_Bitmap(bitmap), m_hBuffer(hBuffer), m_Ref(1) {} + ~ImageCache() { Dispose(); } + + void AddRef() { ++m_Ref; } + void Release() { if (m_Ref > 0) { --m_Ref; } if (m_Ref == 0) { Dispose(); } } + + bool IsInvalid() { return m_Ref == 0; } + //int GetRef() { return m_Ref; } + Bitmap* GetCache() { return m_Bitmap; } + + private: + ImageCache() {} + ImageCache(const ImageCache& cache) {} + + void Dispose() { delete m_Bitmap; m_Bitmap = nullptr; if (m_hBuffer) { ::GlobalFree(m_hBuffer); m_hBuffer = nullptr; } } + + Bitmap* m_Bitmap; + HGLOBAL m_hBuffer; + int m_Ref; + }; + + static std::unordered_map c_CacheMap; +}; +std::unordered_map ImageCachePool::c_CacheMap; + + +#define PI (3.14159265f) +#define CONVERT_TO_RADIANS(X) ((X) * (PI / 180.0f)) + +// GrayScale Matrix +const Gdiplus::ColorMatrix TintedImage::c_GreyScaleMatrix = { + 0.299f, 0.299f, 0.299f, 0.0f, 0.0f, + 0.587f, 0.587f, 0.587f, 0.0f, 0.0f, + 0.114f, 0.114f, 0.114f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 1.0f +}; + +const Gdiplus::ColorMatrix TintedImage::c_IdentityMatrix = { + 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 1.0f +}; + +TintedImageHelper_DefineOptionArray(TintedImage::c_DefaultOptionArray, L""); + +/* +** The constructor. +** +** If disableTransform is true, ImageCrop and ImageRotate are ignored. +** +*/ +TintedImage::TintedImage(const WCHAR* name, const WCHAR** optionArray, bool disableTransform, MeterWindow* meterWindow) : m_DisableTransform(disableTransform), + m_Name(name ? name : L"ImageName"), + m_OptionArray(optionArray ? optionArray : c_DefaultOptionArray), + m_Bitmap(), + m_BitmapTint(), + m_NeedsCrop(false), + m_NeedsTinting(false), + m_NeedsTransform(false), + m_Crop(-1, -1, -1, -1), + m_CropMode(CROPMODE_TL), + m_GreyScale(false), + m_ColorMatrix(new ColorMatrix(c_IdentityMatrix)), + m_Flip(RotateNoneFlipNone), + m_Rotate(), + m_UseExifOrientation(false), + m_MeterWindow(meterWindow), + m_HasPathChanged(false) +{ +} + +/* +** The destructor +** +*/ +TintedImage::~TintedImage() +{ + DisposeImage(); + + delete m_ColorMatrix; +} + +/* +** Disposes the image buffers. +** +*/ +void TintedImage::DisposeImage() +{ + delete m_BitmapTint; + m_BitmapTint = nullptr; + + m_Bitmap = nullptr; + + if (!m_CacheKey.empty()) + { + ImageCachePool::RemoveCache(m_CacheKey); + m_CacheKey.clear(); + } +} + +/* +** Loads the image from file handle +** +*/ +Bitmap* TintedImage::LoadImageFromFileHandle(HANDLE fileHandle, DWORD fileSize, HGLOBAL* phBuffer) +{ + HGLOBAL hBuffer = ::GlobalAlloc(GMEM_MOVEABLE, fileSize); + if (hBuffer) + { + void* pBuffer = ::GlobalLock(hBuffer); + if (pBuffer) + { + DWORD readBytes; + ReadFile(fileHandle, pBuffer, fileSize, &readBytes, nullptr); + ::GlobalUnlock(hBuffer); + + IStream* pStream = nullptr; + if (::CreateStreamOnHGlobal(hBuffer, FALSE, &pStream) == S_OK) + { + Bitmap* bitmap = Bitmap::FromStream(pStream); + pStream->Release(); + + if (Ok == bitmap->GetLastStatus()) + { + GUID guid; + if (Ok == bitmap->GetRawFormat(&guid) && guid != ImageFormatIcon) + { + // Gather EXIF orientation information + if (m_UseExifOrientation) + { + UINT size = bitmap->GetPropertyItemSize(PropertyTagOrientation); + if (size) + { + RotateFlipType flip = RotateNoneFlipNone; + PropertyItem* orientation = (PropertyItem*)new BYTE[size]; + bitmap->GetPropertyItem(PropertyTagOrientation, size, orientation); + if (orientation) + { + switch(*(short*)orientation->value) + { + case 8: + flip = Rotate270FlipNone; + break; + + case 7: + flip = Rotate270FlipX; + break; + + case 6: + flip = Rotate90FlipNone; + break; + + case 5: + flip = Rotate90FlipX; + break; + + case 4: + flip = Rotate180FlipX; + break; + + case 3: + flip = Rotate180FlipNone; + break; + + case 2: + flip = RotateNoneFlipX; + break; + + default: + flip = RotateNoneFlipNone; + } + + bitmap->RotateFlip(flip); + } + delete [] orientation; + } + } + + //////////////////////////////////////////// + // Convert loaded image to faster blittable bitmap (may increase memory usage slightly) + Rect r(0, 0, bitmap->GetWidth(), bitmap->GetHeight()); + Bitmap* clone = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); + { + Graphics graphics(clone); + graphics.DrawImage(bitmap, r, 0, 0, r.Width, r.Height, UnitPixel); + } + delete bitmap; + bitmap = clone; + + ::GlobalFree(hBuffer); + hBuffer = nullptr; + //////////////////////////////////////////// + } + *phBuffer = hBuffer; + return bitmap; + } + + delete bitmap; + } + } + + ::GlobalFree(hBuffer); + } + + *phBuffer = nullptr; + return nullptr; +} + +/* +** Loads the image from disk +** +*/ +void TintedImage::LoadImage(const std::wstring& imageName, bool bLoadAlways) +{ + // Load the bitmap if defined + if (!imageName.empty()) + { + std::wstring filename = m_Path + imageName; + if (m_MeterWindow) m_MeterWindow->MakePathAbsolute(filename); + m_HasPathChanged = false; + + // Check extension and if it is missing, add .png + size_t pos = filename.rfind(L'\\'); + if (filename.find(L'.', (pos == std::wstring::npos) ? 0 : pos + 1) == std::wstring::npos) + { + filename += L".png"; + } + + // Read the bitmap to memory so that it's not locked by GDI+ + DWORD fileSize; + HANDLE fileHandle = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, nullptr); + if (fileHandle != INVALID_HANDLE_VALUE && (fileSize = GetFileSize(fileHandle, nullptr)) != INVALID_FILE_SIZE) + { + // Compare the filename/timestamp/filesize to check if the file has been changed (don't load if it's not) + ULONGLONG fileTime; + GetFileTime(fileHandle, nullptr, nullptr, (LPFILETIME)&fileTime); + std::wstring key = ImageCachePool::CreateKey(filename, fileTime, fileSize, m_UseExifOrientation ? L"EXIF" : L"NONE"); + + if (bLoadAlways || wcscmp(key.c_str(), m_CacheKey.c_str()) != 0) + { + DisposeImage(); + + Bitmap* bitmap = ImageCachePool::GetCache(key); + HGLOBAL hBuffer = nullptr; + + m_Bitmap = (bitmap) ? + bitmap : + LoadImageFromFileHandle(fileHandle, fileSize, &hBuffer); + + if (m_Bitmap) + { + m_CacheKey = key; + ImageCachePool::AddCache(key, m_Bitmap, hBuffer); + + // Check whether the new image needs tinting (or cropping, flipping, rotating) + if (!m_NeedsCrop) + { + if (m_Crop.Width >= 0 || m_Crop.Height >= 0) + { + m_NeedsCrop = true; + } + } + if (!m_NeedsTinting) + { + if (m_GreyScale || !CompareColorMatrix(m_ColorMatrix, &c_IdentityMatrix)) + { + m_NeedsTinting = true; + } + } + if (!m_NeedsTransform) + { + if (m_Flip != RotateNoneFlipNone || m_Rotate != 0.0f) + { + m_NeedsTransform = true; + } + } + } + else + { + LogErrorF(m_MeterWindow, L"%s: Unable to load: %s", m_Name, filename.c_str()); + } + } + CloseHandle(fileHandle); + + if (m_Bitmap) + { + // We need a copy of the image if has tinting (or flipping, rotating) + if (m_NeedsCrop || m_NeedsTinting || m_NeedsTransform) + { + delete m_BitmapTint; + m_BitmapTint = nullptr; + + if (m_Bitmap->GetWidth() > 0 && m_Bitmap->GetHeight() > 0) + { + ApplyCrop(); + + if (!m_BitmapTint || (m_BitmapTint->GetWidth() > 0 && m_BitmapTint->GetHeight() > 0)) + { + ApplyTint(); + ApplyTransform(); + } + } + + m_NeedsCrop = false; + m_NeedsTinting = false; + m_NeedsTransform = false; + } + } + } + else + { + LogErrorF(m_MeterWindow, L"%s: Unable to open: %s", m_Name, filename.c_str()); + + if (fileHandle != INVALID_HANDLE_VALUE) + { + CloseHandle(fileHandle); + } + DisposeImage(); + } + } + else if (IsLoaded()) + { + DisposeImage(); + } +} + +/* +** This will apply the cropping. +** +*/ +void TintedImage::ApplyCrop() +{ + if (m_Crop.Width >= 0 && m_Crop.Height >= 0) + { + if (m_Crop.Width == 0 || m_Crop.Height == 0) + { + m_BitmapTint = new Bitmap(0, 0, PixelFormat32bppPARGB); // create dummy bitmap + } + else + { + int imageW = m_Bitmap->GetWidth(); + int imageH = m_Bitmap->GetHeight(); + + int x, y; + + switch (m_CropMode) + { + case CROPMODE_TL: + default: + x = m_Crop.X; + y = m_Crop.Y; + break; + + case CROPMODE_TR: + x = m_Crop.X + imageW; + y = m_Crop.Y; + break; + + case CROPMODE_BR: + x = m_Crop.X + imageW; + y = m_Crop.Y + imageH; + break; + + case CROPMODE_BL: + x = m_Crop.X; + y = m_Crop.Y + imageH; + break; + + case CROPMODE_C: + x = m_Crop.X + (imageW / 2); + y = m_Crop.Y + (imageH / 2); + break; + } + + Rect r(0, 0, m_Crop.Width, m_Crop.Height); + m_BitmapTint = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); + + Graphics graphics(m_BitmapTint); + graphics.DrawImage(m_Bitmap, r, x, y, r.Width, r.Height, UnitPixel); + } + } +} + +/* +** This will apply the Greyscale matrix and the color tinting. +** +*/ +void TintedImage::ApplyTint() +{ + bool useColorMatrix = !CompareColorMatrix(m_ColorMatrix, &c_IdentityMatrix); + + if (m_GreyScale || useColorMatrix) + { + Bitmap* original = GetImage(); + Bitmap* tint; + + if (m_GreyScale && !useColorMatrix) + { + tint = TurnGreyscale(original); + } + else + { + ImageAttributes ImgAttr; + ImgAttr.SetColorMatrix(m_ColorMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap); + + Rect r(0, 0, original->GetWidth(), original->GetHeight()); + + tint = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); + + Graphics graphics(tint); + + if (m_GreyScale) + { + Bitmap* gray = TurnGreyscale(original); + graphics.DrawImage(gray, r, 0, 0, r.Width, r.Height, UnitPixel, &ImgAttr); + delete gray; + } + else + { + graphics.DrawImage(original, r, 0, 0, r.Width, r.Height, UnitPixel, &ImgAttr); + } + } + + delete m_BitmapTint; + m_BitmapTint = tint; + } +} + +/* +** Turns the image greyscale by applying a greyscale color matrix. +** Note that the returned bitmap image must be freed by caller. +** +*/ +Bitmap* TintedImage::TurnGreyscale(Bitmap* source) +{ + ImageAttributes ImgAttr; + ImgAttr.SetColorMatrix(&c_GreyScaleMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap); + + // We need a blank bitmap to paint our greyscale to in case of alpha + Rect r(0, 0, source->GetWidth(), source->GetHeight()); + Bitmap* bitmap = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); + + Graphics graphics(bitmap); + graphics.DrawImage(source, r, 0, 0, r.Width, r.Height, UnitPixel, &ImgAttr); + + return bitmap; +} + +/* +** This will apply the flipping and rotating. +** +*/ +void TintedImage::ApplyTransform() +{ + if (m_Rotate != 0.0f) + { + Bitmap* original = GetImage(); + + REAL originalW = (REAL)original->GetWidth(); + REAL originalH = (REAL)original->GetHeight(); + + REAL cos_f = cos(CONVERT_TO_RADIANS(m_Rotate)), sin_f = sin(CONVERT_TO_RADIANS(m_Rotate)); + + REAL transformW = fabs(originalW * cos_f) + fabs(originalH * sin_f); + REAL transformH = fabs(originalW * sin_f) + fabs(originalH * cos_f); + + Bitmap* transform = new Bitmap((int)(transformW + 0.5f), (int)(transformH + 0.5f), PixelFormat32bppPARGB); + + Graphics graphics(transform); + graphics.SetPixelOffsetMode(PixelOffsetModeHighQuality); + + REAL cx = transformW / 2.0f; + REAL cy = transformH / 2.0f; + + Matrix rotateMatrix; + rotateMatrix.RotateAt(m_Rotate, PointF(cx, cy)); + + graphics.SetTransform(&rotateMatrix); + + if (m_Flip != RotateNoneFlipNone) + { + original->RotateFlip(m_Flip); + } + + RectF r(cx - originalW / 2.0f, cy - originalH / 2.0f, originalW, originalH); + graphics.DrawImage(original, r, -0.5f, -0.5f, originalW + 1.0f, originalH + 1.0f, UnitPixel); // Makes the anti-aliased edge + + if (m_Flip != RotateNoneFlipNone) + { + original->RotateFlip(m_Flip); + } + + delete m_BitmapTint; + m_BitmapTint = transform; + } + else if (m_Flip != RotateNoneFlipNone) + { + Bitmap* original = GetImage(); + + Rect r(0, 0, original->GetWidth(), original->GetHeight()); + Bitmap* transform = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB); + + Graphics graphics(transform); + + original->RotateFlip(m_Flip); + + graphics.DrawImage(original, r, 0, 0, r.Width, r.Height, UnitPixel); + + original->RotateFlip(m_Flip); + + delete m_BitmapTint; + m_BitmapTint = transform; + } +} + +/* +** Read the meter-specific options from the ini-file. +** +*/ +void TintedImage::ReadOptions(ConfigParser& parser, const WCHAR* section, const WCHAR* imagePath) +{ + // Store the current values so we know if the image needs to be tinted or transformed + Rect oldCrop = m_Crop; + CROPMODE oldCropMode = m_CropMode; + bool oldGreyScale = m_GreyScale; + ColorMatrix oldColorMatrix = *m_ColorMatrix; + RotateFlipType oldFlip = m_Flip; + REAL oldRotate = m_Rotate; + std::wstring oldPath = m_Path; + + m_Path = parser.ReadString(section, m_OptionArray[OptionIndexImagePath], imagePath); + PathUtil::AppendBacklashIfMissing(m_Path); + + m_HasPathChanged = (oldPath != m_Path); + + if (!m_DisableTransform) + { + m_Crop.X = m_Crop.Y = m_Crop.Width = m_Crop.Height = -1; + m_CropMode = CROPMODE_TL; + + const std::wstring& crop = parser.ReadString(section, m_OptionArray[OptionIndexImageCrop], L""); + if (!crop.empty()) + { + if (wcschr(crop.c_str(), L',')) + { + WCHAR* parseSz = _wcsdup(crop.c_str()); + WCHAR* token; + + token = wcstok(parseSz, L","); + if (token) + { + m_Crop.X = parser.ParseInt(token, 0); + + token = wcstok(nullptr, L","); + if (token) + { + m_Crop.Y = parser.ParseInt(token, 0); + + token = wcstok(nullptr, L","); + if (token) + { + m_Crop.Width = parser.ParseInt(token, 0); + + token = wcstok(nullptr, L","); + if (token) + { + m_Crop.Height = parser.ParseInt(token, 0); + + token = wcstok(nullptr, L","); + if (token) + { + m_CropMode = (CROPMODE)parser.ParseInt(token, 0); + } + } + } + } + } + free(parseSz); + } + + if (m_CropMode < CROPMODE_TL || m_CropMode > CROPMODE_C) + { + m_CropMode = CROPMODE_TL; + LogErrorF(m_MeterWindow, L"%s=%s (origin) is not valid in [%s]", m_OptionArray[OptionIndexImageCrop], crop, section); + } + } + } + + m_NeedsCrop = (oldCrop.X != m_Crop.X || oldCrop.Y != m_Crop.Y || oldCrop.Width != m_Crop.Width || oldCrop.Height != m_Crop.Height || oldCropMode != m_CropMode); + + m_GreyScale = parser.ReadBool(section, m_OptionArray[OptionIndexGreyscale], false); + + Color tint = parser.ReadColor(section, m_OptionArray[OptionIndexImageTint], Color::White); + int alpha = parser.ReadInt(section, m_OptionArray[OptionIndexImageAlpha], tint.GetAlpha()); // for backwards compatibility + alpha = min(255, alpha); + alpha = max(0, alpha); + + *m_ColorMatrix = c_IdentityMatrix; + + // Read in the Color Matrix + // It has to be read in like this because it crashes when reading over 17 floats + // at one time. The parser does it fine, but after putting the returned values + // into the Color Matrix the next time the parser is used it crashes. + std::vector matrix1 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix1]); + if (matrix1.size() == 5) + { + for (int i = 0; i < 4; ++i) // The fifth column must be 0. + { + m_ColorMatrix->m[0][i] = matrix1[i]; + } + } + else + { + m_ColorMatrix->m[0][0] = (REAL)tint.GetRed() / 255.0f; + } + + std::vector matrix2 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix2]); + if (matrix2.size() == 5) + { + for (int i = 0; i < 4; ++i) // The fifth column must be 0. + { + m_ColorMatrix->m[1][i] = matrix2[i]; + } + } + else + { + m_ColorMatrix->m[1][1] = (REAL)tint.GetGreen() / 255.0f; + } + + std::vector matrix3 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix3]); + if (matrix3.size() == 5) + { + for (int i = 0; i < 4; ++i) // The fifth column must be 0. + { + m_ColorMatrix->m[2][i] = matrix3[i]; + } + } + else + { + m_ColorMatrix->m[2][2] = (REAL)tint.GetBlue() / 255.0f; + } + + std::vector matrix4 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix4]); + if (matrix4.size() == 5) + { + for (int i = 0; i < 4; ++i) // The fifth column must be 0. + { + m_ColorMatrix->m[3][i] = matrix4[i]; + } + } + else + { + m_ColorMatrix->m[3][3] = (REAL)alpha / 255.0f; + } + + std::vector matrix5 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix5]); + if (matrix5.size() == 5) + { + for (int i = 0; i < 4; ++i) // The fifth column must be 1. + { + m_ColorMatrix->m[4][i] = matrix5[i]; + } + } + + m_NeedsTinting = (oldGreyScale != m_GreyScale || !CompareColorMatrix(&oldColorMatrix, m_ColorMatrix)); + + m_UseExifOrientation = parser.ReadBool(section, m_OptionArray[OptionIndexUseExifOrientation], false); + + const WCHAR* flip = parser.ReadString(section, m_OptionArray[OptionIndexImageFlip], L"NONE").c_str(); + if (_wcsicmp(flip, L"NONE") == 0) + { + m_Flip = RotateNoneFlipNone; + } + else if (_wcsicmp(flip, L"HORIZONTAL") == 0) + { + m_Flip = RotateNoneFlipX; + } + else if (_wcsicmp(flip, L"VERTICAL") == 0) + { + m_Flip = RotateNoneFlipY; + } + else if (_wcsicmp(flip, L"BOTH") == 0) + { + m_Flip = RotateNoneFlipXY; + } + else + { + LogErrorF(m_MeterWindow, L"%s=%s (origin) is not valid in [%s]", m_OptionArray[OptionIndexImageFlip], flip, section); + } + + if (!m_DisableTransform) + { + m_Rotate = (REAL)parser.ReadFloat(section, m_OptionArray[OptionIndexImageRotate], 0.0); + } + + m_NeedsTransform = (oldFlip != m_Flip || oldRotate != m_Rotate); +} + +/* +** Compares the two given color matrices. +** +*/ +bool TintedImage::CompareColorMatrix(const Gdiplus::ColorMatrix* a, const Gdiplus::ColorMatrix* b) +{ + for (int i = 0; i < 5; ++i) + { + for (int j = 0; j < 4; ++j) // The fifth column is reserved. + { + if (a->m[i][j] != b->m[i][j]) + { + return false; + } + } + } + return true; +} diff --git a/Library/TintedImage.h b/Library/TintedImage.h index 8d84477a..2cb7c741 100644 --- a/Library/TintedImage.h +++ b/Library/TintedImage.h @@ -1,144 +1,144 @@ -/* - Copyright (C) 2010 Kimmo Pekkola, Matt King, spx - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __TINTEDIMAGE_H__ -#define __TINTEDIMAGE_H__ - -#include -#include // For Gdiplus.h. -#include -#include -#include "MeterWindow.h" - -/* -** Helper macro to define an array of option names. A prefix must be given. -** -*/ -#define TintedImageHelper_DefineOptionArray(name, prefix) \ - const WCHAR* (name)[TintedImage::OptionCount] = { \ - prefix L"ImageCrop", \ - prefix L"Greyscale", \ - prefix L"ImageTint", \ - prefix L"ImageAlpha", \ - prefix L"ColorMatrix1", \ - prefix L"ColorMatrix2", \ - prefix L"ColorMatrix3", \ - prefix L"ColorMatrix4", \ - prefix L"ColorMatrix5", \ - prefix L"ImageFlip", \ - prefix L"ImageRotate", \ - prefix L"UseExifOrientation", \ - prefix L"ImagePath" \ - }; - -class ConfigParser; - -class TintedImage -{ -public: - enum OptionIndex - { - OptionIndexImageCrop = 0, - OptionIndexGreyscale, - OptionIndexImageTint, - OptionIndexImageAlpha, - OptionIndexColorMatrix1, - OptionIndexColorMatrix2, - OptionIndexColorMatrix3, - OptionIndexColorMatrix4, - OptionIndexColorMatrix5, - OptionIndexImageFlip, - OptionIndexImageRotate, - OptionIndexUseExifOrientation, - OptionIndexImagePath, - - OptionCount - }; - - TintedImage(const WCHAR* name = L"ImageName", const WCHAR** optionArray = c_DefaultOptionArray, bool disableTransform = false, MeterWindow* meterWindow = nullptr); - ~TintedImage(); - - TintedImage(const TintedImage& other) = delete; - TintedImage& operator=(TintedImage other) = delete; - - void ReadOptions(ConfigParser& parser, const WCHAR* section, const WCHAR* imagePath = L""); - - bool IsLoaded() { return (m_Bitmap != nullptr); } - bool IsTinted() { return (m_BitmapTint != nullptr); } - bool IsOptionsChanged() { return m_NeedsCrop || m_NeedsTinting || m_NeedsTransform || m_HasPathChanged; } - void ClearOptionFlags() { m_NeedsCrop = m_NeedsTinting = m_NeedsTransform = m_HasPathChanged = false; } - - Gdiplus::Bitmap* GetOriginalImage() { return m_Bitmap; } - Gdiplus::Bitmap* GetTintedImage() { return m_BitmapTint; } - Gdiplus::Bitmap* GetImage() { return (m_BitmapTint) ? m_BitmapTint : m_Bitmap; } - - void DisposeImage(); - void LoadImage(const std::wstring& imageName, bool bLoadAlways); - -protected: - enum CROPMODE - { - CROPMODE_TL = 1, - CROPMODE_TR, - CROPMODE_BR, - CROPMODE_BL, - CROPMODE_C - }; - - void ApplyCrop(); - void ApplyTint(); - void ApplyTransform(); - - Gdiplus::Bitmap* LoadImageFromFileHandle(HANDLE fileHandle, DWORD fileSize, HGLOBAL* phBuffer); - - static Gdiplus::Bitmap* TurnGreyscale(Gdiplus::Bitmap* source); - static bool CompareColorMatrix(const Gdiplus::ColorMatrix* a, const Gdiplus::ColorMatrix* b); - - Gdiplus::Bitmap* m_Bitmap; - Gdiplus::Bitmap* m_BitmapTint; // Tinted bitmap - - const WCHAR* m_Name; - const WCHAR** m_OptionArray; - const bool m_DisableTransform; - - bool m_NeedsCrop; - bool m_NeedsTinting; - bool m_NeedsTransform; - - Gdiplus::Rect m_Crop; - CROPMODE m_CropMode; - bool m_GreyScale; - Gdiplus::ColorMatrix* m_ColorMatrix; - Gdiplus::RotateFlipType m_Flip; - Gdiplus::REAL m_Rotate; - bool m_UseExifOrientation; - - std::wstring m_Path; - bool m_HasPathChanged; - - std::wstring m_CacheKey; - - MeterWindow* m_MeterWindow; - - static const Gdiplus::ColorMatrix c_GreyScaleMatrix; - static const Gdiplus::ColorMatrix c_IdentityMatrix; - - static const WCHAR* c_DefaultOptionArray[OptionCount]; -}; - -#endif +/* + Copyright (C) 2010 Kimmo Pekkola, Matt King, spx + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __TINTEDIMAGE_H__ +#define __TINTEDIMAGE_H__ + +#include +#include // For Gdiplus.h. +#include +#include +#include "MeterWindow.h" + +/* +** Helper macro to define an array of option names. A prefix must be given. +** +*/ +#define TintedImageHelper_DefineOptionArray(name, prefix) \ + const WCHAR* (name)[TintedImage::OptionCount] = { \ + prefix L"ImageCrop", \ + prefix L"Greyscale", \ + prefix L"ImageTint", \ + prefix L"ImageAlpha", \ + prefix L"ColorMatrix1", \ + prefix L"ColorMatrix2", \ + prefix L"ColorMatrix3", \ + prefix L"ColorMatrix4", \ + prefix L"ColorMatrix5", \ + prefix L"ImageFlip", \ + prefix L"ImageRotate", \ + prefix L"UseExifOrientation", \ + prefix L"ImagePath" \ + }; + +class ConfigParser; + +class TintedImage +{ +public: + enum OptionIndex + { + OptionIndexImageCrop = 0, + OptionIndexGreyscale, + OptionIndexImageTint, + OptionIndexImageAlpha, + OptionIndexColorMatrix1, + OptionIndexColorMatrix2, + OptionIndexColorMatrix3, + OptionIndexColorMatrix4, + OptionIndexColorMatrix5, + OptionIndexImageFlip, + OptionIndexImageRotate, + OptionIndexUseExifOrientation, + OptionIndexImagePath, + + OptionCount + }; + + TintedImage(const WCHAR* name = L"ImageName", const WCHAR** optionArray = c_DefaultOptionArray, bool disableTransform = false, MeterWindow* meterWindow = nullptr); + ~TintedImage(); + + TintedImage(const TintedImage& other) = delete; + TintedImage& operator=(TintedImage other) = delete; + + void ReadOptions(ConfigParser& parser, const WCHAR* section, const WCHAR* imagePath = L""); + + bool IsLoaded() { return (m_Bitmap != nullptr); } + bool IsTinted() { return (m_BitmapTint != nullptr); } + bool IsOptionsChanged() { return m_NeedsCrop || m_NeedsTinting || m_NeedsTransform || m_HasPathChanged; } + void ClearOptionFlags() { m_NeedsCrop = m_NeedsTinting = m_NeedsTransform = m_HasPathChanged = false; } + + Gdiplus::Bitmap* GetOriginalImage() { return m_Bitmap; } + Gdiplus::Bitmap* GetTintedImage() { return m_BitmapTint; } + Gdiplus::Bitmap* GetImage() { return (m_BitmapTint) ? m_BitmapTint : m_Bitmap; } + + void DisposeImage(); + void LoadImage(const std::wstring& imageName, bool bLoadAlways); + +protected: + enum CROPMODE + { + CROPMODE_TL = 1, + CROPMODE_TR, + CROPMODE_BR, + CROPMODE_BL, + CROPMODE_C + }; + + void ApplyCrop(); + void ApplyTint(); + void ApplyTransform(); + + Gdiplus::Bitmap* LoadImageFromFileHandle(HANDLE fileHandle, DWORD fileSize, HGLOBAL* phBuffer); + + static Gdiplus::Bitmap* TurnGreyscale(Gdiplus::Bitmap* source); + static bool CompareColorMatrix(const Gdiplus::ColorMatrix* a, const Gdiplus::ColorMatrix* b); + + Gdiplus::Bitmap* m_Bitmap; + Gdiplus::Bitmap* m_BitmapTint; // Tinted bitmap + + const WCHAR* m_Name; + const WCHAR** m_OptionArray; + const bool m_DisableTransform; + + bool m_NeedsCrop; + bool m_NeedsTinting; + bool m_NeedsTransform; + + Gdiplus::Rect m_Crop; + CROPMODE m_CropMode; + bool m_GreyScale; + Gdiplus::ColorMatrix* m_ColorMatrix; + Gdiplus::RotateFlipType m_Flip; + Gdiplus::REAL m_Rotate; + bool m_UseExifOrientation; + + std::wstring m_Path; + bool m_HasPathChanged; + + std::wstring m_CacheKey; + + MeterWindow* m_MeterWindow; + + static const Gdiplus::ColorMatrix c_GreyScaleMatrix; + static const Gdiplus::ColorMatrix c_IdentityMatrix; + + static const WCHAR* c_DefaultOptionArray[OptionCount]; +}; + +#endif diff --git a/Library/TrayWindow.cpp b/Library/TrayWindow.cpp index 5f79cd26..1f80edd4 100644 --- a/Library/TrayWindow.cpp +++ b/Library/TrayWindow.cpp @@ -1,736 +1,736 @@ -/* - Copyright (C) 2004 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "TrayWindow.h" -#include "Measure.h" -#include "resource.h" -#include "Litestep.h" -#include "Rainmeter.h" -#include "DialogAbout.h" -#include "DialogManage.h" -#include "System.h" -#include "Error.h" -#include "RainmeterQuery.h" -#include "resource.h" -#include "../Version.h" - -#define RAINMETER_OFFICIAL L"http://rainmeter.net/cms/" -#define RAINMETER_HELP L"http://docs.rainmeter.net/" - -#define ZPOS_FLAGS (SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING) - -enum TIMER -{ - TIMER_ADDTRAYICON = 1, - TIMER_TRAYMEASURE = 3 -}; -enum INTERVAL -{ - INTERVAL_ADDTRAYICON = 3000, - INTERVAL_TRAYMEASURE = 1000 -}; - -const UINT WM_TASKBARCREATED = ::RegisterWindowMessage(L"TaskbarCreated"); - -using namespace Gdiplus; - -TrayWindow::TrayWindow() : - m_Icon(), - m_Measure(), - m_MeterType(TRAY_METER_TYPE_HISTOGRAM), - m_Color1(0, 100, 0), - m_Color2(0, 255, 0), - m_Bitmap(), - m_Values(), - m_Pos(), - m_Notification(TRAY_NOTIFICATION_NONE), - m_TrayContextMenuEnabled(true), - m_IconEnabled(true) -{ -} - -TrayWindow::~TrayWindow() -{ - KillTimer(m_Window, TIMER_ADDTRAYICON); - KillTimer(m_Window, TIMER_TRAYMEASURE); - RemoveTrayIcon(); - - delete m_Bitmap; - delete m_Measure; - - for (size_t i = 0, isize = m_Icons.size(); i < isize; ++i) - { - DestroyIcon(m_Icons[i]); - } - m_Icons.clear(); - - if (m_Window) DestroyWindow(m_Window); -} - -void TrayWindow::Initialize() -{ - WNDCLASS wc = {0}; - wc.lpfnWndProc = (WNDPROC)WndProc; - wc.hInstance = Rainmeter::GetInstance().GetModuleInstance(); - wc.lpszClassName = L"RainmeterTrayClass"; - wc.hIcon = GetIcon(IDI_RAINMETER); - - RegisterClass(&wc); - - m_Window = CreateWindowEx( - WS_EX_TOOLWINDOW, - L"RainmeterTrayClass", - nullptr, - WS_POPUP | WS_DISABLED, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - nullptr, - nullptr, - wc.hInstance, - this); - - SetWindowPos(m_Window, HWND_BOTTOM, 0, 0, 0, 0, ZPOS_FLAGS); -} - -bool TrayWindow::AddTrayIcon() -{ - NOTIFYICONDATA tnid = {sizeof(NOTIFYICONDATA)}; - tnid.hWnd = m_Window; - tnid.uID = IDI_TRAY; - tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; - tnid.uCallbackMessage = WM_TRAY_NOTIFYICON; - tnid.hIcon = m_Icon; - wcsncpy_s(tnid.szTip, APPNAME, _TRUNCATE); - - return (Shell_NotifyIcon(NIM_ADD, &tnid) || GetLastError() != ERROR_TIMEOUT); -} - -bool TrayWindow::IsTrayIconReady() -{ - NOTIFYICONDATA tnid = {sizeof(NOTIFYICONDATA)}; - tnid.hWnd = m_Window; - tnid.uID = IDI_TRAY; - - return Shell_NotifyIcon(NIM_MODIFY, &tnid) != FALSE; -} - -void TrayWindow::TryAddTrayIcon() -{ - if (IsTrayIconReady()) - { - ModifyTrayIcon(0); - return; - } - - if (m_Icon) - { - DestroyIcon(m_Icon); - m_Icon = nullptr; - } - - m_Icon = CreateTrayIcon(0); - - if (!AddTrayIcon()) - { - SetTimer(m_Window, TIMER_ADDTRAYICON, INTERVAL_ADDTRAYICON, nullptr); - } -} - -void TrayWindow::CheckTrayIcon() -{ - if (IsTrayIconReady() || AddTrayIcon()) - { - KillTimer(m_Window, TIMER_ADDTRAYICON); - } -} - -void TrayWindow::RemoveTrayIcon() -{ - NOTIFYICONDATA tnid = {sizeof(NOTIFYICONDATA)}; - tnid.hWnd = m_Window; - tnid.uID = IDI_TRAY; - tnid.uFlags = 0; - - Shell_NotifyIcon(NIM_DELETE, &tnid); - - if (m_Icon) - { - DestroyIcon(m_Icon); - m_Icon = nullptr; - } -} - -void TrayWindow::ModifyTrayIcon(double value) -{ - if (m_Icon) - { - DestroyIcon(m_Icon); - m_Icon = nullptr; - } - - m_Icon = CreateTrayIcon(value); - - NOTIFYICONDATA tnid = {sizeof(NOTIFYICONDATA)}; - tnid.hWnd = m_Window; - tnid.uID = IDI_TRAY; - tnid.uFlags = NIF_ICON; - tnid.hIcon = m_Icon; - - Shell_NotifyIcon(NIM_MODIFY, &tnid); -} - -HICON TrayWindow::CreateTrayIcon(double value) -{ - if (m_Measure != nullptr) - { - if (m_MeterType == TRAY_METER_TYPE_HISTOGRAM) - { - m_Values[m_Pos] = value; - m_Pos = (m_Pos + 1) % TRAYICON_SIZE; - - Bitmap trayBitmap(TRAYICON_SIZE, TRAYICON_SIZE); - Graphics graphics(&trayBitmap); - graphics.SetSmoothingMode(SmoothingModeAntiAlias); - - Point points[TRAYICON_SIZE + 2]; - points[0].X = 0; - points[0].Y = TRAYICON_SIZE; - points[TRAYICON_SIZE + 1].X = TRAYICON_SIZE - 1; - points[TRAYICON_SIZE + 1].Y = TRAYICON_SIZE; - - for (int i = 0; i < TRAYICON_SIZE; ++i) - { - points[i + 1].X = i; - points[i + 1].Y = (int)(TRAYICON_SIZE * (1.0 - m_Values[(m_Pos + i) % TRAYICON_SIZE])); - } - - SolidBrush brush(m_Color1); - graphics.FillRectangle(&brush, 0, 0, TRAYICON_SIZE, TRAYICON_SIZE); - - SolidBrush brush2(m_Color2); - graphics.FillPolygon(&brush2, points, TRAYICON_SIZE + 2); - - HICON icon = nullptr; - trayBitmap.GetHICON(&icon); - return icon; - } - else if (m_MeterType == TRAY_METER_TYPE_BITMAP && (m_Bitmap || !m_Icons.empty())) - { - if (!m_Icons.empty()) - { - size_t frame = 0; - size_t frameCount = m_Icons.size(); - - // Select the correct frame linearly - frame = (size_t)(value * frameCount); - frame = min((frameCount - 1), frame); - - return CopyIcon(m_Icons[frame]); - } - else - { - int frame = 0; - int frameCount = 0; - int newX, newY; - - if (m_Bitmap->GetWidth() > m_Bitmap->GetHeight()) - { - frameCount = m_Bitmap->GetWidth() / TRAYICON_SIZE; - } - else - { - frameCount = m_Bitmap->GetHeight() / TRAYICON_SIZE; - } - - // Select the correct frame linearly - frame = (int)(value * frameCount); - frame = min((frameCount - 1), frame); - - if (m_Bitmap->GetWidth() > m_Bitmap->GetHeight()) - { - newX = frame * TRAYICON_SIZE; - newY = 0; - } - else - { - newX = 0; - newY = frame * TRAYICON_SIZE; - } - - Bitmap trayBitmap(TRAYICON_SIZE, TRAYICON_SIZE); - Graphics graphics(&trayBitmap); - graphics.SetSmoothingMode(SmoothingModeAntiAlias); - - // Blit the image - Rect r(0, 0, TRAYICON_SIZE, TRAYICON_SIZE); - graphics.DrawImage(m_Bitmap, r, newX, newY, TRAYICON_SIZE, TRAYICON_SIZE, UnitPixel); - - HICON icon = nullptr; - trayBitmap.GetHICON(&icon); - return icon; - } - } - } - - // Return the default icon if there is no valid measure - return GetIcon(IDI_TRAY); -} - -void TrayWindow::ShowNotification(TRAY_NOTIFICATION id, const WCHAR* title, const WCHAR* text) -{ - if (m_Notification == TRAY_NOTIFICATION_NONE) - { - NOTIFYICONDATA nid = {sizeof(NOTIFYICONDATA)}; - nid.hWnd = m_Window; - nid.uID = IDI_TRAY; - nid.uFlags = NIF_INFO; - nid.uTimeout = 30000; - nid.dwInfoFlags = NIIF_USER; - wcsncpy_s(nid.szInfoTitle, title, _TRUNCATE); - wcsncpy_s(nid.szInfo, text, _TRUNCATE); - - if (IsWindows7OrGreater()) - { - nid.dwInfoFlags |= NIIF_LARGE_ICON; - nid.hBalloonIcon = GetIcon(IDI_RAINMETER, true); - } - - if (Shell_NotifyIcon(NIM_MODIFY, &nid)) - { - m_Notification = id; - } - } -} - -void TrayWindow::ShowWelcomeNotification() -{ - ShowNotification(TRAY_NOTIFICATION_WELCOME, GetString(ID_STR_WELCOME), GetString(ID_STR_CLICKTOMANAGE)); -} - -void TrayWindow::ShowUpdateNotification(const WCHAR* newVersion) -{ - std::wstring text = GetFormattedString(ID_STR_CLICKTODOWNLOAD, newVersion); - ShowNotification(TRAY_NOTIFICATION_UPDATE, GetString(ID_STR_UPDATEAVAILABLE), text.c_str()); -} - -void TrayWindow::SetTrayIcon(bool enabled) -{ - enabled ? TryAddTrayIcon() : RemoveTrayIcon(); - m_IconEnabled = enabled; - - // Save to Rainmeter.ini. - const std::wstring& iniFile = Rainmeter::GetInstance().GetIniFile(); - WritePrivateProfileString(L"Rainmeter", L"TrayIcon", enabled ? nullptr : L"0", iniFile.c_str()); -} - -void TrayWindow::ReadOptions(ConfigParser& parser) -{ - // Clear old Settings - KillTimer(m_Window, TIMER_ADDTRAYICON); - KillTimer(m_Window, TIMER_TRAYMEASURE); - - delete m_Measure; - m_Measure = nullptr; - - delete m_Bitmap; - m_Bitmap = nullptr; - - std::vector::const_iterator iter = m_Icons.begin(); - for ( ; iter != m_Icons.end(); ++iter) - { - DestroyIcon((*iter)); - } - m_Icons.clear(); - - m_MeterType = TRAY_METER_TYPE_NONE; - - // Read tray settings - m_IconEnabled = parser.ReadBool(L"Rainmeter", L"TrayIcon", true); - if (m_IconEnabled) - { - const std::wstring& measureName = parser.ReadString(L"TrayMeasure", L"Measure", L""); - - if (!measureName.empty()) - { - ConfigParser* oldParser = Rainmeter::GetInstance().GetCurrentParser(); - Rainmeter::GetInstance().SetCurrentParser(&parser); - - m_Measure = Measure::Create(measureName.c_str(), nullptr, L"TrayMeasure"); - if (m_Measure) - { - m_Measure->ReadOptions(parser); - } - - Rainmeter::GetInstance().SetCurrentParser(oldParser); - } - - const WCHAR* type = parser.ReadString(L"TrayMeasure", L"TrayMeter", m_Measure ? L"HISTOGRAM" : L"NONE").c_str(); - if (_wcsicmp(type, L"NONE") == 0) - { - // Use main icon - } - else if (_wcsicmp(type, L"HISTOGRAM") == 0) - { - m_MeterType = TRAY_METER_TYPE_HISTOGRAM; - m_Color1 = parser.ReadColor(L"TrayMeasure", L"TrayColor1", Color::MakeARGB(255, 0, 100, 0)); - m_Color2 = parser.ReadColor(L"TrayMeasure", L"TrayColor2", Color::MakeARGB(255, 0, 255, 0)); - } - else if (_wcsicmp(type, L"BITMAP") == 0) - { - m_MeterType = TRAY_METER_TYPE_BITMAP; - - std::wstring imageName = parser.ReadString(L"TrayMeasure", L"TrayBitmap", L""); - - // Load the bitmaps if defined - if (!imageName.empty()) - { - imageName.insert(0, Rainmeter::GetInstance().GetSkinPath()); - const WCHAR* imagePath = imageName.c_str(); - if (_wcsicmp(imagePath + (imageName.size() - 4), L".ico") == 0) - { - int count = 1; - HICON hIcon = nullptr; - - // Load the icons - do - { - WCHAR buffer[MAX_PATH]; - _snwprintf_s(buffer, _TRUNCATE, imagePath, count++); - - hIcon = (HICON)LoadImage(nullptr, buffer, IMAGE_ICON, TRAYICON_SIZE, TRAYICON_SIZE, LR_LOADFROMFILE); - if (hIcon) m_Icons.push_back(hIcon); - if (wcscmp(imagePath, buffer) == 0) break; - } - while(hIcon != nullptr); - } - - if (m_Icons.empty()) - { - // No icons found so load as bitmap - delete m_Bitmap; - m_Bitmap = new Bitmap(imagePath); - Status status = m_Bitmap->GetLastStatus(); - if (Ok != status) - { - delete m_Bitmap; - m_Bitmap = nullptr; - LogWarningF(L"Bitmap image not found: %s", imagePath); - } - } - } - } - else - { - LogErrorF(L"No such TrayMeter: %s", type); - } - - TryAddTrayIcon(); - - if (m_Measure) - { - SetTimer(m_Window, TIMER_TRAYMEASURE, INTERVAL_TRAYMEASURE, nullptr); // Update the tray once per sec - } - } - else - { - RemoveTrayIcon(); - } -} - -LRESULT CALLBACK TrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - TrayWindow* tray = Rainmeter::GetInstance().GetTrayWindow(); - - switch (uMsg) - { - case WM_COMMAND: - switch (wParam) - { - case IDM_MANAGE: - DialogManage::Open(); - break; - - case IDM_ABOUT: - DialogAbout::Open(); - break; - - case IDM_SHOW_HELP: - CommandHandler::RunFile(RAINMETER_HELP); - break; - - case IDM_NEW_VERSION: - CommandHandler::RunFile(RAINMETER_OFFICIAL); - break; - - case IDM_REFRESH: - PostMessage(Rainmeter::GetInstance().GetWindow(), WM_RAINMETER_DELAYED_REFRESH_ALL, (WPARAM)nullptr, (LPARAM)nullptr); - break; - - case IDM_SHOWLOGFILE: - Rainmeter::GetInstance().ShowLogFile(); - break; - - case IDM_STARTLOG: - GetLogger().StartLogFile(); - break; - - case IDM_STOPLOG: - GetLogger().StopLogFile(); - break; - - case IDM_DELETELOGFILE: - GetLogger().DeleteLogFile(); - break; - - case IDM_DEBUGLOG: - Rainmeter::GetInstance().SetDebug(!Rainmeter::GetInstance().GetDebug()); - break; - - case IDM_DISABLEDRAG: - Rainmeter::GetInstance().SetDisableDragging(!Rainmeter::GetInstance().GetDisableDragging()); - break; - - case IDM_EDITCONFIG: - Rainmeter::GetInstance().EditSettings(); - break; - - case IDM_QUIT: - PostQuitMessage(0); - break; - - case IDM_OPENSKINSFOLDER: - Rainmeter::GetInstance().OpenSkinFolder(); - break; - - default: - { - UINT mID = wParam & 0x0FFFF; - - if (mID >= ID_THEME_FIRST && mID <= ID_THEME_LAST) - { - int pos = mID - ID_THEME_FIRST; - - const std::vector& layouts = Rainmeter::GetInstance().GetAllLayouts(); - if (pos >= 0 && pos < (int)layouts.size()) - { - Rainmeter::GetInstance().LoadLayout(layouts[pos]); - } - } - else if (mID >= ID_CONFIG_FIRST && mID <= ID_CONFIG_LAST) - { - Rainmeter::GetInstance().ToggleSkinWithID(mID); - } - else - { - // Forward the message to correct window - int index = (int)(wParam >> 16); - const std::map& windows = Rainmeter::GetInstance().GetAllMeterWindows(); - - if (index < (int)windows.size()) - { - std::map::const_iterator iter = windows.begin(); - for ( ; iter != windows.end(); ++iter) - { - --index; - if (index < 0) - { - MeterWindow* meterWindow = (*iter).second; - SendMessage(meterWindow->GetWindow(), WM_COMMAND, mID, 0); - break; - } - } - } - } - } - break; - } - break; // Don't send WM_COMMANDS any further - - case WM_TRAY_NOTIFYICON: - { - UINT uMouseMsg = (UINT)lParam; - LPCWSTR bang; - - // Check TrayExecute actions - switch (uMouseMsg) - { - case WM_MBUTTONDOWN: - bang = Rainmeter::GetInstance().GetTrayExecuteM().c_str(); - break; - - case WM_RBUTTONDOWN: - bang = Rainmeter::GetInstance().GetTrayExecuteR().c_str(); - break; - - case WM_MBUTTONDBLCLK: - bang = Rainmeter::GetInstance().GetTrayExecuteDM().c_str(); - break; - - case WM_RBUTTONDBLCLK: - bang = Rainmeter::GetInstance().GetTrayExecuteDR().c_str(); - break; - - default: - bang = L""; - break; - } - - if (*bang && - !IsCtrlKeyDown()) // Ctrl is pressed, so only run default action - { - Rainmeter::GetInstance().ExecuteCommand(bang, nullptr); - tray->m_TrayContextMenuEnabled = (uMouseMsg != WM_RBUTTONDOWN); - break; - } - - // Run default UI action - switch (uMouseMsg) - { - case WM_RBUTTONDOWN: - tray->m_TrayContextMenuEnabled = true; - break; - - case WM_RBUTTONUP: - if (tray->m_TrayContextMenuEnabled) - { - POINT pos = System::GetCursorPosition(); - Rainmeter::GetInstance().ShowContextMenu(pos, nullptr); - } - break; - - case WM_LBUTTONUP: - case WM_LBUTTONDBLCLK: - DialogManage::Open(); - break; - - case NIN_BALLOONUSERCLICK: - if (tray->m_Notification == TRAY_NOTIFICATION_WELCOME) - { - DialogManage::Open(); - } - else if (tray->m_Notification == TRAY_NOTIFICATION_UPDATE) - { - CommandHandler::RunFile(RAINMETER_OFFICIAL); - } - tray->m_Notification = TRAY_NOTIFICATION_NONE; - break; - - case NIN_BALLOONHIDE: - case NIN_BALLOONTIMEOUT: - tray->m_Notification = TRAY_NOTIFICATION_NONE; - break; - } - } - break; - - case WM_QUERY_RAINMETER: - if (IsWindow((HWND)lParam)) - { - auto sendCopyData = [&](const std::wstring& data) - { - COPYDATASTRUCT cds; - cds.dwData = wParam; - cds.cbData = (DWORD)((data.length() + 1) * sizeof(WCHAR)); - cds.lpData = (PVOID)data.c_str(); - SendMessage((HWND)lParam, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&cds); - }; - - switch (wParam) - { - case RAINMETER_QUERY_ID_SKINS_PATH: - sendCopyData(Rainmeter::GetInstance().GetSkinPath()); - return 0; - - case RAINMETER_QUERY_ID_SETTINGS_PATH: - sendCopyData(Rainmeter::GetInstance().GetSettingsPath()); - return 0; - - case RAINMETER_QUERY_ID_PLUGINS_PATH: - sendCopyData(Rainmeter::GetInstance().GetPluginPath()); - return 0; - - case RAINMETER_QUERY_ID_PROGRAM_PATH: - sendCopyData(Rainmeter::GetInstance().GetPath()); - return 0; - - case RAINMETER_QUERY_ID_LOG_PATH: - sendCopyData(GetLogger().GetLogFilePath()); - return 0; - - case RAINMETER_QUERY_ID_CONFIG_EDITOR: - sendCopyData(Rainmeter::GetInstance().GetSkinEditor()); - return 0; - - case RAINMETER_QUERY_ID_IS_DEBUGGING: - { - BOOL debug = Rainmeter::GetInstance().GetDebug(); - SendMessage((HWND)lParam, WM_QUERY_RAINMETER_RETURN, (WPARAM)hWnd, (LPARAM)debug); - } - return 0; - } - } - return 1; - - case WM_COPYDATA: - { - COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam; - if (cds->dwData == RAINMETER_QUERY_ID_SKIN_WINDOWHANDLE) - { - LPCWSTR folderPath = (LPCWSTR)cds->lpData; - MeterWindow* mw = Rainmeter::GetInstance().GetMeterWindow(folderPath); - return (mw) ? (LRESULT)mw->GetWindow() : 0; - } - } - return 1; - - case WM_TIMER: - if (wParam == TIMER_TRAYMEASURE) - { - if (tray->m_Measure) - { - tray->m_Measure->Update(); - tray->ModifyTrayIcon(tray->m_Measure->GetRelativeValue()); - } - } - else if (wParam == TIMER_ADDTRAYICON) - { - tray->CheckTrayIcon(); - } - break; - - case WM_DESTROY: - PostQuitMessage(0); - break; - - default: - if (uMsg == WM_TASKBARCREATED) - { - if (tray->IsTrayIconEnabled()) - { - tray->RemoveTrayIcon(); - tray->TryAddTrayIcon(); - } - } - return DefWindowProc(hWnd, uMsg, wParam, lParam); - } - - return 0; -} +/* + Copyright (C) 2004 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "TrayWindow.h" +#include "Measure.h" +#include "resource.h" +#include "Litestep.h" +#include "Rainmeter.h" +#include "DialogAbout.h" +#include "DialogManage.h" +#include "System.h" +#include "Error.h" +#include "RainmeterQuery.h" +#include "resource.h" +#include "../Version.h" + +#define RAINMETER_OFFICIAL L"http://rainmeter.net/cms/" +#define RAINMETER_HELP L"http://docs.rainmeter.net/" + +#define ZPOS_FLAGS (SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING) + +enum TIMER +{ + TIMER_ADDTRAYICON = 1, + TIMER_TRAYMEASURE = 3 +}; +enum INTERVAL +{ + INTERVAL_ADDTRAYICON = 3000, + INTERVAL_TRAYMEASURE = 1000 +}; + +const UINT WM_TASKBARCREATED = ::RegisterWindowMessage(L"TaskbarCreated"); + +using namespace Gdiplus; + +TrayWindow::TrayWindow() : + m_Icon(), + m_Measure(), + m_MeterType(TRAY_METER_TYPE_HISTOGRAM), + m_Color1(0, 100, 0), + m_Color2(0, 255, 0), + m_Bitmap(), + m_Values(), + m_Pos(), + m_Notification(TRAY_NOTIFICATION_NONE), + m_TrayContextMenuEnabled(true), + m_IconEnabled(true) +{ +} + +TrayWindow::~TrayWindow() +{ + KillTimer(m_Window, TIMER_ADDTRAYICON); + KillTimer(m_Window, TIMER_TRAYMEASURE); + RemoveTrayIcon(); + + delete m_Bitmap; + delete m_Measure; + + for (size_t i = 0, isize = m_Icons.size(); i < isize; ++i) + { + DestroyIcon(m_Icons[i]); + } + m_Icons.clear(); + + if (m_Window) DestroyWindow(m_Window); +} + +void TrayWindow::Initialize() +{ + WNDCLASS wc = {0}; + wc.lpfnWndProc = (WNDPROC)WndProc; + wc.hInstance = Rainmeter::GetInstance().GetModuleInstance(); + wc.lpszClassName = L"RainmeterTrayClass"; + wc.hIcon = GetIcon(IDI_RAINMETER); + + RegisterClass(&wc); + + m_Window = CreateWindowEx( + WS_EX_TOOLWINDOW, + L"RainmeterTrayClass", + nullptr, + WS_POPUP | WS_DISABLED, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + nullptr, + nullptr, + wc.hInstance, + this); + + SetWindowPos(m_Window, HWND_BOTTOM, 0, 0, 0, 0, ZPOS_FLAGS); +} + +bool TrayWindow::AddTrayIcon() +{ + NOTIFYICONDATA tnid = {sizeof(NOTIFYICONDATA)}; + tnid.hWnd = m_Window; + tnid.uID = IDI_TRAY; + tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; + tnid.uCallbackMessage = WM_TRAY_NOTIFYICON; + tnid.hIcon = m_Icon; + wcsncpy_s(tnid.szTip, APPNAME, _TRUNCATE); + + return (Shell_NotifyIcon(NIM_ADD, &tnid) || GetLastError() != ERROR_TIMEOUT); +} + +bool TrayWindow::IsTrayIconReady() +{ + NOTIFYICONDATA tnid = {sizeof(NOTIFYICONDATA)}; + tnid.hWnd = m_Window; + tnid.uID = IDI_TRAY; + + return Shell_NotifyIcon(NIM_MODIFY, &tnid) != FALSE; +} + +void TrayWindow::TryAddTrayIcon() +{ + if (IsTrayIconReady()) + { + ModifyTrayIcon(0); + return; + } + + if (m_Icon) + { + DestroyIcon(m_Icon); + m_Icon = nullptr; + } + + m_Icon = CreateTrayIcon(0); + + if (!AddTrayIcon()) + { + SetTimer(m_Window, TIMER_ADDTRAYICON, INTERVAL_ADDTRAYICON, nullptr); + } +} + +void TrayWindow::CheckTrayIcon() +{ + if (IsTrayIconReady() || AddTrayIcon()) + { + KillTimer(m_Window, TIMER_ADDTRAYICON); + } +} + +void TrayWindow::RemoveTrayIcon() +{ + NOTIFYICONDATA tnid = {sizeof(NOTIFYICONDATA)}; + tnid.hWnd = m_Window; + tnid.uID = IDI_TRAY; + tnid.uFlags = 0; + + Shell_NotifyIcon(NIM_DELETE, &tnid); + + if (m_Icon) + { + DestroyIcon(m_Icon); + m_Icon = nullptr; + } +} + +void TrayWindow::ModifyTrayIcon(double value) +{ + if (m_Icon) + { + DestroyIcon(m_Icon); + m_Icon = nullptr; + } + + m_Icon = CreateTrayIcon(value); + + NOTIFYICONDATA tnid = {sizeof(NOTIFYICONDATA)}; + tnid.hWnd = m_Window; + tnid.uID = IDI_TRAY; + tnid.uFlags = NIF_ICON; + tnid.hIcon = m_Icon; + + Shell_NotifyIcon(NIM_MODIFY, &tnid); +} + +HICON TrayWindow::CreateTrayIcon(double value) +{ + if (m_Measure != nullptr) + { + if (m_MeterType == TRAY_METER_TYPE_HISTOGRAM) + { + m_Values[m_Pos] = value; + m_Pos = (m_Pos + 1) % TRAYICON_SIZE; + + Bitmap trayBitmap(TRAYICON_SIZE, TRAYICON_SIZE); + Graphics graphics(&trayBitmap); + graphics.SetSmoothingMode(SmoothingModeAntiAlias); + + Point points[TRAYICON_SIZE + 2]; + points[0].X = 0; + points[0].Y = TRAYICON_SIZE; + points[TRAYICON_SIZE + 1].X = TRAYICON_SIZE - 1; + points[TRAYICON_SIZE + 1].Y = TRAYICON_SIZE; + + for (int i = 0; i < TRAYICON_SIZE; ++i) + { + points[i + 1].X = i; + points[i + 1].Y = (int)(TRAYICON_SIZE * (1.0 - m_Values[(m_Pos + i) % TRAYICON_SIZE])); + } + + SolidBrush brush(m_Color1); + graphics.FillRectangle(&brush, 0, 0, TRAYICON_SIZE, TRAYICON_SIZE); + + SolidBrush brush2(m_Color2); + graphics.FillPolygon(&brush2, points, TRAYICON_SIZE + 2); + + HICON icon = nullptr; + trayBitmap.GetHICON(&icon); + return icon; + } + else if (m_MeterType == TRAY_METER_TYPE_BITMAP && (m_Bitmap || !m_Icons.empty())) + { + if (!m_Icons.empty()) + { + size_t frame = 0; + size_t frameCount = m_Icons.size(); + + // Select the correct frame linearly + frame = (size_t)(value * frameCount); + frame = min((frameCount - 1), frame); + + return CopyIcon(m_Icons[frame]); + } + else + { + int frame = 0; + int frameCount = 0; + int newX, newY; + + if (m_Bitmap->GetWidth() > m_Bitmap->GetHeight()) + { + frameCount = m_Bitmap->GetWidth() / TRAYICON_SIZE; + } + else + { + frameCount = m_Bitmap->GetHeight() / TRAYICON_SIZE; + } + + // Select the correct frame linearly + frame = (int)(value * frameCount); + frame = min((frameCount - 1), frame); + + if (m_Bitmap->GetWidth() > m_Bitmap->GetHeight()) + { + newX = frame * TRAYICON_SIZE; + newY = 0; + } + else + { + newX = 0; + newY = frame * TRAYICON_SIZE; + } + + Bitmap trayBitmap(TRAYICON_SIZE, TRAYICON_SIZE); + Graphics graphics(&trayBitmap); + graphics.SetSmoothingMode(SmoothingModeAntiAlias); + + // Blit the image + Rect r(0, 0, TRAYICON_SIZE, TRAYICON_SIZE); + graphics.DrawImage(m_Bitmap, r, newX, newY, TRAYICON_SIZE, TRAYICON_SIZE, UnitPixel); + + HICON icon = nullptr; + trayBitmap.GetHICON(&icon); + return icon; + } + } + } + + // Return the default icon if there is no valid measure + return GetIcon(IDI_TRAY); +} + +void TrayWindow::ShowNotification(TRAY_NOTIFICATION id, const WCHAR* title, const WCHAR* text) +{ + if (m_Notification == TRAY_NOTIFICATION_NONE) + { + NOTIFYICONDATA nid = {sizeof(NOTIFYICONDATA)}; + nid.hWnd = m_Window; + nid.uID = IDI_TRAY; + nid.uFlags = NIF_INFO; + nid.uTimeout = 30000; + nid.dwInfoFlags = NIIF_USER; + wcsncpy_s(nid.szInfoTitle, title, _TRUNCATE); + wcsncpy_s(nid.szInfo, text, _TRUNCATE); + + if (IsWindows7OrGreater()) + { + nid.dwInfoFlags |= NIIF_LARGE_ICON; + nid.hBalloonIcon = GetIcon(IDI_RAINMETER, true); + } + + if (Shell_NotifyIcon(NIM_MODIFY, &nid)) + { + m_Notification = id; + } + } +} + +void TrayWindow::ShowWelcomeNotification() +{ + ShowNotification(TRAY_NOTIFICATION_WELCOME, GetString(ID_STR_WELCOME), GetString(ID_STR_CLICKTOMANAGE)); +} + +void TrayWindow::ShowUpdateNotification(const WCHAR* newVersion) +{ + std::wstring text = GetFormattedString(ID_STR_CLICKTODOWNLOAD, newVersion); + ShowNotification(TRAY_NOTIFICATION_UPDATE, GetString(ID_STR_UPDATEAVAILABLE), text.c_str()); +} + +void TrayWindow::SetTrayIcon(bool enabled) +{ + enabled ? TryAddTrayIcon() : RemoveTrayIcon(); + m_IconEnabled = enabled; + + // Save to Rainmeter.ini. + const std::wstring& iniFile = Rainmeter::GetInstance().GetIniFile(); + WritePrivateProfileString(L"Rainmeter", L"TrayIcon", enabled ? nullptr : L"0", iniFile.c_str()); +} + +void TrayWindow::ReadOptions(ConfigParser& parser) +{ + // Clear old Settings + KillTimer(m_Window, TIMER_ADDTRAYICON); + KillTimer(m_Window, TIMER_TRAYMEASURE); + + delete m_Measure; + m_Measure = nullptr; + + delete m_Bitmap; + m_Bitmap = nullptr; + + std::vector::const_iterator iter = m_Icons.begin(); + for ( ; iter != m_Icons.end(); ++iter) + { + DestroyIcon((*iter)); + } + m_Icons.clear(); + + m_MeterType = TRAY_METER_TYPE_NONE; + + // Read tray settings + m_IconEnabled = parser.ReadBool(L"Rainmeter", L"TrayIcon", true); + if (m_IconEnabled) + { + const std::wstring& measureName = parser.ReadString(L"TrayMeasure", L"Measure", L""); + + if (!measureName.empty()) + { + ConfigParser* oldParser = Rainmeter::GetInstance().GetCurrentParser(); + Rainmeter::GetInstance().SetCurrentParser(&parser); + + m_Measure = Measure::Create(measureName.c_str(), nullptr, L"TrayMeasure"); + if (m_Measure) + { + m_Measure->ReadOptions(parser); + } + + Rainmeter::GetInstance().SetCurrentParser(oldParser); + } + + const WCHAR* type = parser.ReadString(L"TrayMeasure", L"TrayMeter", m_Measure ? L"HISTOGRAM" : L"NONE").c_str(); + if (_wcsicmp(type, L"NONE") == 0) + { + // Use main icon + } + else if (_wcsicmp(type, L"HISTOGRAM") == 0) + { + m_MeterType = TRAY_METER_TYPE_HISTOGRAM; + m_Color1 = parser.ReadColor(L"TrayMeasure", L"TrayColor1", Color::MakeARGB(255, 0, 100, 0)); + m_Color2 = parser.ReadColor(L"TrayMeasure", L"TrayColor2", Color::MakeARGB(255, 0, 255, 0)); + } + else if (_wcsicmp(type, L"BITMAP") == 0) + { + m_MeterType = TRAY_METER_TYPE_BITMAP; + + std::wstring imageName = parser.ReadString(L"TrayMeasure", L"TrayBitmap", L""); + + // Load the bitmaps if defined + if (!imageName.empty()) + { + imageName.insert(0, Rainmeter::GetInstance().GetSkinPath()); + const WCHAR* imagePath = imageName.c_str(); + if (_wcsicmp(imagePath + (imageName.size() - 4), L".ico") == 0) + { + int count = 1; + HICON hIcon = nullptr; + + // Load the icons + do + { + WCHAR buffer[MAX_PATH]; + _snwprintf_s(buffer, _TRUNCATE, imagePath, count++); + + hIcon = (HICON)LoadImage(nullptr, buffer, IMAGE_ICON, TRAYICON_SIZE, TRAYICON_SIZE, LR_LOADFROMFILE); + if (hIcon) m_Icons.push_back(hIcon); + if (wcscmp(imagePath, buffer) == 0) break; + } + while(hIcon != nullptr); + } + + if (m_Icons.empty()) + { + // No icons found so load as bitmap + delete m_Bitmap; + m_Bitmap = new Bitmap(imagePath); + Status status = m_Bitmap->GetLastStatus(); + if (Ok != status) + { + delete m_Bitmap; + m_Bitmap = nullptr; + LogWarningF(L"Bitmap image not found: %s", imagePath); + } + } + } + } + else + { + LogErrorF(L"No such TrayMeter: %s", type); + } + + TryAddTrayIcon(); + + if (m_Measure) + { + SetTimer(m_Window, TIMER_TRAYMEASURE, INTERVAL_TRAYMEASURE, nullptr); // Update the tray once per sec + } + } + else + { + RemoveTrayIcon(); + } +} + +LRESULT CALLBACK TrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + TrayWindow* tray = Rainmeter::GetInstance().GetTrayWindow(); + + switch (uMsg) + { + case WM_COMMAND: + switch (wParam) + { + case IDM_MANAGE: + DialogManage::Open(); + break; + + case IDM_ABOUT: + DialogAbout::Open(); + break; + + case IDM_SHOW_HELP: + CommandHandler::RunFile(RAINMETER_HELP); + break; + + case IDM_NEW_VERSION: + CommandHandler::RunFile(RAINMETER_OFFICIAL); + break; + + case IDM_REFRESH: + PostMessage(Rainmeter::GetInstance().GetWindow(), WM_RAINMETER_DELAYED_REFRESH_ALL, (WPARAM)nullptr, (LPARAM)nullptr); + break; + + case IDM_SHOWLOGFILE: + Rainmeter::GetInstance().ShowLogFile(); + break; + + case IDM_STARTLOG: + GetLogger().StartLogFile(); + break; + + case IDM_STOPLOG: + GetLogger().StopLogFile(); + break; + + case IDM_DELETELOGFILE: + GetLogger().DeleteLogFile(); + break; + + case IDM_DEBUGLOG: + Rainmeter::GetInstance().SetDebug(!Rainmeter::GetInstance().GetDebug()); + break; + + case IDM_DISABLEDRAG: + Rainmeter::GetInstance().SetDisableDragging(!Rainmeter::GetInstance().GetDisableDragging()); + break; + + case IDM_EDITCONFIG: + Rainmeter::GetInstance().EditSettings(); + break; + + case IDM_QUIT: + PostQuitMessage(0); + break; + + case IDM_OPENSKINSFOLDER: + Rainmeter::GetInstance().OpenSkinFolder(); + break; + + default: + { + UINT mID = wParam & 0x0FFFF; + + if (mID >= ID_THEME_FIRST && mID <= ID_THEME_LAST) + { + int pos = mID - ID_THEME_FIRST; + + const std::vector& layouts = Rainmeter::GetInstance().GetAllLayouts(); + if (pos >= 0 && pos < (int)layouts.size()) + { + Rainmeter::GetInstance().LoadLayout(layouts[pos]); + } + } + else if (mID >= ID_CONFIG_FIRST && mID <= ID_CONFIG_LAST) + { + Rainmeter::GetInstance().ToggleSkinWithID(mID); + } + else + { + // Forward the message to correct window + int index = (int)(wParam >> 16); + const std::map& windows = Rainmeter::GetInstance().GetAllMeterWindows(); + + if (index < (int)windows.size()) + { + std::map::const_iterator iter = windows.begin(); + for ( ; iter != windows.end(); ++iter) + { + --index; + if (index < 0) + { + MeterWindow* meterWindow = (*iter).second; + SendMessage(meterWindow->GetWindow(), WM_COMMAND, mID, 0); + break; + } + } + } + } + } + break; + } + break; // Don't send WM_COMMANDS any further + + case WM_TRAY_NOTIFYICON: + { + UINT uMouseMsg = (UINT)lParam; + LPCWSTR bang; + + // Check TrayExecute actions + switch (uMouseMsg) + { + case WM_MBUTTONDOWN: + bang = Rainmeter::GetInstance().GetTrayExecuteM().c_str(); + break; + + case WM_RBUTTONDOWN: + bang = Rainmeter::GetInstance().GetTrayExecuteR().c_str(); + break; + + case WM_MBUTTONDBLCLK: + bang = Rainmeter::GetInstance().GetTrayExecuteDM().c_str(); + break; + + case WM_RBUTTONDBLCLK: + bang = Rainmeter::GetInstance().GetTrayExecuteDR().c_str(); + break; + + default: + bang = L""; + break; + } + + if (*bang && + !IsCtrlKeyDown()) // Ctrl is pressed, so only run default action + { + Rainmeter::GetInstance().ExecuteCommand(bang, nullptr); + tray->m_TrayContextMenuEnabled = (uMouseMsg != WM_RBUTTONDOWN); + break; + } + + // Run default UI action + switch (uMouseMsg) + { + case WM_RBUTTONDOWN: + tray->m_TrayContextMenuEnabled = true; + break; + + case WM_RBUTTONUP: + if (tray->m_TrayContextMenuEnabled) + { + POINT pos = System::GetCursorPosition(); + Rainmeter::GetInstance().ShowContextMenu(pos, nullptr); + } + break; + + case WM_LBUTTONUP: + case WM_LBUTTONDBLCLK: + DialogManage::Open(); + break; + + case NIN_BALLOONUSERCLICK: + if (tray->m_Notification == TRAY_NOTIFICATION_WELCOME) + { + DialogManage::Open(); + } + else if (tray->m_Notification == TRAY_NOTIFICATION_UPDATE) + { + CommandHandler::RunFile(RAINMETER_OFFICIAL); + } + tray->m_Notification = TRAY_NOTIFICATION_NONE; + break; + + case NIN_BALLOONHIDE: + case NIN_BALLOONTIMEOUT: + tray->m_Notification = TRAY_NOTIFICATION_NONE; + break; + } + } + break; + + case WM_QUERY_RAINMETER: + if (IsWindow((HWND)lParam)) + { + auto sendCopyData = [&](const std::wstring& data) + { + COPYDATASTRUCT cds; + cds.dwData = wParam; + cds.cbData = (DWORD)((data.length() + 1) * sizeof(WCHAR)); + cds.lpData = (PVOID)data.c_str(); + SendMessage((HWND)lParam, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&cds); + }; + + switch (wParam) + { + case RAINMETER_QUERY_ID_SKINS_PATH: + sendCopyData(Rainmeter::GetInstance().GetSkinPath()); + return 0; + + case RAINMETER_QUERY_ID_SETTINGS_PATH: + sendCopyData(Rainmeter::GetInstance().GetSettingsPath()); + return 0; + + case RAINMETER_QUERY_ID_PLUGINS_PATH: + sendCopyData(Rainmeter::GetInstance().GetPluginPath()); + return 0; + + case RAINMETER_QUERY_ID_PROGRAM_PATH: + sendCopyData(Rainmeter::GetInstance().GetPath()); + return 0; + + case RAINMETER_QUERY_ID_LOG_PATH: + sendCopyData(GetLogger().GetLogFilePath()); + return 0; + + case RAINMETER_QUERY_ID_CONFIG_EDITOR: + sendCopyData(Rainmeter::GetInstance().GetSkinEditor()); + return 0; + + case RAINMETER_QUERY_ID_IS_DEBUGGING: + { + BOOL debug = Rainmeter::GetInstance().GetDebug(); + SendMessage((HWND)lParam, WM_QUERY_RAINMETER_RETURN, (WPARAM)hWnd, (LPARAM)debug); + } + return 0; + } + } + return 1; + + case WM_COPYDATA: + { + COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam; + if (cds->dwData == RAINMETER_QUERY_ID_SKIN_WINDOWHANDLE) + { + LPCWSTR folderPath = (LPCWSTR)cds->lpData; + MeterWindow* mw = Rainmeter::GetInstance().GetMeterWindow(folderPath); + return (mw) ? (LRESULT)mw->GetWindow() : 0; + } + } + return 1; + + case WM_TIMER: + if (wParam == TIMER_TRAYMEASURE) + { + if (tray->m_Measure) + { + tray->m_Measure->Update(); + tray->ModifyTrayIcon(tray->m_Measure->GetRelativeValue()); + } + } + else if (wParam == TIMER_ADDTRAYICON) + { + tray->CheckTrayIcon(); + } + break; + + case WM_DESTROY: + PostQuitMessage(0); + break; + + default: + if (uMsg == WM_TASKBARCREATED) + { + if (tray->IsTrayIconEnabled()) + { + tray->RemoveTrayIcon(); + tray->TryAddTrayIcon(); + } + } + return DefWindowProc(hWnd, uMsg, wParam, lParam); + } + + return 0; +} diff --git a/Library/TrayWindow.h b/Library/TrayWindow.h index 63f4f0fa..4407ec76 100644 --- a/Library/TrayWindow.h +++ b/Library/TrayWindow.h @@ -1,101 +1,101 @@ -/* - Copyright (C) 2004 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __TRAYWINDOW_H__ -#define __TRAYWINDOW_H__ - -#include -#include // For Gdiplus.h. -#include -#include - -#define WM_TRAY_NOTIFYICON WM_USER + 101 -#define TRAYICON_SIZE 16 - -enum TRAY_METER_TYPE -{ - TRAY_METER_TYPE_NONE, - TRAY_METER_TYPE_HISTOGRAM, - TRAY_METER_TYPE_BITMAP -}; - -class ConfigParser; -class Measure; - -class TrayWindow -{ -public: - TrayWindow(); - ~TrayWindow(); - - TrayWindow(const TrayWindow& other) = delete; - TrayWindow& operator=(TrayWindow other) = delete; - - void Initialize(); - - void ReadOptions(ConfigParser& parser); - HWND GetWindow() { return m_Window; } - bool IsTrayIconEnabled() { return m_IconEnabled; } - void SetTrayIcon(bool enabled); - - void ShowWelcomeNotification(); - void ShowUpdateNotification(const WCHAR* newVersion); - -protected: - static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - -private: - enum TRAY_NOTIFICATION - { - TRAY_NOTIFICATION_NONE, - TRAY_NOTIFICATION_WELCOME, - TRAY_NOTIFICATION_UPDATE - }; - - bool AddTrayIcon(); - bool IsTrayIconReady(); - void TryAddTrayIcon(); - void CheckTrayIcon(); - void RemoveTrayIcon(); - void ModifyTrayIcon(double value); - HICON CreateTrayIcon(double value); - - void ShowNotification(TRAY_NOTIFICATION id, const WCHAR* title, const WCHAR* text); - - HICON m_Icon; - HWND m_Window; - Measure* m_Measure; - - TRAY_METER_TYPE m_MeterType; - Gdiplus::Color m_Color1; - Gdiplus::Color m_Color2; - Gdiplus::Bitmap* m_Bitmap; - - std::vector m_Icons; - - double m_Values[TRAYICON_SIZE]; - int m_Pos; - - TRAY_NOTIFICATION m_Notification; - - bool m_TrayContextMenuEnabled; - - bool m_IconEnabled; -}; - -#endif +/* + Copyright (C) 2004 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __TRAYWINDOW_H__ +#define __TRAYWINDOW_H__ + +#include +#include // For Gdiplus.h. +#include +#include + +#define WM_TRAY_NOTIFYICON WM_USER + 101 +#define TRAYICON_SIZE 16 + +enum TRAY_METER_TYPE +{ + TRAY_METER_TYPE_NONE, + TRAY_METER_TYPE_HISTOGRAM, + TRAY_METER_TYPE_BITMAP +}; + +class ConfigParser; +class Measure; + +class TrayWindow +{ +public: + TrayWindow(); + ~TrayWindow(); + + TrayWindow(const TrayWindow& other) = delete; + TrayWindow& operator=(TrayWindow other) = delete; + + void Initialize(); + + void ReadOptions(ConfigParser& parser); + HWND GetWindow() { return m_Window; } + bool IsTrayIconEnabled() { return m_IconEnabled; } + void SetTrayIcon(bool enabled); + + void ShowWelcomeNotification(); + void ShowUpdateNotification(const WCHAR* newVersion); + +protected: + static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +private: + enum TRAY_NOTIFICATION + { + TRAY_NOTIFICATION_NONE, + TRAY_NOTIFICATION_WELCOME, + TRAY_NOTIFICATION_UPDATE + }; + + bool AddTrayIcon(); + bool IsTrayIconReady(); + void TryAddTrayIcon(); + void CheckTrayIcon(); + void RemoveTrayIcon(); + void ModifyTrayIcon(double value); + HICON CreateTrayIcon(double value); + + void ShowNotification(TRAY_NOTIFICATION id, const WCHAR* title, const WCHAR* text); + + HICON m_Icon; + HWND m_Window; + Measure* m_Measure; + + TRAY_METER_TYPE m_MeterType; + Gdiplus::Color m_Color1; + Gdiplus::Color m_Color2; + Gdiplus::Bitmap* m_Bitmap; + + std::vector m_Icons; + + double m_Values[TRAYICON_SIZE]; + int m_Pos; + + TRAY_NOTIFICATION m_Notification; + + bool m_TrayContextMenuEnabled; + + bool m_IconEnabled; +}; + +#endif diff --git a/Library/UpdateCheck.cpp b/Library/UpdateCheck.cpp index bf67db5b..bffdf565 100644 --- a/Library/UpdateCheck.cpp +++ b/Library/UpdateCheck.cpp @@ -1,97 +1,97 @@ -/* - Copyright (C) 2004 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Litestep.h" -#include "Rainmeter.h" -#include "TrayWindow.h" -#include "../Version.h" - -void CheckVersion(void* dummy) -{ - HINTERNET hRootHandle = InternetOpen( - L"Rainmeter", - INTERNET_OPEN_TYPE_PRECONFIG, - nullptr, - nullptr, - 0); - - if (hRootHandle == nullptr) - { - return; - } - - HINTERNET hUrlDump = InternetOpenUrl( - hRootHandle, L"http://rainmeter.github.io/rainmeter/release", nullptr, 0, INTERNET_FLAG_RESYNCHRONIZE, 0); - if (hUrlDump) - { - DWORD dwSize; - char urlData[16] = {0}; - if (InternetReadFile(hUrlDump, (LPVOID)urlData, sizeof(urlData) - 1, &dwSize)) - { - auto parseVersion = [](const WCHAR* str)->int - { - int version = _wtoi(str) * 1000000; - const WCHAR* pos = wcschr(str, L'.'); - if (pos) - { - ++pos; // Skip . - version += _wtoi(pos) * 1000; - - pos = wcschr(pos, '.'); - if (pos) - { - ++pos; // Skip . - version += _wtoi(pos); - } - } - return version; - }; - - std::wstring tmpSz = StringUtil::Widen(urlData); - const WCHAR* version = tmpSz.c_str(); - - int availableVersion = parseVersion(version); - if (availableVersion > RAINMETER_VERSION || - (revision_beta && availableVersion == RAINMETER_VERSION)) - { - Rainmeter::GetInstance().SetNewVersion(); - - WCHAR buffer[32]; - const WCHAR* dataFile = Rainmeter::GetInstance().GetDataFile().c_str(); - GetPrivateProfileString(L"Rainmeter", L"LastCheck", L"0", buffer, _countof(buffer), dataFile); - - // Show tray notification only once per new version - int lastVersion = parseVersion(buffer); - if (availableVersion > lastVersion) - { - Rainmeter::GetInstance().GetTrayWindow()->ShowUpdateNotification(version); - WritePrivateProfileString(L"Rainmeter", L"LastCheck", version, dataFile); - } - } - } - InternetCloseHandle(hUrlDump); - } - - InternetCloseHandle(hRootHandle); -} - -void CheckUpdate() -{ - _beginthread(CheckVersion, 0, nullptr); -} +/* + Copyright (C) 2004 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Litestep.h" +#include "Rainmeter.h" +#include "TrayWindow.h" +#include "../Version.h" + +void CheckVersion(void* dummy) +{ + HINTERNET hRootHandle = InternetOpen( + L"Rainmeter", + INTERNET_OPEN_TYPE_PRECONFIG, + nullptr, + nullptr, + 0); + + if (hRootHandle == nullptr) + { + return; + } + + HINTERNET hUrlDump = InternetOpenUrl( + hRootHandle, L"http://rainmeter.github.io/rainmeter/release", nullptr, 0, INTERNET_FLAG_RESYNCHRONIZE, 0); + if (hUrlDump) + { + DWORD dwSize; + char urlData[16] = {0}; + if (InternetReadFile(hUrlDump, (LPVOID)urlData, sizeof(urlData) - 1, &dwSize)) + { + auto parseVersion = [](const WCHAR* str)->int + { + int version = _wtoi(str) * 1000000; + const WCHAR* pos = wcschr(str, L'.'); + if (pos) + { + ++pos; // Skip . + version += _wtoi(pos) * 1000; + + pos = wcschr(pos, '.'); + if (pos) + { + ++pos; // Skip . + version += _wtoi(pos); + } + } + return version; + }; + + std::wstring tmpSz = StringUtil::Widen(urlData); + const WCHAR* version = tmpSz.c_str(); + + int availableVersion = parseVersion(version); + if (availableVersion > RAINMETER_VERSION || + (revision_beta && availableVersion == RAINMETER_VERSION)) + { + Rainmeter::GetInstance().SetNewVersion(); + + WCHAR buffer[32]; + const WCHAR* dataFile = Rainmeter::GetInstance().GetDataFile().c_str(); + GetPrivateProfileString(L"Rainmeter", L"LastCheck", L"0", buffer, _countof(buffer), dataFile); + + // Show tray notification only once per new version + int lastVersion = parseVersion(buffer); + if (availableVersion > lastVersion) + { + Rainmeter::GetInstance().GetTrayWindow()->ShowUpdateNotification(version); + WritePrivateProfileString(L"Rainmeter", L"LastCheck", version, dataFile); + } + } + } + InternetCloseHandle(hUrlDump); + } + + InternetCloseHandle(hRootHandle); +} + +void CheckUpdate() +{ + _beginthread(CheckVersion, 0, nullptr); +} diff --git a/Library/UpdateCheck.h b/Library/UpdateCheck.h index 08908dc5..9a63c2f6 100644 --- a/Library/UpdateCheck.h +++ b/Library/UpdateCheck.h @@ -1,24 +1,24 @@ -/* - Copyright (C) 2004 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __UPDATE_CHECK_H__ -#define __UPDATE_CHECK_H__ - -void CheckUpdate(); - -#endif +/* + Copyright (C) 2004 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __UPDATE_CHECK_H__ +#define __UPDATE_CHECK_H__ + +void CheckUpdate(); + +#endif diff --git a/Library/lua/LuaManager.cpp b/Library/lua/LuaManager.cpp index 4f9c071a..83b30558 100644 --- a/Library/lua/LuaManager.cpp +++ b/Library/lua/LuaManager.cpp @@ -1,103 +1,103 @@ -/* - Copyright (C) 2010 Matt King, Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../../Common/StringUtil.h" -#include "LuaManager.h" -#include "../Logger.h" - -int LuaManager::c_RefCount = 0; -lua_State* LuaManager::c_State = 0; - -std::vector LuaManager::c_UnicodeStateStack; - -void LuaManager::Initialize() -{ - if (c_State == nullptr) - { - // Initialize Lua - c_State = luaL_newstate(); - - luaL_openlibs(c_State); - - // Register custom types and functions - RegisterGlobal(c_State); - RegisterMeasure(c_State); - RegisterMeter(c_State); - RegisterMeterWindow(c_State); - } - - ++c_RefCount; -} - -void LuaManager::Finalize() -{ - if (c_RefCount > 0) - { - --c_RefCount; - } - - if (c_RefCount == 0 && c_State != nullptr) - { - lua_close(c_State); - c_State = nullptr; - } -} - -void LuaManager::ReportErrors(const std::wstring& file) -{ - lua_State* L = c_State; - const char* error = lua_tostring(L, -1); - lua_pop(L, 1); - - // Skip "[string ...]". - const char* pos = strchr(error, ':'); - if (pos) - { - error = pos; - } - - std::wstring str(file, file.find_last_of(L'\\') + 1); - str += IsUnicodeState() ? StringUtil::WidenUTF8(error) : StringUtil::Widen(error); - LogErrorF(L"Script: %s", str.c_str()); -} - -void LuaManager::PushWide(const WCHAR* str) -{ - lua_State* L = c_State; - const std::string narrowStr = IsUnicodeState() ? - StringUtil::NarrowUTF8(str) : StringUtil::Narrow(str); - lua_pushlstring(L, narrowStr.c_str(), narrowStr.length()); -} - -void LuaManager::PushWide(const std::wstring& str) -{ - lua_State* L = c_State; - const std::string narrowStr = IsUnicodeState() ? - StringUtil::NarrowUTF8(str) : StringUtil::Narrow(str); - lua_pushlstring(L, narrowStr.c_str(), narrowStr.length()); -} - -std::wstring LuaManager::ToWide(int narg) -{ - lua_State* L = c_State; - size_t strLen = 0; - const char* str = lua_tolstring(L, narg, &strLen); - return IsUnicodeState() ? - StringUtil::WidenUTF8(str, (int)strLen) : StringUtil::Widen(str, (int)strLen); -} +/* + Copyright (C) 2010 Matt King, Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../../Common/StringUtil.h" +#include "LuaManager.h" +#include "../Logger.h" + +int LuaManager::c_RefCount = 0; +lua_State* LuaManager::c_State = 0; + +std::vector LuaManager::c_UnicodeStateStack; + +void LuaManager::Initialize() +{ + if (c_State == nullptr) + { + // Initialize Lua + c_State = luaL_newstate(); + + luaL_openlibs(c_State); + + // Register custom types and functions + RegisterGlobal(c_State); + RegisterMeasure(c_State); + RegisterMeter(c_State); + RegisterMeterWindow(c_State); + } + + ++c_RefCount; +} + +void LuaManager::Finalize() +{ + if (c_RefCount > 0) + { + --c_RefCount; + } + + if (c_RefCount == 0 && c_State != nullptr) + { + lua_close(c_State); + c_State = nullptr; + } +} + +void LuaManager::ReportErrors(const std::wstring& file) +{ + lua_State* L = c_State; + const char* error = lua_tostring(L, -1); + lua_pop(L, 1); + + // Skip "[string ...]". + const char* pos = strchr(error, ':'); + if (pos) + { + error = pos; + } + + std::wstring str(file, file.find_last_of(L'\\') + 1); + str += IsUnicodeState() ? StringUtil::WidenUTF8(error) : StringUtil::Widen(error); + LogErrorF(L"Script: %s", str.c_str()); +} + +void LuaManager::PushWide(const WCHAR* str) +{ + lua_State* L = c_State; + const std::string narrowStr = IsUnicodeState() ? + StringUtil::NarrowUTF8(str) : StringUtil::Narrow(str); + lua_pushlstring(L, narrowStr.c_str(), narrowStr.length()); +} + +void LuaManager::PushWide(const std::wstring& str) +{ + lua_State* L = c_State; + const std::string narrowStr = IsUnicodeState() ? + StringUtil::NarrowUTF8(str) : StringUtil::Narrow(str); + lua_pushlstring(L, narrowStr.c_str(), narrowStr.length()); +} + +std::wstring LuaManager::ToWide(int narg) +{ + lua_State* L = c_State; + size_t strLen = 0; + const char* str = lua_tolstring(L, narg, &strLen); + return IsUnicodeState() ? + StringUtil::WidenUTF8(str, (int)strLen) : StringUtil::Widen(str, (int)strLen); +} diff --git a/Library/lua/LuaManager.h b/Library/lua/LuaManager.h index 593cd583..cbcf9b9d 100644 --- a/Library/lua/LuaManager.h +++ b/Library/lua/LuaManager.h @@ -1,72 +1,72 @@ -/* - Copyright (C) 2010 Matt King, Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __LUAMANAGER_H__ -#define __LUAMANAGER_H__ - -extern "C" -{ -#include "lua.h" -#include "lualib.h" -#include "lauxlib.h" -} - -#include - -class LuaManager -{ -public: - class ScopedLuaState - { - public: - ScopedLuaState(bool unicode) { LuaManager::c_UnicodeStateStack.push_back(unicode); } - ~ScopedLuaState() { LuaManager::c_UnicodeStateStack.pop_back(); } - operator lua_State*() { return LuaManager::c_State; } - }; - - static void Initialize(); - static void Finalize(); - - static ScopedLuaState GetState(bool unicode) { return ScopedLuaState(unicode); } - - static bool IsUnicodeState() { return c_UnicodeStateStack.back(); } - - static void ReportErrors(const std::wstring& file); - - static void PushWide(const WCHAR* str); - static void PushWide(const std::wstring& str); - static std::wstring ToWide(int narg); - -protected: - static int c_RefCount; - static lua_State* c_State; - -private: - static void RegisterGlobal(lua_State* L); - static void RegisterMeasure(lua_State* L); - static void RegisterMeter(lua_State* L); - static void RegisterMeterWindow(lua_State* L); - static void RegisterMeterString(lua_State* L); - - // If the back of the vector is |true|, Lua strings converted to/from as if they were encoded - // in UTF-8. Otherwise Lua strings are treated as if they are encoded in the default system - // encoding. - static std::vector c_UnicodeStateStack; -}; - -#endif +/* + Copyright (C) 2010 Matt King, Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __LUAMANAGER_H__ +#define __LUAMANAGER_H__ + +extern "C" +{ +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +} + +#include + +class LuaManager +{ +public: + class ScopedLuaState + { + public: + ScopedLuaState(bool unicode) { LuaManager::c_UnicodeStateStack.push_back(unicode); } + ~ScopedLuaState() { LuaManager::c_UnicodeStateStack.pop_back(); } + operator lua_State*() { return LuaManager::c_State; } + }; + + static void Initialize(); + static void Finalize(); + + static ScopedLuaState GetState(bool unicode) { return ScopedLuaState(unicode); } + + static bool IsUnicodeState() { return c_UnicodeStateStack.back(); } + + static void ReportErrors(const std::wstring& file); + + static void PushWide(const WCHAR* str); + static void PushWide(const std::wstring& str); + static std::wstring ToWide(int narg); + +protected: + static int c_RefCount; + static lua_State* c_State; + +private: + static void RegisterGlobal(lua_State* L); + static void RegisterMeasure(lua_State* L); + static void RegisterMeter(lua_State* L); + static void RegisterMeterWindow(lua_State* L); + static void RegisterMeterString(lua_State* L); + + // If the back of the vector is |true|, Lua strings converted to/from as if they were encoded + // in UTF-8. Otherwise Lua strings are treated as if they are encoded in the default system + // encoding. + static std::vector c_UnicodeStateStack; +}; + +#endif diff --git a/Library/lua/LuaModifications.txt b/Library/lua/LuaModifications.txt index 9634b12d..eaeeb2c6 100644 --- a/Library/lua/LuaModifications.txt +++ b/Library/lua/LuaModifications.txt @@ -1,15 +1,15 @@ -lbaselib.c -- Commented out collectgarbage, getfenv, print, and setfenv functions in base_funcs array -- Commented out luaL_register for coroutine library - -liolib.c -- Commented out popen in iolib array -- Commented out createstdfile calls for stdin/stdout/stderr in luaopen_io -- Commented out popen related calls in luaopen_io - -linit.c -- Commented out debug and package libraries - -loslib.c -- Commented out exit function in syslib array +lbaselib.c +- Commented out collectgarbage, getfenv, print, and setfenv functions in base_funcs array +- Commented out luaL_register for coroutine library + +liolib.c +- Commented out popen in iolib array +- Commented out createstdfile calls for stdin/stdout/stderr in luaopen_io +- Commented out popen related calls in luaopen_io + +linit.c +- Commented out debug and package libraries + +loslib.c +- Commented out exit function in syslib array - Changed os_setlocale() to noop and to always return nil \ No newline at end of file diff --git a/Library/lua/LuaScript.cpp b/Library/lua/LuaScript.cpp index 590a35ce..25cb1968 100644 --- a/Library/lua/LuaScript.cpp +++ b/Library/lua/LuaScript.cpp @@ -1,261 +1,261 @@ -/* - Copyright (C) 2010 Matt King, Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../../Common/StringUtil.h" -#include "LuaScript.h" -#include "LuaManager.h" - -/* -** The constructor -** -*/ -LuaScript::LuaScript() : - m_Ref(LUA_NOREF), - m_Unicode(false) -{ -} - -/* -** The destructor -** -*/ -LuaScript::~LuaScript() -{ - Uninitialize(); -} - -bool LuaScript::Initialize(const std::wstring& scriptFile) -{ - assert(!IsInitialized()); - - FILE* file = _wfopen(scriptFile.c_str(), L"rb"); - if (!file) return false; - - fseek(file, 0, SEEK_END); - const long fileSize = ftell(file); - BYTE* fileData = new BYTE[fileSize]; - fseek(file, 0, SEEK_SET); - fread(fileData, fileSize, 1, file); - fclose(file); - file = nullptr; - - auto L = GetState(); - bool scriptLoaded = false; - - // Treat the script as Unicode if it has the UTF-16 LE BOM. - m_Unicode = fileSize > 2 && fileData[0] == 0xFF && fileData[1] == 0xFE; - if (m_Unicode) - { - const std::string utf8Data = - StringUtil::NarrowUTF8((WCHAR*)(fileData + 2), (fileSize - 2) / sizeof(WCHAR)); - scriptLoaded = luaL_loadbuffer(L, utf8Data.c_str(), utf8Data.length(), "") == 0; - } - else - { - scriptLoaded = luaL_loadbuffer(L, (char*)fileData, fileSize, "") == 0; - } - - delete [] fileData; - - if (scriptLoaded) - { - // Create the table this script will reside in - lua_newtable(L); - - // Create the metatable that will store the global table - lua_createtable(L, 0, 1); - - // Push the global teble - lua_pushvalue(L, LUA_GLOBALSINDEX); - - // Set the __index of the table to be the global table - lua_setfield(L, -2, "__index"); - - // Set the metatable for the script's table - lua_setmetatable(L, -2); - - // Put the table into the global table - m_Ref = luaL_ref(L, LUA_GLOBALSINDEX); - - lua_rawgeti(L, LUA_GLOBALSINDEX, m_Ref); - - // Set the environment for the function to be run in to be the table that - // has been created for the script/ - lua_setfenv(L, -2); - - // Execute the Lua script - int result = lua_pcall(L, 0, 0, 0); - if (result == 0) - { - m_File = scriptFile; - return true; - } - else - { - LuaManager::ReportErrors(scriptFile); - Uninitialize(); - } - } - else - { - LuaManager::ReportErrors(scriptFile); - } - - return false; -} - -void LuaScript::Uninitialize() -{ - auto L = GetState(); - - if (m_Ref != LUA_NOREF) - { - luaL_unref(L, LUA_GLOBALSINDEX, m_Ref); - m_Ref = LUA_NOREF; - m_File.clear(); - } -} - -/* -** Checks if given function is defined in the script file. -** -*/ -bool LuaScript::IsFunction(const char* funcName) -{ - auto L = GetState(); - bool bExists = false; - - if (IsInitialized()) - { - // Push our table onto the stack - lua_rawgeti(L, LUA_GLOBALSINDEX, m_Ref); - - // Push the function onto the stack - lua_getfield(L, -1, funcName); - - bExists = lua_isfunction(L, -1); - - // Pop both the table and the function off the stack. - lua_pop(L, 2); - } - - return bExists; -} - -/* -** Runs given function in script file. -** -*/ -void LuaScript::RunFunction(const char* funcName) -{ - auto L = GetState(); - - if (IsInitialized()) - { - // Push our table onto the stack - lua_rawgeti(L, LUA_GLOBALSINDEX, m_Ref); - - // Push the function onto the stack - lua_getfield(L, -1, funcName); - - if (lua_pcall(L, 0, 0, 0)) - { - LuaManager::ReportErrors(m_File); - } - - lua_pop(L, 1); - } -} - -/* -** Runs given function in script file and stores the retruned number or string. -** -*/ -int LuaScript::RunFunctionWithReturn(const char* funcName, double& numValue, std::wstring& strValue) -{ - auto L = GetState(); - int type = LUA_TNIL; - - if (IsInitialized()) - { - // Push our table onto the stack - lua_rawgeti(L, LUA_GLOBALSINDEX, m_Ref); - - // Push the function onto the stack - lua_getfield(L, -1, funcName); - - if (lua_pcall(L, 0, 1, 0)) - { - LuaManager::ReportErrors(m_File); - lua_pop(L, 1); - } - else - { - type = lua_type(L, -1); - if (type == LUA_TNUMBER) - { - numValue = lua_tonumber(L, -1); - } - else if (type == LUA_TSTRING) - { - size_t strLen = 0; - const char* str = lua_tolstring(L, -1, &strLen); - strValue = m_Unicode ? - StringUtil::WidenUTF8(str, (int)strLen) : StringUtil::Widen(str, (int)strLen); - numValue = strtod(str, nullptr); - } - - lua_pop(L, 2); - } - } - - return type; -} - -/* -** Runs given string in the context of the script file. -** -*/ -void LuaScript::RunString(const std::wstring& str) -{ - auto L = GetState(); - - if (IsInitialized()) - { - const std::string narrowStr = m_Unicode ? - StringUtil::NarrowUTF8(str) : StringUtil::Narrow(str); - - // Load the string as a Lua chunk - if (luaL_loadstring(L, narrowStr.c_str())) - { - LuaManager::ReportErrors(m_File); - } - - // Push our table onto the stack - lua_rawgeti(L, LUA_GLOBALSINDEX, m_Ref); - - // Pop table and set the environment of the loaded chunk to it - lua_setfenv(L, -2); - - if (lua_pcall(L, 0, 0, 0)) - { - LuaManager::ReportErrors(m_File); - } - } -} +/* + Copyright (C) 2010 Matt King, Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../../Common/StringUtil.h" +#include "LuaScript.h" +#include "LuaManager.h" + +/* +** The constructor +** +*/ +LuaScript::LuaScript() : + m_Ref(LUA_NOREF), + m_Unicode(false) +{ +} + +/* +** The destructor +** +*/ +LuaScript::~LuaScript() +{ + Uninitialize(); +} + +bool LuaScript::Initialize(const std::wstring& scriptFile) +{ + assert(!IsInitialized()); + + FILE* file = _wfopen(scriptFile.c_str(), L"rb"); + if (!file) return false; + + fseek(file, 0, SEEK_END); + const long fileSize = ftell(file); + BYTE* fileData = new BYTE[fileSize]; + fseek(file, 0, SEEK_SET); + fread(fileData, fileSize, 1, file); + fclose(file); + file = nullptr; + + auto L = GetState(); + bool scriptLoaded = false; + + // Treat the script as Unicode if it has the UTF-16 LE BOM. + m_Unicode = fileSize > 2 && fileData[0] == 0xFF && fileData[1] == 0xFE; + if (m_Unicode) + { + const std::string utf8Data = + StringUtil::NarrowUTF8((WCHAR*)(fileData + 2), (fileSize - 2) / sizeof(WCHAR)); + scriptLoaded = luaL_loadbuffer(L, utf8Data.c_str(), utf8Data.length(), "") == 0; + } + else + { + scriptLoaded = luaL_loadbuffer(L, (char*)fileData, fileSize, "") == 0; + } + + delete [] fileData; + + if (scriptLoaded) + { + // Create the table this script will reside in + lua_newtable(L); + + // Create the metatable that will store the global table + lua_createtable(L, 0, 1); + + // Push the global teble + lua_pushvalue(L, LUA_GLOBALSINDEX); + + // Set the __index of the table to be the global table + lua_setfield(L, -2, "__index"); + + // Set the metatable for the script's table + lua_setmetatable(L, -2); + + // Put the table into the global table + m_Ref = luaL_ref(L, LUA_GLOBALSINDEX); + + lua_rawgeti(L, LUA_GLOBALSINDEX, m_Ref); + + // Set the environment for the function to be run in to be the table that + // has been created for the script/ + lua_setfenv(L, -2); + + // Execute the Lua script + int result = lua_pcall(L, 0, 0, 0); + if (result == 0) + { + m_File = scriptFile; + return true; + } + else + { + LuaManager::ReportErrors(scriptFile); + Uninitialize(); + } + } + else + { + LuaManager::ReportErrors(scriptFile); + } + + return false; +} + +void LuaScript::Uninitialize() +{ + auto L = GetState(); + + if (m_Ref != LUA_NOREF) + { + luaL_unref(L, LUA_GLOBALSINDEX, m_Ref); + m_Ref = LUA_NOREF; + m_File.clear(); + } +} + +/* +** Checks if given function is defined in the script file. +** +*/ +bool LuaScript::IsFunction(const char* funcName) +{ + auto L = GetState(); + bool bExists = false; + + if (IsInitialized()) + { + // Push our table onto the stack + lua_rawgeti(L, LUA_GLOBALSINDEX, m_Ref); + + // Push the function onto the stack + lua_getfield(L, -1, funcName); + + bExists = lua_isfunction(L, -1); + + // Pop both the table and the function off the stack. + lua_pop(L, 2); + } + + return bExists; +} + +/* +** Runs given function in script file. +** +*/ +void LuaScript::RunFunction(const char* funcName) +{ + auto L = GetState(); + + if (IsInitialized()) + { + // Push our table onto the stack + lua_rawgeti(L, LUA_GLOBALSINDEX, m_Ref); + + // Push the function onto the stack + lua_getfield(L, -1, funcName); + + if (lua_pcall(L, 0, 0, 0)) + { + LuaManager::ReportErrors(m_File); + } + + lua_pop(L, 1); + } +} + +/* +** Runs given function in script file and stores the retruned number or string. +** +*/ +int LuaScript::RunFunctionWithReturn(const char* funcName, double& numValue, std::wstring& strValue) +{ + auto L = GetState(); + int type = LUA_TNIL; + + if (IsInitialized()) + { + // Push our table onto the stack + lua_rawgeti(L, LUA_GLOBALSINDEX, m_Ref); + + // Push the function onto the stack + lua_getfield(L, -1, funcName); + + if (lua_pcall(L, 0, 1, 0)) + { + LuaManager::ReportErrors(m_File); + lua_pop(L, 1); + } + else + { + type = lua_type(L, -1); + if (type == LUA_TNUMBER) + { + numValue = lua_tonumber(L, -1); + } + else if (type == LUA_TSTRING) + { + size_t strLen = 0; + const char* str = lua_tolstring(L, -1, &strLen); + strValue = m_Unicode ? + StringUtil::WidenUTF8(str, (int)strLen) : StringUtil::Widen(str, (int)strLen); + numValue = strtod(str, nullptr); + } + + lua_pop(L, 2); + } + } + + return type; +} + +/* +** Runs given string in the context of the script file. +** +*/ +void LuaScript::RunString(const std::wstring& str) +{ + auto L = GetState(); + + if (IsInitialized()) + { + const std::string narrowStr = m_Unicode ? + StringUtil::NarrowUTF8(str) : StringUtil::Narrow(str); + + // Load the string as a Lua chunk + if (luaL_loadstring(L, narrowStr.c_str())) + { + LuaManager::ReportErrors(m_File); + } + + // Push our table onto the stack + lua_rawgeti(L, LUA_GLOBALSINDEX, m_Ref); + + // Pop table and set the environment of the loaded chunk to it + lua_setfenv(L, -2); + + if (lua_pcall(L, 0, 0, 0)) + { + LuaManager::ReportErrors(m_File); + } + } +} diff --git a/Library/lua/LuaScript.h b/Library/lua/LuaScript.h index af47a87f..43e9ee81 100644 --- a/Library/lua/LuaScript.h +++ b/Library/lua/LuaScript.h @@ -1,52 +1,52 @@ -/* - Copyright (C) 2010 Matt King, Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __LUASCRIPT_H__ -#define __LUASCRIPT_H__ - -#include "LuaManager.h" - -class LuaScript -{ -public: - LuaScript(); - ~LuaScript(); - - bool Initialize(const std::wstring& scriptFile); - void Uninitialize(); - bool IsInitialized() { return m_Ref != LUA_NOREF; } - - const std::wstring& GetFile() { return m_File; } - int GetRef() { return m_Ref; } - bool IsUnicode() const { return m_Unicode; } - - LuaManager::ScopedLuaState GetState() { return LuaManager::GetState(m_Unicode); } - - bool IsFunction(const char* funcName); - void RunFunction(const char* funcName); - int RunFunctionWithReturn(const char* funcName, double& numValue, std::wstring& strValue); - void RunString(const std::wstring& str); - -protected: - std::wstring m_File; - int m_Ref; - bool m_Unicode; -}; - -#endif - +/* + Copyright (C) 2010 Matt King, Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __LUASCRIPT_H__ +#define __LUASCRIPT_H__ + +#include "LuaManager.h" + +class LuaScript +{ +public: + LuaScript(); + ~LuaScript(); + + bool Initialize(const std::wstring& scriptFile); + void Uninitialize(); + bool IsInitialized() { return m_Ref != LUA_NOREF; } + + const std::wstring& GetFile() { return m_File; } + int GetRef() { return m_Ref; } + bool IsUnicode() const { return m_Unicode; } + + LuaManager::ScopedLuaState GetState() { return LuaManager::GetState(m_Unicode); } + + bool IsFunction(const char* funcName); + void RunFunction(const char* funcName); + int RunFunctionWithReturn(const char* funcName, double& numValue, std::wstring& strValue); + void RunString(const std::wstring& str); + +protected: + std::wstring m_File; + int m_Ref; + bool m_Unicode; +}; + +#endif + diff --git a/Library/lua/glue/LuaGlobal.cpp b/Library/lua/glue/LuaGlobal.cpp index ccfa3e64..17a89006 100644 --- a/Library/lua/glue/LuaGlobal.cpp +++ b/Library/lua/glue/LuaGlobal.cpp @@ -1,81 +1,81 @@ -/* - Copyright (C) 2010 Matt King, Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../LuaManager.h" -#include "../../Logger.h" -#include "../../../Common/StringUtil.h" - -static int Print(lua_State* L) -{ - // Modified version of luaB_print() - std::string message; - - int n = lua_gettop(L); // Number of arguments - lua_getglobal(L, "tostring"); - - for (int i = 1; i <= n; ++i) - { - lua_pushvalue(L, -1); // Function to be called - lua_pushvalue(L, i); // Value to print - lua_call(L, 1, 1); - - // Get result - const char* s = lua_tostring(L, -1); - if (s == nullptr) - { - return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("print")); - } - - if (i > 1) - { - // About dialog List View doesn't like tabs, just use 4 spaces instead - message += " "; - } - - message += s; - - // Pop result - lua_pop(L, 1); - } - - LogDebug(LuaManager::IsUnicodeState() ? - StringUtil::WidenUTF8(message).c_str() : StringUtil::Widen(message).c_str()); - return 0; -} - -static int tolua_cast(lua_State* L) -{ - // Simply push first argument onto stack. - lua_pushvalue(L, 1); - return 1; -} - -void LuaManager::RegisterGlobal(lua_State* L) -{ - lua_register(L, "print", Print); - - // Register tolua.cast() for backwards compatibility. - const luaL_Reg toluaFuncs[] = - { - { "cast", tolua_cast }, - { nullptr, nullptr } - }; - - luaL_register(L, "tolua", toluaFuncs); -} +/* + Copyright (C) 2010 Matt King, Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../LuaManager.h" +#include "../../Logger.h" +#include "../../../Common/StringUtil.h" + +static int Print(lua_State* L) +{ + // Modified version of luaB_print() + std::string message; + + int n = lua_gettop(L); // Number of arguments + lua_getglobal(L, "tostring"); + + for (int i = 1; i <= n; ++i) + { + lua_pushvalue(L, -1); // Function to be called + lua_pushvalue(L, i); // Value to print + lua_call(L, 1, 1); + + // Get result + const char* s = lua_tostring(L, -1); + if (s == nullptr) + { + return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("print")); + } + + if (i > 1) + { + // About dialog List View doesn't like tabs, just use 4 spaces instead + message += " "; + } + + message += s; + + // Pop result + lua_pop(L, 1); + } + + LogDebug(LuaManager::IsUnicodeState() ? + StringUtil::WidenUTF8(message).c_str() : StringUtil::Widen(message).c_str()); + return 0; +} + +static int tolua_cast(lua_State* L) +{ + // Simply push first argument onto stack. + lua_pushvalue(L, 1); + return 1; +} + +void LuaManager::RegisterGlobal(lua_State* L) +{ + lua_register(L, "print", Print); + + // Register tolua.cast() for backwards compatibility. + const luaL_Reg toluaFuncs[] = + { + { "cast", tolua_cast }, + { nullptr, nullptr } + }; + + luaL_register(L, "tolua", toluaFuncs); +} diff --git a/Library/lua/glue/LuaMeasure.cpp b/Library/lua/glue/LuaMeasure.cpp index dc6557e6..4b8eb436 100644 --- a/Library/lua/glue/LuaMeasure.cpp +++ b/Library/lua/glue/LuaMeasure.cpp @@ -1,158 +1,158 @@ -/* - Copyright (C) 2010 Matt King, Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../LuaManager.h" -#include "../../Measure.h" -#include "../../MeterWindow.h" - -#define DECLARE_SELF(L) \ - void* selfData = lua_touserdata(L, 1); \ - if (!selfData) return 0; \ - Measure* self = *(Measure**)selfData; - -static int GetName(lua_State* L) -{ - DECLARE_SELF(L) - LuaManager::PushWide(self->GetName()); - - return 1; -} - -static int GetOption(lua_State* L) -{ - DECLARE_SELF(L) - MeterWindow* meterWindow = self->GetMeterWindow(); - ConfigParser& parser = meterWindow->GetParser(); - - const std::wstring section = LuaManager::ToWide(2); - const std::wstring defValue = LuaManager::ToWide(3); - const std::wstring& value = - parser.ReadString(self->GetName(), section.c_str(), defValue.c_str()); - LuaManager::PushWide(value); - return 1; -} - -static int GetNumberOption(lua_State* L) -{ - DECLARE_SELF(L) - MeterWindow* meterWindow = self->GetMeterWindow(); - ConfigParser& parser = meterWindow->GetParser(); - - std::wstring strTmp = LuaManager::ToWide(2); - double value = parser.ReadFloat(self->GetName(), strTmp.c_str(), lua_tonumber(L, 3)); - - lua_pushnumber(L, value); - return 1; -} - -static int Disable(lua_State* L) -{ - DECLARE_SELF(L) - self->Disable(); - - return 0; -} - -static int Enable(lua_State* L) -{ - DECLARE_SELF(L) - self->Enable(); - - return 0; -} - -static int GetValue(lua_State* L) -{ - DECLARE_SELF(L) - lua_pushnumber(L, self->GetValue()); - - return 1; -} - -static int GetRelativeValue(lua_State* L) -{ - DECLARE_SELF(L) - lua_pushnumber(L, self->GetRelativeValue()); - - return 1; -} - -static int GetValueRange(lua_State* L) -{ - DECLARE_SELF(L) - lua_pushnumber(L, self->GetValueRange()); - - return 1; -} - -static int GetMinValue(lua_State* L) -{ - DECLARE_SELF(L) - lua_pushnumber(L, self->GetMinValue()); - - return 1; -} - -static int GetMaxValue(lua_State* L) -{ - DECLARE_SELF(L) - lua_pushnumber(L, self->GetMaxValue()); - - return 1; -} - -static int GetStringValue(lua_State* L) -{ - DECLARE_SELF(L) - - int top = lua_gettop(L); - AUTOSCALE autoScale = (top > 1) ? (AUTOSCALE)(int)lua_tonumber(L, 2) : AUTOSCALE_OFF; - double scale = (top > 2) ? lua_tonumber(L, 3) : 1.0; - int decimals = (int)lua_tonumber(L, 4); - bool percentual = lua_toboolean(L, 5) != 0; - - const WCHAR* val = self->GetStringOrFormattedValue(autoScale, scale, decimals, percentual); - LuaManager::PushWide(val); - - return 1; -} - -void LuaManager::RegisterMeasure(lua_State* L) -{ - const luaL_Reg functions[] = - { - { "GetName", GetName }, - { "GetOption", GetOption }, - { "GetNumberOption", GetNumberOption }, - { "Disable", Disable }, - { "Enable", Enable }, - { "GetValue", GetValue }, - { "GetRelativeValue", GetRelativeValue }, - { "GetValueRange", GetValueRange }, - { "GetMinValue", GetMinValue }, - { "GetMaxValue", GetMaxValue }, - { "GetStringValue", GetStringValue }, - { nullptr, nullptr } - }; - - luaL_register(L, "Measure", functions); - lua_pushvalue(L, -1); - lua_setfield(L, -2, "__index"); - lua_pop(L, 1); -} +/* + Copyright (C) 2010 Matt King, Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../LuaManager.h" +#include "../../Measure.h" +#include "../../MeterWindow.h" + +#define DECLARE_SELF(L) \ + void* selfData = lua_touserdata(L, 1); \ + if (!selfData) return 0; \ + Measure* self = *(Measure**)selfData; + +static int GetName(lua_State* L) +{ + DECLARE_SELF(L) + LuaManager::PushWide(self->GetName()); + + return 1; +} + +static int GetOption(lua_State* L) +{ + DECLARE_SELF(L) + MeterWindow* meterWindow = self->GetMeterWindow(); + ConfigParser& parser = meterWindow->GetParser(); + + const std::wstring section = LuaManager::ToWide(2); + const std::wstring defValue = LuaManager::ToWide(3); + const std::wstring& value = + parser.ReadString(self->GetName(), section.c_str(), defValue.c_str()); + LuaManager::PushWide(value); + return 1; +} + +static int GetNumberOption(lua_State* L) +{ + DECLARE_SELF(L) + MeterWindow* meterWindow = self->GetMeterWindow(); + ConfigParser& parser = meterWindow->GetParser(); + + std::wstring strTmp = LuaManager::ToWide(2); + double value = parser.ReadFloat(self->GetName(), strTmp.c_str(), lua_tonumber(L, 3)); + + lua_pushnumber(L, value); + return 1; +} + +static int Disable(lua_State* L) +{ + DECLARE_SELF(L) + self->Disable(); + + return 0; +} + +static int Enable(lua_State* L) +{ + DECLARE_SELF(L) + self->Enable(); + + return 0; +} + +static int GetValue(lua_State* L) +{ + DECLARE_SELF(L) + lua_pushnumber(L, self->GetValue()); + + return 1; +} + +static int GetRelativeValue(lua_State* L) +{ + DECLARE_SELF(L) + lua_pushnumber(L, self->GetRelativeValue()); + + return 1; +} + +static int GetValueRange(lua_State* L) +{ + DECLARE_SELF(L) + lua_pushnumber(L, self->GetValueRange()); + + return 1; +} + +static int GetMinValue(lua_State* L) +{ + DECLARE_SELF(L) + lua_pushnumber(L, self->GetMinValue()); + + return 1; +} + +static int GetMaxValue(lua_State* L) +{ + DECLARE_SELF(L) + lua_pushnumber(L, self->GetMaxValue()); + + return 1; +} + +static int GetStringValue(lua_State* L) +{ + DECLARE_SELF(L) + + int top = lua_gettop(L); + AUTOSCALE autoScale = (top > 1) ? (AUTOSCALE)(int)lua_tonumber(L, 2) : AUTOSCALE_OFF; + double scale = (top > 2) ? lua_tonumber(L, 3) : 1.0; + int decimals = (int)lua_tonumber(L, 4); + bool percentual = lua_toboolean(L, 5) != 0; + + const WCHAR* val = self->GetStringOrFormattedValue(autoScale, scale, decimals, percentual); + LuaManager::PushWide(val); + + return 1; +} + +void LuaManager::RegisterMeasure(lua_State* L) +{ + const luaL_Reg functions[] = + { + { "GetName", GetName }, + { "GetOption", GetOption }, + { "GetNumberOption", GetNumberOption }, + { "Disable", Disable }, + { "Enable", Enable }, + { "GetValue", GetValue }, + { "GetRelativeValue", GetRelativeValue }, + { "GetValueRange", GetValueRange }, + { "GetMinValue", GetMinValue }, + { "GetMaxValue", GetMaxValue }, + { "GetStringValue", GetStringValue }, + { nullptr, nullptr } + }; + + luaL_register(L, "Measure", functions); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); +} diff --git a/Library/lua/glue/LuaMeter.cpp b/Library/lua/glue/LuaMeter.cpp index 3d5bf3ef..dd27a76d 100644 --- a/Library/lua/glue/LuaMeter.cpp +++ b/Library/lua/glue/LuaMeter.cpp @@ -1,175 +1,175 @@ -/* - Copyright (C) 2010 Matt King, Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../LuaManager.h" -#include "../../Meter.h" -#include "../../MeterString.h" - -#define DECLARE_SELF(L) \ - void* selfData = lua_touserdata(L, 1); \ - if (!selfData) return 0; \ - Meter* self = *(Meter**)selfData; - -static int GetName(lua_State* L) -{ - DECLARE_SELF(L) - LuaManager::PushWide(self->GetName()); - - return 1; -} - -static int GetOption(lua_State* L) -{ - DECLARE_SELF(L) - MeterWindow* meterWindow = self->GetMeterWindow(); - ConfigParser& parser = meterWindow->GetParser(); - - const std::wstring section = LuaManager::ToWide(2); - const std::wstring defValue = LuaManager::ToWide(3); - const std::wstring& value = - parser.ReadString(self->GetName(), section.c_str(), defValue.c_str()); - LuaManager::PushWide(value); - return 1; -} - -static int GetW(lua_State* L) -{ - DECLARE_SELF(L) - lua_pushnumber(L, self->GetW()); - - return 1; -} - -static int GetH(lua_State* L) -{ - DECLARE_SELF(L) - lua_pushnumber(L, self->GetH()); - - return 1; - -} - -static int GetX(lua_State* L) -{ - DECLARE_SELF(L) - const bool abs = lua_toboolean(L, 2) != 0; - lua_pushnumber(L, self->GetX(abs)); - - return 1; -} - -static int GetY(lua_State* L) -{ - DECLARE_SELF(L) - const bool abs = lua_toboolean(L, 2) != 0; - lua_pushnumber(L, self->GetY(abs)); - - return 1; -} - -static int SetW(lua_State* L) -{ - DECLARE_SELF(L) - int w = (int)lua_tonumber(L, 2); - self->SetW(w); - - return 0; -} - -static int SetH(lua_State* L) -{ - DECLARE_SELF(L) - int h = (int)lua_tonumber(L, 2); - self->SetH(h); - - return 0; -} - -static int SetX(lua_State* L) -{ - DECLARE_SELF(L) - int x = (int)lua_tonumber(L, 2); - self->SetX(x); - - return 0; -} - -static int SetY(lua_State* L) -{ - DECLARE_SELF(L) - int y = (int)lua_tonumber(L, 2); - self->SetY(y); - - return 0; -} - -static int Hide(lua_State* L) -{ - DECLARE_SELF(L) - self->Hide(); - - return 0; -} - -static int Show(lua_State* L) -{ - DECLARE_SELF(L) - self->Show(); - - return 0; -} - -static int SetText(lua_State* L) -{ - DECLARE_SELF(L) - if (self->GetTypeID() == TypeID()) - { - MeterString* string = (MeterString*)self; - std::wstring str = LuaManager::ToWide(2); - string->SetText(str.c_str()); - } - - return 0; -} - -void LuaManager::RegisterMeter(lua_State* L) -{ - const luaL_Reg functions[] = - { - { "GetName", GetName }, - { "GetOption", GetOption }, - { "GetW", GetW }, - { "GetH", GetH }, - { "GetX", GetX }, - { "GetY", GetY }, - { "SetW", SetW }, - { "SetH", SetH }, - { "SetX", SetX }, - { "SetY", SetY }, - { "Hide", Hide }, - { "Show", Show }, - { "SetText", SetText }, - { nullptr, nullptr } - }; - - luaL_register(L, "Meter", functions); - lua_pushvalue(L, -1); - lua_setfield(L, -2, "__index"); - lua_pop(L, 1); -} +/* + Copyright (C) 2010 Matt King, Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../LuaManager.h" +#include "../../Meter.h" +#include "../../MeterString.h" + +#define DECLARE_SELF(L) \ + void* selfData = lua_touserdata(L, 1); \ + if (!selfData) return 0; \ + Meter* self = *(Meter**)selfData; + +static int GetName(lua_State* L) +{ + DECLARE_SELF(L) + LuaManager::PushWide(self->GetName()); + + return 1; +} + +static int GetOption(lua_State* L) +{ + DECLARE_SELF(L) + MeterWindow* meterWindow = self->GetMeterWindow(); + ConfigParser& parser = meterWindow->GetParser(); + + const std::wstring section = LuaManager::ToWide(2); + const std::wstring defValue = LuaManager::ToWide(3); + const std::wstring& value = + parser.ReadString(self->GetName(), section.c_str(), defValue.c_str()); + LuaManager::PushWide(value); + return 1; +} + +static int GetW(lua_State* L) +{ + DECLARE_SELF(L) + lua_pushnumber(L, self->GetW()); + + return 1; +} + +static int GetH(lua_State* L) +{ + DECLARE_SELF(L) + lua_pushnumber(L, self->GetH()); + + return 1; + +} + +static int GetX(lua_State* L) +{ + DECLARE_SELF(L) + const bool abs = lua_toboolean(L, 2) != 0; + lua_pushnumber(L, self->GetX(abs)); + + return 1; +} + +static int GetY(lua_State* L) +{ + DECLARE_SELF(L) + const bool abs = lua_toboolean(L, 2) != 0; + lua_pushnumber(L, self->GetY(abs)); + + return 1; +} + +static int SetW(lua_State* L) +{ + DECLARE_SELF(L) + int w = (int)lua_tonumber(L, 2); + self->SetW(w); + + return 0; +} + +static int SetH(lua_State* L) +{ + DECLARE_SELF(L) + int h = (int)lua_tonumber(L, 2); + self->SetH(h); + + return 0; +} + +static int SetX(lua_State* L) +{ + DECLARE_SELF(L) + int x = (int)lua_tonumber(L, 2); + self->SetX(x); + + return 0; +} + +static int SetY(lua_State* L) +{ + DECLARE_SELF(L) + int y = (int)lua_tonumber(L, 2); + self->SetY(y); + + return 0; +} + +static int Hide(lua_State* L) +{ + DECLARE_SELF(L) + self->Hide(); + + return 0; +} + +static int Show(lua_State* L) +{ + DECLARE_SELF(L) + self->Show(); + + return 0; +} + +static int SetText(lua_State* L) +{ + DECLARE_SELF(L) + if (self->GetTypeID() == TypeID()) + { + MeterString* string = (MeterString*)self; + std::wstring str = LuaManager::ToWide(2); + string->SetText(str.c_str()); + } + + return 0; +} + +void LuaManager::RegisterMeter(lua_State* L) +{ + const luaL_Reg functions[] = + { + { "GetName", GetName }, + { "GetOption", GetOption }, + { "GetW", GetW }, + { "GetH", GetH }, + { "GetX", GetX }, + { "GetY", GetY }, + { "SetW", SetW }, + { "SetH", SetH }, + { "SetX", SetX }, + { "SetY", SetY }, + { "Hide", Hide }, + { "Show", Show }, + { "SetText", SetText }, + { nullptr, nullptr } + }; + + luaL_register(L, "Meter", functions); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); +} diff --git a/Library/lua/glue/LuaMeterWindow.cpp b/Library/lua/glue/LuaMeterWindow.cpp index fd8c405e..7658b224 100644 --- a/Library/lua/glue/LuaMeterWindow.cpp +++ b/Library/lua/glue/LuaMeterWindow.cpp @@ -1,240 +1,240 @@ -/* - Copyright (C) 2010 Matt King, Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../LuaManager.h" -#include "../../Rainmeter.h" -#include "../../MeterWindow.h" -#include "../../MeterString.h" - -#define DECLARE_SELF(L) \ - void* selfData = lua_touserdata(L, 1); \ - if (!selfData) return 0; \ - MeterWindow* self = *(MeterWindow**)selfData; - -static int Bang(lua_State* L) -{ - DECLARE_SELF(L) - ConfigParser& parser = self->GetParser(); - - std::wstring bang = LuaManager::ToWide(2); - - int top = lua_gettop(L); - if (top == 2) // 1 argument - { - parser.ReplaceVariables(bang); - Rainmeter::GetInstance().ExecuteCommand(bang.c_str(), self); - } - else - { - const WCHAR* bangSz = bang.c_str(); - if (*bangSz == L'!') - { - ++bangSz; // Skip "!" - std::vector args; - for (int i = 3; i <= top; ++i) - { - std::wstring tmpSz = LuaManager::ToWide(i); - parser.ReplaceVariables(tmpSz); - args.push_back(tmpSz); - } - - Rainmeter::GetInstance().ExecuteBang(bangSz, args, self); - } - } - - return 0; -} - -static int GetMeter(lua_State* L) -{ - DECLARE_SELF(L) - const std::wstring meterName = LuaManager::ToWide(2); - - Meter* meter = self->GetMeter(meterName); - if (meter) - { - *(Meter**)lua_newuserdata(L, sizeof(Meter*)) = meter; - lua_getglobal(L, "Meter"); - lua_setmetatable(L, -2); - } - else - { - lua_pushnil(L); - } - - return 1; -} - -static int GetMeasure(lua_State* L) -{ - DECLARE_SELF(L) - const std::wstring measureName = LuaManager::ToWide(2); - - Measure* measure = self->GetMeasure(measureName); - if (measure) - { - *(Measure**)lua_newuserdata(L, sizeof(Measure*)) = measure; - lua_getglobal(L, "Measure"); - lua_setmetatable(L, -2); - } - else - { - lua_pushnil(L); - } - - return 1; -} - -static int GetVariable(lua_State* L) -{ - DECLARE_SELF(L) - - const std::wstring name = LuaManager::ToWide(2); - const std::wstring* value = self->GetParser().GetVariable(name); - if (value) - { - LuaManager::PushWide(*value); - } - else if (lua_gettop(L) >= 3) - { - lua_pushvalue(L, 3); - } - else - { - lua_pushnil(L); - } - - return 1; -} - -static int ReplaceVariables(lua_State* L) -{ - DECLARE_SELF(L) - std::wstring strTmp = LuaManager::ToWide(2); - - self->GetParser().ReplaceVariables(strTmp); - self->GetParser().ReplaceMeasures(strTmp); - LuaManager::PushWide(strTmp); - - return 1; -} - -static int ParseFormula(lua_State* L) -{ - DECLARE_SELF(L) - std::wstring strTmp = LuaManager::ToWide(2); - - double result; - if (!self->GetParser().ParseFormula(strTmp, &result)) - { - result = lua_tonumber(L, 2); - } - - lua_pushnumber(L, result); - - return 1; -} - -static int MoveWindow(lua_State* L) -{ - DECLARE_SELF(L) - int x = (int)lua_tonumber(L, 2); - int y = (int)lua_tonumber(L, 3); - self->MoveWindow(x, y); - - return 0; -} - -static int FadeWindow(lua_State* L) -{ - DECLARE_SELF(L) - int from = (int)lua_tonumber(L, 2); - int to = (int)lua_tonumber(L, 3); - self->FadeWindow(from, to); - - return 0; -} - -static int GetW(lua_State* L) -{ - DECLARE_SELF(L) - lua_pushnumber(L, self->GetW()); - - return 1; -} - -static int GetH(lua_State* L) -{ - DECLARE_SELF(L) - lua_pushnumber(L, self->GetH()); - - return 1; -} - -static int GetX(lua_State* L) -{ - DECLARE_SELF(L) - lua_pushnumber(L, self->GetX()); - - return 1; -} - -static int GetY(lua_State* L) -{ - DECLARE_SELF(L) - lua_pushnumber(L, self->GetY()); - - return 1; -} - -static int MakePathAbsolute(lua_State* L) -{ - DECLARE_SELF(L) - std::wstring path = LuaManager::ToWide(2); - self->MakePathAbsolute(path); - LuaManager::PushWide(path); - - return 1; -} - -void LuaManager::RegisterMeterWindow(lua_State* L) -{ - const luaL_Reg functions[] = - { - { "Bang", Bang }, - { "GetMeter", GetMeter }, - { "GetMeasure", GetMeasure }, - { "GetVariable", GetVariable }, - { "ReplaceVariables", ReplaceVariables }, - { "ParseFormula", ParseFormula }, - { "MoveWindow", MoveWindow }, - { "FadeWindow", FadeWindow }, - { "GetW", GetW }, - { "GetH", GetH }, - { "GetX", GetX }, - { "GetY", GetY }, - { "MakePathAbsolute", MakePathAbsolute }, - { nullptr, nullptr } - }; - - luaL_register(L, "MeterWindow", functions); - lua_pushvalue(L, -1); - lua_setfield(L, -2, "__index"); - lua_pop(L, 1); -} +/* + Copyright (C) 2010 Matt King, Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../LuaManager.h" +#include "../../Rainmeter.h" +#include "../../MeterWindow.h" +#include "../../MeterString.h" + +#define DECLARE_SELF(L) \ + void* selfData = lua_touserdata(L, 1); \ + if (!selfData) return 0; \ + MeterWindow* self = *(MeterWindow**)selfData; + +static int Bang(lua_State* L) +{ + DECLARE_SELF(L) + ConfigParser& parser = self->GetParser(); + + std::wstring bang = LuaManager::ToWide(2); + + int top = lua_gettop(L); + if (top == 2) // 1 argument + { + parser.ReplaceVariables(bang); + Rainmeter::GetInstance().ExecuteCommand(bang.c_str(), self); + } + else + { + const WCHAR* bangSz = bang.c_str(); + if (*bangSz == L'!') + { + ++bangSz; // Skip "!" + std::vector args; + for (int i = 3; i <= top; ++i) + { + std::wstring tmpSz = LuaManager::ToWide(i); + parser.ReplaceVariables(tmpSz); + args.push_back(tmpSz); + } + + Rainmeter::GetInstance().ExecuteBang(bangSz, args, self); + } + } + + return 0; +} + +static int GetMeter(lua_State* L) +{ + DECLARE_SELF(L) + const std::wstring meterName = LuaManager::ToWide(2); + + Meter* meter = self->GetMeter(meterName); + if (meter) + { + *(Meter**)lua_newuserdata(L, sizeof(Meter*)) = meter; + lua_getglobal(L, "Meter"); + lua_setmetatable(L, -2); + } + else + { + lua_pushnil(L); + } + + return 1; +} + +static int GetMeasure(lua_State* L) +{ + DECLARE_SELF(L) + const std::wstring measureName = LuaManager::ToWide(2); + + Measure* measure = self->GetMeasure(measureName); + if (measure) + { + *(Measure**)lua_newuserdata(L, sizeof(Measure*)) = measure; + lua_getglobal(L, "Measure"); + lua_setmetatable(L, -2); + } + else + { + lua_pushnil(L); + } + + return 1; +} + +static int GetVariable(lua_State* L) +{ + DECLARE_SELF(L) + + const std::wstring name = LuaManager::ToWide(2); + const std::wstring* value = self->GetParser().GetVariable(name); + if (value) + { + LuaManager::PushWide(*value); + } + else if (lua_gettop(L) >= 3) + { + lua_pushvalue(L, 3); + } + else + { + lua_pushnil(L); + } + + return 1; +} + +static int ReplaceVariables(lua_State* L) +{ + DECLARE_SELF(L) + std::wstring strTmp = LuaManager::ToWide(2); + + self->GetParser().ReplaceVariables(strTmp); + self->GetParser().ReplaceMeasures(strTmp); + LuaManager::PushWide(strTmp); + + return 1; +} + +static int ParseFormula(lua_State* L) +{ + DECLARE_SELF(L) + std::wstring strTmp = LuaManager::ToWide(2); + + double result; + if (!self->GetParser().ParseFormula(strTmp, &result)) + { + result = lua_tonumber(L, 2); + } + + lua_pushnumber(L, result); + + return 1; +} + +static int MoveWindow(lua_State* L) +{ + DECLARE_SELF(L) + int x = (int)lua_tonumber(L, 2); + int y = (int)lua_tonumber(L, 3); + self->MoveWindow(x, y); + + return 0; +} + +static int FadeWindow(lua_State* L) +{ + DECLARE_SELF(L) + int from = (int)lua_tonumber(L, 2); + int to = (int)lua_tonumber(L, 3); + self->FadeWindow(from, to); + + return 0; +} + +static int GetW(lua_State* L) +{ + DECLARE_SELF(L) + lua_pushnumber(L, self->GetW()); + + return 1; +} + +static int GetH(lua_State* L) +{ + DECLARE_SELF(L) + lua_pushnumber(L, self->GetH()); + + return 1; +} + +static int GetX(lua_State* L) +{ + DECLARE_SELF(L) + lua_pushnumber(L, self->GetX()); + + return 1; +} + +static int GetY(lua_State* L) +{ + DECLARE_SELF(L) + lua_pushnumber(L, self->GetY()); + + return 1; +} + +static int MakePathAbsolute(lua_State* L) +{ + DECLARE_SELF(L) + std::wstring path = LuaManager::ToWide(2); + self->MakePathAbsolute(path); + LuaManager::PushWide(path); + + return 1; +} + +void LuaManager::RegisterMeterWindow(lua_State* L) +{ + const luaL_Reg functions[] = + { + { "Bang", Bang }, + { "GetMeter", GetMeter }, + { "GetMeasure", GetMeasure }, + { "GetVariable", GetVariable }, + { "ReplaceVariables", ReplaceVariables }, + { "ParseFormula", ParseFormula }, + { "MoveWindow", MoveWindow }, + { "FadeWindow", FadeWindow }, + { "GetW", GetW }, + { "GetH", GetH }, + { "GetX", GetX }, + { "GetY", GetY }, + { "MakePathAbsolute", MakePathAbsolute }, + { nullptr, nullptr } + }; + + luaL_register(L, "MeterWindow", functions); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); +} diff --git a/Library/resource.h b/Library/resource.h index 89c60fdc..070e9e53 100644 --- a/Library/resource.h +++ b/Library/resource.h @@ -1,219 +1,219 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by Library.rc -// -#define IDC_STATIC -1 -#define IDI_RAINMETER 100 -#define IDI_TRAY 101 - -#define ID_STR_NUM_BUTTONWIDTH 1998 -#define ID_STR_NUM_LABELWIDTH 1999 -#define ID_STR_ISRTL 2000 -#define ID_STR_UPDATEAVAILABLE 2001 -#define ID_STR_MANAGE 2002 -#define ID_STR_ABOUT 2003 -#define ID_STR_HELP 2004 -#define ID_STR_SKINS 2005 -#define ID_STR_NOSKINS 2006 -#define ID_STR_OPENFOLDER 2007 -#define ID_STR_DISABLEDRAGGING 2008 -#define ID_STR_THEMES 2009 -#define ID_STR_NOTHEMES 2010 -#define ID_STR_EDITSETTINGS 2011 -#define ID_STR_REFRESHALL 2012 -#define ID_STR_LOGGING 2013 -#define ID_STR_SHOWLOGFILE 2014 -#define ID_STR_STARTLOGGING 2015 -#define ID_STR_STOPLOGGING 2016 -#define ID_STR_DELETELOGFILE 2017 -#define ID_STR_DEBUGMODE 2018 -#define ID_STR_EXIT 2019 -#define ID_STR_VARIANTS 2020 -#define ID_STR_SETTINGS 2021 -#define ID_STR_POSITION 2022 -#define ID_STR_DISPLAYMONITOR 2023 -#define ID_STR_USEDEFAULTMONITOR 2024 -#define ID_STR_VIRTUALSCREEN 2025 -#define ID_STR_AUTOSELECTMONITOR 2026 -#define ID_STR_STAYTOPMOST 2027 -#define ID_STR_TOPMOST 2028 -#define ID_STR_NORMAL 2029 -#define ID_STR_BOTTOM 2030 -#define ID_STR_ONDESKTOP 2031 -#define ID_STR_FROMRIGHT 2032 -#define ID_STR_FROMBOTTOM 2033 -#define ID_STR_XASPERCENTAGE 2034 -#define ID_STR_YASPERCENTAGE 2035 -#define ID_STR_TRANSPARENCY 2036 -#define ID_STR_0PERCENT 2037 -#define ID_STR_10PERCENT 2038 -#define ID_STR_20PERCENT 2039 -#define ID_STR_30PERCENT 2040 -#define ID_STR_40PERCENT 2041 -#define ID_STR_50PERCENT 2042 -#define ID_STR_60PERCENT 2043 -#define ID_STR_70PERCENT 2044 -#define ID_STR_80PERCENT 2045 -#define ID_STR_90PERCENT 2046 -#define ID_STR_FADEIN 2047 -#define ID_STR_FADEOUT 2048 -#define ID_STR_HIDEONMOUSEOVER 2049 -#define ID_STR_DRAGGABLE 2050 -#define ID_STR_SAVEPOSITION 2051 -#define ID_STR_SNAPTOEDGES 2052 -#define ID_STR_CLICKTHROUGH 2053 -#define ID_STR_KEEPONSCREEN 2054 -#define ID_STR_MANAGESKIN 2055 -#define ID_STR_EDITSKIN 2056 -#define ID_STR_REFRESHSKIN 2057 -#define ID_STR_UNLOADSKIN 2058 -#define ID_STR_CLOSE 2059 -#define ID_STR_ABOUTRAINMETER 2060 -#define ID_STR_LOG 2061 -#define ID_STR_MEASURES 2062 -#define ID_STR_VARIABLES 2063 -#define ID_STR_PLUGINS 2064 -#define ID_STR_VERSION 2065 -#define ID_STR_TYPE 2066 -#define ID_STR_TIME 2067 -#define ID_STR_MESSAGE 2068 -#define ID_STR_NAME 2069 -#define ID_STR_RANGE 2070 -#define ID_STR_VALUE 2071 -#define ID_STR_AUTHOR 2072 -#define ID_STR_ERROR 2073 -#define ID_STR_WARNING 2074 -#define ID_STR_NOTICE 2075 -#define ID_STR_DEBUG 2076 -#define ID_STR_GETLATESTVERSION 2077 -#define ID_STR_COPYRIGHTNOTICE 2078 -#define ID_STR_COPYTOCLIPBOARD 2079 -#define ID_STR_MANAGERAINMETER 2080 -#define ID_STR_ACTIVESKINS 2081 -#define ID_STR_EXPAND 2082 -#define ID_STR_COLLAPSE 2083 -#define ID_STR_OPENLOG 2084 -#define ID_STR_LOAD 2085 -#define ID_STR_UNLOAD 2086 -#define ID_STR_REFRESH 2087 -#define ID_STR_EDIT 2088 -#define ID_STR_AUTHORSC 2089 -#define ID_STR_VERSIONSC 2090 -#define ID_STR_LICENSESC 2091 -#define ID_STR_INFORMATIONSC 2092 -#define ID_STR_ADDMETADATA 2093 -#define ID_STR_COORDINATESSC 2094 -#define ID_STR_POSITIONSC 2095 -#define ID_STR_LOADORDERSC 2096 -#define ID_STR_TRANSPARENCYSC 2097 -#define ID_STR_ONHOVERSC 2098 -#define ID_STR_DONOTHING 2099 -#define ID_STR_HIDE 2100 -#define ID_STR_SAVENEWTHEME 2101 -#define ID_STR_THEMEDESCRIPTION 2102 -#define ID_STR_SAVEASEMPTYTHEME 2103 -#define ID_STR_EXCLUDEUNUSEDSKINS 2104 -#define ID_STR_INCLUDEWALLPAPER 2105 -#define ID_STR_NAMESC 2106 -#define ID_STR_SAVE 2107 -#define ID_STR_SAVEDTHEMES 2108 -#define ID_STR_DELETE 2109 -#define ID_STR_BACKUP 2110 -#define ID_STR_BACKUPDESCRIPTION 2111 -#define ID_STR_BACKUPE 2112 -#define ID_STR_LANGUAGESC 2113 -#define ID_STR_GENERAL 2114 -#define ID_STR_CHECKFORUPDATES 2115 -#define ID_STR_RESETSTATISTICS 2116 -#define ID_STR_LOGTOFILE 2117 -#define ID_STR_SETTINGSNOTWRITABLE 2118 -#define ID_STR_SETTINGSMOVEFILE 2119 -#define ID_STR_SETTINGSREADONLY 2120 -#define ID_STR_THEMEALREADYEXISTS 2121 -#define ID_STR_THEMESAVEFAIL 2122 -#define ID_STR_THEMEDELETE 2123 -#define ID_STR_LOGFILECREATEFAIL 2124 -#define ID_STR_LOGFILEDELETE 2125 -#define ID_STR_NOAVAILABLESKINS 2126 -#define ID_STR_UNABLETOACTIVATESKIN 2127 -#define ID_STR_UNABLETOREFRESHSKIN 2128 -#define ID_STR_NEWVERSIONREQUIRED 2129 -#define ID_STR_NOMETERSINSKIN 2130 -#define ID_STR_INCLUDEINFINITELOOP 2131 -#define ID_STR_WELCOME 2132 -#define ID_STR_CLICKTOMANAGE 2133 -#define ID_STR_CLICKTODOWNLOAD 2134 -#define ID_STR_CREATERMSKINPACKAGE 2135 -#define ID_STR_EDITORSC 2136 -#define ID_STR_ELLIPSIS 2137 -#define ID_STR_SHOWNOTIFICATIONAREAICON 2138 -#define ID_STR_SOURCE 2139 -#define ID_STR_USED2D 2140 -#define ID_STR_CLEAR 2141 - -#define IDM_REFRESH 4001 -#define IDM_QUIT 4002 -#define IDM_DISABLEDRAG 4003 -#define IDM_MANAGE 4004 -#define IDM_ABOUT 4005 -#define IDM_EDITCONFIG 4006 -#define IDM_CLOSESKIN 4007 -#define IDM_SKIN_VERYTOPMOST 4008 -#define IDM_SKIN_TOPMOST 4009 -#define IDM_SKIN_NORMAL 4010 -#define IDM_SKIN_BOTTOM 4011 -#define IDM_SKIN_ONDESKTOP 4012 -#define IDM_SKIN_TRANSPARENCY_0 4014 -#define IDM_SKIN_TRANSPARENCY_10 4015 -#define IDM_SKIN_TRANSPARENCY_20 4016 -#define IDM_SKIN_TRANSPARENCY_30 4017 -#define IDM_SKIN_TRANSPARENCY_40 4018 -#define IDM_SKIN_TRANSPARENCY_50 4019 -#define IDM_SKIN_TRANSPARENCY_60 4020 -#define IDM_SKIN_TRANSPARENCY_70 4021 -#define IDM_SKIN_TRANSPARENCY_80 4022 -#define IDM_SKIN_TRANSPARENCY_90 4023 -#define IDM_SKIN_REFRESH 4024 -#define IDM_SKIN_HIDEONMOUSE 4025 -#define IDM_SKIN_DRAGGABLE 4026 -#define IDM_SKIN_REMEMBERPOSITION 4027 -#define IDM_SKIN_SNAPTOEDGES 4028 -#define IDM_SKIN_CLICKTHROUGH 4029 -#define IDM_SKIN_EDITSKIN 4030 -#define IDM_SHOW_HELP 4034 -#define IDM_SHOWLOGFILE 4035 -#define IDM_SKIN_TRANSPARENCY_FADEIN 4037 -#define IDM_SKIN_TRANSPARENCY_FADEOUT 4038 -#define IDM_SKIN_KEEPONSCREEN 4039 -#define IDM_SKIN_FROMRIGHT 4040 -#define IDM_SKIN_FROMBOTTOM 4041 -#define IDM_SKIN_XPERCENTAGE 4042 -#define IDM_SKIN_YPERCENTAGE 4043 -#define IDM_OPENSKINSFOLDER 4044 -#define IDM_SKIN_OPENSKINSFOLDER 4045 -#define IDM_SKIN_MONITOR_PRIMARY 4046 -#define IDM_SKIN_MONITOR_AUTOSELECT 4047 -#define IDM_NEW_VERSION 4048 -#define IDM_STARTLOG 4049 -#define IDM_STOPLOG 4050 -#define IDM_DEBUGLOG 4051 -#define IDM_DELETELOGFILE 4052 -#define IDM_SKIN_MANAGESKIN 4053 -#define IDM_MANAGESKINSMENU_EXPAND 4054 -#define IDM_MANAGESKINSMENU_OPENFOLDER 4055 -#define IDM_MANAGESKINSMENU_LOAD 4056 -#define IDM_MANAGESKINSMENU_REFRESH 4057 -#define IDM_MANAGESKINSMENU_EDIT 4058 -#define IDM_COPY 4059 -#define IDM_SKIN_USED2D 4060 - -#define IDM_SKIN_CUSTOMCONTEXTMENU_FIRST 9000 -#define IDM_SKIN_CUSTOMCONTEXTMENU_LAST 9014 - -#define ID_CONFIG_EDIT 30000 -#define ID_CONFIG_FIRST 30001 -#define ID_CONFIG_LAST 40000 -#define ID_THEME_FIRST 40001 -#define ID_THEME_LAST 43000 -#define ID_MONITOR_FIRST 43001 -#define ID_MONITOR_LAST 44000 +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Library.rc +// +#define IDC_STATIC -1 +#define IDI_RAINMETER 100 +#define IDI_TRAY 101 + +#define ID_STR_NUM_BUTTONWIDTH 1998 +#define ID_STR_NUM_LABELWIDTH 1999 +#define ID_STR_ISRTL 2000 +#define ID_STR_UPDATEAVAILABLE 2001 +#define ID_STR_MANAGE 2002 +#define ID_STR_ABOUT 2003 +#define ID_STR_HELP 2004 +#define ID_STR_SKINS 2005 +#define ID_STR_NOSKINS 2006 +#define ID_STR_OPENFOLDER 2007 +#define ID_STR_DISABLEDRAGGING 2008 +#define ID_STR_THEMES 2009 +#define ID_STR_NOTHEMES 2010 +#define ID_STR_EDITSETTINGS 2011 +#define ID_STR_REFRESHALL 2012 +#define ID_STR_LOGGING 2013 +#define ID_STR_SHOWLOGFILE 2014 +#define ID_STR_STARTLOGGING 2015 +#define ID_STR_STOPLOGGING 2016 +#define ID_STR_DELETELOGFILE 2017 +#define ID_STR_DEBUGMODE 2018 +#define ID_STR_EXIT 2019 +#define ID_STR_VARIANTS 2020 +#define ID_STR_SETTINGS 2021 +#define ID_STR_POSITION 2022 +#define ID_STR_DISPLAYMONITOR 2023 +#define ID_STR_USEDEFAULTMONITOR 2024 +#define ID_STR_VIRTUALSCREEN 2025 +#define ID_STR_AUTOSELECTMONITOR 2026 +#define ID_STR_STAYTOPMOST 2027 +#define ID_STR_TOPMOST 2028 +#define ID_STR_NORMAL 2029 +#define ID_STR_BOTTOM 2030 +#define ID_STR_ONDESKTOP 2031 +#define ID_STR_FROMRIGHT 2032 +#define ID_STR_FROMBOTTOM 2033 +#define ID_STR_XASPERCENTAGE 2034 +#define ID_STR_YASPERCENTAGE 2035 +#define ID_STR_TRANSPARENCY 2036 +#define ID_STR_0PERCENT 2037 +#define ID_STR_10PERCENT 2038 +#define ID_STR_20PERCENT 2039 +#define ID_STR_30PERCENT 2040 +#define ID_STR_40PERCENT 2041 +#define ID_STR_50PERCENT 2042 +#define ID_STR_60PERCENT 2043 +#define ID_STR_70PERCENT 2044 +#define ID_STR_80PERCENT 2045 +#define ID_STR_90PERCENT 2046 +#define ID_STR_FADEIN 2047 +#define ID_STR_FADEOUT 2048 +#define ID_STR_HIDEONMOUSEOVER 2049 +#define ID_STR_DRAGGABLE 2050 +#define ID_STR_SAVEPOSITION 2051 +#define ID_STR_SNAPTOEDGES 2052 +#define ID_STR_CLICKTHROUGH 2053 +#define ID_STR_KEEPONSCREEN 2054 +#define ID_STR_MANAGESKIN 2055 +#define ID_STR_EDITSKIN 2056 +#define ID_STR_REFRESHSKIN 2057 +#define ID_STR_UNLOADSKIN 2058 +#define ID_STR_CLOSE 2059 +#define ID_STR_ABOUTRAINMETER 2060 +#define ID_STR_LOG 2061 +#define ID_STR_MEASURES 2062 +#define ID_STR_VARIABLES 2063 +#define ID_STR_PLUGINS 2064 +#define ID_STR_VERSION 2065 +#define ID_STR_TYPE 2066 +#define ID_STR_TIME 2067 +#define ID_STR_MESSAGE 2068 +#define ID_STR_NAME 2069 +#define ID_STR_RANGE 2070 +#define ID_STR_VALUE 2071 +#define ID_STR_AUTHOR 2072 +#define ID_STR_ERROR 2073 +#define ID_STR_WARNING 2074 +#define ID_STR_NOTICE 2075 +#define ID_STR_DEBUG 2076 +#define ID_STR_GETLATESTVERSION 2077 +#define ID_STR_COPYRIGHTNOTICE 2078 +#define ID_STR_COPYTOCLIPBOARD 2079 +#define ID_STR_MANAGERAINMETER 2080 +#define ID_STR_ACTIVESKINS 2081 +#define ID_STR_EXPAND 2082 +#define ID_STR_COLLAPSE 2083 +#define ID_STR_OPENLOG 2084 +#define ID_STR_LOAD 2085 +#define ID_STR_UNLOAD 2086 +#define ID_STR_REFRESH 2087 +#define ID_STR_EDIT 2088 +#define ID_STR_AUTHORSC 2089 +#define ID_STR_VERSIONSC 2090 +#define ID_STR_LICENSESC 2091 +#define ID_STR_INFORMATIONSC 2092 +#define ID_STR_ADDMETADATA 2093 +#define ID_STR_COORDINATESSC 2094 +#define ID_STR_POSITIONSC 2095 +#define ID_STR_LOADORDERSC 2096 +#define ID_STR_TRANSPARENCYSC 2097 +#define ID_STR_ONHOVERSC 2098 +#define ID_STR_DONOTHING 2099 +#define ID_STR_HIDE 2100 +#define ID_STR_SAVENEWTHEME 2101 +#define ID_STR_THEMEDESCRIPTION 2102 +#define ID_STR_SAVEASEMPTYTHEME 2103 +#define ID_STR_EXCLUDEUNUSEDSKINS 2104 +#define ID_STR_INCLUDEWALLPAPER 2105 +#define ID_STR_NAMESC 2106 +#define ID_STR_SAVE 2107 +#define ID_STR_SAVEDTHEMES 2108 +#define ID_STR_DELETE 2109 +#define ID_STR_BACKUP 2110 +#define ID_STR_BACKUPDESCRIPTION 2111 +#define ID_STR_BACKUPE 2112 +#define ID_STR_LANGUAGESC 2113 +#define ID_STR_GENERAL 2114 +#define ID_STR_CHECKFORUPDATES 2115 +#define ID_STR_RESETSTATISTICS 2116 +#define ID_STR_LOGTOFILE 2117 +#define ID_STR_SETTINGSNOTWRITABLE 2118 +#define ID_STR_SETTINGSMOVEFILE 2119 +#define ID_STR_SETTINGSREADONLY 2120 +#define ID_STR_THEMEALREADYEXISTS 2121 +#define ID_STR_THEMESAVEFAIL 2122 +#define ID_STR_THEMEDELETE 2123 +#define ID_STR_LOGFILECREATEFAIL 2124 +#define ID_STR_LOGFILEDELETE 2125 +#define ID_STR_NOAVAILABLESKINS 2126 +#define ID_STR_UNABLETOACTIVATESKIN 2127 +#define ID_STR_UNABLETOREFRESHSKIN 2128 +#define ID_STR_NEWVERSIONREQUIRED 2129 +#define ID_STR_NOMETERSINSKIN 2130 +#define ID_STR_INCLUDEINFINITELOOP 2131 +#define ID_STR_WELCOME 2132 +#define ID_STR_CLICKTOMANAGE 2133 +#define ID_STR_CLICKTODOWNLOAD 2134 +#define ID_STR_CREATERMSKINPACKAGE 2135 +#define ID_STR_EDITORSC 2136 +#define ID_STR_ELLIPSIS 2137 +#define ID_STR_SHOWNOTIFICATIONAREAICON 2138 +#define ID_STR_SOURCE 2139 +#define ID_STR_USED2D 2140 +#define ID_STR_CLEAR 2141 + +#define IDM_REFRESH 4001 +#define IDM_QUIT 4002 +#define IDM_DISABLEDRAG 4003 +#define IDM_MANAGE 4004 +#define IDM_ABOUT 4005 +#define IDM_EDITCONFIG 4006 +#define IDM_CLOSESKIN 4007 +#define IDM_SKIN_VERYTOPMOST 4008 +#define IDM_SKIN_TOPMOST 4009 +#define IDM_SKIN_NORMAL 4010 +#define IDM_SKIN_BOTTOM 4011 +#define IDM_SKIN_ONDESKTOP 4012 +#define IDM_SKIN_TRANSPARENCY_0 4014 +#define IDM_SKIN_TRANSPARENCY_10 4015 +#define IDM_SKIN_TRANSPARENCY_20 4016 +#define IDM_SKIN_TRANSPARENCY_30 4017 +#define IDM_SKIN_TRANSPARENCY_40 4018 +#define IDM_SKIN_TRANSPARENCY_50 4019 +#define IDM_SKIN_TRANSPARENCY_60 4020 +#define IDM_SKIN_TRANSPARENCY_70 4021 +#define IDM_SKIN_TRANSPARENCY_80 4022 +#define IDM_SKIN_TRANSPARENCY_90 4023 +#define IDM_SKIN_REFRESH 4024 +#define IDM_SKIN_HIDEONMOUSE 4025 +#define IDM_SKIN_DRAGGABLE 4026 +#define IDM_SKIN_REMEMBERPOSITION 4027 +#define IDM_SKIN_SNAPTOEDGES 4028 +#define IDM_SKIN_CLICKTHROUGH 4029 +#define IDM_SKIN_EDITSKIN 4030 +#define IDM_SHOW_HELP 4034 +#define IDM_SHOWLOGFILE 4035 +#define IDM_SKIN_TRANSPARENCY_FADEIN 4037 +#define IDM_SKIN_TRANSPARENCY_FADEOUT 4038 +#define IDM_SKIN_KEEPONSCREEN 4039 +#define IDM_SKIN_FROMRIGHT 4040 +#define IDM_SKIN_FROMBOTTOM 4041 +#define IDM_SKIN_XPERCENTAGE 4042 +#define IDM_SKIN_YPERCENTAGE 4043 +#define IDM_OPENSKINSFOLDER 4044 +#define IDM_SKIN_OPENSKINSFOLDER 4045 +#define IDM_SKIN_MONITOR_PRIMARY 4046 +#define IDM_SKIN_MONITOR_AUTOSELECT 4047 +#define IDM_NEW_VERSION 4048 +#define IDM_STARTLOG 4049 +#define IDM_STOPLOG 4050 +#define IDM_DEBUGLOG 4051 +#define IDM_DELETELOGFILE 4052 +#define IDM_SKIN_MANAGESKIN 4053 +#define IDM_MANAGESKINSMENU_EXPAND 4054 +#define IDM_MANAGESKINSMENU_OPENFOLDER 4055 +#define IDM_MANAGESKINSMENU_LOAD 4056 +#define IDM_MANAGESKINSMENU_REFRESH 4057 +#define IDM_MANAGESKINSMENU_EDIT 4058 +#define IDM_COPY 4059 +#define IDM_SKIN_USED2D 4060 + +#define IDM_SKIN_CUSTOMCONTEXTMENU_FIRST 9000 +#define IDM_SKIN_CUSTOMCONTEXTMENU_LAST 9014 + +#define ID_CONFIG_EDIT 30000 +#define ID_CONFIG_FIRST 30001 +#define ID_CONFIG_LAST 40000 +#define ID_THEME_FIRST 40001 +#define ID_THEME_LAST 43000 +#define ID_MONITOR_FIRST 43001 +#define ID_MONITOR_LAST 44000 diff --git a/Plugins/API/RainmeterAPI.cs b/Plugins/API/RainmeterAPI.cs index d8362cf9..9f7be39d 100644 --- a/Plugins/API/RainmeterAPI.cs +++ b/Plugins/API/RainmeterAPI.cs @@ -1,140 +1,140 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -using System; -using System.Runtime.InteropServices; - -namespace Rainmeter -{ - /// - /// Wrapper around the Rainmeter C API. - /// - public class API - { - private IntPtr m_Rm; - - public API(IntPtr rm) - { - m_Rm = rm; - } - - [DllImport("Rainmeter.dll", CharSet = CharSet.Unicode)] - private extern static IntPtr RmReadString(IntPtr rm, string option, string defValue, bool replaceMeasures); - - [DllImport("Rainmeter.dll", CharSet = CharSet.Unicode)] - private extern static double RmReadFormula(IntPtr rm, string option, double defValue); - - [DllImport("Rainmeter.dll", CharSet = CharSet.Unicode)] - private extern static IntPtr RmReplaceVariables(IntPtr rm, string str); - - [DllImport("Rainmeter.dll", CharSet = CharSet.Unicode)] - private extern static IntPtr RmPathToAbsolute(IntPtr rm, string relativePath); - - [DllImport("Rainmeter.dll", EntryPoint = "RmExecute", CharSet = CharSet.Unicode)] - public extern static void Execute(IntPtr skin, string command); - - [DllImport("Rainmeter.dll")] - private extern static IntPtr RmGet(IntPtr rm, RmGetType type); - - [DllImport("Rainmeter.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] - private extern static int LSLog(LogType type, string unused, string message); - - private enum RmGetType - { - MeasureName = 0, - Skin = 1, - SettingsFile = 2, - SkinName = 3, - SkinWindowHandle = 4 - } - - public enum LogType - { - Error = 1, - Warning = 2, - Notice = 3, - Debug = 4 - } - - public string ReadString(string option, string defValue, bool replaceMeasures = true) - { - return Marshal.PtrToStringUni(RmReadString(m_Rm, option, defValue, replaceMeasures)); - } - - public string ReadPath(string option, string defValue) - { - return Marshal.PtrToStringUni(RmPathToAbsolute(m_Rm, ReadString(option, defValue))); - } - - public double ReadDouble(string option, double defValue) - { - return RmReadFormula(m_Rm, option, defValue); - } - - public int ReadInt(string option, int defValue) - { - return (int)RmReadFormula(m_Rm, option, defValue); - } - - public string ReplaceVariables(string str) - { - return Marshal.PtrToStringUni(RmReplaceVariables(m_Rm, str)); - } - - public string GetMeasureName() - { - return Marshal.PtrToStringUni(RmGet(m_Rm, RmGetType.MeasureName)); - } - - public IntPtr GetSkin() - { - return RmGet(m_Rm, RmGetType.Skin); - } - - public string GetSettingsFile() - { - return Marshal.PtrToStringUni(RmGet(m_Rm, RmGetType.SettingsFile)); - } - - public string GetSkinName() - { - return Marshal.PtrToStringUni(RmGet(m_Rm, RmGetType.SkinName)); - } - - public IntPtr GetSkinWindow() - { - return RmGet(m_Rm, RmGetType.SkinWindowHandle); - } - - public static void Log(LogType type, string message) - { - LSLog(type, null, message); - } - } - - /// - /// Dummy attribute to mark method as exported for DllExporter.exe. - /// - [AttributeUsage(AttributeTargets.Method)] - public class DllExport : Attribute - { - public DllExport() - { - } - } -} +/* + Copyright (C) 2011 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +using System; +using System.Runtime.InteropServices; + +namespace Rainmeter +{ + /// + /// Wrapper around the Rainmeter C API. + /// + public class API + { + private IntPtr m_Rm; + + public API(IntPtr rm) + { + m_Rm = rm; + } + + [DllImport("Rainmeter.dll", CharSet = CharSet.Unicode)] + private extern static IntPtr RmReadString(IntPtr rm, string option, string defValue, bool replaceMeasures); + + [DllImport("Rainmeter.dll", CharSet = CharSet.Unicode)] + private extern static double RmReadFormula(IntPtr rm, string option, double defValue); + + [DllImport("Rainmeter.dll", CharSet = CharSet.Unicode)] + private extern static IntPtr RmReplaceVariables(IntPtr rm, string str); + + [DllImport("Rainmeter.dll", CharSet = CharSet.Unicode)] + private extern static IntPtr RmPathToAbsolute(IntPtr rm, string relativePath); + + [DllImport("Rainmeter.dll", EntryPoint = "RmExecute", CharSet = CharSet.Unicode)] + public extern static void Execute(IntPtr skin, string command); + + [DllImport("Rainmeter.dll")] + private extern static IntPtr RmGet(IntPtr rm, RmGetType type); + + [DllImport("Rainmeter.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private extern static int LSLog(LogType type, string unused, string message); + + private enum RmGetType + { + MeasureName = 0, + Skin = 1, + SettingsFile = 2, + SkinName = 3, + SkinWindowHandle = 4 + } + + public enum LogType + { + Error = 1, + Warning = 2, + Notice = 3, + Debug = 4 + } + + public string ReadString(string option, string defValue, bool replaceMeasures = true) + { + return Marshal.PtrToStringUni(RmReadString(m_Rm, option, defValue, replaceMeasures)); + } + + public string ReadPath(string option, string defValue) + { + return Marshal.PtrToStringUni(RmPathToAbsolute(m_Rm, ReadString(option, defValue))); + } + + public double ReadDouble(string option, double defValue) + { + return RmReadFormula(m_Rm, option, defValue); + } + + public int ReadInt(string option, int defValue) + { + return (int)RmReadFormula(m_Rm, option, defValue); + } + + public string ReplaceVariables(string str) + { + return Marshal.PtrToStringUni(RmReplaceVariables(m_Rm, str)); + } + + public string GetMeasureName() + { + return Marshal.PtrToStringUni(RmGet(m_Rm, RmGetType.MeasureName)); + } + + public IntPtr GetSkin() + { + return RmGet(m_Rm, RmGetType.Skin); + } + + public string GetSettingsFile() + { + return Marshal.PtrToStringUni(RmGet(m_Rm, RmGetType.SettingsFile)); + } + + public string GetSkinName() + { + return Marshal.PtrToStringUni(RmGet(m_Rm, RmGetType.SkinName)); + } + + public IntPtr GetSkinWindow() + { + return RmGet(m_Rm, RmGetType.SkinWindowHandle); + } + + public static void Log(LogType type, string message) + { + LSLog(type, null, message); + } + } + + /// + /// Dummy attribute to mark method as exported for DllExporter.exe. + /// + [AttributeUsage(AttributeTargets.Method)] + public class DllExport : Attribute + { + public DllExport() + { + } + } +} diff --git a/Plugins/API/RainmeterAPI.h b/Plugins/API/RainmeterAPI.h index fae3a835..120bd26e 100644 --- a/Plugins/API/RainmeterAPI.h +++ b/Plugins/API/RainmeterAPI.h @@ -1,125 +1,125 @@ -/* - Copyright (C) 2011 Kimmo Pekkola, Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __RAINMETERAPI_H__ -#define __RAINMETERAPI_H__ - -#ifdef LIBRARY_EXPORTS -#define LIBRARY_EXPORT EXTERN_C -#else -#define LIBRARY_EXPORT EXTERN_C __declspec(dllimport) -#endif // LIBRARY_EXPORTS - -#define PLUGIN_EXPORT EXTERN_C __declspec(dllexport) - -// -// Exported functions -// - -#ifdef __cplusplus -LIBRARY_EXPORT LPCWSTR __stdcall RmReadString(void* rm, LPCWSTR option, LPCWSTR defValue, BOOL replaceMeasures = TRUE); -#else -LIBRARY_EXPORT LPCWSTR __stdcall RmReadString(void* rm, LPCWSTR option, LPCWSTR defValue, BOOL replaceMeasures); -#endif // __cplusplus - -LIBRARY_EXPORT double __stdcall RmReadFormula(void* rm, LPCWSTR option, double defValue); - -LIBRARY_EXPORT LPCWSTR __stdcall RmReplaceVariables(void* rm, LPCWSTR str); - -LIBRARY_EXPORT LPCWSTR __stdcall RmPathToAbsolute(void* rm, LPCWSTR relativePath); - -LIBRARY_EXPORT void __stdcall RmExecute(void* skin, LPCWSTR command); - -LIBRARY_EXPORT void* __stdcall RmGet(void* rm, int type); - -enum RmGetType -{ - RMG_MEASURENAME = 0, - RMG_SKIN = 1, - RMG_SETTINGSFILE = 2, - RMG_SKINNAME = 3, - RMG_SKINWINDOWHANDLE = 4 -}; - -LIBRARY_EXPORT void __stdcall RmLog(void* rm, int level, LPCWSTR message); - -LIBRARY_EXPORT void __cdecl RmLogF(void* rm, int level, LPCWSTR format, ...); - -LIBRARY_EXPORT BOOL __cdecl LSLog(int level, LPCWSTR unused, LPCWSTR message); - -// -// Wrapper functions -// - -#ifndef LIBRARY_EXPORTS -__inline LPCWSTR RmReadPath(void* rm, LPCWSTR option, LPCWSTR defValue) -{ - LPCWSTR relativePath = RmReadString(rm, option, defValue, TRUE); - return RmPathToAbsolute(rm, relativePath); -} - -__inline int RmReadInt(void* rm, LPCWSTR option, int defValue) -{ - return (int)RmReadFormula(rm, option, defValue); -} - -__inline double RmReadDouble(void* rm, LPCWSTR option, double defValue) -{ - return RmReadFormula(rm, option, defValue); -} - -__inline LPCWSTR RmGetMeasureName(void* rm) -{ - return (LPCWSTR)RmGet(rm, RMG_MEASURENAME); -} - -__inline LPCWSTR RmGetSettingsFile() -{ - return (LPCWSTR)RmGet(NULL, RMG_SETTINGSFILE); -} - -__inline void* RmGetSkin(void* rm) -{ - return (void*)RmGet(rm, RMG_SKIN); -} - -__inline LPCWSTR RmGetSkinName(void* rm) -{ - return (LPCWSTR)RmGet(rm, RMG_SKINNAME); -} - -__inline HWND RmGetSkinWindow(void* rm) -{ - return (HWND)RmGet(rm, RMG_SKINWINDOWHANDLE); -} - -__inline void RmLog(int level, LPCWSTR message) -{ - LSLog(level, NULL, message); -} - -enum LOGLEVEL -{ - LOG_ERROR = 1, - LOG_WARNING = 2, - LOG_NOTICE = 3, - LOG_DEBUG = 4 -}; -#endif // LIBRARY_EXPORTS - -#endif +/* + Copyright (C) 2011 Kimmo Pekkola, Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __RAINMETERAPI_H__ +#define __RAINMETERAPI_H__ + +#ifdef LIBRARY_EXPORTS +#define LIBRARY_EXPORT EXTERN_C +#else +#define LIBRARY_EXPORT EXTERN_C __declspec(dllimport) +#endif // LIBRARY_EXPORTS + +#define PLUGIN_EXPORT EXTERN_C __declspec(dllexport) + +// +// Exported functions +// + +#ifdef __cplusplus +LIBRARY_EXPORT LPCWSTR __stdcall RmReadString(void* rm, LPCWSTR option, LPCWSTR defValue, BOOL replaceMeasures = TRUE); +#else +LIBRARY_EXPORT LPCWSTR __stdcall RmReadString(void* rm, LPCWSTR option, LPCWSTR defValue, BOOL replaceMeasures); +#endif // __cplusplus + +LIBRARY_EXPORT double __stdcall RmReadFormula(void* rm, LPCWSTR option, double defValue); + +LIBRARY_EXPORT LPCWSTR __stdcall RmReplaceVariables(void* rm, LPCWSTR str); + +LIBRARY_EXPORT LPCWSTR __stdcall RmPathToAbsolute(void* rm, LPCWSTR relativePath); + +LIBRARY_EXPORT void __stdcall RmExecute(void* skin, LPCWSTR command); + +LIBRARY_EXPORT void* __stdcall RmGet(void* rm, int type); + +enum RmGetType +{ + RMG_MEASURENAME = 0, + RMG_SKIN = 1, + RMG_SETTINGSFILE = 2, + RMG_SKINNAME = 3, + RMG_SKINWINDOWHANDLE = 4 +}; + +LIBRARY_EXPORT void __stdcall RmLog(void* rm, int level, LPCWSTR message); + +LIBRARY_EXPORT void __cdecl RmLogF(void* rm, int level, LPCWSTR format, ...); + +LIBRARY_EXPORT BOOL __cdecl LSLog(int level, LPCWSTR unused, LPCWSTR message); + +// +// Wrapper functions +// + +#ifndef LIBRARY_EXPORTS +__inline LPCWSTR RmReadPath(void* rm, LPCWSTR option, LPCWSTR defValue) +{ + LPCWSTR relativePath = RmReadString(rm, option, defValue, TRUE); + return RmPathToAbsolute(rm, relativePath); +} + +__inline int RmReadInt(void* rm, LPCWSTR option, int defValue) +{ + return (int)RmReadFormula(rm, option, defValue); +} + +__inline double RmReadDouble(void* rm, LPCWSTR option, double defValue) +{ + return RmReadFormula(rm, option, defValue); +} + +__inline LPCWSTR RmGetMeasureName(void* rm) +{ + return (LPCWSTR)RmGet(rm, RMG_MEASURENAME); +} + +__inline LPCWSTR RmGetSettingsFile() +{ + return (LPCWSTR)RmGet(NULL, RMG_SETTINGSFILE); +} + +__inline void* RmGetSkin(void* rm) +{ + return (void*)RmGet(rm, RMG_SKIN); +} + +__inline LPCWSTR RmGetSkinName(void* rm) +{ + return (LPCWSTR)RmGet(rm, RMG_SKINNAME); +} + +__inline HWND RmGetSkinWindow(void* rm) +{ + return (HWND)RmGet(rm, RMG_SKINWINDOWHANDLE); +} + +__inline void RmLog(int level, LPCWSTR message) +{ + LSLog(level, NULL, message); +} + +enum LOGLEVEL +{ + LOG_ERROR = 1, + LOG_WARNING = 2, + LOG_NOTICE = 3, + LOG_DEBUG = 4 +}; +#endif // LIBRARY_EXPORTS + +#endif diff --git a/Plugins/API/x32/Rainmeter.lib b/Plugins/API/x32/Rainmeter.lib deleted file mode 100644 index f7d3cb6655ecce39c3a25975b4b9827101f1ace6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4426 zcmcInJ#QOF5FL`XL{T4P6z4lZ=s<9iMv+dWL?b~!S+Wwrlq{TR!`=DBJ5vYnM1dlW zq{<&i?aGy#`~x>>48vWD6e-df2GY9nA8_8>?jCP>N1BY41?Ki|kf>zibmzUkV|VYlO*G^?xYn8fo> zt+-kE?X)|7uVu#^qjvT@ZP^X?w%zgUqn3MCtwg7dkD2~~-94_iH;>NRtzOrS`o~91 z|N2jEW56w9GW{RiZgdK%ntrW~B^v#2QF<`4quHU=4l%BbQsKSYYMNUNSYaP#Ny2?wpg@>|-6I3pV#?wZ}wHj^z)N5fbT@%L@*j#Lj92T#Uv9oT^`B@H% z_lfzi*5|__2w_YSIa#8IGelSNM2`{a572L;e>4Xc%oE**JcqnOG#jwpnI(D#$rUgL zc>w{jXpR;rPxF+e8OqTtP18lXKvR^W^w6;ay+ey6o|*8pMs9KZl(bk11E(J;Dl(EH zG|q?^mxfT`Kap4xQ;SM{wUW6iA827UEN+vyG(aE45|tRBN4OH_r}E?7j^>4^Ju%I%7=tEDoOUvt}8!ff$ zxJSL_(xFg^w(#<+Qe8z@OnUoP%>jZXWleXm>m%KW-m+ugqrj1D}&X{sli|6Da|X3)g3yZrj4_@jpWsR z0=x|BB^2-da#)*u^0k%LlCeGj)&+qj%7wSZQN`uJ9)1X%ivma1Av%zzjk9+ufehfh z51gsstoUET&cHP`DN1?BYWRAZ7ORQXO&W%dKgPO7#b8z-4%B0Bi8mx?aB7;%s=Rz1DA3@TzhD5y-|sB-JfxE-a|ty)=Le!02;e>>V(E9+-M2BmAQUH~lVH$o=XNhirZkn)yVk{sD`>!!K3v319&nm2E4uNZ4v z)jNi1Snj^(w4D}AbMtPc((Qs@10Ug0{pIfFZS&@Gbs2_dIF`NLZn^t)dV%X5n3_o_ ztId|zX;_+rva!cO!>TzuR?D?^8_r?GEjD0yTUL9o+Faf}Y&JS=C-97!4e!=NrxtZk zy5arow1daEZ+MkvICbv(mes(COslADhhC!3aj!J@@4Iz9`nY+k(W$%pH(IV;SM$|O z!P;)nMkr9VClT90t>u`trgz{r9B7JIcHiVs*kaJ{MMe(W9s7|O65WCMycqI%nh5=T z6nHlVoF50CO#xR)MzX-m3~*@@cuMktWQX*}lmRa$fH%~xQ~QAY-jb~6{KUW{rjSJj zr!kH+CNPFkjNlZ8kUDZKhc7S8 zDAlxpWP0`BMptmswJQyxcQ^^G}`BrP(=oX5UNOPlj=B&Ni|`AU29?#&&i)^^4n5#R_$PQ;KZM$laK6 zZL4ivEU2Ng)cK3#KWP}Iwv5?V(r-bUiTl71;VD11myv&!qV_Ch1YeopnBbr;<4lfH z4}be(bmCL{`u+5VTWd8BoA=xKE5`Tv%G%~_Ij%L7li;baP|Er}%0o&ywrMyh^B&NA zU%&qoA3sK)A!kZX78Q0G@Ta_|EPj9jN%|DohaN)UQwl9?|Bi3+;a+x74pqB8AY0uWo>d)*Q;t)!NUGnF$fdX-UDnO0PG_WMUEvSq)|u)h7Q?YA_A z1X>Qdx<$3Pd9FA)UF|1)mNBb1(PiBdJstIQ?}PcpMM?Y^#yLV5A`I<=r3HY2v#hw( z8;i`PAQDlkP`fr9DG-jSTN?J#A+jLI|j!~V)$tv zFIsfzV4Bts6B06aJiwC0oc8j;<0=LJ#QI4@KfzSrGb6hG`A&$KbT0Afu9crB#Y)Uw eiRIU;I*_LIvty;+XT;YO50`C`dRcol(*FaW -#include -#include "../PluginPerfMon/Titledb.h" -#include "../PluginPerfMon/PerfSnap.h" -#include "../PluginPerfMon/PerfObj.h" -#include "../PluginPerfMon/PerfCntr.h" -#include "../PluginPerfMon/ObjList.h" -#include "../PluginPerfMon/ObjInst.h" -#include "../API/RainmeterAPI.h" -#include "../../Common/RawString.h" - -struct MeasureData -{ - std::vector includes; - std::vector excludes; - RawString includesCache; - RawString excludesCache; - int topProcess; - RawString topProcessName; - LONGLONG topProcessValue; - - MeasureData() : - topProcess(-1), - topProcessValue() - { - } -}; - -struct ProcessValues -{ - RawString name; - LONGLONG oldValue; - LONGLONG newValue; - bool found; -}; - -static CPerfTitleDatabase g_CounterTitles(PERF_TITLE_COUNTER); -std::vector g_Processes; - -void UpdateProcesses(); - -void SplitName(WCHAR* names, std::vector& splittedNames) -{ - WCHAR* token = wcstok(names, L";"); - while (token != nullptr) - { - splittedNames.push_back(token); - token = wcstok(nullptr, L";"); - } -} - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - MeasureData* measure = new MeasureData; - *data = measure; -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - MeasureData* measure = (MeasureData*)data; - bool changed = false; - - LPCWSTR value = RmReadString(rm, L"CPUInclude", L""); - if (_wcsicmp(value, measure->includesCache.c_str()) != 0) - { - measure->includesCache = value; - measure->includes.clear(); - - WCHAR* buffer = _wcsdup(value); - SplitName(buffer, measure->includes); - delete buffer; - changed = true; - } - - value = RmReadString(rm, L"CPUExclude", L""); - if (_wcsicmp(value, measure->excludesCache.c_str()) != 0) - { - measure->excludesCache = value; - measure->excludes.clear(); - - WCHAR* buffer = _wcsdup(value); - SplitName(buffer, measure->excludes); - delete buffer; - changed = true; - } - - int topProcess = RmReadInt(rm, L"TopProcess", 0); - if (topProcess != measure->topProcess) - { - measure->topProcess = topProcess; - changed = true; - } - - if (changed) - { - *maxValue = 10000000; // The values are 100 * 100000 - } -} - -bool CheckProcess(MeasureData* measure, const WCHAR* name) -{ - if (measure->includes.empty()) - { - for (size_t i = 0; i < measure->excludes.size(); ++i) - { - if (_wcsicmp(measure->excludes[i].c_str(), name) == 0) - { - return false; // Exclude - } - } - return true; // Include - } - else - { - for (size_t i = 0; i < measure->includes.size(); ++i) - { - if (_wcsicmp(measure->includes[i].c_str(), name) == 0) - { - return true; // Include - } - } - } - return false; -} - -ULONGLONG _GetTickCount64() -{ - typedef ULONGLONG (WINAPI * FPGETTICKCOUNT64)(); - static FPGETTICKCOUNT64 c_GetTickCount64 = (FPGETTICKCOUNT64)GetProcAddress(GetModuleHandle(L"kernel32"), "GetTickCount64"); - - if (c_GetTickCount64) - { - return c_GetTickCount64(); - } - else - { - static ULONGLONG lastTicks = 0; - ULONGLONG ticks = GetTickCount(); - while (ticks < lastTicks) ticks += 0x100000000; - lastTicks = ticks; - return ticks; - } -} - -PLUGIN_EXPORT double Update(void* data) -{ - MeasureData* measure = (MeasureData*)data; - static ULONGLONG oldTime = 0; - - // Only update twice per second - ULONGLONG time = _GetTickCount64(); - if (oldTime == 0 || time - oldTime > 500) - { - UpdateProcesses(); - oldTime = time; - } - - LONGLONG newValue = 0; - - for (size_t i = 0; i < g_Processes.size(); ++i) - { - // Check process include/exclude - if (CheckProcess(measure, g_Processes[i].name.c_str())) - { - if (g_Processes[i].oldValue != 0) - { - LONGLONG value = g_Processes[i].newValue - g_Processes[i].oldValue; - - if (measure->topProcess == 0) - { - // Add all values together - newValue += value; - } - else - { - // Find the top process - if (newValue < value) - { - newValue = value; - measure->topProcessName = g_Processes[i].name; - measure->topProcessValue = newValue; - } - } - } - } - } - - return (double)newValue; -} - -PLUGIN_EXPORT LPCWSTR GetString(void* data) -{ - MeasureData* measure = (MeasureData*)data; - - if (measure->topProcess == 2) - { - return measure->topProcessName.c_str(); - } - - return nullptr; -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - MeasureData* measure = (MeasureData*)data; - delete measure; - - CPerfSnapshot::CleanUp(); -} - -/* - This updates the process status -*/ -void UpdateProcesses() -{ - BYTE data[256]; - WCHAR name[256]; - - std::vector newProcesses; - newProcesses.reserve(g_Processes.size()); - - CPerfSnapshot snapshot(&g_CounterTitles); - CPerfObjectList objList(&snapshot, &g_CounterTitles); - - if (snapshot.TakeSnapshot(L"Process")) - { - CPerfObject* pPerfObj = objList.GetPerfObject(L"Process"); - - if (pPerfObj) - { - for (CPerfObjectInstance* pObjInst = pPerfObj->GetFirstObjectInstance(); - pObjInst != nullptr; - pObjInst = pPerfObj->GetNextObjectInstance()) - { - if (pObjInst->GetObjectInstanceName(name, 256)) - { - if (_wcsicmp(name, L"_Total") == 0) - { - delete pObjInst; - continue; - } - - CPerfCounter* pPerfCntr = pObjInst->GetCounterByName(L"% Processor Time"); - if (pPerfCntr != nullptr) - { - pPerfCntr->GetData(data, 256, nullptr); - - if (pPerfCntr->GetSize() == 8) - { - ProcessValues values; - values.name = name; - values.oldValue = 0; - values.newValue = *(ULONGLONG*)data; - values.found = false; - - // Check if we can find the old value - for (size_t i = 0; i < g_Processes.size(); ++i) - { - if (!g_Processes[i].found && _wcsicmp(g_Processes[i].name.c_str(), name) == 0) - { - values.oldValue = g_Processes[i].newValue; - g_Processes[i].found = true; - break; - } - } - - newProcesses.push_back(std::move(values)); - } - - delete pPerfCntr; - } - } - - delete pObjInst; - } - - delete pPerfObj; - } - } - - g_Processes = std::move(newProcesses); -} +/* + Copyright (C) 2004 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include "../PluginPerfMon/Titledb.h" +#include "../PluginPerfMon/PerfSnap.h" +#include "../PluginPerfMon/PerfObj.h" +#include "../PluginPerfMon/PerfCntr.h" +#include "../PluginPerfMon/ObjList.h" +#include "../PluginPerfMon/ObjInst.h" +#include "../API/RainmeterAPI.h" +#include "../../Common/RawString.h" + +struct MeasureData +{ + std::vector includes; + std::vector excludes; + RawString includesCache; + RawString excludesCache; + int topProcess; + RawString topProcessName; + LONGLONG topProcessValue; + + MeasureData() : + topProcess(-1), + topProcessValue() + { + } +}; + +struct ProcessValues +{ + RawString name; + LONGLONG oldValue; + LONGLONG newValue; + bool found; +}; + +static CPerfTitleDatabase g_CounterTitles(PERF_TITLE_COUNTER); +std::vector g_Processes; + +void UpdateProcesses(); + +void SplitName(WCHAR* names, std::vector& splittedNames) +{ + WCHAR* token = wcstok(names, L";"); + while (token != nullptr) + { + splittedNames.push_back(token); + token = wcstok(nullptr, L";"); + } +} + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + MeasureData* measure = new MeasureData; + *data = measure; +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + MeasureData* measure = (MeasureData*)data; + bool changed = false; + + LPCWSTR value = RmReadString(rm, L"CPUInclude", L""); + if (_wcsicmp(value, measure->includesCache.c_str()) != 0) + { + measure->includesCache = value; + measure->includes.clear(); + + WCHAR* buffer = _wcsdup(value); + SplitName(buffer, measure->includes); + delete buffer; + changed = true; + } + + value = RmReadString(rm, L"CPUExclude", L""); + if (_wcsicmp(value, measure->excludesCache.c_str()) != 0) + { + measure->excludesCache = value; + measure->excludes.clear(); + + WCHAR* buffer = _wcsdup(value); + SplitName(buffer, measure->excludes); + delete buffer; + changed = true; + } + + int topProcess = RmReadInt(rm, L"TopProcess", 0); + if (topProcess != measure->topProcess) + { + measure->topProcess = topProcess; + changed = true; + } + + if (changed) + { + *maxValue = 10000000; // The values are 100 * 100000 + } +} + +bool CheckProcess(MeasureData* measure, const WCHAR* name) +{ + if (measure->includes.empty()) + { + for (size_t i = 0; i < measure->excludes.size(); ++i) + { + if (_wcsicmp(measure->excludes[i].c_str(), name) == 0) + { + return false; // Exclude + } + } + return true; // Include + } + else + { + for (size_t i = 0; i < measure->includes.size(); ++i) + { + if (_wcsicmp(measure->includes[i].c_str(), name) == 0) + { + return true; // Include + } + } + } + return false; +} + +ULONGLONG _GetTickCount64() +{ + typedef ULONGLONG (WINAPI * FPGETTICKCOUNT64)(); + static FPGETTICKCOUNT64 c_GetTickCount64 = (FPGETTICKCOUNT64)GetProcAddress(GetModuleHandle(L"kernel32"), "GetTickCount64"); + + if (c_GetTickCount64) + { + return c_GetTickCount64(); + } + else + { + static ULONGLONG lastTicks = 0; + ULONGLONG ticks = GetTickCount(); + while (ticks < lastTicks) ticks += 0x100000000; + lastTicks = ticks; + return ticks; + } +} + +PLUGIN_EXPORT double Update(void* data) +{ + MeasureData* measure = (MeasureData*)data; + static ULONGLONG oldTime = 0; + + // Only update twice per second + ULONGLONG time = _GetTickCount64(); + if (oldTime == 0 || time - oldTime > 500) + { + UpdateProcesses(); + oldTime = time; + } + + LONGLONG newValue = 0; + + for (size_t i = 0; i < g_Processes.size(); ++i) + { + // Check process include/exclude + if (CheckProcess(measure, g_Processes[i].name.c_str())) + { + if (g_Processes[i].oldValue != 0) + { + LONGLONG value = g_Processes[i].newValue - g_Processes[i].oldValue; + + if (measure->topProcess == 0) + { + // Add all values together + newValue += value; + } + else + { + // Find the top process + if (newValue < value) + { + newValue = value; + measure->topProcessName = g_Processes[i].name; + measure->topProcessValue = newValue; + } + } + } + } + } + + return (double)newValue; +} + +PLUGIN_EXPORT LPCWSTR GetString(void* data) +{ + MeasureData* measure = (MeasureData*)data; + + if (measure->topProcess == 2) + { + return measure->topProcessName.c_str(); + } + + return nullptr; +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + MeasureData* measure = (MeasureData*)data; + delete measure; + + CPerfSnapshot::CleanUp(); +} + +/* + This updates the process status +*/ +void UpdateProcesses() +{ + BYTE data[256]; + WCHAR name[256]; + + std::vector newProcesses; + newProcesses.reserve(g_Processes.size()); + + CPerfSnapshot snapshot(&g_CounterTitles); + CPerfObjectList objList(&snapshot, &g_CounterTitles); + + if (snapshot.TakeSnapshot(L"Process")) + { + CPerfObject* pPerfObj = objList.GetPerfObject(L"Process"); + + if (pPerfObj) + { + for (CPerfObjectInstance* pObjInst = pPerfObj->GetFirstObjectInstance(); + pObjInst != nullptr; + pObjInst = pPerfObj->GetNextObjectInstance()) + { + if (pObjInst->GetObjectInstanceName(name, 256)) + { + if (_wcsicmp(name, L"_Total") == 0) + { + delete pObjInst; + continue; + } + + CPerfCounter* pPerfCntr = pObjInst->GetCounterByName(L"% Processor Time"); + if (pPerfCntr != nullptr) + { + pPerfCntr->GetData(data, 256, nullptr); + + if (pPerfCntr->GetSize() == 8) + { + ProcessValues values; + values.name = name; + values.oldValue = 0; + values.newValue = *(ULONGLONG*)data; + values.found = false; + + // Check if we can find the old value + for (size_t i = 0; i < g_Processes.size(); ++i) + { + if (!g_Processes[i].found && _wcsicmp(g_Processes[i].name.c_str(), name) == 0) + { + values.oldValue = g_Processes[i].newValue; + g_Processes[i].found = true; + break; + } + } + + newProcesses.push_back(std::move(values)); + } + + delete pPerfCntr; + } + } + + delete pObjInst; + } + + delete pPerfObj; + } + } + + g_Processes = std::move(newProcesses); +} diff --git a/Plugins/PluginAdvancedCPU/PluginAdvancedCPU.rc b/Plugins/PluginAdvancedCPU/PluginAdvancedCPU.rc index 4caca28b..cd18f915 100644 --- a/Plugins/PluginAdvancedCPU/PluginAdvancedCPU.rc +++ b/Plugins/PluginAdvancedCPU/PluginAdvancedCPU.rc @@ -1,40 +1,40 @@ -#include -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,5,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.5.0.0" - VALUE "LegalCopyright", " 2010 - Rainy" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,5,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.5.0.0" + VALUE "LegalCopyright", " 2010 - Rainy" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginAdvancedCPU/PluginAdvancedCPU.vcxproj b/Plugins/PluginAdvancedCPU/PluginAdvancedCPU.vcxproj index 05bb5732..428854fa 100644 --- a/Plugins/PluginAdvancedCPU/PluginAdvancedCPU.vcxproj +++ b/Plugins/PluginAdvancedCPU/PluginAdvancedCPU.vcxproj @@ -1,44 +1,44 @@ - - - - - {EE8EC522-8430-4B46-86A3-D943D77F9E4B} - DynamicLibrary - AdvancedCPU - - - - - - - - - - - - - - _USRDLL;%(PreprocessorDefinitions) - - - - - - - - - - - - - - - - - - - - - - + + + + + {EE8EC522-8430-4B46-86A3-D943D77F9E4B} + DynamicLibrary + AdvancedCPU + + + + + + + + + + + + + + _USRDLL;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Plugins/PluginCoreTemp/CoreTempProxy.cpp b/Plugins/PluginCoreTemp/CoreTempProxy.cpp index f6f32077..151a69db 100644 --- a/Plugins/PluginCoreTemp/CoreTempProxy.cpp +++ b/Plugins/PluginCoreTemp/CoreTempProxy.cpp @@ -1,98 +1,98 @@ -#include -#include "CoreTempProxy.h" - -CoreTempProxy::CoreTempProxy(void) -{ - memset(&this->m_pCoreTempData, 0, sizeof(CORE_TEMP_SHARED_DATA)); -} - -CoreTempProxy::~CoreTempProxy(void) -{ -} - -UINT CoreTempProxy::GetCoreLoad(int i_Index) const -{ - return this->m_pCoreTempData.uiLoad[i_Index]; -} - -UINT CoreTempProxy::GetTjMax(int i_Index) const -{ - return this->m_pCoreTempData.uiTjMax[i_Index]; -} - -UINT CoreTempProxy::GetCoreCount() const -{ - return this->m_pCoreTempData.uiCoreCnt; -} - -UINT CoreTempProxy::GetCPUCount() const -{ - return this->m_pCoreTempData.uiCPUCnt; -} - -float CoreTempProxy::GetTemp(int i_Index) const -{ - return this->m_pCoreTempData.fTemp[i_Index]; -} - -float CoreTempProxy::GetVID() const -{ - return this->m_pCoreTempData.fVID; -} - -float CoreTempProxy::GetCPUSpeed() const -{ - return this->m_pCoreTempData.fCPUSpeed; -} - -float CoreTempProxy::GetFSBSpeed() const -{ - return this->m_pCoreTempData.fFSBSpeed; -} - -float CoreTempProxy::GetMultiplier() const -{ - return this->m_pCoreTempData.fMultipier; -} - -LPCSTR CoreTempProxy::GetCPUName() const -{ - return this->m_pCoreTempData.sCPUName; -} - -bool CoreTempProxy::IsFahrenheit() const -{ - return this->m_pCoreTempData.ucFahrenheit != 0; -} - -bool CoreTempProxy::IsDistanceToTjMax() const -{ - return this->m_pCoreTempData.ucDeltaToTjMax != 0; -} - -const CORE_TEMP_SHARED_DATA &CoreTempProxy::GetDataStruct() const -{ - return this->m_pCoreTempData; -} - -bool CoreTempProxy::GetData() -{ - return this->m_SharedMem.ReadSharedMem(&this->m_pCoreTempData); -} - -LPCWSTR CoreTempProxy::GetErrorMessage() -{ - DWORD lastError; - - lastError = ::GetLastError(); - if ((lastError & UNKNOWN_EXCEPTION) > 0) - { - wcscpy_s(this->m_ErrorMessage, L"Unknown error occured while copying shared memory."); - } - else - { - ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, lastError, 0, this->m_ErrorMessage, 99, nullptr); - } - - return this->m_ErrorMessage; +#include +#include "CoreTempProxy.h" + +CoreTempProxy::CoreTempProxy(void) +{ + memset(&this->m_pCoreTempData, 0, sizeof(CORE_TEMP_SHARED_DATA)); +} + +CoreTempProxy::~CoreTempProxy(void) +{ +} + +UINT CoreTempProxy::GetCoreLoad(int i_Index) const +{ + return this->m_pCoreTempData.uiLoad[i_Index]; +} + +UINT CoreTempProxy::GetTjMax(int i_Index) const +{ + return this->m_pCoreTempData.uiTjMax[i_Index]; +} + +UINT CoreTempProxy::GetCoreCount() const +{ + return this->m_pCoreTempData.uiCoreCnt; +} + +UINT CoreTempProxy::GetCPUCount() const +{ + return this->m_pCoreTempData.uiCPUCnt; +} + +float CoreTempProxy::GetTemp(int i_Index) const +{ + return this->m_pCoreTempData.fTemp[i_Index]; +} + +float CoreTempProxy::GetVID() const +{ + return this->m_pCoreTempData.fVID; +} + +float CoreTempProxy::GetCPUSpeed() const +{ + return this->m_pCoreTempData.fCPUSpeed; +} + +float CoreTempProxy::GetFSBSpeed() const +{ + return this->m_pCoreTempData.fFSBSpeed; +} + +float CoreTempProxy::GetMultiplier() const +{ + return this->m_pCoreTempData.fMultipier; +} + +LPCSTR CoreTempProxy::GetCPUName() const +{ + return this->m_pCoreTempData.sCPUName; +} + +bool CoreTempProxy::IsFahrenheit() const +{ + return this->m_pCoreTempData.ucFahrenheit != 0; +} + +bool CoreTempProxy::IsDistanceToTjMax() const +{ + return this->m_pCoreTempData.ucDeltaToTjMax != 0; +} + +const CORE_TEMP_SHARED_DATA &CoreTempProxy::GetDataStruct() const +{ + return this->m_pCoreTempData; +} + +bool CoreTempProxy::GetData() +{ + return this->m_SharedMem.ReadSharedMem(&this->m_pCoreTempData); +} + +LPCWSTR CoreTempProxy::GetErrorMessage() +{ + DWORD lastError; + + lastError = ::GetLastError(); + if ((lastError & UNKNOWN_EXCEPTION) > 0) + { + wcscpy_s(this->m_ErrorMessage, L"Unknown error occured while copying shared memory."); + } + else + { + ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, lastError, 0, this->m_ErrorMessage, 99, nullptr); + } + + return this->m_ErrorMessage; } \ No newline at end of file diff --git a/Plugins/PluginCoreTemp/CoreTempProxy.h b/Plugins/PluginCoreTemp/CoreTempProxy.h index 9017e12e..3187b746 100644 --- a/Plugins/PluginCoreTemp/CoreTempProxy.h +++ b/Plugins/PluginCoreTemp/CoreTempProxy.h @@ -1,34 +1,34 @@ -#pragma once -#include "SharedMem.h" - -#define UNKNOWN_EXCEPTION 0x20000000 - -class CoreTempProxy -{ -public: - CoreTempProxy(void); - virtual ~CoreTempProxy(void); - - UINT GetCoreLoad(int i_Index) const; - UINT GetTjMax(int i_Index) const; - UINT GetCoreCount() const; - UINT GetCPUCount() const; - float GetTemp(int i_Index) const; - float GetVID() const; - float GetCPUSpeed() const; - float GetFSBSpeed() const; - float GetMultiplier() const; - LPCSTR GetCPUName() const; - bool IsFahrenheit() const; - bool IsDistanceToTjMax() const; - const CORE_TEMP_SHARED_DATA &GetDataStruct() const; - - bool GetData(); - DWORD GetDllError() const { return GetLastError(); } - LPCWSTR GetErrorMessage(); -private: - - CSharedMemClient m_SharedMem; - CORE_TEMP_SHARED_DATA m_pCoreTempData; - WCHAR m_ErrorMessage[100]; -}; +#pragma once +#include "SharedMem.h" + +#define UNKNOWN_EXCEPTION 0x20000000 + +class CoreTempProxy +{ +public: + CoreTempProxy(void); + virtual ~CoreTempProxy(void); + + UINT GetCoreLoad(int i_Index) const; + UINT GetTjMax(int i_Index) const; + UINT GetCoreCount() const; + UINT GetCPUCount() const; + float GetTemp(int i_Index) const; + float GetVID() const; + float GetCPUSpeed() const; + float GetFSBSpeed() const; + float GetMultiplier() const; + LPCSTR GetCPUName() const; + bool IsFahrenheit() const; + bool IsDistanceToTjMax() const; + const CORE_TEMP_SHARED_DATA &GetDataStruct() const; + + bool GetData(); + DWORD GetDllError() const { return GetLastError(); } + LPCWSTR GetErrorMessage(); +private: + + CSharedMemClient m_SharedMem; + CORE_TEMP_SHARED_DATA m_pCoreTempData; + WCHAR m_ErrorMessage[100]; +}; diff --git a/Plugins/PluginCoreTemp/PluginCoreTemp.cpp b/Plugins/PluginCoreTemp/PluginCoreTemp.cpp index f571d01a..88e82179 100644 --- a/Plugins/PluginCoreTemp/PluginCoreTemp.cpp +++ b/Plugins/PluginCoreTemp/PluginCoreTemp.cpp @@ -1,212 +1,212 @@ -/* - Copyright (C) 2011 Arthur Liberman - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include "CoreTempProxy.h" -#include "../../Library/Export.h" // Rainmeter's exported functions - -typedef enum eMeasureType -{ - MeasureTemperature, - MeasureMaxTemperature, - MeasureTjMax, - MeasureLoad, - MeasureVid, - MeasureCpuSpeed, - MeasureBusSpeed, - MeasureBusMultiplier, - MeasureCpuName -}; - -struct MeasureData -{ - eMeasureType type; - int index; - - MeasureData() : type(), index() {} -}; - -CoreTempProxy proxy; - -eMeasureType convertStringToMeasureType(LPCWSTR i_String); -bool areStringsEqual(LPCWSTR i_String1, LPCWSTR i_Strting2); -float getHighestTemp(); - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - MeasureData* measure = new MeasureData; - *data = measure; -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - MeasureData* measure = (MeasureData*)data; - - LPCWSTR value = RmReadString(rm, L"CoreTempType", L"Temperature"); - measure->type = convertStringToMeasureType(value); - - if (measure->type == MeasureTemperature || measure->type == MeasureTjMax || measure->type == MeasureLoad) - { - measure->index = RmReadInt(rm, L"CoreTempIndex", 0); - } -} - -PLUGIN_EXPORT double Update(void* data) -{ - MeasureData* measure = (MeasureData*)data; - double result = 0; - - if (proxy.GetData()) - { - switch (measure->type) - { - case MeasureTemperature: - result = proxy.GetTemp(measure->index); - break; - - case MeasureMaxTemperature: - result = getHighestTemp(); - break; - - case MeasureTjMax: - result = proxy.GetTjMax(measure->index); - break; - - case MeasureLoad: - result = proxy.GetCoreLoad(measure->index); - break; - - case MeasureVid: - result = proxy.GetVID(); - break; - - case MeasureCpuSpeed: - result = proxy.GetCPUSpeed(); - break; - - case MeasureBusSpeed: - result = proxy.GetFSBSpeed(); - break; - - case MeasureBusMultiplier: - result = proxy.GetMultiplier(); - break; - } - } - - return result; -} - -PLUGIN_EXPORT LPCWSTR GetString(void* data) -{ - MeasureData* measure = (MeasureData*)data; - static WCHAR buffer[128]; - - switch (measure->type) - { - case MeasureVid: - _snwprintf_s(buffer, _TRUNCATE, L"%.4f", proxy.GetVID()); - break; - - case MeasureCpuName: - _snwprintf_s(buffer, _TRUNCATE, L"%S", proxy.GetCPUName()); - break; - - default: - return nullptr; - } - - return buffer; -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - MeasureData* measure = (MeasureData*)data; - delete measure; -} - -bool areStringsEqual(LPCWSTR i_String1, LPCWSTR i_Strting2) -{ - return _wcsicmp(i_String1, i_Strting2) == 0; -} - -eMeasureType convertStringToMeasureType(LPCWSTR i_String) -{ - eMeasureType result; - - if (areStringsEqual(i_String, L"Temperature")) - { - result = MeasureTemperature; - } - else if (areStringsEqual(i_String, L"MaxTemperature")) - { - result = MeasureMaxTemperature; - } - else if (areStringsEqual(i_String, L"TjMax")) - { - result = MeasureTjMax; - } - else if (areStringsEqual(i_String, L"Load")) - { - result = MeasureLoad; - } - else if (areStringsEqual(i_String, L"Vid")) - { - result = MeasureVid; - } - else if (areStringsEqual(i_String, L"CpuSpeed")) - { - result = MeasureCpuSpeed; - } - else if (areStringsEqual(i_String, L"BusSpeed")) - { - result = MeasureBusSpeed; - } - else if (areStringsEqual(i_String, L"BusMultiplier")) - { - result = MeasureBusMultiplier; - } - else if (areStringsEqual(i_String, L"CpuName")) - { - result = MeasureCpuName; - } - else - { - result = MeasureTemperature; - RmLog(LOG_WARNING, L"CoreTemp.dll: Invalid CoreTempType"); - } - - return result; -} - -float getHighestTemp() -{ - float temp = -255; - UINT coreCount = proxy.GetCoreCount(); - - for (UINT i = 0; i < coreCount; ++i) - { - if (temp < proxy.GetTemp(i)) - { - temp = proxy.GetTemp(i); - } - } - - return temp; -} +/* + Copyright (C) 2011 Arthur Liberman + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include "CoreTempProxy.h" +#include "../../Library/Export.h" // Rainmeter's exported functions + +typedef enum eMeasureType +{ + MeasureTemperature, + MeasureMaxTemperature, + MeasureTjMax, + MeasureLoad, + MeasureVid, + MeasureCpuSpeed, + MeasureBusSpeed, + MeasureBusMultiplier, + MeasureCpuName +}; + +struct MeasureData +{ + eMeasureType type; + int index; + + MeasureData() : type(), index() {} +}; + +CoreTempProxy proxy; + +eMeasureType convertStringToMeasureType(LPCWSTR i_String); +bool areStringsEqual(LPCWSTR i_String1, LPCWSTR i_Strting2); +float getHighestTemp(); + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + MeasureData* measure = new MeasureData; + *data = measure; +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + MeasureData* measure = (MeasureData*)data; + + LPCWSTR value = RmReadString(rm, L"CoreTempType", L"Temperature"); + measure->type = convertStringToMeasureType(value); + + if (measure->type == MeasureTemperature || measure->type == MeasureTjMax || measure->type == MeasureLoad) + { + measure->index = RmReadInt(rm, L"CoreTempIndex", 0); + } +} + +PLUGIN_EXPORT double Update(void* data) +{ + MeasureData* measure = (MeasureData*)data; + double result = 0; + + if (proxy.GetData()) + { + switch (measure->type) + { + case MeasureTemperature: + result = proxy.GetTemp(measure->index); + break; + + case MeasureMaxTemperature: + result = getHighestTemp(); + break; + + case MeasureTjMax: + result = proxy.GetTjMax(measure->index); + break; + + case MeasureLoad: + result = proxy.GetCoreLoad(measure->index); + break; + + case MeasureVid: + result = proxy.GetVID(); + break; + + case MeasureCpuSpeed: + result = proxy.GetCPUSpeed(); + break; + + case MeasureBusSpeed: + result = proxy.GetFSBSpeed(); + break; + + case MeasureBusMultiplier: + result = proxy.GetMultiplier(); + break; + } + } + + return result; +} + +PLUGIN_EXPORT LPCWSTR GetString(void* data) +{ + MeasureData* measure = (MeasureData*)data; + static WCHAR buffer[128]; + + switch (measure->type) + { + case MeasureVid: + _snwprintf_s(buffer, _TRUNCATE, L"%.4f", proxy.GetVID()); + break; + + case MeasureCpuName: + _snwprintf_s(buffer, _TRUNCATE, L"%S", proxy.GetCPUName()); + break; + + default: + return nullptr; + } + + return buffer; +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + MeasureData* measure = (MeasureData*)data; + delete measure; +} + +bool areStringsEqual(LPCWSTR i_String1, LPCWSTR i_Strting2) +{ + return _wcsicmp(i_String1, i_Strting2) == 0; +} + +eMeasureType convertStringToMeasureType(LPCWSTR i_String) +{ + eMeasureType result; + + if (areStringsEqual(i_String, L"Temperature")) + { + result = MeasureTemperature; + } + else if (areStringsEqual(i_String, L"MaxTemperature")) + { + result = MeasureMaxTemperature; + } + else if (areStringsEqual(i_String, L"TjMax")) + { + result = MeasureTjMax; + } + else if (areStringsEqual(i_String, L"Load")) + { + result = MeasureLoad; + } + else if (areStringsEqual(i_String, L"Vid")) + { + result = MeasureVid; + } + else if (areStringsEqual(i_String, L"CpuSpeed")) + { + result = MeasureCpuSpeed; + } + else if (areStringsEqual(i_String, L"BusSpeed")) + { + result = MeasureBusSpeed; + } + else if (areStringsEqual(i_String, L"BusMultiplier")) + { + result = MeasureBusMultiplier; + } + else if (areStringsEqual(i_String, L"CpuName")) + { + result = MeasureCpuName; + } + else + { + result = MeasureTemperature; + RmLog(LOG_WARNING, L"CoreTemp.dll: Invalid CoreTempType"); + } + + return result; +} + +float getHighestTemp() +{ + float temp = -255; + UINT coreCount = proxy.GetCoreCount(); + + for (UINT i = 0; i < coreCount; ++i) + { + if (temp < proxy.GetTemp(i)) + { + temp = proxy.GetTemp(i); + } + } + + return temp; +} diff --git a/Plugins/PluginCoreTemp/PluginCoreTemp.rc b/Plugins/PluginCoreTemp/PluginCoreTemp.rc index 6390bbf7..791b07c6 100644 --- a/Plugins/PluginCoreTemp/PluginCoreTemp.rc +++ b/Plugins/PluginCoreTemp/PluginCoreTemp.rc @@ -1,40 +1,40 @@ -#include -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.0.0.0" - VALUE "LegalCopyright", " 2011 - Arthur Liberman" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.0.0.0" + VALUE "LegalCopyright", " 2011 - Arthur Liberman" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginCoreTemp/PluginCoreTemp.vcxproj b/Plugins/PluginCoreTemp/PluginCoreTemp.vcxproj index 1df57f81..2a8eaa83 100644 --- a/Plugins/PluginCoreTemp/PluginCoreTemp.vcxproj +++ b/Plugins/PluginCoreTemp/PluginCoreTemp.vcxproj @@ -1,41 +1,41 @@ - - - - - {F32FA418-8DF4-4E94-B92B-EBD502F5DC07} - DynamicLibrary - CoreTemp - - - - - - - - - - - - - - _USRDLL;%(PreprocessorDefinitions) - - - - - - - - - - - - - - - - - - - + + + + + {F32FA418-8DF4-4E94-B92B-EBD502F5DC07} + DynamicLibrary + CoreTemp + + + + + + + + + + + + + + _USRDLL;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Plugins/PluginCoreTemp/SharedMem.cpp b/Plugins/PluginCoreTemp/SharedMem.cpp index 0a598b3f..0393820d 100644 --- a/Plugins/PluginCoreTemp/SharedMem.cpp +++ b/Plugins/PluginCoreTemp/SharedMem.cpp @@ -1,66 +1,66 @@ -#include -#include "SharedMem.h" - -CSharedMemClient::CSharedMemClient(void) -{ -} - -CSharedMemClient::~CSharedMemClient(void) -{ -} - -bool CSharedMemClient::ReadSharedMem(PCORE_TEMP_SHARED_DATA i_SharedData) -{ - bool bRet = false; - PCORE_TEMP_SHARED_DATA pSharedData; - HANDLE hdlMemory; - HANDLE hdlMutex; - - hdlMutex = CreateMutex(nullptr,FALSE,CORE_TEMP_MUTEX_OBJECT); - if (hdlMutex == nullptr) - { - return false; - } - - WaitForSingleObject(hdlMutex, INFINITE); - - hdlMemory = OpenFileMapping( - FILE_MAP_READ, // Read only permission. - TRUE, - CORE_TEMP_MAPPING_OBJECT); // "CoreTempMappingObject" - - if (hdlMemory == nullptr) - { - ReleaseMutex(hdlMutex); - CloseHandle(hdlMutex); - return false; - } - - pSharedData = (PCORE_TEMP_SHARED_DATA)MapViewOfFile(hdlMemory, FILE_MAP_READ, 0, 0, 0); - if (pSharedData == nullptr) - { - CloseHandle(hdlMemory); - hdlMemory = nullptr; - ReleaseMutex(hdlMutex); - CloseHandle(hdlMutex); - return false; - } - - __try - { - memcpy_s(i_SharedData, sizeof(core_temp_shared_data), pSharedData, sizeof(core_temp_shared_data)); - bRet = true; - } - __except(1) - { - bRet = false; - SetLastError(0x20000000); //Unknown error - } - - UnmapViewOfFile(pSharedData); - CloseHandle(hdlMemory); - ReleaseMutex(hdlMutex); - CloseHandle(hdlMutex); - - return bRet; +#include +#include "SharedMem.h" + +CSharedMemClient::CSharedMemClient(void) +{ +} + +CSharedMemClient::~CSharedMemClient(void) +{ +} + +bool CSharedMemClient::ReadSharedMem(PCORE_TEMP_SHARED_DATA i_SharedData) +{ + bool bRet = false; + PCORE_TEMP_SHARED_DATA pSharedData; + HANDLE hdlMemory; + HANDLE hdlMutex; + + hdlMutex = CreateMutex(nullptr,FALSE,CORE_TEMP_MUTEX_OBJECT); + if (hdlMutex == nullptr) + { + return false; + } + + WaitForSingleObject(hdlMutex, INFINITE); + + hdlMemory = OpenFileMapping( + FILE_MAP_READ, // Read only permission. + TRUE, + CORE_TEMP_MAPPING_OBJECT); // "CoreTempMappingObject" + + if (hdlMemory == nullptr) + { + ReleaseMutex(hdlMutex); + CloseHandle(hdlMutex); + return false; + } + + pSharedData = (PCORE_TEMP_SHARED_DATA)MapViewOfFile(hdlMemory, FILE_MAP_READ, 0, 0, 0); + if (pSharedData == nullptr) + { + CloseHandle(hdlMemory); + hdlMemory = nullptr; + ReleaseMutex(hdlMutex); + CloseHandle(hdlMutex); + return false; + } + + __try + { + memcpy_s(i_SharedData, sizeof(core_temp_shared_data), pSharedData, sizeof(core_temp_shared_data)); + bRet = true; + } + __except(1) + { + bRet = false; + SetLastError(0x20000000); //Unknown error + } + + UnmapViewOfFile(pSharedData); + CloseHandle(hdlMemory); + ReleaseMutex(hdlMutex); + CloseHandle(hdlMutex); + + return bRet; } \ No newline at end of file diff --git a/Plugins/PluginCoreTemp/SharedMem.h b/Plugins/PluginCoreTemp/SharedMem.h index 8c9110fd..60707795 100644 --- a/Plugins/PluginCoreTemp/SharedMem.h +++ b/Plugins/PluginCoreTemp/SharedMem.h @@ -1,41 +1,41 @@ -// Common.h: -// -////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_COMMON_H__B302F7F1_E8D6_4EF2_9D89_A634D14922BF__INCLUDED_) -#define AFX_COMMON_H__B302F7F1_E8D6_4EF2_9D89_A634D14922BF__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#define CORE_TEMP_MAPPING_OBJECT L"CoreTempMappingObject" -#define CORE_TEMP_MUTEX_OBJECT L"CoreTempMutexObject" - -typedef struct core_temp_shared_data -{ - unsigned int uiLoad[256]; - unsigned int uiTjMax[128]; - unsigned int uiCoreCnt; - unsigned int uiCPUCnt; - float fTemp[256]; - float fVID; - float fCPUSpeed; - float fFSBSpeed; - float fMultipier; - char sCPUName[100]; - unsigned char ucFahrenheit; - unsigned char ucDeltaToTjMax; -}CORE_TEMP_SHARED_DATA,*PCORE_TEMP_SHARED_DATA,**PPCORE_TEMP_SHARED_DATA; - -class CSharedMemClient -{ -// Construction -public: - CSharedMemClient(void); // standard constructor - virtual ~CSharedMemClient(void); - - bool ReadSharedMem(PCORE_TEMP_SHARED_DATA i_SharedData); -}; - -#endif // !defined(AFX_COMMON_H__B302F7F1_E8D6_4EF2_9D89_A634D14922BF__INCLUDED_) +// Common.h: +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_COMMON_H__B302F7F1_E8D6_4EF2_9D89_A634D14922BF__INCLUDED_) +#define AFX_COMMON_H__B302F7F1_E8D6_4EF2_9D89_A634D14922BF__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define CORE_TEMP_MAPPING_OBJECT L"CoreTempMappingObject" +#define CORE_TEMP_MUTEX_OBJECT L"CoreTempMutexObject" + +typedef struct core_temp_shared_data +{ + unsigned int uiLoad[256]; + unsigned int uiTjMax[128]; + unsigned int uiCoreCnt; + unsigned int uiCPUCnt; + float fTemp[256]; + float fVID; + float fCPUSpeed; + float fFSBSpeed; + float fMultipier; + char sCPUName[100]; + unsigned char ucFahrenheit; + unsigned char ucDeltaToTjMax; +}CORE_TEMP_SHARED_DATA,*PCORE_TEMP_SHARED_DATA,**PPCORE_TEMP_SHARED_DATA; + +class CSharedMemClient +{ +// Construction +public: + CSharedMemClient(void); // standard constructor + virtual ~CSharedMemClient(void); + + bool ReadSharedMem(PCORE_TEMP_SHARED_DATA i_SharedData); +}; + +#endif // !defined(AFX_COMMON_H__B302F7F1_E8D6_4EF2_9D89_A634D14922BF__INCLUDED_) diff --git a/Plugins/PluginFileView/PluginFileView.cpp b/Plugins/PluginFileView/PluginFileView.cpp index 4ae003a9..6c2b2ba5 100644 --- a/Plugins/PluginFileView/PluginFileView.cpp +++ b/Plugins/PluginFileView/PluginFileView.cpp @@ -1,1243 +1,1243 @@ -/* - Copyright (C) 2012 Brian Ferguson - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "PluginFileView.h" -#include "../../Common/StringUtil.h" - -#define MAX_LINE_LENGTH 4096 -#define INVALID_FILE L"/<>\\" - -#pragma pack(push, 2) -typedef struct // 16 bytes -{ - BYTE bWidth; // Width, in pixels, of the image - BYTE bHeight; // Height, in pixels, of the image - BYTE bColorCount; // Number of colors in image (0 if >=8bpp) - BYTE bReserved; // Reserved ( must be 0) - WORD wPlanes; // Color Planes - WORD wBitCount; // Bits per pixel - DWORD dwBytesInRes; // How many bytes in this resource? - DWORD dwImageOffset; // Where in the file is this image? -} ICONDIRENTRY, *LPICONDIRENTRY; - -typedef struct // 22 bytes -{ - WORD idReserved; // Reserved (must be 0) - WORD idType; // Resource Type (1 for icons) - WORD idCount; // How many images? - ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em) -} ICONDIR, *LPICONDIR; -#pragma pack(pop) - -unsigned __stdcall SystemThreadProc(void* pParam); -void GetFolderInfo(std::queue& folderQueue, std::wstring& folder, ParentMeasure* parent, RecursiveType rType); -void GetIcon(std::wstring filePath, const std::wstring& iconPath, IconSize iconSize); -HRESULT SaveIcon(HICON hIcon, FILE* fp); - -static std::vector g_ParentMeasures; -static CRITICAL_SECTION g_CriticalSection; -static std::string g_SysProperties; - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - switch (fdwReason) - { - case DLL_PROCESS_ATTACH: - InitializeCriticalSection(&g_CriticalSection); - - // Disable DLL_THREAD_ATTACH and DLL_THREAD_DETACH notification calls. - DisableThreadLibraryCalls(hinstDLL); - break; - - case DLL_PROCESS_DETACH: - DeleteCriticalSection(&g_CriticalSection); - break; - } - - return TRUE; -} - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - ChildMeasure* child = new ChildMeasure; - *data = child; - - if (g_SysProperties.empty()) - { - std::wstring dir = RmReplaceVariables(rm, L"%WINDIR%"); - dir.append(L"\\system32\\control.exe"); - dir.append(IsWindowsVistaOrGreater() ? L" system" : L" sysdm.cpl"); - - g_SysProperties = StringUtil::Narrow(dir); - } -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - ChildMeasure* child = (ChildMeasure*)data; - - void* skin = RmGetSkin(rm); - - std::wstring path = RmReadString(rm, L"Path", L"", FALSE); - if (path[0] == L'[' && path[path.size() - 1] == L']') - { - path = path.substr(1, path.size() - 2); - - for (auto iter : g_ParentMeasures) - { - if (_wcsicmp(iter->name, path.c_str()) == 0 && iter->skin == skin) - { - child->parent = iter; - break; - } - } - - if (!child->parent) - { - RmLogF(rm, LOG_ERROR, L"Invalid Path: \"%s\"", path.c_str()); - return; - } - } - else - { - if (!child->parent) - { - child->parent = new ParentMeasure; - child->parent->skin = skin; - child->parent->name = RmGetMeasureName(rm); - child->parent->ownerChild = child; - child->parent->hwnd = RmGetSkinWindow(rm); - child->parent->rm = rm; - g_ParentMeasures.push_back(child->parent); - } - - // Add trailing "\" if none exists - if (!path.empty() && path[path.size() - 1] != L'\\') - { - path += L'\\'; - } - - child->parent->path = path; - - LPCWSTR sort = RmReadString(rm, L"SortType", L"Name"); - if (_wcsicmp(sort, L"NAME") == 0) - { - child->parent->sortType = STYPE_NAME; - } - else if (_wcsicmp(sort, L"SIZE") == 0) - { - child->parent->sortType = STYPE_SIZE; - } - else if (_wcsicmp(sort, L"TYPE") == 0) - { - child->parent->sortType = STYPE_TYPE; - } - else if (_wcsicmp(sort, L"DATE") == 0) - { - child->parent->sortType = STYPE_DATE; - - LPCWSTR date = RmReadString(rm, L"SortDateType", L"Modified"); - if (_wcsicmp(date, L"MODIFIED") == 0) - { - child->parent->sortDateType = DTYPE_MODIFIED; - } - else if (_wcsicmp(date, L"CREATED") == 0) - { - child->parent->sortDateType = DTYPE_CREATED; - } - else if(_wcsicmp(date, L"ACCESSED") == 0) - { - child->parent->sortDateType = DTYPE_ACCESSED; - } - } - - int count = RmReadInt(rm, L"Count", 1); - child->parent->count = count > 0 ? count : 1; - - int recursive = RmReadInt(rm, L"Recursive", 0); - switch (recursive) - { - default: - RmLog(LOG_WARNING, L"Invalid Recursive type"); - - case 0: - child->parent->recursiveType = RECURSIVE_NONE; - break; - - case 1: - child->parent->recursiveType = RECURSIVE_PARTIAL; - break; - - case 2: - child->parent->recursiveType = RECURSIVE_FULL; - break; - } - - child->parent->sortAscending = 0!=RmReadInt(rm, L"SortAscending", 1); - child->parent->showDotDot = 0!=RmReadInt(rm, L"ShowDotDot", 1); - child->parent->showFile = 0!=RmReadInt(rm, L"ShowFile", 1); - child->parent->showFolder = 0!=RmReadInt(rm, L"ShowFolder", 1); - child->parent->showHidden = 0!=RmReadInt(rm, L"ShowHidden", 1); - child->parent->showSystem = 0!=RmReadInt(rm, L"ShowSystem", 0); - child->parent->hideExtension = 0!=RmReadInt(rm, L"HideExtensions", 0); - child->parent->extensions = Tokenize(RmReadString(rm, L"Extensions", L""), L";"); - - child->parent->wildcardSearch = RmReadString(rm, L"WildcardSearch", L"*"); - - child->parent->finishAction = RmReadString(rm, L"FinishAction", L"", false); - } - - int index = RmReadInt(rm, L"Index", 1) - 1; - child->index = index >= 0 ? index : 1; - - child->ignoreCount = 0!=RmReadInt(rm, L"IgnoreCount", 0); - - LPCWSTR type = RmReadString(rm, L"Type", L"FOLDERPATH"); - if (_wcsicmp(type, L"FOLDERPATH") == 0) - { - child->type = TYPE_FOLDERPATH; - } - else if (_wcsicmp(type, L"FOLDERSIZE") == 0) - { - child->type = TYPE_FOLDERSIZE; - } - else if (_wcsicmp(type, L"FILECOUNT") == 0) - { - child->type = TYPE_FILECOUNT; - } - else if (_wcsicmp(type, L"FOLDERCOUNT") == 0) - { - child->type = TYPE_FOLDERCOUNT; - } - else if (_wcsicmp(type, L"FILENAME") == 0) - { - child->type = TYPE_FILENAME; - } - else if (_wcsicmp(type, L"FILETYPE") == 0) - { - child->type = TYPE_FILETYPE; - } - else if (_wcsicmp(type, L"FILESIZE") == 0) - { - child->type = TYPE_FILESIZE; - } - else if (_wcsicmp(type, L"FILEDATE") == 0) - { - child->type = TYPE_FILEDATE; - - LPCWSTR date = RmReadString(rm, L"DateType", L"Modified"); - if (_wcsicmp(date, L"MODIFIED") == 0) - { - child->date = DTYPE_MODIFIED; - } - else if (_wcsicmp(date, L"CREATED") == 0) - { - child->date = DTYPE_CREATED; - } - else if(_wcsicmp(date, L"ACCESSED") == 0) - { - child->date = DTYPE_ACCESSED; - } - } - else if (_wcsicmp(type, L"ICON") == 0) - { - child->type = TYPE_ICON; - - std::wstring temp = L"icon"; - WCHAR buffer[MAX_PATH]; - _itow_s(child->index + 1, buffer, 10); - temp += buffer; - temp += L".ico"; - child->iconPath = RmReadPath(rm, L"IconPath", temp.c_str()); - - LPCWSTR size = RmReadString(rm, L"IconSize", L"MEDIUM"); - if (_wcsicmp(size, L"SMALL") == 0) - { - child->iconSize = IS_SMALL; - } - else if (_wcsicmp(size, L"MEDIUM") == 0) - { - child->iconSize = IS_MEDIUM; - } - else if (_wcsicmp(size, L"LARGE") == 0) - { - child->iconSize = IS_LARGE; - } - else if (_wcsicmp(size, L"EXTRALARGE") == 0) - { - child->iconSize = IS_EXLARGE; - } - - auto iter = std::find(child->parent->iconChildren.begin(), child->parent->iconChildren.end(), child); - if (iter == child->parent->iconChildren.end()) - { - child->parent->iconChildren.push_back(child); - } - } - else if (_wcsicmp(type, L"FILEPATH") == 0) - { - child->type = TYPE_FILEPATH; - } -} - -PLUGIN_EXPORT double Update(void* data) -{ - ChildMeasure* child = (ChildMeasure*)data; - ParentMeasure* parent = child->parent; - - if (!parent) - { - return 0.0; - } - - EnterCriticalSection(&g_CriticalSection); - if (!parent->thread && parent->ownerChild == child && (parent->needsUpdating || parent->needsIcons)) - { - unsigned int id; - HANDLE thread = (HANDLE)_beginthreadex(nullptr, 0, SystemThreadProc, parent, 0, &id); - if (thread) - { - parent->thread = thread; - } - } - - int trueIndex = child->ignoreCount ? child->index : ((child->index % parent->count) + parent->indexOffset); - double value = 0; - - if (!parent->files.empty() && trueIndex >= 0 && trueIndex < (int)parent->files.size()) - { - switch (child->type) - { - case TYPE_FILESIZE: - value = parent->files[trueIndex].size > 0 ? (double)parent->files[trueIndex].size : 0; - break; - - case TYPE_FILEDATE: - { - FILETIME fTime; - SYSTEMTIME stUTC, stLOCAL; - ULARGE_INTEGER time; - - switch (child->date) - { - case DTYPE_MODIFIED: - fTime = parent->files[trueIndex].modifiedTime; - break; - - case DTYPE_CREATED: - fTime = parent->files[trueIndex].createdTime; - break; - - case DTYPE_ACCESSED: - fTime = parent->files[trueIndex].accessedTime; - break; - } - - FileTimeToSystemTime(&fTime, &stUTC); - SystemTimeToTzSpecificLocalTime(nullptr, &stUTC, &stLOCAL); - SystemTimeToFileTime(&stLOCAL, &fTime); - - time.LowPart = fTime.dwLowDateTime; - time.HighPart = fTime.dwHighDateTime; - - value = (double)(time.QuadPart / 10000000); - } - break; - } - } - - switch (child->type) - { - case TYPE_FILECOUNT: - value = (double)parent->fileCount; - break; - - case TYPE_FOLDERCOUNT: - value = (double)parent->folderCount; - break; - - case TYPE_FOLDERSIZE: - value = (double)parent->folderSize; - break; - } - LeaveCriticalSection(&g_CriticalSection); - - return value; -} - -PLUGIN_EXPORT LPCWSTR GetString(void* data) -{ - ChildMeasure* child = (ChildMeasure*)data; - ParentMeasure* parent = child->parent; - - EnterCriticalSection(&g_CriticalSection); - if (!parent) - { - LeaveCriticalSection(&g_CriticalSection); - return L""; - } - - int trueIndex = child->ignoreCount ? child->index : ((child->index % parent->count) + parent->indexOffset); - child->strValue = L""; - - if (!parent->files.empty() && trueIndex >= 0 && trueIndex < (int)parent->files.size()) - { - switch (child->type) - { - case TYPE_FILESIZE: - if (!parent->files[trueIndex].isFolder) - { - LeaveCriticalSection(&g_CriticalSection); - return nullptr; // Force a numeric return (see the Update function) - } - break; - - case TYPE_FILENAME: - { - std::wstring temp = parent->files[trueIndex].fileName; - if (parent->hideExtension && !parent->files[trueIndex].isFolder) - { - size_t pos = temp.find_last_of(L"."); - if (pos != temp.npos) - { - child->strValue = temp.substr(0, pos); - } - } - else - { - child->strValue = temp; - } - } - break; - - case TYPE_FILETYPE: - child->strValue = parent->files[trueIndex].ext; - break; - - case TYPE_FILEDATE: - { - WCHAR* temp = new WCHAR[MAX_LINE_LENGTH]; - SYSTEMTIME stUTC, stLOCAL; - FILETIME fTime; - - switch (child->date) - { - case DTYPE_MODIFIED: - fTime = parent->files[trueIndex].modifiedTime; - break; - - case DTYPE_CREATED: - fTime = parent->files[trueIndex].createdTime; - break; - - case DTYPE_ACCESSED: - fTime = parent->files[trueIndex].accessedTime; - break; - } - - if (fTime.dwLowDateTime != 0 && fTime.dwHighDateTime != 0) - { - FileTimeToSystemTime(&fTime, &stUTC); - SystemTimeToTzSpecificLocalTime(nullptr, &stUTC, &stLOCAL); - GetDateFormat(LOCALE_USER_DEFAULT, 0, &stLOCAL, nullptr, temp, MAX_LINE_LENGTH); - child->strValue = temp; - child->strValue += L" "; - GetTimeFormat(LOCALE_USER_DEFAULT, 0, &stLOCAL, nullptr, temp, MAX_LINE_LENGTH); - child->strValue += temp; - } - else - { - child->strValue = L""; - } - delete [] temp; - } - break; - - case TYPE_ICON: - child->strValue = child->iconPath; - break; - - case TYPE_FILEPATH: - child->strValue = (_wcsicmp(parent->files[trueIndex].fileName.c_str(), L"..") == 0) ? parent->path : parent->files[trueIndex].path + parent->files[trueIndex].fileName; - break; - } - } - - switch (child->type) - { - case TYPE_FILECOUNT: - case TYPE_FOLDERCOUNT: - case TYPE_FOLDERSIZE: - LeaveCriticalSection(&g_CriticalSection); - return nullptr; // Force numeric return (see the Update function) - break; - - case TYPE_FOLDERPATH: - child->strValue = parent->path; - break; - } - - LeaveCriticalSection(&g_CriticalSection); - return child->strValue.c_str(); -} - -PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) -{ - ChildMeasure* child = (ChildMeasure*)data; - ParentMeasure* parent = child->parent; - - EnterCriticalSection(&g_CriticalSection); - if (!parent || parent->thread) - { - LeaveCriticalSection(&g_CriticalSection); - return; - } - - auto runFile = [&](std::wstring fileName, std::wstring dir, bool isProperty) -> void - { - // Display computer system properties - if (isProperty && dir.empty() && fileName.empty()) - { - WinExec(g_SysProperties.c_str(), SW_SHOWNORMAL); - return; - } - - CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); - - std::wstring file = dir + fileName; - SHELLEXECUTEINFO si = {sizeof(SHELLEXECUTEINFO)}; - - si.lpVerb = isProperty ? L"properties" : nullptr; - si.lpFile = file.c_str(); - si.nShow = SW_SHOWNORMAL; - si.lpDirectory = dir.c_str(); - si.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_ASYNCOK; - - if (isProperty) si.fMask |= SEE_MASK_INVOKEIDLIST; - - ShellExecuteEx(&si); - CoUninitialize(); - }; - - // Parent only commands - if (parent->ownerChild == child) - { - if ((int)parent->files.size() > parent->count) - { - if (_wcsicmp(args, L"PAGEUP") == 0) - { - if ((parent->indexOffset - parent->count) >= 0) - { - parent->indexOffset -= parent->count; - parent->needsIcons = true; - } - else - { - parent->indexOffset = 0; - parent->needsIcons = true; - } - } - else if (_wcsicmp(args, L"PAGEDOWN") == 0) - { - if ((parent->indexOffset + (2 * parent->count)) < (int)parent->files.size()) - { - parent->indexOffset += parent->count; - parent->needsIcons = true; - } - else - { - parent->indexOffset = (int)parent->files.size() - parent->count; - parent->needsIcons = true; - } - } - else if (_wcsicmp(args, L"INDEXUP") ==0) - { - if ((parent->indexOffset - 1) >= 0) - { - --parent->indexOffset; - parent->needsIcons = true; - } - else - { - parent->indexOffset = 0; - parent->needsIcons = true; - } - } - else if (_wcsicmp(args, L"INDEXDOWN") == 0) - { - if ((parent->indexOffset + parent->count) < (int)parent->files.size()) - { - ++parent->indexOffset; - parent->needsIcons = true; - } - else - { - parent->indexOffset = (int)parent->files.size() - parent->count; - parent->needsIcons = true; - } - } - } - - if (_wcsicmp(args, L"UPDATE") == 0) - { - parent->indexOffset = 0; - parent->needsIcons = true; - parent->needsUpdating = true; - } - else if (_wcsicmp(args, L"CONTEXTMENU") == 0) - { - if (!ShowContextMenu(parent->hwnd, parent->path)) - { - RmLogF(parent->rm, LOG_ERROR, L"Cannot open context menu for \"%s\"", parent->path.c_str()); - } - } - else if (_wcsicmp(args, L"PROPERTIES") == 0) - { - runFile(L"", parent->path, true); - } - else if (parent->recursiveType != RECURSIVE_FULL && _wcsicmp(args, L"PREVIOUSFOLDER") == 0) - { - GetParentFolder(parent->path); - - parent->indexOffset = 0; - parent->needsUpdating = true; - parent->needsIcons = true; - } - else - { - // Special commands that allow for a user defined file/folder - std::wstring arg = args; - std::wstring::size_type pos = arg.find_first_of(L' '); - if (pos != std::wstring::npos) - { - arg = arg.substr(pos); - if (!arg.empty()) - { - arg.erase(0, 1); // Skip the space - - if (_wcsnicmp(args, L"CONTEXTMENU", 11) == 0) - { - if (!ShowContextMenu(parent->hwnd, arg)) - { - RmLogF(parent->rm, LOG_ERROR, L"Cannot open context menu for \"%s\"", arg.c_str()); - } - } - else if (_wcsnicmp(args, L"PROPERTIES", 10) == 0) - { - runFile(arg, L"", true); - } - else - { - RmLogF(parent->rm, LOG_WARNING, L"!CommandMeasure: Unknown path: %s", arg.c_str()); - } - } - else - { - RmLogF(parent->rm, LOG_WARNING, L"!CommandMeasure: Unknown command: %s", args); - } - } - } - - LeaveCriticalSection(&g_CriticalSection); - return; - } - - // Child only commands - int trueIndex = child->ignoreCount ? child->index : ((child->index % parent->count) + parent->indexOffset); - if (!parent->files.empty() && trueIndex >= 0 && trueIndex < (int)parent->files.size()) - { - if (_wcsicmp(args, L"OPEN") == 0) - { - runFile(parent->files[trueIndex].fileName, parent->files[trueIndex].path, false); - } - else if (_wcsicmp(args, L"CONTEXTMENU") == 0) - { - std::wstring path = parent->files[trueIndex].path; - std::wstring fileName = parent->files[trueIndex].fileName; - - if (_wcsicmp(fileName.c_str(), L"..") == 0) - { - path = parent->path; - GetParentFolder(path); - fileName = L""; - } - - path.append(fileName); - - if (!ShowContextMenu(parent->hwnd, path)) - { - RmLogF(parent->rm, LOG_ERROR, L"Cannot open context menu for \"%s\"", path.c_str()); - } - } - else if (_wcsicmp(args, L"PROPERTIES") == 0) - { - std::wstring path = parent->files[trueIndex].path; - std::wstring fileName = parent->files[trueIndex].fileName; - - if (_wcsicmp(fileName.c_str(), L"..") == 0) - { - path = parent->path; - GetParentFolder(path); - fileName = L""; - } - - runFile(fileName, path, true); - } - else if (parent->recursiveType != RECURSIVE_FULL && _wcsicmp(args, L"FOLLOWPATH") == 0) - { - if (_wcsicmp(parent->files[trueIndex].fileName.c_str(), L"..") == 0) - { - GetParentFolder(parent->path); - - parent->indexOffset = 0; - parent->needsUpdating = true; - parent->needsIcons = true; - } - else if (parent->files[trueIndex].isFolder) - { - parent->path += parent->files[trueIndex].fileName; - if (parent->path[parent->path.size() - 1] != L'\\') - { - parent->path += L'\\'; - } - - parent->indexOffset = 0; - parent->needsUpdating = true; - parent->needsIcons = true; - } - else - { - runFile(parent->files[trueIndex].fileName, parent->files[trueIndex].path, false); - } - } - else - { - RmLogF(parent->rm, LOG_WARNING, L"!CommandMeasure: Unknown command: %s", args); - } - - LeaveCriticalSection(&g_CriticalSection); - return; - } - - LeaveCriticalSection(&g_CriticalSection); - RmLogF(parent->rm, LOG_WARNING, L"!CommandMeasure: Unknown command: %s", args); -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - ChildMeasure* child = (ChildMeasure*)data; - ParentMeasure* parent = child->parent; - - EnterCriticalSection(&g_CriticalSection); - if (parent && parent->ownerChild == child) - { - if (parent->thread) - { - TerminateThread(parent->thread, 0); - parent->thread = nullptr; - } - - auto iter = std::find(g_ParentMeasures.begin(), g_ParentMeasures.end(), parent); - g_ParentMeasures.erase(iter); - - delete parent; - } - - delete child; - LeaveCriticalSection(&g_CriticalSection); -} - -unsigned __stdcall SystemThreadProc(void* pParam) -{ - CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); - - ParentMeasure* parent = (ParentMeasure*)pParam; - - EnterCriticalSection(&g_CriticalSection); - ParentMeasure* tmp = new ParentMeasure (*parent); - parent->needsUpdating = false; // Set to false here in case skin is reloaded - parent->needsIcons = false; // Set to false here in case skin is reloaded - LeaveCriticalSection(&g_CriticalSection); - - FileInfo file; - - if (tmp->needsUpdating) - { - EnterCriticalSection(&g_CriticalSection); - parent->files.clear(); - parent->fileCount = 0; - parent->folderCount = 0; - parent->folderSize = 0; - LeaveCriticalSection(&g_CriticalSection); - - tmp->files.clear(); - tmp->fileCount = 0; - tmp->folderCount = 0; - tmp->folderSize = 0; - - // If no path is specified, get all the drives instead - if (tmp->path.empty()) - { - WCHAR drive[4] = L" :\\"; - DWORD driveMask = GetLogicalDrives(); - for (int i = 0; i < 32; ++i) - { - if ((driveMask << (31 - i) >> 31) > 0) - { - drive[0] = i + 'A'; - file.fileName = drive; - file.isFolder = true; - file.size = 0; - - ++tmp->folderCount; - tmp->files.push_back(file); - } - } - } - else - { - if (tmp->showDotDot && tmp->recursiveType != RECURSIVE_FULL) - { - file.fileName = L".."; - file.isFolder = true; - - tmp->files.push_back(file); - } - - std::queue folderQueue; - std::wstring folder = tmp->path; - - RecursiveType rType = tmp->recursiveType; - GetFolderInfo(folderQueue, folder, tmp, (rType == RECURSIVE_PARTIAL) ? RECURSIVE_NONE : rType); - - while (rType != RECURSIVE_NONE && !folderQueue.empty()) - { - folder = folderQueue.front(); - GetFolderInfo(folderQueue, folder, tmp, rType); - folderQueue.pop(); - } - } - - // Sort - const int sortAsc = tmp->sortAscending ? 1 : -1; - auto begin = (!tmp->path.empty() && - (tmp->showDotDot && tmp->recursiveType != RECURSIVE_FULL)) ? tmp->files.begin() + 1: tmp->files.begin(); - - switch (tmp->sortType) - { - case STYPE_NAME: - std::sort(begin, tmp->files.end(), - [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool - { - if (file1.isFolder && file2.isFolder) - { - return (sortAsc * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); - } - else if (!file1.isFolder && !file2.isFolder) - { - return (sortAsc * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); - } - return file1.isFolder; - }); - break; - - case STYPE_SIZE: - std::sort(begin, tmp->files.end(), - [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool - { - if (file1.isFolder && file2.isFolder) - { - return (sortAsc * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); - } - else if (!file1.isFolder && !file2.isFolder) - { - return (sortAsc > 0) ? (file1.size < file2.size) : (file1.size > file2.size); - } - return file1.isFolder; - }); - break; - - case STYPE_TYPE: - std::sort(begin, tmp->files.end(), - [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool - { - if (file1.isFolder && file2.isFolder) - { - return (sortAsc * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); - } - else if (!file1.isFolder && !file2.isFolder) - { - int result = (file1.ext.empty() && file2.ext.empty()) ? 0 : sortAsc * _wcsicmp(file1.ext.c_str(), file2.ext.c_str()); - return (0 != result) ? (result < 0) : (sortAsc * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); - } - return file1.isFolder; - }); - break; - - case STYPE_DATE: - switch (tmp->sortDateType) - { - case DTYPE_MODIFIED: - std::sort(begin, tmp->files.end(), - [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool - { - if (file1.isFolder && file2.isFolder) - { - return (sortAsc * CompareFileTime(&file1.modifiedTime, &file2.modifiedTime) < 0); - } - else if (!file1.isFolder && !file2.isFolder) - { - return (sortAsc * CompareFileTime(&file1.modifiedTime, &file2.modifiedTime) < 0); - } - return file1.isFolder; - }); - break; - - case DTYPE_CREATED: - std::sort(begin, tmp->files.end(), - [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool - { - if (file1.isFolder && file2.isFolder) - { - return (sortAsc * CompareFileTime(&file1.createdTime, &file2.createdTime) < 0); - } - else if (!file1.isFolder && !file2.isFolder) - { - return (sortAsc * CompareFileTime(&file1.createdTime, &file2.createdTime) < 0); - } - return file1.isFolder; - }); - break; - - case DTYPE_ACCESSED: - std::sort(begin, tmp->files.end(), - [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool - { - if (file1.isFolder && file2.isFolder) - { - return (sortAsc * CompareFileTime(&file1.accessedTime, &file2.accessedTime) < 0); - } - else if (!file1.isFolder && !file2.isFolder) - { - return (sortAsc * CompareFileTime(&file1.accessedTime, &file2.accessedTime) < 0); - } - return file1.isFolder; - }); - break; - } - break; - } - - EnterCriticalSection(&g_CriticalSection); - parent->files = tmp->files; - parent->files.shrink_to_fit(); - parent->fileCount = tmp->fileCount; - parent->folderCount = tmp->folderCount; - parent->folderSize = tmp->folderSize; - LeaveCriticalSection(&g_CriticalSection); - } - - if (tmp->needsIcons) - { - for (auto iter : tmp->iconChildren) - { - EnterCriticalSection(&g_CriticalSection); - int trueIndex = iter->ignoreCount ? iter->index : ((iter->index % iter->parent->count) + iter->parent->indexOffset); - - if (iter->type == TYPE_ICON && trueIndex >= 0 && trueIndex < (int)tmp->files.size()) - { - std::wstring filePath = tmp->files[trueIndex].path; - filePath += (tmp->files[trueIndex].fileName == L"..") ? L"" :tmp->files[trueIndex].fileName; - GetIcon(filePath, iter->iconPath, iter->iconSize); - } - else if (iter->type == TYPE_ICON) - { - GetIcon(INVALID_FILE, iter->iconPath, iter->iconSize); - } - LeaveCriticalSection(&g_CriticalSection); - } - } - - EnterCriticalSection(&g_CriticalSection); - CloseHandle(parent->thread); - parent->thread = nullptr; - LeaveCriticalSection(&g_CriticalSection); - - if (!tmp->finishAction.empty()) - { - RmExecute(tmp->skin, tmp->finishAction.c_str()); - } - - delete tmp; - - CoUninitialize(); - return 0; -} - -void GetFolderInfo(std::queue& folderQueue, std::wstring& folder, ParentMeasure* parent, RecursiveType rType) -{ - std::wstring path = folder; - folder += (rType == RECURSIVE_NONE) ? parent->wildcardSearch : L"*"; - - WIN32_FIND_DATA fd; - HANDLE find = FindFirstFileEx(folder.c_str(), FindExInfoStandard, &fd, FindExSearchNameMatch, nullptr, 0); - - if (find != INVALID_HANDLE_VALUE) - { - do - { - FileInfo file; - - file.fileName = fd.cFileName; - if (_wcsicmp(file.fileName.c_str(), L".") == 0 || _wcsicmp(file.fileName.c_str(), L"..") == 0) - { - continue; - } - - file.isFolder = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0; - bool isHidden = (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) > 0; - bool isSystem = (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) > 0; - - if (rType == RECURSIVE_FULL && parent->wildcardSearch != L"*" && !file.isFolder) - { - if (!PathMatchSpec(file.fileName.c_str(), parent->wildcardSearch.c_str())) - { - continue; - } - } - - if ((rType != RECURSIVE_PARTIAL) && - ((rType != RECURSIVE_FULL && !parent->showFile && !file.isFolder) || - (rType != RECURSIVE_FULL && !parent->showFolder && file.isFolder) || - (!parent->showHidden && isHidden) ||(!parent->showSystem && isSystem))) - { - continue; - } - - if (rType != RECURSIVE_PARTIAL && !file.isFolder) - { - size_t pos = file.fileName.find_last_of(L"."); - if (pos != std::wstring::npos) - { - file.ext = file.fileName.substr(pos + 1); - - if (parent->extensions.size() > 0) - { - bool found = false; - for (auto iter : parent->extensions) - { - if (_wcsicmp(iter.c_str(), file.ext.c_str()) == 0) - { - found = true; - break; - } - } - - if (!found) - { - continue; - } - } - } - else if (parent->extensions.size() > 0) - { - continue; - } - } - - if (file.isFolder) - { - if (rType != RECURSIVE_FULL) - { - ++parent->folderCount; - } - - folderQueue.push(path + file.fileName + L"\\"); - } - else - { - ++parent->fileCount; - file.size = ((UINT64)fd.nFileSizeHigh << 32) + fd.nFileSizeLow; - } - - parent->folderSize += file.size; - - file.createdTime = fd.ftCreationTime; - file.modifiedTime = fd.ftLastWriteTime; - file.accessedTime = fd.ftLastAccessTime; - - file.path = path; - - if (rType == RECURSIVE_NONE || (rType == RECURSIVE_FULL && !file.isFolder)) - { - parent->files.push_back(file); - } - } - while (FindNextFile(find, &fd)); - FindClose(find); - } -} - -void GetIcon(std::wstring filePath, const std::wstring& iconPath, IconSize iconSize) -{ - SHFILEINFO shFileInfo; - HICON icon = nullptr; - HIMAGELIST* hImageList = nullptr; - FILE* fp = nullptr; - - // Special case for .url files - if (filePath.size() > 3 && _wcsicmp(filePath.substr(filePath.size() - 4).c_str(), L".URL") == 0) - { - WCHAR buffer[MAX_PATH] = L""; - GetPrivateProfileString(L"InternetShortcut", L"IconFile", L"", buffer, sizeof(buffer), filePath.c_str()); - if (*buffer) - { - std::wstring file = buffer; - int iconIndex = 0; - - GetPrivateProfileString(L"InternetShortcut", L"IconIndex", L"-1", buffer, sizeof(buffer), filePath.c_str()); - if (buffer != L"-1") - { - iconIndex = _wtoi(buffer); - } - - int size = 16; - switch (iconSize) - { - case IS_EXLARGE: size = 256; break; - case IS_LARGE: size = 48; break; - case IS_MEDIUM: size = 32; break; - } - - PrivateExtractIcons(file.c_str(), iconIndex, size, size, &icon, nullptr, 1, LR_LOADTRANSPARENT); - } - else - { - std::wstring browser; - WCHAR buffer[MAX_PATH]; - DWORD size = MAX_PATH; - HKEY hKey; - - RegOpenKeyEx(HKEY_CLASSES_ROOT, L"http\\shell\\open\\command", 0, KEY_QUERY_VALUE, &hKey); - RegQueryValueEx(hKey, nullptr, nullptr, nullptr, (LPBYTE)buffer, &size); - RegCloseKey(hKey); - - //Strip quotes - if (buffer[0] == L'"') - { - browser = buffer; browser = browser.substr(1); - size_t pos = browser.find_first_of(L'"'); - browser = browser.substr(0, pos); - } - - filePath = browser; - } - } - - if (icon == nullptr) - { - SHGetFileInfo(filePath.c_str(), 0, &shFileInfo, sizeof(shFileInfo), SHGFI_SYSICONINDEX); - SHGetImageList(iconSize, IID_IImageList, (void**) &hImageList); - ((IImageList*)hImageList)->GetIcon(shFileInfo.iIcon, ILD_TRANSPARENT, &icon); - } - - errno_t error = _wfopen_s(&fp, iconPath.c_str(), L"wb"); - if (filePath == INVALID_FILE || icon == nullptr || (error == 0 && !SaveIcon(icon, fp))) - { - fwrite(iconPath.c_str(), 1, 1, fp); // Clears previous icon - fclose(fp); - } - - DestroyIcon(icon); -} - -HRESULT SaveIcon(HICON hIcon, FILE* fp) -{ - ICONINFO iconInfo; - BITMAP bmColor; - BITMAP bmMask; - if (!fp || nullptr == hIcon || !GetIconInfo(hIcon, &iconInfo) || - !GetObject(iconInfo.hbmColor, sizeof(bmColor), &bmColor) || - !GetObject(iconInfo.hbmMask, sizeof(bmMask), &bmMask)) - return false; - - // support only 16/32 bit icon now - if (bmColor.bmBitsPixel != 16 && bmColor.bmBitsPixel != 32) - return false; - - HDC dc = GetDC(nullptr); - BYTE bmiBytes[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)]; - BITMAPINFO* bmi = (BITMAPINFO*)bmiBytes; - - // color bits - memset(bmi, 0, sizeof(BITMAPINFO)); - bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - GetDIBits(dc, iconInfo.hbmColor, 0, bmColor.bmHeight, nullptr, bmi, DIB_RGB_COLORS); - int colorBytesCount = bmi->bmiHeader.biSizeImage; - BYTE* colorBits = new BYTE[colorBytesCount]; - GetDIBits(dc, iconInfo.hbmColor, 0, bmColor.bmHeight, colorBits, bmi, DIB_RGB_COLORS); - - // mask bits - memset(bmi, 0, sizeof(BITMAPINFO)); - bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - GetDIBits(dc, iconInfo.hbmMask, 0, bmMask.bmHeight, nullptr, bmi, DIB_RGB_COLORS); - int maskBytesCount = bmi->bmiHeader.biSizeImage; - BYTE* maskBits = new BYTE[maskBytesCount]; - GetDIBits(dc, iconInfo.hbmMask, 0, bmMask.bmHeight, maskBits, bmi, DIB_RGB_COLORS); - - ReleaseDC(nullptr, dc); - - // icon data - BITMAPINFOHEADER bmihIcon; - memset(&bmihIcon, 0, sizeof(bmihIcon)); - bmihIcon.biSize = sizeof(BITMAPINFOHEADER); - bmihIcon.biWidth = bmColor.bmWidth; - bmihIcon.biHeight = bmColor.bmHeight * 2; // icXOR + icAND - bmihIcon.biPlanes = bmColor.bmPlanes; - bmihIcon.biBitCount = bmColor.bmBitsPixel; - bmihIcon.biSizeImage = colorBytesCount + maskBytesCount; - - // icon header - ICONDIR dir; - dir.idReserved = 0; // must be 0 - dir.idType = 1; // 1 for icons - dir.idCount = 1; - dir.idEntries[0].bWidth = (BYTE)bmColor.bmWidth; - dir.idEntries[0].bHeight = (BYTE)bmColor.bmHeight; - dir.idEntries[0].bColorCount = 0; // 0 if >= 8bpp - dir.idEntries[0].bReserved = 0; // must be 0 - dir.idEntries[0].wPlanes = bmColor.bmPlanes; - dir.idEntries[0].wBitCount = bmColor.bmBitsPixel; - dir.idEntries[0].dwBytesInRes = sizeof(bmihIcon) + bmihIcon.biSizeImage; - dir.idEntries[0].dwImageOffset = sizeof(ICONDIR); - - fwrite(&dir, sizeof(dir), 1, fp); - fwrite(&bmihIcon, sizeof(bmihIcon), 1, fp); - fwrite(colorBits, colorBytesCount, 1, fp); - fwrite(maskBits, maskBytesCount, 1, fp); - - // Clean up - DeleteObject(iconInfo.hbmColor); - DeleteObject(iconInfo.hbmMask); - delete[] colorBits; - delete[] maskBits; - - fclose(fp); - - return true; +/* + Copyright (C) 2012 Brian Ferguson + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "PluginFileView.h" +#include "../../Common/StringUtil.h" + +#define MAX_LINE_LENGTH 4096 +#define INVALID_FILE L"/<>\\" + +#pragma pack(push, 2) +typedef struct // 16 bytes +{ + BYTE bWidth; // Width, in pixels, of the image + BYTE bHeight; // Height, in pixels, of the image + BYTE bColorCount; // Number of colors in image (0 if >=8bpp) + BYTE bReserved; // Reserved ( must be 0) + WORD wPlanes; // Color Planes + WORD wBitCount; // Bits per pixel + DWORD dwBytesInRes; // How many bytes in this resource? + DWORD dwImageOffset; // Where in the file is this image? +} ICONDIRENTRY, *LPICONDIRENTRY; + +typedef struct // 22 bytes +{ + WORD idReserved; // Reserved (must be 0) + WORD idType; // Resource Type (1 for icons) + WORD idCount; // How many images? + ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em) +} ICONDIR, *LPICONDIR; +#pragma pack(pop) + +unsigned __stdcall SystemThreadProc(void* pParam); +void GetFolderInfo(std::queue& folderQueue, std::wstring& folder, ParentMeasure* parent, RecursiveType rType); +void GetIcon(std::wstring filePath, const std::wstring& iconPath, IconSize iconSize); +HRESULT SaveIcon(HICON hIcon, FILE* fp); + +static std::vector g_ParentMeasures; +static CRITICAL_SECTION g_CriticalSection; +static std::string g_SysProperties; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + InitializeCriticalSection(&g_CriticalSection); + + // Disable DLL_THREAD_ATTACH and DLL_THREAD_DETACH notification calls. + DisableThreadLibraryCalls(hinstDLL); + break; + + case DLL_PROCESS_DETACH: + DeleteCriticalSection(&g_CriticalSection); + break; + } + + return TRUE; +} + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + ChildMeasure* child = new ChildMeasure; + *data = child; + + if (g_SysProperties.empty()) + { + std::wstring dir = RmReplaceVariables(rm, L"%WINDIR%"); + dir.append(L"\\system32\\control.exe"); + dir.append(IsWindowsVistaOrGreater() ? L" system" : L" sysdm.cpl"); + + g_SysProperties = StringUtil::Narrow(dir); + } +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + ChildMeasure* child = (ChildMeasure*)data; + + void* skin = RmGetSkin(rm); + + std::wstring path = RmReadString(rm, L"Path", L"", FALSE); + if (path[0] == L'[' && path[path.size() - 1] == L']') + { + path = path.substr(1, path.size() - 2); + + for (auto iter : g_ParentMeasures) + { + if (_wcsicmp(iter->name, path.c_str()) == 0 && iter->skin == skin) + { + child->parent = iter; + break; + } + } + + if (!child->parent) + { + RmLogF(rm, LOG_ERROR, L"Invalid Path: \"%s\"", path.c_str()); + return; + } + } + else + { + if (!child->parent) + { + child->parent = new ParentMeasure; + child->parent->skin = skin; + child->parent->name = RmGetMeasureName(rm); + child->parent->ownerChild = child; + child->parent->hwnd = RmGetSkinWindow(rm); + child->parent->rm = rm; + g_ParentMeasures.push_back(child->parent); + } + + // Add trailing "\" if none exists + if (!path.empty() && path[path.size() - 1] != L'\\') + { + path += L'\\'; + } + + child->parent->path = path; + + LPCWSTR sort = RmReadString(rm, L"SortType", L"Name"); + if (_wcsicmp(sort, L"NAME") == 0) + { + child->parent->sortType = STYPE_NAME; + } + else if (_wcsicmp(sort, L"SIZE") == 0) + { + child->parent->sortType = STYPE_SIZE; + } + else if (_wcsicmp(sort, L"TYPE") == 0) + { + child->parent->sortType = STYPE_TYPE; + } + else if (_wcsicmp(sort, L"DATE") == 0) + { + child->parent->sortType = STYPE_DATE; + + LPCWSTR date = RmReadString(rm, L"SortDateType", L"Modified"); + if (_wcsicmp(date, L"MODIFIED") == 0) + { + child->parent->sortDateType = DTYPE_MODIFIED; + } + else if (_wcsicmp(date, L"CREATED") == 0) + { + child->parent->sortDateType = DTYPE_CREATED; + } + else if(_wcsicmp(date, L"ACCESSED") == 0) + { + child->parent->sortDateType = DTYPE_ACCESSED; + } + } + + int count = RmReadInt(rm, L"Count", 1); + child->parent->count = count > 0 ? count : 1; + + int recursive = RmReadInt(rm, L"Recursive", 0); + switch (recursive) + { + default: + RmLog(LOG_WARNING, L"Invalid Recursive type"); + + case 0: + child->parent->recursiveType = RECURSIVE_NONE; + break; + + case 1: + child->parent->recursiveType = RECURSIVE_PARTIAL; + break; + + case 2: + child->parent->recursiveType = RECURSIVE_FULL; + break; + } + + child->parent->sortAscending = 0!=RmReadInt(rm, L"SortAscending", 1); + child->parent->showDotDot = 0!=RmReadInt(rm, L"ShowDotDot", 1); + child->parent->showFile = 0!=RmReadInt(rm, L"ShowFile", 1); + child->parent->showFolder = 0!=RmReadInt(rm, L"ShowFolder", 1); + child->parent->showHidden = 0!=RmReadInt(rm, L"ShowHidden", 1); + child->parent->showSystem = 0!=RmReadInt(rm, L"ShowSystem", 0); + child->parent->hideExtension = 0!=RmReadInt(rm, L"HideExtensions", 0); + child->parent->extensions = Tokenize(RmReadString(rm, L"Extensions", L""), L";"); + + child->parent->wildcardSearch = RmReadString(rm, L"WildcardSearch", L"*"); + + child->parent->finishAction = RmReadString(rm, L"FinishAction", L"", false); + } + + int index = RmReadInt(rm, L"Index", 1) - 1; + child->index = index >= 0 ? index : 1; + + child->ignoreCount = 0!=RmReadInt(rm, L"IgnoreCount", 0); + + LPCWSTR type = RmReadString(rm, L"Type", L"FOLDERPATH"); + if (_wcsicmp(type, L"FOLDERPATH") == 0) + { + child->type = TYPE_FOLDERPATH; + } + else if (_wcsicmp(type, L"FOLDERSIZE") == 0) + { + child->type = TYPE_FOLDERSIZE; + } + else if (_wcsicmp(type, L"FILECOUNT") == 0) + { + child->type = TYPE_FILECOUNT; + } + else if (_wcsicmp(type, L"FOLDERCOUNT") == 0) + { + child->type = TYPE_FOLDERCOUNT; + } + else if (_wcsicmp(type, L"FILENAME") == 0) + { + child->type = TYPE_FILENAME; + } + else if (_wcsicmp(type, L"FILETYPE") == 0) + { + child->type = TYPE_FILETYPE; + } + else if (_wcsicmp(type, L"FILESIZE") == 0) + { + child->type = TYPE_FILESIZE; + } + else if (_wcsicmp(type, L"FILEDATE") == 0) + { + child->type = TYPE_FILEDATE; + + LPCWSTR date = RmReadString(rm, L"DateType", L"Modified"); + if (_wcsicmp(date, L"MODIFIED") == 0) + { + child->date = DTYPE_MODIFIED; + } + else if (_wcsicmp(date, L"CREATED") == 0) + { + child->date = DTYPE_CREATED; + } + else if(_wcsicmp(date, L"ACCESSED") == 0) + { + child->date = DTYPE_ACCESSED; + } + } + else if (_wcsicmp(type, L"ICON") == 0) + { + child->type = TYPE_ICON; + + std::wstring temp = L"icon"; + WCHAR buffer[MAX_PATH]; + _itow_s(child->index + 1, buffer, 10); + temp += buffer; + temp += L".ico"; + child->iconPath = RmReadPath(rm, L"IconPath", temp.c_str()); + + LPCWSTR size = RmReadString(rm, L"IconSize", L"MEDIUM"); + if (_wcsicmp(size, L"SMALL") == 0) + { + child->iconSize = IS_SMALL; + } + else if (_wcsicmp(size, L"MEDIUM") == 0) + { + child->iconSize = IS_MEDIUM; + } + else if (_wcsicmp(size, L"LARGE") == 0) + { + child->iconSize = IS_LARGE; + } + else if (_wcsicmp(size, L"EXTRALARGE") == 0) + { + child->iconSize = IS_EXLARGE; + } + + auto iter = std::find(child->parent->iconChildren.begin(), child->parent->iconChildren.end(), child); + if (iter == child->parent->iconChildren.end()) + { + child->parent->iconChildren.push_back(child); + } + } + else if (_wcsicmp(type, L"FILEPATH") == 0) + { + child->type = TYPE_FILEPATH; + } +} + +PLUGIN_EXPORT double Update(void* data) +{ + ChildMeasure* child = (ChildMeasure*)data; + ParentMeasure* parent = child->parent; + + if (!parent) + { + return 0.0; + } + + EnterCriticalSection(&g_CriticalSection); + if (!parent->thread && parent->ownerChild == child && (parent->needsUpdating || parent->needsIcons)) + { + unsigned int id; + HANDLE thread = (HANDLE)_beginthreadex(nullptr, 0, SystemThreadProc, parent, 0, &id); + if (thread) + { + parent->thread = thread; + } + } + + int trueIndex = child->ignoreCount ? child->index : ((child->index % parent->count) + parent->indexOffset); + double value = 0; + + if (!parent->files.empty() && trueIndex >= 0 && trueIndex < (int)parent->files.size()) + { + switch (child->type) + { + case TYPE_FILESIZE: + value = parent->files[trueIndex].size > 0 ? (double)parent->files[trueIndex].size : 0; + break; + + case TYPE_FILEDATE: + { + FILETIME fTime; + SYSTEMTIME stUTC, stLOCAL; + ULARGE_INTEGER time; + + switch (child->date) + { + case DTYPE_MODIFIED: + fTime = parent->files[trueIndex].modifiedTime; + break; + + case DTYPE_CREATED: + fTime = parent->files[trueIndex].createdTime; + break; + + case DTYPE_ACCESSED: + fTime = parent->files[trueIndex].accessedTime; + break; + } + + FileTimeToSystemTime(&fTime, &stUTC); + SystemTimeToTzSpecificLocalTime(nullptr, &stUTC, &stLOCAL); + SystemTimeToFileTime(&stLOCAL, &fTime); + + time.LowPart = fTime.dwLowDateTime; + time.HighPart = fTime.dwHighDateTime; + + value = (double)(time.QuadPart / 10000000); + } + break; + } + } + + switch (child->type) + { + case TYPE_FILECOUNT: + value = (double)parent->fileCount; + break; + + case TYPE_FOLDERCOUNT: + value = (double)parent->folderCount; + break; + + case TYPE_FOLDERSIZE: + value = (double)parent->folderSize; + break; + } + LeaveCriticalSection(&g_CriticalSection); + + return value; +} + +PLUGIN_EXPORT LPCWSTR GetString(void* data) +{ + ChildMeasure* child = (ChildMeasure*)data; + ParentMeasure* parent = child->parent; + + EnterCriticalSection(&g_CriticalSection); + if (!parent) + { + LeaveCriticalSection(&g_CriticalSection); + return L""; + } + + int trueIndex = child->ignoreCount ? child->index : ((child->index % parent->count) + parent->indexOffset); + child->strValue = L""; + + if (!parent->files.empty() && trueIndex >= 0 && trueIndex < (int)parent->files.size()) + { + switch (child->type) + { + case TYPE_FILESIZE: + if (!parent->files[trueIndex].isFolder) + { + LeaveCriticalSection(&g_CriticalSection); + return nullptr; // Force a numeric return (see the Update function) + } + break; + + case TYPE_FILENAME: + { + std::wstring temp = parent->files[trueIndex].fileName; + if (parent->hideExtension && !parent->files[trueIndex].isFolder) + { + size_t pos = temp.find_last_of(L"."); + if (pos != temp.npos) + { + child->strValue = temp.substr(0, pos); + } + } + else + { + child->strValue = temp; + } + } + break; + + case TYPE_FILETYPE: + child->strValue = parent->files[trueIndex].ext; + break; + + case TYPE_FILEDATE: + { + WCHAR* temp = new WCHAR[MAX_LINE_LENGTH]; + SYSTEMTIME stUTC, stLOCAL; + FILETIME fTime; + + switch (child->date) + { + case DTYPE_MODIFIED: + fTime = parent->files[trueIndex].modifiedTime; + break; + + case DTYPE_CREATED: + fTime = parent->files[trueIndex].createdTime; + break; + + case DTYPE_ACCESSED: + fTime = parent->files[trueIndex].accessedTime; + break; + } + + if (fTime.dwLowDateTime != 0 && fTime.dwHighDateTime != 0) + { + FileTimeToSystemTime(&fTime, &stUTC); + SystemTimeToTzSpecificLocalTime(nullptr, &stUTC, &stLOCAL); + GetDateFormat(LOCALE_USER_DEFAULT, 0, &stLOCAL, nullptr, temp, MAX_LINE_LENGTH); + child->strValue = temp; + child->strValue += L" "; + GetTimeFormat(LOCALE_USER_DEFAULT, 0, &stLOCAL, nullptr, temp, MAX_LINE_LENGTH); + child->strValue += temp; + } + else + { + child->strValue = L""; + } + delete [] temp; + } + break; + + case TYPE_ICON: + child->strValue = child->iconPath; + break; + + case TYPE_FILEPATH: + child->strValue = (_wcsicmp(parent->files[trueIndex].fileName.c_str(), L"..") == 0) ? parent->path : parent->files[trueIndex].path + parent->files[trueIndex].fileName; + break; + } + } + + switch (child->type) + { + case TYPE_FILECOUNT: + case TYPE_FOLDERCOUNT: + case TYPE_FOLDERSIZE: + LeaveCriticalSection(&g_CriticalSection); + return nullptr; // Force numeric return (see the Update function) + break; + + case TYPE_FOLDERPATH: + child->strValue = parent->path; + break; + } + + LeaveCriticalSection(&g_CriticalSection); + return child->strValue.c_str(); +} + +PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) +{ + ChildMeasure* child = (ChildMeasure*)data; + ParentMeasure* parent = child->parent; + + EnterCriticalSection(&g_CriticalSection); + if (!parent || parent->thread) + { + LeaveCriticalSection(&g_CriticalSection); + return; + } + + auto runFile = [&](std::wstring fileName, std::wstring dir, bool isProperty) -> void + { + // Display computer system properties + if (isProperty && dir.empty() && fileName.empty()) + { + WinExec(g_SysProperties.c_str(), SW_SHOWNORMAL); + return; + } + + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + + std::wstring file = dir + fileName; + SHELLEXECUTEINFO si = {sizeof(SHELLEXECUTEINFO)}; + + si.lpVerb = isProperty ? L"properties" : nullptr; + si.lpFile = file.c_str(); + si.nShow = SW_SHOWNORMAL; + si.lpDirectory = dir.c_str(); + si.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_ASYNCOK; + + if (isProperty) si.fMask |= SEE_MASK_INVOKEIDLIST; + + ShellExecuteEx(&si); + CoUninitialize(); + }; + + // Parent only commands + if (parent->ownerChild == child) + { + if ((int)parent->files.size() > parent->count) + { + if (_wcsicmp(args, L"PAGEUP") == 0) + { + if ((parent->indexOffset - parent->count) >= 0) + { + parent->indexOffset -= parent->count; + parent->needsIcons = true; + } + else + { + parent->indexOffset = 0; + parent->needsIcons = true; + } + } + else if (_wcsicmp(args, L"PAGEDOWN") == 0) + { + if ((parent->indexOffset + (2 * parent->count)) < (int)parent->files.size()) + { + parent->indexOffset += parent->count; + parent->needsIcons = true; + } + else + { + parent->indexOffset = (int)parent->files.size() - parent->count; + parent->needsIcons = true; + } + } + else if (_wcsicmp(args, L"INDEXUP") ==0) + { + if ((parent->indexOffset - 1) >= 0) + { + --parent->indexOffset; + parent->needsIcons = true; + } + else + { + parent->indexOffset = 0; + parent->needsIcons = true; + } + } + else if (_wcsicmp(args, L"INDEXDOWN") == 0) + { + if ((parent->indexOffset + parent->count) < (int)parent->files.size()) + { + ++parent->indexOffset; + parent->needsIcons = true; + } + else + { + parent->indexOffset = (int)parent->files.size() - parent->count; + parent->needsIcons = true; + } + } + } + + if (_wcsicmp(args, L"UPDATE") == 0) + { + parent->indexOffset = 0; + parent->needsIcons = true; + parent->needsUpdating = true; + } + else if (_wcsicmp(args, L"CONTEXTMENU") == 0) + { + if (!ShowContextMenu(parent->hwnd, parent->path)) + { + RmLogF(parent->rm, LOG_ERROR, L"Cannot open context menu for \"%s\"", parent->path.c_str()); + } + } + else if (_wcsicmp(args, L"PROPERTIES") == 0) + { + runFile(L"", parent->path, true); + } + else if (parent->recursiveType != RECURSIVE_FULL && _wcsicmp(args, L"PREVIOUSFOLDER") == 0) + { + GetParentFolder(parent->path); + + parent->indexOffset = 0; + parent->needsUpdating = true; + parent->needsIcons = true; + } + else + { + // Special commands that allow for a user defined file/folder + std::wstring arg = args; + std::wstring::size_type pos = arg.find_first_of(L' '); + if (pos != std::wstring::npos) + { + arg = arg.substr(pos); + if (!arg.empty()) + { + arg.erase(0, 1); // Skip the space + + if (_wcsnicmp(args, L"CONTEXTMENU", 11) == 0) + { + if (!ShowContextMenu(parent->hwnd, arg)) + { + RmLogF(parent->rm, LOG_ERROR, L"Cannot open context menu for \"%s\"", arg.c_str()); + } + } + else if (_wcsnicmp(args, L"PROPERTIES", 10) == 0) + { + runFile(arg, L"", true); + } + else + { + RmLogF(parent->rm, LOG_WARNING, L"!CommandMeasure: Unknown path: %s", arg.c_str()); + } + } + else + { + RmLogF(parent->rm, LOG_WARNING, L"!CommandMeasure: Unknown command: %s", args); + } + } + } + + LeaveCriticalSection(&g_CriticalSection); + return; + } + + // Child only commands + int trueIndex = child->ignoreCount ? child->index : ((child->index % parent->count) + parent->indexOffset); + if (!parent->files.empty() && trueIndex >= 0 && trueIndex < (int)parent->files.size()) + { + if (_wcsicmp(args, L"OPEN") == 0) + { + runFile(parent->files[trueIndex].fileName, parent->files[trueIndex].path, false); + } + else if (_wcsicmp(args, L"CONTEXTMENU") == 0) + { + std::wstring path = parent->files[trueIndex].path; + std::wstring fileName = parent->files[trueIndex].fileName; + + if (_wcsicmp(fileName.c_str(), L"..") == 0) + { + path = parent->path; + GetParentFolder(path); + fileName = L""; + } + + path.append(fileName); + + if (!ShowContextMenu(parent->hwnd, path)) + { + RmLogF(parent->rm, LOG_ERROR, L"Cannot open context menu for \"%s\"", path.c_str()); + } + } + else if (_wcsicmp(args, L"PROPERTIES") == 0) + { + std::wstring path = parent->files[trueIndex].path; + std::wstring fileName = parent->files[trueIndex].fileName; + + if (_wcsicmp(fileName.c_str(), L"..") == 0) + { + path = parent->path; + GetParentFolder(path); + fileName = L""; + } + + runFile(fileName, path, true); + } + else if (parent->recursiveType != RECURSIVE_FULL && _wcsicmp(args, L"FOLLOWPATH") == 0) + { + if (_wcsicmp(parent->files[trueIndex].fileName.c_str(), L"..") == 0) + { + GetParentFolder(parent->path); + + parent->indexOffset = 0; + parent->needsUpdating = true; + parent->needsIcons = true; + } + else if (parent->files[trueIndex].isFolder) + { + parent->path += parent->files[trueIndex].fileName; + if (parent->path[parent->path.size() - 1] != L'\\') + { + parent->path += L'\\'; + } + + parent->indexOffset = 0; + parent->needsUpdating = true; + parent->needsIcons = true; + } + else + { + runFile(parent->files[trueIndex].fileName, parent->files[trueIndex].path, false); + } + } + else + { + RmLogF(parent->rm, LOG_WARNING, L"!CommandMeasure: Unknown command: %s", args); + } + + LeaveCriticalSection(&g_CriticalSection); + return; + } + + LeaveCriticalSection(&g_CriticalSection); + RmLogF(parent->rm, LOG_WARNING, L"!CommandMeasure: Unknown command: %s", args); +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + ChildMeasure* child = (ChildMeasure*)data; + ParentMeasure* parent = child->parent; + + EnterCriticalSection(&g_CriticalSection); + if (parent && parent->ownerChild == child) + { + if (parent->thread) + { + TerminateThread(parent->thread, 0); + parent->thread = nullptr; + } + + auto iter = std::find(g_ParentMeasures.begin(), g_ParentMeasures.end(), parent); + g_ParentMeasures.erase(iter); + + delete parent; + } + + delete child; + LeaveCriticalSection(&g_CriticalSection); +} + +unsigned __stdcall SystemThreadProc(void* pParam) +{ + CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + + ParentMeasure* parent = (ParentMeasure*)pParam; + + EnterCriticalSection(&g_CriticalSection); + ParentMeasure* tmp = new ParentMeasure (*parent); + parent->needsUpdating = false; // Set to false here in case skin is reloaded + parent->needsIcons = false; // Set to false here in case skin is reloaded + LeaveCriticalSection(&g_CriticalSection); + + FileInfo file; + + if (tmp->needsUpdating) + { + EnterCriticalSection(&g_CriticalSection); + parent->files.clear(); + parent->fileCount = 0; + parent->folderCount = 0; + parent->folderSize = 0; + LeaveCriticalSection(&g_CriticalSection); + + tmp->files.clear(); + tmp->fileCount = 0; + tmp->folderCount = 0; + tmp->folderSize = 0; + + // If no path is specified, get all the drives instead + if (tmp->path.empty()) + { + WCHAR drive[4] = L" :\\"; + DWORD driveMask = GetLogicalDrives(); + for (int i = 0; i < 32; ++i) + { + if ((driveMask << (31 - i) >> 31) > 0) + { + drive[0] = i + 'A'; + file.fileName = drive; + file.isFolder = true; + file.size = 0; + + ++tmp->folderCount; + tmp->files.push_back(file); + } + } + } + else + { + if (tmp->showDotDot && tmp->recursiveType != RECURSIVE_FULL) + { + file.fileName = L".."; + file.isFolder = true; + + tmp->files.push_back(file); + } + + std::queue folderQueue; + std::wstring folder = tmp->path; + + RecursiveType rType = tmp->recursiveType; + GetFolderInfo(folderQueue, folder, tmp, (rType == RECURSIVE_PARTIAL) ? RECURSIVE_NONE : rType); + + while (rType != RECURSIVE_NONE && !folderQueue.empty()) + { + folder = folderQueue.front(); + GetFolderInfo(folderQueue, folder, tmp, rType); + folderQueue.pop(); + } + } + + // Sort + const int sortAsc = tmp->sortAscending ? 1 : -1; + auto begin = (!tmp->path.empty() && + (tmp->showDotDot && tmp->recursiveType != RECURSIVE_FULL)) ? tmp->files.begin() + 1: tmp->files.begin(); + + switch (tmp->sortType) + { + case STYPE_NAME: + std::sort(begin, tmp->files.end(), + [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool + { + if (file1.isFolder && file2.isFolder) + { + return (sortAsc * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); + } + else if (!file1.isFolder && !file2.isFolder) + { + return (sortAsc * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); + } + return file1.isFolder; + }); + break; + + case STYPE_SIZE: + std::sort(begin, tmp->files.end(), + [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool + { + if (file1.isFolder && file2.isFolder) + { + return (sortAsc * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); + } + else if (!file1.isFolder && !file2.isFolder) + { + return (sortAsc > 0) ? (file1.size < file2.size) : (file1.size > file2.size); + } + return file1.isFolder; + }); + break; + + case STYPE_TYPE: + std::sort(begin, tmp->files.end(), + [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool + { + if (file1.isFolder && file2.isFolder) + { + return (sortAsc * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); + } + else if (!file1.isFolder && !file2.isFolder) + { + int result = (file1.ext.empty() && file2.ext.empty()) ? 0 : sortAsc * _wcsicmp(file1.ext.c_str(), file2.ext.c_str()); + return (0 != result) ? (result < 0) : (sortAsc * _wcsicmp(file1.fileName.c_str(), file2.fileName.c_str()) < 0); + } + return file1.isFolder; + }); + break; + + case STYPE_DATE: + switch (tmp->sortDateType) + { + case DTYPE_MODIFIED: + std::sort(begin, tmp->files.end(), + [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool + { + if (file1.isFolder && file2.isFolder) + { + return (sortAsc * CompareFileTime(&file1.modifiedTime, &file2.modifiedTime) < 0); + } + else if (!file1.isFolder && !file2.isFolder) + { + return (sortAsc * CompareFileTime(&file1.modifiedTime, &file2.modifiedTime) < 0); + } + return file1.isFolder; + }); + break; + + case DTYPE_CREATED: + std::sort(begin, tmp->files.end(), + [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool + { + if (file1.isFolder && file2.isFolder) + { + return (sortAsc * CompareFileTime(&file1.createdTime, &file2.createdTime) < 0); + } + else if (!file1.isFolder && !file2.isFolder) + { + return (sortAsc * CompareFileTime(&file1.createdTime, &file2.createdTime) < 0); + } + return file1.isFolder; + }); + break; + + case DTYPE_ACCESSED: + std::sort(begin, tmp->files.end(), + [&sortAsc](const FileInfo& file1, const FileInfo& file2) -> bool + { + if (file1.isFolder && file2.isFolder) + { + return (sortAsc * CompareFileTime(&file1.accessedTime, &file2.accessedTime) < 0); + } + else if (!file1.isFolder && !file2.isFolder) + { + return (sortAsc * CompareFileTime(&file1.accessedTime, &file2.accessedTime) < 0); + } + return file1.isFolder; + }); + break; + } + break; + } + + EnterCriticalSection(&g_CriticalSection); + parent->files = tmp->files; + parent->files.shrink_to_fit(); + parent->fileCount = tmp->fileCount; + parent->folderCount = tmp->folderCount; + parent->folderSize = tmp->folderSize; + LeaveCriticalSection(&g_CriticalSection); + } + + if (tmp->needsIcons) + { + for (auto iter : tmp->iconChildren) + { + EnterCriticalSection(&g_CriticalSection); + int trueIndex = iter->ignoreCount ? iter->index : ((iter->index % iter->parent->count) + iter->parent->indexOffset); + + if (iter->type == TYPE_ICON && trueIndex >= 0 && trueIndex < (int)tmp->files.size()) + { + std::wstring filePath = tmp->files[trueIndex].path; + filePath += (tmp->files[trueIndex].fileName == L"..") ? L"" :tmp->files[trueIndex].fileName; + GetIcon(filePath, iter->iconPath, iter->iconSize); + } + else if (iter->type == TYPE_ICON) + { + GetIcon(INVALID_FILE, iter->iconPath, iter->iconSize); + } + LeaveCriticalSection(&g_CriticalSection); + } + } + + EnterCriticalSection(&g_CriticalSection); + CloseHandle(parent->thread); + parent->thread = nullptr; + LeaveCriticalSection(&g_CriticalSection); + + if (!tmp->finishAction.empty()) + { + RmExecute(tmp->skin, tmp->finishAction.c_str()); + } + + delete tmp; + + CoUninitialize(); + return 0; +} + +void GetFolderInfo(std::queue& folderQueue, std::wstring& folder, ParentMeasure* parent, RecursiveType rType) +{ + std::wstring path = folder; + folder += (rType == RECURSIVE_NONE) ? parent->wildcardSearch : L"*"; + + WIN32_FIND_DATA fd; + HANDLE find = FindFirstFileEx(folder.c_str(), FindExInfoStandard, &fd, FindExSearchNameMatch, nullptr, 0); + + if (find != INVALID_HANDLE_VALUE) + { + do + { + FileInfo file; + + file.fileName = fd.cFileName; + if (_wcsicmp(file.fileName.c_str(), L".") == 0 || _wcsicmp(file.fileName.c_str(), L"..") == 0) + { + continue; + } + + file.isFolder = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0; + bool isHidden = (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) > 0; + bool isSystem = (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) > 0; + + if (rType == RECURSIVE_FULL && parent->wildcardSearch != L"*" && !file.isFolder) + { + if (!PathMatchSpec(file.fileName.c_str(), parent->wildcardSearch.c_str())) + { + continue; + } + } + + if ((rType != RECURSIVE_PARTIAL) && + ((rType != RECURSIVE_FULL && !parent->showFile && !file.isFolder) || + (rType != RECURSIVE_FULL && !parent->showFolder && file.isFolder) || + (!parent->showHidden && isHidden) ||(!parent->showSystem && isSystem))) + { + continue; + } + + if (rType != RECURSIVE_PARTIAL && !file.isFolder) + { + size_t pos = file.fileName.find_last_of(L"."); + if (pos != std::wstring::npos) + { + file.ext = file.fileName.substr(pos + 1); + + if (parent->extensions.size() > 0) + { + bool found = false; + for (auto iter : parent->extensions) + { + if (_wcsicmp(iter.c_str(), file.ext.c_str()) == 0) + { + found = true; + break; + } + } + + if (!found) + { + continue; + } + } + } + else if (parent->extensions.size() > 0) + { + continue; + } + } + + if (file.isFolder) + { + if (rType != RECURSIVE_FULL) + { + ++parent->folderCount; + } + + folderQueue.push(path + file.fileName + L"\\"); + } + else + { + ++parent->fileCount; + file.size = ((UINT64)fd.nFileSizeHigh << 32) + fd.nFileSizeLow; + } + + parent->folderSize += file.size; + + file.createdTime = fd.ftCreationTime; + file.modifiedTime = fd.ftLastWriteTime; + file.accessedTime = fd.ftLastAccessTime; + + file.path = path; + + if (rType == RECURSIVE_NONE || (rType == RECURSIVE_FULL && !file.isFolder)) + { + parent->files.push_back(file); + } + } + while (FindNextFile(find, &fd)); + FindClose(find); + } +} + +void GetIcon(std::wstring filePath, const std::wstring& iconPath, IconSize iconSize) +{ + SHFILEINFO shFileInfo; + HICON icon = nullptr; + HIMAGELIST* hImageList = nullptr; + FILE* fp = nullptr; + + // Special case for .url files + if (filePath.size() > 3 && _wcsicmp(filePath.substr(filePath.size() - 4).c_str(), L".URL") == 0) + { + WCHAR buffer[MAX_PATH] = L""; + GetPrivateProfileString(L"InternetShortcut", L"IconFile", L"", buffer, sizeof(buffer), filePath.c_str()); + if (*buffer) + { + std::wstring file = buffer; + int iconIndex = 0; + + GetPrivateProfileString(L"InternetShortcut", L"IconIndex", L"-1", buffer, sizeof(buffer), filePath.c_str()); + if (buffer != L"-1") + { + iconIndex = _wtoi(buffer); + } + + int size = 16; + switch (iconSize) + { + case IS_EXLARGE: size = 256; break; + case IS_LARGE: size = 48; break; + case IS_MEDIUM: size = 32; break; + } + + PrivateExtractIcons(file.c_str(), iconIndex, size, size, &icon, nullptr, 1, LR_LOADTRANSPARENT); + } + else + { + std::wstring browser; + WCHAR buffer[MAX_PATH]; + DWORD size = MAX_PATH; + HKEY hKey; + + RegOpenKeyEx(HKEY_CLASSES_ROOT, L"http\\shell\\open\\command", 0, KEY_QUERY_VALUE, &hKey); + RegQueryValueEx(hKey, nullptr, nullptr, nullptr, (LPBYTE)buffer, &size); + RegCloseKey(hKey); + + //Strip quotes + if (buffer[0] == L'"') + { + browser = buffer; browser = browser.substr(1); + size_t pos = browser.find_first_of(L'"'); + browser = browser.substr(0, pos); + } + + filePath = browser; + } + } + + if (icon == nullptr) + { + SHGetFileInfo(filePath.c_str(), 0, &shFileInfo, sizeof(shFileInfo), SHGFI_SYSICONINDEX); + SHGetImageList(iconSize, IID_IImageList, (void**) &hImageList); + ((IImageList*)hImageList)->GetIcon(shFileInfo.iIcon, ILD_TRANSPARENT, &icon); + } + + errno_t error = _wfopen_s(&fp, iconPath.c_str(), L"wb"); + if (filePath == INVALID_FILE || icon == nullptr || (error == 0 && !SaveIcon(icon, fp))) + { + fwrite(iconPath.c_str(), 1, 1, fp); // Clears previous icon + fclose(fp); + } + + DestroyIcon(icon); +} + +HRESULT SaveIcon(HICON hIcon, FILE* fp) +{ + ICONINFO iconInfo; + BITMAP bmColor; + BITMAP bmMask; + if (!fp || nullptr == hIcon || !GetIconInfo(hIcon, &iconInfo) || + !GetObject(iconInfo.hbmColor, sizeof(bmColor), &bmColor) || + !GetObject(iconInfo.hbmMask, sizeof(bmMask), &bmMask)) + return false; + + // support only 16/32 bit icon now + if (bmColor.bmBitsPixel != 16 && bmColor.bmBitsPixel != 32) + return false; + + HDC dc = GetDC(nullptr); + BYTE bmiBytes[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)]; + BITMAPINFO* bmi = (BITMAPINFO*)bmiBytes; + + // color bits + memset(bmi, 0, sizeof(BITMAPINFO)); + bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + GetDIBits(dc, iconInfo.hbmColor, 0, bmColor.bmHeight, nullptr, bmi, DIB_RGB_COLORS); + int colorBytesCount = bmi->bmiHeader.biSizeImage; + BYTE* colorBits = new BYTE[colorBytesCount]; + GetDIBits(dc, iconInfo.hbmColor, 0, bmColor.bmHeight, colorBits, bmi, DIB_RGB_COLORS); + + // mask bits + memset(bmi, 0, sizeof(BITMAPINFO)); + bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + GetDIBits(dc, iconInfo.hbmMask, 0, bmMask.bmHeight, nullptr, bmi, DIB_RGB_COLORS); + int maskBytesCount = bmi->bmiHeader.biSizeImage; + BYTE* maskBits = new BYTE[maskBytesCount]; + GetDIBits(dc, iconInfo.hbmMask, 0, bmMask.bmHeight, maskBits, bmi, DIB_RGB_COLORS); + + ReleaseDC(nullptr, dc); + + // icon data + BITMAPINFOHEADER bmihIcon; + memset(&bmihIcon, 0, sizeof(bmihIcon)); + bmihIcon.biSize = sizeof(BITMAPINFOHEADER); + bmihIcon.biWidth = bmColor.bmWidth; + bmihIcon.biHeight = bmColor.bmHeight * 2; // icXOR + icAND + bmihIcon.biPlanes = bmColor.bmPlanes; + bmihIcon.biBitCount = bmColor.bmBitsPixel; + bmihIcon.biSizeImage = colorBytesCount + maskBytesCount; + + // icon header + ICONDIR dir; + dir.idReserved = 0; // must be 0 + dir.idType = 1; // 1 for icons + dir.idCount = 1; + dir.idEntries[0].bWidth = (BYTE)bmColor.bmWidth; + dir.idEntries[0].bHeight = (BYTE)bmColor.bmHeight; + dir.idEntries[0].bColorCount = 0; // 0 if >= 8bpp + dir.idEntries[0].bReserved = 0; // must be 0 + dir.idEntries[0].wPlanes = bmColor.bmPlanes; + dir.idEntries[0].wBitCount = bmColor.bmBitsPixel; + dir.idEntries[0].dwBytesInRes = sizeof(bmihIcon) + bmihIcon.biSizeImage; + dir.idEntries[0].dwImageOffset = sizeof(ICONDIR); + + fwrite(&dir, sizeof(dir), 1, fp); + fwrite(&bmihIcon, sizeof(bmihIcon), 1, fp); + fwrite(colorBits, colorBytesCount, 1, fp); + fwrite(maskBits, maskBytesCount, 1, fp); + + // Clean up + DeleteObject(iconInfo.hbmColor); + DeleteObject(iconInfo.hbmMask); + delete[] colorBits; + delete[] maskBits; + + fclose(fp); + + return true; } \ No newline at end of file diff --git a/Plugins/PluginFileView/PluginFileView.h b/Plugins/PluginFileView/PluginFileView.h index 1f77c36c..abcb62b3 100644 --- a/Plugins/PluginFileView/PluginFileView.h +++ b/Plugins/PluginFileView/PluginFileView.h @@ -1,285 +1,285 @@ -/* - Copyright (C) 2012 Brian Ferguson - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include - -enum MeasureType -{ - TYPE_FOLDERPATH, - TYPE_FOLDERSIZE, - TYPE_FILECOUNT, - TYPE_FOLDERCOUNT, - TYPE_FILENAME, - TYPE_FILETYPE, - TYPE_FILESIZE, - TYPE_FILEDATE, - TYPE_FILEPATH, - TYPE_ICON -}; - -enum DateType -{ - DTYPE_MODIFIED, - DTYPE_CREATED, - DTYPE_ACCESSED -}; - -enum SortType -{ - STYPE_NAME, - STYPE_SIZE, - STYPE_TYPE, - STYPE_DATE -}; - -enum IconSize -{ - IS_SMALL = 1, // 16x16 - IS_MEDIUM = 0, // 32x32 - IS_LARGE = 2, // 48x48 - IS_EXLARGE = 4 // 256x256 -}; - -enum RecursiveType -{ - RECURSIVE_NONE, - RECURSIVE_PARTIAL, - RECURSIVE_FULL -}; - -struct FileInfo -{ - std::wstring fileName; - std::wstring path; - std::wstring ext; - bool isFolder; - UINT64 size; - FILETIME createdTime; - FILETIME modifiedTime; - FILETIME accessedTime; - - FileInfo() : - fileName(L""), - path(L""), - ext(L""), - isFolder(false), - size(0), - createdTime(), - modifiedTime(), - accessedTime() { } -}; - -struct ChildMeasure; - -struct ParentMeasure -{ - std::wstring path; - std::wstring wildcardSearch; - SortType sortType; - DateType sortDateType; - int count; - RecursiveType recursiveType; - bool sortAscending; - bool showDotDot; - bool showFile; - bool showFolder; - bool showHidden; - bool showSystem; - bool hideExtension; - std::vector extensions; - std::wstring finishAction; - - std::vector iconChildren; - std::vector files; - int fileCount; - int folderCount; - UINT64 folderSize; - bool needsUpdating; - bool needsIcons; - int indexOffset; - HANDLE thread; - - void* rm; - HWND hwnd; - void* skin; - LPCWSTR name; - ChildMeasure* ownerChild; - - ParentMeasure() : - path(), - wildcardSearch(), - folderSize(0), - sortType(STYPE_NAME), - sortDateType(DTYPE_MODIFIED), - count(0), - sortAscending(true), - showDotDot(true), - showFile(true), - showFolder(true), - showHidden(true), - showSystem(false), - hideExtension(false), - extensions(), - finishAction(), - iconChildren(), - files(), - skin(nullptr), - name(), - ownerChild(nullptr), - rm(), - hwnd(), - thread(nullptr), - fileCount(0), - folderCount(0), - needsUpdating(true), - needsIcons(true), - indexOffset(0), - recursiveType(RECURSIVE_NONE) { } -}; - -struct ChildMeasure -{ - MeasureType type; - DateType date; - IconSize iconSize; - std::wstring iconPath; - int index; - bool ignoreCount; - - std::wstring strValue; - ParentMeasure* parent; - - ChildMeasure() : - type(TYPE_FOLDERPATH), - date(DTYPE_MODIFIED), - iconSize(IS_LARGE), - iconPath(), - index(1), - ignoreCount(false), - strValue(), - parent(nullptr) { } -}; - -std::vector Tokenize(const std::wstring& str, const std::wstring& delimiters) -{ - std::vector tokens; - - std::wstring::size_type lastPos = str.find_first_not_of(delimiters, 0); - std::wstring::size_type pos = str.find_first_of(delimiters, lastPos); - - while (std::wstring::npos != pos || std::wstring::npos != lastPos) - { - tokens.emplace_back(str.substr(lastPos, pos - lastPos)); - lastPos = str.find_first_not_of(delimiters, pos); - pos = str.find_first_of(delimiters, lastPos); - } - - return tokens; -} - -void GetParentFolder(std::wstring& path) -{ - std::vector tokens = Tokenize(path, L"\\"); - if (tokens.size() < 2) - { - path.clear(); - } - else - { - path.clear(); - for (size_t i = 0; i < tokens.size() - 1; ++i) - { - path += tokens[i]; - path += L"\\"; - } - } -} - -bool ShowContextMenu(HWND hwnd, std::wstring& path) -{ - POINT pos; - GetCursorPos(&pos); - - // If the mouse is outside of the boundaries of - // the skin, use the upper-left corner of the skin - RECT rect; - GetWindowRect(hwnd, &rect); - if (pos.x < rect.left || pos.x > rect.right || - pos.y < rect.top || pos.y > rect.bottom) - { - pos.x = rect.left; - pos.y = rect.top; - } - - ITEMIDLIST* id = nullptr; - HRESULT result = SHParseDisplayName(path.c_str(), nullptr, &id, 0, nullptr); - if (!SUCCEEDED(result) || !id) - return false; - - Microsoft::WRL::ComPtr iFolder = nullptr; - LPCITEMIDLIST idChild = nullptr; - result = SHBindToParent(id, IID_IShellFolder, (void**)&iFolder, &idChild); - if (!SUCCEEDED(result) || !iFolder) - return false; - - Microsoft::WRL::ComPtr iMenu = nullptr; - result = iFolder->GetUIObjectOf(hwnd, 1, (const ITEMIDLIST **)&idChild, IID_IContextMenu, nullptr, (void**)&iMenu); - if (!SUCCEEDED(result) || !iFolder) - return false; - - HMENU hMenu = CreatePopupMenu(); - if (!hMenu) - return false; - - if (SUCCEEDED(iMenu->QueryContextMenu(hMenu, 0, 1, 0x7FFF, CMF_NORMAL))) - { - int iCmd = TrackPopupMenuEx(hMenu, TPM_RETURNCMD, pos.x, pos.y, hwnd, NULL); - if (iCmd > 0) - { - CMINVOKECOMMANDINFOEX info = { 0 }; - info.cbSize = sizeof(info); - info.fMask = CMIC_MASK_UNICODE | CMIC_MASK_ASYNCOK; - info.hwnd = hwnd; - info.lpVerb = MAKEINTRESOURCEA(iCmd - 1); - info.lpVerbW = MAKEINTRESOURCEW(iCmd - 1); - info.nShow = SW_SHOWNORMAL; - - iMenu->InvokeCommand((LPCMINVOKECOMMANDINFO)&info); - } - } - - DestroyMenu(hMenu); - return true; -} - -/*std::wstring UINT64_To_String(UINT64 value) -{ - std::wstring result; - result.reserve(20); // Max of 20 digits possible - do - { - result += "0123456789"[value % 10]; - value /= 10; - } - while(value); - - std::reverse(result.begin(), result.end()); - - return result; +/* + Copyright (C) 2012 Brian Ferguson + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include + +enum MeasureType +{ + TYPE_FOLDERPATH, + TYPE_FOLDERSIZE, + TYPE_FILECOUNT, + TYPE_FOLDERCOUNT, + TYPE_FILENAME, + TYPE_FILETYPE, + TYPE_FILESIZE, + TYPE_FILEDATE, + TYPE_FILEPATH, + TYPE_ICON +}; + +enum DateType +{ + DTYPE_MODIFIED, + DTYPE_CREATED, + DTYPE_ACCESSED +}; + +enum SortType +{ + STYPE_NAME, + STYPE_SIZE, + STYPE_TYPE, + STYPE_DATE +}; + +enum IconSize +{ + IS_SMALL = 1, // 16x16 + IS_MEDIUM = 0, // 32x32 + IS_LARGE = 2, // 48x48 + IS_EXLARGE = 4 // 256x256 +}; + +enum RecursiveType +{ + RECURSIVE_NONE, + RECURSIVE_PARTIAL, + RECURSIVE_FULL +}; + +struct FileInfo +{ + std::wstring fileName; + std::wstring path; + std::wstring ext; + bool isFolder; + UINT64 size; + FILETIME createdTime; + FILETIME modifiedTime; + FILETIME accessedTime; + + FileInfo() : + fileName(L""), + path(L""), + ext(L""), + isFolder(false), + size(0), + createdTime(), + modifiedTime(), + accessedTime() { } +}; + +struct ChildMeasure; + +struct ParentMeasure +{ + std::wstring path; + std::wstring wildcardSearch; + SortType sortType; + DateType sortDateType; + int count; + RecursiveType recursiveType; + bool sortAscending; + bool showDotDot; + bool showFile; + bool showFolder; + bool showHidden; + bool showSystem; + bool hideExtension; + std::vector extensions; + std::wstring finishAction; + + std::vector iconChildren; + std::vector files; + int fileCount; + int folderCount; + UINT64 folderSize; + bool needsUpdating; + bool needsIcons; + int indexOffset; + HANDLE thread; + + void* rm; + HWND hwnd; + void* skin; + LPCWSTR name; + ChildMeasure* ownerChild; + + ParentMeasure() : + path(), + wildcardSearch(), + folderSize(0), + sortType(STYPE_NAME), + sortDateType(DTYPE_MODIFIED), + count(0), + sortAscending(true), + showDotDot(true), + showFile(true), + showFolder(true), + showHidden(true), + showSystem(false), + hideExtension(false), + extensions(), + finishAction(), + iconChildren(), + files(), + skin(nullptr), + name(), + ownerChild(nullptr), + rm(), + hwnd(), + thread(nullptr), + fileCount(0), + folderCount(0), + needsUpdating(true), + needsIcons(true), + indexOffset(0), + recursiveType(RECURSIVE_NONE) { } +}; + +struct ChildMeasure +{ + MeasureType type; + DateType date; + IconSize iconSize; + std::wstring iconPath; + int index; + bool ignoreCount; + + std::wstring strValue; + ParentMeasure* parent; + + ChildMeasure() : + type(TYPE_FOLDERPATH), + date(DTYPE_MODIFIED), + iconSize(IS_LARGE), + iconPath(), + index(1), + ignoreCount(false), + strValue(), + parent(nullptr) { } +}; + +std::vector Tokenize(const std::wstring& str, const std::wstring& delimiters) +{ + std::vector tokens; + + std::wstring::size_type lastPos = str.find_first_not_of(delimiters, 0); + std::wstring::size_type pos = str.find_first_of(delimiters, lastPos); + + while (std::wstring::npos != pos || std::wstring::npos != lastPos) + { + tokens.emplace_back(str.substr(lastPos, pos - lastPos)); + lastPos = str.find_first_not_of(delimiters, pos); + pos = str.find_first_of(delimiters, lastPos); + } + + return tokens; +} + +void GetParentFolder(std::wstring& path) +{ + std::vector tokens = Tokenize(path, L"\\"); + if (tokens.size() < 2) + { + path.clear(); + } + else + { + path.clear(); + for (size_t i = 0; i < tokens.size() - 1; ++i) + { + path += tokens[i]; + path += L"\\"; + } + } +} + +bool ShowContextMenu(HWND hwnd, std::wstring& path) +{ + POINT pos; + GetCursorPos(&pos); + + // If the mouse is outside of the boundaries of + // the skin, use the upper-left corner of the skin + RECT rect; + GetWindowRect(hwnd, &rect); + if (pos.x < rect.left || pos.x > rect.right || + pos.y < rect.top || pos.y > rect.bottom) + { + pos.x = rect.left; + pos.y = rect.top; + } + + ITEMIDLIST* id = nullptr; + HRESULT result = SHParseDisplayName(path.c_str(), nullptr, &id, 0, nullptr); + if (!SUCCEEDED(result) || !id) + return false; + + Microsoft::WRL::ComPtr iFolder = nullptr; + LPCITEMIDLIST idChild = nullptr; + result = SHBindToParent(id, IID_IShellFolder, (void**)&iFolder, &idChild); + if (!SUCCEEDED(result) || !iFolder) + return false; + + Microsoft::WRL::ComPtr iMenu = nullptr; + result = iFolder->GetUIObjectOf(hwnd, 1, (const ITEMIDLIST **)&idChild, IID_IContextMenu, nullptr, (void**)&iMenu); + if (!SUCCEEDED(result) || !iFolder) + return false; + + HMENU hMenu = CreatePopupMenu(); + if (!hMenu) + return false; + + if (SUCCEEDED(iMenu->QueryContextMenu(hMenu, 0, 1, 0x7FFF, CMF_NORMAL))) + { + int iCmd = TrackPopupMenuEx(hMenu, TPM_RETURNCMD, pos.x, pos.y, hwnd, NULL); + if (iCmd > 0) + { + CMINVOKECOMMANDINFOEX info = { 0 }; + info.cbSize = sizeof(info); + info.fMask = CMIC_MASK_UNICODE | CMIC_MASK_ASYNCOK; + info.hwnd = hwnd; + info.lpVerb = MAKEINTRESOURCEA(iCmd - 1); + info.lpVerbW = MAKEINTRESOURCEW(iCmd - 1); + info.nShow = SW_SHOWNORMAL; + + iMenu->InvokeCommand((LPCMINVOKECOMMANDINFO)&info); + } + } + + DestroyMenu(hMenu); + return true; +} + +/*std::wstring UINT64_To_String(UINT64 value) +{ + std::wstring result; + result.reserve(20); // Max of 20 digits possible + do + { + result += "0123456789"[value % 10]; + value /= 10; + } + while(value); + + std::reverse(result.begin(), result.end()); + + return result; }*/ \ No newline at end of file diff --git a/Plugins/PluginFileView/PluginFileView.rc b/Plugins/PluginFileView/PluginFileView.rc index 2a71669e..87dfae06 100644 --- a/Plugins/PluginFileView/PluginFileView.rc +++ b/Plugins/PluginFileView/PluginFileView.rc @@ -1,40 +1,40 @@ -#include -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,0,3,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "2.0.3.0" - VALUE "LegalCopyright", " 2012 - Brian Ferguson" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 2,0,3,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "2.0.3.0" + VALUE "LegalCopyright", " 2012 - Brian Ferguson" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginFileView/PluginFileView.vcxproj b/Plugins/PluginFileView/PluginFileView.vcxproj index fdf97cd3..bc74b24e 100644 --- a/Plugins/PluginFileView/PluginFileView.vcxproj +++ b/Plugins/PluginFileView/PluginFileView.vcxproj @@ -1,47 +1,47 @@ - - - - - {64FDEE97-6B7E-40E5-A489-ECA322825BC8} - DynamicLibrary - FileView - - - - - - - - - - - - - - _USRDLL;HAVE_CONFIG_H;SUPPORT_UTF8;%(PreprocessorDefinitions) - - - - - Shlwapi.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - {19312085-aa51-4bd6-be92-4b6098cca539} - - - - - + + + + + {64FDEE97-6B7E-40E5-A489-ECA322825BC8} + DynamicLibrary + FileView + + + + + + + + + + + + + + _USRDLL;HAVE_CONFIG_H;SUPPORT_UTF8;%(PreprocessorDefinitions) + + + + + Shlwapi.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + {19312085-aa51-4bd6-be92-4b6098cca539} + + + + + \ No newline at end of file diff --git a/Plugins/PluginFileView/PluginFileView.vcxproj.filters b/Plugins/PluginFileView/PluginFileView.vcxproj.filters index b1f3ddf8..3714c215 100644 --- a/Plugins/PluginFileView/PluginFileView.vcxproj.filters +++ b/Plugins/PluginFileView/PluginFileView.vcxproj.filters @@ -1,13 +1,13 @@ - - - - - - - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/Plugins/PluginFileView/StdAfx.h b/Plugins/PluginFileView/StdAfx.h index 0aa2dafd..ca0ed1f0 100644 --- a/Plugins/PluginFileView/StdAfx.h +++ b/Plugins/PluginFileView/StdAfx.h @@ -1,41 +1,41 @@ -/* - Copyright (C) 2012 Brian Ferguson - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __STDAFX_H__ -#define __STDAFX_H__ - -// WinAPI -#include -#include -#include -#include -#include -#include -#include -#include - -// STL -#include -#include -#include -#include - -// Rainmeter API -#include "../API/RainmeterAPI.h" - +/* + Copyright (C) 2012 Brian Ferguson + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __STDAFX_H__ +#define __STDAFX_H__ + +// WinAPI +#include +#include +#include +#include +#include +#include +#include +#include + +// STL +#include +#include +#include +#include + +// Rainmeter API +#include "../API/RainmeterAPI.h" + #endif \ No newline at end of file diff --git a/Plugins/PluginFolderInfo/FolderInfo.cpp b/Plugins/PluginFolderInfo/FolderInfo.cpp index 55f859c5..818000ea 100644 --- a/Plugins/PluginFolderInfo/FolderInfo.cpp +++ b/Plugins/PluginFolderInfo/FolderInfo.cpp @@ -1,194 +1,194 @@ -/* - Copyright (C) 2010 Elestel - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "FolderInfo.h" -#include -#include -#include "../API/RainmeterAPI.h" - -#define UPDATE_TIME_MIN_MS 10000 - -CFolderInfo::CFolderInfo(void* ownerSkin) : - m_InstanceCount(1), - m_Skin(ownerSkin), - m_IncludeSubFolders(false), - m_IncludeHiddenFiles(false), - m_IncludeSystemFiles(false), - m_Size(), - m_FileCount(), - m_FolderCount(), - m_RegExpFilter(), - m_LastUpdateTime() -{ -} - -CFolderInfo::~CFolderInfo() -{ - FreePcre(); -} - -void CFolderInfo::AddInstance() -{ - ++m_InstanceCount; -} - -void CFolderInfo::RemoveInstance() -{ - --m_InstanceCount; - if (m_InstanceCount == 0) - { - delete this; - } -} - -void CFolderInfo::Clear() -{ - m_Size = 0; - m_FileCount = 0; - m_FolderCount = 0; -} - -void CFolderInfo::FreePcre() -{ - if (m_RegExpFilter) - { - pcre_free(m_RegExpFilter); - m_RegExpFilter = nullptr; - } -} - -void CFolderInfo::Update() -{ - DWORD now = GetTickCount(); - if (now - m_LastUpdateTime > UPDATE_TIME_MIN_MS) - { - Clear(); - - if (!m_Path.empty()) - { - CalculateSize(); - } - - m_LastUpdateTime = now; - } -} - -void CFolderInfo::CalculateSize() -{ - std::list folderQueue; - folderQueue.push_back(m_Path.c_str()); - - WCHAR searchPattern[MAX_PATH + 10]; - WCHAR buffer[MAX_PATH]; - char utf8Buf[MAX_PATH * 3]; - WIN32_FIND_DATA findData; - HANDLE findHandle; - while (!folderQueue.empty()) - { - const RawString& ref = folderQueue.front(); - wsprintf(searchPattern, L"%s%s", ref.c_str(), L"\\*.*"); - - findHandle = FindFirstFile(searchPattern, &findData); - if (INVALID_HANDLE_VALUE == findHandle) - { - folderQueue.pop_front(); - continue; - } - - do - { - // special case for "." and ".." - if (wcscmp(findData.cFileName, L".") == 0 || - wcscmp(findData.cFileName, L"..") == 0) - { - continue; - } - - bool isFolder = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0; - - if (!m_IncludeHiddenFiles && (findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) - { - continue; - } - else if (!m_IncludeSystemFiles && (findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) - { - continue; - } - else if (!isFolder && m_RegExpFilter) - { - const int utf8BufLen = WideCharToMultiByte( - CP_UTF8, 0, findData.cFileName, (int)wcslen(findData.cFileName) + 1, utf8Buf, MAX_PATH * 3, - nullptr, nullptr); - if (0 != pcre_exec(m_RegExpFilter, nullptr, utf8Buf, utf8BufLen, 0, 0, nullptr, 0)) - { - continue; - } - } - - if (isFolder) - { - m_FolderCount++; - if (m_IncludeSubFolders) - { - wsprintf(buffer, L"%s\\%s", ref.c_str(), findData.cFileName); - folderQueue.push_back(buffer); - } - } - else - { - m_FileCount++; - m_Size += ((UINT64)findData.nFileSizeHigh << 32) + findData.nFileSizeLow; - } - } - while (FindNextFile(findHandle, &findData)); - FindClose(findHandle); - - folderQueue.pop_front(); - } -} - -void CFolderInfo::SetPath(LPCWSTR path) -{ - if (wcscmp(m_Path.c_str(), path) != 0) - { - m_Path = path; - - // Force update next time - m_LastUpdateTime = 0; - } -} - -void CFolderInfo::SetRegExpFilter(LPCWSTR filter) -{ - FreePcre(); - - if (*filter) - { - const int filterLen = (int)wcslen(filter) + 1; - int bufLen = WideCharToMultiByte(CP_UTF8, 0, filter, filterLen, nullptr, 0, nullptr, nullptr); - - char* buf = new char[bufLen]; - WideCharToMultiByte(CP_UTF8, 0, filter, filterLen, buf, bufLen, nullptr, nullptr); - - const char* error; - int erroffset; - m_RegExpFilter = pcre_compile(buf, PCRE_UTF8, &error, &erroffset, nullptr); - - delete [] buf; - } -} +/* + Copyright (C) 2010 Elestel + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "FolderInfo.h" +#include +#include +#include "../API/RainmeterAPI.h" + +#define UPDATE_TIME_MIN_MS 10000 + +CFolderInfo::CFolderInfo(void* ownerSkin) : + m_InstanceCount(1), + m_Skin(ownerSkin), + m_IncludeSubFolders(false), + m_IncludeHiddenFiles(false), + m_IncludeSystemFiles(false), + m_Size(), + m_FileCount(), + m_FolderCount(), + m_RegExpFilter(), + m_LastUpdateTime() +{ +} + +CFolderInfo::~CFolderInfo() +{ + FreePcre(); +} + +void CFolderInfo::AddInstance() +{ + ++m_InstanceCount; +} + +void CFolderInfo::RemoveInstance() +{ + --m_InstanceCount; + if (m_InstanceCount == 0) + { + delete this; + } +} + +void CFolderInfo::Clear() +{ + m_Size = 0; + m_FileCount = 0; + m_FolderCount = 0; +} + +void CFolderInfo::FreePcre() +{ + if (m_RegExpFilter) + { + pcre_free(m_RegExpFilter); + m_RegExpFilter = nullptr; + } +} + +void CFolderInfo::Update() +{ + DWORD now = GetTickCount(); + if (now - m_LastUpdateTime > UPDATE_TIME_MIN_MS) + { + Clear(); + + if (!m_Path.empty()) + { + CalculateSize(); + } + + m_LastUpdateTime = now; + } +} + +void CFolderInfo::CalculateSize() +{ + std::list folderQueue; + folderQueue.push_back(m_Path.c_str()); + + WCHAR searchPattern[MAX_PATH + 10]; + WCHAR buffer[MAX_PATH]; + char utf8Buf[MAX_PATH * 3]; + WIN32_FIND_DATA findData; + HANDLE findHandle; + while (!folderQueue.empty()) + { + const RawString& ref = folderQueue.front(); + wsprintf(searchPattern, L"%s%s", ref.c_str(), L"\\*.*"); + + findHandle = FindFirstFile(searchPattern, &findData); + if (INVALID_HANDLE_VALUE == findHandle) + { + folderQueue.pop_front(); + continue; + } + + do + { + // special case for "." and ".." + if (wcscmp(findData.cFileName, L".") == 0 || + wcscmp(findData.cFileName, L"..") == 0) + { + continue; + } + + bool isFolder = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0; + + if (!m_IncludeHiddenFiles && (findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) + { + continue; + } + else if (!m_IncludeSystemFiles && (findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) + { + continue; + } + else if (!isFolder && m_RegExpFilter) + { + const int utf8BufLen = WideCharToMultiByte( + CP_UTF8, 0, findData.cFileName, (int)wcslen(findData.cFileName) + 1, utf8Buf, MAX_PATH * 3, + nullptr, nullptr); + if (0 != pcre_exec(m_RegExpFilter, nullptr, utf8Buf, utf8BufLen, 0, 0, nullptr, 0)) + { + continue; + } + } + + if (isFolder) + { + m_FolderCount++; + if (m_IncludeSubFolders) + { + wsprintf(buffer, L"%s\\%s", ref.c_str(), findData.cFileName); + folderQueue.push_back(buffer); + } + } + else + { + m_FileCount++; + m_Size += ((UINT64)findData.nFileSizeHigh << 32) + findData.nFileSizeLow; + } + } + while (FindNextFile(findHandle, &findData)); + FindClose(findHandle); + + folderQueue.pop_front(); + } +} + +void CFolderInfo::SetPath(LPCWSTR path) +{ + if (wcscmp(m_Path.c_str(), path) != 0) + { + m_Path = path; + + // Force update next time + m_LastUpdateTime = 0; + } +} + +void CFolderInfo::SetRegExpFilter(LPCWSTR filter) +{ + FreePcre(); + + if (*filter) + { + const int filterLen = (int)wcslen(filter) + 1; + int bufLen = WideCharToMultiByte(CP_UTF8, 0, filter, filterLen, nullptr, 0, nullptr, nullptr); + + char* buf = new char[bufLen]; + WideCharToMultiByte(CP_UTF8, 0, filter, filterLen, buf, bufLen, nullptr, nullptr); + + const char* error; + int erroffset; + m_RegExpFilter = pcre_compile(buf, PCRE_UTF8, &error, &erroffset, nullptr); + + delete [] buf; + } +} diff --git a/Plugins/PluginFolderInfo/FolderInfo.h b/Plugins/PluginFolderInfo/FolderInfo.h index f4fb50e1..25c52c38 100644 --- a/Plugins/PluginFolderInfo/FolderInfo.h +++ b/Plugins/PluginFolderInfo/FolderInfo.h @@ -1,68 +1,68 @@ -/* - Copyright (C) 2010 Elestel - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma once - -#include -#include -#include "../../Common/RawString.h" -#include "../../Library/pcre-8.10/config.h" -#include "../../Library/pcre-8.10/pcre.h" - -class CFolderInfo -{ -public: - CFolderInfo(void* ownerSkin); - ~CFolderInfo(); - - void AddInstance(); - void RemoveInstance(); - - void* GetSkin() { return m_Skin; } - DWORD GetLastUpdateTime() { return m_LastUpdateTime; } - - void SetPath(LPCWSTR path); - void SetRegExpFilter(LPCWSTR filter); - void SetSubFolders(bool flag) { m_IncludeSubFolders = flag; } - void SetHiddenFiles(bool flag) { m_IncludeHiddenFiles = flag; } - void SetSystemFiles(bool flag) { m_IncludeSystemFiles = flag; } - - UINT64 GetSize() { return m_Size; } - int GetFileCount() { return m_FileCount; } - int GetFolderCount() { return m_FolderCount; } - - void Update(); - -private: - void Clear(); - void FreePcre(); - void CalculateSize(); - - UINT m_InstanceCount; - void* m_Skin; - - RawString m_Path; - bool m_IncludeSubFolders; - bool m_IncludeHiddenFiles; - bool m_IncludeSystemFiles; - UINT64 m_Size; - UINT m_FileCount; - UINT m_FolderCount; - pcre* m_RegExpFilter; - DWORD m_LastUpdateTime; -}; +/* + Copyright (C) 2010 Elestel + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include +#include +#include "../../Common/RawString.h" +#include "../../Library/pcre-8.10/config.h" +#include "../../Library/pcre-8.10/pcre.h" + +class CFolderInfo +{ +public: + CFolderInfo(void* ownerSkin); + ~CFolderInfo(); + + void AddInstance(); + void RemoveInstance(); + + void* GetSkin() { return m_Skin; } + DWORD GetLastUpdateTime() { return m_LastUpdateTime; } + + void SetPath(LPCWSTR path); + void SetRegExpFilter(LPCWSTR filter); + void SetSubFolders(bool flag) { m_IncludeSubFolders = flag; } + void SetHiddenFiles(bool flag) { m_IncludeHiddenFiles = flag; } + void SetSystemFiles(bool flag) { m_IncludeSystemFiles = flag; } + + UINT64 GetSize() { return m_Size; } + int GetFileCount() { return m_FileCount; } + int GetFolderCount() { return m_FolderCount; } + + void Update(); + +private: + void Clear(); + void FreePcre(); + void CalculateSize(); + + UINT m_InstanceCount; + void* m_Skin; + + RawString m_Path; + bool m_IncludeSubFolders; + bool m_IncludeHiddenFiles; + bool m_IncludeSystemFiles; + UINT64 m_Size; + UINT m_FileCount; + UINT m_FolderCount; + pcre* m_RegExpFilter; + DWORD m_LastUpdateTime; +}; diff --git a/Plugins/PluginFolderInfo/FolderInfoPlugin.cpp b/Plugins/PluginFolderInfo/FolderInfoPlugin.cpp index c868ec8a..9c009179 100644 --- a/Plugins/PluginFolderInfo/FolderInfoPlugin.cpp +++ b/Plugins/PluginFolderInfo/FolderInfoPlugin.cpp @@ -1,158 +1,158 @@ -/* - Copyright (C) 2010 Elestel - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include -#include "FolderInfo.h" -#include "../API/RainmeterAPI.h" - -enum MeasureType -{ - MEASURE_FILECOUNT, - MEASURE_FOLDERCOUNT, - MEASURE_FOLDERSIZE -}; - -struct MeasureData -{ - LPCWSTR section; - CFolderInfo* folder; - MeasureType type; - bool parent; - - MeasureData(LPCWSTR section) : - section(section), - folder(), - type(MEASURE_FILECOUNT), - parent(false) - { - } -}; - -std::vector g_Measures; - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - MeasureData* measure = new MeasureData(RmGetMeasureName(rm)); - *data = measure; - g_Measures.push_back(measure); - - void* skin = RmGetSkin(rm); - - LPCWSTR str = RmReadString(rm, L"Folder", L"", FALSE); - if (*str == L'[') - { - const size_t len = wcslen(str); - for (auto iter = g_Measures.cbegin(); iter != g_Measures.cend(); ++iter) - { - if ((*iter)->folder && - (*iter)->folder->GetSkin() == skin && - wcsncmp(&str[1], (*iter)->section, len - 2) == 0) - { - measure->folder = (*iter)->folder; - measure->folder->AddInstance(); - return; - } - } - } - - measure->folder = new CFolderInfo(skin); - measure->parent = true; -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - MeasureData* measure = (MeasureData*)data; - CFolderInfo* folder = measure->folder; - - if (!folder) - { - return; - } - - LPCWSTR str = RmReadString(rm, L"InfoType", L""); - if (_wcsicmp(str, L"FolderSize") == 0 || _wcsicmp(str, L"FolderSizeStr") == 0) - { - measure->type = MEASURE_FOLDERSIZE; - } - else if (_wcsicmp(str, L"FolderCount") == 0 || _wcsicmp(str, L"FolderCountStr") == 0) - { - measure->type = MEASURE_FOLDERCOUNT; - } - else if (_wcsicmp(str, L"FileCount") == 0 || _wcsicmp(str, L"FileCountStr") == 0) - { - measure->type = MEASURE_FILECOUNT; - } - - if (measure->parent) - { - str = RmReadPath(rm, L"Folder", L""); - folder->SetPath(str); - - str = RmReadString(rm, L"RegExpFilter", L""); - folder->SetRegExpFilter(str); - - folder->SetSubFolders(RmReadInt(rm, L"IncludeSubFolders", 0) == 1); - folder->SetHiddenFiles(RmReadInt(rm, L"IncludeHiddenFiles", 0) == 1); - folder->SetSystemFiles(RmReadInt(rm, L"IncludeSystemFiles", 0) == 1); - } -} - -PLUGIN_EXPORT double Update(void* data) -{ - MeasureData* measure = (MeasureData*)data; - if (!measure->folder) - { - return 0.0; - } - - if (measure->parent) - { - measure->folder->Update(); - } - - switch (measure->type) - { - case MEASURE_FOLDERSIZE: - return (double)measure->folder->GetSize(); - - case MEASURE_FILECOUNT: - return measure->folder->GetFileCount(); - - case MEASURE_FOLDERCOUNT: - return measure->folder->GetFolderCount(); - } - - return 0.0; -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - MeasureData* measure = (MeasureData*)data; - - if (measure->folder) - { - measure->folder->RemoveInstance(); - } - - delete measure; - - std::vector::iterator iter = std::find(g_Measures.begin(), g_Measures.end(), measure); - g_Measures.erase(iter); -} +/* + Copyright (C) 2010 Elestel + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include "FolderInfo.h" +#include "../API/RainmeterAPI.h" + +enum MeasureType +{ + MEASURE_FILECOUNT, + MEASURE_FOLDERCOUNT, + MEASURE_FOLDERSIZE +}; + +struct MeasureData +{ + LPCWSTR section; + CFolderInfo* folder; + MeasureType type; + bool parent; + + MeasureData(LPCWSTR section) : + section(section), + folder(), + type(MEASURE_FILECOUNT), + parent(false) + { + } +}; + +std::vector g_Measures; + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + MeasureData* measure = new MeasureData(RmGetMeasureName(rm)); + *data = measure; + g_Measures.push_back(measure); + + void* skin = RmGetSkin(rm); + + LPCWSTR str = RmReadString(rm, L"Folder", L"", FALSE); + if (*str == L'[') + { + const size_t len = wcslen(str); + for (auto iter = g_Measures.cbegin(); iter != g_Measures.cend(); ++iter) + { + if ((*iter)->folder && + (*iter)->folder->GetSkin() == skin && + wcsncmp(&str[1], (*iter)->section, len - 2) == 0) + { + measure->folder = (*iter)->folder; + measure->folder->AddInstance(); + return; + } + } + } + + measure->folder = new CFolderInfo(skin); + measure->parent = true; +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + MeasureData* measure = (MeasureData*)data; + CFolderInfo* folder = measure->folder; + + if (!folder) + { + return; + } + + LPCWSTR str = RmReadString(rm, L"InfoType", L""); + if (_wcsicmp(str, L"FolderSize") == 0 || _wcsicmp(str, L"FolderSizeStr") == 0) + { + measure->type = MEASURE_FOLDERSIZE; + } + else if (_wcsicmp(str, L"FolderCount") == 0 || _wcsicmp(str, L"FolderCountStr") == 0) + { + measure->type = MEASURE_FOLDERCOUNT; + } + else if (_wcsicmp(str, L"FileCount") == 0 || _wcsicmp(str, L"FileCountStr") == 0) + { + measure->type = MEASURE_FILECOUNT; + } + + if (measure->parent) + { + str = RmReadPath(rm, L"Folder", L""); + folder->SetPath(str); + + str = RmReadString(rm, L"RegExpFilter", L""); + folder->SetRegExpFilter(str); + + folder->SetSubFolders(RmReadInt(rm, L"IncludeSubFolders", 0) == 1); + folder->SetHiddenFiles(RmReadInt(rm, L"IncludeHiddenFiles", 0) == 1); + folder->SetSystemFiles(RmReadInt(rm, L"IncludeSystemFiles", 0) == 1); + } +} + +PLUGIN_EXPORT double Update(void* data) +{ + MeasureData* measure = (MeasureData*)data; + if (!measure->folder) + { + return 0.0; + } + + if (measure->parent) + { + measure->folder->Update(); + } + + switch (measure->type) + { + case MEASURE_FOLDERSIZE: + return (double)measure->folder->GetSize(); + + case MEASURE_FILECOUNT: + return measure->folder->GetFileCount(); + + case MEASURE_FOLDERCOUNT: + return measure->folder->GetFolderCount(); + } + + return 0.0; +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + MeasureData* measure = (MeasureData*)data; + + if (measure->folder) + { + measure->folder->RemoveInstance(); + } + + delete measure; + + std::vector::iterator iter = std::find(g_Measures.begin(), g_Measures.end(), measure); + g_Measures.erase(iter); +} diff --git a/Plugins/PluginFolderInfo/PluginFolderInfo.rc b/Plugins/PluginFolderInfo/PluginFolderInfo.rc index bcb98f6b..f6b95d65 100644 --- a/Plugins/PluginFolderInfo/PluginFolderInfo.rc +++ b/Plugins/PluginFolderInfo/PluginFolderInfo.rc @@ -1,40 +1,40 @@ -#include -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.0.0.0" - VALUE "LegalCopyright", " 2010 - Elestel" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.0.0.0" + VALUE "LegalCopyright", " 2010 - Elestel" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginFolderInfo/PluginFolderInfo.vcxproj b/Plugins/PluginFolderInfo/PluginFolderInfo.vcxproj index ef10e77a..9aa98a9e 100644 --- a/Plugins/PluginFolderInfo/PluginFolderInfo.vcxproj +++ b/Plugins/PluginFolderInfo/PluginFolderInfo.vcxproj @@ -1,44 +1,44 @@ - - - - - {A221819D-4263-42AA-B22A-C022924842A7} - DynamicLibrary - FolderInfo - - - - - - - - - - - - - - _USRDLL;HAVE_CONFIG_H;SUPPORT_UTF8;%(PreprocessorDefinitions) - - - - - - - - - - - - - - - - - - - - - - + + + + + {A221819D-4263-42AA-B22A-C022924842A7} + DynamicLibrary + FolderInfo + + + + + + + + + + + + + + _USRDLL;HAVE_CONFIG_H;SUPPORT_UTF8;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Plugins/PluginFolderInfo/PluginFolderInfo.vcxproj.filters b/Plugins/PluginFolderInfo/PluginFolderInfo.vcxproj.filters index e6939414..d06fff1a 100644 --- a/Plugins/PluginFolderInfo/PluginFolderInfo.vcxproj.filters +++ b/Plugins/PluginFolderInfo/PluginFolderInfo.vcxproj.filters @@ -1,33 +1,33 @@ - - - - - - pcre - - - pcre - - - pcre - - - pcre - - - - - - - pcre - - - - - - - - {aaeb51d4-65cd-4eb6-954f-724800c27387} - - + + + + + + pcre + + + pcre + + + pcre + + + pcre + + + + + + + pcre + + + + + + + + {aaeb51d4-65cd-4eb6-954f-724800c27387} + + \ No newline at end of file diff --git a/Plugins/PluginInputText/AssemblyInfo.cs b/Plugins/PluginInputText/AssemblyInfo.cs index 8c05e710..54a916d0 100644 --- a/Plugins/PluginInputText/AssemblyInfo.cs +++ b/Plugins/PluginInputText/AssemblyInfo.cs @@ -1,7 +1,7 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -[assembly: AssemblyCopyright("© 2010 - Peter Souza IV")] -[assembly: AssemblyVersion("1.7.0.0")] -[assembly: AssemblyInformationalVersion(Rainmeter.Version.Informational)] -[assembly: AssemblyProduct("Rainmeter")] +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyCopyright("© 2010 - Peter Souza IV")] +[assembly: AssemblyVersion("1.7.0.0")] +[assembly: AssemblyInformationalVersion(Rainmeter.Version.Informational)] +[assembly: AssemblyProduct("Rainmeter")] diff --git a/Plugins/PluginInputText/InputBox.Designer.cs b/Plugins/PluginInputText/InputBox.Designer.cs index 1206c36e..76e6dd27 100644 --- a/Plugins/PluginInputText/InputBox.Designer.cs +++ b/Plugins/PluginInputText/InputBox.Designer.cs @@ -1,105 +1,105 @@ -namespace InputText -{ - partial class InputBox - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.txtInput = new System.Windows.Forms.TextBox(); - this.btnOK = new System.Windows.Forms.Button(); - this.btnCancel = new System.Windows.Forms.Button(); - this.SuspendLayout(); - // - // txtInput - // - this.txtInput.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.txtInput.Location = new System.Drawing.Point(0, 0); - this.txtInput.Margin = new System.Windows.Forms.Padding(0); - this.txtInput.Multiline = true; - this.txtInput.Name = "txtInput"; - this.txtInput.Size = new System.Drawing.Size(200, 22); - this.txtInput.TabIndex = 0; - this.txtInput.Leave += new System.EventHandler(this.txtInput_Leave); - // - // btnOK - // - this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK; - this.btnOK.Location = new System.Drawing.Point(2, 2); - this.btnOK.Margin = new System.Windows.Forms.Padding(0); - this.btnOK.Name = "btnOK"; - this.btnOK.Size = new System.Drawing.Size(2, 2); - this.btnOK.TabIndex = 1; - this.btnOK.TabStop = false; - this.btnOK.Text = "OK"; - this.btnOK.UseVisualStyleBackColor = true; - this.btnOK.Click += new System.EventHandler(this.btnOK_Click); - // - // btnCancel - // - this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.btnCancel.Location = new System.Drawing.Point(2, 2); - this.btnCancel.Margin = new System.Windows.Forms.Padding(0); - this.btnCancel.Name = "btnCancel"; - this.btnCancel.Size = new System.Drawing.Size(2, 2); - this.btnCancel.TabIndex = 2; - this.btnCancel.TabStop = false; - this.btnCancel.Text = "btnCancel"; - this.btnCancel.UseVisualStyleBackColor = true; - this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); - // - // InputBox - // - this.AcceptButton = this.btnOK; - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; - this.AutoSize = true; - this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.CancelButton = this.btnCancel; - this.ClientSize = new System.Drawing.Size(251, 42); - this.Controls.Add(this.txtInput); - this.Controls.Add(this.btnCancel); - this.Controls.Add(this.btnOK); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - this.Name = "InputBox"; - this.ShowIcon = false; - this.ShowInTaskbar = false; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "InputBox"; - this.Deactivate += new System.EventHandler(this.InputBox_Deactivate); - this.Load += new System.EventHandler(this.InputBox_Load); - this.Shown += new System.EventHandler(this.InputBox_Shown); - this.Leave += new System.EventHandler(this.InputBox_Leave); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.TextBox txtInput; - private System.Windows.Forms.Button btnOK; - private System.Windows.Forms.Button btnCancel; - } +namespace InputText +{ + partial class InputBox + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.txtInput = new System.Windows.Forms.TextBox(); + this.btnOK = new System.Windows.Forms.Button(); + this.btnCancel = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // txtInput + // + this.txtInput.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.txtInput.Location = new System.Drawing.Point(0, 0); + this.txtInput.Margin = new System.Windows.Forms.Padding(0); + this.txtInput.Multiline = true; + this.txtInput.Name = "txtInput"; + this.txtInput.Size = new System.Drawing.Size(200, 22); + this.txtInput.TabIndex = 0; + this.txtInput.Leave += new System.EventHandler(this.txtInput_Leave); + // + // btnOK + // + this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK; + this.btnOK.Location = new System.Drawing.Point(2, 2); + this.btnOK.Margin = new System.Windows.Forms.Padding(0); + this.btnOK.Name = "btnOK"; + this.btnOK.Size = new System.Drawing.Size(2, 2); + this.btnOK.TabIndex = 1; + this.btnOK.TabStop = false; + this.btnOK.Text = "OK"; + this.btnOK.UseVisualStyleBackColor = true; + this.btnOK.Click += new System.EventHandler(this.btnOK_Click); + // + // btnCancel + // + this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btnCancel.Location = new System.Drawing.Point(2, 2); + this.btnCancel.Margin = new System.Windows.Forms.Padding(0); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.Size = new System.Drawing.Size(2, 2); + this.btnCancel.TabIndex = 2; + this.btnCancel.TabStop = false; + this.btnCancel.Text = "btnCancel"; + this.btnCancel.UseVisualStyleBackColor = true; + this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); + // + // InputBox + // + this.AcceptButton = this.btnOK; + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.AutoSize = true; + this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.CancelButton = this.btnCancel; + this.ClientSize = new System.Drawing.Size(251, 42); + this.Controls.Add(this.txtInput); + this.Controls.Add(this.btnCancel); + this.Controls.Add(this.btnOK); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; + this.Name = "InputBox"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "InputBox"; + this.Deactivate += new System.EventHandler(this.InputBox_Deactivate); + this.Load += new System.EventHandler(this.InputBox_Load); + this.Shown += new System.EventHandler(this.InputBox_Shown); + this.Leave += new System.EventHandler(this.InputBox_Leave); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox txtInput; + private System.Windows.Forms.Button btnOK; + private System.Windows.Forms.Button btnCancel; + } } \ No newline at end of file diff --git a/Plugins/PluginInputText/InputBox.cs b/Plugins/PluginInputText/InputBox.cs index 9d9b4fff..41096fb9 100644 --- a/Plugins/PluginInputText/InputBox.cs +++ b/Plugins/PluginInputText/InputBox.cs @@ -1,382 +1,382 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -using System; -using System.Drawing; -using System.Windows.Forms; - -namespace InputText -{ - public partial class InputBox : Form - { - private SkinWindow parent = null; - - private bool _FocusDismiss = true; - private string _TextValue = string.Empty; - - public InputBox(SkinWindow parent) - { - this.parent = parent; - - InitializeComponent(); - } - - // This event will make sure we have focus when the inputbox is shown ot the user. - // it will only cause focus if the window itself has focus (i.e. doesn't steal). - private void InputBox_Shown(object sender, EventArgs e) - { - this.Activate(); - this.BringToFront(); - this.Activate(); - this.BringToFront(); - this.txtInput.Focus(); - } - - private void InputBox_Load(object sender, EventArgs e) - { - this.Activate(); - this.BringToFront(); - this.Activate(); - this.BringToFront(); - } - - // All exceptions are swallowed for the sake of this example. Since the majority - // (if not all) of these are rather simple in nature, debugging without errors - // should be fairly simple anyway. - // - // However, if you wanted to log errors, a simple way would be to add something like - // this: - // - // try - // { - // ... // code you are testing - // } - // catch (Exception ex) - // { - // API.Log(API.LogType.Warning, "InputText :: exception :: " + ex.GetType().ToString() + ": " + ex.Message); - // } - - #region TextValue -- returns the inputted text - public string TextValue - { - get { return this._TextValue; } - } - #endregion - #region ChangeFontFace(string) -- changes the text's font name - public void ChangeFontFace(string sFont) - { - try - { - this.txtInput.Font = new Font(sFont, this.txtInput.Font.Size); - } - catch { } - } - #endregion - #region ChangeFontColor(string) -- changes the font's color, supports 6 and 8-digit hex or a series of 3 or 4 comma-separated numbers - public void ChangeFontColor(string sColor) - { - try - { - sColor = sColor.Trim(); - - if (sColor.Contains(",")) // #,#,# or #,#,#,# format - { - string[] sParts = sColor.Trim().Replace(" ", string.Empty).Split(new char[] { ',' }, StringSplitOptions.None); - this.txtInput.ForeColor = Color.FromArgb(int.Parse(sParts[0]), int.Parse(sParts[1]), int.Parse(sParts[2])); - this.txtInput.ForeColor = Color.FromArgb(int.Parse(sParts[3]), int.Parse(sParts[0]), int.Parse(sParts[1]), int.Parse(sParts[2])); - } - else - { - if (sColor.Length == 6) // 6-digit hex (no alpha transparency) - { - uint iColor = uint.Parse(sColor, System.Globalization.NumberStyles.HexNumber); - // Since it was omitted, force full opacity (not transparent at all) - this.txtInput.ForeColor = Color.FromArgb((int)(0xFF000000 | iColor)); - } - else if (sColor.Length == 8) // 8-digit hex (with alpha transparency) - { - uint iColor = uint.Parse(sColor, System.Globalization.NumberStyles.HexNumber); - // This swaps RRGGBBAA for AARRGGBB, which Color.FromArgb() wants - iColor = ((iColor & 0xFFFFFF00) >> 8) | ((iColor & 0x000000FF) << 24); - this.txtInput.ForeColor = Color.FromArgb((int)iColor); - } - } - } - catch { } - } - #endregion - #region ChangeBackColor(string) -- changes the background color, supports 6 and 8-digit hex or a series of 3 or 4 comma-separated numbers - public void ChangeBackColor(string sColor) - { - try - { - sColor = sColor.Trim(); - - if (sColor.Contains(",")) // #,#,# or #,#,#,# format - { - string[] sParts = sColor.Trim().Replace(" ", string.Empty).Split(new char[] { ',' }, StringSplitOptions.None); - this.txtInput.BackColor = Color.FromArgb(int.Parse(sParts[0]), int.Parse(sParts[1]), int.Parse(sParts[2])); - - // Change 0-255 transparency to a 0.0-1.0 transparency range - double dTrans = (double)int.Parse(sParts[3]); - dTrans /= 255.0; - this.Opacity = dTrans; - } - else - { - if (sColor.Length == 6) // 6-digit hex (no alpha transparency) - { - uint iColor = uint.Parse(sColor, System.Globalization.NumberStyles.HexNumber); - this.txtInput.BackColor = Color.FromArgb((int)(0xFF000000 | iColor)); - // Since it was omitted, force full opacity (not transparent at all) - this.Opacity = 1.0; - } - else if (sColor.Length == 8) // 8-digit hex (with alpha transparency) - { - uint iColor = uint.Parse(sColor, System.Globalization.NumberStyles.HexNumber); - // This swaps RRGGBBAA for AARRGGBB, which Color.FromArgb() wants - iColor = ((iColor & 0xFFFFFF00) >> 8) | ((iColor & 0x000000FF) << 24); - this.txtInput.BackColor = Color.FromArgb((int)((0xFF000000) | (0x00FFFFFF & iColor))); - - // Change 0-255 transparency to a 0.0-1.0 transparency range - double dTrans = (double)((iColor & 0xFF000000) >> 24); - dTrans /= 255.0; - this.Opacity = dTrans; - } - } - } - catch { } - } - #endregion - #region ChangeStringAlign(string) -- Changes text horizontal alignment - public void ChangeStringAlign(string sAlign) - { - try - { - sAlign = sAlign.ToUpper().Trim(); - - if (sAlign == "LEFT") - this.txtInput.TextAlign = HorizontalAlignment.Left; - else if (sAlign == "CENTER") - this.txtInput.TextAlign = HorizontalAlignment.Center; - else if (sAlign == "RIGHT") - this.txtInput.TextAlign = HorizontalAlignment.Right; - } - catch { } - } - #endregion - #region ChangeFontSize(string) -- changes the font's point size (supports floating-point values) - public void ChangeFontSize(string sSize) - { - try - { - this.txtInput.Font = new Font(this.txtInput.Font.Name, float.Parse(sSize)); - } - catch { } - } - #endregion - #region MakeTopmost() -- forces the form to have the 'Always On Top' property - public void MakeTopmost() - { - this.TopMost = true; - } - #endregion - #region MakePassword(bool) -- causes the textbox to be password style - public void MakePassword(bool bPass) - { - this.txtInput.PasswordChar = bPass ? '*' : '\0'; - } - #endregion - #region ChangeFontStringStyle() -- changes the font's bold/italic styles - public void ChangeFontStringStyle(string sStyle) - { - try - { - sStyle = sStyle.ToUpper().Trim(); - - if (sStyle == "NORMAL") - this.txtInput.Font = new Font(this.txtInput.Font, FontStyle.Regular); - else if (sStyle == "BOLD") - this.txtInput.Font = new Font(this.txtInput.Font, FontStyle.Bold); - else if (sStyle == "ITALIC") - this.txtInput.Font = new Font(this.txtInput.Font, FontStyle.Italic); - else if (sStyle == "BOLDITALIC") - this.txtInput.Font = new Font(this.txtInput.Font, FontStyle.Bold | FontStyle.Italic); - } - catch { } - } - #endregion - #region ChangeW(string) -- changes the width of the input textbox - public void ChangeW(string sWidth) - { - try - { - this.txtInput.Width = int.Parse(sWidth); - } - catch { } - } - #endregion - #region ChangeH(string) -- changes the height of the input textbox - public void ChangeH(string sHeight) - { - try - { - this.txtInput.Height = int.Parse(sHeight); - } - catch { } - } - #endregion - #region ChangeX(string) -- changes the X (horizontal) position of the input textbox, relative to its parent skin - public void ChangeX(string sX) - { - try - { - // If the position is changed, make sure the form's auto-location is disabled. - if (this.StartPosition != FormStartPosition.Manual) - this.StartPosition = FormStartPosition.Manual; - - // Notice that we need the position of the parent window for offset location. - // - // The Rainmeter class does this for us - this.Location = new System.Drawing.Point(this.parent.X + int.Parse(sX), this.Location.Y); - } - catch { } - } - #endregion - #region ChangeY(string) -- changes the Y (vertical) position of the input textbox, relative to its parent skin - public void ChangeY(string sY) - { - try - { - // If the position is changed, make sure the form's auto-location is disabled. - if (this.StartPosition != FormStartPosition.Manual) - this.StartPosition = FormStartPosition.Manual; - - // Notice that we need the position of the parent window for offset location. - // - // The Rainmeter class does this for us - this.Location = new System.Drawing.Point(this.Location.X, this.parent.Y + int.Parse(sY)); - } - catch { } - } - #endregion - #region DefaultValue(string) -- sets the default text to appear in the input textbox - public void DefaultValue(string val) - { - this.txtInput.Text = val; - } - #endregion - #region MakeFocusDismiss(bool) -- dismisses the input textbox if it loses cursor/window focus - public void MakeFocusDismiss(bool bDismissing) - { - this._FocusDismiss = bDismissing; - } - #endregion - - #region ShowInputBox() -- shows text input textbox - - private DialogResult drBackup = DialogResult.None; - - public bool ShowInputBox() - { - if (this.drBackup != DialogResult.None) - return false; - - if (this._FocusDismiss) - { - this.Show(this.parent); - - while (this.DialogResult == DialogResult.None && - this.drBackup == DialogResult.None) - { - Application.DoEvents(); - System.Threading.Thread.Sleep(44); - } - } - else - { - this.ShowDialog(this.parent); - } - - if (this.drBackup != DialogResult.None) - { - if (this.drBackup != DialogResult.OK) - return false; - } - else if (this.DialogResult != DialogResult.None) - { - if (this.DialogResult != DialogResult.OK) - return false; - } - - return true; - } - - public void Abort() - { - this.drBackup = DialogResult.Abort; - this.Close(); - } - - private void txtInput_Leave(object sender, EventArgs e) - { - if (this._FocusDismiss) - { - this.drBackup = DialogResult.Cancel; - this.Close(); - } - } - - private void InputBox_Leave(object sender, EventArgs e) - { - if (this._FocusDismiss) - { - this.drBackup = DialogResult.Cancel; - this.Close(); - } - } - - private void InputBox_Deactivate(object sender, EventArgs e) - { - if (this._FocusDismiss) - { - this.drBackup = DialogResult.Cancel; - this.Close(); - } - } - - private void btnOK_Click(object sender, EventArgs e) - { - this._FocusDismiss = false; - this._TextValue = this.txtInput.Text.Trim(); - this.drBackup = DialogResult.OK; - this.DialogResult = DialogResult.OK; - this.Close(); - } - - private void btnCancel_Click(object sender, EventArgs e) - { - this._FocusDismiss = false; - this.drBackup = DialogResult.Cancel; - this.DialogResult = DialogResult.Cancel; - this.Close(); - } - - #endregion - } -} +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace InputText +{ + public partial class InputBox : Form + { + private SkinWindow parent = null; + + private bool _FocusDismiss = true; + private string _TextValue = string.Empty; + + public InputBox(SkinWindow parent) + { + this.parent = parent; + + InitializeComponent(); + } + + // This event will make sure we have focus when the inputbox is shown ot the user. + // it will only cause focus if the window itself has focus (i.e. doesn't steal). + private void InputBox_Shown(object sender, EventArgs e) + { + this.Activate(); + this.BringToFront(); + this.Activate(); + this.BringToFront(); + this.txtInput.Focus(); + } + + private void InputBox_Load(object sender, EventArgs e) + { + this.Activate(); + this.BringToFront(); + this.Activate(); + this.BringToFront(); + } + + // All exceptions are swallowed for the sake of this example. Since the majority + // (if not all) of these are rather simple in nature, debugging without errors + // should be fairly simple anyway. + // + // However, if you wanted to log errors, a simple way would be to add something like + // this: + // + // try + // { + // ... // code you are testing + // } + // catch (Exception ex) + // { + // API.Log(API.LogType.Warning, "InputText :: exception :: " + ex.GetType().ToString() + ": " + ex.Message); + // } + + #region TextValue -- returns the inputted text + public string TextValue + { + get { return this._TextValue; } + } + #endregion + #region ChangeFontFace(string) -- changes the text's font name + public void ChangeFontFace(string sFont) + { + try + { + this.txtInput.Font = new Font(sFont, this.txtInput.Font.Size); + } + catch { } + } + #endregion + #region ChangeFontColor(string) -- changes the font's color, supports 6 and 8-digit hex or a series of 3 or 4 comma-separated numbers + public void ChangeFontColor(string sColor) + { + try + { + sColor = sColor.Trim(); + + if (sColor.Contains(",")) // #,#,# or #,#,#,# format + { + string[] sParts = sColor.Trim().Replace(" ", string.Empty).Split(new char[] { ',' }, StringSplitOptions.None); + this.txtInput.ForeColor = Color.FromArgb(int.Parse(sParts[0]), int.Parse(sParts[1]), int.Parse(sParts[2])); + this.txtInput.ForeColor = Color.FromArgb(int.Parse(sParts[3]), int.Parse(sParts[0]), int.Parse(sParts[1]), int.Parse(sParts[2])); + } + else + { + if (sColor.Length == 6) // 6-digit hex (no alpha transparency) + { + uint iColor = uint.Parse(sColor, System.Globalization.NumberStyles.HexNumber); + // Since it was omitted, force full opacity (not transparent at all) + this.txtInput.ForeColor = Color.FromArgb((int)(0xFF000000 | iColor)); + } + else if (sColor.Length == 8) // 8-digit hex (with alpha transparency) + { + uint iColor = uint.Parse(sColor, System.Globalization.NumberStyles.HexNumber); + // This swaps RRGGBBAA for AARRGGBB, which Color.FromArgb() wants + iColor = ((iColor & 0xFFFFFF00) >> 8) | ((iColor & 0x000000FF) << 24); + this.txtInput.ForeColor = Color.FromArgb((int)iColor); + } + } + } + catch { } + } + #endregion + #region ChangeBackColor(string) -- changes the background color, supports 6 and 8-digit hex or a series of 3 or 4 comma-separated numbers + public void ChangeBackColor(string sColor) + { + try + { + sColor = sColor.Trim(); + + if (sColor.Contains(",")) // #,#,# or #,#,#,# format + { + string[] sParts = sColor.Trim().Replace(" ", string.Empty).Split(new char[] { ',' }, StringSplitOptions.None); + this.txtInput.BackColor = Color.FromArgb(int.Parse(sParts[0]), int.Parse(sParts[1]), int.Parse(sParts[2])); + + // Change 0-255 transparency to a 0.0-1.0 transparency range + double dTrans = (double)int.Parse(sParts[3]); + dTrans /= 255.0; + this.Opacity = dTrans; + } + else + { + if (sColor.Length == 6) // 6-digit hex (no alpha transparency) + { + uint iColor = uint.Parse(sColor, System.Globalization.NumberStyles.HexNumber); + this.txtInput.BackColor = Color.FromArgb((int)(0xFF000000 | iColor)); + // Since it was omitted, force full opacity (not transparent at all) + this.Opacity = 1.0; + } + else if (sColor.Length == 8) // 8-digit hex (with alpha transparency) + { + uint iColor = uint.Parse(sColor, System.Globalization.NumberStyles.HexNumber); + // This swaps RRGGBBAA for AARRGGBB, which Color.FromArgb() wants + iColor = ((iColor & 0xFFFFFF00) >> 8) | ((iColor & 0x000000FF) << 24); + this.txtInput.BackColor = Color.FromArgb((int)((0xFF000000) | (0x00FFFFFF & iColor))); + + // Change 0-255 transparency to a 0.0-1.0 transparency range + double dTrans = (double)((iColor & 0xFF000000) >> 24); + dTrans /= 255.0; + this.Opacity = dTrans; + } + } + } + catch { } + } + #endregion + #region ChangeStringAlign(string) -- Changes text horizontal alignment + public void ChangeStringAlign(string sAlign) + { + try + { + sAlign = sAlign.ToUpper().Trim(); + + if (sAlign == "LEFT") + this.txtInput.TextAlign = HorizontalAlignment.Left; + else if (sAlign == "CENTER") + this.txtInput.TextAlign = HorizontalAlignment.Center; + else if (sAlign == "RIGHT") + this.txtInput.TextAlign = HorizontalAlignment.Right; + } + catch { } + } + #endregion + #region ChangeFontSize(string) -- changes the font's point size (supports floating-point values) + public void ChangeFontSize(string sSize) + { + try + { + this.txtInput.Font = new Font(this.txtInput.Font.Name, float.Parse(sSize)); + } + catch { } + } + #endregion + #region MakeTopmost() -- forces the form to have the 'Always On Top' property + public void MakeTopmost() + { + this.TopMost = true; + } + #endregion + #region MakePassword(bool) -- causes the textbox to be password style + public void MakePassword(bool bPass) + { + this.txtInput.PasswordChar = bPass ? '*' : '\0'; + } + #endregion + #region ChangeFontStringStyle() -- changes the font's bold/italic styles + public void ChangeFontStringStyle(string sStyle) + { + try + { + sStyle = sStyle.ToUpper().Trim(); + + if (sStyle == "NORMAL") + this.txtInput.Font = new Font(this.txtInput.Font, FontStyle.Regular); + else if (sStyle == "BOLD") + this.txtInput.Font = new Font(this.txtInput.Font, FontStyle.Bold); + else if (sStyle == "ITALIC") + this.txtInput.Font = new Font(this.txtInput.Font, FontStyle.Italic); + else if (sStyle == "BOLDITALIC") + this.txtInput.Font = new Font(this.txtInput.Font, FontStyle.Bold | FontStyle.Italic); + } + catch { } + } + #endregion + #region ChangeW(string) -- changes the width of the input textbox + public void ChangeW(string sWidth) + { + try + { + this.txtInput.Width = int.Parse(sWidth); + } + catch { } + } + #endregion + #region ChangeH(string) -- changes the height of the input textbox + public void ChangeH(string sHeight) + { + try + { + this.txtInput.Height = int.Parse(sHeight); + } + catch { } + } + #endregion + #region ChangeX(string) -- changes the X (horizontal) position of the input textbox, relative to its parent skin + public void ChangeX(string sX) + { + try + { + // If the position is changed, make sure the form's auto-location is disabled. + if (this.StartPosition != FormStartPosition.Manual) + this.StartPosition = FormStartPosition.Manual; + + // Notice that we need the position of the parent window for offset location. + // + // The Rainmeter class does this for us + this.Location = new System.Drawing.Point(this.parent.X + int.Parse(sX), this.Location.Y); + } + catch { } + } + #endregion + #region ChangeY(string) -- changes the Y (vertical) position of the input textbox, relative to its parent skin + public void ChangeY(string sY) + { + try + { + // If the position is changed, make sure the form's auto-location is disabled. + if (this.StartPosition != FormStartPosition.Manual) + this.StartPosition = FormStartPosition.Manual; + + // Notice that we need the position of the parent window for offset location. + // + // The Rainmeter class does this for us + this.Location = new System.Drawing.Point(this.Location.X, this.parent.Y + int.Parse(sY)); + } + catch { } + } + #endregion + #region DefaultValue(string) -- sets the default text to appear in the input textbox + public void DefaultValue(string val) + { + this.txtInput.Text = val; + } + #endregion + #region MakeFocusDismiss(bool) -- dismisses the input textbox if it loses cursor/window focus + public void MakeFocusDismiss(bool bDismissing) + { + this._FocusDismiss = bDismissing; + } + #endregion + + #region ShowInputBox() -- shows text input textbox + + private DialogResult drBackup = DialogResult.None; + + public bool ShowInputBox() + { + if (this.drBackup != DialogResult.None) + return false; + + if (this._FocusDismiss) + { + this.Show(this.parent); + + while (this.DialogResult == DialogResult.None && + this.drBackup == DialogResult.None) + { + Application.DoEvents(); + System.Threading.Thread.Sleep(44); + } + } + else + { + this.ShowDialog(this.parent); + } + + if (this.drBackup != DialogResult.None) + { + if (this.drBackup != DialogResult.OK) + return false; + } + else if (this.DialogResult != DialogResult.None) + { + if (this.DialogResult != DialogResult.OK) + return false; + } + + return true; + } + + public void Abort() + { + this.drBackup = DialogResult.Abort; + this.Close(); + } + + private void txtInput_Leave(object sender, EventArgs e) + { + if (this._FocusDismiss) + { + this.drBackup = DialogResult.Cancel; + this.Close(); + } + } + + private void InputBox_Leave(object sender, EventArgs e) + { + if (this._FocusDismiss) + { + this.drBackup = DialogResult.Cancel; + this.Close(); + } + } + + private void InputBox_Deactivate(object sender, EventArgs e) + { + if (this._FocusDismiss) + { + this.drBackup = DialogResult.Cancel; + this.Close(); + } + } + + private void btnOK_Click(object sender, EventArgs e) + { + this._FocusDismiss = false; + this._TextValue = this.txtInput.Text.Trim(); + this.drBackup = DialogResult.OK; + this.DialogResult = DialogResult.OK; + this.Close(); + } + + private void btnCancel_Click(object sender, EventArgs e) + { + this._FocusDismiss = false; + this.drBackup = DialogResult.Cancel; + this.DialogResult = DialogResult.Cancel; + this.Close(); + } + + #endregion + } +} diff --git a/Plugins/PluginInputText/InputBox.resx b/Plugins/PluginInputText/InputBox.resx index 5ea0895e..7080a7d1 100644 --- a/Plugins/PluginInputText/InputBox.resx +++ b/Plugins/PluginInputText/InputBox.resx @@ -1,120 +1,120 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + \ No newline at end of file diff --git a/Plugins/PluginInputText/Main.cs b/Plugins/PluginInputText/Main.cs index a666e30f..2344b912 100644 --- a/Plugins/PluginInputText/Main.cs +++ b/Plugins/PluginInputText/Main.cs @@ -1,208 +1,208 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Threading; -using Rainmeter; - -namespace InputText -{ - internal partial class Measure - { - private Rainmeter.API rm; - - private string LastInput = string.Empty; - private bool IsExecuteBangRunning = false; - - private object locker = new object(); - - internal Measure(Rainmeter.API rm) - { - this.rm = rm; - } - - internal void Reload(Rainmeter.API rm, ref double maxValue) - { - // Do nothing here. - } - - internal double Update() - { - return 0.0; - } - - internal string GetString() - { - lock (this.locker) - { - return this.LastInput; - } - } - - internal void ExecuteBang(string args) - { - bool go = false; - - lock (this.locker) - { - if (!this.IsExecuteBangRunning) - { - this.IsExecuteBangRunning = true; - go = true; - } - } - - if (go) - { - ExecuteBangParam param = new ExecuteBangParam(args); - if (ReadOptions(param)) // Read all options in main thread for thread-safety - { - ThreadPool.QueueUserWorkItem(_ => - { - try - { - ExecuteCommands(param); - } - catch (Exception ex) - { - API.Log(API.LogType.Error, "C# plugin in ExecuteBang(), " + ex.GetType().ToString() + ": " + ex.Message); - } - - lock (this.locker) - { - this.IsExecuteBangRunning = false; - } - }); - } - else - { - // No need to continue - lock (this.locker) - { - this.IsExecuteBangRunning = false; - } - } - } - } - - private class ExecuteBangParam - { - internal enum BangType - { - Unknown, - SetVariable, - ExecuteBatch - }; - internal Dictionary Options; - internal List> OverrideOptions; - internal List Commands; - internal string Command; - internal string DismissAction; - internal BangType Type; - - internal ExecuteBangParam(string args) - { - this.Options = new Dictionary(); - this.OverrideOptions = new List>(); - this.Commands = new List(); - this.Command = args.Trim(); - this.DismissAction = null; - this.Type = BangType.Unknown; - } - }; - - private bool _IsFinalizing = false; - - internal void Dispose() - { - this._IsFinalizing = true; - FinalizePluginCode(); - } - } - - #region Plugin - - public static class Plugin - { - static IntPtr StringBuffer = IntPtr.Zero; - - [DllExport] - public static void Initialize(ref IntPtr data, IntPtr rm) - { - data = GCHandle.ToIntPtr(GCHandle.Alloc(new Measure(new Rainmeter.API(rm)))); - } - - [DllExport] - public static void Finalize(IntPtr data) - { - Measure measure = (Measure)GCHandle.FromIntPtr(data).Target; - measure.Dispose(); - GCHandle.FromIntPtr(data).Free(); - - if (StringBuffer != IntPtr.Zero) - { - Marshal.FreeHGlobal(StringBuffer); - StringBuffer = IntPtr.Zero; - } - } - - [DllExport] - public static void Reload(IntPtr data, IntPtr rm, ref double maxValue) - { - Measure measure = (Measure)GCHandle.FromIntPtr(data).Target; - measure.Reload(new Rainmeter.API(rm), ref maxValue); - } - - [DllExport] - public static double Update(IntPtr data) - { - Measure measure = (Measure)GCHandle.FromIntPtr(data).Target; - return measure.Update(); - } - - [DllExport] - public static IntPtr GetString(IntPtr data) - { - Measure measure = (Measure)GCHandle.FromIntPtr(data).Target; - if (StringBuffer != IntPtr.Zero) - { - Marshal.FreeHGlobal(StringBuffer); - StringBuffer = IntPtr.Zero; - } - - string stringValue = measure.GetString(); - if (stringValue != null) - { - StringBuffer = Marshal.StringToHGlobalUni(stringValue); - } - - return StringBuffer; - } - - [DllExport] - public static void ExecuteBang(IntPtr data, IntPtr args) - { - Measure measure = (Measure)GCHandle.FromIntPtr(data).Target; - measure.ExecuteBang(Marshal.PtrToStringUni(args)); - } - } - - #endregion -} +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading; +using Rainmeter; + +namespace InputText +{ + internal partial class Measure + { + private Rainmeter.API rm; + + private string LastInput = string.Empty; + private bool IsExecuteBangRunning = false; + + private object locker = new object(); + + internal Measure(Rainmeter.API rm) + { + this.rm = rm; + } + + internal void Reload(Rainmeter.API rm, ref double maxValue) + { + // Do nothing here. + } + + internal double Update() + { + return 0.0; + } + + internal string GetString() + { + lock (this.locker) + { + return this.LastInput; + } + } + + internal void ExecuteBang(string args) + { + bool go = false; + + lock (this.locker) + { + if (!this.IsExecuteBangRunning) + { + this.IsExecuteBangRunning = true; + go = true; + } + } + + if (go) + { + ExecuteBangParam param = new ExecuteBangParam(args); + if (ReadOptions(param)) // Read all options in main thread for thread-safety + { + ThreadPool.QueueUserWorkItem(_ => + { + try + { + ExecuteCommands(param); + } + catch (Exception ex) + { + API.Log(API.LogType.Error, "C# plugin in ExecuteBang(), " + ex.GetType().ToString() + ": " + ex.Message); + } + + lock (this.locker) + { + this.IsExecuteBangRunning = false; + } + }); + } + else + { + // No need to continue + lock (this.locker) + { + this.IsExecuteBangRunning = false; + } + } + } + } + + private class ExecuteBangParam + { + internal enum BangType + { + Unknown, + SetVariable, + ExecuteBatch + }; + internal Dictionary Options; + internal List> OverrideOptions; + internal List Commands; + internal string Command; + internal string DismissAction; + internal BangType Type; + + internal ExecuteBangParam(string args) + { + this.Options = new Dictionary(); + this.OverrideOptions = new List>(); + this.Commands = new List(); + this.Command = args.Trim(); + this.DismissAction = null; + this.Type = BangType.Unknown; + } + }; + + private bool _IsFinalizing = false; + + internal void Dispose() + { + this._IsFinalizing = true; + FinalizePluginCode(); + } + } + + #region Plugin + + public static class Plugin + { + static IntPtr StringBuffer = IntPtr.Zero; + + [DllExport] + public static void Initialize(ref IntPtr data, IntPtr rm) + { + data = GCHandle.ToIntPtr(GCHandle.Alloc(new Measure(new Rainmeter.API(rm)))); + } + + [DllExport] + public static void Finalize(IntPtr data) + { + Measure measure = (Measure)GCHandle.FromIntPtr(data).Target; + measure.Dispose(); + GCHandle.FromIntPtr(data).Free(); + + if (StringBuffer != IntPtr.Zero) + { + Marshal.FreeHGlobal(StringBuffer); + StringBuffer = IntPtr.Zero; + } + } + + [DllExport] + public static void Reload(IntPtr data, IntPtr rm, ref double maxValue) + { + Measure measure = (Measure)GCHandle.FromIntPtr(data).Target; + measure.Reload(new Rainmeter.API(rm), ref maxValue); + } + + [DllExport] + public static double Update(IntPtr data) + { + Measure measure = (Measure)GCHandle.FromIntPtr(data).Target; + return measure.Update(); + } + + [DllExport] + public static IntPtr GetString(IntPtr data) + { + Measure measure = (Measure)GCHandle.FromIntPtr(data).Target; + if (StringBuffer != IntPtr.Zero) + { + Marshal.FreeHGlobal(StringBuffer); + StringBuffer = IntPtr.Zero; + } + + string stringValue = measure.GetString(); + if (stringValue != null) + { + StringBuffer = Marshal.StringToHGlobalUni(stringValue); + } + + return StringBuffer; + } + + [DllExport] + public static void ExecuteBang(IntPtr data, IntPtr args) + { + Measure measure = (Measure)GCHandle.FromIntPtr(data).Target; + measure.ExecuteBang(Marshal.PtrToStringUni(args)); + } + } + + #endregion +} diff --git a/Plugins/PluginInputText/PluginCode.cs b/Plugins/PluginInputText/PluginCode.cs index f4ce586a..402d614b 100644 --- a/Plugins/PluginInputText/PluginCode.cs +++ b/Plugins/PluginInputText/PluginCode.cs @@ -1,524 +1,524 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -using System; -using System.Collections.Generic; -using Rainmeter; - -// The bulk of your plugin's code belongs in this file. -namespace InputText -{ - internal partial class Measure - { - private bool ReadOptions(ExecuteBangParam param) - { - // Get default options - ReadOption("DefaultValue", param.Options); - ReadOption("X", param.Options, true); - ReadOption("Y", param.Options, true); - ReadOption("W", param.Options, true); - ReadOption("H", param.Options, true); - ReadOption("StringStyle", param.Options); - ReadOption("StringAlign", param.Options); - ReadOption("FocusDismiss", param.Options); - ReadOption("FontColor", param.Options); - ReadOption("FontFace", param.Options); - ReadOption("FontSize", param.Options, true); - ReadOption("SolidColor", param.Options); - ReadOption("Password", param.Options); - ReadOption("TopMost", param.Options); - - param.DismissAction = rm.ReadString("OnDismissAction", "", false); - - #region Handle a single parameter - - // If our parameter list only contains a single word, then open a textbox immediately - // and set a value. This mode does not do any batching. - if (!param.Command.Contains(" ")) - { - param.Type = ExecuteBangParam.BangType.SetVariable; - return true; - } - - #endregion - #region Handle multiple parameters - - // Our parameter list contains at least two words, so split them up - string[] sParts = param.Command.Split(new string[] { " " }, StringSplitOptions.None); - - // If the first parameter is 'ExecuteBatch' (not case sensitive)... - if (sParts[0].Trim().ToUpper() == "EXECUTEBATCH") - { - param.Type = ExecuteBangParam.BangType.ExecuteBatch; - - // ExecuteBatch tells this plugin to go through the measure's settings to look - // for lines beginning with "Command" and executing Rainmeter bangs for each one. - // If a line contains $UserInput$, then an input textbox is opened and command - // execution pauses until the user enters text or dismisses the textbox. If the - // textbox is dismissed (Escape key, for example), all processing ends, otherwise - // it continues depending on the range of commands selected. - // - // Each "Command" line allows overriding all settings that the input textbox - // supports, therefor some checking and substitution is performed, thus a - // more complex parser has been implemented. - // - // ExecuteBatch expects this syntax: - // ExecuteBatch [All|#|#-#] - // - // This allows Rainmeter to call the plugin to execute a range including: - // All All commands in the measure - // # Only a single command in the measure - // #-# A specific range of commands in the measure - - #region Determine range - // Determine range. Default is 1 to 1,000,000,000, although if processing finds - // that a requested line is blank, it will stop all processing (so 'All' will - // only parse 14 lines if "Command15" does not exist or is blank). - int iMin = 1; - int iMax = 1000000000; - try - { - if (sParts[1].Trim().ToUpper() != "ALL") - { - if (sParts[1].Contains("-")) - { - string[] sSubParts = sParts[1].Split(new string[] { "-" }, StringSplitOptions.None); - iMin = int.Parse(sSubParts[0]); - iMax = int.Parse(sSubParts[1]); - } - else - iMin = iMax = int.Parse(sParts[1]); - } - } - catch // handle all errors above - { - // Any error above will be ignored and the default range used instead. - // This can occur if the measure asks to ExecuteBatch an invalid range - // or the range could not be translated to an acceptable format. - // - // For example: ExecuteBatch asdf - iMin = 1; - iMax = 1000000000; - } - #endregion - #region Parse commands in range - // Parse each command in the range, aborting if any line returns 'false' or - // the requested command line does not exist in the config for that measure. - for (int i = iMin; i <= iMax; i++) - { - // Read this command's line - string sLine = rm.ReadString("Command" + i.ToString(), "", false); - - // If empty/non-existent, abort - if (string.IsNullOrEmpty(sLine)) - break; - - #region Handle in-line overrides - // Create a blank list of overrides - Dictionary Overrides = new Dictionary(); - - // Start looking for overridable settings and adjust the list accordingly, - // stripping out settings from the line if they are discovered. - // - // The supporting TagData() function allows for whitespace if quotes are - // used. For example: - // - // DefaultValue="hello there, how are you" - sLine = ScanAndReplace(sLine, "DefaultValue", Overrides); - sLine = ScanAndReplace(sLine, "X", Overrides, true); - sLine = ScanAndReplace(sLine, "Y", Overrides, true); - sLine = ScanAndReplace(sLine, "W", Overrides, true); - sLine = ScanAndReplace(sLine, "H", Overrides, true); - sLine = ScanAndReplace(sLine, "StringStyle", Overrides); - sLine = ScanAndReplace(sLine, "StringAlign", Overrides); - sLine = ScanAndReplace(sLine, "FocusDismiss", Overrides); - sLine = ScanAndReplace(sLine, "FontColor", Overrides); - sLine = ScanAndReplace(sLine, "FontFace", Overrides); - sLine = ScanAndReplace(sLine, "FontSize", Overrides, true); - sLine = ScanAndReplace(sLine, "SolidColor", Overrides); - sLine = ScanAndReplace(sLine, "Password", Overrides); - sLine = ScanAndReplace(sLine, "TopMost", Overrides); - - param.OverrideOptions.Add(Overrides); - #endregion - - param.Commands.Add(sLine); - } - #endregion - - return param.Commands.Count > 0; - } - - #endregion - - // Unhandled command, log the message but otherwise do nothing - param.Type = ExecuteBangParam.BangType.Unknown; - API.Log(API.LogType.Debug, "InputText: Received command \"" + sParts[0].Trim() + "\", left unhandled"); - - return false; - } - - private void ExecuteCommands(ExecuteBangParam param) - { - switch (param.Type) - { - case ExecuteBangParam.BangType.SetVariable: - { - // Assume that the parameter is the name of the variable - - // Ask for input - string sInput = GetUserInput(param.Options); - - // If the user cancelled out of the inputbox (ESC key, etc.), then abort - if (sInput == null) - { - // Execute OnDismissAction if defined - if (!String.IsNullOrEmpty(param.DismissAction)) - API.Execute(rm.GetSkin(), param.DismissAction); - break; - } - - // Ask Rainmeter to set the variable using a bang (http://rainmeter.net/RainCMS/?q=Bangs) - API.Execute(rm.GetSkin(), "!SetVariable " + param.Command + " \"" + sInput + "\""); - - // Note that the skin needs DynamicVariables=1 in the measure's settings or the above - // code will have no effect. - } - break; - - case ExecuteBangParam.BangType.ExecuteBatch: - { - for (int i = 0; i < param.Commands.Count; ++i) - { - // Execute the line, but if there's a problem (error or they cancel the - // input textbox), then abort - if (!ExecuteLine(param.Commands[i], param.Options, param.OverrideOptions[i])) - { - // Execute OnDismissAction if defined - if (!String.IsNullOrEmpty(param.DismissAction)) - API.Execute(rm.GetSkin(), param.DismissAction); - break; - } - - // Continue to the next line, if there is any - } - } - break; - } - } - - #region This is all code custom to this plugin - - #region Parse the current command line - private bool ExecuteLine(string sLine, Dictionary Options, Dictionary Overrides) - { - // If this line contains a $UserInput$ token, then we need to do some extra - // parsing - if (sLine.ToUpper().Contains("$USERINPUT$")) - { - try - { - // Get user input - string sInput = GetUserInput(Options, Overrides); - if (sInput == null) - { - // API.Log(API.LogType.Debug, "InputText: Aborted, user cancelled text box"); - return false; - } - - // Swap out the $UserInput$ token with what the user typed - sLine = Replace(sLine, "$USERINPUT$", sInput); - } - catch (Exception ex) - { - // If there was an error doing any of the above, log it for debugging purposes. - API.Log(API.LogType.Warning, "InputText: Exception " + ex.GetType().ToString() + ": " + ex.Message); - return false; - } - } - - // Execute the bang. This will either be the original line from CommandX= (sLine variable) or - // an adjusted line based on special parsing above. - // API.Log(API.LogType.Debug, "InputText: Executing bang: " + sLine); - API.Execute(rm.GetSkin(), sLine); - return true; - } - #endregion - #region GetUserInput() -- creates an input textbox and handles all INI and override settings - - delegate void ChangeSettingFromString(string value); - delegate void ChangeInputBoxSetting(string option, ChangeSettingFromString method); - - private InputBox _InputBox = null; - private object _InputBoxLocker = new object(); - - private string GetUserInput(Dictionary Options) - { - // No INI overrides provided, so create an empty list - return GetUserInput(Options, new Dictionary()); - } - private string GetUserInput(Dictionary Options, Dictionary Overrides) - { - InputBox input = null; - - lock (this._InputBoxLocker) - { - if (this._IsFinalizing) - return null; - - SkinWindow skin = new SkinWindow(rm); - - // Create the form. 'InputBox' is a .NET form with a textbox and two button controls on it. - this._InputBox = new InputBox(skin); - input = this._InputBox; - - input.ChangeX("0"); - input.ChangeY("0"); - - // Change the styles of the InputBox form based on overrides or INI values - #region Style and preference tweaks (INI and override settings) - - ChangeInputBoxSetting changeSetting = (opt, change) => - { - if (Overrides.ContainsKey(opt)) - change(Overrides[opt]); - else if (Options.ContainsKey(opt)) - change(Options[opt]); - }; - - changeSetting("FontFace", input.ChangeFontFace); - changeSetting("FontSize", input.ChangeFontSize); - - changeSetting("W", input.ChangeW); - changeSetting("H", input.ChangeH); - changeSetting("X", input.ChangeX); - changeSetting("Y", input.ChangeY); - - changeSetting("StringStyle", input.ChangeFontStringStyle); - changeSetting("StringAlign", input.ChangeStringAlign); - - changeSetting("FontColor", input.ChangeFontColor); - changeSetting("SolidColor", input.ChangeBackColor); - - if (Overrides.ContainsKey("FocusDismiss")) - input.MakeFocusDismiss(Overrides["FocusDismiss"] == "1"); - else if (Options.ContainsKey("FocusDismiss")) - input.MakeFocusDismiss(Options["FocusDismiss"].Trim() == "1"); - - if (Overrides.ContainsKey("Password")) - input.MakePassword(Overrides["Password"] == "1"); - else if (Options.ContainsKey("Password")) - input.MakePassword(Options["Password"].Trim() == "1"); - - string topmost = null; - if (Overrides.ContainsKey("TopMost")) - topmost = Overrides["TopMost"]; - else if (Options.ContainsKey("TopMost")) - topmost = Options["TopMost"].Trim(); - switch (topmost) - { - case "1": - input.MakeTopmost(); - break; - case "0": - break; - default: // AUTO - if (skin.IsTopmost) - input.MakeTopmost(); - break; - } - - changeSetting("DefaultValue", input.DefaultValue); - - #endregion - } - - string result = null; - - if (input.ShowInputBox()) - { - lock (this.locker) - { - this.LastInput = input.TextValue; - result = this.LastInput; - } - } - - // Dispose - input = null; - lock (this._InputBoxLocker) - { - this._InputBox.Dispose(); - this._InputBox = null; - } - return result; - } - - private void FinalizePluginCode() - { - lock (this._InputBoxLocker) - { - if (this._InputBox != null) - { - this._InputBox.Abort(); - System.Threading.Thread.Sleep(50); // Wait for closing input box - } - } - } - #endregion - - #region ReadOption(), ParseInlineOption() -- reads given option's value from Rainmeter - private void ReadOption(string optionName, Dictionary Options, bool formula = false) - { - string value = rm.ReadString(optionName, ""); - if (!string.IsNullOrEmpty(value)) - { - if (formula && value[0] == '(') - Options.Add(optionName, rm.ReadInt(optionName, 0).ToString()); - else - Options.Add(optionName, value); - } - } - private string ParseInlineOption(string data, bool formula = false) - { - IntPtr skin = rm.GetSkin(); - string keyName = "__InputText_ParseInline_TemporaryKey__"; - string bang = "!SetOption \"" + rm.GetMeasureName() + "\" " + keyName + " "; - string quote = (data.IndexOf('"') >= 0) ? "\"\"\"" : "\""; - - API.Execute(skin, bang + quote + data + quote); // set temporarily - string value = formula ? rm.ReadInt(keyName, 0).ToString() : rm.ReadString(keyName, ""); - API.Execute(skin, bang + "\"\""); // remove - - return value; - } - #endregion - - #region Replace() -- case-insensitive string replacement - private static string Replace(string sIn, string sFind, string sReplace) - { - int iReplace = sIn.ToUpper().IndexOf(sFind.ToUpper()); - - string sLineNew = string.Empty; - - if (iReplace > 0) - sLineNew += sIn.Substring(0, iReplace); - sLineNew += sReplace; - sLineNew += sIn.Substring(iReplace + sFind.Length); - - return sLineNew; - } - private static string Replace(string sIn, int iStart, int iLength, string sReplace) - { - int iReplace = iStart; - - string sLineNew = string.Empty; - - if (iReplace > 0) - sLineNew += sIn.Substring(0, iReplace); - sLineNew += sReplace; - sLineNew += sIn.Substring(iReplace + iLength); - - return sLineNew; - } - #endregion - #region TagLoc(), TagData() -- text parsing utilities for the override tags - private int TagLoc(string sLine, string sTag) - { - if (!string.IsNullOrEmpty(sLine) && !string.IsNullOrEmpty(sTag)) - { - int loc = sLine.ToUpper().IndexOf(" " + sTag.ToUpper() + "="); - if (loc >= 0) - return loc + 1; - } - return -1; - } - - private string TagData(string sLine, string sTag, int iStart) - { - if (iStart < 0) - return string.Empty; - - iStart += sTag.Length + 1; - - string sTagData = string.Empty; - bool bInQuote = false; - - try - { - - for (int i = 0; ; i++) - { - if (i == 0) - { - if (sLine[i + iStart] == '"') - { - bInQuote = true; - continue; - } - } - - if (sLine[i + iStart] == '"') - break; - - if (!bInQuote) - if (char.IsWhiteSpace(sLine[i + iStart])) - break; - - sTagData += sLine[i + iStart]; - } - } - catch { } - - if (bInQuote == true) - return "\"" + sTagData + "\""; - - return sTagData; - } - #endregion - #region ScanAndReplace() -- searches for a tag and its value, adding it to overrides if found, and then removing it from the input line - private string ScanAndReplace(string sLine, string sTagName, Dictionary Overrides, bool formula = false) - { - int loc = TagLoc(sLine, sTagName); - if (loc >= 0) - { - string sTagData = TagData(sLine, sTagName, loc); - // API.Log(API.LogType.Debug, "InputText: Overriding " + sTagName + " with " + sTagData); - - string data = (sTagData.StartsWith("\"")) ? sTagData.Substring(1, sTagData.Length - 2) : sTagData; - if (!string.IsNullOrEmpty(data)) - { - int index; - if (formula && data[0] == '(') - data = ParseInlineOption(data, true); - else if ((index = data.IndexOf('[')) >= 0 && data.IndexOf(']', index) > 0) - data = ParseInlineOption(data, false); - } - - Overrides.Add(sTagName, data); - - sLine = Replace(sLine, loc - 1, 1 + sTagName.Length + 1 + sTagData.Length, string.Empty); - } - - return sLine; - } - #endregion - - #endregion - } -} +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +using System; +using System.Collections.Generic; +using Rainmeter; + +// The bulk of your plugin's code belongs in this file. +namespace InputText +{ + internal partial class Measure + { + private bool ReadOptions(ExecuteBangParam param) + { + // Get default options + ReadOption("DefaultValue", param.Options); + ReadOption("X", param.Options, true); + ReadOption("Y", param.Options, true); + ReadOption("W", param.Options, true); + ReadOption("H", param.Options, true); + ReadOption("StringStyle", param.Options); + ReadOption("StringAlign", param.Options); + ReadOption("FocusDismiss", param.Options); + ReadOption("FontColor", param.Options); + ReadOption("FontFace", param.Options); + ReadOption("FontSize", param.Options, true); + ReadOption("SolidColor", param.Options); + ReadOption("Password", param.Options); + ReadOption("TopMost", param.Options); + + param.DismissAction = rm.ReadString("OnDismissAction", "", false); + + #region Handle a single parameter + + // If our parameter list only contains a single word, then open a textbox immediately + // and set a value. This mode does not do any batching. + if (!param.Command.Contains(" ")) + { + param.Type = ExecuteBangParam.BangType.SetVariable; + return true; + } + + #endregion + #region Handle multiple parameters + + // Our parameter list contains at least two words, so split them up + string[] sParts = param.Command.Split(new string[] { " " }, StringSplitOptions.None); + + // If the first parameter is 'ExecuteBatch' (not case sensitive)... + if (sParts[0].Trim().ToUpper() == "EXECUTEBATCH") + { + param.Type = ExecuteBangParam.BangType.ExecuteBatch; + + // ExecuteBatch tells this plugin to go through the measure's settings to look + // for lines beginning with "Command" and executing Rainmeter bangs for each one. + // If a line contains $UserInput$, then an input textbox is opened and command + // execution pauses until the user enters text or dismisses the textbox. If the + // textbox is dismissed (Escape key, for example), all processing ends, otherwise + // it continues depending on the range of commands selected. + // + // Each "Command" line allows overriding all settings that the input textbox + // supports, therefor some checking and substitution is performed, thus a + // more complex parser has been implemented. + // + // ExecuteBatch expects this syntax: + // ExecuteBatch [All|#|#-#] + // + // This allows Rainmeter to call the plugin to execute a range including: + // All All commands in the measure + // # Only a single command in the measure + // #-# A specific range of commands in the measure + + #region Determine range + // Determine range. Default is 1 to 1,000,000,000, although if processing finds + // that a requested line is blank, it will stop all processing (so 'All' will + // only parse 14 lines if "Command15" does not exist or is blank). + int iMin = 1; + int iMax = 1000000000; + try + { + if (sParts[1].Trim().ToUpper() != "ALL") + { + if (sParts[1].Contains("-")) + { + string[] sSubParts = sParts[1].Split(new string[] { "-" }, StringSplitOptions.None); + iMin = int.Parse(sSubParts[0]); + iMax = int.Parse(sSubParts[1]); + } + else + iMin = iMax = int.Parse(sParts[1]); + } + } + catch // handle all errors above + { + // Any error above will be ignored and the default range used instead. + // This can occur if the measure asks to ExecuteBatch an invalid range + // or the range could not be translated to an acceptable format. + // + // For example: ExecuteBatch asdf + iMin = 1; + iMax = 1000000000; + } + #endregion + #region Parse commands in range + // Parse each command in the range, aborting if any line returns 'false' or + // the requested command line does not exist in the config for that measure. + for (int i = iMin; i <= iMax; i++) + { + // Read this command's line + string sLine = rm.ReadString("Command" + i.ToString(), "", false); + + // If empty/non-existent, abort + if (string.IsNullOrEmpty(sLine)) + break; + + #region Handle in-line overrides + // Create a blank list of overrides + Dictionary Overrides = new Dictionary(); + + // Start looking for overridable settings and adjust the list accordingly, + // stripping out settings from the line if they are discovered. + // + // The supporting TagData() function allows for whitespace if quotes are + // used. For example: + // + // DefaultValue="hello there, how are you" + sLine = ScanAndReplace(sLine, "DefaultValue", Overrides); + sLine = ScanAndReplace(sLine, "X", Overrides, true); + sLine = ScanAndReplace(sLine, "Y", Overrides, true); + sLine = ScanAndReplace(sLine, "W", Overrides, true); + sLine = ScanAndReplace(sLine, "H", Overrides, true); + sLine = ScanAndReplace(sLine, "StringStyle", Overrides); + sLine = ScanAndReplace(sLine, "StringAlign", Overrides); + sLine = ScanAndReplace(sLine, "FocusDismiss", Overrides); + sLine = ScanAndReplace(sLine, "FontColor", Overrides); + sLine = ScanAndReplace(sLine, "FontFace", Overrides); + sLine = ScanAndReplace(sLine, "FontSize", Overrides, true); + sLine = ScanAndReplace(sLine, "SolidColor", Overrides); + sLine = ScanAndReplace(sLine, "Password", Overrides); + sLine = ScanAndReplace(sLine, "TopMost", Overrides); + + param.OverrideOptions.Add(Overrides); + #endregion + + param.Commands.Add(sLine); + } + #endregion + + return param.Commands.Count > 0; + } + + #endregion + + // Unhandled command, log the message but otherwise do nothing + param.Type = ExecuteBangParam.BangType.Unknown; + API.Log(API.LogType.Debug, "InputText: Received command \"" + sParts[0].Trim() + "\", left unhandled"); + + return false; + } + + private void ExecuteCommands(ExecuteBangParam param) + { + switch (param.Type) + { + case ExecuteBangParam.BangType.SetVariable: + { + // Assume that the parameter is the name of the variable + + // Ask for input + string sInput = GetUserInput(param.Options); + + // If the user cancelled out of the inputbox (ESC key, etc.), then abort + if (sInput == null) + { + // Execute OnDismissAction if defined + if (!String.IsNullOrEmpty(param.DismissAction)) + API.Execute(rm.GetSkin(), param.DismissAction); + break; + } + + // Ask Rainmeter to set the variable using a bang (http://rainmeter.net/RainCMS/?q=Bangs) + API.Execute(rm.GetSkin(), "!SetVariable " + param.Command + " \"" + sInput + "\""); + + // Note that the skin needs DynamicVariables=1 in the measure's settings or the above + // code will have no effect. + } + break; + + case ExecuteBangParam.BangType.ExecuteBatch: + { + for (int i = 0; i < param.Commands.Count; ++i) + { + // Execute the line, but if there's a problem (error or they cancel the + // input textbox), then abort + if (!ExecuteLine(param.Commands[i], param.Options, param.OverrideOptions[i])) + { + // Execute OnDismissAction if defined + if (!String.IsNullOrEmpty(param.DismissAction)) + API.Execute(rm.GetSkin(), param.DismissAction); + break; + } + + // Continue to the next line, if there is any + } + } + break; + } + } + + #region This is all code custom to this plugin + + #region Parse the current command line + private bool ExecuteLine(string sLine, Dictionary Options, Dictionary Overrides) + { + // If this line contains a $UserInput$ token, then we need to do some extra + // parsing + if (sLine.ToUpper().Contains("$USERINPUT$")) + { + try + { + // Get user input + string sInput = GetUserInput(Options, Overrides); + if (sInput == null) + { + // API.Log(API.LogType.Debug, "InputText: Aborted, user cancelled text box"); + return false; + } + + // Swap out the $UserInput$ token with what the user typed + sLine = Replace(sLine, "$USERINPUT$", sInput); + } + catch (Exception ex) + { + // If there was an error doing any of the above, log it for debugging purposes. + API.Log(API.LogType.Warning, "InputText: Exception " + ex.GetType().ToString() + ": " + ex.Message); + return false; + } + } + + // Execute the bang. This will either be the original line from CommandX= (sLine variable) or + // an adjusted line based on special parsing above. + // API.Log(API.LogType.Debug, "InputText: Executing bang: " + sLine); + API.Execute(rm.GetSkin(), sLine); + return true; + } + #endregion + #region GetUserInput() -- creates an input textbox and handles all INI and override settings + + delegate void ChangeSettingFromString(string value); + delegate void ChangeInputBoxSetting(string option, ChangeSettingFromString method); + + private InputBox _InputBox = null; + private object _InputBoxLocker = new object(); + + private string GetUserInput(Dictionary Options) + { + // No INI overrides provided, so create an empty list + return GetUserInput(Options, new Dictionary()); + } + private string GetUserInput(Dictionary Options, Dictionary Overrides) + { + InputBox input = null; + + lock (this._InputBoxLocker) + { + if (this._IsFinalizing) + return null; + + SkinWindow skin = new SkinWindow(rm); + + // Create the form. 'InputBox' is a .NET form with a textbox and two button controls on it. + this._InputBox = new InputBox(skin); + input = this._InputBox; + + input.ChangeX("0"); + input.ChangeY("0"); + + // Change the styles of the InputBox form based on overrides or INI values + #region Style and preference tweaks (INI and override settings) + + ChangeInputBoxSetting changeSetting = (opt, change) => + { + if (Overrides.ContainsKey(opt)) + change(Overrides[opt]); + else if (Options.ContainsKey(opt)) + change(Options[opt]); + }; + + changeSetting("FontFace", input.ChangeFontFace); + changeSetting("FontSize", input.ChangeFontSize); + + changeSetting("W", input.ChangeW); + changeSetting("H", input.ChangeH); + changeSetting("X", input.ChangeX); + changeSetting("Y", input.ChangeY); + + changeSetting("StringStyle", input.ChangeFontStringStyle); + changeSetting("StringAlign", input.ChangeStringAlign); + + changeSetting("FontColor", input.ChangeFontColor); + changeSetting("SolidColor", input.ChangeBackColor); + + if (Overrides.ContainsKey("FocusDismiss")) + input.MakeFocusDismiss(Overrides["FocusDismiss"] == "1"); + else if (Options.ContainsKey("FocusDismiss")) + input.MakeFocusDismiss(Options["FocusDismiss"].Trim() == "1"); + + if (Overrides.ContainsKey("Password")) + input.MakePassword(Overrides["Password"] == "1"); + else if (Options.ContainsKey("Password")) + input.MakePassword(Options["Password"].Trim() == "1"); + + string topmost = null; + if (Overrides.ContainsKey("TopMost")) + topmost = Overrides["TopMost"]; + else if (Options.ContainsKey("TopMost")) + topmost = Options["TopMost"].Trim(); + switch (topmost) + { + case "1": + input.MakeTopmost(); + break; + case "0": + break; + default: // AUTO + if (skin.IsTopmost) + input.MakeTopmost(); + break; + } + + changeSetting("DefaultValue", input.DefaultValue); + + #endregion + } + + string result = null; + + if (input.ShowInputBox()) + { + lock (this.locker) + { + this.LastInput = input.TextValue; + result = this.LastInput; + } + } + + // Dispose + input = null; + lock (this._InputBoxLocker) + { + this._InputBox.Dispose(); + this._InputBox = null; + } + return result; + } + + private void FinalizePluginCode() + { + lock (this._InputBoxLocker) + { + if (this._InputBox != null) + { + this._InputBox.Abort(); + System.Threading.Thread.Sleep(50); // Wait for closing input box + } + } + } + #endregion + + #region ReadOption(), ParseInlineOption() -- reads given option's value from Rainmeter + private void ReadOption(string optionName, Dictionary Options, bool formula = false) + { + string value = rm.ReadString(optionName, ""); + if (!string.IsNullOrEmpty(value)) + { + if (formula && value[0] == '(') + Options.Add(optionName, rm.ReadInt(optionName, 0).ToString()); + else + Options.Add(optionName, value); + } + } + private string ParseInlineOption(string data, bool formula = false) + { + IntPtr skin = rm.GetSkin(); + string keyName = "__InputText_ParseInline_TemporaryKey__"; + string bang = "!SetOption \"" + rm.GetMeasureName() + "\" " + keyName + " "; + string quote = (data.IndexOf('"') >= 0) ? "\"\"\"" : "\""; + + API.Execute(skin, bang + quote + data + quote); // set temporarily + string value = formula ? rm.ReadInt(keyName, 0).ToString() : rm.ReadString(keyName, ""); + API.Execute(skin, bang + "\"\""); // remove + + return value; + } + #endregion + + #region Replace() -- case-insensitive string replacement + private static string Replace(string sIn, string sFind, string sReplace) + { + int iReplace = sIn.ToUpper().IndexOf(sFind.ToUpper()); + + string sLineNew = string.Empty; + + if (iReplace > 0) + sLineNew += sIn.Substring(0, iReplace); + sLineNew += sReplace; + sLineNew += sIn.Substring(iReplace + sFind.Length); + + return sLineNew; + } + private static string Replace(string sIn, int iStart, int iLength, string sReplace) + { + int iReplace = iStart; + + string sLineNew = string.Empty; + + if (iReplace > 0) + sLineNew += sIn.Substring(0, iReplace); + sLineNew += sReplace; + sLineNew += sIn.Substring(iReplace + iLength); + + return sLineNew; + } + #endregion + #region TagLoc(), TagData() -- text parsing utilities for the override tags + private int TagLoc(string sLine, string sTag) + { + if (!string.IsNullOrEmpty(sLine) && !string.IsNullOrEmpty(sTag)) + { + int loc = sLine.ToUpper().IndexOf(" " + sTag.ToUpper() + "="); + if (loc >= 0) + return loc + 1; + } + return -1; + } + + private string TagData(string sLine, string sTag, int iStart) + { + if (iStart < 0) + return string.Empty; + + iStart += sTag.Length + 1; + + string sTagData = string.Empty; + bool bInQuote = false; + + try + { + + for (int i = 0; ; i++) + { + if (i == 0) + { + if (sLine[i + iStart] == '"') + { + bInQuote = true; + continue; + } + } + + if (sLine[i + iStart] == '"') + break; + + if (!bInQuote) + if (char.IsWhiteSpace(sLine[i + iStart])) + break; + + sTagData += sLine[i + iStart]; + } + } + catch { } + + if (bInQuote == true) + return "\"" + sTagData + "\""; + + return sTagData; + } + #endregion + #region ScanAndReplace() -- searches for a tag and its value, adding it to overrides if found, and then removing it from the input line + private string ScanAndReplace(string sLine, string sTagName, Dictionary Overrides, bool formula = false) + { + int loc = TagLoc(sLine, sTagName); + if (loc >= 0) + { + string sTagData = TagData(sLine, sTagName, loc); + // API.Log(API.LogType.Debug, "InputText: Overriding " + sTagName + " with " + sTagData); + + string data = (sTagData.StartsWith("\"")) ? sTagData.Substring(1, sTagData.Length - 2) : sTagData; + if (!string.IsNullOrEmpty(data)) + { + int index; + if (formula && data[0] == '(') + data = ParseInlineOption(data, true); + else if ((index = data.IndexOf('[')) >= 0 && data.IndexOf(']', index) > 0) + data = ParseInlineOption(data, false); + } + + Overrides.Add(sTagName, data); + + sLine = Replace(sLine, loc - 1, 1 + sTagName.Length + 1 + sTagData.Length, string.Empty); + } + + return sLine; + } + #endregion + + #endregion + } +} diff --git a/Plugins/PluginInputText/PluginInputText.csproj b/Plugins/PluginInputText/PluginInputText.csproj index 1b074450..d5bbe8f4 100644 --- a/Plugins/PluginInputText/PluginInputText.csproj +++ b/Plugins/PluginInputText/PluginInputText.csproj @@ -1,101 +1,101 @@ - - - - Debug - x86 - 9.0.30729 - 2.0 - {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D} - Library - Properties - Rainmeter - InputText - v2.0 - 512 - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - true - full - false - TRACE;DEBUG - prompt - 4 - 1607 - x86 - - - none - true - TRACE - prompt - 4 - 1607 - x86 - - - true - TRACE;DEBUG;X64 - full - x64 - prompt - 1607 - - - TRACE;X64 - true - none - x64 - prompt - 1607 - - - OnOutputUpdated - - - - - - - - - - - - - Form - - - InputBox.cs - - - - - - - InputBox.cs - - - - - - "$(RmOutDirRoot)Tools\DllExporter.exe" "$(ConfigurationName)" "$(PlatformName)" "$(TargetDir)\" "$(TargetFileName)" - + + + + Debug + x86 + 9.0.30729 + 2.0 + {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D} + Library + Properties + Rainmeter + InputText + v2.0 + 512 + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + full + false + TRACE;DEBUG + prompt + 4 + 1607 + x86 + + + none + true + TRACE + prompt + 4 + 1607 + x86 + + + true + TRACE;DEBUG;X64 + full + x64 + prompt + 1607 + + + TRACE;X64 + true + none + x64 + prompt + 1607 + + + OnOutputUpdated + + + + + + + + + + + + + Form + + + InputBox.cs + + + + + + + InputBox.cs + + + + + + "$(RmOutDirRoot)Tools\DllExporter.exe" "$(ConfigurationName)" "$(PlatformName)" "$(TargetDir)\" "$(TargetFileName)" + \ No newline at end of file diff --git a/Plugins/PluginInputText/Rainmeter.cs b/Plugins/PluginInputText/Rainmeter.cs index 24d55474..22b7f77f 100644 --- a/Plugins/PluginInputText/Rainmeter.cs +++ b/Plugins/PluginInputText/Rainmeter.cs @@ -1,133 +1,133 @@ -/* - Copyright (C) 2013 Rainmeter Team - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -using System; -using System.Runtime.InteropServices; -using Rainmeter; - -// This is a utility class / toolkit for communicating with Rainmeter and managing -// window positioning. -// -// You should not need to edit this code except to expand the toolkit support. -// -// Rather, most of your plugin's code should go in PluginCode.cs or additional files -// that you create (such as new forms, classes, and controls). -namespace InputText -{ - public class SkinWindow : System.Windows.Forms.IWin32Window - { - private string _SkinName; - private IntPtr _Handle; - - private int _X = 0; - private int _Y = 0; - private int _W = 0; - private int _H = 0; - - private bool _IsTopmost = false; - - public SkinWindow(Rainmeter.API rm) - { - UpdateStatus(rm); - } - - #region Methods for getting the screen-relative location of the current skin - - public IntPtr Handle - { - get { return this._Handle; } - } - - public int X - { - get { return this._X; } - } - - public int Y - { - get { return this._Y; } - } - - public int Width - { - get { return this._W; } - } - - public int Height - { - get { return this._H; } - } - - public bool IsTopmost - { - get { return this._IsTopmost; } - } - - public void UpdateStatus(Rainmeter.API rm = null) - { - if (rm != null) - { - this._SkinName = rm.GetSkinName(); - this._Handle = rm.GetSkinWindow(); - } - - RECT rct; - if (GetWindowRect(this._Handle, out rct)) - { - this._X = rct.Left; - this._Y = rct.Top; - this._W = rct.Right - rct.Left; - this._H = rct.Bottom - rct.Top; - } - else - { - API.Log(API.LogType.Error, - "Rainmeter told us the HWND for window '" + this._SkinName + "' is " + this._Handle.ToInt32().ToString() + "L, but couldn't receive a proper RECT from it"); - } - - this._IsTopmost = ((GetWindowLong(this._Handle, GWL_EXSTYLE) & WS_EX_TOPMOST) > 0); - } - - #region GetWindowRect() platform invoke to get the size/location of a window - - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect); - - [StructLayout(LayoutKind.Sequential)] - public struct RECT - { - public int Left; // x position of upper-left corner - public int Top; // y position of upper-left corner - public int Right; // x position of lower-right corner - public int Bottom; // y position of lower-right corner - } - #endregion - #region GetWindowLong() -- platform invoke to check a window's Z-order (Topmost=Auto) - - [DllImport("user32.dll")] - private static extern int GetWindowLong(IntPtr hwnd, int nIndex); - - private const int GWL_EXSTYLE = -20; - private const int WS_EX_TOPMOST = 8; - - #endregion - - #endregion - } -} +/* + Copyright (C) 2013 Rainmeter Team + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +using System; +using System.Runtime.InteropServices; +using Rainmeter; + +// This is a utility class / toolkit for communicating with Rainmeter and managing +// window positioning. +// +// You should not need to edit this code except to expand the toolkit support. +// +// Rather, most of your plugin's code should go in PluginCode.cs or additional files +// that you create (such as new forms, classes, and controls). +namespace InputText +{ + public class SkinWindow : System.Windows.Forms.IWin32Window + { + private string _SkinName; + private IntPtr _Handle; + + private int _X = 0; + private int _Y = 0; + private int _W = 0; + private int _H = 0; + + private bool _IsTopmost = false; + + public SkinWindow(Rainmeter.API rm) + { + UpdateStatus(rm); + } + + #region Methods for getting the screen-relative location of the current skin + + public IntPtr Handle + { + get { return this._Handle; } + } + + public int X + { + get { return this._X; } + } + + public int Y + { + get { return this._Y; } + } + + public int Width + { + get { return this._W; } + } + + public int Height + { + get { return this._H; } + } + + public bool IsTopmost + { + get { return this._IsTopmost; } + } + + public void UpdateStatus(Rainmeter.API rm = null) + { + if (rm != null) + { + this._SkinName = rm.GetSkinName(); + this._Handle = rm.GetSkinWindow(); + } + + RECT rct; + if (GetWindowRect(this._Handle, out rct)) + { + this._X = rct.Left; + this._Y = rct.Top; + this._W = rct.Right - rct.Left; + this._H = rct.Bottom - rct.Top; + } + else + { + API.Log(API.LogType.Error, + "Rainmeter told us the HWND for window '" + this._SkinName + "' is " + this._Handle.ToInt32().ToString() + "L, but couldn't receive a proper RECT from it"); + } + + this._IsTopmost = ((GetWindowLong(this._Handle, GWL_EXSTYLE) & WS_EX_TOPMOST) > 0); + } + + #region GetWindowRect() platform invoke to get the size/location of a window + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect); + + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public int Left; // x position of upper-left corner + public int Top; // y position of upper-left corner + public int Right; // x position of lower-right corner + public int Bottom; // y position of lower-right corner + } + #endregion + #region GetWindowLong() -- platform invoke to check a window's Z-order (Topmost=Auto) + + [DllImport("user32.dll")] + private static extern int GetWindowLong(IntPtr hwnd, int nIndex); + + private const int GWL_EXSTYLE = -20; + private const int WS_EX_TOPMOST = 8; + + #endregion + + #endregion + } +} diff --git a/Plugins/PluginMediaKey/PluginMediaKey.cpp b/Plugins/PluginMediaKey/PluginMediaKey.cpp index 8f7d5974..6e22cc24 100644 --- a/Plugins/PluginMediaKey/PluginMediaKey.cpp +++ b/Plugins/PluginMediaKey/PluginMediaKey.cpp @@ -1,72 +1,72 @@ -/* - Copyright (C) 2010 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include -#include "../../Library/Export.h" // Rainmeter's exported functions - -void SendKey(WORD key) -{ - KEYBDINPUT kbi; - kbi.wVk = key; - kbi.wScan = 0; - kbi.dwFlags = 0; - kbi.time = 0; - kbi.dwExtraInfo = (ULONG_PTR)GetMessageExtraInfo(); - - INPUT input; - input.type = INPUT_KEYBOARD; - input.ki = kbi; - - SendInput(1, &input, sizeof(INPUT)); -} - -PLUGIN_EXPORT void ExecuteBang(LPCTSTR args, UINT id) -{ - if (_wcsicmp(args, L"NextTrack") == 0) - { - SendKey(VK_MEDIA_NEXT_TRACK); - } - else if (_wcsicmp(args, L"PrevTrack") == 0) - { - SendKey(VK_MEDIA_PREV_TRACK); - } - else if (_wcsicmp(args, L"Stop") == 0) - { - SendKey(VK_MEDIA_STOP); - } - else if (_wcsicmp(args, L"PlayPause") == 0) - { - SendKey(VK_MEDIA_PLAY_PAUSE); - } - else if (_wcsicmp(args, L"VolumeMute") == 0) - { - SendKey(VK_VOLUME_MUTE); - } - else if (_wcsicmp(args, L"VolumeDown") == 0) - { - SendKey(VK_VOLUME_DOWN); - } - else if (_wcsicmp(args, L"VolumeUp") == 0) - { - SendKey(VK_VOLUME_UP); - } - else - { - RmLog(LOG_WARNING, L"MediaKey.dll: Unknown bang"); - } -} +/* + Copyright (C) 2010 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include "../../Library/Export.h" // Rainmeter's exported functions + +void SendKey(WORD key) +{ + KEYBDINPUT kbi; + kbi.wVk = key; + kbi.wScan = 0; + kbi.dwFlags = 0; + kbi.time = 0; + kbi.dwExtraInfo = (ULONG_PTR)GetMessageExtraInfo(); + + INPUT input; + input.type = INPUT_KEYBOARD; + input.ki = kbi; + + SendInput(1, &input, sizeof(INPUT)); +} + +PLUGIN_EXPORT void ExecuteBang(LPCTSTR args, UINT id) +{ + if (_wcsicmp(args, L"NextTrack") == 0) + { + SendKey(VK_MEDIA_NEXT_TRACK); + } + else if (_wcsicmp(args, L"PrevTrack") == 0) + { + SendKey(VK_MEDIA_PREV_TRACK); + } + else if (_wcsicmp(args, L"Stop") == 0) + { + SendKey(VK_MEDIA_STOP); + } + else if (_wcsicmp(args, L"PlayPause") == 0) + { + SendKey(VK_MEDIA_PLAY_PAUSE); + } + else if (_wcsicmp(args, L"VolumeMute") == 0) + { + SendKey(VK_VOLUME_MUTE); + } + else if (_wcsicmp(args, L"VolumeDown") == 0) + { + SendKey(VK_VOLUME_DOWN); + } + else if (_wcsicmp(args, L"VolumeUp") == 0) + { + SendKey(VK_VOLUME_UP); + } + else + { + RmLog(LOG_WARNING, L"MediaKey.dll: Unknown bang"); + } +} diff --git a/Plugins/PluginMediaKey/PluginMediaKey.rc b/Plugins/PluginMediaKey/PluginMediaKey.rc index aa1db293..24e4ac4b 100644 --- a/Plugins/PluginMediaKey/PluginMediaKey.rc +++ b/Plugins/PluginMediaKey/PluginMediaKey.rc @@ -1,40 +1,40 @@ -#include -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.0.0.0" - VALUE "LegalCopyright", " 2010 - Birunthan Mohanathas" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } +#include +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.0.0.0" + VALUE "LegalCopyright", " 2010 - Birunthan Mohanathas" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } } \ No newline at end of file diff --git a/Plugins/PluginMediaKey/PluginMediaKey.vcxproj b/Plugins/PluginMediaKey/PluginMediaKey.vcxproj index 3c6c6b53..f6f6b4c5 100644 --- a/Plugins/PluginMediaKey/PluginMediaKey.vcxproj +++ b/Plugins/PluginMediaKey/PluginMediaKey.vcxproj @@ -1,35 +1,35 @@ - - - - - {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4} - DynamicLibrary - MediaKey - - - - - - - - - - - - - - _USRDLL;%(PreprocessorDefinitions) - - - - - - - - - - - - - + + + + + {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4} + DynamicLibrary + MediaKey + + + + + + + + + + + + + + _USRDLL;%(PreprocessorDefinitions) + + + + + + + + + + + + + \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/Cover.cpp b/Plugins/PluginNowPlaying/Cover.cpp index a6038d6e..ae97dcff 100644 --- a/Plugins/PluginNowPlaying/Cover.cpp +++ b/Plugins/PluginNowPlaying/Cover.cpp @@ -1,228 +1,228 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Cover.h" - -namespace { - -bool WriteCoverToFile(const TagLib::ByteVector& data, const std::wstring& target) -{ - FILE* f = _wfopen(target.c_str(), L"wb"); - if (f) - { - const bool written = fwrite(data.data(), 1, data.size(), f) == data.size(); - fclose(f); - return written; - } - - return false; -} - -bool ExtractAPE(TagLib::APE::Tag* tag, const std::wstring& target) -{ - const TagLib::APE::ItemListMap& listMap = tag->itemListMap(); - if (listMap.contains("COVER ART (FRONT)")) - { - const TagLib::ByteVector nullStringTerminator(1, 0); - TagLib::ByteVector item = listMap["COVER ART (FRONT)"].value(); - const int pos = item.find(nullStringTerminator); // Skip the filename. - if (pos != -1) - { - const TagLib::ByteVector& pic = item.mid(pos + 1); - return WriteCoverToFile(pic, target); - } - } - - return false; -} - -bool ExtractID3(TagLib::ID3v2::Tag* tag, const std::wstring& target) -{ - const TagLib::ID3v2::FrameList& frameList = tag->frameList("APIC"); - if (!frameList.isEmpty()) - { - // Just grab the first image. - const auto* frame = (TagLib::ID3v2::AttachedPictureFrame*)frameList.front(); - return WriteCoverToFile(frame->picture(), target); - } - - return false; -} - -bool ExtractASF(TagLib::ASF::File* file, const std::wstring& target) -{ - const TagLib::ASF::AttributeListMap& attrListMap = file->tag()->attributeListMap(); - if (attrListMap.contains("WM/Picture")) - { - const TagLib::ASF::AttributeList& attrList = attrListMap["WM/Picture"]; - if (!attrList.isEmpty()) - { - // Let's grab the first cover. TODO: Check/loop for correct type. - const TagLib::ASF::Picture& wmpic = attrList[0].toPicture(); - if (wmpic.isValid()) - { - return WriteCoverToFile(wmpic.picture(), target); - } - } - } - - return false; -} - -bool ExtractFLAC(TagLib::FLAC::File* file, const std::wstring& target) -{ - const TagLib::List& picList = file->pictureList(); - if (!picList.isEmpty()) - { - // Just grab the first image. - const TagLib::FLAC::Picture* pic = picList[0]; - return WriteCoverToFile(pic->data(), target); - } - - return false; -} - -bool ExtractMP4(TagLib::MP4::File* file, const std::wstring& target) -{ - TagLib::MP4::Tag* tag = file->tag(); - const TagLib::MP4::ItemListMap& itemListMap = tag->itemListMap(); - if (itemListMap.contains("covr")) - { - const TagLib::MP4::CoverArtList& coverArtList = itemListMap["covr"].toCoverArtList(); - if (!coverArtList.isEmpty()) - { - const TagLib::MP4::CoverArt* pic = &(coverArtList.front()); - return WriteCoverToFile(pic->data(), target); - } - } - - return false; -} - -} // namespace - -/* -** Checks if cover art is in cache. -** -*/ -bool CCover::GetCached(std::wstring& path) -{ - path += L".art"; - return (_waccess(path.c_str(), 0) == 0) ? true : false; -} - -/* -** Attemps to find local cover art in various formats. -** -*/ -bool CCover::GetLocal(std::wstring filename, const std::wstring& folder, std::wstring& target) -{ - std::wstring testPath = folder + filename; - testPath += L"."; - std::wstring::size_type origLen = testPath.length(); - - const int extCount = 4; - LPCTSTR extName[extCount] = { L"jpg", L"jpeg", L"png", L"bmp" }; - - for (int i = 0; i < extCount; ++i) - { - testPath += extName[i]; - if (_waccess(testPath.c_str(), 0) == 0) - { - target = testPath; - return true; - } - else - { - // Get rid of the added extension - testPath.resize(origLen); - } - } - - return false; -} - -/* -** Attempts to extract cover art from audio files. -** -*/ -bool CCover::GetEmbedded(const TagLib::FileRef& fr, const std::wstring& target) -{ - bool found = false; - - if (TagLib::MPEG::File* file = dynamic_cast(fr.file())) - { - if (file->ID3v2Tag()) - { - found = ExtractID3(file->ID3v2Tag(), target); - } - if (!found && file->APETag()) - { - found = ExtractAPE(file->APETag(), target); - } - } - else if (TagLib::FLAC::File* file = dynamic_cast(fr.file())) - { - found = ExtractFLAC(file, target); - - if (!found && file->ID3v2Tag()) - { - found = ExtractID3(file->ID3v2Tag(), target); - } - } - else if (TagLib::MP4::File* file = dynamic_cast(fr.file())) - { - found = ExtractMP4(file, target); - } - else if (TagLib::ASF::File* file = dynamic_cast(fr.file())) - { - found = ExtractASF(file, target); - } - else if (TagLib::APE::File* file = dynamic_cast(fr.file())) - { - if (file->APETag()) - { - found = ExtractAPE(file->APETag(), target); - } - } - else if (TagLib::MPC::File* file = dynamic_cast(fr.file())) - { - if (file->APETag()) - { - found = ExtractAPE(file->APETag(), target); - } - } - - return found; -} - -/* -** Returns path without filename. -** -*/ -std::wstring CCover::GetFileFolder(const std::wstring& file) -{ - std::wstring::size_type pos = file.find_last_of(L'\\'); - if (pos != std::wstring::npos) - { - return file.substr(0, ++pos); - } - - return file; -} +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Cover.h" + +namespace { + +bool WriteCoverToFile(const TagLib::ByteVector& data, const std::wstring& target) +{ + FILE* f = _wfopen(target.c_str(), L"wb"); + if (f) + { + const bool written = fwrite(data.data(), 1, data.size(), f) == data.size(); + fclose(f); + return written; + } + + return false; +} + +bool ExtractAPE(TagLib::APE::Tag* tag, const std::wstring& target) +{ + const TagLib::APE::ItemListMap& listMap = tag->itemListMap(); + if (listMap.contains("COVER ART (FRONT)")) + { + const TagLib::ByteVector nullStringTerminator(1, 0); + TagLib::ByteVector item = listMap["COVER ART (FRONT)"].value(); + const int pos = item.find(nullStringTerminator); // Skip the filename. + if (pos != -1) + { + const TagLib::ByteVector& pic = item.mid(pos + 1); + return WriteCoverToFile(pic, target); + } + } + + return false; +} + +bool ExtractID3(TagLib::ID3v2::Tag* tag, const std::wstring& target) +{ + const TagLib::ID3v2::FrameList& frameList = tag->frameList("APIC"); + if (!frameList.isEmpty()) + { + // Just grab the first image. + const auto* frame = (TagLib::ID3v2::AttachedPictureFrame*)frameList.front(); + return WriteCoverToFile(frame->picture(), target); + } + + return false; +} + +bool ExtractASF(TagLib::ASF::File* file, const std::wstring& target) +{ + const TagLib::ASF::AttributeListMap& attrListMap = file->tag()->attributeListMap(); + if (attrListMap.contains("WM/Picture")) + { + const TagLib::ASF::AttributeList& attrList = attrListMap["WM/Picture"]; + if (!attrList.isEmpty()) + { + // Let's grab the first cover. TODO: Check/loop for correct type. + const TagLib::ASF::Picture& wmpic = attrList[0].toPicture(); + if (wmpic.isValid()) + { + return WriteCoverToFile(wmpic.picture(), target); + } + } + } + + return false; +} + +bool ExtractFLAC(TagLib::FLAC::File* file, const std::wstring& target) +{ + const TagLib::List& picList = file->pictureList(); + if (!picList.isEmpty()) + { + // Just grab the first image. + const TagLib::FLAC::Picture* pic = picList[0]; + return WriteCoverToFile(pic->data(), target); + } + + return false; +} + +bool ExtractMP4(TagLib::MP4::File* file, const std::wstring& target) +{ + TagLib::MP4::Tag* tag = file->tag(); + const TagLib::MP4::ItemListMap& itemListMap = tag->itemListMap(); + if (itemListMap.contains("covr")) + { + const TagLib::MP4::CoverArtList& coverArtList = itemListMap["covr"].toCoverArtList(); + if (!coverArtList.isEmpty()) + { + const TagLib::MP4::CoverArt* pic = &(coverArtList.front()); + return WriteCoverToFile(pic->data(), target); + } + } + + return false; +} + +} // namespace + +/* +** Checks if cover art is in cache. +** +*/ +bool CCover::GetCached(std::wstring& path) +{ + path += L".art"; + return (_waccess(path.c_str(), 0) == 0) ? true : false; +} + +/* +** Attemps to find local cover art in various formats. +** +*/ +bool CCover::GetLocal(std::wstring filename, const std::wstring& folder, std::wstring& target) +{ + std::wstring testPath = folder + filename; + testPath += L"."; + std::wstring::size_type origLen = testPath.length(); + + const int extCount = 4; + LPCTSTR extName[extCount] = { L"jpg", L"jpeg", L"png", L"bmp" }; + + for (int i = 0; i < extCount; ++i) + { + testPath += extName[i]; + if (_waccess(testPath.c_str(), 0) == 0) + { + target = testPath; + return true; + } + else + { + // Get rid of the added extension + testPath.resize(origLen); + } + } + + return false; +} + +/* +** Attempts to extract cover art from audio files. +** +*/ +bool CCover::GetEmbedded(const TagLib::FileRef& fr, const std::wstring& target) +{ + bool found = false; + + if (TagLib::MPEG::File* file = dynamic_cast(fr.file())) + { + if (file->ID3v2Tag()) + { + found = ExtractID3(file->ID3v2Tag(), target); + } + if (!found && file->APETag()) + { + found = ExtractAPE(file->APETag(), target); + } + } + else if (TagLib::FLAC::File* file = dynamic_cast(fr.file())) + { + found = ExtractFLAC(file, target); + + if (!found && file->ID3v2Tag()) + { + found = ExtractID3(file->ID3v2Tag(), target); + } + } + else if (TagLib::MP4::File* file = dynamic_cast(fr.file())) + { + found = ExtractMP4(file, target); + } + else if (TagLib::ASF::File* file = dynamic_cast(fr.file())) + { + found = ExtractASF(file, target); + } + else if (TagLib::APE::File* file = dynamic_cast(fr.file())) + { + if (file->APETag()) + { + found = ExtractAPE(file->APETag(), target); + } + } + else if (TagLib::MPC::File* file = dynamic_cast(fr.file())) + { + if (file->APETag()) + { + found = ExtractAPE(file->APETag(), target); + } + } + + return found; +} + +/* +** Returns path without filename. +** +*/ +std::wstring CCover::GetFileFolder(const std::wstring& file) +{ + std::wstring::size_type pos = file.find_last_of(L'\\'); + if (pos != std::wstring::npos) + { + return file.substr(0, ++pos); + } + + return file; +} diff --git a/Plugins/PluginNowPlaying/Cover.h b/Plugins/PluginNowPlaying/Cover.h index 2562adff..46683f30 100644 --- a/Plugins/PluginNowPlaying/Cover.h +++ b/Plugins/PluginNowPlaying/Cover.h @@ -1,50 +1,50 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __COVER_H__ -#define __COVER_H__ - -// TagLib -#include "fileref.h" -#include "apefile.h" -#include "apetag.h" -#include "asffile.h" -#include "attachedpictureframe.h" -#include "commentsframe.h" -#include "flacfile.h" -#include "id3v1genres.h" -#include "id3v2tag.h" -#include "mpcfile.h" -#include "mpegfile.h" -#include "mp4file.h" -#include "tag.h" -#include "taglib.h" -#include "textidentificationframe.h" -#include "tstring.h" -#include "vorbisfile.h" - -class CCover -{ -public: - static bool GetCached(std::wstring& path); - static bool GetLocal(std::wstring filename, const std::wstring& folder, std::wstring& target); - static bool GetEmbedded(const TagLib::FileRef& fr, const std::wstring& target); - static std::wstring GetFileFolder(const std::wstring& file); -}; - +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __COVER_H__ +#define __COVER_H__ + +// TagLib +#include "fileref.h" +#include "apefile.h" +#include "apetag.h" +#include "asffile.h" +#include "attachedpictureframe.h" +#include "commentsframe.h" +#include "flacfile.h" +#include "id3v1genres.h" +#include "id3v2tag.h" +#include "mpcfile.h" +#include "mpegfile.h" +#include "mp4file.h" +#include "tag.h" +#include "taglib.h" +#include "textidentificationframe.h" +#include "tstring.h" +#include "vorbisfile.h" + +class CCover +{ +public: + static bool GetCached(std::wstring& path); + static bool GetLocal(std::wstring filename, const std::wstring& folder, std::wstring& target); + static bool GetEmbedded(const TagLib::FileRef& fr, const std::wstring& target); + static std::wstring GetFileFolder(const std::wstring& file); +}; + #endif \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/Internet.cpp b/Plugins/PluginNowPlaying/Internet.cpp index 994c49c2..fa7ca1cb 100644 --- a/Plugins/PluginNowPlaying/Internet.cpp +++ b/Plugins/PluginNowPlaying/Internet.cpp @@ -1,265 +1,265 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Internet.h" - -HINTERNET Internet::c_NetHandle = nullptr; - -/* -** Initialize internet handle and crtical section. -** -*/ -void Internet::Initialize() -{ - c_NetHandle = InternetOpen(L"Rainmeter NowPlaying.dll", - INTERNET_OPEN_TYPE_PRECONFIG, - nullptr, - nullptr, - 0); - - if (!c_NetHandle) - { - RmLog(LOG_ERROR, L"NowPlaying.dll: Unable to open net handle"); - } -} - -/* -** Close handles and delete critical section. -** -*/ -void Internet::Finalize() -{ - if (c_NetHandle) InternetCloseHandle(c_NetHandle); -} - -/* -** Downloads given url and returns it as a string. -** -*/ -std::wstring Internet::DownloadUrl(const std::wstring& url, int codepage) -{ - // From WebParser.cpp - std::wstring result; - DWORD flags = INTERNET_FLAG_RESYNCHRONIZE; - HINTERNET hUrlDump = InternetOpenUrl(c_NetHandle, url.c_str(), nullptr, 0, flags, 0); - - if (!hUrlDump) - { - return result; - } - - // Allocate the buffer. - const int CHUNK_SIZE = 8192; - BYTE* lpData = new BYTE[CHUNK_SIZE]; - BYTE* lpOutPut; - BYTE* lpHolding = nullptr; - int nCounter = 1; - int nBufferSize; - DWORD dwDataSize = 0; - DWORD dwSize = 0; - - do - { - // Read the data. - if (!InternetReadFile(hUrlDump, (LPVOID)lpData, CHUNK_SIZE, &dwSize)) - { - break; - } - else - { - // Check if all of the data has been read. This should - // never get called on the first time through the loop. - if (dwSize == 0) - { - break; - } - - // Determine the buffer size to hold the new data and the data - // already written (if any). - nBufferSize = dwDataSize + dwSize; - - // Allocate the output buffer. - lpOutPut = new BYTE[nBufferSize + 2]; - - // Make sure the buffer is not the initial buffer. - if (lpHolding != nullptr) - { - // Copy the data in the holding buffer. - memcpy(lpOutPut, lpHolding, dwDataSize); - - // Delete the old buffer - delete [] lpHolding; - - lpHolding = lpOutPut; - lpOutPut = lpOutPut + dwDataSize; - } - else - { - lpHolding = lpOutPut; - } - - // Copy the data buffer. - memcpy(lpOutPut, lpData, dwSize); - - dwDataSize += dwSize; - - // End with double null - lpOutPut[dwSize] = 0; - lpOutPut[dwSize + 1] = 0; - - // Increment the number of buffers read. - ++nCounter; - - // Clear the buffer - memset(lpData, 0, CHUNK_SIZE); - } - } while (true); - - InternetCloseHandle(hUrlDump); - - delete [] lpData; - - if (lpHolding) - { - result = ConvertToWide((LPCSTR)lpHolding, codepage); - delete [] lpHolding; - } - - return result; -} - -/* -** Encode reserved characters. -** -*/ -std::wstring Internet::EncodeUrl(const std::wstring& url) -{ - // Based on http://www.zedwood.com/article/111/cpp-urlencode-function - const WCHAR* urlChars = L" !*'();:@&=+$,/?#[]"; - std::wstring ret; - - for (size_t i = 0, max = url.length(); i < max; ++i) - { - if (wcschr(urlChars, url[i])) - { - // If reserved character - ret.append(L"%"); - WCHAR buffer[3]; - _snwprintf_s(buffer, 3, L"%.2X", url[i]); - ret.append(buffer); - } - else - { - ret.push_back(url[i]); - } - } - return ret; -} - -/* -** Decodes numeric references. -** -*/ -void Internet::DecodeReferences(std::wstring& str) -{ - // From WebParser.cpp - std::wstring::size_type start = 0; - - while ((start = str.find(L'&', start)) != std::wstring::npos) - { - std::wstring::size_type end, pos; - - if ((end = str.find(L';', start)) == std::wstring::npos) break; - pos = start + 1; - - if (pos == end) // &; - skip - { - start = end + 1; - continue; - } - else if ((end - pos) > 10) // name (or number) is too long - { - ++start; - continue; - } - - if (str[pos] == L'#') // Numeric character reference - { - if (++pos == end) // &#; - skip - { - start = end + 1; - continue; - } - - int base; - if (str[pos] == L'x' || str[pos] == L'X') - { - if (++pos == end) // &#x; or &#X; - skip - { - start = end + 1; - continue; - } - base = 16; - } - else - { - base = 10; - } - - std::wstring num(str, pos, end - pos); - WCHAR* pch = nullptr; - errno = 0; - long ch = wcstol(num.c_str(), &pch, base); - if (pch == nullptr || *pch != L'\0' || errno == ERANGE || ch <= 0 || ch >= 0xFFFE) // invalid character - { - start = pos; - continue; - } - str.replace(start, end - start + 1, 1, (WCHAR)ch); - ++start; - } - else // Character entity reference - { - start = end + 1; - continue; - } - } -} - -/* -** Convert multibyte string to wide string. -** -*/ -std::wstring Internet::ConvertToWide(LPCSTR str, int codepage) -{ - std::wstring szWide; - - if (str && *str) - { - int strLen = (int)strlen(str); - int bufLen = MultiByteToWideChar(codepage, 0, str, strLen, nullptr, 0); - if (bufLen > 0) - { - szWide.resize(bufLen); - MultiByteToWideChar(codepage, 0, str, strLen, &szWide[0], bufLen); - } - } - - return szWide; -} +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Internet.h" + +HINTERNET Internet::c_NetHandle = nullptr; + +/* +** Initialize internet handle and crtical section. +** +*/ +void Internet::Initialize() +{ + c_NetHandle = InternetOpen(L"Rainmeter NowPlaying.dll", + INTERNET_OPEN_TYPE_PRECONFIG, + nullptr, + nullptr, + 0); + + if (!c_NetHandle) + { + RmLog(LOG_ERROR, L"NowPlaying.dll: Unable to open net handle"); + } +} + +/* +** Close handles and delete critical section. +** +*/ +void Internet::Finalize() +{ + if (c_NetHandle) InternetCloseHandle(c_NetHandle); +} + +/* +** Downloads given url and returns it as a string. +** +*/ +std::wstring Internet::DownloadUrl(const std::wstring& url, int codepage) +{ + // From WebParser.cpp + std::wstring result; + DWORD flags = INTERNET_FLAG_RESYNCHRONIZE; + HINTERNET hUrlDump = InternetOpenUrl(c_NetHandle, url.c_str(), nullptr, 0, flags, 0); + + if (!hUrlDump) + { + return result; + } + + // Allocate the buffer. + const int CHUNK_SIZE = 8192; + BYTE* lpData = new BYTE[CHUNK_SIZE]; + BYTE* lpOutPut; + BYTE* lpHolding = nullptr; + int nCounter = 1; + int nBufferSize; + DWORD dwDataSize = 0; + DWORD dwSize = 0; + + do + { + // Read the data. + if (!InternetReadFile(hUrlDump, (LPVOID)lpData, CHUNK_SIZE, &dwSize)) + { + break; + } + else + { + // Check if all of the data has been read. This should + // never get called on the first time through the loop. + if (dwSize == 0) + { + break; + } + + // Determine the buffer size to hold the new data and the data + // already written (if any). + nBufferSize = dwDataSize + dwSize; + + // Allocate the output buffer. + lpOutPut = new BYTE[nBufferSize + 2]; + + // Make sure the buffer is not the initial buffer. + if (lpHolding != nullptr) + { + // Copy the data in the holding buffer. + memcpy(lpOutPut, lpHolding, dwDataSize); + + // Delete the old buffer + delete [] lpHolding; + + lpHolding = lpOutPut; + lpOutPut = lpOutPut + dwDataSize; + } + else + { + lpHolding = lpOutPut; + } + + // Copy the data buffer. + memcpy(lpOutPut, lpData, dwSize); + + dwDataSize += dwSize; + + // End with double null + lpOutPut[dwSize] = 0; + lpOutPut[dwSize + 1] = 0; + + // Increment the number of buffers read. + ++nCounter; + + // Clear the buffer + memset(lpData, 0, CHUNK_SIZE); + } + } while (true); + + InternetCloseHandle(hUrlDump); + + delete [] lpData; + + if (lpHolding) + { + result = ConvertToWide((LPCSTR)lpHolding, codepage); + delete [] lpHolding; + } + + return result; +} + +/* +** Encode reserved characters. +** +*/ +std::wstring Internet::EncodeUrl(const std::wstring& url) +{ + // Based on http://www.zedwood.com/article/111/cpp-urlencode-function + const WCHAR* urlChars = L" !*'();:@&=+$,/?#[]"; + std::wstring ret; + + for (size_t i = 0, max = url.length(); i < max; ++i) + { + if (wcschr(urlChars, url[i])) + { + // If reserved character + ret.append(L"%"); + WCHAR buffer[3]; + _snwprintf_s(buffer, 3, L"%.2X", url[i]); + ret.append(buffer); + } + else + { + ret.push_back(url[i]); + } + } + return ret; +} + +/* +** Decodes numeric references. +** +*/ +void Internet::DecodeReferences(std::wstring& str) +{ + // From WebParser.cpp + std::wstring::size_type start = 0; + + while ((start = str.find(L'&', start)) != std::wstring::npos) + { + std::wstring::size_type end, pos; + + if ((end = str.find(L';', start)) == std::wstring::npos) break; + pos = start + 1; + + if (pos == end) // &; - skip + { + start = end + 1; + continue; + } + else if ((end - pos) > 10) // name (or number) is too long + { + ++start; + continue; + } + + if (str[pos] == L'#') // Numeric character reference + { + if (++pos == end) // &#; - skip + { + start = end + 1; + continue; + } + + int base; + if (str[pos] == L'x' || str[pos] == L'X') + { + if (++pos == end) // &#x; or &#X; - skip + { + start = end + 1; + continue; + } + base = 16; + } + else + { + base = 10; + } + + std::wstring num(str, pos, end - pos); + WCHAR* pch = nullptr; + errno = 0; + long ch = wcstol(num.c_str(), &pch, base); + if (pch == nullptr || *pch != L'\0' || errno == ERANGE || ch <= 0 || ch >= 0xFFFE) // invalid character + { + start = pos; + continue; + } + str.replace(start, end - start + 1, 1, (WCHAR)ch); + ++start; + } + else // Character entity reference + { + start = end + 1; + continue; + } + } +} + +/* +** Convert multibyte string to wide string. +** +*/ +std::wstring Internet::ConvertToWide(LPCSTR str, int codepage) +{ + std::wstring szWide; + + if (str && *str) + { + int strLen = (int)strlen(str); + int bufLen = MultiByteToWideChar(codepage, 0, str, strLen, nullptr, 0); + if (bufLen > 0) + { + szWide.resize(bufLen); + MultiByteToWideChar(codepage, 0, str, strLen, &szWide[0], bufLen); + } + } + + return szWide; +} diff --git a/Plugins/PluginNowPlaying/Internet.h b/Plugins/PluginNowPlaying/Internet.h index d54b3b60..5cee0e84 100644 --- a/Plugins/PluginNowPlaying/Internet.h +++ b/Plugins/PluginNowPlaying/Internet.h @@ -1,37 +1,37 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __INTERNET_H__ -#define __INTERNET_H__ - -class Internet -{ -public: - static void Initialize(); - static void Finalize(); - - static std::wstring DownloadUrl(const std::wstring& url, int codepage); - static std::wstring EncodeUrl(const std::wstring& url); - static void DecodeReferences(std::wstring& str); - static std::wstring ConvertToWide(LPCSTR str, int codepage); - -private: - static HINTERNET c_NetHandle; -}; - +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __INTERNET_H__ +#define __INTERNET_H__ + +class Internet +{ +public: + static void Initialize(); + static void Finalize(); + + static std::wstring DownloadUrl(const std::wstring& url, int codepage); + static std::wstring EncodeUrl(const std::wstring& url); + static void DecodeReferences(std::wstring& str); + static std::wstring ConvertToWide(LPCSTR str, int codepage); + +private: + static HINTERNET c_NetHandle; +}; + #endif \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/Lyrics.cpp b/Plugins/PluginNowPlaying/Lyrics.cpp index 74147332..5abf1ddb 100644 --- a/Plugins/PluginNowPlaying/Lyrics.cpp +++ b/Plugins/PluginNowPlaying/Lyrics.cpp @@ -1,192 +1,192 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Player.h" -#include "Internet.h" -#include "Lyrics.h" - -/* -** Download lyrics from various serivces. -** -*/ -bool Lyrics::GetFromInternet(const std::wstring& artist, const std::wstring& title, std::wstring& out) -{ - std::wstring encArtist = Internet::EncodeUrl(artist); - std::wstring encTitle = Internet::EncodeUrl(title); - - bool found = GetFromWikia(encArtist, encTitle, out) || - GetFromLYRDB(encArtist, encTitle, out) || - GetFromLetras(encArtist, encTitle, out); - - return found; -} - -/* -** Download lyrics from LyricWiki. -** -*/ -bool Lyrics::GetFromWikia(const std::wstring& artist, const std::wstring& title, std::wstring& data) -{ - bool ret = false; - - std::wstring url = L"http://lyrics.wikia.com/api.php?func=getSong&fmt=json&artist=" + artist; - url += L"&song="; - url += title; - - data = Internet::DownloadUrl(url, CP_UTF8); - if (!data.empty()) - { - // First we get the URL to the actual wiki page - std::wstring::size_type pos = data.find(L"http://"); - if (pos != std::wstring::npos) - { - data.erase(0, pos); - pos = data.find_first_of(L'\''); - url.assign(data, 0, pos); - - // Fetch the wiki page - data = Internet::DownloadUrl(url, CP_UTF8); - if (!data.empty()) - { - pos = data.find(L"'lyricbox'"); - pos = data.find(L"&#", pos); - if (pos != std::wstring::npos) - { - // Get and decode lyrics - data.erase(0, pos); - pos = data.find(L""); - if (pos != std::wstring::npos) - { - // Skip unavailable lyrics - return ret; - } - - while ((pos = data.find(L"
"), pos) != std::wstring::npos) - { - data.replace(pos, 6, L"\n"); - } - - // Get rid of all HTML tags - std::wstring::size_type len = 0; - while ((pos = data.find_first_of(L'<'), pos) != std::wstring::npos) - { - len = data.find_first_of(L'>', pos); - len -= pos; - data.erase(pos, ++len); - } - - ret = true; - } - } - } - } - - return ret; -} - -/* -** Download lyrics from LYRDB. -** -*/ -bool Lyrics::GetFromLYRDB(const std::wstring& artist, const std::wstring& title, std::wstring& data) -{ - bool ret = false; - - std::wstring query = artist + L"|"; - query += title; - - // LYRDB doesn't like apostrophes - std::wstring::size_type pos = 0; - while ((pos = query.find(L"%27", pos)) != std::wstring::npos) - { - query.erase(pos, 3); - } - - std::wstring url = L"http://webservices.lyrdb.com/lookup.php?q=" + query; - url += L"&for=match&agent=RainmeterNowPlaying"; - - data = Internet::DownloadUrl(url, CP_ACP); - if (!data.empty()) - { - pos = data.find(L"\\"); - if (pos != std::wstring::npos) - { - // Grab the first match - url.assign(data, 0, pos); - url.insert(0, L"http://webservices.lyrdb.com/getlyr.php?q="); - - data = Internet::DownloadUrl(url, CP_ACP); - if (!data.empty()) - { - ret = true; - } - } - } - - return ret; -} - -/* -** Download lyrics from Letras. -** -*/ -bool Lyrics::GetFromLetras(const std::wstring& artist, const std::wstring& title, std::wstring& data) -{ - bool ret = false; - - std::wstring url = L"http://letras.terra.com.br/winamp.php?musica=" + title; - url += L"&artista="; - url += artist; - data = Internet::DownloadUrl(url, CP_ACP); - if (!data.empty()) - { - std::wstring::size_type pos = data.find(L"\"letra\""); - pos = data.find(L"

", pos); - if (pos != std::wstring::npos) - { - pos += 3; - data.erase(0, pos); - - pos = data.find(L"

"); - data.resize(pos); - - Internet::DecodeReferences(data); - - while ((pos = data.find(L"
"), pos) != std::wstring::npos) - { - data.erase(pos, 5); - } - - ret = true; - } - } - - return ret; -} +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Player.h" +#include "Internet.h" +#include "Lyrics.h" + +/* +** Download lyrics from various serivces. +** +*/ +bool Lyrics::GetFromInternet(const std::wstring& artist, const std::wstring& title, std::wstring& out) +{ + std::wstring encArtist = Internet::EncodeUrl(artist); + std::wstring encTitle = Internet::EncodeUrl(title); + + bool found = GetFromWikia(encArtist, encTitle, out) || + GetFromLYRDB(encArtist, encTitle, out) || + GetFromLetras(encArtist, encTitle, out); + + return found; +} + +/* +** Download lyrics from LyricWiki. +** +*/ +bool Lyrics::GetFromWikia(const std::wstring& artist, const std::wstring& title, std::wstring& data) +{ + bool ret = false; + + std::wstring url = L"http://lyrics.wikia.com/api.php?func=getSong&fmt=json&artist=" + artist; + url += L"&song="; + url += title; + + data = Internet::DownloadUrl(url, CP_UTF8); + if (!data.empty()) + { + // First we get the URL to the actual wiki page + std::wstring::size_type pos = data.find(L"http://"); + if (pos != std::wstring::npos) + { + data.erase(0, pos); + pos = data.find_first_of(L'\''); + url.assign(data, 0, pos); + + // Fetch the wiki page + data = Internet::DownloadUrl(url, CP_UTF8); + if (!data.empty()) + { + pos = data.find(L"'lyricbox'"); + pos = data.find(L"&#", pos); + if (pos != std::wstring::npos) + { + // Get and decode lyrics + data.erase(0, pos); + pos = data.find(L""); + if (pos != std::wstring::npos) + { + // Skip unavailable lyrics + return ret; + } + + while ((pos = data.find(L"
"), pos) != std::wstring::npos) + { + data.replace(pos, 6, L"\n"); + } + + // Get rid of all HTML tags + std::wstring::size_type len = 0; + while ((pos = data.find_first_of(L'<'), pos) != std::wstring::npos) + { + len = data.find_first_of(L'>', pos); + len -= pos; + data.erase(pos, ++len); + } + + ret = true; + } + } + } + } + + return ret; +} + +/* +** Download lyrics from LYRDB. +** +*/ +bool Lyrics::GetFromLYRDB(const std::wstring& artist, const std::wstring& title, std::wstring& data) +{ + bool ret = false; + + std::wstring query = artist + L"|"; + query += title; + + // LYRDB doesn't like apostrophes + std::wstring::size_type pos = 0; + while ((pos = query.find(L"%27", pos)) != std::wstring::npos) + { + query.erase(pos, 3); + } + + std::wstring url = L"http://webservices.lyrdb.com/lookup.php?q=" + query; + url += L"&for=match&agent=RainmeterNowPlaying"; + + data = Internet::DownloadUrl(url, CP_ACP); + if (!data.empty()) + { + pos = data.find(L"\\"); + if (pos != std::wstring::npos) + { + // Grab the first match + url.assign(data, 0, pos); + url.insert(0, L"http://webservices.lyrdb.com/getlyr.php?q="); + + data = Internet::DownloadUrl(url, CP_ACP); + if (!data.empty()) + { + ret = true; + } + } + } + + return ret; +} + +/* +** Download lyrics from Letras. +** +*/ +bool Lyrics::GetFromLetras(const std::wstring& artist, const std::wstring& title, std::wstring& data) +{ + bool ret = false; + + std::wstring url = L"http://letras.terra.com.br/winamp.php?musica=" + title; + url += L"&artista="; + url += artist; + data = Internet::DownloadUrl(url, CP_ACP); + if (!data.empty()) + { + std::wstring::size_type pos = data.find(L"\"letra\""); + pos = data.find(L"

", pos); + if (pos != std::wstring::npos) + { + pos += 3; + data.erase(0, pos); + + pos = data.find(L"

"); + data.resize(pos); + + Internet::DecodeReferences(data); + + while ((pos = data.find(L"
"), pos) != std::wstring::npos) + { + data.erase(pos, 5); + } + + ret = true; + } + } + + return ret; +} diff --git a/Plugins/PluginNowPlaying/Lyrics.h b/Plugins/PluginNowPlaying/Lyrics.h index 312bd330..934509c0 100644 --- a/Plugins/PluginNowPlaying/Lyrics.h +++ b/Plugins/PluginNowPlaying/Lyrics.h @@ -1,33 +1,33 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __LYRICS_H__ -#define __LYRICS_H__ - -class Lyrics -{ -public: - static bool GetFromInternet(const std::wstring& artist, const std::wstring& title, std::wstring& out); - -private: - static bool GetFromLetras(const std::wstring& artist, const std::wstring& title, std::wstring& data); - static bool GetFromLYRDB(const std::wstring& artist, const std::wstring& title, std::wstring& data); - static bool GetFromWikia(const std::wstring& artist, const std::wstring& title, std::wstring& data); -}; - +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __LYRICS_H__ +#define __LYRICS_H__ + +class Lyrics +{ +public: + static bool GetFromInternet(const std::wstring& artist, const std::wstring& title, std::wstring& out); + +private: + static bool GetFromLetras(const std::wstring& artist, const std::wstring& title, std::wstring& data); + static bool GetFromLYRDB(const std::wstring& artist, const std::wstring& title, std::wstring& data); + static bool GetFromWikia(const std::wstring& artist, const std::wstring& title, std::wstring& data); +}; + #endif \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/NowPlaying.cpp b/Plugins/PluginNowPlaying/NowPlaying.cpp index 4b42f902..24a214d7 100644 --- a/Plugins/PluginNowPlaying/NowPlaying.cpp +++ b/Plugins/PluginNowPlaying/NowPlaying.cpp @@ -1,617 +1,617 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "NowPlaying.h" -#include "Internet.h" -#include "PlayerAIMP.h" -#include "PlayerCAD.h" -#include "PlayerITunes.h" -#include "PlayerSpotify.h" -#include "PlayerWinamp.h" -#include "PlayerWLM.h" -#include "PlayerWMP.h" - -static std::vector g_ParentMeasures; -bool g_Initialized = false; -HINSTANCE g_Instance = nullptr; - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - switch (fdwReason) - { - case DLL_PROCESS_ATTACH: - g_Instance = hinstDLL; - - // Disable DLL_THREAD_ATTACH and DLL_THREAD_DETACH notification calls - DisableThreadLibraryCalls(hinstDLL); - break; - } - - return TRUE; -} - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - Measure* measure = new Measure; - *data = measure; - - if (!g_Initialized) - { - Internet::Initialize(); - g_Initialized = true; - } -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - Measure* measure = (Measure*)data; - - // Data is stored in two structs: Measure and ParentMeasure. ParentMeasure is created for measures - // with PlayerName=someplayer. Measure is created for all measures and points to ParentMeasure as - // referenced in PlayerName=[section]. - - // Read settings from the ini-file - void* skin = RmGetSkin(rm); - LPCWSTR str = RmReadString(rm, L"PlayerName", L"", FALSE); - if (str[0] == L'[') - { - if (measure->parent) - { - // Don't let a measure measure change its parent - } - else - { - // PlayerName starts with [ so use referenced section - ++str; - size_t len = wcslen(str); - if (len > 0 && str[len - 1] == L']') - { - --len; - - std::vector::iterator iter = g_ParentMeasures.begin(); - for ( ; iter != g_ParentMeasures.end(); ++iter) - { - if (skin == (*iter)->skin && - _wcsnicmp(str, (*iter)->ownerName, len) == 0) - { - // Use same ParentMeasure as referenced section - measure->parent = (*iter); - ++measure->parent->measureCount; - - break; - } - } - - if (!measure->parent) - { - // The referenced section doesn't exist - std::wstring error = L"NowPlaying.dll: Invalid PlayerName="; - error.append(str - 1, len + 2); - error += L" in ["; - error += RmGetMeasureName(rm); - error += L"]"; - RmLog(LOG_WARNING, error.c_str()); - return; - } - } - } - } - else - { - // ParentMeasure is created when PlayerName is an actual player (and not a reference) - ParentMeasure* parent = measure->parent; - Player* oldPlayer = nullptr; - if (parent) - { - if (parent->data != data) - { - // Don't let a measure-only measure become a parent measure - return; - } - - oldPlayer = parent->player; - } - else - { - parent = new ParentMeasure; - g_ParentMeasures.push_back(parent); - parent->data = data; - parent->skin = skin; - parent->ownerName = RmGetMeasureName(rm); - measure->parent = parent; - } - - if (_wcsicmp(L"AIMP", str) == 0) - { - parent->player = PlayerAIMP::Create(); - } - else if (_wcsicmp(L"CAD", str) == 0) - { - parent->player = PlayerCAD::Create(); - } - else if (_wcsicmp(L"foobar2000", str) == 0) - { - HWND fooWindow = FindWindow(L"foo_rainmeter_class", nullptr); - if (fooWindow) - { - const WCHAR* error = L"Your foobar2000 plugin is out of date.\n\nDo you want to update the plugin now?"; - if (MessageBox(nullptr, error, L"Rainmeter", MB_YESNO | MB_ICONINFORMATION | MB_TOPMOST) == IDYES) - { - ShellExecute(nullptr, L"open", L"http://github.com/poiru/foo-cad#readme", nullptr, nullptr, SW_SHOWNORMAL); - } - } - - parent->player = PlayerCAD::Create(); - } - else if (_wcsicmp(L"iTunes", str) == 0) - { - parent->player = PlayerITunes::Create(); - } - else if (_wcsicmp(L"MediaMonkey", str) == 0) - { - parent->player = PlayerWinamp::Create(WA_MEDIAMONKEY); - } - else if (_wcsicmp(L"Spotify", str) == 0) - { - parent->player = PlayerSpotify::Create(); - } - else if (_wcsicmp(L"WinAmp", str) == 0) - { - parent->player = PlayerWinamp::Create(WA_WINAMP); - } - else if (_wcsicmp(L"WMP", str) == 0) - { - parent->player = PlayerWMP::Create(); - } - else - { - // Default to WLM - parent->player = PlayerWLM::Create(); - - if (_wcsicmp(L"WLM", str) != 0) - { - std::wstring error = L"NowPlaying.dll: Invalid PlayerName="; - error += str; - error += L" in ["; - error += parent->ownerName; - error += L"]"; - RmLog(LOG_ERROR, error.c_str()); - } - } - - parent->player->AddInstance(); - parent->playerPath = RmReadString(rm, L"PlayerPath", L""); - parent->trackChangeAction = RmReadString(rm, L"TrackChangeAction", L"", FALSE); - parent->disableLeadingZero = RmReadInt(rm, L"DisableLeadingZero", 0) != 0; - - if (oldPlayer) - { - parent->player->SetMeasures(oldPlayer->GetMeasures()); - - // Remove instance here so that player doesn't have to reinitialize if PlayerName was - // not changed. - oldPlayer->RemoveInstance(); - } - } - - str = RmReadString(rm, L"PlayerType", L""); - if (_wcsicmp(L"ARTIST", str) == 0) - { - measure->type = MEASURE_ARTIST; - } - else if (_wcsicmp(L"TITLE", str) == 0) - { - measure->type = MEASURE_TITLE; - } - else if (_wcsicmp(L"ALBUM", str) == 0) - { - measure->type = MEASURE_ALBUM; - } - else if (_wcsicmp(L"COVER", str) == 0) - { - measure->type = MEASURE_COVER; - } - else if (_wcsicmp(L"DURATION", str) == 0) - { - measure->type = MEASURE_DURATION; - } - else if (_wcsicmp(L"POSITION", str) == 0) - { - measure->type = MEASURE_POSITION; - } - else if (_wcsicmp(L"PROGRESS", str) == 0) - { - measure->type = MEASURE_PROGRESS; - *maxValue = 100.0; - } - else if (_wcsicmp(L"RATING", str) == 0) - { - measure->type = MEASURE_RATING; - *maxValue = 5.0; - } - else if (_wcsicmp(L"STATE", str) == 0) - { - measure->type = MEASURE_STATE; - } - else if (_wcsicmp(L"STATUS", str) == 0) - { - measure->type = MEASURE_STATUS; - } - else if (_wcsicmp(L"VOLUME", str) == 0) - { - measure->type = MEASURE_VOLUME; - *maxValue = 100.0; - } - else if (_wcsicmp(L"SHUFFLE", str) == 0) - { - measure->type = MEASURE_SHUFFLE; - } - else if (_wcsicmp(L"REPEAT", str) == 0) - { - measure->type = MEASURE_REPEAT; - } - else if (_wcsicmp(L"LYRICS", str) == 0) - { - RmLog(LOG_WARNING, L"NowPlaying.dll: Using undocumented PlayerType=LYRICS!"); - measure->type = MEASURE_LYRICS; - } - else if (_wcsicmp(L"FILE", str) == 0) - { - measure->type = MEASURE_FILE; - } - else if (_wcsicmp(L"NUMBER", str) == 0) - { - measure->type = MEASURE_NUMBER; - } - else if (_wcsicmp(L"YEAR", str) == 0) - { - measure->type = MEASURE_YEAR; - } - else - { - std::wstring error = L"NowPlaying.dll: Invalid PlayerType="; - error += str; - error += L" in ["; - error += RmGetMeasureName(rm); - error += L"]"; - RmLog(LOG_WARNING, error.c_str()); - } - - measure->parent->player->AddMeasure(measure->type); -} - -PLUGIN_EXPORT double Update(void* data) -{ - Measure* measure = (Measure*)data; - ParentMeasure* parent = measure->parent; - if (!parent) return 0.0; - - Player* player = parent->player; - - // Only allow parent measure to update - if (parent->data == data) - { - player->UpdateMeasure(); - - // Execute TrackChangeAction= if necessary - if (!parent->trackChangeAction.empty() && - parent->trackCount != player->GetTrackCount()) - { - RmExecute(parent->skin, parent->trackChangeAction.c_str()); - parent->trackCount = player->GetTrackCount(); - } - } - - switch (measure->type) - { - case MEASURE_DURATION: - return player->GetDuration(); - - case MEASURE_POSITION: - return player->GetPosition(); - - case MEASURE_PROGRESS: - if (player->GetDuration()) - { - return (player->GetPosition() * 100) / player->GetDuration(); - } - return 0.0; - - case MEASURE_RATING: - return player->GetRating(); - - case MEASURE_VOLUME: - return player->GetVolume(); - - case MEASURE_STATE: - return player->GetState(); - - case MEASURE_STATUS: - return player->IsInitialized(); - - case MEASURE_SHUFFLE: - return player->GetShuffle(); - - case MEASURE_REPEAT: - return player->GetRepeat(); - - case MEASURE_NUMBER: - return player->GetNumber(); - - case MEASURE_YEAR: - return player->GetYear(); - } - - return 0.0; -} - -PLUGIN_EXPORT LPCWSTR GetString(void* data) -{ - Measure* measure = (Measure*)data; - ParentMeasure* parent = measure->parent; - if (!parent) return nullptr; - - const Player* player = parent->player; - static WCHAR buffer[32]; - - switch (measure->type) - { - case MEASURE_ARTIST: - return player->GetArtist(); - - case MEASURE_TITLE: - return player->GetTitle(); - - case MEASURE_ALBUM: - return player->GetAlbum(); - - case MEASURE_LYRICS: - return player->GetLyrics(); - - case MEASURE_COVER: - return player->GetCoverPath(); - - case MEASURE_FILE: - return player->GetFilePath(); - - case MEASURE_DURATION: - SecondsToTime(player->GetDuration(), parent->disableLeadingZero, buffer); - return buffer; - - case MEASURE_POSITION: - SecondsToTime(player->GetPosition(), parent->disableLeadingZero, buffer); - return buffer; - - case MEASURE_PROGRESS: - _itow_s(player->GetDuration() ? ((player->GetPosition() * 100) / player->GetDuration()) : 0, buffer, 10); - return buffer; - - case MEASURE_RATING: - _itow_s(player->GetRating(), buffer, 10); - return buffer; - - case MEASURE_VOLUME: - _itow_s(player->GetVolume(), buffer, 10); - return buffer; - - case MEASURE_STATE: - _itow_s(player->GetState(), buffer, 10); - return buffer; - - case MEASURE_STATUS: - _itow_s((int)player->IsInitialized(), buffer, 10); - return buffer; - - case MEASURE_SHUFFLE: - _itow_s((int)player->GetShuffle(), buffer, 10); - return buffer; - - case MEASURE_REPEAT: - _itow_s((int)player->GetRepeat(), buffer, 10); - return buffer; - - case MEASURE_NUMBER: - _itow_s(player->GetNumber(), buffer, 10); - return buffer; - - case MEASURE_YEAR: - _itow_s(player->GetYear(), buffer, 10); - return buffer; - } - - return nullptr; -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - Measure* measure = (Measure*)data; - ParentMeasure* parent = measure->parent; - if (parent) - { - Player* player = parent->player; - if (--parent->measureCount == 0) - { - player->RemoveInstance(); - delete parent; - - std::vector::iterator iter = std::find(g_ParentMeasures.begin(), g_ParentMeasures.end(), parent); - g_ParentMeasures.erase(iter); - - if (g_ParentMeasures.empty()) - { - Internet::Finalize(); - } - } - } - - delete measure; -} - -PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) -{ - Measure* measure = (Measure*)data; - ParentMeasure* parent = measure->parent; - if (!parent) return; - - Player* player = parent->player; - - if (!player->IsInitialized()) - { - if (_wcsicmp(args, L"OpenPlayer") == 0 || _wcsicmp(args, L"TogglePlayer") == 0) - { - player->OpenPlayer(parent->playerPath); - } - } - else if (_wcsicmp(args, L"Pause") == 0) - { - player->Pause(); - } - else if (_wcsicmp(args, L"Play") == 0) - { - player->Play(); - } - else if (_wcsicmp(args, L"PlayPause") == 0) - { - (player->GetState() != STATE_PLAYING) ? player->Play() : player->Pause(); - } - else if (_wcsicmp(args, L"Next") == 0) - { - player->Next(); - } - else if (_wcsicmp(args, L"Previous") == 0) - { - player->Previous(); - } - else if (_wcsicmp(args, L"Stop") == 0) - { - player->Stop(); - } - else if (_wcsicmp(args, L"OpenPlayer") == 0) - { - player->OpenPlayer(parent->playerPath); - } - else if (_wcsicmp(args, L"ClosePlayer") == 0 || _wcsicmp(args, L"TogglePlayer") == 0) - { - player->ClosePlayer(); - } - else - { - LPCWSTR arg = wcschr(args, L' '); - - if (arg) - { - ++arg; // Skip the space - - if (_wcsnicmp(args, L"SetPosition", 11) == 0) - { - int position = (_wtoi(arg) * (int)player->GetDuration()) / 100; - if (arg[0] == L'+' || arg[0] == L'-') - { - position += player->GetPosition(); - } - - player->SetPosition(position); - } - else if (_wcsnicmp(args, L"SetRating", 9) == 0) - { - int rating = _wtoi(arg); - if (rating >= 0 && rating <= 5) - { - player->SetRating(rating); - } - } - else if (_wcsnicmp(args, L"SetVolume", 9) == 0) - { - int volume = _wtoi(arg); - if (arg[0] == L'+' || arg[0] == L'-') - { - // Relative to current volume - volume += player->GetVolume(); - } - - if (volume < 0) - { - volume = 0; - } - else if (volume > 100) - { - volume = 100; - } - player->SetVolume(volume);; - } - else if (_wcsnicmp(args, L"SetShuffle", 9) == 0) - { - int state = _wtoi(arg); - if (state == -1) - { - player->SetShuffle(!player->GetShuffle()); - } - else if (state == 0 || state == 1) - { - player->SetShuffle(state != 0); - } - } - else if (_wcsnicmp(args, L"SetRepeat", 9) == 0) - { - int state = _wtoi(arg); - if (state == -1) - { - player->SetRepeat(!player->GetRepeat()); - } - else if (state == 0 || state == 1) - { - player->SetRepeat(state != 0); - } - } - else - { - RmLog(LOG_WARNING, L"NowPlaying.dll: Unknown args"); - } - } - else - { - RmLog(LOG_WARNING, L"NowPlaying.dll: Unknown args"); - } - } -} - -void SecondsToTime(UINT seconds, bool leadingZero, WCHAR* buffer) -{ - int hours = seconds; - int mins = seconds; - hours /= 3600; - mins %= 3600; - int secs = mins; - mins /= 60; - secs %= 60; - - if (seconds < 0) - { - hours = mins = secs = 0; - } - - if (hours) - { - _snwprintf_s(buffer, 32, _TRUNCATE, leadingZero ? L"%i:%02i:%02i" : L"%02i:%02i:%02i", hours, mins, secs); - } - else - { - _snwprintf_s(buffer, 32, _TRUNCATE, leadingZero ? L"%i:%02i" : L"%02i:%02i", mins, secs); - } -} +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "NowPlaying.h" +#include "Internet.h" +#include "PlayerAIMP.h" +#include "PlayerCAD.h" +#include "PlayerITunes.h" +#include "PlayerSpotify.h" +#include "PlayerWinamp.h" +#include "PlayerWLM.h" +#include "PlayerWMP.h" + +static std::vector g_ParentMeasures; +bool g_Initialized = false; +HINSTANCE g_Instance = nullptr; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + g_Instance = hinstDLL; + + // Disable DLL_THREAD_ATTACH and DLL_THREAD_DETACH notification calls + DisableThreadLibraryCalls(hinstDLL); + break; + } + + return TRUE; +} + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + Measure* measure = new Measure; + *data = measure; + + if (!g_Initialized) + { + Internet::Initialize(); + g_Initialized = true; + } +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + Measure* measure = (Measure*)data; + + // Data is stored in two structs: Measure and ParentMeasure. ParentMeasure is created for measures + // with PlayerName=someplayer. Measure is created for all measures and points to ParentMeasure as + // referenced in PlayerName=[section]. + + // Read settings from the ini-file + void* skin = RmGetSkin(rm); + LPCWSTR str = RmReadString(rm, L"PlayerName", L"", FALSE); + if (str[0] == L'[') + { + if (measure->parent) + { + // Don't let a measure measure change its parent + } + else + { + // PlayerName starts with [ so use referenced section + ++str; + size_t len = wcslen(str); + if (len > 0 && str[len - 1] == L']') + { + --len; + + std::vector::iterator iter = g_ParentMeasures.begin(); + for ( ; iter != g_ParentMeasures.end(); ++iter) + { + if (skin == (*iter)->skin && + _wcsnicmp(str, (*iter)->ownerName, len) == 0) + { + // Use same ParentMeasure as referenced section + measure->parent = (*iter); + ++measure->parent->measureCount; + + break; + } + } + + if (!measure->parent) + { + // The referenced section doesn't exist + std::wstring error = L"NowPlaying.dll: Invalid PlayerName="; + error.append(str - 1, len + 2); + error += L" in ["; + error += RmGetMeasureName(rm); + error += L"]"; + RmLog(LOG_WARNING, error.c_str()); + return; + } + } + } + } + else + { + // ParentMeasure is created when PlayerName is an actual player (and not a reference) + ParentMeasure* parent = measure->parent; + Player* oldPlayer = nullptr; + if (parent) + { + if (parent->data != data) + { + // Don't let a measure-only measure become a parent measure + return; + } + + oldPlayer = parent->player; + } + else + { + parent = new ParentMeasure; + g_ParentMeasures.push_back(parent); + parent->data = data; + parent->skin = skin; + parent->ownerName = RmGetMeasureName(rm); + measure->parent = parent; + } + + if (_wcsicmp(L"AIMP", str) == 0) + { + parent->player = PlayerAIMP::Create(); + } + else if (_wcsicmp(L"CAD", str) == 0) + { + parent->player = PlayerCAD::Create(); + } + else if (_wcsicmp(L"foobar2000", str) == 0) + { + HWND fooWindow = FindWindow(L"foo_rainmeter_class", nullptr); + if (fooWindow) + { + const WCHAR* error = L"Your foobar2000 plugin is out of date.\n\nDo you want to update the plugin now?"; + if (MessageBox(nullptr, error, L"Rainmeter", MB_YESNO | MB_ICONINFORMATION | MB_TOPMOST) == IDYES) + { + ShellExecute(nullptr, L"open", L"http://github.com/poiru/foo-cad#readme", nullptr, nullptr, SW_SHOWNORMAL); + } + } + + parent->player = PlayerCAD::Create(); + } + else if (_wcsicmp(L"iTunes", str) == 0) + { + parent->player = PlayerITunes::Create(); + } + else if (_wcsicmp(L"MediaMonkey", str) == 0) + { + parent->player = PlayerWinamp::Create(WA_MEDIAMONKEY); + } + else if (_wcsicmp(L"Spotify", str) == 0) + { + parent->player = PlayerSpotify::Create(); + } + else if (_wcsicmp(L"WinAmp", str) == 0) + { + parent->player = PlayerWinamp::Create(WA_WINAMP); + } + else if (_wcsicmp(L"WMP", str) == 0) + { + parent->player = PlayerWMP::Create(); + } + else + { + // Default to WLM + parent->player = PlayerWLM::Create(); + + if (_wcsicmp(L"WLM", str) != 0) + { + std::wstring error = L"NowPlaying.dll: Invalid PlayerName="; + error += str; + error += L" in ["; + error += parent->ownerName; + error += L"]"; + RmLog(LOG_ERROR, error.c_str()); + } + } + + parent->player->AddInstance(); + parent->playerPath = RmReadString(rm, L"PlayerPath", L""); + parent->trackChangeAction = RmReadString(rm, L"TrackChangeAction", L"", FALSE); + parent->disableLeadingZero = RmReadInt(rm, L"DisableLeadingZero", 0) != 0; + + if (oldPlayer) + { + parent->player->SetMeasures(oldPlayer->GetMeasures()); + + // Remove instance here so that player doesn't have to reinitialize if PlayerName was + // not changed. + oldPlayer->RemoveInstance(); + } + } + + str = RmReadString(rm, L"PlayerType", L""); + if (_wcsicmp(L"ARTIST", str) == 0) + { + measure->type = MEASURE_ARTIST; + } + else if (_wcsicmp(L"TITLE", str) == 0) + { + measure->type = MEASURE_TITLE; + } + else if (_wcsicmp(L"ALBUM", str) == 0) + { + measure->type = MEASURE_ALBUM; + } + else if (_wcsicmp(L"COVER", str) == 0) + { + measure->type = MEASURE_COVER; + } + else if (_wcsicmp(L"DURATION", str) == 0) + { + measure->type = MEASURE_DURATION; + } + else if (_wcsicmp(L"POSITION", str) == 0) + { + measure->type = MEASURE_POSITION; + } + else if (_wcsicmp(L"PROGRESS", str) == 0) + { + measure->type = MEASURE_PROGRESS; + *maxValue = 100.0; + } + else if (_wcsicmp(L"RATING", str) == 0) + { + measure->type = MEASURE_RATING; + *maxValue = 5.0; + } + else if (_wcsicmp(L"STATE", str) == 0) + { + measure->type = MEASURE_STATE; + } + else if (_wcsicmp(L"STATUS", str) == 0) + { + measure->type = MEASURE_STATUS; + } + else if (_wcsicmp(L"VOLUME", str) == 0) + { + measure->type = MEASURE_VOLUME; + *maxValue = 100.0; + } + else if (_wcsicmp(L"SHUFFLE", str) == 0) + { + measure->type = MEASURE_SHUFFLE; + } + else if (_wcsicmp(L"REPEAT", str) == 0) + { + measure->type = MEASURE_REPEAT; + } + else if (_wcsicmp(L"LYRICS", str) == 0) + { + RmLog(LOG_WARNING, L"NowPlaying.dll: Using undocumented PlayerType=LYRICS!"); + measure->type = MEASURE_LYRICS; + } + else if (_wcsicmp(L"FILE", str) == 0) + { + measure->type = MEASURE_FILE; + } + else if (_wcsicmp(L"NUMBER", str) == 0) + { + measure->type = MEASURE_NUMBER; + } + else if (_wcsicmp(L"YEAR", str) == 0) + { + measure->type = MEASURE_YEAR; + } + else + { + std::wstring error = L"NowPlaying.dll: Invalid PlayerType="; + error += str; + error += L" in ["; + error += RmGetMeasureName(rm); + error += L"]"; + RmLog(LOG_WARNING, error.c_str()); + } + + measure->parent->player->AddMeasure(measure->type); +} + +PLUGIN_EXPORT double Update(void* data) +{ + Measure* measure = (Measure*)data; + ParentMeasure* parent = measure->parent; + if (!parent) return 0.0; + + Player* player = parent->player; + + // Only allow parent measure to update + if (parent->data == data) + { + player->UpdateMeasure(); + + // Execute TrackChangeAction= if necessary + if (!parent->trackChangeAction.empty() && + parent->trackCount != player->GetTrackCount()) + { + RmExecute(parent->skin, parent->trackChangeAction.c_str()); + parent->trackCount = player->GetTrackCount(); + } + } + + switch (measure->type) + { + case MEASURE_DURATION: + return player->GetDuration(); + + case MEASURE_POSITION: + return player->GetPosition(); + + case MEASURE_PROGRESS: + if (player->GetDuration()) + { + return (player->GetPosition() * 100) / player->GetDuration(); + } + return 0.0; + + case MEASURE_RATING: + return player->GetRating(); + + case MEASURE_VOLUME: + return player->GetVolume(); + + case MEASURE_STATE: + return player->GetState(); + + case MEASURE_STATUS: + return player->IsInitialized(); + + case MEASURE_SHUFFLE: + return player->GetShuffle(); + + case MEASURE_REPEAT: + return player->GetRepeat(); + + case MEASURE_NUMBER: + return player->GetNumber(); + + case MEASURE_YEAR: + return player->GetYear(); + } + + return 0.0; +} + +PLUGIN_EXPORT LPCWSTR GetString(void* data) +{ + Measure* measure = (Measure*)data; + ParentMeasure* parent = measure->parent; + if (!parent) return nullptr; + + const Player* player = parent->player; + static WCHAR buffer[32]; + + switch (measure->type) + { + case MEASURE_ARTIST: + return player->GetArtist(); + + case MEASURE_TITLE: + return player->GetTitle(); + + case MEASURE_ALBUM: + return player->GetAlbum(); + + case MEASURE_LYRICS: + return player->GetLyrics(); + + case MEASURE_COVER: + return player->GetCoverPath(); + + case MEASURE_FILE: + return player->GetFilePath(); + + case MEASURE_DURATION: + SecondsToTime(player->GetDuration(), parent->disableLeadingZero, buffer); + return buffer; + + case MEASURE_POSITION: + SecondsToTime(player->GetPosition(), parent->disableLeadingZero, buffer); + return buffer; + + case MEASURE_PROGRESS: + _itow_s(player->GetDuration() ? ((player->GetPosition() * 100) / player->GetDuration()) : 0, buffer, 10); + return buffer; + + case MEASURE_RATING: + _itow_s(player->GetRating(), buffer, 10); + return buffer; + + case MEASURE_VOLUME: + _itow_s(player->GetVolume(), buffer, 10); + return buffer; + + case MEASURE_STATE: + _itow_s(player->GetState(), buffer, 10); + return buffer; + + case MEASURE_STATUS: + _itow_s((int)player->IsInitialized(), buffer, 10); + return buffer; + + case MEASURE_SHUFFLE: + _itow_s((int)player->GetShuffle(), buffer, 10); + return buffer; + + case MEASURE_REPEAT: + _itow_s((int)player->GetRepeat(), buffer, 10); + return buffer; + + case MEASURE_NUMBER: + _itow_s(player->GetNumber(), buffer, 10); + return buffer; + + case MEASURE_YEAR: + _itow_s(player->GetYear(), buffer, 10); + return buffer; + } + + return nullptr; +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + Measure* measure = (Measure*)data; + ParentMeasure* parent = measure->parent; + if (parent) + { + Player* player = parent->player; + if (--parent->measureCount == 0) + { + player->RemoveInstance(); + delete parent; + + std::vector::iterator iter = std::find(g_ParentMeasures.begin(), g_ParentMeasures.end(), parent); + g_ParentMeasures.erase(iter); + + if (g_ParentMeasures.empty()) + { + Internet::Finalize(); + } + } + } + + delete measure; +} + +PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) +{ + Measure* measure = (Measure*)data; + ParentMeasure* parent = measure->parent; + if (!parent) return; + + Player* player = parent->player; + + if (!player->IsInitialized()) + { + if (_wcsicmp(args, L"OpenPlayer") == 0 || _wcsicmp(args, L"TogglePlayer") == 0) + { + player->OpenPlayer(parent->playerPath); + } + } + else if (_wcsicmp(args, L"Pause") == 0) + { + player->Pause(); + } + else if (_wcsicmp(args, L"Play") == 0) + { + player->Play(); + } + else if (_wcsicmp(args, L"PlayPause") == 0) + { + (player->GetState() != STATE_PLAYING) ? player->Play() : player->Pause(); + } + else if (_wcsicmp(args, L"Next") == 0) + { + player->Next(); + } + else if (_wcsicmp(args, L"Previous") == 0) + { + player->Previous(); + } + else if (_wcsicmp(args, L"Stop") == 0) + { + player->Stop(); + } + else if (_wcsicmp(args, L"OpenPlayer") == 0) + { + player->OpenPlayer(parent->playerPath); + } + else if (_wcsicmp(args, L"ClosePlayer") == 0 || _wcsicmp(args, L"TogglePlayer") == 0) + { + player->ClosePlayer(); + } + else + { + LPCWSTR arg = wcschr(args, L' '); + + if (arg) + { + ++arg; // Skip the space + + if (_wcsnicmp(args, L"SetPosition", 11) == 0) + { + int position = (_wtoi(arg) * (int)player->GetDuration()) / 100; + if (arg[0] == L'+' || arg[0] == L'-') + { + position += player->GetPosition(); + } + + player->SetPosition(position); + } + else if (_wcsnicmp(args, L"SetRating", 9) == 0) + { + int rating = _wtoi(arg); + if (rating >= 0 && rating <= 5) + { + player->SetRating(rating); + } + } + else if (_wcsnicmp(args, L"SetVolume", 9) == 0) + { + int volume = _wtoi(arg); + if (arg[0] == L'+' || arg[0] == L'-') + { + // Relative to current volume + volume += player->GetVolume(); + } + + if (volume < 0) + { + volume = 0; + } + else if (volume > 100) + { + volume = 100; + } + player->SetVolume(volume);; + } + else if (_wcsnicmp(args, L"SetShuffle", 9) == 0) + { + int state = _wtoi(arg); + if (state == -1) + { + player->SetShuffle(!player->GetShuffle()); + } + else if (state == 0 || state == 1) + { + player->SetShuffle(state != 0); + } + } + else if (_wcsnicmp(args, L"SetRepeat", 9) == 0) + { + int state = _wtoi(arg); + if (state == -1) + { + player->SetRepeat(!player->GetRepeat()); + } + else if (state == 0 || state == 1) + { + player->SetRepeat(state != 0); + } + } + else + { + RmLog(LOG_WARNING, L"NowPlaying.dll: Unknown args"); + } + } + else + { + RmLog(LOG_WARNING, L"NowPlaying.dll: Unknown args"); + } + } +} + +void SecondsToTime(UINT seconds, bool leadingZero, WCHAR* buffer) +{ + int hours = seconds; + int mins = seconds; + hours /= 3600; + mins %= 3600; + int secs = mins; + mins /= 60; + secs %= 60; + + if (seconds < 0) + { + hours = mins = secs = 0; + } + + if (hours) + { + _snwprintf_s(buffer, 32, _TRUNCATE, leadingZero ? L"%i:%02i:%02i" : L"%02i:%02i:%02i", hours, mins, secs); + } + else + { + _snwprintf_s(buffer, 32, _TRUNCATE, leadingZero ? L"%i:%02i" : L"%02i:%02i", mins, secs); + } +} diff --git a/Plugins/PluginNowPlaying/NowPlaying.h b/Plugins/PluginNowPlaying/NowPlaying.h index 1321ea1a..c634dc0f 100644 --- a/Plugins/PluginNowPlaying/NowPlaying.h +++ b/Plugins/PluginNowPlaying/NowPlaying.h @@ -1,60 +1,60 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __NOWPLAYING_H__ -#define __NOWPLAYING_H__ - -#include "Player.h" - -struct ParentMeasure -{ - ParentMeasure() : - player(), - data(), - skin(), - ownerName(), - measureCount(1), - trackCount(0), - disableLeadingZero(false) - {} - - Player* player; - void* data; - void* skin; - LPCWSTR ownerName; - std::wstring trackChangeAction; - std::wstring playerPath; - UINT measureCount; - UINT trackCount; - bool disableLeadingZero; -}; - -struct Measure -{ - Measure() : - parent(), - type(MEASURE_NONE) - {} - - ParentMeasure* parent; - MeasureType type; -}; - -void SecondsToTime(UINT seconds, bool leadingZero, WCHAR* buffer); - -#endif +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __NOWPLAYING_H__ +#define __NOWPLAYING_H__ + +#include "Player.h" + +struct ParentMeasure +{ + ParentMeasure() : + player(), + data(), + skin(), + ownerName(), + measureCount(1), + trackCount(0), + disableLeadingZero(false) + {} + + Player* player; + void* data; + void* skin; + LPCWSTR ownerName; + std::wstring trackChangeAction; + std::wstring playerPath; + UINT measureCount; + UINT trackCount; + bool disableLeadingZero; +}; + +struct Measure +{ + Measure() : + parent(), + type(MEASURE_NONE) + {} + + ParentMeasure* parent; + MeasureType type; +}; + +void SecondsToTime(UINT seconds, bool leadingZero, WCHAR* buffer); + +#endif diff --git a/Plugins/PluginNowPlaying/Player.cpp b/Plugins/PluginNowPlaying/Player.cpp index bfcddbda..abeff368 100644 --- a/Plugins/PluginNowPlaying/Player.cpp +++ b/Plugins/PluginNowPlaying/Player.cpp @@ -1,218 +1,218 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "Player.h" - -/* -** Constructor. -** -*/ -Player::Player() : - m_Initialized(false), - m_InstanceCount(), - m_UpdateCount(), - m_TrackCount(), - m_Measures(), - m_State(), - m_Number(), - m_Year(), - m_Shuffle(false), - m_Repeat(false), - m_Duration(), - m_Position(), - m_Rating(), - m_Volume(), - m_InternetThread() -{ - // Get temporary file for cover art - WCHAR buffer[MAX_PATH]; - GetTempPath(MAX_PATH, buffer); - GetTempFileName(buffer, L"jpg", 0, buffer); - m_TempCoverPath = buffer; -} - -/* -** Destructor. -** -*/ -Player::~Player() -{ - DeleteFile(m_TempCoverPath.c_str()); - - if (m_InternetThread) - { - TerminateThread(m_InternetThread, 0); - } -} - -/* -** Called during initialization of main measure. -** -*/ -void Player::AddInstance() -{ - ++m_InstanceCount; -} - -/* -** Called during destruction of main measure. -** -*/ -void Player::RemoveInstance() -{ - m_UpdateCount = 0; - - if (--m_InstanceCount == 0) - { - delete this; - } -} - -/* -** Called during initialization of any measure. -** -*/ -void Player::AddMeasure(INT type) -{ - m_Measures |= type; -} - -/* -** Called during update of main measure. -** -*/ -void Player::UpdateMeasure() -{ - if (++m_UpdateCount == m_InstanceCount) - { - UpdateData(); - m_UpdateCount = 0; - } -} - -/* -** Default implementation for getting cover. -** -*/ -void Player::FindCover() -{ - TagLib::FileRef fr(m_FilePath.c_str(), false); - if (!fr.isNull() && CCover::GetEmbedded(fr, m_TempCoverPath)) - { - m_CoverPath = m_TempCoverPath; - } - else - { - std::wstring trackFolder = CCover::GetFileFolder(m_FilePath); - - if (!CCover::GetLocal(L"cover", trackFolder, m_CoverPath) && - !CCover::GetLocal(L"folder", trackFolder, m_CoverPath)) - { - // Nothing found - m_CoverPath.clear(); - } - } -} - -/* -** Default implementation for getting lyrics. -** -*/ -void Player::FindLyrics() -{ - if (!m_InternetThread) - { - m_Lyrics.clear(); - - unsigned int id; - HANDLE thread = (HANDLE)_beginthreadex(nullptr, 0, LyricsThreadProc, this, 0, &id); - if (thread) - { - m_InternetThread = thread; - } - else - { - RmLog(LOG_DEBUG, L"NowPlaying.dll: Failed to start lyrics thread"); - } - } -} - -/* -** Thread to download lyrics. -** -*/ -unsigned __stdcall Player::LyricsThreadProc(void* pParam) -{ - Player* player = (Player*)pParam; - - std::wstring lyrics; - bool found; - - while (true) - { - UINT beforeCount = player->GetTrackCount(); - found = Lyrics::GetFromInternet(player->m_Artist, player->m_Title, lyrics); - UINT afterCount = player->GetTrackCount(); - - if (beforeCount == afterCount) - { - // We're on the same track - break; - } - - // Track changed, try again - } - - if (found) - { - player->m_Lyrics = lyrics; - } - - CloseHandle(player->m_InternetThread); - player->m_InternetThread = nullptr; - - return 0; -} - -/* -** Clear track information. -** -*/ -void Player::ClearData(bool all) -{ - m_State = STATE_STOPPED; - m_Artist.clear(); - m_Album.clear(); - m_Title.clear(); - m_Lyrics.clear(); - m_FilePath.clear(); - m_CoverPath.clear(); - m_Duration = 0; - m_Position = 0; - m_Rating = 0; - m_Number = 0; - m_Year = 0; - - if (all) - { - m_Volume = 0; - m_Shuffle = false; - m_Repeat = false; - } -} +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "Player.h" + +/* +** Constructor. +** +*/ +Player::Player() : + m_Initialized(false), + m_InstanceCount(), + m_UpdateCount(), + m_TrackCount(), + m_Measures(), + m_State(), + m_Number(), + m_Year(), + m_Shuffle(false), + m_Repeat(false), + m_Duration(), + m_Position(), + m_Rating(), + m_Volume(), + m_InternetThread() +{ + // Get temporary file for cover art + WCHAR buffer[MAX_PATH]; + GetTempPath(MAX_PATH, buffer); + GetTempFileName(buffer, L"jpg", 0, buffer); + m_TempCoverPath = buffer; +} + +/* +** Destructor. +** +*/ +Player::~Player() +{ + DeleteFile(m_TempCoverPath.c_str()); + + if (m_InternetThread) + { + TerminateThread(m_InternetThread, 0); + } +} + +/* +** Called during initialization of main measure. +** +*/ +void Player::AddInstance() +{ + ++m_InstanceCount; +} + +/* +** Called during destruction of main measure. +** +*/ +void Player::RemoveInstance() +{ + m_UpdateCount = 0; + + if (--m_InstanceCount == 0) + { + delete this; + } +} + +/* +** Called during initialization of any measure. +** +*/ +void Player::AddMeasure(INT type) +{ + m_Measures |= type; +} + +/* +** Called during update of main measure. +** +*/ +void Player::UpdateMeasure() +{ + if (++m_UpdateCount == m_InstanceCount) + { + UpdateData(); + m_UpdateCount = 0; + } +} + +/* +** Default implementation for getting cover. +** +*/ +void Player::FindCover() +{ + TagLib::FileRef fr(m_FilePath.c_str(), false); + if (!fr.isNull() && CCover::GetEmbedded(fr, m_TempCoverPath)) + { + m_CoverPath = m_TempCoverPath; + } + else + { + std::wstring trackFolder = CCover::GetFileFolder(m_FilePath); + + if (!CCover::GetLocal(L"cover", trackFolder, m_CoverPath) && + !CCover::GetLocal(L"folder", trackFolder, m_CoverPath)) + { + // Nothing found + m_CoverPath.clear(); + } + } +} + +/* +** Default implementation for getting lyrics. +** +*/ +void Player::FindLyrics() +{ + if (!m_InternetThread) + { + m_Lyrics.clear(); + + unsigned int id; + HANDLE thread = (HANDLE)_beginthreadex(nullptr, 0, LyricsThreadProc, this, 0, &id); + if (thread) + { + m_InternetThread = thread; + } + else + { + RmLog(LOG_DEBUG, L"NowPlaying.dll: Failed to start lyrics thread"); + } + } +} + +/* +** Thread to download lyrics. +** +*/ +unsigned __stdcall Player::LyricsThreadProc(void* pParam) +{ + Player* player = (Player*)pParam; + + std::wstring lyrics; + bool found; + + while (true) + { + UINT beforeCount = player->GetTrackCount(); + found = Lyrics::GetFromInternet(player->m_Artist, player->m_Title, lyrics); + UINT afterCount = player->GetTrackCount(); + + if (beforeCount == afterCount) + { + // We're on the same track + break; + } + + // Track changed, try again + } + + if (found) + { + player->m_Lyrics = lyrics; + } + + CloseHandle(player->m_InternetThread); + player->m_InternetThread = nullptr; + + return 0; +} + +/* +** Clear track information. +** +*/ +void Player::ClearData(bool all) +{ + m_State = STATE_STOPPED; + m_Artist.clear(); + m_Album.clear(); + m_Title.clear(); + m_Lyrics.clear(); + m_FilePath.clear(); + m_CoverPath.clear(); + m_Duration = 0; + m_Position = 0; + m_Rating = 0; + m_Number = 0; + m_Year = 0; + + if (all) + { + m_Volume = 0; + m_Shuffle = false; + m_Repeat = false; + } +} diff --git a/Plugins/PluginNowPlaying/Player.h b/Plugins/PluginNowPlaying/Player.h index 1a67890e..bc975870 100644 --- a/Plugins/PluginNowPlaying/Player.h +++ b/Plugins/PluginNowPlaying/Player.h @@ -1,140 +1,140 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __PLAYER_H__ -#define __PLAYER_H__ - -#include "fileref.h" -#include "tag.h" -#include "Cover.h" -#include "Internet.h" -#include "Lyrics.h" - -enum StateType -{ - STATE_STOPPED, - STATE_PLAYING, - STATE_PAUSED -}; - -enum MeasureType -{ - MEASURE_NONE = 0x00000000, - MEASURE_ARTIST = 0x00000001, - MEASURE_TITLE = 0x00000002, - MEASURE_ALBUM = 0x00000004, - MEASURE_LYRICS = 0x00000008, - MEASURE_COVER = 0x00000010, - MEASURE_FILE = 0x00000020, - MEASURE_DURATION = 0x00000040, - MEASURE_POSITION = 0x00000080, - MEASURE_PROGRESS = 0x00000100, - MEASURE_RATING = 0x00000200, - MEASURE_VOLUME = 0x00000400, - MEASURE_STATE = 0x00000800, - MEASURE_STATUS = 0x00001000, - MEASURE_SHUFFLE = 0x00002000, - MEASURE_REPEAT = 0x00004000, - MEASURE_NUMBER = 0x00008000, - MEASURE_YEAR = 0x00010000 -}; - -class __declspec(novtable) Player -{ -public: - Player(); - virtual ~Player() = 0; - - void AddInstance(); - void RemoveInstance(); - void UpdateMeasure(); - void AddMeasure(INT type); - virtual void UpdateData() = 0; - - bool IsInitialized() const { return m_Initialized; } - UINT GetTrackCount() const { return m_TrackCount; } - - void FindCover(); - void FindLyrics(); - - virtual void Pause() {} - virtual void Play() {} - virtual void Stop() {} - virtual void Next() {} - virtual void Previous() {} - virtual void SetPosition(int position) {} // position: position in seconds - virtual void SetRating(int rating) {} // rating: 0 - 5 - virtual void SetVolume(int volume) {} // volume: 0 - 100 - virtual void SetShuffle(bool state) {} // state: off = 0, on = 1 - virtual void SetRepeat(bool state) {} // state: off = 0, on = 1 - virtual void OpenPlayer(std::wstring& path) {} - virtual void ClosePlayer() {} - - INT GetMeasures() const { return m_Measures; } - void SetMeasures(INT measures) { m_Measures = measures; } - - StateType GetState() const { return m_State; } - LPCTSTR GetArtist() const { return m_Artist.c_str(); } - LPCTSTR GetAlbum() const { return m_Album.c_str(); } - LPCTSTR GetTitle() const { return m_Title.c_str(); } - LPCTSTR GetLyrics() const { return m_Lyrics.c_str(); } - LPCTSTR GetCoverPath() const { return m_CoverPath.c_str(); } - LPCTSTR GetFilePath() const { return m_FilePath.c_str(); } - UINT GetDuration() const { return m_Duration; } - UINT GetPosition() const { return m_Position; } - UINT GetRating() const { return m_Rating; } - UINT GetVolume() const { return m_Volume; } - UINT GetNumber() const { return m_Number; } - UINT GetYear() const { return m_Year; } - bool GetShuffle() const { return m_Shuffle; } - bool GetRepeat() const { return m_Repeat; } - -protected: - void ClearData(bool all = true); - - bool m_Initialized; - UINT m_InstanceCount; - UINT m_UpdateCount; - UINT m_TrackCount; - std::wstring m_TempCoverPath; - - INT m_Measures; - - StateType m_State; - std::wstring m_Artist; - std::wstring m_Title; - std::wstring m_Album; - std::wstring m_Lyrics; - std::wstring m_CoverPath; // Path to cover art image - std::wstring m_FilePath; // Path to playing file - UINT m_Duration; // Track duration in seconds - UINT m_Position; // Current position in seconds - UINT m_Rating; // Track rating from 0 to 100 - UINT m_Volume; // Volume from 0 to 100 - UINT m_Number; - UINT m_Year; - bool m_Shuffle; - bool m_Repeat; - -private: - static unsigned __stdcall LyricsThreadProc(void* pParam); - - HANDLE m_InternetThread; -}; - +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __PLAYER_H__ +#define __PLAYER_H__ + +#include "fileref.h" +#include "tag.h" +#include "Cover.h" +#include "Internet.h" +#include "Lyrics.h" + +enum StateType +{ + STATE_STOPPED, + STATE_PLAYING, + STATE_PAUSED +}; + +enum MeasureType +{ + MEASURE_NONE = 0x00000000, + MEASURE_ARTIST = 0x00000001, + MEASURE_TITLE = 0x00000002, + MEASURE_ALBUM = 0x00000004, + MEASURE_LYRICS = 0x00000008, + MEASURE_COVER = 0x00000010, + MEASURE_FILE = 0x00000020, + MEASURE_DURATION = 0x00000040, + MEASURE_POSITION = 0x00000080, + MEASURE_PROGRESS = 0x00000100, + MEASURE_RATING = 0x00000200, + MEASURE_VOLUME = 0x00000400, + MEASURE_STATE = 0x00000800, + MEASURE_STATUS = 0x00001000, + MEASURE_SHUFFLE = 0x00002000, + MEASURE_REPEAT = 0x00004000, + MEASURE_NUMBER = 0x00008000, + MEASURE_YEAR = 0x00010000 +}; + +class __declspec(novtable) Player +{ +public: + Player(); + virtual ~Player() = 0; + + void AddInstance(); + void RemoveInstance(); + void UpdateMeasure(); + void AddMeasure(INT type); + virtual void UpdateData() = 0; + + bool IsInitialized() const { return m_Initialized; } + UINT GetTrackCount() const { return m_TrackCount; } + + void FindCover(); + void FindLyrics(); + + virtual void Pause() {} + virtual void Play() {} + virtual void Stop() {} + virtual void Next() {} + virtual void Previous() {} + virtual void SetPosition(int position) {} // position: position in seconds + virtual void SetRating(int rating) {} // rating: 0 - 5 + virtual void SetVolume(int volume) {} // volume: 0 - 100 + virtual void SetShuffle(bool state) {} // state: off = 0, on = 1 + virtual void SetRepeat(bool state) {} // state: off = 0, on = 1 + virtual void OpenPlayer(std::wstring& path) {} + virtual void ClosePlayer() {} + + INT GetMeasures() const { return m_Measures; } + void SetMeasures(INT measures) { m_Measures = measures; } + + StateType GetState() const { return m_State; } + LPCTSTR GetArtist() const { return m_Artist.c_str(); } + LPCTSTR GetAlbum() const { return m_Album.c_str(); } + LPCTSTR GetTitle() const { return m_Title.c_str(); } + LPCTSTR GetLyrics() const { return m_Lyrics.c_str(); } + LPCTSTR GetCoverPath() const { return m_CoverPath.c_str(); } + LPCTSTR GetFilePath() const { return m_FilePath.c_str(); } + UINT GetDuration() const { return m_Duration; } + UINT GetPosition() const { return m_Position; } + UINT GetRating() const { return m_Rating; } + UINT GetVolume() const { return m_Volume; } + UINT GetNumber() const { return m_Number; } + UINT GetYear() const { return m_Year; } + bool GetShuffle() const { return m_Shuffle; } + bool GetRepeat() const { return m_Repeat; } + +protected: + void ClearData(bool all = true); + + bool m_Initialized; + UINT m_InstanceCount; + UINT m_UpdateCount; + UINT m_TrackCount; + std::wstring m_TempCoverPath; + + INT m_Measures; + + StateType m_State; + std::wstring m_Artist; + std::wstring m_Title; + std::wstring m_Album; + std::wstring m_Lyrics; + std::wstring m_CoverPath; // Path to cover art image + std::wstring m_FilePath; // Path to playing file + UINT m_Duration; // Track duration in seconds + UINT m_Position; // Current position in seconds + UINT m_Rating; // Track rating from 0 to 100 + UINT m_Volume; // Volume from 0 to 100 + UINT m_Number; + UINT m_Year; + bool m_Shuffle; + bool m_Repeat; + +private: + static unsigned __stdcall LyricsThreadProc(void* pParam); + + HANDLE m_InternetThread; +}; + #endif \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/PlayerAIMP.cpp b/Plugins/PluginNowPlaying/PlayerAIMP.cpp index 34f66df8..6767bd81 100644 --- a/Plugins/PluginNowPlaying/PlayerAIMP.cpp +++ b/Plugins/PluginNowPlaying/PlayerAIMP.cpp @@ -1,363 +1,363 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "PlayerAIMP.h" -#include "AIMP/aimp2_sdk.h" -#include "Winamp/wa_ipc.h" - -Player* PlayerAIMP::c_Player = nullptr; - -/* -** Constructor. -** -*/ -PlayerAIMP::PlayerAIMP() : Player(), - m_Window(), - m_WinampWindow(), - m_LastCheckTime(0), - m_LastFileSize(0), - m_LastTitleSize(0), - m_FileMap(), - m_FileMapHandle() -{ -} - -/* -** Destructor. -** -*/ -PlayerAIMP::~PlayerAIMP() -{ - c_Player = nullptr; - if (m_FileMap) UnmapViewOfFile(m_FileMap); - if (m_FileMapHandle) CloseHandle(m_FileMapHandle); -} - -/* -** Creates a shared class object. -** -*/ -Player* PlayerAIMP::Create() -{ - if (!c_Player) - { - c_Player = new PlayerAIMP(); - } - - return c_Player; -} - -/* -** Try to find AIMP periodically. -** -*/ -bool PlayerAIMP::CheckWindow() -{ - DWORD time = GetTickCount(); - - // Try to find AIMP every 5 seconds - if (time - m_LastCheckTime > 5000) - { - m_LastCheckTime = time; - m_Window = FindWindow(L"AIMP2_RemoteInfo", L"AIMP2_RemoteInfo"); - - if (m_Window) - { - m_WinampWindow = FindWindow(L"Winamp v1.x", nullptr); - - m_FileMapHandle = OpenFileMapping(FILE_MAP_READ, FALSE, L"AIMP2_RemoteInfo"); - if (m_FileMapHandle) - { - m_FileMap = (LPVOID)MapViewOfFile(m_FileMapHandle, FILE_MAP_READ, 0, 0, 2048); - if (m_FileMap) - { - m_Initialized = true; - } - } - } - } - - return m_Initialized; -} - -/* -** Called during each update of the main measure. -** -*/ -void PlayerAIMP::UpdateData() -{ - if (!m_Initialized) - { - if (m_LastTitleSize != 0) - { - m_LastFileSize = 0; - m_LastTitleSize = 0; - } - - if (!CheckWindow()) return; - } - - // If initialized - m_State = (StateType)SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_Player); - if (m_State == STATE_STOPPED) - { - // Make sure AIMP is still active - if (!IsWindow(m_Window)) - { - m_Initialized = false; - ClearData(); - - if (m_FileMap) UnmapViewOfFile(m_FileMap); - if (m_FileMapHandle) CloseHandle(m_FileMapHandle); - } - else if (m_State != STATE_STOPPED) - { - ClearData(false); - m_LastFileSize = 0; - m_LastTitleSize = 0; - } - - // Don't continue if AIMP has quit or is stopped - return; - } - - m_Position = (UINT)SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_POS); - m_Volume = (UINT)SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_VOLUME); - - AIMP2FileInfo* info = (AIMP2FileInfo*)m_FileMap; - if (info->cbSizeOf > 0 && - info->nFileSize != m_LastFileSize || // Avoid reading the same file - info->nTitleLen != m_LastTitleSize) - { - m_LastFileSize = info->nFileSize; - m_LastTitleSize = info->nTitleLen; - - // 44 is sizeof(AIMP2FileInfo) / 2 (due to WCHAR being 16-bit). - // Written explicitly due to size differences in 32bit/64bit. - LPCTSTR stringData = (LPCTSTR)m_FileMap; - stringData += 44; - - m_Album.assign(stringData, info->nAlbumLen); - - stringData += info->nAlbumLen; - m_Artist.assign(stringData, info->nArtistLen); - - stringData += info->nArtistLen; - stringData += info->nDateLen; - std::wstring filepath(stringData, info->nFileNameLen); - - stringData += info->nFileNameLen; - stringData += info->nGenreLen; - m_Title.assign(stringData, info->nTitleLen); - - m_Duration = info->nDuration / 1000; - m_Number = (UINT)info->nTrackID; - - m_Shuffle = SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_SHUFFLE) != 0; - m_Repeat = SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_REPEAT) != 0; - - // Get rating through the AIMP Winamp API - m_Rating = (UINT)SendMessage(m_WinampWindow, WM_WA_IPC, 0, IPC_GETRATING); - - if (filepath != m_FilePath) - { - m_FilePath = filepath; - ++m_TrackCount; - - if (m_Measures & MEASURE_COVER) FindCover(); - - if (m_Measures & MEASURE_LYRICS) FindLyrics(); - } - } -} - -/* -** Handles the Pause bang. -** -*/ -void PlayerAIMP::Pause() -{ - SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_PAUSE); -} - -/* -** Handles the Play bang. -** -*/ -void PlayerAIMP::Play() -{ - SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_PLAY); -} - -/* -** Handles the Stop bang. -** -*/ -void PlayerAIMP::Stop() -{ - SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_STOP); -} - -/* -** Handles the Next bang. -** -*/ -void PlayerAIMP::Next() -{ - SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_NEXT); -} - -/* -** Handles the Previous bang. -** -*/ -void PlayerAIMP::Previous() -{ - SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_PREV); -} - -/* -** Handles the SetPosition bang. -** -*/ -void PlayerAIMP::SetPosition(int position) -{ - SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_SET, MAKELPARAM(position, AIMP_STS_POS)); -} - -/* -** Handles the SetRating bang. -** -*/ -void PlayerAIMP::SetRating(int rating) -{ - // Set rating through the AIMP Winamp API - if (m_State != STATE_STOPPED) - { - SendMessage(m_WinampWindow, WM_WA_IPC, rating, IPC_SETRATING); - m_Rating = rating; - } -} - -/* -** Handles the SetVolume bang. -** -*/ -void PlayerAIMP::SetVolume(int volume) -{ - SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_SET, MAKELPARAM(volume, AIMP_STS_VOLUME)); -} - -/* -** Handles the SetShuffle bang. -** -*/ -void PlayerAIMP::SetShuffle(bool state) -{ - m_Shuffle = state; - SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_SET, MAKELPARAM(m_Shuffle, AIMP_STS_SHUFFLE)); -} - -/* -** Handles the SetRepeat bang. -** -*/ -void PlayerAIMP::SetRepeat(bool state) -{ - m_Repeat = state; - SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_SET, MAKELPARAM(m_Repeat, AIMP_STS_REPEAT)); -} - -/* -** Handles the ClosePlayer bang. -** -*/ -void PlayerAIMP::ClosePlayer() -{ - SendMessage(m_Window, WM_CLOSE, 0, 0); -} - -/* -** Handles the OpenPlayer bang. -** -*/ -void PlayerAIMP::OpenPlayer(std::wstring& path) -{ - if (path.empty()) - { - // Check for AIMP2 first - DWORD size = 512; - WCHAR* data = new WCHAR[size]; - DWORD type = 0; - HKEY hKey; - - RegOpenKeyEx(HKEY_LOCAL_MACHINE, - L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\AIMP2", - 0, - KEY_QUERY_VALUE, - &hKey); - - if (RegQueryValueEx(hKey, - L"DisplayIcon", - nullptr, - (LPDWORD)&type, - (LPBYTE)data, - (LPDWORD)&size) == ERROR_SUCCESS) - { - if (type == REG_SZ) - { - ShellExecute(nullptr, L"open", data, nullptr, nullptr, SW_SHOW); - path = data; - } - } - else - { - // Let's try AIMP3 - RegCloseKey(hKey); - RegOpenKeyEx(HKEY_LOCAL_MACHINE, - L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\AIMP3", - 0, - KEY_QUERY_VALUE, - &hKey); - - if (RegQueryValueEx(hKey, - L"DisplayIcon", - nullptr, - (LPDWORD)&type, - (LPBYTE)data, - (LPDWORD)&size) == ERROR_SUCCESS) - { - if (type == REG_SZ) - { - path = data; - path.resize(path.find_last_of(L'\\') + 1); - path += L"AIMP3.exe"; - ShellExecute(nullptr, L"open", path.c_str(), nullptr, nullptr, SW_SHOW); - } - } - } - - delete [] data; - RegCloseKey(hKey); - } - else - { - ShellExecute(nullptr, L"open", path.c_str(), nullptr, nullptr, SW_SHOW); - } -} +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "PlayerAIMP.h" +#include "AIMP/aimp2_sdk.h" +#include "Winamp/wa_ipc.h" + +Player* PlayerAIMP::c_Player = nullptr; + +/* +** Constructor. +** +*/ +PlayerAIMP::PlayerAIMP() : Player(), + m_Window(), + m_WinampWindow(), + m_LastCheckTime(0), + m_LastFileSize(0), + m_LastTitleSize(0), + m_FileMap(), + m_FileMapHandle() +{ +} + +/* +** Destructor. +** +*/ +PlayerAIMP::~PlayerAIMP() +{ + c_Player = nullptr; + if (m_FileMap) UnmapViewOfFile(m_FileMap); + if (m_FileMapHandle) CloseHandle(m_FileMapHandle); +} + +/* +** Creates a shared class object. +** +*/ +Player* PlayerAIMP::Create() +{ + if (!c_Player) + { + c_Player = new PlayerAIMP(); + } + + return c_Player; +} + +/* +** Try to find AIMP periodically. +** +*/ +bool PlayerAIMP::CheckWindow() +{ + DWORD time = GetTickCount(); + + // Try to find AIMP every 5 seconds + if (time - m_LastCheckTime > 5000) + { + m_LastCheckTime = time; + m_Window = FindWindow(L"AIMP2_RemoteInfo", L"AIMP2_RemoteInfo"); + + if (m_Window) + { + m_WinampWindow = FindWindow(L"Winamp v1.x", nullptr); + + m_FileMapHandle = OpenFileMapping(FILE_MAP_READ, FALSE, L"AIMP2_RemoteInfo"); + if (m_FileMapHandle) + { + m_FileMap = (LPVOID)MapViewOfFile(m_FileMapHandle, FILE_MAP_READ, 0, 0, 2048); + if (m_FileMap) + { + m_Initialized = true; + } + } + } + } + + return m_Initialized; +} + +/* +** Called during each update of the main measure. +** +*/ +void PlayerAIMP::UpdateData() +{ + if (!m_Initialized) + { + if (m_LastTitleSize != 0) + { + m_LastFileSize = 0; + m_LastTitleSize = 0; + } + + if (!CheckWindow()) return; + } + + // If initialized + m_State = (StateType)SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_Player); + if (m_State == STATE_STOPPED) + { + // Make sure AIMP is still active + if (!IsWindow(m_Window)) + { + m_Initialized = false; + ClearData(); + + if (m_FileMap) UnmapViewOfFile(m_FileMap); + if (m_FileMapHandle) CloseHandle(m_FileMapHandle); + } + else if (m_State != STATE_STOPPED) + { + ClearData(false); + m_LastFileSize = 0; + m_LastTitleSize = 0; + } + + // Don't continue if AIMP has quit or is stopped + return; + } + + m_Position = (UINT)SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_POS); + m_Volume = (UINT)SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_VOLUME); + + AIMP2FileInfo* info = (AIMP2FileInfo*)m_FileMap; + if (info->cbSizeOf > 0 && + info->nFileSize != m_LastFileSize || // Avoid reading the same file + info->nTitleLen != m_LastTitleSize) + { + m_LastFileSize = info->nFileSize; + m_LastTitleSize = info->nTitleLen; + + // 44 is sizeof(AIMP2FileInfo) / 2 (due to WCHAR being 16-bit). + // Written explicitly due to size differences in 32bit/64bit. + LPCTSTR stringData = (LPCTSTR)m_FileMap; + stringData += 44; + + m_Album.assign(stringData, info->nAlbumLen); + + stringData += info->nAlbumLen; + m_Artist.assign(stringData, info->nArtistLen); + + stringData += info->nArtistLen; + stringData += info->nDateLen; + std::wstring filepath(stringData, info->nFileNameLen); + + stringData += info->nFileNameLen; + stringData += info->nGenreLen; + m_Title.assign(stringData, info->nTitleLen); + + m_Duration = info->nDuration / 1000; + m_Number = (UINT)info->nTrackID; + + m_Shuffle = SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_SHUFFLE) != 0; + m_Repeat = SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_GET, AIMP_STS_REPEAT) != 0; + + // Get rating through the AIMP Winamp API + m_Rating = (UINT)SendMessage(m_WinampWindow, WM_WA_IPC, 0, IPC_GETRATING); + + if (filepath != m_FilePath) + { + m_FilePath = filepath; + ++m_TrackCount; + + if (m_Measures & MEASURE_COVER) FindCover(); + + if (m_Measures & MEASURE_LYRICS) FindLyrics(); + } + } +} + +/* +** Handles the Pause bang. +** +*/ +void PlayerAIMP::Pause() +{ + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_PAUSE); +} + +/* +** Handles the Play bang. +** +*/ +void PlayerAIMP::Play() +{ + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_PLAY); +} + +/* +** Handles the Stop bang. +** +*/ +void PlayerAIMP::Stop() +{ + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_STOP); +} + +/* +** Handles the Next bang. +** +*/ +void PlayerAIMP::Next() +{ + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_NEXT); +} + +/* +** Handles the Previous bang. +** +*/ +void PlayerAIMP::Previous() +{ + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_PREV); +} + +/* +** Handles the SetPosition bang. +** +*/ +void PlayerAIMP::SetPosition(int position) +{ + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_SET, MAKELPARAM(position, AIMP_STS_POS)); +} + +/* +** Handles the SetRating bang. +** +*/ +void PlayerAIMP::SetRating(int rating) +{ + // Set rating through the AIMP Winamp API + if (m_State != STATE_STOPPED) + { + SendMessage(m_WinampWindow, WM_WA_IPC, rating, IPC_SETRATING); + m_Rating = rating; + } +} + +/* +** Handles the SetVolume bang. +** +*/ +void PlayerAIMP::SetVolume(int volume) +{ + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_SET, MAKELPARAM(volume, AIMP_STS_VOLUME)); +} + +/* +** Handles the SetShuffle bang. +** +*/ +void PlayerAIMP::SetShuffle(bool state) +{ + m_Shuffle = state; + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_SET, MAKELPARAM(m_Shuffle, AIMP_STS_SHUFFLE)); +} + +/* +** Handles the SetRepeat bang. +** +*/ +void PlayerAIMP::SetRepeat(bool state) +{ + m_Repeat = state; + SendMessage(m_Window, WM_AIMP_COMMAND, WM_AIMP_STATUS_SET, MAKELPARAM(m_Repeat, AIMP_STS_REPEAT)); +} + +/* +** Handles the ClosePlayer bang. +** +*/ +void PlayerAIMP::ClosePlayer() +{ + SendMessage(m_Window, WM_CLOSE, 0, 0); +} + +/* +** Handles the OpenPlayer bang. +** +*/ +void PlayerAIMP::OpenPlayer(std::wstring& path) +{ + if (path.empty()) + { + // Check for AIMP2 first + DWORD size = 512; + WCHAR* data = new WCHAR[size]; + DWORD type = 0; + HKEY hKey; + + RegOpenKeyEx(HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\AIMP2", + 0, + KEY_QUERY_VALUE, + &hKey); + + if (RegQueryValueEx(hKey, + L"DisplayIcon", + nullptr, + (LPDWORD)&type, + (LPBYTE)data, + (LPDWORD)&size) == ERROR_SUCCESS) + { + if (type == REG_SZ) + { + ShellExecute(nullptr, L"open", data, nullptr, nullptr, SW_SHOW); + path = data; + } + } + else + { + // Let's try AIMP3 + RegCloseKey(hKey); + RegOpenKeyEx(HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\AIMP3", + 0, + KEY_QUERY_VALUE, + &hKey); + + if (RegQueryValueEx(hKey, + L"DisplayIcon", + nullptr, + (LPDWORD)&type, + (LPBYTE)data, + (LPDWORD)&size) == ERROR_SUCCESS) + { + if (type == REG_SZ) + { + path = data; + path.resize(path.find_last_of(L'\\') + 1); + path += L"AIMP3.exe"; + ShellExecute(nullptr, L"open", path.c_str(), nullptr, nullptr, SW_SHOW); + } + } + } + + delete [] data; + RegCloseKey(hKey); + } + else + { + ShellExecute(nullptr, L"open", path.c_str(), nullptr, nullptr, SW_SHOW); + } +} diff --git a/Plugins/PluginNowPlaying/PlayerAIMP.h b/Plugins/PluginNowPlaying/PlayerAIMP.h index 23243b6b..3eecc6bb 100644 --- a/Plugins/PluginNowPlaying/PlayerAIMP.h +++ b/Plugins/PluginNowPlaying/PlayerAIMP.h @@ -1,64 +1,64 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __PLAYERAIMP_H__ -#define __PLAYERAIMP_H__ - -#include "Player.h" - -class PlayerAIMP : public Player -{ -public: - virtual ~PlayerAIMP(); - - static Player* Create(); - - virtual void UpdateData(); - - virtual void Pause(); - virtual void Play(); - virtual void Stop(); - virtual void Next(); - virtual void Previous(); - virtual void SetPosition(int position); - virtual void SetRating(int rating); - virtual void SetVolume(int volume); - virtual void SetShuffle(bool state); - virtual void SetRepeat(bool state); - virtual void ClosePlayer(); - virtual void OpenPlayer(std::wstring& path); - -protected: - PlayerAIMP(); - -private: - bool Initialize(); - bool CheckWindow(); - - static Player* c_Player; - - HWND m_Window; // AIMP window - HWND m_WinampWindow; // AIMP Winamp API window - DWORD m_LastCheckTime; - INT64 m_LastFileSize; - DWORD m_LastTitleSize; - LPVOID m_FileMap; - HANDLE m_FileMapHandle; -}; - -#endif +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __PLAYERAIMP_H__ +#define __PLAYERAIMP_H__ + +#include "Player.h" + +class PlayerAIMP : public Player +{ +public: + virtual ~PlayerAIMP(); + + static Player* Create(); + + virtual void UpdateData(); + + virtual void Pause(); + virtual void Play(); + virtual void Stop(); + virtual void Next(); + virtual void Previous(); + virtual void SetPosition(int position); + virtual void SetRating(int rating); + virtual void SetVolume(int volume); + virtual void SetShuffle(bool state); + virtual void SetRepeat(bool state); + virtual void ClosePlayer(); + virtual void OpenPlayer(std::wstring& path); + +protected: + PlayerAIMP(); + +private: + bool Initialize(); + bool CheckWindow(); + + static Player* c_Player; + + HWND m_Window; // AIMP window + HWND m_WinampWindow; // AIMP Winamp API window + DWORD m_LastCheckTime; + INT64 m_LastFileSize; + DWORD m_LastTitleSize; + LPVOID m_FileMap; + HANDLE m_FileMapHandle; +}; + +#endif diff --git a/Plugins/PluginNowPlaying/PlayerCAD.cpp b/Plugins/PluginNowPlaying/PlayerCAD.cpp index 7175ab9b..d65b8881 100644 --- a/Plugins/PluginNowPlaying/PlayerCAD.cpp +++ b/Plugins/PluginNowPlaying/PlayerCAD.cpp @@ -1,556 +1,556 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "PlayerCAD.h" -#include "CAD/cad_sdk.h" - -Player* PlayerCAD::c_Player = nullptr; -extern HINSTANCE g_Instance; - -// This player emulates the CD Art Display IPC interface, which is supported by -// MusicBee, VLC (with libcad plugin), and possibly others. - -/* -** Constructor. -** -*/ -PlayerCAD::PlayerCAD() : Player(), - m_Window(), - m_PlayerWindow(), - m_ExtendedAPI(false), - m_Open(false) -{ - Initialize(); -} - -/* -** Constructor. -** -*/ -PlayerCAD::~PlayerCAD() -{ - c_Player = nullptr; - Uninitialize(); -} - -/* -** Creates a shared class object. -** -*/ -Player* PlayerCAD::Create() -{ - if (!c_Player) - { - c_Player = new PlayerCAD(); - } - - return c_Player; -} - -/* -** Create receiver window. -** -*/ -void PlayerCAD::Initialize() -{ - // Create windows class - WNDCLASS wc = {0}; - wc.hInstance = g_Instance; - wc.lpfnWndProc = WndProc; - wc.lpszClassName = L"NowPlayingCADClass"; - RegisterClass(&wc); - - // Create reciever window - m_Window = CreateWindow( - L"NowPlayingCADClass", - L"CD Art Display 1.x Class", - WS_DISABLED, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - nullptr, - nullptr, - g_Instance, - this); - - // Add WM_USER/WM_COPYDATA to allowed messages from lower level processes - const HMODULE hUser32 = GetModuleHandle(L"user32"); - - // Try ChangeWindowMessageFilterEx first (Win7+) - auto changeWindowMessageFilterEx = - (decltype(ChangeWindowMessageFilterEx)*)GetProcAddress(hUser32, "ChangeWindowMessageFilterEx"); - if (changeWindowMessageFilterEx) - { - changeWindowMessageFilterEx(m_Window, WM_USER, MSGFLT_ALLOW, nullptr); - changeWindowMessageFilterEx(m_Window, WM_COPYDATA, MSGFLT_ALLOW, nullptr); - } - else - { - // Try ChangeWindowMessageFilter (Vista) - auto changeWindowMessageFilter = - (decltype(ChangeWindowMessageFilter)*)GetProcAddress(hUser32, "ChangeWindowMessageFilter"); - if (changeWindowMessageFilter) - { - changeWindowMessageFilter(WM_USER, MSGFLT_ALLOW); - changeWindowMessageFilter(WM_COPYDATA, MSGFLT_ALLOW); - } - } - - WCHAR buffer[MAX_PATH]; - LPCTSTR file = RmGetSettingsFile(); - - // Read saved settings - GetPrivateProfileString(L"NowPlaying.dll", L"ClassName", nullptr, buffer, MAX_PATH, file); - std::wstring className = buffer; - - GetPrivateProfileString(L"NowPlaying.dll", L"WindowName", nullptr, buffer, MAX_PATH, file); - std::wstring windowName = buffer; - - GetPrivateProfileString(L"NowPlaying.dll", L"PlayerPath", nullptr, buffer, MAX_PATH, file); - m_PlayerPath = buffer; - - LPCTSTR classSz = className.empty() ? nullptr : className.c_str(); - LPCTSTR windowSz = windowName.empty() ? nullptr : windowName.c_str(); - - if (classSz || windowSz) - { - m_PlayerWindow = FindWindow(classSz, windowSz); - } - else - { - classSz = L"CD Art Display IPC Class"; - m_PlayerWindow = FindWindow(classSz, nullptr); - if (m_PlayerWindow) - { - WritePrivateProfileString(L"NowPlaying.dll", L"ClassName", classSz, file); - - windowSz = (GetWindowText(m_PlayerWindow, buffer, MAX_PATH) > 0) ? buffer : nullptr; - WritePrivateProfileString(L"NowPlaying.dll", L"WindowName", windowSz, file); - - DWORD pID; - GetWindowThreadProcessId(m_PlayerWindow, &pID); - HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pID); - if (hProcess) - { - if (GetModuleFileNameEx(hProcess, nullptr, buffer, MAX_PATH) > 0) - { - WritePrivateProfileString(L"NowPlaying.dll", L"PlayerPath", buffer, file); - } - - CloseHandle(hProcess); - } - } - } - - if (m_PlayerWindow) - { - m_Initialized = true; - - if (classSz && wcscmp(classSz, L"CD Art Display IPC Class") == 0) - { - m_ExtendedAPI = true; - } - - SendMessage(m_PlayerWindow, WM_USER, (WPARAM)m_Window, IPC_SET_CALLBACK_HWND); - m_State = (StateType)SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_STATE); - - if (m_State != STATE_STOPPED) - { - SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_CURRENT_TRACK); - } - } -} - -/* -** Destroy reciever window. -** -*/ -void PlayerCAD::Uninitialize() -{ - DestroyWindow(m_Window); - UnregisterClass(L"NowPlayingCADClass", g_Instance); -} - -/* -** Window procedure for the reciever window. -** -*/ -LRESULT CALLBACK PlayerCAD::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static PlayerCAD* player; - - switch (msg) - { - case WM_CREATE: - { - // Get pointer to the PlayerCAD class from the CreateWindow call - player = (PlayerCAD*)((CREATESTRUCT*)lParam)->lpCreateParams; - return 0; - } - - case WM_DESTROY: - { - SendMessage(player->m_PlayerWindow, WM_USER, 0, IPC_SHUTDOWN_NOTIFICATION); - return 0; - } - - case WM_USER: - switch (lParam) - { - case IPC_TRACK_CHANGED_NOTIFICATION: - { - PostMessage(player->m_PlayerWindow, WM_USER, 0, IPC_GET_CURRENT_TRACK); - break; - } - - case IPC_STATE_CHANGED_NOTIFICATION: - { - player->m_State = (StateType)wParam; - if (player->m_State == STATE_STOPPED) - { - player->ClearData(false); - } - break; - } - - case IPC_VOLUME_CHANGED_NOTIFICATION: - { - player->m_Volume = (UINT)wParam; - break; - } - - case IPC_REPEAT_CHANGED_NOTIFICATION: - { - player->m_Repeat = wParam != 0; - break; - } - - case IPC_SHUFFLE_CHANGED_NOTIFICATION: - { - player->m_Shuffle = wParam != 0; - break; - } - - case IPC_RATING_CHANGED_NOTIFICATION: - { - player->m_Rating = ((UINT)wParam + 1) / 2; // From 0 - 10 to 0 - 5 - break; - } - - case IPC_SHUTDOWN_NOTIFICATION: - { - player->m_Initialized = false; - player->ClearData(); - break; - } - } - return 0; - - case WM_COPYDATA: - { - PCOPYDATASTRUCT cds = (PCOPYDATASTRUCT)lParam; - if (cds->dwData == IPC_CURRENT_TRACK_NOTIFICATION) - { - player->m_Shuffle = SendMessage(player->m_PlayerWindow, WM_USER, 0, IPC_GET_SHUFFLE) != 0; - player->m_Repeat = SendMessage(player->m_PlayerWindow, WM_USER, 0, IPC_GET_REPEAT) != 0; - - // TODO: Sent on track update? - ++player->m_TrackCount; - - WCHAR* data = (WCHAR*)cds->lpData; - WCHAR* pos; - UINT index = 1; - while ((pos = wcschr(data, '\t')) != nullptr) - { - switch (index) - { - case 1: - player->m_Title.assign(data, pos - data); - break; - - case 2: - player->m_Artist.assign(data, pos - data); - break; - - case 3: - player->m_Album.assign(data, pos - data); - break; - - case 5: - player->m_Year = (UINT)_wtoi(data); - break; - - case 7: - player->m_Number = (UINT)_wtoi(data); - break; - - case 8: - player->m_Duration = (UINT)_wtoi(data); - break; - - case 9: - player->m_FilePath.assign(data, pos - data); - break; - - case 10: - player->m_Rating = ((UINT)_wtoi(data) + 1) / 2; // 0 - 10 -> 0 - 5 - break; - - case 11: - if (*data == L' ') - { - player->FindCover(); - } - else - { - player->m_CoverPath.assign(data, pos - data); - } - break; - } - - data = pos + 1; - ++index; - - if (index == 12) - { - break; - } - } - - if (player->m_Measures & MEASURE_LYRICS) - { - player->FindLyrics(); - } - } - else if (cds->dwData == IPC_NEW_COVER_NOTIFICATION) - { - WCHAR* data = (WCHAR*)cds->lpData; - if (data) - { - player->m_CoverPath.assign(data); - } - } - else if (cds->dwData == IPC_REGISTER_NOTIFICATION && !player->m_Initialized) - { - std::wstring data = (WCHAR*)cds->lpData; - if (data[0] == L'1') - { - data.erase(0, 2); // Get rid of the 1\t at the beginning - - std::wstring::size_type len = data.find_first_of(L'\t'); - std::wstring className(data, 0, len); - data.erase(0, ++len); - - len = data.find_first_of(L'\t'); - std::wstring windowName(data, 0, len); - data.erase(0, ++len); - - len = data.find_first_of(L'\t'); - player->m_PlayerPath.assign(data, 0, len); - data.erase(0, ++len); - - LPCTSTR classSz = className.empty() ? nullptr : className.c_str(); - LPCTSTR windowSz = windowName.empty() ? nullptr : windowName.c_str(); - LPCTSTR file = RmGetSettingsFile(); - - WritePrivateProfileString(L"NowPlaying.dll", L"ClassName", classSz, file); - WritePrivateProfileString(L"NowPlaying.dll", L"WindowName", windowSz, file); - WritePrivateProfileString(L"NowPlaying.dll", L"PlayerPath", player->m_PlayerPath.c_str(), file); - - player->m_PlayerWindow = FindWindow(classSz, windowSz); - - if (player->m_PlayerWindow) - { - player->m_Initialized = true; - player->m_ExtendedAPI = (classSz && wcscmp(classSz, L"CD Art Display IPC Class") == 0); - player->m_State = (StateType)SendMessage(player->m_PlayerWindow, WM_USER, 0, IPC_GET_STATE); - - if (player->m_State != STATE_STOPPED) - { - PostMessage(player->m_PlayerWindow, WM_USER, 0, IPC_GET_CURRENT_TRACK); - } - - if (player->m_Open) - { - if (windowSz && wcscmp(windowSz, L"foobar2000") == 0) - { - // Activate foobar2000 in case it starts minimized - SendMessage(player->m_PlayerWindow, WM_USER, 0, IPC_SHOW_WINDOW); - } - - player->m_Open = false; - } - } - } - } - } - return 0; - - default: - return DefWindowProc(hwnd, msg, wParam, lParam); - } -} - -/* -** Called during each update of the main measure. -** -*/ -void PlayerCAD::UpdateData() -{ - if (m_State != STATE_STOPPED) - { - m_Position = (UINT)SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_POSITION); - m_Volume = (UINT)SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_VOLUME); - } -} - -/* -** Handles the Pause bang. -** -*/ -void PlayerCAD::Pause() -{ - SendMessage(m_PlayerWindow, WM_USER, 0, m_ExtendedAPI ? IPC_PAUSE : IPC_PLAYPAUSE); -} - -/* -** Handles the Play bang. -** -*/ -void PlayerCAD::Play() -{ - SendMessage(m_PlayerWindow, WM_USER, 0, m_ExtendedAPI ? IPC_PLAY : IPC_PLAYPAUSE); -} - -/* -** Handles the Stop bang. -** -*/ -void PlayerCAD::Stop() -{ - SendMessage(m_PlayerWindow, WM_USER, 0, IPC_STOP); -} - -/* -** Handles the Next bang. -** -*/ -void PlayerCAD::Next() -{ - SendMessage(m_PlayerWindow, WM_USER, 0, IPC_NEXT); -} - -/* -** Handles the Previous bang. -** -*/ -void PlayerCAD::Previous() -{ - SendMessage(m_PlayerWindow, WM_USER, 0, IPC_PREVIOUS); -} - -/* -** Handles the SetPosition bang. -** -*/ -void PlayerCAD::SetPosition(int position) -{ - SendMessage(m_PlayerWindow, WM_USER, position, IPC_SET_POSITION); -} - -/* -** Handles the SetRating bang. -** -*/ -void PlayerCAD::SetRating(int rating) -{ - m_Rating = rating; - rating *= 2; // From 0 - 5 to 0 - 10 - SendMessage(m_PlayerWindow, WM_USER, rating, IPC_SET_RATING); -} - -/* -** Handles the SetVolume bang. -** -*/ -void PlayerCAD::SetVolume(int volume) -{ - SendMessage(m_PlayerWindow, WM_USER, volume, IPC_SET_VOLUME); -} - -/* -** Handles the SetShuffle bang. -** -*/ -void PlayerCAD::SetShuffle(bool state) -{ - SendMessage(m_PlayerWindow, WM_USER, (WPARAM)state, IPC_SET_SHUFFLE); - m_Shuffle = SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_SHUFFLE) != 0; -} - -/* -** Handles the SetRepeat bang. -** -*/ -void PlayerCAD::SetRepeat(bool state) -{ - SendMessage(m_PlayerWindow, WM_USER, (WPARAM)state, IPC_SET_REPEAT); - m_Repeat = SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_REPEAT) != 0; -} - -/* -** Handles the ClosePlayer bang. -** -*/ -void PlayerCAD::ClosePlayer() -{ - SendMessage(m_PlayerWindow, WM_USER, 0, IPC_CLOSE); - // TODO - m_Initialized = false; - ClearData(); -} - -/* -** Handles the OpenPlayer bang. -** -*/ -void PlayerCAD::OpenPlayer(std::wstring& path) -{ - if (!m_Initialized) - { - HINSTANCE ret = nullptr; - - if (!path.empty()) - { - ret = ShellExecute(nullptr, L"open", path.c_str(), nullptr, nullptr, SW_SHOW); - } - else if (!m_PlayerPath.empty()) - { - ret = ShellExecute(nullptr, L"open", m_PlayerPath.c_str(), nullptr, nullptr, SW_SHOW); - } - - m_Open = (ret > (HINSTANCE)32); - } - else - { - // Bring player to front - SendMessage(m_PlayerWindow, WM_USER, 0, IPC_SHOW_WINDOW); - } -} +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "PlayerCAD.h" +#include "CAD/cad_sdk.h" + +Player* PlayerCAD::c_Player = nullptr; +extern HINSTANCE g_Instance; + +// This player emulates the CD Art Display IPC interface, which is supported by +// MusicBee, VLC (with libcad plugin), and possibly others. + +/* +** Constructor. +** +*/ +PlayerCAD::PlayerCAD() : Player(), + m_Window(), + m_PlayerWindow(), + m_ExtendedAPI(false), + m_Open(false) +{ + Initialize(); +} + +/* +** Constructor. +** +*/ +PlayerCAD::~PlayerCAD() +{ + c_Player = nullptr; + Uninitialize(); +} + +/* +** Creates a shared class object. +** +*/ +Player* PlayerCAD::Create() +{ + if (!c_Player) + { + c_Player = new PlayerCAD(); + } + + return c_Player; +} + +/* +** Create receiver window. +** +*/ +void PlayerCAD::Initialize() +{ + // Create windows class + WNDCLASS wc = {0}; + wc.hInstance = g_Instance; + wc.lpfnWndProc = WndProc; + wc.lpszClassName = L"NowPlayingCADClass"; + RegisterClass(&wc); + + // Create reciever window + m_Window = CreateWindow( + L"NowPlayingCADClass", + L"CD Art Display 1.x Class", + WS_DISABLED, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + nullptr, + nullptr, + g_Instance, + this); + + // Add WM_USER/WM_COPYDATA to allowed messages from lower level processes + const HMODULE hUser32 = GetModuleHandle(L"user32"); + + // Try ChangeWindowMessageFilterEx first (Win7+) + auto changeWindowMessageFilterEx = + (decltype(ChangeWindowMessageFilterEx)*)GetProcAddress(hUser32, "ChangeWindowMessageFilterEx"); + if (changeWindowMessageFilterEx) + { + changeWindowMessageFilterEx(m_Window, WM_USER, MSGFLT_ALLOW, nullptr); + changeWindowMessageFilterEx(m_Window, WM_COPYDATA, MSGFLT_ALLOW, nullptr); + } + else + { + // Try ChangeWindowMessageFilter (Vista) + auto changeWindowMessageFilter = + (decltype(ChangeWindowMessageFilter)*)GetProcAddress(hUser32, "ChangeWindowMessageFilter"); + if (changeWindowMessageFilter) + { + changeWindowMessageFilter(WM_USER, MSGFLT_ALLOW); + changeWindowMessageFilter(WM_COPYDATA, MSGFLT_ALLOW); + } + } + + WCHAR buffer[MAX_PATH]; + LPCTSTR file = RmGetSettingsFile(); + + // Read saved settings + GetPrivateProfileString(L"NowPlaying.dll", L"ClassName", nullptr, buffer, MAX_PATH, file); + std::wstring className = buffer; + + GetPrivateProfileString(L"NowPlaying.dll", L"WindowName", nullptr, buffer, MAX_PATH, file); + std::wstring windowName = buffer; + + GetPrivateProfileString(L"NowPlaying.dll", L"PlayerPath", nullptr, buffer, MAX_PATH, file); + m_PlayerPath = buffer; + + LPCTSTR classSz = className.empty() ? nullptr : className.c_str(); + LPCTSTR windowSz = windowName.empty() ? nullptr : windowName.c_str(); + + if (classSz || windowSz) + { + m_PlayerWindow = FindWindow(classSz, windowSz); + } + else + { + classSz = L"CD Art Display IPC Class"; + m_PlayerWindow = FindWindow(classSz, nullptr); + if (m_PlayerWindow) + { + WritePrivateProfileString(L"NowPlaying.dll", L"ClassName", classSz, file); + + windowSz = (GetWindowText(m_PlayerWindow, buffer, MAX_PATH) > 0) ? buffer : nullptr; + WritePrivateProfileString(L"NowPlaying.dll", L"WindowName", windowSz, file); + + DWORD pID; + GetWindowThreadProcessId(m_PlayerWindow, &pID); + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pID); + if (hProcess) + { + if (GetModuleFileNameEx(hProcess, nullptr, buffer, MAX_PATH) > 0) + { + WritePrivateProfileString(L"NowPlaying.dll", L"PlayerPath", buffer, file); + } + + CloseHandle(hProcess); + } + } + } + + if (m_PlayerWindow) + { + m_Initialized = true; + + if (classSz && wcscmp(classSz, L"CD Art Display IPC Class") == 0) + { + m_ExtendedAPI = true; + } + + SendMessage(m_PlayerWindow, WM_USER, (WPARAM)m_Window, IPC_SET_CALLBACK_HWND); + m_State = (StateType)SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_STATE); + + if (m_State != STATE_STOPPED) + { + SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_CURRENT_TRACK); + } + } +} + +/* +** Destroy reciever window. +** +*/ +void PlayerCAD::Uninitialize() +{ + DestroyWindow(m_Window); + UnregisterClass(L"NowPlayingCADClass", g_Instance); +} + +/* +** Window procedure for the reciever window. +** +*/ +LRESULT CALLBACK PlayerCAD::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static PlayerCAD* player; + + switch (msg) + { + case WM_CREATE: + { + // Get pointer to the PlayerCAD class from the CreateWindow call + player = (PlayerCAD*)((CREATESTRUCT*)lParam)->lpCreateParams; + return 0; + } + + case WM_DESTROY: + { + SendMessage(player->m_PlayerWindow, WM_USER, 0, IPC_SHUTDOWN_NOTIFICATION); + return 0; + } + + case WM_USER: + switch (lParam) + { + case IPC_TRACK_CHANGED_NOTIFICATION: + { + PostMessage(player->m_PlayerWindow, WM_USER, 0, IPC_GET_CURRENT_TRACK); + break; + } + + case IPC_STATE_CHANGED_NOTIFICATION: + { + player->m_State = (StateType)wParam; + if (player->m_State == STATE_STOPPED) + { + player->ClearData(false); + } + break; + } + + case IPC_VOLUME_CHANGED_NOTIFICATION: + { + player->m_Volume = (UINT)wParam; + break; + } + + case IPC_REPEAT_CHANGED_NOTIFICATION: + { + player->m_Repeat = wParam != 0; + break; + } + + case IPC_SHUFFLE_CHANGED_NOTIFICATION: + { + player->m_Shuffle = wParam != 0; + break; + } + + case IPC_RATING_CHANGED_NOTIFICATION: + { + player->m_Rating = ((UINT)wParam + 1) / 2; // From 0 - 10 to 0 - 5 + break; + } + + case IPC_SHUTDOWN_NOTIFICATION: + { + player->m_Initialized = false; + player->ClearData(); + break; + } + } + return 0; + + case WM_COPYDATA: + { + PCOPYDATASTRUCT cds = (PCOPYDATASTRUCT)lParam; + if (cds->dwData == IPC_CURRENT_TRACK_NOTIFICATION) + { + player->m_Shuffle = SendMessage(player->m_PlayerWindow, WM_USER, 0, IPC_GET_SHUFFLE) != 0; + player->m_Repeat = SendMessage(player->m_PlayerWindow, WM_USER, 0, IPC_GET_REPEAT) != 0; + + // TODO: Sent on track update? + ++player->m_TrackCount; + + WCHAR* data = (WCHAR*)cds->lpData; + WCHAR* pos; + UINT index = 1; + while ((pos = wcschr(data, '\t')) != nullptr) + { + switch (index) + { + case 1: + player->m_Title.assign(data, pos - data); + break; + + case 2: + player->m_Artist.assign(data, pos - data); + break; + + case 3: + player->m_Album.assign(data, pos - data); + break; + + case 5: + player->m_Year = (UINT)_wtoi(data); + break; + + case 7: + player->m_Number = (UINT)_wtoi(data); + break; + + case 8: + player->m_Duration = (UINT)_wtoi(data); + break; + + case 9: + player->m_FilePath.assign(data, pos - data); + break; + + case 10: + player->m_Rating = ((UINT)_wtoi(data) + 1) / 2; // 0 - 10 -> 0 - 5 + break; + + case 11: + if (*data == L' ') + { + player->FindCover(); + } + else + { + player->m_CoverPath.assign(data, pos - data); + } + break; + } + + data = pos + 1; + ++index; + + if (index == 12) + { + break; + } + } + + if (player->m_Measures & MEASURE_LYRICS) + { + player->FindLyrics(); + } + } + else if (cds->dwData == IPC_NEW_COVER_NOTIFICATION) + { + WCHAR* data = (WCHAR*)cds->lpData; + if (data) + { + player->m_CoverPath.assign(data); + } + } + else if (cds->dwData == IPC_REGISTER_NOTIFICATION && !player->m_Initialized) + { + std::wstring data = (WCHAR*)cds->lpData; + if (data[0] == L'1') + { + data.erase(0, 2); // Get rid of the 1\t at the beginning + + std::wstring::size_type len = data.find_first_of(L'\t'); + std::wstring className(data, 0, len); + data.erase(0, ++len); + + len = data.find_first_of(L'\t'); + std::wstring windowName(data, 0, len); + data.erase(0, ++len); + + len = data.find_first_of(L'\t'); + player->m_PlayerPath.assign(data, 0, len); + data.erase(0, ++len); + + LPCTSTR classSz = className.empty() ? nullptr : className.c_str(); + LPCTSTR windowSz = windowName.empty() ? nullptr : windowName.c_str(); + LPCTSTR file = RmGetSettingsFile(); + + WritePrivateProfileString(L"NowPlaying.dll", L"ClassName", classSz, file); + WritePrivateProfileString(L"NowPlaying.dll", L"WindowName", windowSz, file); + WritePrivateProfileString(L"NowPlaying.dll", L"PlayerPath", player->m_PlayerPath.c_str(), file); + + player->m_PlayerWindow = FindWindow(classSz, windowSz); + + if (player->m_PlayerWindow) + { + player->m_Initialized = true; + player->m_ExtendedAPI = (classSz && wcscmp(classSz, L"CD Art Display IPC Class") == 0); + player->m_State = (StateType)SendMessage(player->m_PlayerWindow, WM_USER, 0, IPC_GET_STATE); + + if (player->m_State != STATE_STOPPED) + { + PostMessage(player->m_PlayerWindow, WM_USER, 0, IPC_GET_CURRENT_TRACK); + } + + if (player->m_Open) + { + if (windowSz && wcscmp(windowSz, L"foobar2000") == 0) + { + // Activate foobar2000 in case it starts minimized + SendMessage(player->m_PlayerWindow, WM_USER, 0, IPC_SHOW_WINDOW); + } + + player->m_Open = false; + } + } + } + } + } + return 0; + + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } +} + +/* +** Called during each update of the main measure. +** +*/ +void PlayerCAD::UpdateData() +{ + if (m_State != STATE_STOPPED) + { + m_Position = (UINT)SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_POSITION); + m_Volume = (UINT)SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_VOLUME); + } +} + +/* +** Handles the Pause bang. +** +*/ +void PlayerCAD::Pause() +{ + SendMessage(m_PlayerWindow, WM_USER, 0, m_ExtendedAPI ? IPC_PAUSE : IPC_PLAYPAUSE); +} + +/* +** Handles the Play bang. +** +*/ +void PlayerCAD::Play() +{ + SendMessage(m_PlayerWindow, WM_USER, 0, m_ExtendedAPI ? IPC_PLAY : IPC_PLAYPAUSE); +} + +/* +** Handles the Stop bang. +** +*/ +void PlayerCAD::Stop() +{ + SendMessage(m_PlayerWindow, WM_USER, 0, IPC_STOP); +} + +/* +** Handles the Next bang. +** +*/ +void PlayerCAD::Next() +{ + SendMessage(m_PlayerWindow, WM_USER, 0, IPC_NEXT); +} + +/* +** Handles the Previous bang. +** +*/ +void PlayerCAD::Previous() +{ + SendMessage(m_PlayerWindow, WM_USER, 0, IPC_PREVIOUS); +} + +/* +** Handles the SetPosition bang. +** +*/ +void PlayerCAD::SetPosition(int position) +{ + SendMessage(m_PlayerWindow, WM_USER, position, IPC_SET_POSITION); +} + +/* +** Handles the SetRating bang. +** +*/ +void PlayerCAD::SetRating(int rating) +{ + m_Rating = rating; + rating *= 2; // From 0 - 5 to 0 - 10 + SendMessage(m_PlayerWindow, WM_USER, rating, IPC_SET_RATING); +} + +/* +** Handles the SetVolume bang. +** +*/ +void PlayerCAD::SetVolume(int volume) +{ + SendMessage(m_PlayerWindow, WM_USER, volume, IPC_SET_VOLUME); +} + +/* +** Handles the SetShuffle bang. +** +*/ +void PlayerCAD::SetShuffle(bool state) +{ + SendMessage(m_PlayerWindow, WM_USER, (WPARAM)state, IPC_SET_SHUFFLE); + m_Shuffle = SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_SHUFFLE) != 0; +} + +/* +** Handles the SetRepeat bang. +** +*/ +void PlayerCAD::SetRepeat(bool state) +{ + SendMessage(m_PlayerWindow, WM_USER, (WPARAM)state, IPC_SET_REPEAT); + m_Repeat = SendMessage(m_PlayerWindow, WM_USER, 0, IPC_GET_REPEAT) != 0; +} + +/* +** Handles the ClosePlayer bang. +** +*/ +void PlayerCAD::ClosePlayer() +{ + SendMessage(m_PlayerWindow, WM_USER, 0, IPC_CLOSE); + // TODO + m_Initialized = false; + ClearData(); +} + +/* +** Handles the OpenPlayer bang. +** +*/ +void PlayerCAD::OpenPlayer(std::wstring& path) +{ + if (!m_Initialized) + { + HINSTANCE ret = nullptr; + + if (!path.empty()) + { + ret = ShellExecute(nullptr, L"open", path.c_str(), nullptr, nullptr, SW_SHOW); + } + else if (!m_PlayerPath.empty()) + { + ret = ShellExecute(nullptr, L"open", m_PlayerPath.c_str(), nullptr, nullptr, SW_SHOW); + } + + m_Open = (ret > (HINSTANCE)32); + } + else + { + // Bring player to front + SendMessage(m_PlayerWindow, WM_USER, 0, IPC_SHOW_WINDOW); + } +} diff --git a/Plugins/PluginNowPlaying/PlayerCAD.h b/Plugins/PluginNowPlaying/PlayerCAD.h index aba56197..72700add 100644 --- a/Plugins/PluginNowPlaying/PlayerCAD.h +++ b/Plugins/PluginNowPlaying/PlayerCAD.h @@ -1,63 +1,63 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __PLAYERCAD_H__ -#define __PLAYERCAD_H__ - -#include "Player.h" - -class PlayerCAD : public Player -{ -public: - virtual ~PlayerCAD(); - - static Player* Create(); - - virtual void UpdateData(); - - virtual void Pause(); - virtual void Play(); - virtual void Stop(); - virtual void Next(); - virtual void Previous(); - virtual void SetPosition(int position); - virtual void SetRating(int rating); - virtual void SetVolume(int volume); - virtual void SetShuffle(bool state); - virtual void SetRepeat(bool state); - virtual void ClosePlayer(); - virtual void OpenPlayer(std::wstring& path); - -protected: - PlayerCAD(); - -private: - void Initialize(); - void Uninitialize(); - static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - - static Player* c_Player; - - HWND m_Window; - HWND m_PlayerWindow; - std::wstring m_PlayerPath; - bool m_ExtendedAPI; - bool m_Open; -}; - -#endif +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __PLAYERCAD_H__ +#define __PLAYERCAD_H__ + +#include "Player.h" + +class PlayerCAD : public Player +{ +public: + virtual ~PlayerCAD(); + + static Player* Create(); + + virtual void UpdateData(); + + virtual void Pause(); + virtual void Play(); + virtual void Stop(); + virtual void Next(); + virtual void Previous(); + virtual void SetPosition(int position); + virtual void SetRating(int rating); + virtual void SetVolume(int volume); + virtual void SetShuffle(bool state); + virtual void SetRepeat(bool state); + virtual void ClosePlayer(); + virtual void OpenPlayer(std::wstring& path); + +protected: + PlayerCAD(); + +private: + void Initialize(); + void Uninitialize(); + static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + + static Player* c_Player; + + HWND m_Window; + HWND m_PlayerWindow; + std::wstring m_PlayerPath; + bool m_ExtendedAPI; + bool m_Open; +}; + +#endif diff --git a/Plugins/PluginNowPlaying/PlayerITunes.cpp b/Plugins/PluginNowPlaying/PlayerITunes.cpp index 791e1198..a99e0ae2 100644 --- a/Plugins/PluginNowPlaying/PlayerITunes.cpp +++ b/Plugins/PluginNowPlaying/PlayerITunes.cpp @@ -1,641 +1,641 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "PlayerITunes.h" - -Player* PlayerITunes::c_Player = nullptr; -extern HINSTANCE g_Instance; - -/* -** Constructor. -** -*/ -PlayerITunes::CEventHandler::CEventHandler(PlayerITunes* player) : - m_Player(player), - m_RefCount(), - m_ConnectionPoint(), - m_ConnectionCookie() -{ - IConnectionPointContainer* icpc; - m_Player->m_iTunes->QueryInterface(IID_IConnectionPointContainer, (void**)&icpc); - icpc->FindConnectionPoint(DIID__IiTunesEvents, &m_ConnectionPoint); - m_ConnectionPoint->Advise(this, &m_ConnectionCookie); - icpc->Release(); -} - -/* -** Destructor. -** -*/ -PlayerITunes::CEventHandler::~CEventHandler() -{ - if (m_ConnectionPoint) - { - m_ConnectionPoint->Unadvise(m_ConnectionCookie); - m_ConnectionPoint->Release(); - } -} - -HRESULT STDMETHODCALLTYPE PlayerITunes::CEventHandler::QueryInterface(REFIID iid, void** ppvObject) -{ - if (iid == IID_IUnknown || iid == IID_IUnknown || iid == DIID__IiTunesEvents) - { - ++m_RefCount; - *ppvObject = this; - return S_OK; - } - - return E_NOINTERFACE; -} - -ULONG STDMETHODCALLTYPE PlayerITunes::CEventHandler::AddRef() -{ - return ++m_RefCount; -} - -ULONG STDMETHODCALLTYPE PlayerITunes::CEventHandler::Release() -{ - return --m_RefCount; -} - -HRESULT STDMETHODCALLTYPE PlayerITunes::CEventHandler::Invoke(DISPID dispidMember, REFIID, LCID, WORD, DISPPARAMS* dispParams, VARIANT*, EXCEPINFO*, UINT*) -{ - switch (dispidMember) - { - case ITEventDatabaseChanged: - m_Player->OnDatabaseChange(); - break; - - case ITEventPlayerPlay: - m_Player->OnStateChange(true); - m_Player->OnTrackChange(); - break; - - case ITEventPlayerStop: - m_Player->OnStateChange(false); - break; - - case ITEventPlayerPlayingTrackChanged: - m_Player->OnTrackChange(); - break; - - case ITEventSoundVolumeChanged: - m_Player->OnVolumeChange(dispParams->rgvarg[0].intVal); - break; - - case ITEventAboutToPromptUserToQuit: - PostMessage(m_Player->m_CallbackWindow, WM_USER, ITEventAboutToPromptUserToQuit, 0); - SetTimer(m_Player->m_CallbackWindow, TIMER_CHECKACTIVE, 500, nullptr); - break; - } - - return S_OK; -} - -/* -** Constructor. -** -*/ -PlayerITunes::PlayerITunes() : Player(), - m_CallbackWindow(), - m_LastCheckTime(0), - m_iTunesActive(false), - m_iTunes(), - m_iTunesEvent() -{ - // Create windows class - WNDCLASS wc = {0}; - wc.hInstance = g_Instance; - wc.lpfnWndProc = WndProc; - wc.lpszClassName = L"NowPlayingITunesClass"; - RegisterClass(&wc); - - // Create callback window - m_CallbackWindow = CreateWindow(L"NowPlayingITunesClass", - L"CallbackWindow", - WS_DISABLED, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - HWND_MESSAGE, - nullptr, - g_Instance, - this); -} - -/* -** Destructor. -** -*/ -PlayerITunes::~PlayerITunes() -{ - c_Player = nullptr; - - DestroyWindow(m_CallbackWindow); - UnregisterClass(L"NowPlayingITunesClass", g_Instance); - - Uninitialize(); -} - -/* -** Creates a shared class object. -** -*/ -Player* PlayerITunes::Create() -{ - if (!c_Player) - { - c_Player = new PlayerITunes(); - } - - return c_Player; -} - -/* -** Initialize iTunes COM interface and event handler. -** -*/ -void PlayerITunes::Initialize() -{ - while (true) - { - HRESULT hr = CoCreateInstance(CLSID_iTunesApp, nullptr, CLSCTX_LOCAL_SERVER, IID_IiTunes, (PVOID*)&m_iTunes); - - if (hr == CO_E_SERVER_EXEC_FAILURE) - { - // This seems to happen if there is a modal dialog being shown in iTunes - // or some other delay has occurred. Retrying should do the trick. - continue; - } - else if (hr != S_OK) - { - // Failed to get hold of iTunes instance via COM - m_iTunes = nullptr; - } - - break; - } - - if (m_iTunes) - { - m_Initialized = true; - - // Set up event handler - m_iTunesEvent = new CEventHandler(this); - - // Try getting track info and player state - ITPlayerState state; - if (SUCCEEDED(m_iTunes->get_PlayerState(&state))) - { - if (state == ITPlayerStateStopped) - { - // Determine if paused of stopped - long position = 0; - m_iTunes->get_PlayerPosition(&position); - - if (position != 0) - { - m_State = STATE_PAUSED; - OnTrackChange(); - } - } - else if (state == ITPlayerStatePlaying) - { - m_State = STATE_PLAYING; - OnTrackChange(); - } - } - - long volume; - m_iTunes->get_SoundVolume(&volume); - m_Volume = (UINT)volume; - - OnDatabaseChange(); - } - else - { - m_Initialized = false; - } -} - -/* -** Close iTunes COM interface. -** -*/ -void PlayerITunes::Uninitialize() -{ - if (m_Initialized) - { - m_Initialized = false; - ClearData(); - - m_iTunes->Release(); - delete m_iTunesEvent; - } -} - -/* -** Window procedure for the callback window. -** -*/ -LRESULT CALLBACK PlayerITunes::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static PlayerITunes* player; - - switch (msg) - { - case WM_CREATE: - // Get pointer to the PlayerITunes class from the CreateWindow call - player = (PlayerITunes*)(((CREATESTRUCT*)lParam)->lpCreateParams); - return 0; - - case WM_USER: - if (wParam == ITEventAboutToPromptUserToQuit) - { - // Event handler calls this through a PostMessage when iTunes quits - player->Uninitialize(); - } - return 0; - - case WM_TIMER: - if (wParam == TIMER_CHECKACTIVE) - { - if (!FindWindow(L"iTunesApp", L"iTunes") && !FindWindow(L"iTunes", L"iTunes")) - { - player->m_iTunesActive = false; - KillTimer(hwnd, TIMER_CHECKACTIVE); - } - } - return 0; - - default: - return DefWindowProc(hwnd, msg, wParam, lParam); - } -} - -/* -** Try to find iTunes periodically. -** -*/ -bool PlayerITunes::CheckWindow() -{ - DWORD time = GetTickCount(); - if (time - m_LastCheckTime > 5000) - { - m_LastCheckTime = time; - - if ((FindWindow(L"iTunesApp", L"iTunes") || FindWindow(L"iTunes", L"iTunes")) && !m_iTunesActive) - { - m_iTunesActive = true; - Initialize(); - } - } - - return m_Initialized; -} - -/* -** Called during each update of the main measure. -** -*/ -void PlayerITunes::UpdateData() -{ - if ((m_Initialized || CheckWindow()) && m_State != STATE_STOPPED) - { - long position = 0; - m_iTunes->get_PlayerPosition(&position); - m_Position = (UINT)position; - } -} - -/* -** Called by iTunes event handler when the database is changed. -** -*/ -void PlayerITunes::OnDatabaseChange() -{ - // Check the shuffle state. TODO: Find better way - IITPlaylist* playlist; - HRESULT hr = m_iTunes->get_CurrentPlaylist(&playlist); - if (SUCCEEDED(hr) && playlist) - { - VARIANT_BOOL shuffle; - hr = playlist->get_Shuffle(&shuffle); - if (SUCCEEDED(hr)) - { - m_Shuffle = shuffle != VARIANT_FALSE; - } - - playlist->Release(); - } -} - -/* -** Called by iTunes event handler on track change. -** -*/ -void PlayerITunes::OnTrackChange() -{ - IITTrack* track; - HRESULT hr = m_iTunes->get_CurrentTrack(&track); - if (SUCCEEDED(hr) && track) - { - BSTR tmpStr; - long tmpVal; - - // Get metadata - track->get_Artist(&tmpStr); - tmpStr ? (m_Artist = tmpStr) : m_Artist.clear(); - - track->get_Name(&tmpStr); - tmpStr ? (m_Title = tmpStr) : m_Title.clear(); - - track->get_Album(&tmpStr); - tmpStr ? (m_Album = tmpStr) : m_Album.clear(); - - track->get_Duration(&tmpVal); - m_Duration = (UINT)tmpVal; - - // Rating is 0 - 100, divide to 0 - 5 - track->get_Rating(&tmpVal); - tmpVal /= 20L; - m_Rating = (UINT)tmpVal; - - track->get_TrackNumber(&tmpVal); - m_Number = (UINT)tmpVal; - - track->get_Year(&tmpVal); - m_Year = (UINT)tmpVal; - - IITPlaylist* playlist; - hr = track->get_Playlist(&playlist); - if (SUCCEEDED(hr)) - { - ITPlaylistRepeatMode repeat; - hr = playlist->get_SongRepeat(&repeat); - if (SUCCEEDED(hr)) - { - m_Repeat = repeat != ITPlaylistRepeatModeOff; - } - - playlist->Release(); - } - - IITFileOrCDTrack* file; - hr = track->QueryInterface(&file); - if (SUCCEEDED(hr)) - { - file->get_Location(&tmpStr); - file->Release(); - if (tmpStr && wcscmp(tmpStr, m_FilePath.c_str()) != 0) - { - ++m_TrackCount; - m_FilePath = tmpStr; - - if (m_Measures & MEASURE_COVER) - { - m_CoverPath.clear(); - - // Check for embedded art through iTunes interface - IITArtworkCollection* artworkCollection; - hr = track->get_Artwork(&artworkCollection); - - if (SUCCEEDED(hr)) - { - long count; - artworkCollection->get_Count(&count); - - if (count > 0) - { - IITArtwork* artwork; - hr = artworkCollection->get_Item(1, &artwork); - - if (SUCCEEDED(hr)) - { - _bstr_t coverPath = m_TempCoverPath.c_str(); - hr = artwork->SaveArtworkToFile(coverPath); - if (SUCCEEDED(hr)) - { - m_CoverPath = m_TempCoverPath; - } - - artwork->Release(); - } - } - - artworkCollection->Release(); - } - } - - if (m_Measures & MEASURE_LYRICS) - { - FindLyrics(); - } - } - } - - track->Release(); - } - else - { - ClearData(false); - } -} - -/* -** Called by iTunes event handler on player state change. -** -*/ -void PlayerITunes::OnStateChange(bool playing) -{ - if (playing) - { - m_State = STATE_PLAYING; - } - else - { - long position = 0; - m_iTunes->get_PlayerPosition(&position); - - // Guess if paused or stopped from track time - m_State = (position == 0) ? STATE_STOPPED : STATE_PAUSED; - if (m_State == STATE_STOPPED) - { - ClearData(false); - } - } -} - -/* -** Called by iTunes event handler on volume change. -** -*/ -void PlayerITunes::OnVolumeChange(int volume) -{ - m_Volume = volume; -} - -/* -** Handles the Pause bang. -** -*/ -void PlayerITunes::Pause() -{ - m_iTunes->Pause(); -} - -/* -** Handles the Play bang. -** -*/ -void PlayerITunes::Play() -{ - m_iTunes->Play(); -} - -/* -** Handles the Stop bang. -** -*/ -void PlayerITunes::Stop() -{ - m_iTunes->Stop(); -} - -/* -** Handles the Next bang. -** -*/ -void PlayerITunes::Next() -{ - m_iTunes->NextTrack(); -} - -/* -** Handles the Previous bang. -** -*/ -void PlayerITunes::Previous() -{ - m_iTunes->PreviousTrack(); -} - -/* -** Handles the SetPosition bang. -** -*/ -void PlayerITunes::SetPosition(int position) -{ - m_iTunes->put_PlayerPosition((long)position); -} - -/* -** Handles the SetRating bang. -** -*/ -void PlayerITunes::SetRating(int rating) -{ - IITTrack* track; - HRESULT hr = m_iTunes->get_CurrentTrack(&track); - if (SUCCEEDED(hr) && track) - { - rating *= 20; - track->put_Rating((long)rating); - track->Release(); - } -} - -/* -** Handles the SetVolume bang. -** -*/ -void PlayerITunes::SetVolume(int volume) -{ - m_iTunes->put_SoundVolume((long)volume); -} - -/* -** Handles the SetShuffle bang. -** -*/ -void PlayerITunes::SetShuffle(bool state) -{ - IITTrack* track; - HRESULT hr = m_iTunes->get_CurrentTrack(&track); - if (SUCCEEDED(hr) && track) - { - IITPlaylist* playlist; - hr = track->get_Playlist(&playlist); - if (SUCCEEDED(hr)) - { - m_Shuffle = state; - VARIANT_BOOL shuffle = m_Shuffle ? VARIANT_TRUE : VARIANT_FALSE; - playlist->put_Shuffle(shuffle); - - playlist->Release(); - } - - track->Release(); - } -} - -/* -** Handles the SetRepeat bang. -** -*/ -void PlayerITunes::SetRepeat(bool state) -{ - IITTrack* track; - HRESULT hr = m_iTunes->get_CurrentTrack(&track); - if (SUCCEEDED(hr) && track) - { - IITPlaylist* playlist; - hr = track->get_Playlist(&playlist); - if (SUCCEEDED(hr)) - { - m_Repeat = state; - playlist->put_SongRepeat((ITPlaylistRepeatMode)m_Repeat); - - playlist->Release(); - } - - track->Release(); - } -} - -/* -** Handles the ClosePlayer bang. -** -*/ -void PlayerITunes::ClosePlayer() -{ - m_iTunes->Quit(); - Uninitialize(); - SetTimer(m_CallbackWindow, TIMER_CHECKACTIVE, 500, nullptr); -} - -/* -** Handles the OpenPlayer bang. -** -*/ -void PlayerITunes::OpenPlayer(std::wstring& path) -{ - ShellExecute(nullptr, L"open", path.empty() ? L"iTunes.exe" : path.c_str(), nullptr, nullptr, SW_SHOW); -} +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "PlayerITunes.h" + +Player* PlayerITunes::c_Player = nullptr; +extern HINSTANCE g_Instance; + +/* +** Constructor. +** +*/ +PlayerITunes::CEventHandler::CEventHandler(PlayerITunes* player) : + m_Player(player), + m_RefCount(), + m_ConnectionPoint(), + m_ConnectionCookie() +{ + IConnectionPointContainer* icpc; + m_Player->m_iTunes->QueryInterface(IID_IConnectionPointContainer, (void**)&icpc); + icpc->FindConnectionPoint(DIID__IiTunesEvents, &m_ConnectionPoint); + m_ConnectionPoint->Advise(this, &m_ConnectionCookie); + icpc->Release(); +} + +/* +** Destructor. +** +*/ +PlayerITunes::CEventHandler::~CEventHandler() +{ + if (m_ConnectionPoint) + { + m_ConnectionPoint->Unadvise(m_ConnectionCookie); + m_ConnectionPoint->Release(); + } +} + +HRESULT STDMETHODCALLTYPE PlayerITunes::CEventHandler::QueryInterface(REFIID iid, void** ppvObject) +{ + if (iid == IID_IUnknown || iid == IID_IUnknown || iid == DIID__IiTunesEvents) + { + ++m_RefCount; + *ppvObject = this; + return S_OK; + } + + return E_NOINTERFACE; +} + +ULONG STDMETHODCALLTYPE PlayerITunes::CEventHandler::AddRef() +{ + return ++m_RefCount; +} + +ULONG STDMETHODCALLTYPE PlayerITunes::CEventHandler::Release() +{ + return --m_RefCount; +} + +HRESULT STDMETHODCALLTYPE PlayerITunes::CEventHandler::Invoke(DISPID dispidMember, REFIID, LCID, WORD, DISPPARAMS* dispParams, VARIANT*, EXCEPINFO*, UINT*) +{ + switch (dispidMember) + { + case ITEventDatabaseChanged: + m_Player->OnDatabaseChange(); + break; + + case ITEventPlayerPlay: + m_Player->OnStateChange(true); + m_Player->OnTrackChange(); + break; + + case ITEventPlayerStop: + m_Player->OnStateChange(false); + break; + + case ITEventPlayerPlayingTrackChanged: + m_Player->OnTrackChange(); + break; + + case ITEventSoundVolumeChanged: + m_Player->OnVolumeChange(dispParams->rgvarg[0].intVal); + break; + + case ITEventAboutToPromptUserToQuit: + PostMessage(m_Player->m_CallbackWindow, WM_USER, ITEventAboutToPromptUserToQuit, 0); + SetTimer(m_Player->m_CallbackWindow, TIMER_CHECKACTIVE, 500, nullptr); + break; + } + + return S_OK; +} + +/* +** Constructor. +** +*/ +PlayerITunes::PlayerITunes() : Player(), + m_CallbackWindow(), + m_LastCheckTime(0), + m_iTunesActive(false), + m_iTunes(), + m_iTunesEvent() +{ + // Create windows class + WNDCLASS wc = {0}; + wc.hInstance = g_Instance; + wc.lpfnWndProc = WndProc; + wc.lpszClassName = L"NowPlayingITunesClass"; + RegisterClass(&wc); + + // Create callback window + m_CallbackWindow = CreateWindow(L"NowPlayingITunesClass", + L"CallbackWindow", + WS_DISABLED, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + HWND_MESSAGE, + nullptr, + g_Instance, + this); +} + +/* +** Destructor. +** +*/ +PlayerITunes::~PlayerITunes() +{ + c_Player = nullptr; + + DestroyWindow(m_CallbackWindow); + UnregisterClass(L"NowPlayingITunesClass", g_Instance); + + Uninitialize(); +} + +/* +** Creates a shared class object. +** +*/ +Player* PlayerITunes::Create() +{ + if (!c_Player) + { + c_Player = new PlayerITunes(); + } + + return c_Player; +} + +/* +** Initialize iTunes COM interface and event handler. +** +*/ +void PlayerITunes::Initialize() +{ + while (true) + { + HRESULT hr = CoCreateInstance(CLSID_iTunesApp, nullptr, CLSCTX_LOCAL_SERVER, IID_IiTunes, (PVOID*)&m_iTunes); + + if (hr == CO_E_SERVER_EXEC_FAILURE) + { + // This seems to happen if there is a modal dialog being shown in iTunes + // or some other delay has occurred. Retrying should do the trick. + continue; + } + else if (hr != S_OK) + { + // Failed to get hold of iTunes instance via COM + m_iTunes = nullptr; + } + + break; + } + + if (m_iTunes) + { + m_Initialized = true; + + // Set up event handler + m_iTunesEvent = new CEventHandler(this); + + // Try getting track info and player state + ITPlayerState state; + if (SUCCEEDED(m_iTunes->get_PlayerState(&state))) + { + if (state == ITPlayerStateStopped) + { + // Determine if paused of stopped + long position = 0; + m_iTunes->get_PlayerPosition(&position); + + if (position != 0) + { + m_State = STATE_PAUSED; + OnTrackChange(); + } + } + else if (state == ITPlayerStatePlaying) + { + m_State = STATE_PLAYING; + OnTrackChange(); + } + } + + long volume; + m_iTunes->get_SoundVolume(&volume); + m_Volume = (UINT)volume; + + OnDatabaseChange(); + } + else + { + m_Initialized = false; + } +} + +/* +** Close iTunes COM interface. +** +*/ +void PlayerITunes::Uninitialize() +{ + if (m_Initialized) + { + m_Initialized = false; + ClearData(); + + m_iTunes->Release(); + delete m_iTunesEvent; + } +} + +/* +** Window procedure for the callback window. +** +*/ +LRESULT CALLBACK PlayerITunes::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static PlayerITunes* player; + + switch (msg) + { + case WM_CREATE: + // Get pointer to the PlayerITunes class from the CreateWindow call + player = (PlayerITunes*)(((CREATESTRUCT*)lParam)->lpCreateParams); + return 0; + + case WM_USER: + if (wParam == ITEventAboutToPromptUserToQuit) + { + // Event handler calls this through a PostMessage when iTunes quits + player->Uninitialize(); + } + return 0; + + case WM_TIMER: + if (wParam == TIMER_CHECKACTIVE) + { + if (!FindWindow(L"iTunesApp", L"iTunes") && !FindWindow(L"iTunes", L"iTunes")) + { + player->m_iTunesActive = false; + KillTimer(hwnd, TIMER_CHECKACTIVE); + } + } + return 0; + + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } +} + +/* +** Try to find iTunes periodically. +** +*/ +bool PlayerITunes::CheckWindow() +{ + DWORD time = GetTickCount(); + if (time - m_LastCheckTime > 5000) + { + m_LastCheckTime = time; + + if ((FindWindow(L"iTunesApp", L"iTunes") || FindWindow(L"iTunes", L"iTunes")) && !m_iTunesActive) + { + m_iTunesActive = true; + Initialize(); + } + } + + return m_Initialized; +} + +/* +** Called during each update of the main measure. +** +*/ +void PlayerITunes::UpdateData() +{ + if ((m_Initialized || CheckWindow()) && m_State != STATE_STOPPED) + { + long position = 0; + m_iTunes->get_PlayerPosition(&position); + m_Position = (UINT)position; + } +} + +/* +** Called by iTunes event handler when the database is changed. +** +*/ +void PlayerITunes::OnDatabaseChange() +{ + // Check the shuffle state. TODO: Find better way + IITPlaylist* playlist; + HRESULT hr = m_iTunes->get_CurrentPlaylist(&playlist); + if (SUCCEEDED(hr) && playlist) + { + VARIANT_BOOL shuffle; + hr = playlist->get_Shuffle(&shuffle); + if (SUCCEEDED(hr)) + { + m_Shuffle = shuffle != VARIANT_FALSE; + } + + playlist->Release(); + } +} + +/* +** Called by iTunes event handler on track change. +** +*/ +void PlayerITunes::OnTrackChange() +{ + IITTrack* track; + HRESULT hr = m_iTunes->get_CurrentTrack(&track); + if (SUCCEEDED(hr) && track) + { + BSTR tmpStr; + long tmpVal; + + // Get metadata + track->get_Artist(&tmpStr); + tmpStr ? (m_Artist = tmpStr) : m_Artist.clear(); + + track->get_Name(&tmpStr); + tmpStr ? (m_Title = tmpStr) : m_Title.clear(); + + track->get_Album(&tmpStr); + tmpStr ? (m_Album = tmpStr) : m_Album.clear(); + + track->get_Duration(&tmpVal); + m_Duration = (UINT)tmpVal; + + // Rating is 0 - 100, divide to 0 - 5 + track->get_Rating(&tmpVal); + tmpVal /= 20L; + m_Rating = (UINT)tmpVal; + + track->get_TrackNumber(&tmpVal); + m_Number = (UINT)tmpVal; + + track->get_Year(&tmpVal); + m_Year = (UINT)tmpVal; + + IITPlaylist* playlist; + hr = track->get_Playlist(&playlist); + if (SUCCEEDED(hr)) + { + ITPlaylistRepeatMode repeat; + hr = playlist->get_SongRepeat(&repeat); + if (SUCCEEDED(hr)) + { + m_Repeat = repeat != ITPlaylistRepeatModeOff; + } + + playlist->Release(); + } + + IITFileOrCDTrack* file; + hr = track->QueryInterface(&file); + if (SUCCEEDED(hr)) + { + file->get_Location(&tmpStr); + file->Release(); + if (tmpStr && wcscmp(tmpStr, m_FilePath.c_str()) != 0) + { + ++m_TrackCount; + m_FilePath = tmpStr; + + if (m_Measures & MEASURE_COVER) + { + m_CoverPath.clear(); + + // Check for embedded art through iTunes interface + IITArtworkCollection* artworkCollection; + hr = track->get_Artwork(&artworkCollection); + + if (SUCCEEDED(hr)) + { + long count; + artworkCollection->get_Count(&count); + + if (count > 0) + { + IITArtwork* artwork; + hr = artworkCollection->get_Item(1, &artwork); + + if (SUCCEEDED(hr)) + { + _bstr_t coverPath = m_TempCoverPath.c_str(); + hr = artwork->SaveArtworkToFile(coverPath); + if (SUCCEEDED(hr)) + { + m_CoverPath = m_TempCoverPath; + } + + artwork->Release(); + } + } + + artworkCollection->Release(); + } + } + + if (m_Measures & MEASURE_LYRICS) + { + FindLyrics(); + } + } + } + + track->Release(); + } + else + { + ClearData(false); + } +} + +/* +** Called by iTunes event handler on player state change. +** +*/ +void PlayerITunes::OnStateChange(bool playing) +{ + if (playing) + { + m_State = STATE_PLAYING; + } + else + { + long position = 0; + m_iTunes->get_PlayerPosition(&position); + + // Guess if paused or stopped from track time + m_State = (position == 0) ? STATE_STOPPED : STATE_PAUSED; + if (m_State == STATE_STOPPED) + { + ClearData(false); + } + } +} + +/* +** Called by iTunes event handler on volume change. +** +*/ +void PlayerITunes::OnVolumeChange(int volume) +{ + m_Volume = volume; +} + +/* +** Handles the Pause bang. +** +*/ +void PlayerITunes::Pause() +{ + m_iTunes->Pause(); +} + +/* +** Handles the Play bang. +** +*/ +void PlayerITunes::Play() +{ + m_iTunes->Play(); +} + +/* +** Handles the Stop bang. +** +*/ +void PlayerITunes::Stop() +{ + m_iTunes->Stop(); +} + +/* +** Handles the Next bang. +** +*/ +void PlayerITunes::Next() +{ + m_iTunes->NextTrack(); +} + +/* +** Handles the Previous bang. +** +*/ +void PlayerITunes::Previous() +{ + m_iTunes->PreviousTrack(); +} + +/* +** Handles the SetPosition bang. +** +*/ +void PlayerITunes::SetPosition(int position) +{ + m_iTunes->put_PlayerPosition((long)position); +} + +/* +** Handles the SetRating bang. +** +*/ +void PlayerITunes::SetRating(int rating) +{ + IITTrack* track; + HRESULT hr = m_iTunes->get_CurrentTrack(&track); + if (SUCCEEDED(hr) && track) + { + rating *= 20; + track->put_Rating((long)rating); + track->Release(); + } +} + +/* +** Handles the SetVolume bang. +** +*/ +void PlayerITunes::SetVolume(int volume) +{ + m_iTunes->put_SoundVolume((long)volume); +} + +/* +** Handles the SetShuffle bang. +** +*/ +void PlayerITunes::SetShuffle(bool state) +{ + IITTrack* track; + HRESULT hr = m_iTunes->get_CurrentTrack(&track); + if (SUCCEEDED(hr) && track) + { + IITPlaylist* playlist; + hr = track->get_Playlist(&playlist); + if (SUCCEEDED(hr)) + { + m_Shuffle = state; + VARIANT_BOOL shuffle = m_Shuffle ? VARIANT_TRUE : VARIANT_FALSE; + playlist->put_Shuffle(shuffle); + + playlist->Release(); + } + + track->Release(); + } +} + +/* +** Handles the SetRepeat bang. +** +*/ +void PlayerITunes::SetRepeat(bool state) +{ + IITTrack* track; + HRESULT hr = m_iTunes->get_CurrentTrack(&track); + if (SUCCEEDED(hr) && track) + { + IITPlaylist* playlist; + hr = track->get_Playlist(&playlist); + if (SUCCEEDED(hr)) + { + m_Repeat = state; + playlist->put_SongRepeat((ITPlaylistRepeatMode)m_Repeat); + + playlist->Release(); + } + + track->Release(); + } +} + +/* +** Handles the ClosePlayer bang. +** +*/ +void PlayerITunes::ClosePlayer() +{ + m_iTunes->Quit(); + Uninitialize(); + SetTimer(m_CallbackWindow, TIMER_CHECKACTIVE, 500, nullptr); +} + +/* +** Handles the OpenPlayer bang. +** +*/ +void PlayerITunes::OpenPlayer(std::wstring& path) +{ + ShellExecute(nullptr, L"open", path.empty() ? L"iTunes.exe" : path.c_str(), nullptr, nullptr, SW_SHOW); +} diff --git a/Plugins/PluginNowPlaying/PlayerITunes.h b/Plugins/PluginNowPlaying/PlayerITunes.h index 70b0249c..5f61afa8 100644 --- a/Plugins/PluginNowPlaying/PlayerITunes.h +++ b/Plugins/PluginNowPlaying/PlayerITunes.h @@ -1,96 +1,96 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __PLAYERITUNES_H__ -#define __PLAYERITUNES_H__ - -#include "Player.h" -#include "iTunes/iTunesCOMInterface.h" - -const int TIMER_CHECKACTIVE = 1; - -class PlayerITunes : public Player -{ -public: - virtual ~PlayerITunes(); - - static Player* Create(); - - virtual void UpdateData(); - - virtual void Pause(); - virtual void Play(); - virtual void Stop(); - virtual void Next(); - virtual void Previous(); - virtual void SetPosition(int position); - virtual void SetRating(int rating); - virtual void SetVolume(int volume); - virtual void SetShuffle(bool state); - virtual void SetRepeat(bool state); - virtual void ClosePlayer(); - virtual void OpenPlayer(std::wstring& path); - -protected: - PlayerITunes(); - -private: - class CEventHandler : public _IiTunesEvents - { - public: - CEventHandler(PlayerITunes* player); - ~CEventHandler(); - - // IUnknown - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - - // IDispatch - HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT*) { return E_NOTIMPL; } - HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT, LCID, ITypeInfo**) { return E_NOTIMPL; } - HRESULT STDMETHODCALLTYPE GetIDsOfNames(const IID&, LPOLESTR*, UINT, LCID, DISPID*) { return E_NOTIMPL; } - HRESULT STDMETHODCALLTYPE Invoke(DISPID dispidMember, REFIID, LCID, WORD, DISPPARAMS* pDispParams, VARIANT*, EXCEPINFO*, UINT*); - - private: - ULONG m_RefCount; - PlayerITunes* m_Player; - IConnectionPoint* m_ConnectionPoint; - DWORD m_ConnectionCookie; - }; - - void Initialize(); - void Uninitialize(); - void OnDatabaseChange(); - void OnTrackChange(); - void OnStateChange(bool playing); - void OnVolumeChange(int volume); - bool CheckWindow(); - - static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - - static Player* c_Player; - - HWND m_CallbackWindow; - DWORD m_LastCheckTime; - bool m_iTunesActive; - IiTunes* m_iTunes; - CEventHandler* m_iTunesEvent; -}; - -#endif +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __PLAYERITUNES_H__ +#define __PLAYERITUNES_H__ + +#include "Player.h" +#include "iTunes/iTunesCOMInterface.h" + +const int TIMER_CHECKACTIVE = 1; + +class PlayerITunes : public Player +{ +public: + virtual ~PlayerITunes(); + + static Player* Create(); + + virtual void UpdateData(); + + virtual void Pause(); + virtual void Play(); + virtual void Stop(); + virtual void Next(); + virtual void Previous(); + virtual void SetPosition(int position); + virtual void SetRating(int rating); + virtual void SetVolume(int volume); + virtual void SetShuffle(bool state); + virtual void SetRepeat(bool state); + virtual void ClosePlayer(); + virtual void OpenPlayer(std::wstring& path); + +protected: + PlayerITunes(); + +private: + class CEventHandler : public _IiTunesEvents + { + public: + CEventHandler(PlayerITunes* player); + ~CEventHandler(); + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + // IDispatch + HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT*) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT, LCID, ITypeInfo**) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE GetIDsOfNames(const IID&, LPOLESTR*, UINT, LCID, DISPID*) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE Invoke(DISPID dispidMember, REFIID, LCID, WORD, DISPPARAMS* pDispParams, VARIANT*, EXCEPINFO*, UINT*); + + private: + ULONG m_RefCount; + PlayerITunes* m_Player; + IConnectionPoint* m_ConnectionPoint; + DWORD m_ConnectionCookie; + }; + + void Initialize(); + void Uninitialize(); + void OnDatabaseChange(); + void OnTrackChange(); + void OnStateChange(bool playing); + void OnVolumeChange(int volume); + bool CheckWindow(); + + static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + + static Player* c_Player; + + HWND m_CallbackWindow; + DWORD m_LastCheckTime; + bool m_iTunesActive; + IiTunes* m_iTunes; + CEventHandler* m_iTunesEvent; +}; + +#endif diff --git a/Plugins/PluginNowPlaying/PlayerSpotify.cpp b/Plugins/PluginNowPlaying/PlayerSpotify.cpp index 6fbebb4f..43031e3a 100644 --- a/Plugins/PluginNowPlaying/PlayerSpotify.cpp +++ b/Plugins/PluginNowPlaying/PlayerSpotify.cpp @@ -1,234 +1,234 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "PlayerSpotify.h" - -Player* PlayerSpotify::c_Player = nullptr; - -/* -** Constructor. -** -*/ -PlayerSpotify::PlayerSpotify() : Player(), - m_Window(), - m_LastCheckTime(0) -{ -} - -/* -** Destructor. -** -*/ -PlayerSpotify::~PlayerSpotify() -{ - c_Player = nullptr; -} - -/* -** Creates a shared class object. -** -*/ -Player* PlayerSpotify::Create() -{ - if (!c_Player) - { - c_Player = new PlayerSpotify(); - } - - return c_Player; -} - -/* -** Try to find Spotify periodically. -** -*/ -bool PlayerSpotify::CheckWindow() -{ - DWORD time = GetTickCount(); - - // Try to find Spotify window every 5 seconds - if (time - m_LastCheckTime > 5000) - { - m_LastCheckTime = time; - - m_Window = FindWindow(L"SpotifyMainWindow", nullptr); - if (m_Window) - { - m_Initialized = true; - } - } - - return m_Initialized; -} - -/* -** Called during each update of the main measure. -** -*/ -void PlayerSpotify::UpdateData() -{ - if (m_Initialized || CheckWindow()) - { - // Parse title and artist from window title - WCHAR buffer[256]; - if (GetWindowText(m_Window, buffer, 256) > 10) - { - std::wstring title = &buffer[10]; // Skip "Spotify - " - - std::wstring::size_type pos = title.find(L" \u2013 "); - if (pos != std::wstring::npos) - { - std::wstring artist(title, 0, pos); - pos += 3; // Skip " - " - std::wstring track(title, pos); - - if (track != m_Title || artist != m_Artist) - { - m_State = STATE_PLAYING; - m_Title = track; - m_Artist = artist; - ++m_TrackCount; - - if (m_Measures & MEASURE_LYRICS) - { - FindLyrics(); - } - } - return; - } - } - else if (IsWindow(m_Window)) - { - m_State = STATE_PAUSED; - } - else - { - ClearData(); - m_Initialized = false; - } - } -} - -/* -** Handles the Play bang. -** -*/ -void PlayerSpotify::Play() -{ - SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_PLAYPAUSE); -} - -/* -** Handles the Stop bang. -** -*/ -void PlayerSpotify::Stop() -{ - SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_STOP); -} - -/* -** Handles the Next bang. -** -*/ -void PlayerSpotify::Next() -{ - SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_NEXT); -} - -/* -** Handles the Previous bang. -** -*/ -void PlayerSpotify::Previous() -{ - SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_PREV); -} - - -/* -** Handles the ClosePlayer bang. -** -*/ -void PlayerSpotify::ClosePlayer() -{ - // A little harsh... - DWORD pID; - GetWindowThreadProcessId(m_Window, &pID); - HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pID); - if (hProcess) - { - TerminateProcess(hProcess, 0); - CloseHandle(hProcess); - } -} - -/* -** Handles the OpenPlayer bang. -** -*/ -void PlayerSpotify::OpenPlayer(std::wstring& path) -{ - if (!m_Initialized) - { - if (path.empty()) - { - // Gotta figure out where Winamp is located at - HKEY hKey; - RegOpenKeyEx(HKEY_CLASSES_ROOT, - L"spotify\\DefaultIcon", - 0, - KEY_QUERY_VALUE, - &hKey); - - DWORD size = 512; - WCHAR* data = new WCHAR[size]; - DWORD type = 0; - - if (RegQueryValueEx(hKey, - nullptr, - nullptr, - (LPDWORD)&type, - (LPBYTE)data, - (LPDWORD)&size) == ERROR_SUCCESS) - { - if (type == REG_SZ) - { - path = data; - path.erase(0, 1); // Get rid of the leading quote - path.resize(path.length() - 3); // And the ",0 at the end - ShellExecute(nullptr, L"open", path.c_str(), nullptr, nullptr, SW_SHOW); - } - } - - delete [] data; - RegCloseKey(hKey); - } - else - { - ShellExecute(nullptr, L"open", path.c_str(), nullptr, nullptr, SW_SHOW); - } - } - else - { - // Already active, restore the window - ShowWindow(m_Window, SW_SHOWNORMAL); - BringWindowToTop(m_Window); - } -} +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "PlayerSpotify.h" + +Player* PlayerSpotify::c_Player = nullptr; + +/* +** Constructor. +** +*/ +PlayerSpotify::PlayerSpotify() : Player(), + m_Window(), + m_LastCheckTime(0) +{ +} + +/* +** Destructor. +** +*/ +PlayerSpotify::~PlayerSpotify() +{ + c_Player = nullptr; +} + +/* +** Creates a shared class object. +** +*/ +Player* PlayerSpotify::Create() +{ + if (!c_Player) + { + c_Player = new PlayerSpotify(); + } + + return c_Player; +} + +/* +** Try to find Spotify periodically. +** +*/ +bool PlayerSpotify::CheckWindow() +{ + DWORD time = GetTickCount(); + + // Try to find Spotify window every 5 seconds + if (time - m_LastCheckTime > 5000) + { + m_LastCheckTime = time; + + m_Window = FindWindow(L"SpotifyMainWindow", nullptr); + if (m_Window) + { + m_Initialized = true; + } + } + + return m_Initialized; +} + +/* +** Called during each update of the main measure. +** +*/ +void PlayerSpotify::UpdateData() +{ + if (m_Initialized || CheckWindow()) + { + // Parse title and artist from window title + WCHAR buffer[256]; + if (GetWindowText(m_Window, buffer, 256) > 10) + { + std::wstring title = &buffer[10]; // Skip "Spotify - " + + std::wstring::size_type pos = title.find(L" \u2013 "); + if (pos != std::wstring::npos) + { + std::wstring artist(title, 0, pos); + pos += 3; // Skip " - " + std::wstring track(title, pos); + + if (track != m_Title || artist != m_Artist) + { + m_State = STATE_PLAYING; + m_Title = track; + m_Artist = artist; + ++m_TrackCount; + + if (m_Measures & MEASURE_LYRICS) + { + FindLyrics(); + } + } + return; + } + } + else if (IsWindow(m_Window)) + { + m_State = STATE_PAUSED; + } + else + { + ClearData(); + m_Initialized = false; + } + } +} + +/* +** Handles the Play bang. +** +*/ +void PlayerSpotify::Play() +{ + SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_PLAYPAUSE); +} + +/* +** Handles the Stop bang. +** +*/ +void PlayerSpotify::Stop() +{ + SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_STOP); +} + +/* +** Handles the Next bang. +** +*/ +void PlayerSpotify::Next() +{ + SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_NEXT); +} + +/* +** Handles the Previous bang. +** +*/ +void PlayerSpotify::Previous() +{ + SendMessage(m_Window, WM_APPCOMMAND, 0, SPOTIFY_PREV); +} + + +/* +** Handles the ClosePlayer bang. +** +*/ +void PlayerSpotify::ClosePlayer() +{ + // A little harsh... + DWORD pID; + GetWindowThreadProcessId(m_Window, &pID); + HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pID); + if (hProcess) + { + TerminateProcess(hProcess, 0); + CloseHandle(hProcess); + } +} + +/* +** Handles the OpenPlayer bang. +** +*/ +void PlayerSpotify::OpenPlayer(std::wstring& path) +{ + if (!m_Initialized) + { + if (path.empty()) + { + // Gotta figure out where Winamp is located at + HKEY hKey; + RegOpenKeyEx(HKEY_CLASSES_ROOT, + L"spotify\\DefaultIcon", + 0, + KEY_QUERY_VALUE, + &hKey); + + DWORD size = 512; + WCHAR* data = new WCHAR[size]; + DWORD type = 0; + + if (RegQueryValueEx(hKey, + nullptr, + nullptr, + (LPDWORD)&type, + (LPBYTE)data, + (LPDWORD)&size) == ERROR_SUCCESS) + { + if (type == REG_SZ) + { + path = data; + path.erase(0, 1); // Get rid of the leading quote + path.resize(path.length() - 3); // And the ",0 at the end + ShellExecute(nullptr, L"open", path.c_str(), nullptr, nullptr, SW_SHOW); + } + } + + delete [] data; + RegCloseKey(hKey); + } + else + { + ShellExecute(nullptr, L"open", path.c_str(), nullptr, nullptr, SW_SHOW); + } + } + else + { + // Already active, restore the window + ShowWindow(m_Window, SW_SHOWNORMAL); + BringWindowToTop(m_Window); + } +} diff --git a/Plugins/PluginNowPlaying/PlayerSpotify.h b/Plugins/PluginNowPlaying/PlayerSpotify.h index b8bbbe9d..ff6bc2ad 100644 --- a/Plugins/PluginNowPlaying/PlayerSpotify.h +++ b/Plugins/PluginNowPlaying/PlayerSpotify.h @@ -1,63 +1,63 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __PLAYERSPOTIFY_H__ -#define __PLAYERSPOTIFY_H__ - -#include "Player.h" - -class PlayerSpotify : public Player -{ -public: - virtual ~PlayerSpotify(); - - static Player* Create(); - - virtual void Pause() { return Play(); } - virtual void Play(); - virtual void Stop(); - virtual void Next(); - virtual void Previous(); - virtual void ClosePlayer(); - virtual void OpenPlayer(std::wstring& path); - virtual void UpdateData(); - -protected: - PlayerSpotify(); - -private: - enum SPOTIFYCOMMAND - { - SPOTIFY_MUTE = 524288, - SPOTIFY_VOLUMEDOWN = 589824, - SPOTIFY_VOLUMEUP = 655360, - SPOTIFY_NEXT = 720896, - SPOTIFY_PREV = 786432, - SPOTIFY_STOP = 851968, - SPOTIFY_PLAYPAUSE = 917504 - }; - - bool CheckWindow(); - - static Player* c_Player; - - HWND m_Window; - DWORD m_LastCheckTime; -}; - -#endif +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __PLAYERSPOTIFY_H__ +#define __PLAYERSPOTIFY_H__ + +#include "Player.h" + +class PlayerSpotify : public Player +{ +public: + virtual ~PlayerSpotify(); + + static Player* Create(); + + virtual void Pause() { return Play(); } + virtual void Play(); + virtual void Stop(); + virtual void Next(); + virtual void Previous(); + virtual void ClosePlayer(); + virtual void OpenPlayer(std::wstring& path); + virtual void UpdateData(); + +protected: + PlayerSpotify(); + +private: + enum SPOTIFYCOMMAND + { + SPOTIFY_MUTE = 524288, + SPOTIFY_VOLUMEDOWN = 589824, + SPOTIFY_VOLUMEUP = 655360, + SPOTIFY_NEXT = 720896, + SPOTIFY_PREV = 786432, + SPOTIFY_STOP = 851968, + SPOTIFY_PLAYPAUSE = 917504 + }; + + bool CheckWindow(); + + static Player* c_Player; + + HWND m_Window; + DWORD m_LastCheckTime; +}; + +#endif diff --git a/Plugins/PluginNowPlaying/PlayerWLM.cpp b/Plugins/PluginNowPlaying/PlayerWLM.cpp index 071f64ae..5acb9b3e 100644 --- a/Plugins/PluginNowPlaying/PlayerWLM.cpp +++ b/Plugins/PluginNowPlaying/PlayerWLM.cpp @@ -1,207 +1,207 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "PlayerWLM.h" - -Player* PlayerWLM::c_Player = nullptr; -extern HINSTANCE g_Instance; - -// This player emulates the MSN/WLM Messenger 'Listening to' interface, which is -// supported by OpenPandora, Last.fm, Media Player Classic, TTPlayer, Zune, etc. - -/* -** Constructor. -** -*/ -PlayerWLM::PlayerWLM() : Player(), - m_Window() -{ - // Create windows class - WNDCLASS wc = {0}; - wc.hInstance = g_Instance; - wc.lpfnWndProc = WndProc; - wc.lpszClassName = L"MsnMsgrUIManager"; - RegisterClass(&wc); - - // Create dummy window - m_Window = CreateWindow(L"MsnMsgrUIManager", - L"", - WS_DISABLED, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - nullptr, - nullptr, - g_Instance, - this); - - m_Initialized = true; -} - -/* -** Destructor. -** -*/ -PlayerWLM::~PlayerWLM() -{ - c_Player = nullptr; - DestroyWindow(m_Window); - UnregisterClass(L"MsnMsgrUIManager", g_Instance); -} - -/* -** Creates a shared class object. -** -*/ -Player* PlayerWLM::Create() -{ - if (!c_Player) - { - c_Player = new PlayerWLM(); - } - - return c_Player; -} - -LRESULT CALLBACK PlayerWLM::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static PlayerWLM* player; - - switch (msg) - { - case WM_CREATE: - { - // Get pointer to the PlayerWLM class from the CreateWindow call - player = (PlayerWLM*)((CREATESTRUCT*)lParam)->lpCreateParams; - return 0; - } - - case WM_COPYDATA: - { - PCOPYDATASTRUCT cds = (PCOPYDATASTRUCT)lParam; - if (cds->dwData != 1351) return 0; - - // lpData: \0Music\0\0\0\0<artist>\0<album>\0 - std::wstring data = (WCHAR*)cds->lpData; - - // Some players include player name in the beginning. Skip that. - std::wstring::size_type len = data.find(L"\\0Music\\0"); - len += 9; - data.erase(0, len); // Get rid of \0Music\0 - - bool playing = (data[0] == L'1'); - - if (playing) - { - ++player->m_TrackCount; - player->m_State = STATE_PLAYING; - data.erase(0, 3); // Get rid of the status - - // TODO: Handle invalid - len = data.find_first_of(L'\\'); - len += 2; - data.erase(0, len); // Get rid of the format - - len = data.find_first_of(L'\\'); - player->m_Title.assign(data, 0, len); - len += 2; - data.erase(0, len); - - len = data.find_first_of(L'\\'); - player->m_Artist.assign(data, 0, len); - len += 2; - data.erase(0, len); - - len = data.find_first_of(L'\\'); - player->m_Album.assign(data, 0, len); - - if (player->m_Measures & MEASURE_LYRICS) - { - player->FindLyrics(); - } - } - else - { - player->ClearData(false); - } - - return 0; - } - } - - return DefWindowProc(hWnd, msg, wParam, lParam); -} - -void PlayerWLM::SendKeyInput(WORD key) -{ - KEYBDINPUT kbi = {0}; - kbi.wVk = key; - kbi.dwExtraInfo = (ULONG_PTR)GetMessageExtraInfo(); - - INPUT input = {0}; - input.type = INPUT_KEYBOARD; - input.ki = kbi; - - SendInput(1, &input, sizeof(INPUT)); -} - -/* -** Called during each update of the main measure. -** -*/ -void PlayerWLM::UpdateData() -{ -} - -/* -** Handles the Play bang. -** -*/ -void PlayerWLM::Play() -{ - SendKeyInput(VK_MEDIA_PLAY_PAUSE); -} - -/* -** Handles the Stop bang. -** -*/ -void PlayerWLM::Stop() -{ - SendKeyInput(VK_MEDIA_STOP); -} - -/* -** Handles the Next bang. -** -*/ -void PlayerWLM::Next() -{ - SendKeyInput(VK_MEDIA_NEXT_TRACK); -} - -/* -** Handles the Previous bang. -** -*/ -void PlayerWLM::Previous() -{ - SendKeyInput(VK_MEDIA_PREV_TRACK); -} +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "PlayerWLM.h" + +Player* PlayerWLM::c_Player = nullptr; +extern HINSTANCE g_Instance; + +// This player emulates the MSN/WLM Messenger 'Listening to' interface, which is +// supported by OpenPandora, Last.fm, Media Player Classic, TTPlayer, Zune, etc. + +/* +** Constructor. +** +*/ +PlayerWLM::PlayerWLM() : Player(), + m_Window() +{ + // Create windows class + WNDCLASS wc = {0}; + wc.hInstance = g_Instance; + wc.lpfnWndProc = WndProc; + wc.lpszClassName = L"MsnMsgrUIManager"; + RegisterClass(&wc); + + // Create dummy window + m_Window = CreateWindow(L"MsnMsgrUIManager", + L"", + WS_DISABLED, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + nullptr, + nullptr, + g_Instance, + this); + + m_Initialized = true; +} + +/* +** Destructor. +** +*/ +PlayerWLM::~PlayerWLM() +{ + c_Player = nullptr; + DestroyWindow(m_Window); + UnregisterClass(L"MsnMsgrUIManager", g_Instance); +} + +/* +** Creates a shared class object. +** +*/ +Player* PlayerWLM::Create() +{ + if (!c_Player) + { + c_Player = new PlayerWLM(); + } + + return c_Player; +} + +LRESULT CALLBACK PlayerWLM::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static PlayerWLM* player; + + switch (msg) + { + case WM_CREATE: + { + // Get pointer to the PlayerWLM class from the CreateWindow call + player = (PlayerWLM*)((CREATESTRUCT*)lParam)->lpCreateParams; + return 0; + } + + case WM_COPYDATA: + { + PCOPYDATASTRUCT cds = (PCOPYDATASTRUCT)lParam; + if (cds->dwData != 1351) return 0; + + // lpData: \0Music\0<status>\0<format>\0<title>\0<artist>\0<album>\0 + std::wstring data = (WCHAR*)cds->lpData; + + // Some players include player name in the beginning. Skip that. + std::wstring::size_type len = data.find(L"\\0Music\\0"); + len += 9; + data.erase(0, len); // Get rid of \0Music\0 + + bool playing = (data[0] == L'1'); + + if (playing) + { + ++player->m_TrackCount; + player->m_State = STATE_PLAYING; + data.erase(0, 3); // Get rid of the status + + // TODO: Handle invalid + len = data.find_first_of(L'\\'); + len += 2; + data.erase(0, len); // Get rid of the format + + len = data.find_first_of(L'\\'); + player->m_Title.assign(data, 0, len); + len += 2; + data.erase(0, len); + + len = data.find_first_of(L'\\'); + player->m_Artist.assign(data, 0, len); + len += 2; + data.erase(0, len); + + len = data.find_first_of(L'\\'); + player->m_Album.assign(data, 0, len); + + if (player->m_Measures & MEASURE_LYRICS) + { + player->FindLyrics(); + } + } + else + { + player->ClearData(false); + } + + return 0; + } + } + + return DefWindowProc(hWnd, msg, wParam, lParam); +} + +void PlayerWLM::SendKeyInput(WORD key) +{ + KEYBDINPUT kbi = {0}; + kbi.wVk = key; + kbi.dwExtraInfo = (ULONG_PTR)GetMessageExtraInfo(); + + INPUT input = {0}; + input.type = INPUT_KEYBOARD; + input.ki = kbi; + + SendInput(1, &input, sizeof(INPUT)); +} + +/* +** Called during each update of the main measure. +** +*/ +void PlayerWLM::UpdateData() +{ +} + +/* +** Handles the Play bang. +** +*/ +void PlayerWLM::Play() +{ + SendKeyInput(VK_MEDIA_PLAY_PAUSE); +} + +/* +** Handles the Stop bang. +** +*/ +void PlayerWLM::Stop() +{ + SendKeyInput(VK_MEDIA_STOP); +} + +/* +** Handles the Next bang. +** +*/ +void PlayerWLM::Next() +{ + SendKeyInput(VK_MEDIA_NEXT_TRACK); +} + +/* +** Handles the Previous bang. +** +*/ +void PlayerWLM::Previous() +{ + SendKeyInput(VK_MEDIA_PREV_TRACK); +} diff --git a/Plugins/PluginNowPlaying/PlayerWLM.h b/Plugins/PluginNowPlaying/PlayerWLM.h index 56ebfedd..741e8ad2 100644 --- a/Plugins/PluginNowPlaying/PlayerWLM.h +++ b/Plugins/PluginNowPlaying/PlayerWLM.h @@ -1,51 +1,51 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __PLAYERWLM_H__ -#define __PLAYERWLM_H__ - -#include "Player.h" - -class PlayerWLM : public Player -{ -public: - virtual ~PlayerWLM(); - - static Player* Create(); - - virtual void UpdateData(); - - virtual void Pause() { return Play(); } - virtual void Play(); - virtual void Stop(); - virtual void Next(); - virtual void Previous(); - -protected: - PlayerWLM(); - -private: - static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - void SendKeyInput(WORD key); - - static Player* c_Player; - - HWND m_Window; -}; - -#endif +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __PLAYERWLM_H__ +#define __PLAYERWLM_H__ + +#include "Player.h" + +class PlayerWLM : public Player +{ +public: + virtual ~PlayerWLM(); + + static Player* Create(); + + virtual void UpdateData(); + + virtual void Pause() { return Play(); } + virtual void Play(); + virtual void Stop(); + virtual void Next(); + virtual void Previous(); + +protected: + PlayerWLM(); + +private: + static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + void SendKeyInput(WORD key); + + static Player* c_Player; + + HWND m_Window; +}; + +#endif diff --git a/Plugins/PluginNowPlaying/PlayerWMP.cpp b/Plugins/PluginNowPlaying/PlayerWMP.cpp index 3ccad5b3..598c2644 100644 --- a/Plugins/PluginNowPlaying/PlayerWMP.cpp +++ b/Plugins/PluginNowPlaying/PlayerWMP.cpp @@ -1,657 +1,657 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "PlayerWMP.h" - -Player* PlayerWMP::c_Player = nullptr; -extern HINSTANCE g_Instance; - -namespace { - -// Definitions of ATL stuff we need to avoid dependency on atlbase.h (which is not included in free -// versions of Visual Studio). - -MIDL_INTERFACE("B6EA2050-048A-11d1-82B9-00C04FB9942E") -IAxWinHostWindow : public IUnknown -{ -public: - virtual HRESULT STDMETHODCALLTYPE CreateControl( - LPCOLESTR lpTricsData, HWND hWnd, IStream *pStream) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateControlEx( - LPCOLESTR lpszTricsData, HWND hWnd, IStream* pStream, IUnknown** ppUnk, REFIID iidAdvise, - IUnknown* punkSink) = 0; - - virtual HRESULT STDMETHODCALLTYPE AttachControl(IUnknown* pUnkControl, HWND hWnd) = 0; - virtual HRESULT STDMETHODCALLTYPE QueryControl(REFIID riid, void** ppvObject) = 0; - virtual HRESULT STDMETHODCALLTYPE SetExternalDispatch(IDispatch* pDisp) = 0; - virtual HRESULT STDMETHODCALLTYPE SetExternalUIHandler(void* pDisp) = 0; -}; - -typedef BOOL (WINAPI * AtlAxWinInitFunc)(); -typedef HRESULT (WINAPI * AtlAxGetControlFunc)(HWND h, IUnknown** pp); -typedef HRESULT (WINAPI * AtlAxGetHostFunc)(HWND h, IUnknown** pp); - -HMODULE InitializeAtlLibrary() -{ - static HMODULE s_ATL = LoadLibrary(L"atl"); - if (s_ATL) - { - auto atlAxWinInit = (AtlAxWinInitFunc)GetProcAddress(s_ATL, "AtlAxWinInit"); - atlAxWinInit(); - } - return s_ATL; -} - -} // namespace - -// -// PlayerWMP::CRemoteHost -// - -PlayerWMP::CRemoteHost::CRemoteHost() : - m_Player(), - m_RefCount(0) -{ -} - -PlayerWMP::CRemoteHost::~CRemoteHost() -{ -} - -ULONG STDMETHODCALLTYPE PlayerWMP::CRemoteHost::AddRef() -{ - ++m_RefCount; - return m_RefCount; -} - -ULONG STDMETHODCALLTYPE PlayerWMP::CRemoteHost::Release() -{ - --m_RefCount; - if (m_RefCount == 0) - { - delete this; - return 0; - } - return m_RefCount; -} - -HRESULT STDMETHODCALLTYPE PlayerWMP::CRemoteHost::QueryInterface(IID const& riid, void** object) -{ - if (!object) - { - return E_POINTER; - } - - if (riid == __uuidof(IUnknown) || - riid == __uuidof(IServiceProvider)) - { - *object = (IServiceProvider*)this; - } - else if (riid == __uuidof(IWMPRemoteMediaServices)) - { - *object = (IWMPRemoteMediaServices*)this; - } - else if (riid == __uuidof(IWMPEvents)) - { - *object = (IWMPEvents*)this; - } - else - { - *object = nullptr; - return E_NOINTERFACE; - } - - AddRef(); - return S_OK; -} - -HRESULT PlayerWMP::CRemoteHost::QueryService(REFGUID guidService, REFIID riid, void** ppv) -{ - return QueryInterface(riid, ppv); -} - -HRESULT PlayerWMP::CRemoteHost::GetServiceType(BSTR* pbstrType) -{ - *pbstrType = SysAllocString(L"RemoteNoDialogs"); - return *pbstrType ? S_OK : E_POINTER; -} - -HRESULT PlayerWMP::CRemoteHost::GetApplicationName(BSTR* pbstrName) -{ - *pbstrName = SysAllocString(L"Rainmeter NowPlaying"); - return *pbstrName ? S_OK : E_POINTER; -} - -HRESULT PlayerWMP::CRemoteHost::GetScriptableObject(BSTR* pbstrName, IDispatch** ppDispatch) -{ - if (pbstrName) - { - *pbstrName = nullptr; - } - if (ppDispatch) - { - *ppDispatch = nullptr; - } - return E_NOTIMPL; -} - -HRESULT PlayerWMP::CRemoteHost::GetCustomUIMode(BSTR* pbstrFile) -{ - return E_POINTER; -} - -/* -** Called when playing track changes. -** -*/ -void PlayerWMP::CRemoteHost::CurrentItemChange(IDispatch* pdispMedia) -{ - m_Player->m_TrackChanged = true; -} - -/* -** Called when play state changes. -** -*/ -void PlayerWMP::CRemoteHost::PlayStateChange(long NewState) -{ - switch (NewState) - { - case wmppsStopped: - case wmppsMediaEnded: - m_Player->ClearData(false); - break; - - case wmppsPaused: - m_Player->m_State = STATE_PAUSED; - break; - - case wmppsPlaying: - if (m_Player->m_State == STATE_STOPPED) - { - m_Player->m_TrackChanged = true; - } - m_Player->m_State = STATE_PLAYING; - break; - - default: - break; - } -} - -/* -** Called when WMP quits. -** -*/ -void PlayerWMP::CRemoteHost::SwitchedToControl() -{ - m_Player->ClearData(); - m_Player->Uninitialize(); -} - -// -// PlayerWMP -// - -PlayerWMP::PlayerWMP() : Player(), - m_TrackChanged(false), - m_Window(), - m_LastCheckTime(0), - m_ConnectionCookie() -{ -} - -PlayerWMP::~PlayerWMP() -{ - c_Player = nullptr; - Uninitialize(); -} - -/* -** Creates a shared class object. -** -*/ -Player* PlayerWMP::Create() -{ - if (!c_Player) - { - c_Player = new PlayerWMP(); - } - - return c_Player; -} - -/* -** Set up the COM interface with WMP. -** -*/ -void PlayerWMP::Initialize() -{ - HMODULE atl = InitializeAtlLibrary(); - if (!atl) - { - RmLog(LOG_ERROR, L"NowPlaying: ATL not found"); - return; - } - - auto atlAxGetControl = (AtlAxGetControlFunc)GetProcAddress(atl, "AtlAxGetControl"); - auto atlAxGetHost = (AtlAxGetHostFunc)GetProcAddress(atl, "AtlAxGetHost"); - - WNDCLASS wc = {0}; - wc.hInstance = g_Instance; - wc.lpfnWndProc = DefWindowProc; - wc.lpszClassName = L"NowPlayingWMP"; - RegisterClass(&wc); - - // Create the container window and the ATL host window. - m_Window = CreateWindow( - L"NowPlayingWMP", L"", - WS_DISABLED, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - nullptr, nullptr, g_Instance, nullptr); - - HWND window = CreateWindow( - L"AtlAxWin", L"", - WS_DISABLED | WS_CHILD, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - m_Window, nullptr, g_Instance, nullptr); - - Microsoft::WRL::ComPtr<IUnknown> axHost; - Microsoft::WRL::ComPtr<IObjectWithSite> hostObject; - HRESULT hr = atlAxGetHost(window, axHost.GetAddressOf()); - if (SUCCEEDED(hr)) - { - hr = axHost.As(&hostObject); - } - - Microsoft::WRL::ComPtr<CRemoteHost> remoteHost(new CRemoteHost()); - if (SUCCEEDED(hr)) - { - remoteHost->m_Player = this; - hr = hostObject->SetSite((IWMPRemoteMediaServices*)remoteHost.Get()); - } - - Microsoft::WRL::ComPtr<IAxWinHostWindow> axWinHostWindow; - if (SUCCEEDED(hr)) - { - hr = axHost.As(&axWinHostWindow); - } - - if (SUCCEEDED(hr)) - { - hr = axWinHostWindow->CreateControl(L"{6BF52A52-394A-11D3-B153-00C04F79FAA6}", window, nullptr); - } - - Microsoft::WRL::ComPtr<IUnknown> axControl; - if (SUCCEEDED(hr)) - { - hr = atlAxGetControl(window, axControl.GetAddressOf()); - } - - if (SUCCEEDED(hr)) - { - hr = axControl.As(&m_IPlayer); - } - - // Connect the event interface. - Microsoft::WRL::ComPtr<IConnectionPointContainer> wmpPlayerConnectionContainer; - if (SUCCEEDED(hr)) - { - hr = m_IPlayer.As(&wmpPlayerConnectionContainer); - } - - if (SUCCEEDED(hr)) - { - hr = wmpPlayerConnectionContainer->FindConnectionPoint( - __uuidof(IWMPEvents), m_IConnectionPoint.GetAddressOf()); - } - - if (SUCCEEDED(hr)) - { - hr = m_IConnectionPoint->Advise(remoteHost->GetUnknown(), &m_ConnectionCookie); - if (!m_ConnectionCookie) - { - hr = E_FAIL; - } - } - - if (SUCCEEDED(hr)) - { - hr = m_IPlayer->get_controls(&m_IControls); - } - - if (SUCCEEDED(hr)) - { - hr = m_IPlayer->get_settings(&m_ISettings); - } - - if (SUCCEEDED(hr)) - { - WMPPlayState state; - m_IPlayer->get_playState(&state); - if (state == wmppsPlaying) - { - m_State = STATE_PLAYING; - } - else if (state == wmppsPaused) - { - m_State = STATE_PAUSED; - } - - if (m_State != STATE_STOPPED) - { - m_TrackChanged = true; - } - - m_Initialized = true; - } - else - { - Uninitialize(); - } -} - -/* -** Close the interface with WMP. -** -*/ -void PlayerWMP::Uninitialize() -{ - if (m_Initialized) - { - m_Initialized = false; - - if (m_ConnectionCookie) - { - m_IConnectionPoint->Unadvise(m_ConnectionCookie); - m_ConnectionCookie = 0; - } - - m_IControls.Reset(); - m_ISettings.Reset(); - m_IConnectionPoint.Reset(); - m_IPlayer.Reset(); - DestroyWindow(m_Window); - UnregisterClass(L"NowPlayingWMP", g_Instance); - } -} - -/* -** Called during each update of the main measure. -** -*/ -void PlayerWMP::UpdateData() -{ - if (m_Initialized) - { - // Get the volume - long volume; - m_ISettings->get_volume(&volume); - m_Volume = (UINT)volume; - - if (m_State != STATE_STOPPED) - { - double position; - m_IControls->get_currentPosition(&position); - m_Position = (UINT)position; - } - - if (m_TrackChanged) - { - m_TrackChanged = false; - - Microsoft::WRL::ComPtr<IWMPMedia> spMedia; - m_IPlayer->get_currentMedia(spMedia.GetAddressOf()); - - if (spMedia) - { - BSTR val; - - spMedia->getItemInfo(_bstr_t(L"Artist"), &val); - m_Artist = val; - - spMedia->getItemInfo(_bstr_t(L"Title"), &val); - m_Title = val; - - spMedia->getItemInfo(_bstr_t(L"Album"), &val); - m_Album = val; - - spMedia->getItemInfo(_bstr_t(L"UserRating"), &val); - int rating = _wtoi(val); - - if (rating > 75) - { - m_Rating = 5; - } - else if (rating > 50) - { - m_Rating = 4; - } - else if (rating > 25) - { - m_Rating = 3; - } - else if (rating > 1) - { - m_Rating = 2; - } - else - { - m_Rating = rating; - } - - spMedia->getItemInfo(_bstr_t(L"WM/TrackNumber"), &val); - m_Number = (UINT)_wtoi(val); - - spMedia->getItemInfo(_bstr_t(L"WM/Year"), &val); - m_Year = (UINT)_wtoi(val); - - double duration; - spMedia->get_duration(&duration); - m_Duration = (UINT)duration; - - BSTR url; - spMedia->get_sourceURL(&url); - std::wstring targetPath = url; - - if (targetPath != m_FilePath) - { - ++m_TrackCount; - m_FilePath = targetPath; - - // Find cover if needed - // TODO: Fix temp solution - if (m_Measures & MEASURE_COVER || m_InstanceCount == 0) - { - spMedia->getItemInfo(_bstr_t(L"WM/WMCollectionID"), &val); - targetPath.resize(targetPath.find_last_of(L'\\') + 1); - targetPath += L"AlbumArt_"; - targetPath += val; - targetPath += L"_Large.jpg"; - - if (_waccess(targetPath.c_str(), 0) == 0) - { - m_CoverPath = targetPath; - } - else - { - FindCover(); - } - } - - if (m_Measures & MEASURE_LYRICS) - { - FindLyrics(); - } - } - } - } - } - else - { - DWORD time = GetTickCount(); - - // Try to find WMP window every 5 seconds - if (m_LastCheckTime = 0 || time - m_LastCheckTime > 5000) - { - m_LastCheckTime = time; - - if (FindWindow(L"WMPlayerApp", nullptr)) - { - Initialize(); - } - } - } -} - -/* -** Handles the Pause bang. -** -*/ -void PlayerWMP::Pause() -{ - m_IControls->pause(); -} - -/* -** Handles the Play bang. -** -*/ -void PlayerWMP::Play() -{ - m_IControls->play(); -} - -/* -** Handles the Stop bang. -** -*/ -void PlayerWMP::Stop() -{ - m_IControls->stop(); - // TODO: FIXME - m_State = STATE_STOPPED; -} - -/* -** Handles the Next bang. -** -*/ -void PlayerWMP::Next() -{ - m_IControls->next(); -} - -/* -** Handles the Previous bang. -** -*/ -void PlayerWMP::Previous() -{ - m_IControls->previous(); -} - -/* -** Handles the SetPosition bang. -** -*/ -void PlayerWMP::SetPosition(int position) -{ - m_IControls->put_currentPosition((double)position); -} - -/* -** Handles the SetRating bang. -** -*/ -void PlayerWMP::SetRating(int rating) -{ - if (m_State != STATE_STOPPED) - { - Microsoft::WRL::ComPtr<IWMPMedia> spMedia; - m_IPlayer->get_currentMedia(spMedia.GetAddressOf()); - - if (spMedia) - { - BSTR val; - switch (rating) - { - case 0: - val = L"0"; - break; - - case 1: - val = L"1"; - break; - - case 2: - val = L"25"; - break; - - case 3: - val = L"50"; - break; - - case 4: - val = L"75"; - break; - - default: // case 5: - val = L"99"; - break; - } - - spMedia->setItemInfo(_bstr_t(L"UserRating"), val); - m_Rating = rating; - } - } -} - -/* -** Handles the SetVolume bang. -** -*/ -void PlayerWMP::SetVolume(int volume) -{ - m_ISettings->put_volume(volume); -} - -/* -** Handles the ClosePlayer bang. -** -*/ -void PlayerWMP::ClosePlayer() -{ - HWND wnd = FindWindow(L"WMPlayerApp", nullptr); - - if (wnd) - { - SendMessage(wnd, WM_CLOSE, 0, 0); - } -} - -/* -** Handles the OpenPlayer bang. -** -*/ -void PlayerWMP::OpenPlayer(std::wstring& path) -{ - ShellExecute(nullptr, L"open", path.empty() ? L"wmplayer.exe" : path.c_str(), nullptr, nullptr, SW_SHOW); -} +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "PlayerWMP.h" + +Player* PlayerWMP::c_Player = nullptr; +extern HINSTANCE g_Instance; + +namespace { + +// Definitions of ATL stuff we need to avoid dependency on atlbase.h (which is not included in free +// versions of Visual Studio). + +MIDL_INTERFACE("B6EA2050-048A-11d1-82B9-00C04FB9942E") +IAxWinHostWindow : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE CreateControl( + LPCOLESTR lpTricsData, HWND hWnd, IStream *pStream) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateControlEx( + LPCOLESTR lpszTricsData, HWND hWnd, IStream* pStream, IUnknown** ppUnk, REFIID iidAdvise, + IUnknown* punkSink) = 0; + + virtual HRESULT STDMETHODCALLTYPE AttachControl(IUnknown* pUnkControl, HWND hWnd) = 0; + virtual HRESULT STDMETHODCALLTYPE QueryControl(REFIID riid, void** ppvObject) = 0; + virtual HRESULT STDMETHODCALLTYPE SetExternalDispatch(IDispatch* pDisp) = 0; + virtual HRESULT STDMETHODCALLTYPE SetExternalUIHandler(void* pDisp) = 0; +}; + +typedef BOOL (WINAPI * AtlAxWinInitFunc)(); +typedef HRESULT (WINAPI * AtlAxGetControlFunc)(HWND h, IUnknown** pp); +typedef HRESULT (WINAPI * AtlAxGetHostFunc)(HWND h, IUnknown** pp); + +HMODULE InitializeAtlLibrary() +{ + static HMODULE s_ATL = LoadLibrary(L"atl"); + if (s_ATL) + { + auto atlAxWinInit = (AtlAxWinInitFunc)GetProcAddress(s_ATL, "AtlAxWinInit"); + atlAxWinInit(); + } + return s_ATL; +} + +} // namespace + +// +// PlayerWMP::CRemoteHost +// + +PlayerWMP::CRemoteHost::CRemoteHost() : + m_Player(), + m_RefCount(0) +{ +} + +PlayerWMP::CRemoteHost::~CRemoteHost() +{ +} + +ULONG STDMETHODCALLTYPE PlayerWMP::CRemoteHost::AddRef() +{ + ++m_RefCount; + return m_RefCount; +} + +ULONG STDMETHODCALLTYPE PlayerWMP::CRemoteHost::Release() +{ + --m_RefCount; + if (m_RefCount == 0) + { + delete this; + return 0; + } + return m_RefCount; +} + +HRESULT STDMETHODCALLTYPE PlayerWMP::CRemoteHost::QueryInterface(IID const& riid, void** object) +{ + if (!object) + { + return E_POINTER; + } + + if (riid == __uuidof(IUnknown) || + riid == __uuidof(IServiceProvider)) + { + *object = (IServiceProvider*)this; + } + else if (riid == __uuidof(IWMPRemoteMediaServices)) + { + *object = (IWMPRemoteMediaServices*)this; + } + else if (riid == __uuidof(IWMPEvents)) + { + *object = (IWMPEvents*)this; + } + else + { + *object = nullptr; + return E_NOINTERFACE; + } + + AddRef(); + return S_OK; +} + +HRESULT PlayerWMP::CRemoteHost::QueryService(REFGUID guidService, REFIID riid, void** ppv) +{ + return QueryInterface(riid, ppv); +} + +HRESULT PlayerWMP::CRemoteHost::GetServiceType(BSTR* pbstrType) +{ + *pbstrType = SysAllocString(L"RemoteNoDialogs"); + return *pbstrType ? S_OK : E_POINTER; +} + +HRESULT PlayerWMP::CRemoteHost::GetApplicationName(BSTR* pbstrName) +{ + *pbstrName = SysAllocString(L"Rainmeter NowPlaying"); + return *pbstrName ? S_OK : E_POINTER; +} + +HRESULT PlayerWMP::CRemoteHost::GetScriptableObject(BSTR* pbstrName, IDispatch** ppDispatch) +{ + if (pbstrName) + { + *pbstrName = nullptr; + } + if (ppDispatch) + { + *ppDispatch = nullptr; + } + return E_NOTIMPL; +} + +HRESULT PlayerWMP::CRemoteHost::GetCustomUIMode(BSTR* pbstrFile) +{ + return E_POINTER; +} + +/* +** Called when playing track changes. +** +*/ +void PlayerWMP::CRemoteHost::CurrentItemChange(IDispatch* pdispMedia) +{ + m_Player->m_TrackChanged = true; +} + +/* +** Called when play state changes. +** +*/ +void PlayerWMP::CRemoteHost::PlayStateChange(long NewState) +{ + switch (NewState) + { + case wmppsStopped: + case wmppsMediaEnded: + m_Player->ClearData(false); + break; + + case wmppsPaused: + m_Player->m_State = STATE_PAUSED; + break; + + case wmppsPlaying: + if (m_Player->m_State == STATE_STOPPED) + { + m_Player->m_TrackChanged = true; + } + m_Player->m_State = STATE_PLAYING; + break; + + default: + break; + } +} + +/* +** Called when WMP quits. +** +*/ +void PlayerWMP::CRemoteHost::SwitchedToControl() +{ + m_Player->ClearData(); + m_Player->Uninitialize(); +} + +// +// PlayerWMP +// + +PlayerWMP::PlayerWMP() : Player(), + m_TrackChanged(false), + m_Window(), + m_LastCheckTime(0), + m_ConnectionCookie() +{ +} + +PlayerWMP::~PlayerWMP() +{ + c_Player = nullptr; + Uninitialize(); +} + +/* +** Creates a shared class object. +** +*/ +Player* PlayerWMP::Create() +{ + if (!c_Player) + { + c_Player = new PlayerWMP(); + } + + return c_Player; +} + +/* +** Set up the COM interface with WMP. +** +*/ +void PlayerWMP::Initialize() +{ + HMODULE atl = InitializeAtlLibrary(); + if (!atl) + { + RmLog(LOG_ERROR, L"NowPlaying: ATL not found"); + return; + } + + auto atlAxGetControl = (AtlAxGetControlFunc)GetProcAddress(atl, "AtlAxGetControl"); + auto atlAxGetHost = (AtlAxGetHostFunc)GetProcAddress(atl, "AtlAxGetHost"); + + WNDCLASS wc = {0}; + wc.hInstance = g_Instance; + wc.lpfnWndProc = DefWindowProc; + wc.lpszClassName = L"NowPlayingWMP"; + RegisterClass(&wc); + + // Create the container window and the ATL host window. + m_Window = CreateWindow( + L"NowPlayingWMP", L"", + WS_DISABLED, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + nullptr, nullptr, g_Instance, nullptr); + + HWND window = CreateWindow( + L"AtlAxWin", L"", + WS_DISABLED | WS_CHILD, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + m_Window, nullptr, g_Instance, nullptr); + + Microsoft::WRL::ComPtr<IUnknown> axHost; + Microsoft::WRL::ComPtr<IObjectWithSite> hostObject; + HRESULT hr = atlAxGetHost(window, axHost.GetAddressOf()); + if (SUCCEEDED(hr)) + { + hr = axHost.As(&hostObject); + } + + Microsoft::WRL::ComPtr<CRemoteHost> remoteHost(new CRemoteHost()); + if (SUCCEEDED(hr)) + { + remoteHost->m_Player = this; + hr = hostObject->SetSite((IWMPRemoteMediaServices*)remoteHost.Get()); + } + + Microsoft::WRL::ComPtr<IAxWinHostWindow> axWinHostWindow; + if (SUCCEEDED(hr)) + { + hr = axHost.As(&axWinHostWindow); + } + + if (SUCCEEDED(hr)) + { + hr = axWinHostWindow->CreateControl(L"{6BF52A52-394A-11D3-B153-00C04F79FAA6}", window, nullptr); + } + + Microsoft::WRL::ComPtr<IUnknown> axControl; + if (SUCCEEDED(hr)) + { + hr = atlAxGetControl(window, axControl.GetAddressOf()); + } + + if (SUCCEEDED(hr)) + { + hr = axControl.As(&m_IPlayer); + } + + // Connect the event interface. + Microsoft::WRL::ComPtr<IConnectionPointContainer> wmpPlayerConnectionContainer; + if (SUCCEEDED(hr)) + { + hr = m_IPlayer.As(&wmpPlayerConnectionContainer); + } + + if (SUCCEEDED(hr)) + { + hr = wmpPlayerConnectionContainer->FindConnectionPoint( + __uuidof(IWMPEvents), m_IConnectionPoint.GetAddressOf()); + } + + if (SUCCEEDED(hr)) + { + hr = m_IConnectionPoint->Advise(remoteHost->GetUnknown(), &m_ConnectionCookie); + if (!m_ConnectionCookie) + { + hr = E_FAIL; + } + } + + if (SUCCEEDED(hr)) + { + hr = m_IPlayer->get_controls(&m_IControls); + } + + if (SUCCEEDED(hr)) + { + hr = m_IPlayer->get_settings(&m_ISettings); + } + + if (SUCCEEDED(hr)) + { + WMPPlayState state; + m_IPlayer->get_playState(&state); + if (state == wmppsPlaying) + { + m_State = STATE_PLAYING; + } + else if (state == wmppsPaused) + { + m_State = STATE_PAUSED; + } + + if (m_State != STATE_STOPPED) + { + m_TrackChanged = true; + } + + m_Initialized = true; + } + else + { + Uninitialize(); + } +} + +/* +** Close the interface with WMP. +** +*/ +void PlayerWMP::Uninitialize() +{ + if (m_Initialized) + { + m_Initialized = false; + + if (m_ConnectionCookie) + { + m_IConnectionPoint->Unadvise(m_ConnectionCookie); + m_ConnectionCookie = 0; + } + + m_IControls.Reset(); + m_ISettings.Reset(); + m_IConnectionPoint.Reset(); + m_IPlayer.Reset(); + DestroyWindow(m_Window); + UnregisterClass(L"NowPlayingWMP", g_Instance); + } +} + +/* +** Called during each update of the main measure. +** +*/ +void PlayerWMP::UpdateData() +{ + if (m_Initialized) + { + // Get the volume + long volume; + m_ISettings->get_volume(&volume); + m_Volume = (UINT)volume; + + if (m_State != STATE_STOPPED) + { + double position; + m_IControls->get_currentPosition(&position); + m_Position = (UINT)position; + } + + if (m_TrackChanged) + { + m_TrackChanged = false; + + Microsoft::WRL::ComPtr<IWMPMedia> spMedia; + m_IPlayer->get_currentMedia(spMedia.GetAddressOf()); + + if (spMedia) + { + BSTR val; + + spMedia->getItemInfo(_bstr_t(L"Artist"), &val); + m_Artist = val; + + spMedia->getItemInfo(_bstr_t(L"Title"), &val); + m_Title = val; + + spMedia->getItemInfo(_bstr_t(L"Album"), &val); + m_Album = val; + + spMedia->getItemInfo(_bstr_t(L"UserRating"), &val); + int rating = _wtoi(val); + + if (rating > 75) + { + m_Rating = 5; + } + else if (rating > 50) + { + m_Rating = 4; + } + else if (rating > 25) + { + m_Rating = 3; + } + else if (rating > 1) + { + m_Rating = 2; + } + else + { + m_Rating = rating; + } + + spMedia->getItemInfo(_bstr_t(L"WM/TrackNumber"), &val); + m_Number = (UINT)_wtoi(val); + + spMedia->getItemInfo(_bstr_t(L"WM/Year"), &val); + m_Year = (UINT)_wtoi(val); + + double duration; + spMedia->get_duration(&duration); + m_Duration = (UINT)duration; + + BSTR url; + spMedia->get_sourceURL(&url); + std::wstring targetPath = url; + + if (targetPath != m_FilePath) + { + ++m_TrackCount; + m_FilePath = targetPath; + + // Find cover if needed + // TODO: Fix temp solution + if (m_Measures & MEASURE_COVER || m_InstanceCount == 0) + { + spMedia->getItemInfo(_bstr_t(L"WM/WMCollectionID"), &val); + targetPath.resize(targetPath.find_last_of(L'\\') + 1); + targetPath += L"AlbumArt_"; + targetPath += val; + targetPath += L"_Large.jpg"; + + if (_waccess(targetPath.c_str(), 0) == 0) + { + m_CoverPath = targetPath; + } + else + { + FindCover(); + } + } + + if (m_Measures & MEASURE_LYRICS) + { + FindLyrics(); + } + } + } + } + } + else + { + DWORD time = GetTickCount(); + + // Try to find WMP window every 5 seconds + if (m_LastCheckTime = 0 || time - m_LastCheckTime > 5000) + { + m_LastCheckTime = time; + + if (FindWindow(L"WMPlayerApp", nullptr)) + { + Initialize(); + } + } + } +} + +/* +** Handles the Pause bang. +** +*/ +void PlayerWMP::Pause() +{ + m_IControls->pause(); +} + +/* +** Handles the Play bang. +** +*/ +void PlayerWMP::Play() +{ + m_IControls->play(); +} + +/* +** Handles the Stop bang. +** +*/ +void PlayerWMP::Stop() +{ + m_IControls->stop(); + // TODO: FIXME + m_State = STATE_STOPPED; +} + +/* +** Handles the Next bang. +** +*/ +void PlayerWMP::Next() +{ + m_IControls->next(); +} + +/* +** Handles the Previous bang. +** +*/ +void PlayerWMP::Previous() +{ + m_IControls->previous(); +} + +/* +** Handles the SetPosition bang. +** +*/ +void PlayerWMP::SetPosition(int position) +{ + m_IControls->put_currentPosition((double)position); +} + +/* +** Handles the SetRating bang. +** +*/ +void PlayerWMP::SetRating(int rating) +{ + if (m_State != STATE_STOPPED) + { + Microsoft::WRL::ComPtr<IWMPMedia> spMedia; + m_IPlayer->get_currentMedia(spMedia.GetAddressOf()); + + if (spMedia) + { + BSTR val; + switch (rating) + { + case 0: + val = L"0"; + break; + + case 1: + val = L"1"; + break; + + case 2: + val = L"25"; + break; + + case 3: + val = L"50"; + break; + + case 4: + val = L"75"; + break; + + default: // case 5: + val = L"99"; + break; + } + + spMedia->setItemInfo(_bstr_t(L"UserRating"), val); + m_Rating = rating; + } + } +} + +/* +** Handles the SetVolume bang. +** +*/ +void PlayerWMP::SetVolume(int volume) +{ + m_ISettings->put_volume(volume); +} + +/* +** Handles the ClosePlayer bang. +** +*/ +void PlayerWMP::ClosePlayer() +{ + HWND wnd = FindWindow(L"WMPlayerApp", nullptr); + + if (wnd) + { + SendMessage(wnd, WM_CLOSE, 0, 0); + } +} + +/* +** Handles the OpenPlayer bang. +** +*/ +void PlayerWMP::OpenPlayer(std::wstring& path) +{ + ShellExecute(nullptr, L"open", path.empty() ? L"wmplayer.exe" : path.c_str(), nullptr, nullptr, SW_SHOW); +} diff --git a/Plugins/PluginNowPlaying/PlayerWMP.h b/Plugins/PluginNowPlaying/PlayerWMP.h index e4f3e8e4..e00122c9 100644 --- a/Plugins/PluginNowPlaying/PlayerWMP.h +++ b/Plugins/PluginNowPlaying/PlayerWMP.h @@ -1,144 +1,144 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __PLAYERWMP_H__ -#define __PLAYERWMP_H__ - -#include "Player.h" -#include <wmp.h> -#include <wrl/client.h> - -class PlayerWMP : public Player -{ -public: - virtual ~PlayerWMP(); - - static Player* Create(); - - virtual void UpdateData(); - - virtual void Pause(); - virtual void Play(); - virtual void Stop(); - virtual void Next(); - virtual void Previous(); - virtual void SetPosition(int position); - virtual void SetRating(int rating); - virtual void SetVolume(int volume); - virtual void OpenPlayer(std::wstring& path); - virtual void ClosePlayer(); - -protected: - PlayerWMP(); - -private: - class CRemoteHost : - public IServiceProvider, - public IWMPRemoteMediaServices, - public IWMPEvents - { - public: - CRemoteHost(); - ~CRemoteHost(); - - PlayerWMP* m_Player; - - IUnknown* GetUnknown() const { return (IServiceProvider*)this; } - - // IUnknown - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override; - virtual ULONG STDMETHODCALLTYPE AddRef() override; - virtual ULONG STDMETHODCALLTYPE Release() override; - - // IServiceProvider - STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void** ppv); - - // IWMPRemoteMediaServices - STDMETHOD(GetServiceType)(BSTR* pbstrType); - STDMETHOD(GetApplicationName)(BSTR* pbstrName); - STDMETHOD(GetScriptableObject)(BSTR* pbstrName, IDispatch** ppDispatch); - STDMETHOD(GetCustomUIMode)(BSTR* pbstrFile); - - // IWMPEvents - void STDMETHODCALLTYPE OpenStateChange(long NewState) {} - void STDMETHODCALLTYPE PlayStateChange(long NewState); - void STDMETHODCALLTYPE AudioLanguageChange(long LangID) {} - void STDMETHODCALLTYPE StatusChange() {} - void STDMETHODCALLTYPE ScriptCommand(BSTR scType, BSTR Param) {} - void STDMETHODCALLTYPE NewStream() {} - void STDMETHODCALLTYPE Disconnect(long Result) {} - void STDMETHODCALLTYPE Buffering(VARIANT_BOOL Start) {} - void STDMETHODCALLTYPE Error() {} - void STDMETHODCALLTYPE Warning(long WarningType, long Param, BSTR Description) {} - void STDMETHODCALLTYPE EndOfStream(long Result) {} - void STDMETHODCALLTYPE PositionChange(double oldPosition, double newPosition) {} - void STDMETHODCALLTYPE MarkerHit(long MarkerNum) {} - void STDMETHODCALLTYPE DurationUnitChange(long NewDurationUnit) {} - void STDMETHODCALLTYPE CdromMediaChange(long CdromNum) {} - void STDMETHODCALLTYPE PlaylistChange(IDispatch* Playlist, WMPPlaylistChangeEventType change) {} - void STDMETHODCALLTYPE CurrentPlaylistChange(WMPPlaylistChangeEventType change) {} - void STDMETHODCALLTYPE CurrentPlaylistItemAvailable(BSTR bstrItemName) {} - void STDMETHODCALLTYPE MediaChange(IDispatch* pdispMedia) {} - void STDMETHODCALLTYPE CurrentMediaItemAvailable(BSTR bstrItemName) {} - void STDMETHODCALLTYPE CurrentItemChange(IDispatch* pdispMedia); - void STDMETHODCALLTYPE MediaCollectionChange() {} - void STDMETHODCALLTYPE MediaCollectionAttributeStringAdded(BSTR bstrAttribName, BSTR bstrAttribVal) {} - void STDMETHODCALLTYPE MediaCollectionAttributeStringRemoved(BSTR bstrAttribName, BSTR bstrAttribVal) {} - void STDMETHODCALLTYPE MediaCollectionAttributeStringChanged(BSTR bstrAttribName, BSTR bstrOldAttribVal, BSTR bstrNewAttribVal) {} - void STDMETHODCALLTYPE PlaylistCollectionChange() {} - void STDMETHODCALLTYPE PlaylistCollectionPlaylistAdded(BSTR bstrPlaylistName) {} - void STDMETHODCALLTYPE PlaylistCollectionPlaylistRemoved(BSTR bstrPlaylistName) {} - void STDMETHODCALLTYPE PlaylistCollectionPlaylistSetAsDeleted(BSTR bstrPlaylistName, VARIANT_BOOL varfIsDeleted) {} - void STDMETHODCALLTYPE ModeChange(BSTR ModeName, VARIANT_BOOL NewValue) {} - void STDMETHODCALLTYPE MediaError(IDispatch* pMediaObject) {} - void STDMETHODCALLTYPE OpenPlaylistSwitch(IDispatch* pItem) {} - void STDMETHODCALLTYPE DomainChange(BSTR strDomain) {} - void STDMETHODCALLTYPE SwitchedToPlayerApplication() {} - void STDMETHODCALLTYPE SwitchedToControl(); - void STDMETHODCALLTYPE PlayerDockedStateChange() {} - void STDMETHODCALLTYPE PlayerReconnect() {} - void STDMETHODCALLTYPE Click(short nButton, short nShiftState, long fX, long fY) {} - void STDMETHODCALLTYPE DoubleClick(short nButton, short nShiftState, long fX, long fY) {} - void STDMETHODCALLTYPE KeyDown(short nKeyCode, short nShiftState) {} - void STDMETHODCALLTYPE KeyPress(short nKeyAscii) {} - void STDMETHODCALLTYPE KeyUp(short nKeyCode, short nShiftState) {} - void STDMETHODCALLTYPE MouseDown(short nButton, short nShiftState, long fX, long fY) {} - void STDMETHODCALLTYPE MouseMove(short nButton, short nShiftState, long fX, long fY) {} - void STDMETHODCALLTYPE MouseUp(short nButton, short nShiftState, long fX, long fY) {} - - private: - ULONG m_RefCount; - }; - - void Initialize(); - void Uninitialize(); - - static Player* c_Player; - - bool m_TrackChanged; - HWND m_Window; - DWORD m_LastCheckTime; - - Microsoft::WRL::ComPtr<IWMPPlayer4> m_IPlayer; - Microsoft::WRL::ComPtr<IWMPControls> m_IControls; - Microsoft::WRL::ComPtr<IWMPSettings> m_ISettings; - Microsoft::WRL::ComPtr<IConnectionPoint> m_IConnectionPoint; - DWORD m_ConnectionCookie; -}; - -#endif +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __PLAYERWMP_H__ +#define __PLAYERWMP_H__ + +#include "Player.h" +#include <wmp.h> +#include <wrl/client.h> + +class PlayerWMP : public Player +{ +public: + virtual ~PlayerWMP(); + + static Player* Create(); + + virtual void UpdateData(); + + virtual void Pause(); + virtual void Play(); + virtual void Stop(); + virtual void Next(); + virtual void Previous(); + virtual void SetPosition(int position); + virtual void SetRating(int rating); + virtual void SetVolume(int volume); + virtual void OpenPlayer(std::wstring& path); + virtual void ClosePlayer(); + +protected: + PlayerWMP(); + +private: + class CRemoteHost : + public IServiceProvider, + public IWMPRemoteMediaServices, + public IWMPEvents + { + public: + CRemoteHost(); + ~CRemoteHost(); + + PlayerWMP* m_Player; + + IUnknown* GetUnknown() const { return (IServiceProvider*)this; } + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override; + virtual ULONG STDMETHODCALLTYPE AddRef() override; + virtual ULONG STDMETHODCALLTYPE Release() override; + + // IServiceProvider + STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void** ppv); + + // IWMPRemoteMediaServices + STDMETHOD(GetServiceType)(BSTR* pbstrType); + STDMETHOD(GetApplicationName)(BSTR* pbstrName); + STDMETHOD(GetScriptableObject)(BSTR* pbstrName, IDispatch** ppDispatch); + STDMETHOD(GetCustomUIMode)(BSTR* pbstrFile); + + // IWMPEvents + void STDMETHODCALLTYPE OpenStateChange(long NewState) {} + void STDMETHODCALLTYPE PlayStateChange(long NewState); + void STDMETHODCALLTYPE AudioLanguageChange(long LangID) {} + void STDMETHODCALLTYPE StatusChange() {} + void STDMETHODCALLTYPE ScriptCommand(BSTR scType, BSTR Param) {} + void STDMETHODCALLTYPE NewStream() {} + void STDMETHODCALLTYPE Disconnect(long Result) {} + void STDMETHODCALLTYPE Buffering(VARIANT_BOOL Start) {} + void STDMETHODCALLTYPE Error() {} + void STDMETHODCALLTYPE Warning(long WarningType, long Param, BSTR Description) {} + void STDMETHODCALLTYPE EndOfStream(long Result) {} + void STDMETHODCALLTYPE PositionChange(double oldPosition, double newPosition) {} + void STDMETHODCALLTYPE MarkerHit(long MarkerNum) {} + void STDMETHODCALLTYPE DurationUnitChange(long NewDurationUnit) {} + void STDMETHODCALLTYPE CdromMediaChange(long CdromNum) {} + void STDMETHODCALLTYPE PlaylistChange(IDispatch* Playlist, WMPPlaylistChangeEventType change) {} + void STDMETHODCALLTYPE CurrentPlaylistChange(WMPPlaylistChangeEventType change) {} + void STDMETHODCALLTYPE CurrentPlaylistItemAvailable(BSTR bstrItemName) {} + void STDMETHODCALLTYPE MediaChange(IDispatch* pdispMedia) {} + void STDMETHODCALLTYPE CurrentMediaItemAvailable(BSTR bstrItemName) {} + void STDMETHODCALLTYPE CurrentItemChange(IDispatch* pdispMedia); + void STDMETHODCALLTYPE MediaCollectionChange() {} + void STDMETHODCALLTYPE MediaCollectionAttributeStringAdded(BSTR bstrAttribName, BSTR bstrAttribVal) {} + void STDMETHODCALLTYPE MediaCollectionAttributeStringRemoved(BSTR bstrAttribName, BSTR bstrAttribVal) {} + void STDMETHODCALLTYPE MediaCollectionAttributeStringChanged(BSTR bstrAttribName, BSTR bstrOldAttribVal, BSTR bstrNewAttribVal) {} + void STDMETHODCALLTYPE PlaylistCollectionChange() {} + void STDMETHODCALLTYPE PlaylistCollectionPlaylistAdded(BSTR bstrPlaylistName) {} + void STDMETHODCALLTYPE PlaylistCollectionPlaylistRemoved(BSTR bstrPlaylistName) {} + void STDMETHODCALLTYPE PlaylistCollectionPlaylistSetAsDeleted(BSTR bstrPlaylistName, VARIANT_BOOL varfIsDeleted) {} + void STDMETHODCALLTYPE ModeChange(BSTR ModeName, VARIANT_BOOL NewValue) {} + void STDMETHODCALLTYPE MediaError(IDispatch* pMediaObject) {} + void STDMETHODCALLTYPE OpenPlaylistSwitch(IDispatch* pItem) {} + void STDMETHODCALLTYPE DomainChange(BSTR strDomain) {} + void STDMETHODCALLTYPE SwitchedToPlayerApplication() {} + void STDMETHODCALLTYPE SwitchedToControl(); + void STDMETHODCALLTYPE PlayerDockedStateChange() {} + void STDMETHODCALLTYPE PlayerReconnect() {} + void STDMETHODCALLTYPE Click(short nButton, short nShiftState, long fX, long fY) {} + void STDMETHODCALLTYPE DoubleClick(short nButton, short nShiftState, long fX, long fY) {} + void STDMETHODCALLTYPE KeyDown(short nKeyCode, short nShiftState) {} + void STDMETHODCALLTYPE KeyPress(short nKeyAscii) {} + void STDMETHODCALLTYPE KeyUp(short nKeyCode, short nShiftState) {} + void STDMETHODCALLTYPE MouseDown(short nButton, short nShiftState, long fX, long fY) {} + void STDMETHODCALLTYPE MouseMove(short nButton, short nShiftState, long fX, long fY) {} + void STDMETHODCALLTYPE MouseUp(short nButton, short nShiftState, long fX, long fY) {} + + private: + ULONG m_RefCount; + }; + + void Initialize(); + void Uninitialize(); + + static Player* c_Player; + + bool m_TrackChanged; + HWND m_Window; + DWORD m_LastCheckTime; + + Microsoft::WRL::ComPtr<IWMPPlayer4> m_IPlayer; + Microsoft::WRL::ComPtr<IWMPControls> m_IControls; + Microsoft::WRL::ComPtr<IWMPSettings> m_ISettings; + Microsoft::WRL::ComPtr<IConnectionPoint> m_IConnectionPoint; + DWORD m_ConnectionCookie; +}; + +#endif diff --git a/Plugins/PluginNowPlaying/PlayerWinamp.cpp b/Plugins/PluginNowPlaying/PlayerWinamp.cpp index 1ce4b1b5..1aad6775 100644 --- a/Plugins/PluginNowPlaying/PlayerWinamp.cpp +++ b/Plugins/PluginNowPlaying/PlayerWinamp.cpp @@ -1,501 +1,501 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include <cmath> -#include "PlayerWinamp.h" -#include "Winamp/wa_ipc.h" -#include "Winamp/wa_cmd.h" - -Player* PlayerWinamp::c_Player = nullptr; - -// This player retrieves data through the Winamp IPC interface. - -/* -** Constructor. -** -*/ -PlayerWinamp::PlayerWinamp(WINAMPTYPE type) : Player(), - m_Window(), - m_LastCheckTime(0), - m_UseUnicodeAPI(false), - m_PlayingStream(false), - m_WinampType(type), - m_WinampHandle(), - m_WinampAddress() -{ -} - -/* -** Destructor. -** -*/ -PlayerWinamp::~PlayerWinamp() -{ - c_Player = nullptr; - if (m_WinampHandle) CloseHandle(m_WinampHandle); -} - -/* -** Creates a shared class object. -** -*/ -Player* PlayerWinamp::Create(WINAMPTYPE type) -{ - if (!c_Player) - { - c_Player = new PlayerWinamp(type); - } - - return c_Player; -} - -/* -** Try to find Winamp periodically. -** -*/ -bool PlayerWinamp::CheckWindow() -{ - DWORD time = GetTickCount(); - - // Try to find Winamp window every 5 seconds - if (time - m_LastCheckTime > 5000) - { - m_LastCheckTime = time; - - m_Window = FindWindow(L"Winamp v1.x", nullptr); - if (m_Window) - { - DWORD pID; - GetWindowThreadProcessId(m_Window, &pID); - m_WinampHandle = OpenProcess(PROCESS_VM_READ, FALSE, pID); - - if (m_WinampHandle) - { - m_WinampAddress = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_PLAYING_FILENAME); - m_UseUnicodeAPI = m_WinampAddress ? true : false; - m_Initialized = true; - } - } - } - - return m_Initialized; -} - -/* -** Called during each update of the main measure. -** -*/ -void PlayerWinamp::UpdateData() -{ - if (m_Initialized || CheckWindow()) - { - const auto playing = SendMessage(m_Window, WM_WA_IPC, 0, IPC_ISPLAYING); - if (playing == 0) - { - // Make sure Winamp is still active - if (!IsWindow(m_Window)) - { - m_Initialized = false; - ClearData(); - - if (m_WinampHandle) CloseHandle(m_WinampHandle); - } - else if (m_State != STATE_STOPPED) - { - ClearData(false); - } - - // Don't continue if Winamp has quit or is stopped - return; - } - else - { - m_State = (playing == 1) ? STATE_PLAYING : STATE_PAUSED; - m_Position = (UINT)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETOUTPUTTIME) / 1000; // ms to secs - m_Volume = ((UINT)SendMessage(m_Window, WM_WA_IPC, -666, IPC_SETVOLUME) * 100) / 255; // 0 - 255 to 0 - 100 - } - - WCHAR wBuffer[MAX_PATH]; - char cBuffer[MAX_PATH]; - - if (m_UseUnicodeAPI) - { - if (!ReadProcessMemory(m_WinampHandle, m_WinampAddress, &wBuffer, sizeof(wBuffer), nullptr)) - { - // Failed to read memory - return; - } - } - else - { - // MediaMonkey doesn't support wide IPC messages - const auto pos = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETLISTPOS); - LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, pos, IPC_GETPLAYLISTFILE); - - if (!ReadProcessMemory(m_WinampHandle, address, &cBuffer, sizeof(cBuffer), nullptr)) - { - // Failed to read memory - return; - } - - mbstowcs(wBuffer, cBuffer, MAX_PATH); - } - - if (wcscmp(wBuffer, m_FilePath.c_str()) != 0) - { - ++m_TrackCount; - m_FilePath = wBuffer; - m_PlayingStream = (m_FilePath.find(L"://") != std::wstring::npos); - - if (!m_PlayingStream) - { - const int duration = (int)SendMessage(m_Window, WM_WA_IPC, 1, IPC_GETOUTPUTTIME); - m_Duration = (duration != -1) ? duration : 0; - - m_Rating = (UINT)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETRATING); - m_Shuffle = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_SHUFFLE) != 0; - m_Repeat = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_REPEAT) != 0; - - TagLib::FileRef fr(wBuffer, false); - TagLib::Tag* tag = fr.tag(); - if (tag) - { - m_Artist = tag->artist().toWString(); - m_Album = tag->album().toWString(); - m_Title = tag->title().toWString(); - m_Number = tag->track(); - m_Year = tag->year(); - - if (m_Measures & MEASURE_LYRICS) - { - FindLyrics(); - } - } - else if (m_Measures & MEASURE_LYRICS) - { - m_Lyrics.clear(); - } - - // Find cover if needed - if (m_Measures & MEASURE_COVER) - { - if (tag && CCover::GetEmbedded(fr, m_TempCoverPath)) - { - // Got everything, return - m_CoverPath = m_TempCoverPath; - return; - } - - std::wstring trackFolder = CCover::GetFileFolder(m_FilePath); - if (tag && !m_Album.empty()) - { - // Winamp stores covers usually as %album%.jpg - std::wstring file = m_Album; - std::wstring::size_type end = file.length(); - for (std::wstring::size_type pos = 0; pos < end; ++pos) - { - // Replace reserved chars according to Winamp specs - switch (file[pos]) - { - case L'?': - case L'*': - case L'|': - file[pos] = L'_'; - break; - - case L'/': - case L'\\': - case L':': - file[pos] = L'-'; - break; - - case L'\"': - file[pos] = L'\''; - break; - - case L'<': - file[pos] = L'('; - break; - - case L'>': - file[pos] = L')'; - break; - } - } - - if (CCover::GetLocal(file, trackFolder, m_CoverPath)) - { - // %album% art file found - return; - } - } - - if (!CCover::GetLocal(L"cover", trackFolder, m_CoverPath) && - !CCover::GetLocal(L"folder", trackFolder, m_CoverPath)) - { - // Nothing found - m_CoverPath.clear(); - } - } - - if (tag) - { - return; - } - } - else - { - m_Rating = 0; - m_Duration = 0; - m_CoverPath.clear(); - } - } - else if (!m_PlayingStream) - { - if (m_Duration == 0) - { - const int duration = (int)SendMessage(m_Window, WM_WA_IPC, 1, IPC_GETOUTPUTTIME); - m_Duration = (duration != -1) ? duration : 0; - } - - return; - } - - // TagLib couldn't parse the file or Winamp is playing a stream, try to get title - if (m_UseUnicodeAPI) - { - LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_PLAYING_TITLE); - ReadProcessMemory(m_WinampHandle, address, &wBuffer, sizeof(wBuffer), nullptr); - } - else - { - const auto pos = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETLISTPOS); - LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, pos, IPC_GETPLAYLISTTITLE); - ReadProcessMemory(m_WinampHandle, address, &cBuffer, sizeof(cBuffer), nullptr); - mbstowcs(wBuffer, cBuffer, MAX_PATH); - } - - std::wstring title = wBuffer; - std::wstring::size_type pos = title.find(L" - "); - if (pos != std::wstring::npos) - { - m_Artist.assign(title, 0, pos); - pos += 3; // Skip " - " - m_Title.assign(title, pos, title.length() - pos); - m_Album.clear(); - - if (m_PlayingStream) - { - // Remove crap from title if playing radio - pos = m_Title.find(L" ("); - if (pos != std::wstring::npos) - { - m_Title.resize(pos); - } - } - } - else - { - m_Title = title; - m_Artist.clear(); - m_Album.clear(); - } - } -} - -/* -** Handles the Pause bang. -** -*/ -void PlayerWinamp::Pause() -{ - SendMessage(m_Window, WM_COMMAND, WINAMP_PAUSE, 0); -} - -/* -** Handles the Play bang. -** -*/ -void PlayerWinamp::Play() -{ - SendMessage(m_Window, WM_COMMAND, WINAMP_PLAY, 0); -} - -/* -** Handles the Stop bang. -** -*/ -void PlayerWinamp::Stop() -{ - SendMessage(m_Window, WM_COMMAND, WINAMP_STOP, 0); -} - -/* -** Handles the Next bang. -** -*/ -void PlayerWinamp::Next() -{ - SendMessage(m_Window, WM_COMMAND, WINAMP_FASTFWD, 0); -} - -/* -** Handles the Previous bang. -** -*/ -void PlayerWinamp::Previous() -{ - SendMessage(m_Window, WM_COMMAND, WINAMP_REWIND, 0); -} - -/* -** Handles the SetPosition bang. -** -*/ -void PlayerWinamp::SetPosition(int position) -{ - position *= 1000; // To milliseconds - SendMessage(m_Window, WM_WA_IPC, position, IPC_JUMPTOTIME); -} - -/* -** Handles the SetRating bang. -** -*/ -void PlayerWinamp::SetRating(int rating) -{ - if (rating < 0) - { - rating = 0; - } - else if (rating > 5) - { - rating = 5; - } - - SendMessage(m_Window, WM_WA_IPC, rating, IPC_SETRATING); - m_Rating = rating; -} - -/* -** Handles the SetVolume bang. -** -*/ -void PlayerWinamp::SetVolume(int volume) -{ - // Winamp accepts volume in 0 - 255 range - float fVolume = volume * 2.55f; - SendMessage(m_Window, WM_WA_IPC, (WPARAM)ceil(fVolume), IPC_SETVOLUME); -} - -/* -** Handles the SetShuffle bang. -** -*/ -void PlayerWinamp::SetShuffle(bool state) -{ - if (!m_PlayingStream) - { - m_Shuffle = state; - SendMessage(m_Window, WM_WA_IPC, (WPARAM)m_Shuffle, IPC_SET_SHUFFLE); - } -} - -/* -** Handles the SetRepeat bang. -** -*/ -void PlayerWinamp::SetRepeat(bool state) -{ - if (!m_PlayingStream) - { - m_Repeat = state; - SendMessage(m_Window, WM_WA_IPC, (WPARAM)m_Repeat, IPC_SET_REPEAT); - } -} - -/* -** Handles the ClosePlayer bang. -** -*/ -void PlayerWinamp::ClosePlayer() -{ - if (m_WinampType == WA_WINAMP) - { - SendMessage(m_Window, WM_CLOSE, 0, 0); - } - else // if (m_WinampType == WA_MEDIAMONKEY) - { - HWND wnd = FindWindow(L"TFMainWindow", L"MediaMonkey"); - if (wnd) - { - SendMessage(wnd, WM_CLOSE, 0, 0); - } - } -} - -/* -** Handles the OpenPlayer bang. -** -*/ -void PlayerWinamp::OpenPlayer(std::wstring& path) -{ - if (m_WinampType == WA_WINAMP) - { - ShellExecute(nullptr, L"open", path.empty() ? L"winamp.exe" : path.c_str(), nullptr, nullptr, SW_SHOW); - } - else // if (m_WinampType == WA_MEDIAMONKEY) - { - if (path.empty()) - { - // Gotta figure out where Winamp is located at - HKEY hKey; - RegOpenKeyEx(HKEY_LOCAL_MACHINE, - L"SOFTWARE\\Clients\\Media\\MediaMonkey\\shell\\open\\command", - 0, - KEY_QUERY_VALUE, - &hKey); - - DWORD size = 512; - WCHAR* data = new WCHAR[size]; - DWORD type = 0; - - if (RegQueryValueEx(hKey, - nullptr, - nullptr, - (LPDWORD)&type, - (LPBYTE)data, - (LPDWORD)&size) == ERROR_SUCCESS) - { - if (type == REG_SZ) - { - ShellExecute(nullptr, L"open", data, nullptr, nullptr, SW_SHOW); - path = data; - } - } - - delete [] data; - RegCloseKey(hKey); - } - else - { - ShellExecute(nullptr, L"open", path.c_str(), nullptr, nullptr, SW_SHOW); - } - } -} +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include <cmath> +#include "PlayerWinamp.h" +#include "Winamp/wa_ipc.h" +#include "Winamp/wa_cmd.h" + +Player* PlayerWinamp::c_Player = nullptr; + +// This player retrieves data through the Winamp IPC interface. + +/* +** Constructor. +** +*/ +PlayerWinamp::PlayerWinamp(WINAMPTYPE type) : Player(), + m_Window(), + m_LastCheckTime(0), + m_UseUnicodeAPI(false), + m_PlayingStream(false), + m_WinampType(type), + m_WinampHandle(), + m_WinampAddress() +{ +} + +/* +** Destructor. +** +*/ +PlayerWinamp::~PlayerWinamp() +{ + c_Player = nullptr; + if (m_WinampHandle) CloseHandle(m_WinampHandle); +} + +/* +** Creates a shared class object. +** +*/ +Player* PlayerWinamp::Create(WINAMPTYPE type) +{ + if (!c_Player) + { + c_Player = new PlayerWinamp(type); + } + + return c_Player; +} + +/* +** Try to find Winamp periodically. +** +*/ +bool PlayerWinamp::CheckWindow() +{ + DWORD time = GetTickCount(); + + // Try to find Winamp window every 5 seconds + if (time - m_LastCheckTime > 5000) + { + m_LastCheckTime = time; + + m_Window = FindWindow(L"Winamp v1.x", nullptr); + if (m_Window) + { + DWORD pID; + GetWindowThreadProcessId(m_Window, &pID); + m_WinampHandle = OpenProcess(PROCESS_VM_READ, FALSE, pID); + + if (m_WinampHandle) + { + m_WinampAddress = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_PLAYING_FILENAME); + m_UseUnicodeAPI = m_WinampAddress ? true : false; + m_Initialized = true; + } + } + } + + return m_Initialized; +} + +/* +** Called during each update of the main measure. +** +*/ +void PlayerWinamp::UpdateData() +{ + if (m_Initialized || CheckWindow()) + { + const auto playing = SendMessage(m_Window, WM_WA_IPC, 0, IPC_ISPLAYING); + if (playing == 0) + { + // Make sure Winamp is still active + if (!IsWindow(m_Window)) + { + m_Initialized = false; + ClearData(); + + if (m_WinampHandle) CloseHandle(m_WinampHandle); + } + else if (m_State != STATE_STOPPED) + { + ClearData(false); + } + + // Don't continue if Winamp has quit or is stopped + return; + } + else + { + m_State = (playing == 1) ? STATE_PLAYING : STATE_PAUSED; + m_Position = (UINT)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETOUTPUTTIME) / 1000; // ms to secs + m_Volume = ((UINT)SendMessage(m_Window, WM_WA_IPC, -666, IPC_SETVOLUME) * 100) / 255; // 0 - 255 to 0 - 100 + } + + WCHAR wBuffer[MAX_PATH]; + char cBuffer[MAX_PATH]; + + if (m_UseUnicodeAPI) + { + if (!ReadProcessMemory(m_WinampHandle, m_WinampAddress, &wBuffer, sizeof(wBuffer), nullptr)) + { + // Failed to read memory + return; + } + } + else + { + // MediaMonkey doesn't support wide IPC messages + const auto pos = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETLISTPOS); + LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, pos, IPC_GETPLAYLISTFILE); + + if (!ReadProcessMemory(m_WinampHandle, address, &cBuffer, sizeof(cBuffer), nullptr)) + { + // Failed to read memory + return; + } + + mbstowcs(wBuffer, cBuffer, MAX_PATH); + } + + if (wcscmp(wBuffer, m_FilePath.c_str()) != 0) + { + ++m_TrackCount; + m_FilePath = wBuffer; + m_PlayingStream = (m_FilePath.find(L"://") != std::wstring::npos); + + if (!m_PlayingStream) + { + const int duration = (int)SendMessage(m_Window, WM_WA_IPC, 1, IPC_GETOUTPUTTIME); + m_Duration = (duration != -1) ? duration : 0; + + m_Rating = (UINT)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETRATING); + m_Shuffle = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_SHUFFLE) != 0; + m_Repeat = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_REPEAT) != 0; + + TagLib::FileRef fr(wBuffer, false); + TagLib::Tag* tag = fr.tag(); + if (tag) + { + m_Artist = tag->artist().toWString(); + m_Album = tag->album().toWString(); + m_Title = tag->title().toWString(); + m_Number = tag->track(); + m_Year = tag->year(); + + if (m_Measures & MEASURE_LYRICS) + { + FindLyrics(); + } + } + else if (m_Measures & MEASURE_LYRICS) + { + m_Lyrics.clear(); + } + + // Find cover if needed + if (m_Measures & MEASURE_COVER) + { + if (tag && CCover::GetEmbedded(fr, m_TempCoverPath)) + { + // Got everything, return + m_CoverPath = m_TempCoverPath; + return; + } + + std::wstring trackFolder = CCover::GetFileFolder(m_FilePath); + if (tag && !m_Album.empty()) + { + // Winamp stores covers usually as %album%.jpg + std::wstring file = m_Album; + std::wstring::size_type end = file.length(); + for (std::wstring::size_type pos = 0; pos < end; ++pos) + { + // Replace reserved chars according to Winamp specs + switch (file[pos]) + { + case L'?': + case L'*': + case L'|': + file[pos] = L'_'; + break; + + case L'/': + case L'\\': + case L':': + file[pos] = L'-'; + break; + + case L'\"': + file[pos] = L'\''; + break; + + case L'<': + file[pos] = L'('; + break; + + case L'>': + file[pos] = L')'; + break; + } + } + + if (CCover::GetLocal(file, trackFolder, m_CoverPath)) + { + // %album% art file found + return; + } + } + + if (!CCover::GetLocal(L"cover", trackFolder, m_CoverPath) && + !CCover::GetLocal(L"folder", trackFolder, m_CoverPath)) + { + // Nothing found + m_CoverPath.clear(); + } + } + + if (tag) + { + return; + } + } + else + { + m_Rating = 0; + m_Duration = 0; + m_CoverPath.clear(); + } + } + else if (!m_PlayingStream) + { + if (m_Duration == 0) + { + const int duration = (int)SendMessage(m_Window, WM_WA_IPC, 1, IPC_GETOUTPUTTIME); + m_Duration = (duration != -1) ? duration : 0; + } + + return; + } + + // TagLib couldn't parse the file or Winamp is playing a stream, try to get title + if (m_UseUnicodeAPI) + { + LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_PLAYING_TITLE); + ReadProcessMemory(m_WinampHandle, address, &wBuffer, sizeof(wBuffer), nullptr); + } + else + { + const auto pos = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETLISTPOS); + LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, pos, IPC_GETPLAYLISTTITLE); + ReadProcessMemory(m_WinampHandle, address, &cBuffer, sizeof(cBuffer), nullptr); + mbstowcs(wBuffer, cBuffer, MAX_PATH); + } + + std::wstring title = wBuffer; + std::wstring::size_type pos = title.find(L" - "); + if (pos != std::wstring::npos) + { + m_Artist.assign(title, 0, pos); + pos += 3; // Skip " - " + m_Title.assign(title, pos, title.length() - pos); + m_Album.clear(); + + if (m_PlayingStream) + { + // Remove crap from title if playing radio + pos = m_Title.find(L" ("); + if (pos != std::wstring::npos) + { + m_Title.resize(pos); + } + } + } + else + { + m_Title = title; + m_Artist.clear(); + m_Album.clear(); + } + } +} + +/* +** Handles the Pause bang. +** +*/ +void PlayerWinamp::Pause() +{ + SendMessage(m_Window, WM_COMMAND, WINAMP_PAUSE, 0); +} + +/* +** Handles the Play bang. +** +*/ +void PlayerWinamp::Play() +{ + SendMessage(m_Window, WM_COMMAND, WINAMP_PLAY, 0); +} + +/* +** Handles the Stop bang. +** +*/ +void PlayerWinamp::Stop() +{ + SendMessage(m_Window, WM_COMMAND, WINAMP_STOP, 0); +} + +/* +** Handles the Next bang. +** +*/ +void PlayerWinamp::Next() +{ + SendMessage(m_Window, WM_COMMAND, WINAMP_FASTFWD, 0); +} + +/* +** Handles the Previous bang. +** +*/ +void PlayerWinamp::Previous() +{ + SendMessage(m_Window, WM_COMMAND, WINAMP_REWIND, 0); +} + +/* +** Handles the SetPosition bang. +** +*/ +void PlayerWinamp::SetPosition(int position) +{ + position *= 1000; // To milliseconds + SendMessage(m_Window, WM_WA_IPC, position, IPC_JUMPTOTIME); +} + +/* +** Handles the SetRating bang. +** +*/ +void PlayerWinamp::SetRating(int rating) +{ + if (rating < 0) + { + rating = 0; + } + else if (rating > 5) + { + rating = 5; + } + + SendMessage(m_Window, WM_WA_IPC, rating, IPC_SETRATING); + m_Rating = rating; +} + +/* +** Handles the SetVolume bang. +** +*/ +void PlayerWinamp::SetVolume(int volume) +{ + // Winamp accepts volume in 0 - 255 range + float fVolume = volume * 2.55f; + SendMessage(m_Window, WM_WA_IPC, (WPARAM)ceil(fVolume), IPC_SETVOLUME); +} + +/* +** Handles the SetShuffle bang. +** +*/ +void PlayerWinamp::SetShuffle(bool state) +{ + if (!m_PlayingStream) + { + m_Shuffle = state; + SendMessage(m_Window, WM_WA_IPC, (WPARAM)m_Shuffle, IPC_SET_SHUFFLE); + } +} + +/* +** Handles the SetRepeat bang. +** +*/ +void PlayerWinamp::SetRepeat(bool state) +{ + if (!m_PlayingStream) + { + m_Repeat = state; + SendMessage(m_Window, WM_WA_IPC, (WPARAM)m_Repeat, IPC_SET_REPEAT); + } +} + +/* +** Handles the ClosePlayer bang. +** +*/ +void PlayerWinamp::ClosePlayer() +{ + if (m_WinampType == WA_WINAMP) + { + SendMessage(m_Window, WM_CLOSE, 0, 0); + } + else // if (m_WinampType == WA_MEDIAMONKEY) + { + HWND wnd = FindWindow(L"TFMainWindow", L"MediaMonkey"); + if (wnd) + { + SendMessage(wnd, WM_CLOSE, 0, 0); + } + } +} + +/* +** Handles the OpenPlayer bang. +** +*/ +void PlayerWinamp::OpenPlayer(std::wstring& path) +{ + if (m_WinampType == WA_WINAMP) + { + ShellExecute(nullptr, L"open", path.empty() ? L"winamp.exe" : path.c_str(), nullptr, nullptr, SW_SHOW); + } + else // if (m_WinampType == WA_MEDIAMONKEY) + { + if (path.empty()) + { + // Gotta figure out where Winamp is located at + HKEY hKey; + RegOpenKeyEx(HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Clients\\Media\\MediaMonkey\\shell\\open\\command", + 0, + KEY_QUERY_VALUE, + &hKey); + + DWORD size = 512; + WCHAR* data = new WCHAR[size]; + DWORD type = 0; + + if (RegQueryValueEx(hKey, + nullptr, + nullptr, + (LPDWORD)&type, + (LPBYTE)data, + (LPDWORD)&size) == ERROR_SUCCESS) + { + if (type == REG_SZ) + { + ShellExecute(nullptr, L"open", data, nullptr, nullptr, SW_SHOW); + path = data; + } + } + + delete [] data; + RegCloseKey(hKey); + } + else + { + ShellExecute(nullptr, L"open", path.c_str(), nullptr, nullptr, SW_SHOW); + } + } +} diff --git a/Plugins/PluginNowPlaying/PlayerWinamp.h b/Plugins/PluginNowPlaying/PlayerWinamp.h index c9d50343..5a0c5aaf 100644 --- a/Plugins/PluginNowPlaying/PlayerWinamp.h +++ b/Plugins/PluginNowPlaying/PlayerWinamp.h @@ -1,69 +1,69 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __PLAYERWINAMP_H__ -#define __PLAYERWINAMP_H__ - -#include "Player.h" - -enum WINAMPTYPE -{ - WA_WINAMP, - WA_MEDIAMONKEY -}; - -class PlayerWinamp : public Player -{ -public: - virtual ~PlayerWinamp(); - - static Player* Create(WINAMPTYPE type); - - virtual void UpdateData(); - - virtual void Pause(); - virtual void Play(); - virtual void Stop(); - virtual void Next(); - virtual void Previous(); - virtual void SetPosition(int position); - virtual void SetRating(int rating); - virtual void SetVolume(int volume); - virtual void SetShuffle(bool state); - virtual void SetRepeat(bool state); - virtual void ClosePlayer(); - virtual void OpenPlayer(std::wstring& path); - -protected: - PlayerWinamp(WINAMPTYPE type); - -private: - bool CheckWindow(); - - static Player* c_Player; - - HWND m_Window; // Winamp window - DWORD m_LastCheckTime; - bool m_UseUnicodeAPI; - bool m_PlayingStream; - WINAMPTYPE m_WinampType; - HANDLE m_WinampHandle; // Handle to Winamp process - LPCVOID m_WinampAddress; -}; - -#endif +/* + Copyright (C) 2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __PLAYERWINAMP_H__ +#define __PLAYERWINAMP_H__ + +#include "Player.h" + +enum WINAMPTYPE +{ + WA_WINAMP, + WA_MEDIAMONKEY +}; + +class PlayerWinamp : public Player +{ +public: + virtual ~PlayerWinamp(); + + static Player* Create(WINAMPTYPE type); + + virtual void UpdateData(); + + virtual void Pause(); + virtual void Play(); + virtual void Stop(); + virtual void Next(); + virtual void Previous(); + virtual void SetPosition(int position); + virtual void SetRating(int rating); + virtual void SetVolume(int volume); + virtual void SetShuffle(bool state); + virtual void SetRepeat(bool state); + virtual void ClosePlayer(); + virtual void OpenPlayer(std::wstring& path); + +protected: + PlayerWinamp(WINAMPTYPE type); + +private: + bool CheckWindow(); + + static Player* c_Player; + + HWND m_Window; // Winamp window + DWORD m_LastCheckTime; + bool m_UseUnicodeAPI; + bool m_PlayingStream; + WINAMPTYPE m_WinampType; + HANDLE m_WinampHandle; // Handle to Winamp process + LPCVOID m_WinampAddress; +}; + +#endif diff --git a/Plugins/PluginNowPlaying/PluginNowPlaying.rc b/Plugins/PluginNowPlaying/PluginNowPlaying.rc index 3c4c0e21..805618ff 100644 --- a/Plugins/PluginNowPlaying/PluginNowPlaying.rc +++ b/Plugins/PluginNowPlaying/PluginNowPlaying.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,1,5,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.1.5.0" - VALUE "LegalCopyright", " 2012 - Birunthan Mohanathas" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,1,5,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.1.5.0" + VALUE "LegalCopyright", " 2012 - Birunthan Mohanathas" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj index 40ff376c..b000e646 100644 --- a/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj +++ b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj @@ -1,186 +1,186 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{C7FECFCD-E6C6-4F95-BB9A-E1762B043969}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>NowPlaying</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>./taglib;./taglib/toolkit;./taglib/asf;./taglib/mpeg;./taglib/ogg;./taglib/ogg/flac;./taglib/flac;./taglib/mpc;./taglib/ogg/vorbis;./taglib/mpeg/id3v2;./taglib/mpeg/id3v2/frames;./taglib/mpeg/id3v1;./taglib/ape;./taglib/wavpack;./taglib/mp4;.\SDKs\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <ExceptionHandling Condition="'$(Configuration)'=='Release'">false</ExceptionHandling> - <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">false</WholeProgramOptimization> - </ClCompile> - <Link> - <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration> - <AdditionalDependencies>Psapi.lib;WinInet.lib;comsuppwd.lib;%(AdditionalDependencies)</AdditionalDependencies> - <RuntimeTypeInfo>true</RuntimeTypeInfo> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClCompile Include="Cover.cpp"> - <PrecompiledHeader>Use</PrecompiledHeader> - </ClCompile> - <ClCompile Include="Internet.cpp"> - <PrecompiledHeader>Use</PrecompiledHeader> - </ClCompile> - <ClCompile Include="Lyrics.cpp"> - <PrecompiledHeader>Use</PrecompiledHeader> - </ClCompile> - <ClCompile Include="NowPlaying.cpp"> - <PrecompiledHeader>Use</PrecompiledHeader> - </ClCompile> - <ClCompile Include="Player.cpp"> - <PrecompiledHeader>Use</PrecompiledHeader> - </ClCompile> - <ClCompile Include="PlayerAIMP.cpp"> - <PrecompiledHeader>Use</PrecompiledHeader> - </ClCompile> - <ClCompile Include="PlayerCAD.cpp"> - <PrecompiledHeader>Use</PrecompiledHeader> - </ClCompile> - <ClCompile Include="PlayerITunes.cpp"> - <PrecompiledHeader>Use</PrecompiledHeader> - </ClCompile> - <ClCompile Include="PlayerSpotify.cpp"> - <PrecompiledHeader>Use</PrecompiledHeader> - </ClCompile> - <ClCompile Include="PlayerWinamp.cpp"> - <PrecompiledHeader>Use</PrecompiledHeader> - </ClCompile> - <ClCompile Include="PlayerWLM.cpp"> - <PrecompiledHeader>Use</PrecompiledHeader> - </ClCompile> - <ClCompile Include="PlayerWMP.cpp"> - <PrecompiledHeader>Use</PrecompiledHeader> - </ClCompile> - <ClCompile Include="SDKs\iTunes\iTunesCOMInterface_i.c" /> - <ClCompile Include="StdAfx.cpp"> - <PrecompiledHeader>Create</PrecompiledHeader> - </ClCompile> - <ClCompile Include="TagLibUnity.cpp" /> - </ItemGroup> - <ItemGroup> - <ClInclude Include="Cover.h" /> - <ClInclude Include="Internet.h" /> - <ClInclude Include="Lyrics.h" /> - <ClInclude Include="NowPlaying.h" /> - <ClInclude Include="Player.h" /> - <ClInclude Include="PlayerAIMP.h" /> - <ClInclude Include="PlayerCAD.h" /> - <ClInclude Include="PlayerITunes.h" /> - <ClInclude Include="PlayerSpotify.h" /> - <ClInclude Include="PlayerWinamp.h" /> - <ClInclude Include="PlayerWLM.h" /> - <ClInclude Include="PlayerWMP.h" /> - <ClInclude Include="SDKs\AIMP\aimp2_sdk.h" /> - <ClInclude Include="SDKs\CAD\cad_sdk.h" /> - <ClInclude Include="SDKs\iTunes\iTunesCOMInterface.h" /> - <ClInclude Include="SDKs\Winamp\wa_cmd.h" /> - <ClInclude Include="SDKs\Winamp\wa_dlg.h" /> - <ClInclude Include="SDKs\Winamp\wa_hotkeys.h" /> - <ClInclude Include="SDKs\Winamp\wa_ipc.h" /> - <ClInclude Include="StdAfx.h" /> - </ItemGroup> - <ItemGroup> - <ClInclude Include="taglib\tag.h" /> - <ClInclude Include="taglib\fileref.h" /> - <ClInclude Include="taglib\audioproperties.h" /> - <ClInclude Include="taglib\taglib_export.h" /> - <ClInclude Include="taglib\toolkit\taglib.h" /> - <ClInclude Include="taglib\toolkit\tpropertymap.h" /> - <ClInclude Include="taglib\toolkit\tstring.h" /> - <ClInclude Include="taglib\toolkit\tlist.h" /> - <ClInclude Include="taglib\toolkit\tstringlist.h" /> - <ClInclude Include="taglib\toolkit\tbytevector.h" /> - <ClInclude Include="taglib\toolkit\tbytevectorlist.h" /> - <ClInclude Include="taglib\toolkit\tbytevectorstream.h" /> - <ClInclude Include="taglib\toolkit\tiostream.h" /> - <ClInclude Include="taglib\toolkit\tfile.h" /> - <ClInclude Include="taglib\toolkit\tfilestream.h" /> - <ClInclude Include="taglib\toolkit\tmap.h" /> - <ClInclude Include="taglib\toolkit\trefcounter.h" /> - <ClInclude Include="taglib\toolkit\tdebuglistener.h" /> - <ClInclude Include="taglib\mp4\mp4atom.h" /> - <ClInclude Include="taglib\mp4\mp4coverart.h" /> - <ClInclude Include="taglib\mp4\mp4file.h" /> - <ClInclude Include="taglib\mp4\mp4item.h" /> - <ClInclude Include="taglib\mp4\mp4properties.h" /> - <ClInclude Include="taglib\mp4\mp4tag.h" /> - <ClInclude Include="taglib\mpeg\mpegfile.h" /> - <ClInclude Include="taglib\mpeg\mpegproperties.h" /> - <ClInclude Include="taglib\mpeg\mpegheader.h" /> - <ClInclude Include="taglib\mpeg\xingheader.h" /> - <ClInclude Include="taglib\mpeg\id3v1\id3v1tag.h" /> - <ClInclude Include="taglib\mpeg\id3v1\id3v1genres.h" /> - <ClInclude Include="taglib\mpeg\id3v2\id3v2extendedheader.h" /> - <ClInclude Include="taglib\mpeg\id3v2\id3v2frame.h" /> - <ClInclude Include="taglib\mpeg\id3v2\id3v2header.h" /> - <ClInclude Include="taglib\mpeg\id3v2\id3v2synchdata.h" /> - <ClInclude Include="taglib\mpeg\id3v2\id3v2footer.h" /> - <ClInclude Include="taglib\mpeg\id3v2\id3v2framefactory.h" /> - <ClInclude Include="taglib\mpeg\id3v2\id3v2tag.h" /> - <ClInclude Include="taglib\mpeg\id3v2\frames\attachedpictureframe.h" /> - <ClInclude Include="taglib\mpeg\id3v2\frames\commentsframe.h" /> - <ClInclude Include="taglib\mpeg\id3v2\frames\generalencapsulatedobjectframe.h" /> - <ClInclude Include="taglib\mpeg\id3v2\frames\ownershipframe.h" /> - <ClInclude Include="taglib\mpeg\id3v2\frames\popularimeterframe.h" /> - <ClInclude Include="taglib\mpeg\id3v2\frames\privateframe.h" /> - <ClInclude Include="taglib\mpeg\id3v2\frames\relativevolumeframe.h" /> - <ClInclude Include="taglib\mpeg\id3v2\frames\textidentificationframe.h" /> - <ClInclude Include="taglib\mpeg\id3v2\frames\uniquefileidentifierframe.h" /> - <ClInclude Include="taglib\mpeg\id3v2\frames\unknownframe.h" /> - <ClInclude Include="taglib\mpeg\id3v2\frames\unsynchronizedlyricsframe.h" /> - <ClInclude Include="taglib\mpeg\id3v2\frames\urllinkframe.h" /> - <ClInclude Include="taglib\ogg\oggfile.h" /> - <ClInclude Include="taglib\ogg\oggpage.h" /> - <ClInclude Include="taglib\ogg\oggpageheader.h" /> - <ClInclude Include="taglib\ogg\xiphcomment.h" /> - <ClInclude Include="taglib\ogg\vorbis\vorbisfile.h" /> - <ClInclude Include="taglib\ogg\vorbis\vorbisproperties.h" /> - <ClInclude Include="taglib\ogg\flac\oggflacfile.h" /> - <ClInclude Include="taglib\flac\flacfile.h" /> - <ClInclude Include="taglib\flac\flacpicture.h" /> - <ClInclude Include="taglib\flac\flacproperties.h" /> - <ClInclude Include="taglib\flac\flacmetadatablock.h" /> - <ClInclude Include="taglib\ape\apefile.h" /> - <ClInclude Include="taglib\ape\apeproperties.h" /> - <ClInclude Include="taglib\ape\apetag.h" /> - <ClInclude Include="taglib\ape\apefooter.h" /> - <ClInclude Include="taglib\ape\apeitem.h" /> - <ClInclude Include="taglib\mpc\mpcfile.h" /> - <ClInclude Include="taglib\mpc\mpcproperties.h" /> - <ClInclude Include="taglib\riff\wav\infotag.h" /> - <ClInclude Include="taglib\asf\asffile.h" /> - <ClInclude Include="taglib\asf\asfproperties.h" /> - <ClInclude Include="taglib\asf\asftag.h" /> - <ClInclude Include="taglib\asf\asfattribute.h" /> - <ClInclude Include="taglib\asf\asfpicture.h" /> - <ClCompile Include="TagLibUnity_ape.cpp" /> - <ClCompile Include="TagLibUnity_asf.cpp" /> - <ClCompile Include="TagLibUnity_flac.cpp" /> - <ClCompile Include="TagLibUnity_mp4.cpp" /> - <ClCompile Include="TagLibUnity_mpeg.cpp" /> - <ClCompile Include="TagLibUnity_mpeg_id3v2.cpp" /> - <ClCompile Include="TagLibUnity_ogg.cpp" /> - <ClCompile Include="TagLibUnity_toolkit.cpp" /> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="PluginNowPlaying.rc" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{C7FECFCD-E6C6-4F95-BB9A-E1762B043969}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>NowPlaying</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>./taglib;./taglib/toolkit;./taglib/asf;./taglib/mpeg;./taglib/ogg;./taglib/ogg/flac;./taglib/flac;./taglib/mpc;./taglib/ogg/vorbis;./taglib/mpeg/id3v2;./taglib/mpeg/id3v2/frames;./taglib/mpeg/id3v1;./taglib/ape;./taglib/wavpack;./taglib/mp4;.\SDKs\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <ExceptionHandling Condition="'$(Configuration)'=='Release'">false</ExceptionHandling> + <WholeProgramOptimization Condition="'$(Configuration)'=='Release'">false</WholeProgramOptimization> + </ClCompile> + <Link> + <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration> + <AdditionalDependencies>Psapi.lib;WinInet.lib;comsuppwd.lib;%(AdditionalDependencies)</AdditionalDependencies> + <RuntimeTypeInfo>true</RuntimeTypeInfo> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="Cover.cpp"> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + <ClCompile Include="Internet.cpp"> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + <ClCompile Include="Lyrics.cpp"> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + <ClCompile Include="NowPlaying.cpp"> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + <ClCompile Include="Player.cpp"> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + <ClCompile Include="PlayerAIMP.cpp"> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + <ClCompile Include="PlayerCAD.cpp"> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + <ClCompile Include="PlayerITunes.cpp"> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + <ClCompile Include="PlayerSpotify.cpp"> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + <ClCompile Include="PlayerWinamp.cpp"> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + <ClCompile Include="PlayerWLM.cpp"> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + <ClCompile Include="PlayerWMP.cpp"> + <PrecompiledHeader>Use</PrecompiledHeader> + </ClCompile> + <ClCompile Include="SDKs\iTunes\iTunesCOMInterface_i.c" /> + <ClCompile Include="StdAfx.cpp"> + <PrecompiledHeader>Create</PrecompiledHeader> + </ClCompile> + <ClCompile Include="TagLibUnity.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="Cover.h" /> + <ClInclude Include="Internet.h" /> + <ClInclude Include="Lyrics.h" /> + <ClInclude Include="NowPlaying.h" /> + <ClInclude Include="Player.h" /> + <ClInclude Include="PlayerAIMP.h" /> + <ClInclude Include="PlayerCAD.h" /> + <ClInclude Include="PlayerITunes.h" /> + <ClInclude Include="PlayerSpotify.h" /> + <ClInclude Include="PlayerWinamp.h" /> + <ClInclude Include="PlayerWLM.h" /> + <ClInclude Include="PlayerWMP.h" /> + <ClInclude Include="SDKs\AIMP\aimp2_sdk.h" /> + <ClInclude Include="SDKs\CAD\cad_sdk.h" /> + <ClInclude Include="SDKs\iTunes\iTunesCOMInterface.h" /> + <ClInclude Include="SDKs\Winamp\wa_cmd.h" /> + <ClInclude Include="SDKs\Winamp\wa_dlg.h" /> + <ClInclude Include="SDKs\Winamp\wa_hotkeys.h" /> + <ClInclude Include="SDKs\Winamp\wa_ipc.h" /> + <ClInclude Include="StdAfx.h" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="taglib\tag.h" /> + <ClInclude Include="taglib\fileref.h" /> + <ClInclude Include="taglib\audioproperties.h" /> + <ClInclude Include="taglib\taglib_export.h" /> + <ClInclude Include="taglib\toolkit\taglib.h" /> + <ClInclude Include="taglib\toolkit\tpropertymap.h" /> + <ClInclude Include="taglib\toolkit\tstring.h" /> + <ClInclude Include="taglib\toolkit\tlist.h" /> + <ClInclude Include="taglib\toolkit\tstringlist.h" /> + <ClInclude Include="taglib\toolkit\tbytevector.h" /> + <ClInclude Include="taglib\toolkit\tbytevectorlist.h" /> + <ClInclude Include="taglib\toolkit\tbytevectorstream.h" /> + <ClInclude Include="taglib\toolkit\tiostream.h" /> + <ClInclude Include="taglib\toolkit\tfile.h" /> + <ClInclude Include="taglib\toolkit\tfilestream.h" /> + <ClInclude Include="taglib\toolkit\tmap.h" /> + <ClInclude Include="taglib\toolkit\trefcounter.h" /> + <ClInclude Include="taglib\toolkit\tdebuglistener.h" /> + <ClInclude Include="taglib\mp4\mp4atom.h" /> + <ClInclude Include="taglib\mp4\mp4coverart.h" /> + <ClInclude Include="taglib\mp4\mp4file.h" /> + <ClInclude Include="taglib\mp4\mp4item.h" /> + <ClInclude Include="taglib\mp4\mp4properties.h" /> + <ClInclude Include="taglib\mp4\mp4tag.h" /> + <ClInclude Include="taglib\mpeg\mpegfile.h" /> + <ClInclude Include="taglib\mpeg\mpegproperties.h" /> + <ClInclude Include="taglib\mpeg\mpegheader.h" /> + <ClInclude Include="taglib\mpeg\xingheader.h" /> + <ClInclude Include="taglib\mpeg\id3v1\id3v1tag.h" /> + <ClInclude Include="taglib\mpeg\id3v1\id3v1genres.h" /> + <ClInclude Include="taglib\mpeg\id3v2\id3v2extendedheader.h" /> + <ClInclude Include="taglib\mpeg\id3v2\id3v2frame.h" /> + <ClInclude Include="taglib\mpeg\id3v2\id3v2header.h" /> + <ClInclude Include="taglib\mpeg\id3v2\id3v2synchdata.h" /> + <ClInclude Include="taglib\mpeg\id3v2\id3v2footer.h" /> + <ClInclude Include="taglib\mpeg\id3v2\id3v2framefactory.h" /> + <ClInclude Include="taglib\mpeg\id3v2\id3v2tag.h" /> + <ClInclude Include="taglib\mpeg\id3v2\frames\attachedpictureframe.h" /> + <ClInclude Include="taglib\mpeg\id3v2\frames\commentsframe.h" /> + <ClInclude Include="taglib\mpeg\id3v2\frames\generalencapsulatedobjectframe.h" /> + <ClInclude Include="taglib\mpeg\id3v2\frames\ownershipframe.h" /> + <ClInclude Include="taglib\mpeg\id3v2\frames\popularimeterframe.h" /> + <ClInclude Include="taglib\mpeg\id3v2\frames\privateframe.h" /> + <ClInclude Include="taglib\mpeg\id3v2\frames\relativevolumeframe.h" /> + <ClInclude Include="taglib\mpeg\id3v2\frames\textidentificationframe.h" /> + <ClInclude Include="taglib\mpeg\id3v2\frames\uniquefileidentifierframe.h" /> + <ClInclude Include="taglib\mpeg\id3v2\frames\unknownframe.h" /> + <ClInclude Include="taglib\mpeg\id3v2\frames\unsynchronizedlyricsframe.h" /> + <ClInclude Include="taglib\mpeg\id3v2\frames\urllinkframe.h" /> + <ClInclude Include="taglib\ogg\oggfile.h" /> + <ClInclude Include="taglib\ogg\oggpage.h" /> + <ClInclude Include="taglib\ogg\oggpageheader.h" /> + <ClInclude Include="taglib\ogg\xiphcomment.h" /> + <ClInclude Include="taglib\ogg\vorbis\vorbisfile.h" /> + <ClInclude Include="taglib\ogg\vorbis\vorbisproperties.h" /> + <ClInclude Include="taglib\ogg\flac\oggflacfile.h" /> + <ClInclude Include="taglib\flac\flacfile.h" /> + <ClInclude Include="taglib\flac\flacpicture.h" /> + <ClInclude Include="taglib\flac\flacproperties.h" /> + <ClInclude Include="taglib\flac\flacmetadatablock.h" /> + <ClInclude Include="taglib\ape\apefile.h" /> + <ClInclude Include="taglib\ape\apeproperties.h" /> + <ClInclude Include="taglib\ape\apetag.h" /> + <ClInclude Include="taglib\ape\apefooter.h" /> + <ClInclude Include="taglib\ape\apeitem.h" /> + <ClInclude Include="taglib\mpc\mpcfile.h" /> + <ClInclude Include="taglib\mpc\mpcproperties.h" /> + <ClInclude Include="taglib\riff\wav\infotag.h" /> + <ClInclude Include="taglib\asf\asffile.h" /> + <ClInclude Include="taglib\asf\asfproperties.h" /> + <ClInclude Include="taglib\asf\asftag.h" /> + <ClInclude Include="taglib\asf\asfattribute.h" /> + <ClInclude Include="taglib\asf\asfpicture.h" /> + <ClCompile Include="TagLibUnity_ape.cpp" /> + <ClCompile Include="TagLibUnity_asf.cpp" /> + <ClCompile Include="TagLibUnity_flac.cpp" /> + <ClCompile Include="TagLibUnity_mp4.cpp" /> + <ClCompile Include="TagLibUnity_mpeg.cpp" /> + <ClCompile Include="TagLibUnity_mpeg_id3v2.cpp" /> + <ClCompile Include="TagLibUnity_ogg.cpp" /> + <ClCompile Include="TagLibUnity_toolkit.cpp" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="PluginNowPlaying.rc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters index 6a81dce4..89675ca9 100644 --- a/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters +++ b/Plugins/PluginNowPlaying/PluginNowPlaying.vcxproj.filters @@ -1,386 +1,386 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="taglib"> - <UniqueIdentifier>{068012df-e981-4223-a90f-e0cc39dc46bb}</UniqueIdentifier> - </Filter> - <Filter Include="SDKs"> - <UniqueIdentifier>{1dbf5fab-83a1-45ab-8ab6-e5ae7b7b0516}</UniqueIdentifier> - </Filter> - <Filter Include="SDKs\AIMP"> - <UniqueIdentifier>{3ba19b2c-1c00-4093-a1b8-184aeaae6cc8}</UniqueIdentifier> - </Filter> - <Filter Include="SDKs\Winamp"> - <UniqueIdentifier>{18242178-1d8d-435b-8676-c5a0eb8c1f1b}</UniqueIdentifier> - </Filter> - <Filter Include="SDKs\iTunes"> - <UniqueIdentifier>{f632b821-b18a-445e-b7a2-2844b6633beb}</UniqueIdentifier> - </Filter> - <Filter Include="SDKs\CD Art Display"> - <UniqueIdentifier>{9e4422be-972a-442d-95f1-f238ef237a7b}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files"> - <UniqueIdentifier>{3f6e39c4-31fd-45a7-a450-6c090c99ff47}</UniqueIdentifier> - </Filter> - <Filter Include="Source Files"> - <UniqueIdentifier>{abad9374-731c-48b4-8ae1-45793b348013}</UniqueIdentifier> - </Filter> - </ItemGroup> - <ItemGroup> - <ClCompile Include="SDKs\iTunes\iTunesCOMInterface_i.c"> - <Filter>SDKs\iTunes</Filter> - </ClCompile> - <ClCompile Include="NowPlaying.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="PlayerWMP.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="Player.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="PlayerAIMP.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="PlayerCAD.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="PlayerITunes.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="PlayerSpotify.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="PlayerWinamp.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="StdAfx.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="PlayerWLM.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="Cover.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="Lyrics.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="Internet.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="TagLibUnity_toolkit.cpp"> - <Filter>taglib</Filter> - </ClCompile> - <ClCompile Include="TagLibUnity.cpp"> - <Filter>taglib</Filter> - </ClCompile> - <ClCompile Include="TagLibUnity_ape.cpp"> - <Filter>taglib</Filter> - </ClCompile> - <ClCompile Include="TagLibUnity_asf.cpp"> - <Filter>taglib</Filter> - </ClCompile> - <ClCompile Include="TagLibUnity_flac.cpp"> - <Filter>taglib</Filter> - </ClCompile> - <ClCompile Include="TagLibUnity_mp4.cpp"> - <Filter>taglib</Filter> - </ClCompile> - <ClCompile Include="TagLibUnity_mpeg.cpp"> - <Filter>taglib</Filter> - </ClCompile> - <ClCompile Include="TagLibUnity_mpeg_id3v2.cpp"> - <Filter>taglib</Filter> - </ClCompile> - <ClCompile Include="TagLibUnity_ogg.cpp"> - <Filter>taglib</Filter> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ClInclude Include="SDKs\AIMP\aimp2_sdk.h"> - <Filter>SDKs\AIMP</Filter> - </ClInclude> - <ClInclude Include="SDKs\iTunes\iTunesCOMInterface.h"> - <Filter>SDKs\iTunes</Filter> - </ClInclude> - <ClInclude Include="SDKs\Winamp\wa_dlg.h"> - <Filter>SDKs\Winamp</Filter> - </ClInclude> - <ClInclude Include="SDKs\Winamp\wa_hotkeys.h"> - <Filter>SDKs\Winamp</Filter> - </ClInclude> - <ClInclude Include="SDKs\Winamp\wa_ipc.h"> - <Filter>SDKs\Winamp</Filter> - </ClInclude> - <ClInclude Include="SDKs\Winamp\wa_cmd.h"> - <Filter>SDKs\Winamp</Filter> - </ClInclude> - <ClInclude Include="SDKs\CAD\cad_sdk.h"> - <Filter>SDKs\CD Art Display</Filter> - </ClInclude> - <ClInclude Include="PlayerCAD.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="PlayerAIMP.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="Player.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="NowPlaying.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="PlayerITunes.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="PlayerSpotify.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="PlayerWinamp.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="PlayerWMP.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="StdAfx.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="PlayerWLM.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="Cover.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="Lyrics.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="Internet.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="taglib\ape\apefile.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\ape\apefooter.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\ape\apeitem.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\ape\apeproperties.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\ape\apetag.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\asf\asfattribute.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\asf\asffile.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\asf\asfpicture.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\asf\asfproperties.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\asf\asftag.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\frames\attachedpictureframe.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\audioproperties.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\frames\commentsframe.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\fileref.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\flac\flacfile.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\flac\flacmetadatablock.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\flac\flacpicture.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\flac\flacproperties.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\frames\generalencapsulatedobjectframe.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v1\id3v1genres.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v1\id3v1tag.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\id3v2extendedheader.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\id3v2footer.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\id3v2frame.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\id3v2framefactory.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\id3v2header.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\id3v2synchdata.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\id3v2tag.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\riff\wav\infotag.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpc\mpcfile.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpc\mpcproperties.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\mpegfile.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\mpegheader.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\mpegproperties.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\ogg\oggfile.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\ogg\flac\oggflacfile.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\ogg\oggpage.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\ogg\oggpageheader.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\frames\ownershipframe.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\frames\popularimeterframe.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\frames\privateframe.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\frames\relativevolumeframe.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\tag.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\toolkit\taglib.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\taglib_export.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\toolkit\tbytevector.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\toolkit\tbytevectorlist.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\toolkit\tbytevectorstream.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\toolkit\tdebuglistener.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\frames\textidentificationframe.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\toolkit\tfile.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\toolkit\tfilestream.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\toolkit\tiostream.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\toolkit\tlist.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\toolkit\tmap.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\toolkit\trefcounter.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\toolkit\tstring.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\toolkit\tstringlist.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mp4\mp4atom.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mp4\mp4coverart.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mp4\mp4file.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mp4\mp4item.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mp4\mp4properties.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mp4\mp4tag.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\frames\uniquefileidentifierframe.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\frames\unknownframe.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\frames\unsynchronizedlyricsframe.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\id3v2\frames\urllinkframe.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\ogg\vorbis\vorbisfile.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\ogg\vorbis\vorbisproperties.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\mpeg\xingheader.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\ogg\xiphcomment.h"> - <Filter>taglib</Filter> - </ClInclude> - <ClInclude Include="taglib\toolkit\tpropertymap.h"> - <Filter>taglib</Filter> - </ClInclude> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="PluginNowPlaying.rc"> - <Filter>Source Files</Filter> - </ResourceCompile> - </ItemGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="taglib"> + <UniqueIdentifier>{068012df-e981-4223-a90f-e0cc39dc46bb}</UniqueIdentifier> + </Filter> + <Filter Include="SDKs"> + <UniqueIdentifier>{1dbf5fab-83a1-45ab-8ab6-e5ae7b7b0516}</UniqueIdentifier> + </Filter> + <Filter Include="SDKs\AIMP"> + <UniqueIdentifier>{3ba19b2c-1c00-4093-a1b8-184aeaae6cc8}</UniqueIdentifier> + </Filter> + <Filter Include="SDKs\Winamp"> + <UniqueIdentifier>{18242178-1d8d-435b-8676-c5a0eb8c1f1b}</UniqueIdentifier> + </Filter> + <Filter Include="SDKs\iTunes"> + <UniqueIdentifier>{f632b821-b18a-445e-b7a2-2844b6633beb}</UniqueIdentifier> + </Filter> + <Filter Include="SDKs\CD Art Display"> + <UniqueIdentifier>{9e4422be-972a-442d-95f1-f238ef237a7b}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{3f6e39c4-31fd-45a7-a450-6c090c99ff47}</UniqueIdentifier> + </Filter> + <Filter Include="Source Files"> + <UniqueIdentifier>{abad9374-731c-48b4-8ae1-45793b348013}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="SDKs\iTunes\iTunesCOMInterface_i.c"> + <Filter>SDKs\iTunes</Filter> + </ClCompile> + <ClCompile Include="NowPlaying.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="PlayerWMP.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="Player.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="PlayerAIMP.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="PlayerCAD.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="PlayerITunes.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="PlayerSpotify.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="PlayerWinamp.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="StdAfx.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="PlayerWLM.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="Cover.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="Lyrics.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="Internet.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="TagLibUnity_toolkit.cpp"> + <Filter>taglib</Filter> + </ClCompile> + <ClCompile Include="TagLibUnity.cpp"> + <Filter>taglib</Filter> + </ClCompile> + <ClCompile Include="TagLibUnity_ape.cpp"> + <Filter>taglib</Filter> + </ClCompile> + <ClCompile Include="TagLibUnity_asf.cpp"> + <Filter>taglib</Filter> + </ClCompile> + <ClCompile Include="TagLibUnity_flac.cpp"> + <Filter>taglib</Filter> + </ClCompile> + <ClCompile Include="TagLibUnity_mp4.cpp"> + <Filter>taglib</Filter> + </ClCompile> + <ClCompile Include="TagLibUnity_mpeg.cpp"> + <Filter>taglib</Filter> + </ClCompile> + <ClCompile Include="TagLibUnity_mpeg_id3v2.cpp"> + <Filter>taglib</Filter> + </ClCompile> + <ClCompile Include="TagLibUnity_ogg.cpp"> + <Filter>taglib</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="SDKs\AIMP\aimp2_sdk.h"> + <Filter>SDKs\AIMP</Filter> + </ClInclude> + <ClInclude Include="SDKs\iTunes\iTunesCOMInterface.h"> + <Filter>SDKs\iTunes</Filter> + </ClInclude> + <ClInclude Include="SDKs\Winamp\wa_dlg.h"> + <Filter>SDKs\Winamp</Filter> + </ClInclude> + <ClInclude Include="SDKs\Winamp\wa_hotkeys.h"> + <Filter>SDKs\Winamp</Filter> + </ClInclude> + <ClInclude Include="SDKs\Winamp\wa_ipc.h"> + <Filter>SDKs\Winamp</Filter> + </ClInclude> + <ClInclude Include="SDKs\Winamp\wa_cmd.h"> + <Filter>SDKs\Winamp</Filter> + </ClInclude> + <ClInclude Include="SDKs\CAD\cad_sdk.h"> + <Filter>SDKs\CD Art Display</Filter> + </ClInclude> + <ClInclude Include="PlayerCAD.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="PlayerAIMP.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="Player.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="NowPlaying.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="PlayerITunes.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="PlayerSpotify.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="PlayerWinamp.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="PlayerWMP.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="StdAfx.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="PlayerWLM.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="Cover.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="Lyrics.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="Internet.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="taglib\ape\apefile.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\ape\apefooter.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\ape\apeitem.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\ape\apeproperties.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\ape\apetag.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\asf\asfattribute.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\asf\asffile.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\asf\asfpicture.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\asf\asfproperties.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\asf\asftag.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\frames\attachedpictureframe.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\audioproperties.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\frames\commentsframe.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\fileref.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\flac\flacfile.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\flac\flacmetadatablock.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\flac\flacpicture.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\flac\flacproperties.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\frames\generalencapsulatedobjectframe.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v1\id3v1genres.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v1\id3v1tag.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\id3v2extendedheader.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\id3v2footer.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\id3v2frame.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\id3v2framefactory.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\id3v2header.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\id3v2synchdata.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\id3v2tag.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\riff\wav\infotag.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpc\mpcfile.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpc\mpcproperties.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\mpegfile.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\mpegheader.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\mpegproperties.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\ogg\oggfile.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\ogg\flac\oggflacfile.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\ogg\oggpage.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\ogg\oggpageheader.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\frames\ownershipframe.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\frames\popularimeterframe.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\frames\privateframe.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\frames\relativevolumeframe.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\tag.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\toolkit\taglib.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\taglib_export.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\toolkit\tbytevector.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\toolkit\tbytevectorlist.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\toolkit\tbytevectorstream.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\toolkit\tdebuglistener.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\frames\textidentificationframe.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\toolkit\tfile.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\toolkit\tfilestream.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\toolkit\tiostream.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\toolkit\tlist.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\toolkit\tmap.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\toolkit\trefcounter.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\toolkit\tstring.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\toolkit\tstringlist.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mp4\mp4atom.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mp4\mp4coverart.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mp4\mp4file.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mp4\mp4item.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mp4\mp4properties.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mp4\mp4tag.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\frames\uniquefileidentifierframe.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\frames\unknownframe.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\frames\unsynchronizedlyricsframe.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\id3v2\frames\urllinkframe.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\ogg\vorbis\vorbisfile.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\ogg\vorbis\vorbisproperties.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\mpeg\xingheader.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\ogg\xiphcomment.h"> + <Filter>taglib</Filter> + </ClInclude> + <ClInclude Include="taglib\toolkit\tpropertymap.h"> + <Filter>taglib</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="PluginNowPlaying.rc"> + <Filter>Source Files</Filter> + </ResourceCompile> + </ItemGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/SDKs/AIMP/aimp2_sdk.h b/Plugins/PluginNowPlaying/SDKs/AIMP/aimp2_sdk.h index b7afebea..4f28328d 100644 --- a/Plugins/PluginNowPlaying/SDKs/AIMP/aimp2_sdk.h +++ b/Plugins/PluginNowPlaying/SDKs/AIMP/aimp2_sdk.h @@ -1,726 +1,726 @@ -// Translated by Vitaliy Diatlov -// AIMP2: SDK (02.07.2009), v2.60 - -#ifndef AIMP2_SDK_H -#define AIMP2_SDK_H - -#include <windows.h> -#include <unknwn.h> - -const char AIMP2_RemoteClass[] = "AIMP2_RemoteInfo"; -const int AIMP2_RemoteFileSize = 2048; - -const int WM_AIMP_COMMAND = WM_USER + 0x75; // WParam = One of Command, LPARAM - Parameter - -const int WM_AIMP_STATUS_GET = 1; -const int WM_AIMP_STATUS_SET = 2;//HiWord of LParam - Command, LoWord of LParam - Parameter -const int WM_AIMP_CALLFUNC = 3;// LPARAM - Func ID (see below Func ID for Addons) -const int WM_AIMP_GET_VERSION = 4; -const int WM_AIMP_STATUS_CHANGE = 5; - -const int WM_LANG = WM_USER + 101; - - // CallBack types -const int AIMP_STATUS_CHANGE = 1; -const int AIMP_PLAY_FILE = 2; -const int AIMP_INFO_UPDATE = 5; // Update Info for current track -const int AIMP_PLAYER_STATE = 11; // Play/Pause/Stop -const int AIMP_EFFECT_CHANGED = 12; // Balance, Speed, Tempo, Pitch, Flanger and etc. -const int AIMP_EQ_CHANGED = 13; // Sliders changed -const int AIMP_TRACK_POS_CHANGED = 14; - - // AIMP_Status_Set / AIMP_Status_Get -const int AIMP_STS_VOLUME = 1; -const int AIMP_STS_BALANCE = 2; -const int AIMP_STS_SPEED = 3; -const int AIMP_STS_Player = 4; -const int AIMP_STS_MUTE = 5; -const int AIMP_STS_REVERB = 6; -const int AIMP_STS_ECHO = 7; -const int AIMP_STS_CHORUS = 8; -const int AIMP_STS_Flanger = 9; - -const int AIMP_STS_EQ_STS = 10; -const int AIMP_STS_EQ_SLDR01 = 11; -const int AIMP_STS_EQ_SLDR02 = 12; -const int AIMP_STS_EQ_SLDR03 = 13; -const int AIMP_STS_EQ_SLDR04 = 14; -const int AIMP_STS_EQ_SLDR05 = 15; -const int AIMP_STS_EQ_SLDR06 = 16; -const int AIMP_STS_EQ_SLDR07 = 17; -const int AIMP_STS_EQ_SLDR08 = 18; -const int AIMP_STS_EQ_SLDR09 = 19; -const int AIMP_STS_EQ_SLDR10 = 20; -const int AIMP_STS_EQ_SLDR11 = 21; -const int AIMP_STS_EQ_SLDR12 = 22; -const int AIMP_STS_EQ_SLDR13 = 23; -const int AIMP_STS_EQ_SLDR14 = 24; -const int AIMP_STS_EQ_SLDR15 = 25; -const int AIMP_STS_EQ_SLDR16 = 26; -const int AIMP_STS_EQ_SLDR17 = 27; -const int AIMP_STS_EQ_SLDR18 = 28; - -const int AIMP_STS_REPEAT = 29; -const int AIMP_STS_ON_STOP = 30; -const int AIMP_STS_POS = 31; -const int AIMP_STS_LENGTH = 32; -const int AIMP_STS_REPEATPLS = 33; -const int AIMP_STS_REP_PLS_1 = 34; -const int AIMP_STS_KBPS = 35; -const int AIMP_STS_KHZ = 36; -const int AIMP_STS_MODE = 37; -const int AIMP_STS_RADIO = 38; -const int AIMP_STS_STREAM_TYPE = 39; // Music / CDA / Radio -const int AIMP_STS_TIMER = 40; // Reverse / Normal -const int AIMP_STS_SHUFFLE = 41; - -const int AIMP_STS_MAIN_HWND = 42; -const int AIMP_STS_TC_HWND = 43; -const int AIMP_STS_APP_HWND = 44; -const int AIMP_STS_PL_HWND = 45; -const int AIMP_STS_EQ_HWND = 46; - -const int AIMP_STS_TRAY = 47; - - // Support Exts Flags -const int AIMP_PLS_EXTS = 1; -const int AIMP_AUDIO_EXTS = 2; - - // Menu IDs -const int AIMP_MAIN_MENU_OPN = 0; -const int AIMP_MAIN_MENU_UTILS = 1; -const int AIMP_MAIN_MENU_FNC = 2; -const int AIMP_MAIN_MENU_CFG = 3; -const int AIMP_UTILS_MENU = 4; -const int AIMP_PLS_MENU_ADD = 5; -const int AIMP_PLS_MENU_JUMP = 6; -const int AIMP_PLS_MENU_FNC = 7; -const int AIMP_PLS_MENU_SEND = 8; -const int AIMP_PLS_MENU_DEL = 9; -const int AIMP_ADD_MENU = 10; -const int AIMP_DEL_MENU = 11; -const int AIMP_FND_MENU = 12; -const int AIMP_SRT_MENU = 13; -const int AIMP_MSC_MENU = 14; -const int AIMP_PLS_MENU = 15; -const int AIMP_TRAY_UTILS = 16; -const int AIMP_TRAY = 17; -const int AIMP_EQ_LIB = 18; -// use AIMP_UTILS_MENU overthis: -// + AIMP_MAIN_MENU_UTILS = 1; -// + AIMP_TRAY_UTILS = 16; - - // AIMP_CallFunction -const int AIMP_OPEN_FILES = 0; -const int AIMP_OPEN_DIR = 1; -const int AIMP_ABOUT = 2; -const int AIMP_SLEEP_TIMER = 3; -const int AIMP_UTILS_AC = 4; -const int AIMP_UTILS_SR = 5; -const int AIMP_UTILS_TE = 6; -const int AIMP_UTILS_CDB = 7; -const int AIMP_OPTIONS = 8; -const int AIMP_PLUGINS = 9; -const int AIMP_QUIT = 10; -const int AIMP_NEXT_VIS = 11; -const int AIMP_PREV_VIS = 12; -const int AIMP_EQ_ANALOG = 13; -const int AIMP_TO_TRAY = 14; -const int AIMP_PLAY = 15; -const int AIMP_PAUSE = 16; -const int AIMP_STOP = 17; -const int AIMP_NEXT = 18; -const int AIMP_PREV = 19; -const int AIMP_ADD_FILES = 20; -const int AIMP_ADD_DIR = 21; -const int AIMP_ADD_PLS = 22; -const int AIMP_ADD_URL = 23; -const int AIMP_DEL_FILES = 24; -const int AIMP_DEL_BAD = 25; -const int AIMP_DEL_FROMHDD = 26; -const int AIMP_DEL_OFF = 27; -const int AIMP_DEL_OFF_HDD = 28; -const int AIMP_RESCAN_PLS = 29; -const int AIMP_SHOW_CURFILE = 30; -const int AIMP_SORT_INVERT = 31; -const int AIMP_SORT_RANDOM = 32; -const int AIMP_SORT_TITLE = 33; -const int AIMP_SORT_ARTIST = 34; -const int AIMP_SORT_FOLDER = 35; -const int AIMP_SORT_LENGTH = 36; -const int AIMP_SORT_RATING = 37; -const int AIMP_SEARCH = 38; -const int AIMP_OPEN_PLS = 39; -const int AIMP_SAVE_PLS = 40; -const int AIMP_PLAY_LAST = 41; -const int AIMP_OFF_SELECTED = 42; -const int AIMP_ON_SELECTED = 43; -const int AIMP_ADD2BOOKMARK = 44; -const int AIMP_EDITBOOKMARK = 45; - - - // For AIMP_GetPath -const int AIMP_CFG_DATA = 0; -const int AIMP_CFG_PLS = 1; -const int AIMP_CFG_LNG = 2; -const int AIMP_CFG_SKINS = 3; -const int AIMP_CFG_PLUGINS = 4; -const int AIMP_CFG_ICONS = 5; -const int AIMP_CFG_ML = 6; - - - // For AIMP_QueryObject -const int IAIMP2PlayerID = 0x0001; -const int IAIMP2PlaylistManagerID = 0x0003; -const int IAIMP2ExtendedID = 0x0004; -const int IAIMP2CoverArtManagerID = 0x0005; -const int IAIMP2PlaylistManager2ID = 0x0006; -const int IAIMPConfigFileID = 0x0010; -const int IAIMPLanguageFileID = 0x0011; - - - - // For AIMP_ObjectClass -const int AIMP_EXT_LC_MESSAGE = 100; -const int AIMP_EXT_ML_MESSAGE = 101; - - - // Option Frame Position Flags -const int AIMP_FRAME_POS_PLAY = 1; -const int AIMP_FRAME_POS_PLAYLIST = 2; -const int AIMP_FRAME_POS_PLAYER = 3; -const int AIMP_FRAME_POS_TEMPLATE = 4; -const int AIMP_FRAME_POS_SYSTEM = 5; -const int AIMP_FRAME_POS_SKINS = 6; -const int AIMP_FRAME_POS_LANGS = 7; - - // AIMP_PLS_SORT_TYPE_XXX -const int AIMP_PLS_SORT_TYPE_TITLE = 1; -const int AIMP_PLS_SORT_TYPE_FILENAME = 2; -const int AIMP_PLS_SORT_TYPE_DURATION = 3; -const int AIMP_PLS_SORT_TYPE_ARTIST = 4; -const int AIMP_PLS_SORT_TYPE_INVERSE = 5; -const int AIMP_PLS_SORT_TYPE_RANDOMIZE = 6; - -#pragma pack(push, 1) -struct AIMP2FileInfo -{ - DWORD cbSizeOf; - // - BOOL nActive; - DWORD nBitRate; - DWORD nChannels; - DWORD nDuration; - INT64 nFileSize; - DWORD nRating; - DWORD nSampleRate; - DWORD nTrackID; - // - DWORD nAlbumLen; - DWORD nArtistLen; - DWORD nDateLen; - DWORD nFileNameLen; - DWORD nGenreLen; - DWORD nTitleLen; - // - PWCHAR sAlbum; - PWCHAR sArtist; - PWCHAR sDate; - PWCHAR sFileName; - PWCHAR sGenre; - PWCHAR sTitle; -}; -#pragma pack(pop) -typedef boolean (WINAPI *AIMPPlaylistDeleteProc)(AIMP2FileInfo AFileInfo, DWORD AUserData); -typedef int (WINAPI *AIMPPlaylistSortProc)(AIMP2FileInfo AFileInfo1, AIMP2FileInfo AFileInfo2, DWORD AUserData); - -typedef void (WINAPI *AIMPMenuProc)(DWORD User, void *Handle); - -typedef void (WINAPI *AIMPStatusChange)(DWORD User, DWORD CallBackType); - -typedef void (WINAPI *CallBackFunc)(DWORD User, DWORD dwCBType); - -#pragma pack(push, 1) -struct PLSInfo -{ - PCHAR PLSName; - DWORD FileCount; - DWORD PLSDuration; - INT64 PLSSize; - int PlaylistID; -}; -#pragma pack(pop) - -#pragma pack(push, 1) -struct AIMPMenuInfo -{ - boolean Checkbox; - boolean RadioItem; - boolean Checked; - boolean Enabled; - int ProcPtr; // TAIMPMenuProc; - HBITMAP Bitmap; // 0 - no bmp - PWCHAR Caption; - DWORD User; -}; -#pragma pack(pop) - -class IPLSStrings - : public IUnknown -{ -public: - virtual boolean WINAPI AddFile( - PWCHAR FileName, - AIMP2FileInfo *FileInfo - ); - virtual boolean WINAPI DelFile( - int ID - ); - virtual PWCHAR WINAPI GetFileName( - int ID - ); - virtual boolean WINAPI GetFileInfo( - int ID, - AIMP2FileInfo *FileInfo - ); - virtual DWORD WINAPI GetFileObj( - int ID - ); - virtual int WINAPI GetCount(); -}; - -class IAIMP2Controller - :public IUnknown -{ -public: - virtual boolean WINAPI IsUnicodeVersion(); - virtual boolean WINAPI AIMP_CallBack_Set( - DWORD dwCBType, - CallBackFunc CallBackFuncPtr, - DWORD User - ); - virtual boolean WINAPI AIMP_CallBack_Remove( - DWORD dwCBType, - int ProcPtr - ); - // Status - virtual DWORD WINAPI AIMP_Status_Get( - DWORD StatusType - ); - virtual boolean WINAPI AIMP_Status_Set( - DWORD StatusType, - DWORD Value - ); - // Playlist - virtual boolean WINAPI AIMP_PLS_Clear( - int ID - ); - virtual boolean WINAPI AIMP_PLS_Delete( - int ID - ); - virtual boolean WINAPI AIMP_PLS_New( - PWCHAR Name - ); - virtual boolean WINAPI AIMP_PLS_Info( - int Index, - PLSInfo *info - ); - virtual short WINAPI AIMP_PLS_Count(); - virtual boolean WINAPI AIMP_PLS_GetFiles( - int ID, - IPLSStrings **Strings - ); - virtual boolean WINAPI AIMP_PLS_GetSelFiles( - int ID, - IPLSStrings **Strings - ); - virtual boolean WINAPI AIMP_PLS_AddFiles( - int ID, - IPLSStrings *Strings - ); - virtual boolean WINAPI AIMP_PLS_SetPLS( - int ID - ); - // System - virtual boolean WINAPI AIMP_NewStrings( - IPLSStrings **Strings - ); - virtual boolean WINAPI AIMP_GetCurrentTrack( - AIMP2FileInfo *AInfo - ); - virtual boolean WINAPI AIMP_QueryInfo( - PWCHAR Filename, - AIMP2FileInfo *AInfo - ); - virtual DWORD WINAPI AIMP_GetSystemVersion(); - virtual boolean WINAPI AIMP_CallFunction( - DWORD FuncID - ); - virtual int WINAPI AIMP_GetLanguage( - PWCHAR Str, - int ACount - ); - virtual int WINAPI AIMP_GetCfgPath( - PWCHAR Str, - int ACount - ); - virtual int WINAPI AIMP_GetSupportExts( - DWORD Flags, - PWCHAR Str, - int BufSize - ); - // Menu - virtual DWORD WINAPI AIMP_GetSupportExts( - DWORD Parent, - AIMPMenuInfo *MenuInfo - ); - virtual DWORD WINAPI AIMP_Menu_Create( - DWORD MenuID, - AIMPMenuInfo *MenuInfo - ); - virtual boolean WINAPI AIMP_Menu_Update( - int Handle, - AIMPMenuInfo *MenuInfo - ); - virtual boolean WINAPI AIMP_Menu_Remove( - int Handle - ); - // extention - virtual boolean WINAPI AIMP_QueryObject( - DWORD ObjectID, - void *Obj - ); -}; - -class IAIMPAddonHeader - :public IUnknown -{ -public: - virtual BOOL WINAPI GetHasSettingsDialog() = 0; - virtual PWCHAR WINAPI GetPluginAuthor() = 0; - virtual PWCHAR WINAPI GetPluginName() = 0; - virtual void WINAPI Finalize() = 0; - virtual void WINAPI Initialize(IAIMP2Controller *AController) = 0; - virtual void WINAPI ShowSettingsDialog(HWND AParentWindow) = 0; -}; - -typedef IAIMPAddonHeader *(WINAPI *AddonProc)(); - -typedef BOOL (WINAPI *AIMPAddonHeaderProc)(IAIMPAddonHeader *AHeader); -// Export function name: AIMP_QueryAddonEx - -//============================================================================== -// Old Style Addon struct - don't use for new plugins -//============================================================================== - -typedef PCHAR (WINAPI *GetPlgNameFunc)(); -typedef PCHAR (WINAPI *GetAutorFunc)(); -typedef void (WINAPI *InitFunc)(IAIMP2Controller *AIMP); -typedef void (WINAPI *ConfigFunc)(DWORD Handle, DWORD Win); -typedef void (WINAPI *FreeFunc)(); - -#pragma pack(push, 1) -struct AIMPAddonHeader -{ - DWORD version; - DWORD DllInstance; - GetPlgNameFunc PlgNameFuncPtr; - GetAutorFunc AutorFuncPtr; - InitFunc InitFuncPtr; - ConfigFunc ConfigFuncPtr; - FreeFunc FreeFuncPtr; -}; -#pragma pack(pop) - -//============================================================================== - -class IAIMP2OptionFrame - :public IUnknown -{ -public: - virtual HWND WINAPI FrameCreate( - HWND AParent - ); - virtual void *WINAPI FrameData( - ); // reserved - virtual int WINAPI FrameFlags( - ); // See FramePositionFlags - virtual PWCHAR WINAPI FrameName( - ); - virtual HWND WINAPI FrameFree( - HWND AWindow - ); - virtual void WINAPI FrameLoadConfigNotify( - ); - virtual void WINAPI FrameSaveConfigNotify( - ); -}; - -class IAIMP2Player - : public IUnknown -{ -public: - virtual int WINAPI Version(); - virtual boolean WINAPI PlayTrack( - int ID, - int ATrackIndex - ); - virtual void WINAPI PlayOrResume(); - virtual void WINAPI Pause(); - virtual void WINAPI Stop(); - virtual void WINAPI NextTrack(); - virtual void WINAPI PrevTrack(); -}; - -class IAIMP2PlaylistManager - : public IUnknown -{ -public: - virtual int WINAPI AIMP_PLS_CreateFromFile( - PWCHAR AFile, - boolean AActivate, - boolean AStartPlay - ); - virtual int WINAPI AIMP_PLS_ID_ActiveGet(); - virtual boolean WINAPI AIMP_PLS_ID_ActiveSet( - int ID - ); - virtual int WINAPI AIMP_PLS_ID_PlayingGet(); - virtual int WINAPI AIMP_PLS_ID_PlayingGetTrackIndex( - int ID - ); - virtual int WINAPI AIMP_PLS_NewEx( - PWCHAR AName, - boolean AActivate - ); - virtual boolean WINAPI AIMP_PLS_PlayFile( - PWCHAR AFileName, - boolean AFailIfNotExists - ); - // Playlist Processing - virtual boolean WINAPI AIMP_PLS_DeleteByFilter( - int ID, - DWORD AFilterProc, - DWORD AUserData - ); - virtual boolean WINAPI AIMP_PLS_SortByFilter( - int ID, - DWORD AFilterProc, - DWORD AUserData - ); - // Entries - virtual boolean WINAPI AIMP_PLS_Entry_Delete( - int ID, - int AEntryIndex - ); - virtual boolean WINAPI AIMP_PLS_Entry_DeleteAll( - int ID - ); - virtual boolean WINAPI AIMP_PLS_Entry_FileNameGet( - int ID, - int AEntryIndex, - PWCHAR PBuf, - DWORD ABufLen - ); - virtual boolean WINAPI AIMP_PLS_Entry_FileNameSet( - int ID, - int AEntryIndex, - PWCHAR PBuf - ); - virtual int WINAPI AIMP_PLS_Entry_FocusedGet( - int ID - ); - virtual boolean WINAPI AIMP_PLS_Entry_FocusedSet( - int ID, - int AEntryIndex - ); - virtual boolean WINAPI AIMP_PLS_Entry_InfoGet( - int ID, - int AEntryIndex, - AIMP2FileInfo *PFileInfo - ); - virtual boolean WINAPI AIMP_PLS_Entry_InfoSet( - int ID, - int AEntryIndex, - AIMP2FileInfo *PFileInfo - ); - virtual boolean WINAPI AIMP_PLS_Entry_PlayingSwitchGet( - int ID, - int AEntryIndex - ); - virtual boolean WINAPI AIMP_PLS_Entry_PlayingSwitchSet( - int ID, - int AEntryIndex, - boolean ASwitch - ); - virtual boolean WINAPI AIMP_PLS_Entry_ReloadInfo( - int ID, - int AEntryIndex - ); - // Load/Save Playlists - virtual boolean WINAPI AIMP_PM_DestroyStream( - DWORD AHandle - ); - virtual DWORD WINAPI AIMP_PM_ReadItem( - DWORD AHandle, - AIMP2FileInfo *PItem - ); - virtual DWORD WINAPI AIMP_PM_ReadStream( - PWCHAR AFileName, - int *Count - ); - virtual DWORD WINAPI AIMP_PM_SaveStream( - PWCHAR AFileName - ); - virtual DWORD WINAPI AIMP_PM_WriteItem( - DWORD AHandle, - AIMP2FileInfo *PItem - ); - // added in 2.50 B295 - virtual boolean WINAPI AIMP_PLS_ID_PlayingSetTrackIndex( - int ID, - int AEntryIndex - ); -}; - -class IAIMP2PlaylistManager2 - : public IAIMP2PlaylistManager -{ -public: - // Count of loaded playlists - virtual unsigned short WINAPI AIMP_PLS_Count(); - // Return = -1 - ID is not valid, otherthis - count of files in playlist - virtual int WINAPI AIMP_PLS_GetFilesCount(int ID); - virtual HRESULT WINAPI AIMP_PLS_GetInfo(int ID, INT64 *ADuration, INT64 *ASize); - virtual HRESULT WINAPI AIMP_PLS_GetName(int ID, PWCHAR ABuffer, int ABufferSizeInChars); - // Custom Sorting, see AIMP_PLS_SORT_TYPE_XXX - virtual HRESULT WINAPI AIMP_PLS_Sort(int ID, int ASortType); - virtual HRESULT WINAPI AIMP_PLS_SortByTemplate(int ID, PWCHAR ABuffer, int ABufferSizeInChars); - // if Index = -1 returned ID of current playlist. - virtual HRESULT WINAPI AIMP_PLS_ID_By_Index(int Index, int *ID); - // Get Formated title for Entry - virtual HRESULT WINAPI AIMP_PLS_Entry_GetTitle(int ID, int AEntryIndex, - PWCHAR ABuffer, int ABufferSizeInChars); - // Set Entry to playback queue - virtual HRESULT WINAPI AIMP_PLS_Entry_QueueRemove(int ID, int AEntryIndex); - virtual HRESULT WINAPI AIMP_PLS_Entry_QueueSet(int ID, int AEntryIndex, BOOL AInsertAtQueueBegining); - // Moving Entry - virtual HRESULT WINAPI AIMP_PLS_Entry_SetPosition(int ID, int AEntryIndex, int ANewEntryIndex); -}; - -// See IAIMP2ExtendedID -class IAIMP2Extended - :public IUnknown -{ -public: - virtual int WINAPI AIMP_GetPath( - int ID, - PWCHAR buffer, - int bufSize - ); - virtual boolean WINAPI AIMP_ObjectClass( - int ID, - void *AData, - boolean ARegister - ); - // User Option Dialogs - virtual DWORD WINAPI AIMP_Options_FrameAdd( - IAIMP2OptionFrame *AFrame - ); - virtual DWORD WINAPI AIMP_Options_FrameRemove( - IAIMP2OptionFrame *AFrame - ); - virtual DWORD WINAPI AIMP_Options_ModifiedChanged( - IAIMP2OptionFrame *AFrame - ); -}; - -class IAIMP2CoverArtManager - :public IUnknown -{ -public: - // Return picture will be proportional stretched to ADisplaySize value - virtual HBITMAP WINAPI GetCoverArtForFile(PWCHAR AFile, const SIZE *ADisplaySize); - // Draw CoverArt of playing file, Return - cover art drawing successfuly - // CoverArt will be proportional stretched to R value - virtual HRESULT WINAPI CurrentCoverArtDraw(HDC DC, const RECT *R); - // Return <> S_OK, CoverArt is empty or file are not playing - virtual HRESULT WINAPI CurrentCoverArtGetSize(SIZE *ASize); - // W, H - destination display sizes, function will correct sizes for proportional drawing - // Return <> S_OK, CoverArt is empty or file are not playing - virtual HRESULT WINAPI CurrentCoverArtCorrectSizes(int *W, int *H); -}; - - // See IAIMPLanguageFileID -class IAIMPLanguageFile - :public IUnknown -{ -public: - virtual int AIMP_Lang_Version(); - virtual int AIMP_Lang_CurrentFile(PWCHAR ABuffer, int ABufferSizeInChars); - virtual HRESULT AIMP_Lang_IsSectionExists(PWCHAR ASectionName, int ASectionNameSizeInChars); - virtual HRESULT AIMP_Lang_ReadString(PWCHAR ASectionName, PWCHAR AItemName, PWCHAR AValueBuffer, - int ASectionNameSizeInChars, int AItemNameSizeInChars, int AValueBufferSizeInChars); - // When Language changed AIMP will send to window handle "WM_LANG" message - virtual HRESULT AIMP_Lang_Notification(HWND AWndHandle, BOOL ARegister); -}; - -// See IAIMPConfigFileID -class IAIMPConfigFile - :public IUnknown -{ - // functions return null value, if value don't exists in configuration file - virtual HRESULT AIMP_Config_ReadString(PWCHAR ASectionName, PWCHAR AItemName, PWCHAR AValueBuffer, - int ASectionNameSizeInChars, int AItemNameSizeInChars, int AValueBufferSizeInChars); - virtual HRESULT AIMP_Config_ReadInteger(PWCHAR ASectionName, PWCHAR AItemName, - int ASectionNameSizeInChars, int AItemNameSizeInChars, int * AValue); - // - virtual HRESULT AIMP_Config_WriteString(PWCHAR ASectionName, PWCHAR AItemName, PWCHAR AValueBuffer, - int ASectionNameSizeInChars, int AItemNameSizeInChars, int AValueBufferSizeInChars); - virtual HRESULT AIMP_Config_WriteInteger(PWCHAR ASectionName, PWCHAR AItemName, - int ASectionNameSizeInChars, int AItemNameSizeInChars, int AValue); - // - virtual HRESULT AIMP_Config_IsSectionExists(PWCHAR ASectionName, int ASectionNameSizeInChars); - virtual HRESULT AIMP_Config_RemoveSection(PWCHAR ASectionName, int ASectionNameSizeInChars); -}; - -//============================================================================== -// V I S U A L S -//============================================================================== - -const int VIS_RQD_DATA_WAVE = 1; -const int VIS_RQD_DATA_SPECTRUM = 2; -const int VIS_RQD_NOT_SUSPEND = 4; - -typedef short WaveForm[2][512]; -typedef short Spectrum[2][256]; - -struct AIMPVisualData -{ - int LevelR; - int LevelL; - Spectrum spectrum; - WaveForm waveForm; -}; - -typedef AIMPVisualData *PAIMPVisualData; - -class IAIMP2VisualPlugin - :public IUnknown -{ -public: - virtual PWCHAR WINAPI AuthorName(); - virtual PWCHAR WINAPI PluginName(); - virtual PWCHAR WINAPI PluginInfo(); - virtual DWORD WINAPI PluginFlags(); - virtual BOOL WINAPI Initialize(); - virtual void WINAPI Deinitialize(); - virtual void WINAPI DisplayClick(int X, int Y); - virtual void WINAPI DisplayRender(HDC DC, PAIMPVisualData AData); - virtual void WINAPI DisplayResize(int AWidth, int AHeight); -}; - -// Export function name: AIMP_QueryVisual -typedef IAIMP2VisualPlugin *(WINAPI *AIMPVisualProc)(); - +// Translated by Vitaliy Diatlov +// AIMP2: SDK (02.07.2009), v2.60 + +#ifndef AIMP2_SDK_H +#define AIMP2_SDK_H + +#include <windows.h> +#include <unknwn.h> + +const char AIMP2_RemoteClass[] = "AIMP2_RemoteInfo"; +const int AIMP2_RemoteFileSize = 2048; + +const int WM_AIMP_COMMAND = WM_USER + 0x75; // WParam = One of Command, LPARAM - Parameter + +const int WM_AIMP_STATUS_GET = 1; +const int WM_AIMP_STATUS_SET = 2;//HiWord of LParam - Command, LoWord of LParam - Parameter +const int WM_AIMP_CALLFUNC = 3;// LPARAM - Func ID (see below Func ID for Addons) +const int WM_AIMP_GET_VERSION = 4; +const int WM_AIMP_STATUS_CHANGE = 5; + +const int WM_LANG = WM_USER + 101; + + // CallBack types +const int AIMP_STATUS_CHANGE = 1; +const int AIMP_PLAY_FILE = 2; +const int AIMP_INFO_UPDATE = 5; // Update Info for current track +const int AIMP_PLAYER_STATE = 11; // Play/Pause/Stop +const int AIMP_EFFECT_CHANGED = 12; // Balance, Speed, Tempo, Pitch, Flanger and etc. +const int AIMP_EQ_CHANGED = 13; // Sliders changed +const int AIMP_TRACK_POS_CHANGED = 14; + + // AIMP_Status_Set / AIMP_Status_Get +const int AIMP_STS_VOLUME = 1; +const int AIMP_STS_BALANCE = 2; +const int AIMP_STS_SPEED = 3; +const int AIMP_STS_Player = 4; +const int AIMP_STS_MUTE = 5; +const int AIMP_STS_REVERB = 6; +const int AIMP_STS_ECHO = 7; +const int AIMP_STS_CHORUS = 8; +const int AIMP_STS_Flanger = 9; + +const int AIMP_STS_EQ_STS = 10; +const int AIMP_STS_EQ_SLDR01 = 11; +const int AIMP_STS_EQ_SLDR02 = 12; +const int AIMP_STS_EQ_SLDR03 = 13; +const int AIMP_STS_EQ_SLDR04 = 14; +const int AIMP_STS_EQ_SLDR05 = 15; +const int AIMP_STS_EQ_SLDR06 = 16; +const int AIMP_STS_EQ_SLDR07 = 17; +const int AIMP_STS_EQ_SLDR08 = 18; +const int AIMP_STS_EQ_SLDR09 = 19; +const int AIMP_STS_EQ_SLDR10 = 20; +const int AIMP_STS_EQ_SLDR11 = 21; +const int AIMP_STS_EQ_SLDR12 = 22; +const int AIMP_STS_EQ_SLDR13 = 23; +const int AIMP_STS_EQ_SLDR14 = 24; +const int AIMP_STS_EQ_SLDR15 = 25; +const int AIMP_STS_EQ_SLDR16 = 26; +const int AIMP_STS_EQ_SLDR17 = 27; +const int AIMP_STS_EQ_SLDR18 = 28; + +const int AIMP_STS_REPEAT = 29; +const int AIMP_STS_ON_STOP = 30; +const int AIMP_STS_POS = 31; +const int AIMP_STS_LENGTH = 32; +const int AIMP_STS_REPEATPLS = 33; +const int AIMP_STS_REP_PLS_1 = 34; +const int AIMP_STS_KBPS = 35; +const int AIMP_STS_KHZ = 36; +const int AIMP_STS_MODE = 37; +const int AIMP_STS_RADIO = 38; +const int AIMP_STS_STREAM_TYPE = 39; // Music / CDA / Radio +const int AIMP_STS_TIMER = 40; // Reverse / Normal +const int AIMP_STS_SHUFFLE = 41; + +const int AIMP_STS_MAIN_HWND = 42; +const int AIMP_STS_TC_HWND = 43; +const int AIMP_STS_APP_HWND = 44; +const int AIMP_STS_PL_HWND = 45; +const int AIMP_STS_EQ_HWND = 46; + +const int AIMP_STS_TRAY = 47; + + // Support Exts Flags +const int AIMP_PLS_EXTS = 1; +const int AIMP_AUDIO_EXTS = 2; + + // Menu IDs +const int AIMP_MAIN_MENU_OPN = 0; +const int AIMP_MAIN_MENU_UTILS = 1; +const int AIMP_MAIN_MENU_FNC = 2; +const int AIMP_MAIN_MENU_CFG = 3; +const int AIMP_UTILS_MENU = 4; +const int AIMP_PLS_MENU_ADD = 5; +const int AIMP_PLS_MENU_JUMP = 6; +const int AIMP_PLS_MENU_FNC = 7; +const int AIMP_PLS_MENU_SEND = 8; +const int AIMP_PLS_MENU_DEL = 9; +const int AIMP_ADD_MENU = 10; +const int AIMP_DEL_MENU = 11; +const int AIMP_FND_MENU = 12; +const int AIMP_SRT_MENU = 13; +const int AIMP_MSC_MENU = 14; +const int AIMP_PLS_MENU = 15; +const int AIMP_TRAY_UTILS = 16; +const int AIMP_TRAY = 17; +const int AIMP_EQ_LIB = 18; +// use AIMP_UTILS_MENU overthis: +// + AIMP_MAIN_MENU_UTILS = 1; +// + AIMP_TRAY_UTILS = 16; + + // AIMP_CallFunction +const int AIMP_OPEN_FILES = 0; +const int AIMP_OPEN_DIR = 1; +const int AIMP_ABOUT = 2; +const int AIMP_SLEEP_TIMER = 3; +const int AIMP_UTILS_AC = 4; +const int AIMP_UTILS_SR = 5; +const int AIMP_UTILS_TE = 6; +const int AIMP_UTILS_CDB = 7; +const int AIMP_OPTIONS = 8; +const int AIMP_PLUGINS = 9; +const int AIMP_QUIT = 10; +const int AIMP_NEXT_VIS = 11; +const int AIMP_PREV_VIS = 12; +const int AIMP_EQ_ANALOG = 13; +const int AIMP_TO_TRAY = 14; +const int AIMP_PLAY = 15; +const int AIMP_PAUSE = 16; +const int AIMP_STOP = 17; +const int AIMP_NEXT = 18; +const int AIMP_PREV = 19; +const int AIMP_ADD_FILES = 20; +const int AIMP_ADD_DIR = 21; +const int AIMP_ADD_PLS = 22; +const int AIMP_ADD_URL = 23; +const int AIMP_DEL_FILES = 24; +const int AIMP_DEL_BAD = 25; +const int AIMP_DEL_FROMHDD = 26; +const int AIMP_DEL_OFF = 27; +const int AIMP_DEL_OFF_HDD = 28; +const int AIMP_RESCAN_PLS = 29; +const int AIMP_SHOW_CURFILE = 30; +const int AIMP_SORT_INVERT = 31; +const int AIMP_SORT_RANDOM = 32; +const int AIMP_SORT_TITLE = 33; +const int AIMP_SORT_ARTIST = 34; +const int AIMP_SORT_FOLDER = 35; +const int AIMP_SORT_LENGTH = 36; +const int AIMP_SORT_RATING = 37; +const int AIMP_SEARCH = 38; +const int AIMP_OPEN_PLS = 39; +const int AIMP_SAVE_PLS = 40; +const int AIMP_PLAY_LAST = 41; +const int AIMP_OFF_SELECTED = 42; +const int AIMP_ON_SELECTED = 43; +const int AIMP_ADD2BOOKMARK = 44; +const int AIMP_EDITBOOKMARK = 45; + + + // For AIMP_GetPath +const int AIMP_CFG_DATA = 0; +const int AIMP_CFG_PLS = 1; +const int AIMP_CFG_LNG = 2; +const int AIMP_CFG_SKINS = 3; +const int AIMP_CFG_PLUGINS = 4; +const int AIMP_CFG_ICONS = 5; +const int AIMP_CFG_ML = 6; + + + // For AIMP_QueryObject +const int IAIMP2PlayerID = 0x0001; +const int IAIMP2PlaylistManagerID = 0x0003; +const int IAIMP2ExtendedID = 0x0004; +const int IAIMP2CoverArtManagerID = 0x0005; +const int IAIMP2PlaylistManager2ID = 0x0006; +const int IAIMPConfigFileID = 0x0010; +const int IAIMPLanguageFileID = 0x0011; + + + + // For AIMP_ObjectClass +const int AIMP_EXT_LC_MESSAGE = 100; +const int AIMP_EXT_ML_MESSAGE = 101; + + + // Option Frame Position Flags +const int AIMP_FRAME_POS_PLAY = 1; +const int AIMP_FRAME_POS_PLAYLIST = 2; +const int AIMP_FRAME_POS_PLAYER = 3; +const int AIMP_FRAME_POS_TEMPLATE = 4; +const int AIMP_FRAME_POS_SYSTEM = 5; +const int AIMP_FRAME_POS_SKINS = 6; +const int AIMP_FRAME_POS_LANGS = 7; + + // AIMP_PLS_SORT_TYPE_XXX +const int AIMP_PLS_SORT_TYPE_TITLE = 1; +const int AIMP_PLS_SORT_TYPE_FILENAME = 2; +const int AIMP_PLS_SORT_TYPE_DURATION = 3; +const int AIMP_PLS_SORT_TYPE_ARTIST = 4; +const int AIMP_PLS_SORT_TYPE_INVERSE = 5; +const int AIMP_PLS_SORT_TYPE_RANDOMIZE = 6; + +#pragma pack(push, 1) +struct AIMP2FileInfo +{ + DWORD cbSizeOf; + // + BOOL nActive; + DWORD nBitRate; + DWORD nChannels; + DWORD nDuration; + INT64 nFileSize; + DWORD nRating; + DWORD nSampleRate; + DWORD nTrackID; + // + DWORD nAlbumLen; + DWORD nArtistLen; + DWORD nDateLen; + DWORD nFileNameLen; + DWORD nGenreLen; + DWORD nTitleLen; + // + PWCHAR sAlbum; + PWCHAR sArtist; + PWCHAR sDate; + PWCHAR sFileName; + PWCHAR sGenre; + PWCHAR sTitle; +}; +#pragma pack(pop) +typedef boolean (WINAPI *AIMPPlaylistDeleteProc)(AIMP2FileInfo AFileInfo, DWORD AUserData); +typedef int (WINAPI *AIMPPlaylistSortProc)(AIMP2FileInfo AFileInfo1, AIMP2FileInfo AFileInfo2, DWORD AUserData); + +typedef void (WINAPI *AIMPMenuProc)(DWORD User, void *Handle); + +typedef void (WINAPI *AIMPStatusChange)(DWORD User, DWORD CallBackType); + +typedef void (WINAPI *CallBackFunc)(DWORD User, DWORD dwCBType); + +#pragma pack(push, 1) +struct PLSInfo +{ + PCHAR PLSName; + DWORD FileCount; + DWORD PLSDuration; + INT64 PLSSize; + int PlaylistID; +}; +#pragma pack(pop) + +#pragma pack(push, 1) +struct AIMPMenuInfo +{ + boolean Checkbox; + boolean RadioItem; + boolean Checked; + boolean Enabled; + int ProcPtr; // TAIMPMenuProc; + HBITMAP Bitmap; // 0 - no bmp + PWCHAR Caption; + DWORD User; +}; +#pragma pack(pop) + +class IPLSStrings + : public IUnknown +{ +public: + virtual boolean WINAPI AddFile( + PWCHAR FileName, + AIMP2FileInfo *FileInfo + ); + virtual boolean WINAPI DelFile( + int ID + ); + virtual PWCHAR WINAPI GetFileName( + int ID + ); + virtual boolean WINAPI GetFileInfo( + int ID, + AIMP2FileInfo *FileInfo + ); + virtual DWORD WINAPI GetFileObj( + int ID + ); + virtual int WINAPI GetCount(); +}; + +class IAIMP2Controller + :public IUnknown +{ +public: + virtual boolean WINAPI IsUnicodeVersion(); + virtual boolean WINAPI AIMP_CallBack_Set( + DWORD dwCBType, + CallBackFunc CallBackFuncPtr, + DWORD User + ); + virtual boolean WINAPI AIMP_CallBack_Remove( + DWORD dwCBType, + int ProcPtr + ); + // Status + virtual DWORD WINAPI AIMP_Status_Get( + DWORD StatusType + ); + virtual boolean WINAPI AIMP_Status_Set( + DWORD StatusType, + DWORD Value + ); + // Playlist + virtual boolean WINAPI AIMP_PLS_Clear( + int ID + ); + virtual boolean WINAPI AIMP_PLS_Delete( + int ID + ); + virtual boolean WINAPI AIMP_PLS_New( + PWCHAR Name + ); + virtual boolean WINAPI AIMP_PLS_Info( + int Index, + PLSInfo *info + ); + virtual short WINAPI AIMP_PLS_Count(); + virtual boolean WINAPI AIMP_PLS_GetFiles( + int ID, + IPLSStrings **Strings + ); + virtual boolean WINAPI AIMP_PLS_GetSelFiles( + int ID, + IPLSStrings **Strings + ); + virtual boolean WINAPI AIMP_PLS_AddFiles( + int ID, + IPLSStrings *Strings + ); + virtual boolean WINAPI AIMP_PLS_SetPLS( + int ID + ); + // System + virtual boolean WINAPI AIMP_NewStrings( + IPLSStrings **Strings + ); + virtual boolean WINAPI AIMP_GetCurrentTrack( + AIMP2FileInfo *AInfo + ); + virtual boolean WINAPI AIMP_QueryInfo( + PWCHAR Filename, + AIMP2FileInfo *AInfo + ); + virtual DWORD WINAPI AIMP_GetSystemVersion(); + virtual boolean WINAPI AIMP_CallFunction( + DWORD FuncID + ); + virtual int WINAPI AIMP_GetLanguage( + PWCHAR Str, + int ACount + ); + virtual int WINAPI AIMP_GetCfgPath( + PWCHAR Str, + int ACount + ); + virtual int WINAPI AIMP_GetSupportExts( + DWORD Flags, + PWCHAR Str, + int BufSize + ); + // Menu + virtual DWORD WINAPI AIMP_GetSupportExts( + DWORD Parent, + AIMPMenuInfo *MenuInfo + ); + virtual DWORD WINAPI AIMP_Menu_Create( + DWORD MenuID, + AIMPMenuInfo *MenuInfo + ); + virtual boolean WINAPI AIMP_Menu_Update( + int Handle, + AIMPMenuInfo *MenuInfo + ); + virtual boolean WINAPI AIMP_Menu_Remove( + int Handle + ); + // extention + virtual boolean WINAPI AIMP_QueryObject( + DWORD ObjectID, + void *Obj + ); +}; + +class IAIMPAddonHeader + :public IUnknown +{ +public: + virtual BOOL WINAPI GetHasSettingsDialog() = 0; + virtual PWCHAR WINAPI GetPluginAuthor() = 0; + virtual PWCHAR WINAPI GetPluginName() = 0; + virtual void WINAPI Finalize() = 0; + virtual void WINAPI Initialize(IAIMP2Controller *AController) = 0; + virtual void WINAPI ShowSettingsDialog(HWND AParentWindow) = 0; +}; + +typedef IAIMPAddonHeader *(WINAPI *AddonProc)(); + +typedef BOOL (WINAPI *AIMPAddonHeaderProc)(IAIMPAddonHeader *AHeader); +// Export function name: AIMP_QueryAddonEx + +//============================================================================== +// Old Style Addon struct - don't use for new plugins +//============================================================================== + +typedef PCHAR (WINAPI *GetPlgNameFunc)(); +typedef PCHAR (WINAPI *GetAutorFunc)(); +typedef void (WINAPI *InitFunc)(IAIMP2Controller *AIMP); +typedef void (WINAPI *ConfigFunc)(DWORD Handle, DWORD Win); +typedef void (WINAPI *FreeFunc)(); + +#pragma pack(push, 1) +struct AIMPAddonHeader +{ + DWORD version; + DWORD DllInstance; + GetPlgNameFunc PlgNameFuncPtr; + GetAutorFunc AutorFuncPtr; + InitFunc InitFuncPtr; + ConfigFunc ConfigFuncPtr; + FreeFunc FreeFuncPtr; +}; +#pragma pack(pop) + +//============================================================================== + +class IAIMP2OptionFrame + :public IUnknown +{ +public: + virtual HWND WINAPI FrameCreate( + HWND AParent + ); + virtual void *WINAPI FrameData( + ); // reserved + virtual int WINAPI FrameFlags( + ); // See FramePositionFlags + virtual PWCHAR WINAPI FrameName( + ); + virtual HWND WINAPI FrameFree( + HWND AWindow + ); + virtual void WINAPI FrameLoadConfigNotify( + ); + virtual void WINAPI FrameSaveConfigNotify( + ); +}; + +class IAIMP2Player + : public IUnknown +{ +public: + virtual int WINAPI Version(); + virtual boolean WINAPI PlayTrack( + int ID, + int ATrackIndex + ); + virtual void WINAPI PlayOrResume(); + virtual void WINAPI Pause(); + virtual void WINAPI Stop(); + virtual void WINAPI NextTrack(); + virtual void WINAPI PrevTrack(); +}; + +class IAIMP2PlaylistManager + : public IUnknown +{ +public: + virtual int WINAPI AIMP_PLS_CreateFromFile( + PWCHAR AFile, + boolean AActivate, + boolean AStartPlay + ); + virtual int WINAPI AIMP_PLS_ID_ActiveGet(); + virtual boolean WINAPI AIMP_PLS_ID_ActiveSet( + int ID + ); + virtual int WINAPI AIMP_PLS_ID_PlayingGet(); + virtual int WINAPI AIMP_PLS_ID_PlayingGetTrackIndex( + int ID + ); + virtual int WINAPI AIMP_PLS_NewEx( + PWCHAR AName, + boolean AActivate + ); + virtual boolean WINAPI AIMP_PLS_PlayFile( + PWCHAR AFileName, + boolean AFailIfNotExists + ); + // Playlist Processing + virtual boolean WINAPI AIMP_PLS_DeleteByFilter( + int ID, + DWORD AFilterProc, + DWORD AUserData + ); + virtual boolean WINAPI AIMP_PLS_SortByFilter( + int ID, + DWORD AFilterProc, + DWORD AUserData + ); + // Entries + virtual boolean WINAPI AIMP_PLS_Entry_Delete( + int ID, + int AEntryIndex + ); + virtual boolean WINAPI AIMP_PLS_Entry_DeleteAll( + int ID + ); + virtual boolean WINAPI AIMP_PLS_Entry_FileNameGet( + int ID, + int AEntryIndex, + PWCHAR PBuf, + DWORD ABufLen + ); + virtual boolean WINAPI AIMP_PLS_Entry_FileNameSet( + int ID, + int AEntryIndex, + PWCHAR PBuf + ); + virtual int WINAPI AIMP_PLS_Entry_FocusedGet( + int ID + ); + virtual boolean WINAPI AIMP_PLS_Entry_FocusedSet( + int ID, + int AEntryIndex + ); + virtual boolean WINAPI AIMP_PLS_Entry_InfoGet( + int ID, + int AEntryIndex, + AIMP2FileInfo *PFileInfo + ); + virtual boolean WINAPI AIMP_PLS_Entry_InfoSet( + int ID, + int AEntryIndex, + AIMP2FileInfo *PFileInfo + ); + virtual boolean WINAPI AIMP_PLS_Entry_PlayingSwitchGet( + int ID, + int AEntryIndex + ); + virtual boolean WINAPI AIMP_PLS_Entry_PlayingSwitchSet( + int ID, + int AEntryIndex, + boolean ASwitch + ); + virtual boolean WINAPI AIMP_PLS_Entry_ReloadInfo( + int ID, + int AEntryIndex + ); + // Load/Save Playlists + virtual boolean WINAPI AIMP_PM_DestroyStream( + DWORD AHandle + ); + virtual DWORD WINAPI AIMP_PM_ReadItem( + DWORD AHandle, + AIMP2FileInfo *PItem + ); + virtual DWORD WINAPI AIMP_PM_ReadStream( + PWCHAR AFileName, + int *Count + ); + virtual DWORD WINAPI AIMP_PM_SaveStream( + PWCHAR AFileName + ); + virtual DWORD WINAPI AIMP_PM_WriteItem( + DWORD AHandle, + AIMP2FileInfo *PItem + ); + // added in 2.50 B295 + virtual boolean WINAPI AIMP_PLS_ID_PlayingSetTrackIndex( + int ID, + int AEntryIndex + ); +}; + +class IAIMP2PlaylistManager2 + : public IAIMP2PlaylistManager +{ +public: + // Count of loaded playlists + virtual unsigned short WINAPI AIMP_PLS_Count(); + // Return = -1 - ID is not valid, otherthis - count of files in playlist + virtual int WINAPI AIMP_PLS_GetFilesCount(int ID); + virtual HRESULT WINAPI AIMP_PLS_GetInfo(int ID, INT64 *ADuration, INT64 *ASize); + virtual HRESULT WINAPI AIMP_PLS_GetName(int ID, PWCHAR ABuffer, int ABufferSizeInChars); + // Custom Sorting, see AIMP_PLS_SORT_TYPE_XXX + virtual HRESULT WINAPI AIMP_PLS_Sort(int ID, int ASortType); + virtual HRESULT WINAPI AIMP_PLS_SortByTemplate(int ID, PWCHAR ABuffer, int ABufferSizeInChars); + // if Index = -1 returned ID of current playlist. + virtual HRESULT WINAPI AIMP_PLS_ID_By_Index(int Index, int *ID); + // Get Formated title for Entry + virtual HRESULT WINAPI AIMP_PLS_Entry_GetTitle(int ID, int AEntryIndex, + PWCHAR ABuffer, int ABufferSizeInChars); + // Set Entry to playback queue + virtual HRESULT WINAPI AIMP_PLS_Entry_QueueRemove(int ID, int AEntryIndex); + virtual HRESULT WINAPI AIMP_PLS_Entry_QueueSet(int ID, int AEntryIndex, BOOL AInsertAtQueueBegining); + // Moving Entry + virtual HRESULT WINAPI AIMP_PLS_Entry_SetPosition(int ID, int AEntryIndex, int ANewEntryIndex); +}; + +// See IAIMP2ExtendedID +class IAIMP2Extended + :public IUnknown +{ +public: + virtual int WINAPI AIMP_GetPath( + int ID, + PWCHAR buffer, + int bufSize + ); + virtual boolean WINAPI AIMP_ObjectClass( + int ID, + void *AData, + boolean ARegister + ); + // User Option Dialogs + virtual DWORD WINAPI AIMP_Options_FrameAdd( + IAIMP2OptionFrame *AFrame + ); + virtual DWORD WINAPI AIMP_Options_FrameRemove( + IAIMP2OptionFrame *AFrame + ); + virtual DWORD WINAPI AIMP_Options_ModifiedChanged( + IAIMP2OptionFrame *AFrame + ); +}; + +class IAIMP2CoverArtManager + :public IUnknown +{ +public: + // Return picture will be proportional stretched to ADisplaySize value + virtual HBITMAP WINAPI GetCoverArtForFile(PWCHAR AFile, const SIZE *ADisplaySize); + // Draw CoverArt of playing file, Return - cover art drawing successfuly + // CoverArt will be proportional stretched to R value + virtual HRESULT WINAPI CurrentCoverArtDraw(HDC DC, const RECT *R); + // Return <> S_OK, CoverArt is empty or file are not playing + virtual HRESULT WINAPI CurrentCoverArtGetSize(SIZE *ASize); + // W, H - destination display sizes, function will correct sizes for proportional drawing + // Return <> S_OK, CoverArt is empty or file are not playing + virtual HRESULT WINAPI CurrentCoverArtCorrectSizes(int *W, int *H); +}; + + // See IAIMPLanguageFileID +class IAIMPLanguageFile + :public IUnknown +{ +public: + virtual int AIMP_Lang_Version(); + virtual int AIMP_Lang_CurrentFile(PWCHAR ABuffer, int ABufferSizeInChars); + virtual HRESULT AIMP_Lang_IsSectionExists(PWCHAR ASectionName, int ASectionNameSizeInChars); + virtual HRESULT AIMP_Lang_ReadString(PWCHAR ASectionName, PWCHAR AItemName, PWCHAR AValueBuffer, + int ASectionNameSizeInChars, int AItemNameSizeInChars, int AValueBufferSizeInChars); + // When Language changed AIMP will send to window handle "WM_LANG" message + virtual HRESULT AIMP_Lang_Notification(HWND AWndHandle, BOOL ARegister); +}; + +// See IAIMPConfigFileID +class IAIMPConfigFile + :public IUnknown +{ + // functions return null value, if value don't exists in configuration file + virtual HRESULT AIMP_Config_ReadString(PWCHAR ASectionName, PWCHAR AItemName, PWCHAR AValueBuffer, + int ASectionNameSizeInChars, int AItemNameSizeInChars, int AValueBufferSizeInChars); + virtual HRESULT AIMP_Config_ReadInteger(PWCHAR ASectionName, PWCHAR AItemName, + int ASectionNameSizeInChars, int AItemNameSizeInChars, int * AValue); + // + virtual HRESULT AIMP_Config_WriteString(PWCHAR ASectionName, PWCHAR AItemName, PWCHAR AValueBuffer, + int ASectionNameSizeInChars, int AItemNameSizeInChars, int AValueBufferSizeInChars); + virtual HRESULT AIMP_Config_WriteInteger(PWCHAR ASectionName, PWCHAR AItemName, + int ASectionNameSizeInChars, int AItemNameSizeInChars, int AValue); + // + virtual HRESULT AIMP_Config_IsSectionExists(PWCHAR ASectionName, int ASectionNameSizeInChars); + virtual HRESULT AIMP_Config_RemoveSection(PWCHAR ASectionName, int ASectionNameSizeInChars); +}; + +//============================================================================== +// V I S U A L S +//============================================================================== + +const int VIS_RQD_DATA_WAVE = 1; +const int VIS_RQD_DATA_SPECTRUM = 2; +const int VIS_RQD_NOT_SUSPEND = 4; + +typedef short WaveForm[2][512]; +typedef short Spectrum[2][256]; + +struct AIMPVisualData +{ + int LevelR; + int LevelL; + Spectrum spectrum; + WaveForm waveForm; +}; + +typedef AIMPVisualData *PAIMPVisualData; + +class IAIMP2VisualPlugin + :public IUnknown +{ +public: + virtual PWCHAR WINAPI AuthorName(); + virtual PWCHAR WINAPI PluginName(); + virtual PWCHAR WINAPI PluginInfo(); + virtual DWORD WINAPI PluginFlags(); + virtual BOOL WINAPI Initialize(); + virtual void WINAPI Deinitialize(); + virtual void WINAPI DisplayClick(int X, int Y); + virtual void WINAPI DisplayRender(HDC DC, PAIMPVisualData AData); + virtual void WINAPI DisplayResize(int AWidth, int AHeight); +}; + +// Export function name: AIMP_QueryVisual +typedef IAIMP2VisualPlugin *(WINAPI *AIMPVisualProc)(); + #endif \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/SDKs/CAD/cad_sdk.h b/Plugins/PluginNowPlaying/SDKs/CAD/cad_sdk.h index d9745b0c..ee08ef4c 100644 --- a/Plugins/PluginNowPlaying/SDKs/CAD/cad_sdk.h +++ b/Plugins/PluginNowPlaying/SDKs/CAD/cad_sdk.h @@ -1,42 +1,42 @@ -#ifndef __CADSDK_H__ -#define __CADSDK_H__ - -enum IPCMESSAGE -{ - IPC_PLAY = 100, - IPC_PLAYPAUSE = 101, - IPC_PAUSE = 102, - IPC_STOP = 103, - IPC_NEXT = 104, - IPC_PREVIOUS = 105, - IPC_VOLUME_CHANGED_NOTIFICATION = 108, - IPC_SET_VOLUME = 108, - IPC_GET_VOLUME = 109, - IPC_GET_CURRENT_TRACK = 110, - IPC_GET_DURATION = 113, - IPC_SET_POSITION = 114, - IPC_SET_CALLBACK_HWND = 120, - IPC_GET_POSITION = 122, - IPC_TRACK_CHANGED_NOTIFICATION = 123, - IPC_SHOW_WINDOW = 124, - IPC_GET_STATE = 125, - IPC_STATE_CHANGED_NOTIFICATION = 126, - IPC_REPEAT_CHANGED_NOTIFICATION = 128, - IPC_SET_REPEAT = 128, - IPC_SHUTDOWN_NOTIFICATION = 129, - IPC_GET_REPEAT = 130, - IPC_CLOSE = 131, - IPC_SHUFFLE_CHANGED_NOTIFICATION = 140, - IPC_GET_SHUFFLE = 140, - IPC_SET_SHUFFLE = 141, - IPC_RATING_CHANGED_NOTIFICATION = 639, - IPC_SET_RATING = 639, - IPC_REGISTER_NOTIFICATION = 700, - IPC_CURRENT_TRACK_NOTIFICATION = 701, - IPC_CURRENT_LYRICS_NOTIFICATION = 702, - IPC_NEW_LYRICS_NOTIFICATION = 703, - IPC_NEW_COVER_NOTIFICATION = 800, - IPC_GET_LYRICS = 801 -}; - -#endif +#ifndef __CADSDK_H__ +#define __CADSDK_H__ + +enum IPCMESSAGE +{ + IPC_PLAY = 100, + IPC_PLAYPAUSE = 101, + IPC_PAUSE = 102, + IPC_STOP = 103, + IPC_NEXT = 104, + IPC_PREVIOUS = 105, + IPC_VOLUME_CHANGED_NOTIFICATION = 108, + IPC_SET_VOLUME = 108, + IPC_GET_VOLUME = 109, + IPC_GET_CURRENT_TRACK = 110, + IPC_GET_DURATION = 113, + IPC_SET_POSITION = 114, + IPC_SET_CALLBACK_HWND = 120, + IPC_GET_POSITION = 122, + IPC_TRACK_CHANGED_NOTIFICATION = 123, + IPC_SHOW_WINDOW = 124, + IPC_GET_STATE = 125, + IPC_STATE_CHANGED_NOTIFICATION = 126, + IPC_REPEAT_CHANGED_NOTIFICATION = 128, + IPC_SET_REPEAT = 128, + IPC_SHUTDOWN_NOTIFICATION = 129, + IPC_GET_REPEAT = 130, + IPC_CLOSE = 131, + IPC_SHUFFLE_CHANGED_NOTIFICATION = 140, + IPC_GET_SHUFFLE = 140, + IPC_SET_SHUFFLE = 141, + IPC_RATING_CHANGED_NOTIFICATION = 639, + IPC_SET_RATING = 639, + IPC_REGISTER_NOTIFICATION = 700, + IPC_CURRENT_TRACK_NOTIFICATION = 701, + IPC_CURRENT_LYRICS_NOTIFICATION = 702, + IPC_NEW_LYRICS_NOTIFICATION = 703, + IPC_NEW_COVER_NOTIFICATION = 800, + IPC_GET_LYRICS = 801 +}; + +#endif diff --git a/Plugins/PluginNowPlaying/SDKs/Winamp/wa_cmd.h b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_cmd.h index 0791df2a..1f33a899 100644 --- a/Plugins/PluginNowPlaying/SDKs/Winamp/wa_cmd.h +++ b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_cmd.h @@ -1,97 +1,97 @@ -#define WINAMP_STOPPED 0 -#define WINAMP_PLAYING 1 -#define WINAMP_PAUSED 3 - -#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_REWIND 40044 -#define WINAMP_PLAY 40045 -#define WINAMP_PAUSE 40046 -#define WINAMP_STOP 40047 -#define WINAMP_FASTFWD 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_REWIND_SHIFT 40144 -#define WINAMP_PLAY_SHIFT 40145 -#define WINAMP_PAUSE_SHIFT 40146 -#define WINAMP_STOP_SHIFT 40147 -#define WINAMP_FASTFWD_SHIFT 40148 -#define WINAMP_REWIND_CTRL 40154 -#define WINAMP_PLAY_CTRL 40155 -#define WINAMP_PAUSE_CTRL 40156 -#define WINAMP_STOP_CTRL 40157 -#define WINAMP_FASTFWD_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 - -#define WINAMP_OPTIONS_EQ 40036 // toggles the EQ window -#define WINAMP_OPTIONS_PLEDIT 40040 // toggles the playlist window -#define WINAMP_VOLUMEUP 40058 // turns the volume up a little -#define WINAMP_VOLUMEDOWN 40059 // turns the volume down a little -#define WINAMP_FFWD5S 40060 // fast forwards 5 seconds -#define WINAMP_REW5S 40061 // rewinds 5 seconds - -// the following are the five main control buttons, with optionally shift -// or control pressed -// (for the exact functions of each, just try it out) -#define WINAMP_BUTTON1 40044 -#define WINAMP_BUTTON2 40045 -#define WINAMP_BUTTON3 40046 -#define WINAMP_BUTTON4 40047 -#define WINAMP_BUTTON5 40048 -#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_FILE_PLAY 40029 // pops up the load file(s) box -#define WINAMP_OPTIONS_PREFS 40012 // pops up the preferences -#define WINAMP_OPTIONS_AOT 40019 // toggles always on top -#define WINAMP_HELP_ABOUT 40041 // pops up the about box :) +#define WINAMP_STOPPED 0 +#define WINAMP_PLAYING 1 +#define WINAMP_PAUSED 3 + +#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_REWIND 40044 +#define WINAMP_PLAY 40045 +#define WINAMP_PAUSE 40046 +#define WINAMP_STOP 40047 +#define WINAMP_FASTFWD 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_REWIND_SHIFT 40144 +#define WINAMP_PLAY_SHIFT 40145 +#define WINAMP_PAUSE_SHIFT 40146 +#define WINAMP_STOP_SHIFT 40147 +#define WINAMP_FASTFWD_SHIFT 40148 +#define WINAMP_REWIND_CTRL 40154 +#define WINAMP_PLAY_CTRL 40155 +#define WINAMP_PAUSE_CTRL 40156 +#define WINAMP_STOP_CTRL 40157 +#define WINAMP_FASTFWD_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 + +#define WINAMP_OPTIONS_EQ 40036 // toggles the EQ window +#define WINAMP_OPTIONS_PLEDIT 40040 // toggles the playlist window +#define WINAMP_VOLUMEUP 40058 // turns the volume up a little +#define WINAMP_VOLUMEDOWN 40059 // turns the volume down a little +#define WINAMP_FFWD5S 40060 // fast forwards 5 seconds +#define WINAMP_REW5S 40061 // rewinds 5 seconds + +// the following are the five main control buttons, with optionally shift +// or control pressed +// (for the exact functions of each, just try it out) +#define WINAMP_BUTTON1 40044 +#define WINAMP_BUTTON2 40045 +#define WINAMP_BUTTON3 40046 +#define WINAMP_BUTTON4 40047 +#define WINAMP_BUTTON5 40048 +#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_FILE_PLAY 40029 // pops up the load file(s) box +#define WINAMP_OPTIONS_PREFS 40012 // pops up the preferences +#define WINAMP_OPTIONS_AOT 40019 // toggles always on top +#define WINAMP_HELP_ABOUT 40041 // pops up the about box :) diff --git a/Plugins/PluginNowPlaying/SDKs/Winamp/wa_dlg.h b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_dlg.h index df912b25..e6edd49d 100644 --- a/Plugins/PluginNowPlaying/SDKs/Winamp/wa_dlg.h +++ b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_dlg.h @@ -1,436 +1,436 @@ -/* -** Copyright (C) 2003-2008 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. -** -*/ - -#ifndef _WA_DLG_H_ -#define _WA_DLG_H_ - -#include "wa_ipc.h" -#ifdef __cplusplus -extern "C" { -#endif -/* - 1) gen.bmp has a generic window frame for plugins to use. - its format is similar to the minibrowser's. - In addition gen.bmp includes a font for the titlebar, in both - highlight and no-highlight modes. The font is variable width, - and it uses the first color before the letter A as the delimiter. - The no-highlight form of letter must be the same width as the - highlight form. - 2) genex.bmp has button and scrollbar images, as well as some individual - pixels that describe the colors for the dialog. The button and - scrollbar images should be self explanatory (note that the buttons - have 4 pixel sized edges that are not stretched, and the center is - stretched), and the scrollbars do something similar. - The colors start at (48,0) and run every other pixel. The meaning - of each pixel is: - x=48: item background (background to edits, listviews etc) - x=50: item foreground (text color of edit/listview, etc) - x=52: window background (used to set the bg color for the dialog) - x=54: button text color - x=56: window text color - x=58: color of dividers and sunken borders - x=60: selection color for playlists - x=62: listview header background color - x=64: listview header text color - x=66: listview header frame top color - x=68: listview header frame middle color - x=70: listview header frame bottom color - x=72: listview header empty color - x=74: scrollbar foreground color - x=76: scrollbar background color - x=78: inverse scrollbar foreground color - x=80: inverse scrollbar background color - x=82: scrollbar dead area color - x=84: listview/treeview selection bar text color (active) - x=86: listview/treeview selection bar back color (active) - x=88: listview/treeview selection bar text color (inactive) - x=90: listview/treeview selection bar back color (inactive) - x=92: alternate item background - x=94: alternate item foreground -*/ - -#define DCW_SUNKENBORDER 0x00010000 -#define DCW_DIVIDER 0x00020000 - -enum -{ - WADLG_ITEMBG, - WADLG_ITEMFG, - WADLG_WNDBG, - WADLG_BUTTONFG, - WADLG_WNDFG, - WADLG_HILITE, - WADLG_SELCOLOR, - WADLG_LISTHEADER_BGCOLOR, - WADLG_LISTHEADER_FONTCOLOR, - WADLG_LISTHEADER_FRAME_TOPCOLOR, - WADLG_LISTHEADER_FRAME_MIDDLECOLOR, - WADLG_LISTHEADER_FRAME_BOTTOMCOLOR, - WADLG_LISTHEADER_EMPTY_BGCOLOR, - WADLG_SCROLLBAR_FGCOLOR, - WADLG_SCROLLBAR_BGCOLOR, - WADLG_SCROLLBAR_INV_FGCOLOR, - WADLG_SCROLLBAR_INV_BGCOLOR, - WADLG_SCROLLBAR_DEADAREA_COLOR, - WADLG_SELBAR_FGCOLOR, - WADLG_SELBAR_BGCOLOR, - WADLG_INACT_SELBAR_FGCOLOR, - WADLG_INACT_SELBAR_BGCOLOR, - WADLG_ITEMBG2, - WADLG_ITEMFG2, - WADLG_NUM_COLORS -}; - -typedef enum _WACURSOR // used in IPC_GETSKINCURSORS -{ - WACURSOR_VOLUME = 0, // volume & balane - WACURSOR_POSITION = 1, // position - WACURSOR_BTN_WINSHADE = 2, // winshade - WACURSOR_BTN_MINIMIZE = 3, // minimize - WACURSOR_BTN_CLOSE = 4, // close - WACURSOR_MENU = 5, // main menu - WACURSOR_TITLEBAR = 6, // title bar - WACURSOR_SONGNAME = 7, - WACURSOR_NORMAL = 8, - WACURSOR_WINSHADE_BTN_WINSHADE = 9, - WACURSOR_WINSHADE_BTN_MINIMIZE = 10, - WACURSOR_WINSHADE_POSITION = 11, - WACURSOR_WINSHADE_BTN_CLOSE = 12, - WACURSOR_WINSHADE_MENU = 13, - WACURSOR_WINSHADE_NORMAL = 14, - WACURSOR_PL_BTN_WINSHADE = 15, - WACURSOR_PL_BTN_CLOSE = 16, - WACURSOR_PL_TITLEBAR = 17, - WACURSOR_PL_VSCROLL = 18, - WACURSOR_PL_RESIZE = 19, - WACURSOR_PL_NORMAL = 20, - WACURSOR_PL_WINSHADE_BTN_WINSHADE = 21, - WACURSOR_PL_WINSHADE_BTN_CLOSE = 22, - WACURSOR_PL_WINSHADE_HSIZE = 23, - WACURSOR_PL_WINSHADE_NORMAL = 24, - WACURSOR_EQ_SLIDER = 25, - WACURSOR_EQ_BTN_CLOSE = 26, - WACURSOR_EQ_TITLEBAR = 27, - WACURSOR_EQ_NORMAL = 28, -} WACURSOR; - -void WADlg_init(HWND hwndWinamp); // call this on init, or on WM_DISPLAYCHANGE -void WADlg_close(); -int WADlg_getColor(int idx); -int WADlg_initted(); - -LRESULT WADlg_handleDialogMsgs(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); // -void WADlg_DrawChildWindowBorders(HWND hwndDlg, int *tab, int tabsize); // each entry in tab would be the id | DCW_* - -HBITMAP WADlg_getBitmap(); - -/// define WA_DLG_IMPLEMENT in one of your source files before including this .h -// if you are making a media library plugin, you dont need to do this, look at view_ex for -// an example of how to get the function *'s via an IPC message. -#ifdef __cplusplus -} -#endif - -#ifdef WA_DLG_IMPLEMENT - -static HBRUSH wadlg_lastbrush=0; -static HBITMAP wadlg_bitmap=0; // load this manually -static int wadlg_colors[WADLG_NUM_COLORS]; -static int wadlg_defcolors[WADLG_NUM_COLORS]= -{ - RGB(0,0,0), - RGB(0,255,0), - RGB(36,36,60), - RGB(57,56,66), - RGB(255,255,255), - RGB(132,148,165), - RGB(0,0,198), - RGB(36*2,36*2,60*2), - RGB(255,255,255), - RGB(36*3,36*3,60*3), - RGB(36,36,60), - RGB(36*0.5,36*0.5,60*0.5), - RGB(36,36,60), - RGB(36*1,36*1,60*1), - RGB(36*1,36*1,60*1), - RGB(121,130,150), - RGB(78,88,110), - RGB(36*1,36*1,60*1), - RGB(255,255,255), - RGB(0,0,180), - RGB(0,255,0), - RGB(0,0,128), - RGB(0,0,0), - RGB(0,255,0), -}; - -int WADlg_initted() -{ - return !!wadlg_bitmap; -} - -int WADlg_getColor(int idx) -{ - if (idx < 0 || idx >= WADLG_NUM_COLORS) return 0; - return wadlg_colors[idx]; -} - -HBITMAP WADlg_getBitmap() -{ - return wadlg_bitmap; -} - -void WADlg_init(HWND hwndWinamp) // call this on init, or on WM_DISPLAYCHANGE -{ - if (wadlg_bitmap) DeleteObject(wadlg_bitmap); - wadlg_bitmap = (HBITMAP) SendMessage(hwndWinamp,WM_WA_IPC,0,IPC_GET_GENSKINBITMAP); - if (wadlg_bitmap) - { - HDC tmpDC=CreateCompatibleDC(NULL); - HGDIOBJ o=SelectObject(tmpDC,(HGDIOBJ)wadlg_bitmap); - int defbgcol=GetPixel(tmpDC,111,0); - for (int x = 0; x < WADLG_NUM_COLORS; x ++) - { - int a=GetPixel(tmpDC,48+x*2,0); - if (a == CLR_INVALID || a == RGB(0,198,255) || a == defbgcol) - { - //defaults for old skins - if (x == WADLG_SELBAR_FGCOLOR || x == WADLG_INACT_SELBAR_FGCOLOR) a=wadlg_colors[WADLG_WNDFG]; - else if (x == WADLG_SELBAR_BGCOLOR || x == WADLG_INACT_SELBAR_BGCOLOR) - { - a=wadlg_colors[WADLG_SELCOLOR]; - if (x == WADLG_INACT_SELBAR_BGCOLOR) - a=((a/2)&0x7F7F7F)+(((wadlg_colors[WADLG_WNDBG])/2)&0x7F7F7F); - } - else if (x == WADLG_ITEMBG2) - { - a=wadlg_colors[WADLG_ITEMBG]; - } - else if (x == WADLG_ITEMFG2) - { - a=wadlg_colors[WADLG_ITEMFG]; - } - else a=wadlg_defcolors[x]; - } - wadlg_colors[x]=a; - } - - SelectObject(tmpDC,o); - DeleteDC(tmpDC); - } -} - -void WADlg_close() -{ - if (wadlg_bitmap) DeleteObject(wadlg_bitmap); - wadlg_bitmap=0; - if (wadlg_lastbrush) DeleteObject(wadlg_lastbrush); - wadlg_lastbrush=0; -} - -void WADlg_dotLine(HDC hdc, int left, int top, int len, int vert) -{ - for(int i=(top&1);i<len-1;i+=2) - { - if(vert) - { - MoveToEx(hdc,left,top+i,NULL); - LineTo(hdc,left,top+i+1); - } - else - { - MoveToEx(hdc,left+i,top,NULL); - LineTo(hdc,left+i+1,top); - } - } -} - -LRESULT WADlg_handleDialogMsgs(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (uMsg == WM_DRAWITEM) - { - DRAWITEMSTRUCT *di = (DRAWITEMSTRUCT *)lParam; - if (di->CtlType == ODT_BUTTON) { - wchar_t wt[256]; - RECT r; - GetDlgItemTextW(hwndDlg,(INT)wParam,wt,sizeof(wt)/sizeof(*wt)); - - HDC hdc = CreateCompatibleDC(di->hDC); - HBITMAP hbmpOld = (HBITMAP)SelectObject(hdc, wadlg_bitmap); - - r=di->rcItem; - SetStretchBltMode(di->hDC,COLORONCOLOR); - - int yoffs = (di->itemState & ODS_SELECTED) ? 15 : 0; - - BitBlt(di->hDC,r.left,r.top,4,4,hdc,0,yoffs,SRCCOPY); // top left - StretchBlt(di->hDC,r.left+4,r.top,r.right-r.left-4-4,4,hdc,4,yoffs,47-4-4,4,SRCCOPY); // top center - BitBlt(di->hDC,r.right-4,r.top,4,4,hdc,47-4,yoffs,SRCCOPY); // top right - - StretchBlt(di->hDC,r.left,r.top+4,4,r.bottom-r.top-4-4,hdc,0,4+yoffs,4,15-4-4,SRCCOPY); // left edge - StretchBlt(di->hDC,r.right-4,r.top+4,4,r.bottom-r.top-4-4,hdc,47-4,4+yoffs,4,15-4-4,SRCCOPY); // right edge - - // center - StretchBlt(di->hDC,r.left+4,r.top+4,r.right-r.left-4-4,r.bottom-r.top-4-4,hdc,4,4+yoffs,47-4-4,15-4-4,SRCCOPY); - - BitBlt(di->hDC,r.left,r.bottom-4,4,4,hdc,0,15-4+yoffs,SRCCOPY); // bottom left - StretchBlt(di->hDC,r.left+4,r.bottom-4,r.right-r.left-4-4,4,hdc,4,15-4+yoffs,47-4-4,4,SRCCOPY); // bottom center - BitBlt(di->hDC,r.right-4,r.bottom-4,4,4,hdc,47-4,15-4+yoffs,SRCCOPY); // bottom right - - // draw text - SetBkMode(di->hDC,TRANSPARENT); - - // this will do a different style for the button text depending on enabled state of the button - COLORREF colour = wadlg_colors[WADLG_BUTTONFG]; - if(!IsWindowEnabled(di->hwndItem)){ - COLORREF fg = wadlg_colors[WADLG_WNDFG], - bg = wadlg_colors[WADLG_WNDBG]; - colour = RGB((GetRValue(fg)+GetRValue(bg))/2, - (GetGValue(fg)+GetGValue(bg))/2, - (GetBValue(fg)+GetBValue(bg))/2); - } - SetTextColor(di->hDC,colour); - - if (di->itemState & ODS_SELECTED) {r.left+=2; r.top+=2;} - DrawTextW(di->hDC,wt,-1,&r,DT_VCENTER|DT_SINGLELINE|DT_CENTER); - - SelectObject(hdc, hbmpOld); - DeleteDC(hdc); - - if(GetFocus()==di->hwndItem) { - HPEN hpen, hpenOld; - hpen =CreatePen(PS_SOLID,0,RGB(0,0,0)); - hpenOld = (HPEN)SelectObject(di->hDC, hpen); - WADlg_dotLine(di->hDC,r.left+2,r.top+2,r.right-r.left-3,0); - WADlg_dotLine(di->hDC,r.right-3,r.top+2,r.bottom-r.top-3,1); - WADlg_dotLine(di->hDC,r.left+2,r.top+2,r.bottom-r.top-3,1); - WADlg_dotLine(di->hDC,r.left+2,r.bottom-3,r.right-r.left-3,0); - SelectObject(di->hDC, hpenOld); - DeleteObject(hpen); - } - } - } - - switch(uMsg) - { - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORDLG: - case WM_CTLCOLORBTN: - case WM_CTLCOLORSTATIC: - case WM_CTLCOLOREDIT: - { - int bgcolor=(uMsg == WM_CTLCOLOREDIT || uMsg == WM_CTLCOLORLISTBOX) ? wadlg_colors[WADLG_ITEMBG] : (uMsg == WM_CTLCOLORBTN ? wadlg_colors[WADLG_ITEMBG] : wadlg_colors[WADLG_WNDBG]); - LOGBRUSH lb={BS_SOLID,GetNearestColor((HDC)wParam,bgcolor)}; - if (wadlg_lastbrush) DeleteObject(wadlg_lastbrush); - wadlg_lastbrush=CreateBrushIndirect(&lb); - SetTextColor((HDC)wParam,uMsg == WM_CTLCOLORSTATIC ? wadlg_colors[WADLG_WNDFG] : wadlg_colors[WADLG_ITEMFG]); - SetBkColor((HDC)wParam,lb.lbColor); - return (LRESULT)wadlg_lastbrush; - } - } - return 0; -} - -static int RectInRect(RECT *rect1, RECT *rect2) -{ - // this has a bias towards true - - // this could probably be optimized a lot - return ((rect1->top >= rect2->top && rect1->top <= rect2->bottom) || - (rect1->bottom >= rect2->top && rect1->bottom <= rect2->bottom) || - (rect2->top >= rect1->top && rect2->top <= rect1->bottom) || - (rect2->bottom >= rect1->top && rect2->bottom <= rect1->bottom)) // vertical intersect - && - ((rect1->left >= rect2->left && rect1->left <= rect2->right) || - (rect1->right >= rect2->left && rect1->right <= rect2->right) || - (rect2->left >= rect1->left && rect2->left <= rect1->right) || - (rect2->right >= rect1->left && rect2->right <= rect1->right)) // horiz intersect - ; -} - -static void WADlg_removeFromRgn(HRGN hrgn, int left, int top, int right, int bottom) -{ - HRGN rgn2=CreateRectRgn(left,top,right,bottom); - CombineRgn(hrgn,hrgn,rgn2,RGN_DIFF); - DeleteObject(rgn2); -} - -void WADlg_DrawChildWindowBorders(HWND hwndDlg, int *tab, int tabsize) -{ - PAINTSTRUCT ps; - BeginPaint(hwndDlg,&ps); - HRGN hrgn = (ps.fErase) ? CreateRectRgnIndirect(&ps.rcPaint) : NULL; - HPEN pen = CreatePen(PS_SOLID, 0, wadlg_colors[WADLG_HILITE]); - HGDIOBJ o = SelectObject(ps.hdc, pen); - - while (tabsize--) - { - RECT r; - int a = *tab++; - GetWindowRect(GetDlgItem(hwndDlg, a & 0xffff),&r); - MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&r, 2); - - if (RectInRect(&ps.rcPaint,&r)) - { - if ((a & 0xffff0000) == DCW_SUNKENBORDER) - { - MoveToEx(ps.hdc,r.left,r.bottom,NULL); - LineTo(ps.hdc,r.right,r.bottom); - LineTo(ps.hdc,r.right,r.top-1); - if(hrgn) - { - WADlg_removeFromRgn(hrgn,r.left,r.bottom,r.right,r.bottom+1); - WADlg_removeFromRgn(hrgn,r.right,r.top,r.right+1,r.bottom); - } - } - else if ((a & 0xffff0000) == DCW_DIVIDER) - { - if (r.right - r.left < r.bottom - r.top) // vertical - { - int left=(r.left+r.right)/2; - MoveToEx(ps.hdc,left,r.top,NULL); - LineTo(ps.hdc,left,r.bottom+1); - if(hrgn) WADlg_removeFromRgn(hrgn,left,r.top,left+1,r.bottom); - } - else // horiz - { - int top=(r.top+r.bottom)/2; - MoveToEx(ps.hdc,r.left,top,NULL); - LineTo(ps.hdc,r.right+1,top); - if(hrgn) WADlg_removeFromRgn(hrgn,r.left,top,r.right,top+1); - } - } - } - } - - SelectObject(ps.hdc, o); - DeleteObject(pen); - - if(hrgn) - { - //erase bkgnd while clipping out our own drawn stuff (for flickerless display) - HBRUSH b = CreateSolidBrush(wadlg_colors[WADLG_WNDBG]); - FillRgn(ps.hdc,hrgn,b); - DeleteObject(b); - DeleteObject(hrgn); - } - EndPaint(hwndDlg,&ps); -} -#endif - +/* +** Copyright (C) 2003-2008 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. +** +*/ + +#ifndef _WA_DLG_H_ +#define _WA_DLG_H_ + +#include "wa_ipc.h" +#ifdef __cplusplus +extern "C" { +#endif +/* + 1) gen.bmp has a generic window frame for plugins to use. + its format is similar to the minibrowser's. + In addition gen.bmp includes a font for the titlebar, in both + highlight and no-highlight modes. The font is variable width, + and it uses the first color before the letter A as the delimiter. + The no-highlight form of letter must be the same width as the + highlight form. + 2) genex.bmp has button and scrollbar images, as well as some individual + pixels that describe the colors for the dialog. The button and + scrollbar images should be self explanatory (note that the buttons + have 4 pixel sized edges that are not stretched, and the center is + stretched), and the scrollbars do something similar. + The colors start at (48,0) and run every other pixel. The meaning + of each pixel is: + x=48: item background (background to edits, listviews etc) + x=50: item foreground (text color of edit/listview, etc) + x=52: window background (used to set the bg color for the dialog) + x=54: button text color + x=56: window text color + x=58: color of dividers and sunken borders + x=60: selection color for playlists + x=62: listview header background color + x=64: listview header text color + x=66: listview header frame top color + x=68: listview header frame middle color + x=70: listview header frame bottom color + x=72: listview header empty color + x=74: scrollbar foreground color + x=76: scrollbar background color + x=78: inverse scrollbar foreground color + x=80: inverse scrollbar background color + x=82: scrollbar dead area color + x=84: listview/treeview selection bar text color (active) + x=86: listview/treeview selection bar back color (active) + x=88: listview/treeview selection bar text color (inactive) + x=90: listview/treeview selection bar back color (inactive) + x=92: alternate item background + x=94: alternate item foreground +*/ + +#define DCW_SUNKENBORDER 0x00010000 +#define DCW_DIVIDER 0x00020000 + +enum +{ + WADLG_ITEMBG, + WADLG_ITEMFG, + WADLG_WNDBG, + WADLG_BUTTONFG, + WADLG_WNDFG, + WADLG_HILITE, + WADLG_SELCOLOR, + WADLG_LISTHEADER_BGCOLOR, + WADLG_LISTHEADER_FONTCOLOR, + WADLG_LISTHEADER_FRAME_TOPCOLOR, + WADLG_LISTHEADER_FRAME_MIDDLECOLOR, + WADLG_LISTHEADER_FRAME_BOTTOMCOLOR, + WADLG_LISTHEADER_EMPTY_BGCOLOR, + WADLG_SCROLLBAR_FGCOLOR, + WADLG_SCROLLBAR_BGCOLOR, + WADLG_SCROLLBAR_INV_FGCOLOR, + WADLG_SCROLLBAR_INV_BGCOLOR, + WADLG_SCROLLBAR_DEADAREA_COLOR, + WADLG_SELBAR_FGCOLOR, + WADLG_SELBAR_BGCOLOR, + WADLG_INACT_SELBAR_FGCOLOR, + WADLG_INACT_SELBAR_BGCOLOR, + WADLG_ITEMBG2, + WADLG_ITEMFG2, + WADLG_NUM_COLORS +}; + +typedef enum _WACURSOR // used in IPC_GETSKINCURSORS +{ + WACURSOR_VOLUME = 0, // volume & balane + WACURSOR_POSITION = 1, // position + WACURSOR_BTN_WINSHADE = 2, // winshade + WACURSOR_BTN_MINIMIZE = 3, // minimize + WACURSOR_BTN_CLOSE = 4, // close + WACURSOR_MENU = 5, // main menu + WACURSOR_TITLEBAR = 6, // title bar + WACURSOR_SONGNAME = 7, + WACURSOR_NORMAL = 8, + WACURSOR_WINSHADE_BTN_WINSHADE = 9, + WACURSOR_WINSHADE_BTN_MINIMIZE = 10, + WACURSOR_WINSHADE_POSITION = 11, + WACURSOR_WINSHADE_BTN_CLOSE = 12, + WACURSOR_WINSHADE_MENU = 13, + WACURSOR_WINSHADE_NORMAL = 14, + WACURSOR_PL_BTN_WINSHADE = 15, + WACURSOR_PL_BTN_CLOSE = 16, + WACURSOR_PL_TITLEBAR = 17, + WACURSOR_PL_VSCROLL = 18, + WACURSOR_PL_RESIZE = 19, + WACURSOR_PL_NORMAL = 20, + WACURSOR_PL_WINSHADE_BTN_WINSHADE = 21, + WACURSOR_PL_WINSHADE_BTN_CLOSE = 22, + WACURSOR_PL_WINSHADE_HSIZE = 23, + WACURSOR_PL_WINSHADE_NORMAL = 24, + WACURSOR_EQ_SLIDER = 25, + WACURSOR_EQ_BTN_CLOSE = 26, + WACURSOR_EQ_TITLEBAR = 27, + WACURSOR_EQ_NORMAL = 28, +} WACURSOR; + +void WADlg_init(HWND hwndWinamp); // call this on init, or on WM_DISPLAYCHANGE +void WADlg_close(); +int WADlg_getColor(int idx); +int WADlg_initted(); + +LRESULT WADlg_handleDialogMsgs(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); // +void WADlg_DrawChildWindowBorders(HWND hwndDlg, int *tab, int tabsize); // each entry in tab would be the id | DCW_* + +HBITMAP WADlg_getBitmap(); + +/// define WA_DLG_IMPLEMENT in one of your source files before including this .h +// if you are making a media library plugin, you dont need to do this, look at view_ex for +// an example of how to get the function *'s via an IPC message. +#ifdef __cplusplus +} +#endif + +#ifdef WA_DLG_IMPLEMENT + +static HBRUSH wadlg_lastbrush=0; +static HBITMAP wadlg_bitmap=0; // load this manually +static int wadlg_colors[WADLG_NUM_COLORS]; +static int wadlg_defcolors[WADLG_NUM_COLORS]= +{ + RGB(0,0,0), + RGB(0,255,0), + RGB(36,36,60), + RGB(57,56,66), + RGB(255,255,255), + RGB(132,148,165), + RGB(0,0,198), + RGB(36*2,36*2,60*2), + RGB(255,255,255), + RGB(36*3,36*3,60*3), + RGB(36,36,60), + RGB(36*0.5,36*0.5,60*0.5), + RGB(36,36,60), + RGB(36*1,36*1,60*1), + RGB(36*1,36*1,60*1), + RGB(121,130,150), + RGB(78,88,110), + RGB(36*1,36*1,60*1), + RGB(255,255,255), + RGB(0,0,180), + RGB(0,255,0), + RGB(0,0,128), + RGB(0,0,0), + RGB(0,255,0), +}; + +int WADlg_initted() +{ + return !!wadlg_bitmap; +} + +int WADlg_getColor(int idx) +{ + if (idx < 0 || idx >= WADLG_NUM_COLORS) return 0; + return wadlg_colors[idx]; +} + +HBITMAP WADlg_getBitmap() +{ + return wadlg_bitmap; +} + +void WADlg_init(HWND hwndWinamp) // call this on init, or on WM_DISPLAYCHANGE +{ + if (wadlg_bitmap) DeleteObject(wadlg_bitmap); + wadlg_bitmap = (HBITMAP) SendMessage(hwndWinamp,WM_WA_IPC,0,IPC_GET_GENSKINBITMAP); + if (wadlg_bitmap) + { + HDC tmpDC=CreateCompatibleDC(NULL); + HGDIOBJ o=SelectObject(tmpDC,(HGDIOBJ)wadlg_bitmap); + int defbgcol=GetPixel(tmpDC,111,0); + for (int x = 0; x < WADLG_NUM_COLORS; x ++) + { + int a=GetPixel(tmpDC,48+x*2,0); + if (a == CLR_INVALID || a == RGB(0,198,255) || a == defbgcol) + { + //defaults for old skins + if (x == WADLG_SELBAR_FGCOLOR || x == WADLG_INACT_SELBAR_FGCOLOR) a=wadlg_colors[WADLG_WNDFG]; + else if (x == WADLG_SELBAR_BGCOLOR || x == WADLG_INACT_SELBAR_BGCOLOR) + { + a=wadlg_colors[WADLG_SELCOLOR]; + if (x == WADLG_INACT_SELBAR_BGCOLOR) + a=((a/2)&0x7F7F7F)+(((wadlg_colors[WADLG_WNDBG])/2)&0x7F7F7F); + } + else if (x == WADLG_ITEMBG2) + { + a=wadlg_colors[WADLG_ITEMBG]; + } + else if (x == WADLG_ITEMFG2) + { + a=wadlg_colors[WADLG_ITEMFG]; + } + else a=wadlg_defcolors[x]; + } + wadlg_colors[x]=a; + } + + SelectObject(tmpDC,o); + DeleteDC(tmpDC); + } +} + +void WADlg_close() +{ + if (wadlg_bitmap) DeleteObject(wadlg_bitmap); + wadlg_bitmap=0; + if (wadlg_lastbrush) DeleteObject(wadlg_lastbrush); + wadlg_lastbrush=0; +} + +void WADlg_dotLine(HDC hdc, int left, int top, int len, int vert) +{ + for(int i=(top&1);i<len-1;i+=2) + { + if(vert) + { + MoveToEx(hdc,left,top+i,NULL); + LineTo(hdc,left,top+i+1); + } + else + { + MoveToEx(hdc,left+i,top,NULL); + LineTo(hdc,left+i+1,top); + } + } +} + +LRESULT WADlg_handleDialogMsgs(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_DRAWITEM) + { + DRAWITEMSTRUCT *di = (DRAWITEMSTRUCT *)lParam; + if (di->CtlType == ODT_BUTTON) { + wchar_t wt[256]; + RECT r; + GetDlgItemTextW(hwndDlg,(INT)wParam,wt,sizeof(wt)/sizeof(*wt)); + + HDC hdc = CreateCompatibleDC(di->hDC); + HBITMAP hbmpOld = (HBITMAP)SelectObject(hdc, wadlg_bitmap); + + r=di->rcItem; + SetStretchBltMode(di->hDC,COLORONCOLOR); + + int yoffs = (di->itemState & ODS_SELECTED) ? 15 : 0; + + BitBlt(di->hDC,r.left,r.top,4,4,hdc,0,yoffs,SRCCOPY); // top left + StretchBlt(di->hDC,r.left+4,r.top,r.right-r.left-4-4,4,hdc,4,yoffs,47-4-4,4,SRCCOPY); // top center + BitBlt(di->hDC,r.right-4,r.top,4,4,hdc,47-4,yoffs,SRCCOPY); // top right + + StretchBlt(di->hDC,r.left,r.top+4,4,r.bottom-r.top-4-4,hdc,0,4+yoffs,4,15-4-4,SRCCOPY); // left edge + StretchBlt(di->hDC,r.right-4,r.top+4,4,r.bottom-r.top-4-4,hdc,47-4,4+yoffs,4,15-4-4,SRCCOPY); // right edge + + // center + StretchBlt(di->hDC,r.left+4,r.top+4,r.right-r.left-4-4,r.bottom-r.top-4-4,hdc,4,4+yoffs,47-4-4,15-4-4,SRCCOPY); + + BitBlt(di->hDC,r.left,r.bottom-4,4,4,hdc,0,15-4+yoffs,SRCCOPY); // bottom left + StretchBlt(di->hDC,r.left+4,r.bottom-4,r.right-r.left-4-4,4,hdc,4,15-4+yoffs,47-4-4,4,SRCCOPY); // bottom center + BitBlt(di->hDC,r.right-4,r.bottom-4,4,4,hdc,47-4,15-4+yoffs,SRCCOPY); // bottom right + + // draw text + SetBkMode(di->hDC,TRANSPARENT); + + // this will do a different style for the button text depending on enabled state of the button + COLORREF colour = wadlg_colors[WADLG_BUTTONFG]; + if(!IsWindowEnabled(di->hwndItem)){ + COLORREF fg = wadlg_colors[WADLG_WNDFG], + bg = wadlg_colors[WADLG_WNDBG]; + colour = RGB((GetRValue(fg)+GetRValue(bg))/2, + (GetGValue(fg)+GetGValue(bg))/2, + (GetBValue(fg)+GetBValue(bg))/2); + } + SetTextColor(di->hDC,colour); + + if (di->itemState & ODS_SELECTED) {r.left+=2; r.top+=2;} + DrawTextW(di->hDC,wt,-1,&r,DT_VCENTER|DT_SINGLELINE|DT_CENTER); + + SelectObject(hdc, hbmpOld); + DeleteDC(hdc); + + if(GetFocus()==di->hwndItem) { + HPEN hpen, hpenOld; + hpen =CreatePen(PS_SOLID,0,RGB(0,0,0)); + hpenOld = (HPEN)SelectObject(di->hDC, hpen); + WADlg_dotLine(di->hDC,r.left+2,r.top+2,r.right-r.left-3,0); + WADlg_dotLine(di->hDC,r.right-3,r.top+2,r.bottom-r.top-3,1); + WADlg_dotLine(di->hDC,r.left+2,r.top+2,r.bottom-r.top-3,1); + WADlg_dotLine(di->hDC,r.left+2,r.bottom-3,r.right-r.left-3,0); + SelectObject(di->hDC, hpenOld); + DeleteObject(hpen); + } + } + } + + switch(uMsg) + { + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLORDLG: + case WM_CTLCOLORBTN: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLOREDIT: + { + int bgcolor=(uMsg == WM_CTLCOLOREDIT || uMsg == WM_CTLCOLORLISTBOX) ? wadlg_colors[WADLG_ITEMBG] : (uMsg == WM_CTLCOLORBTN ? wadlg_colors[WADLG_ITEMBG] : wadlg_colors[WADLG_WNDBG]); + LOGBRUSH lb={BS_SOLID,GetNearestColor((HDC)wParam,bgcolor)}; + if (wadlg_lastbrush) DeleteObject(wadlg_lastbrush); + wadlg_lastbrush=CreateBrushIndirect(&lb); + SetTextColor((HDC)wParam,uMsg == WM_CTLCOLORSTATIC ? wadlg_colors[WADLG_WNDFG] : wadlg_colors[WADLG_ITEMFG]); + SetBkColor((HDC)wParam,lb.lbColor); + return (LRESULT)wadlg_lastbrush; + } + } + return 0; +} + +static int RectInRect(RECT *rect1, RECT *rect2) +{ + // this has a bias towards true + + // this could probably be optimized a lot + return ((rect1->top >= rect2->top && rect1->top <= rect2->bottom) || + (rect1->bottom >= rect2->top && rect1->bottom <= rect2->bottom) || + (rect2->top >= rect1->top && rect2->top <= rect1->bottom) || + (rect2->bottom >= rect1->top && rect2->bottom <= rect1->bottom)) // vertical intersect + && + ((rect1->left >= rect2->left && rect1->left <= rect2->right) || + (rect1->right >= rect2->left && rect1->right <= rect2->right) || + (rect2->left >= rect1->left && rect2->left <= rect1->right) || + (rect2->right >= rect1->left && rect2->right <= rect1->right)) // horiz intersect + ; +} + +static void WADlg_removeFromRgn(HRGN hrgn, int left, int top, int right, int bottom) +{ + HRGN rgn2=CreateRectRgn(left,top,right,bottom); + CombineRgn(hrgn,hrgn,rgn2,RGN_DIFF); + DeleteObject(rgn2); +} + +void WADlg_DrawChildWindowBorders(HWND hwndDlg, int *tab, int tabsize) +{ + PAINTSTRUCT ps; + BeginPaint(hwndDlg,&ps); + HRGN hrgn = (ps.fErase) ? CreateRectRgnIndirect(&ps.rcPaint) : NULL; + HPEN pen = CreatePen(PS_SOLID, 0, wadlg_colors[WADLG_HILITE]); + HGDIOBJ o = SelectObject(ps.hdc, pen); + + while (tabsize--) + { + RECT r; + int a = *tab++; + GetWindowRect(GetDlgItem(hwndDlg, a & 0xffff),&r); + MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&r, 2); + + if (RectInRect(&ps.rcPaint,&r)) + { + if ((a & 0xffff0000) == DCW_SUNKENBORDER) + { + MoveToEx(ps.hdc,r.left,r.bottom,NULL); + LineTo(ps.hdc,r.right,r.bottom); + LineTo(ps.hdc,r.right,r.top-1); + if(hrgn) + { + WADlg_removeFromRgn(hrgn,r.left,r.bottom,r.right,r.bottom+1); + WADlg_removeFromRgn(hrgn,r.right,r.top,r.right+1,r.bottom); + } + } + else if ((a & 0xffff0000) == DCW_DIVIDER) + { + if (r.right - r.left < r.bottom - r.top) // vertical + { + int left=(r.left+r.right)/2; + MoveToEx(ps.hdc,left,r.top,NULL); + LineTo(ps.hdc,left,r.bottom+1); + if(hrgn) WADlg_removeFromRgn(hrgn,left,r.top,left+1,r.bottom); + } + else // horiz + { + int top=(r.top+r.bottom)/2; + MoveToEx(ps.hdc,r.left,top,NULL); + LineTo(ps.hdc,r.right+1,top); + if(hrgn) WADlg_removeFromRgn(hrgn,r.left,top,r.right,top+1); + } + } + } + } + + SelectObject(ps.hdc, o); + DeleteObject(pen); + + if(hrgn) + { + //erase bkgnd while clipping out our own drawn stuff (for flickerless display) + HBRUSH b = CreateSolidBrush(wadlg_colors[WADLG_WNDBG]); + FillRgn(ps.hdc,hrgn,b); + DeleteObject(b); + DeleteObject(hrgn); + } + EndPaint(hwndDlg,&ps); +} +#endif + #endif//_WA_DLG_H_ \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/SDKs/Winamp/wa_hotkeys.h b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_hotkeys.h index c4cbf8da..6739a576 100644 --- a/Plugins/PluginNowPlaying/SDKs/Winamp/wa_hotkeys.h +++ b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_hotkeys.h @@ -1,39 +1,39 @@ -#ifndef WA_HOTKEYS -#define WA_HOTKEYS - -//#define IPC_GEN_HOTKEYS_ADD xxxx //pass a genHotkeysAddStruct * struct in data -// -//To get the IPC_GEN_HOTKEYS_ADD IPC number, do this: -// -// genhotkeys_add_ipc=SendMessage(winampWindow,WM_WA_IPC,(WPARAM)&"GenHotkeysAdd",IPC_REGISTER_WINAMP_IPCMESSAGE); -// -//Then you can use: -// -// PostMessage(winampWindow,WM_WA_IPC,(WPARAM)&myGenHotkeysAddStruct,genhotkeys_add_ipc); -// - -//flags for the genHotkeysAddStruct struct -#define HKF_BRING_TO_FRONT 0x1 // calls SetForegroundWindow before sending the message -#define HKF_HWND_WPARAM 0x2 // sets wParam with Winamp's window handle -#define HKF_COPY 0x4 // copies returned text to the clipboard -#define HKF_PLPOS_WPARAM 0x8 // sets wParam with current pledit position -#define HKF_ISPLAYING_WL 0x10 // sets wParam to genHotkeysAddStruct's wParam if playing, lParam if not - // uses IPC_ISPLAYING to check if playing -#define HKF_SHOWHIDE 0x20 // brings Winamp to front or minimizes Winamp if already at front -#define HKF_NOSENDMSG 0x40 // don't send any message to the winamp window - -#define HKF_DISABLED 0x80000000 - -typedef struct { - char *name; //name that will appear in the Global Hotkeys preferences panel - DWORD flags; //one or more flags from above - UINT uMsg; //message that will be sent to winamp's main window (must always be !=NULL) - WPARAM wParam; //wParam that will be sent to winamp's main window - LPARAM lParam; //lParam that will be sent to winamp's main window - char *id; //unique string to identify this command - case insensitive - HWND wnd; //set the HWND to send message (or 0 for main winamp window) - - int extended[6]; //for future extension - always set to zero! -} genHotkeysAddStruct; - +#ifndef WA_HOTKEYS +#define WA_HOTKEYS + +//#define IPC_GEN_HOTKEYS_ADD xxxx //pass a genHotkeysAddStruct * struct in data +// +//To get the IPC_GEN_HOTKEYS_ADD IPC number, do this: +// +// genhotkeys_add_ipc=SendMessage(winampWindow,WM_WA_IPC,(WPARAM)&"GenHotkeysAdd",IPC_REGISTER_WINAMP_IPCMESSAGE); +// +//Then you can use: +// +// PostMessage(winampWindow,WM_WA_IPC,(WPARAM)&myGenHotkeysAddStruct,genhotkeys_add_ipc); +// + +//flags for the genHotkeysAddStruct struct +#define HKF_BRING_TO_FRONT 0x1 // calls SetForegroundWindow before sending the message +#define HKF_HWND_WPARAM 0x2 // sets wParam with Winamp's window handle +#define HKF_COPY 0x4 // copies returned text to the clipboard +#define HKF_PLPOS_WPARAM 0x8 // sets wParam with current pledit position +#define HKF_ISPLAYING_WL 0x10 // sets wParam to genHotkeysAddStruct's wParam if playing, lParam if not + // uses IPC_ISPLAYING to check if playing +#define HKF_SHOWHIDE 0x20 // brings Winamp to front or minimizes Winamp if already at front +#define HKF_NOSENDMSG 0x40 // don't send any message to the winamp window + +#define HKF_DISABLED 0x80000000 + +typedef struct { + char *name; //name that will appear in the Global Hotkeys preferences panel + DWORD flags; //one or more flags from above + UINT uMsg; //message that will be sent to winamp's main window (must always be !=NULL) + WPARAM wParam; //wParam that will be sent to winamp's main window + LPARAM lParam; //lParam that will be sent to winamp's main window + char *id; //unique string to identify this command - case insensitive + HWND wnd; //set the HWND to send message (or 0 for main winamp window) + + int extended[6]; //for future extension - always set to zero! +} genHotkeysAddStruct; + #endif \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/SDKs/Winamp/wa_ipc.h b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_ipc.h index 7e1f75d2..cb285007 100644 --- a/Plugins/PluginNowPlaying/SDKs/Winamp/wa_ipc.h +++ b/Plugins/PluginNowPlaying/SDKs/Winamp/wa_ipc.h @@ -1,2470 +1,2470 @@ -/* -** Copyright (C) 1997-2008 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. -** -*/ - -#ifndef _WA_IPC_H_ -#define _WA_IPC_H_ - -#include <windows.h> -#include <stddef.h> -#if (_MSC_VER <= 1200) -typedef int intptr_t; -#endif -/* -** This is the modern replacement for the classic 'frontend.h'. Most of these -** updates are designed for in-process use, i.e. from a plugin. -** -*/ - -/* Most of the IPC_* messages involve sending the message in the form of: -** result = SendMessage(hwnd_winamp,WM_WA_IPC,(parameter),IPC_*); -** Where different then this is specified (typically with WM_COPYDATA variants) -** -** When you use SendMessage(hwnd_winamp,WM_WA_IPC,(parameter),IPC_*) and specify a IPC_* -** which is not currently implemented/supported by the Winamp version being used then it -** will return 1 for 'result'. This is a good way of helping to check if an api being -** used which returns a function pointer, etc is even going to be valid. -*/ - -#define WM_WA_IPC WM_USER - -#define WINAMP_VERSION_MAJOR(winampVersion) ((winampVersion & 0x0000FF00) >> 12) -#define WINAMP_VERSION_MINOR(winampVersion) (winampVersion & 0x000000FF) // returns, i.e. 0x12 for 5.12 and 0x10 for 5.1... - - -#define IPC_GETVERSION 0 -/* int version = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION); -** -** The version returned will be 0x20yx for Winamp 2.yx. -** Versions previous to Winamp 2.0 typically (but not always) use 0x1zyx for 1.zx. -** Just a bit weird but that's the way it goes. -** -** For Winamp 5.x it uses the format 0x50yx for Winamp 5.yx -** e.g. 5.01 -> 0x5001 -** 5.09 -> 0x5009 -** 5.1 -> 0x5010 -** -** Notes: For 5.02 this api will return the same value as for a 5.01 build. -** For 5.07 this api will return the same value as for a 5.06 build. -*/ - - -#define IPC_GETVERSIONSTRING 1 - - -#define IPC_GETREGISTEREDVERSION 770 -/* (requires Winamp 5.0+) -** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETREGISTEREDVERSION); -** -** This will open the Winamp Preferences and show the Winamp Pro page. -*/ - - -typedef struct { - const char *filename; - const char *title; - int length; -} enqueueFileWithMetaStruct; // send this to a IPC_PLAYFILE in a non WM_COPYDATA, -// and you get the nice desired result. if title is NULL, it is treated as a "thing", -// otherwise it's assumed to be a file (for speed) - -typedef struct { - const wchar_t *filename; - const wchar_t *title; - int length; -} enqueueFileWithMetaStructW; - -#define IPC_PLAYFILE 100 // dont be fooled, this is really the same as enqueufile -#define IPC_ENQUEUEFILE 100 -#define IPC_PLAYFILEW 1100 -#define IPC_ENQUEUEFILEW 1100 -/* This is sent as a WM_COPYDATA with IPC_PLAYFILE as the dwData member and the string -** of the file / playlist to be enqueued into the playlist editor as the lpData member. -** This will just enqueue the file or files since you can use this to enqueue a playlist. -** It will not clear the current playlist or change the playback state. -** -** COPYDATASTRUCT cds = {0}; -** cds.dwData = IPC_ENQUEUEFILE; -** cds.lpData = (void*)"c:\\test\\folder\\test.mp3"; -** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char -** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); -** -** -** With 2.9+ and all of the 5.x versions you can send this as a normal WM_WA_IPC -** (non WM_COPYDATA) with an enqueueFileWithMetaStruct as the param. -** If the title member is null then it is treated as a "thing" otherwise it will be -** assumed to be a file (for speed). -** -** enqueueFileWithMetaStruct eFWMS = {0}; -** eFWMS.filename = "c:\\test\\folder\\test.mp3"; -** eFWMS.title = "Whipping Good"; -** eFWMS.length = 300; // this is the number of seconds for the track -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&eFWMS,IPC_ENQUEUEFILE); -*/ - - -#define IPC_DELETE 101 -#define IPC_DELETE_INT 1101 -/* SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_DELETE); -** Use this api to clear Winamp's internal playlist. -** You should not need to use IPC_DELETE_INT since it is used internally by Winamp when -** it is dealing with some lame Windows Explorer issues (hard to believe that!). -*/ - - -#define IPC_STARTPLAY 102 -#define IPC_STARTPLAY_INT 1102 -/* SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_STARTPLAY); -** Sending this will start playback and is almost the same as hitting the play button. -** The IPC_STARTPLAY_INT version is used internally and you should not need to use it -** since it won't be any fun. -*/ - - -#define IPC_CHDIR 103 -/* This is sent as a WM_COPYDATA type message with IPC_CHDIR as the dwData value and the -** directory you want to change to as the lpData member. -** -** COPYDATASTRUCT cds = {0}; -** cds.dwData = IPC_CHDIR; -** cds.lpData = (void*)"c:\\download"; -** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char -** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); -** -** The above example will make Winamp change to the directory 'C:\download'. -*/ - - -#define IPC_ISPLAYING 104 -/* int res = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISPLAYING); -** This is sent to retrieve the current playback state of Winamp. -** If it returns 1, Winamp is playing. -** If it returns 3, Winamp is paused. -** If it returns 0, Winamp is not playing. -*/ - - -#define IPC_GETOUTPUTTIME 105 -/* int res = SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETOUTPUTTIME); -** This api can return two different sets of information about current playback status. -** -** If mode = 0 then it will return the position (in ms) of the currently playing track. -** Will return -1 if Winamp is not playing. -** -** If mode = 1 then it will return the current track length (in seconds). -** Will return -1 if there are no tracks (or possibly if Winamp cannot get the length). -** -** If mode = 2 then it will return the current track length (in milliseconds). -** Will return -1 if there are no tracks (or possibly if Winamp cannot get the length). -*/ - - -#define IPC_JUMPTOTIME 106 -/* (requires Winamp 1.60+) -** SendMessage(hwnd_winamp,WM_WA_IPC,ms,IPC_JUMPTOTIME); -** This api sets the current position (in milliseconds) for the currently playing song. -** The resulting playback position may only be an approximate time since some playback -** formats do not provide exact seeking e.g. mp3 -** This returns -1 if Winamp is not playing, 1 on end of file, or 0 if it was successful. -*/ - - -#define IPC_GETMODULENAME 109 -#define IPC_EX_ISRIGHTEXE 666 -/* usually shouldnt bother using these, but here goes: -** send a WM_COPYDATA with IPC_GETMODULENAME, and an internal -** flag gets set, which if you send a normal WM_WA_IPC message with -** IPC_EX_ISRIGHTEXE, it returns whether or not that filename -** matches. lame, I know. -*/ - - -#define IPC_WRITEPLAYLIST 120 -/* (requires Winamp 1.666+) -** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_WRITEPLAYLIST); -** -** IPC_WRITEPLAYLIST will write the current playlist to '<winampdir>\\Winamp.m3u' and -** will also return the current playlist position (see IPC_GETLISTPOS). -** -** This is kinda obsoleted by some of the newer 2.x api items but it still is good for -** use with a front-end program (instead of a plug-in) and you want to see what is in the -** current playlist. -** -** This api will only save out extended file information in the #EXTINF entry if Winamp -** has already read the data such as if the file was played of scrolled into view. If -** Winamp has not read the data then you will only find the file with its filepath entry -** (as is the base requirements for a m3u playlist). -*/ - - -#define IPC_SETPLAYLISTPOS 121 -/* (requires Winamp 2.0+) -** SendMessage(hwnd_winamp,WM_WA_IPC,position,IPC_SETPLAYLISTPOS) -** IPC_SETPLAYLISTPOS sets the playlist position to the specified 'position'. -** It will not change playback status or anything else. It will just set the current -** position in the playlist and will update the playlist view if necessary. -** -** If you use SendMessage(hwnd_winamp,WM_COMMAND,MAKEWPARAM(WINAMP_BUTTON2,0),0); -** after using IPC_SETPLAYLISTPOS then Winamp will start playing the file at 'position'. -*/ - - -#define IPC_SETVOLUME 122 -/* (requires Winamp 2.0+) -** SendMessage(hwnd_winamp,WM_WA_IPC,volume,IPC_SETVOLUME); -** IPC_SETVOLUME sets the volume of Winamp (between the range of 0 to 255). -** -** If you pass 'volume' as -666 then the message will return the current volume. -** int curvol = SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETVOLUME); -*/ - - -#define IPC_GETVOLUME(hwnd_winamp) SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETVOLUME) -/* (requires Winamp 2.0+) -** int curvol = IPC_GETVOLUME(hwnd_winamp); -** This will return the current volume of Winamp or -*/ - - -#define IPC_SETPANNING 123 -/* (requires Winamp 2.0+) -** SendMessage(hwnd_winamp,WM_WA_IPC,panning,IPC_SETPANNING); -** IPC_SETPANNING sets the panning of Winamp from 0 (left) to 255 (right). -** -** At least in 5.x+ this works from -127 (left) to 127 (right). -** -** If you pass 'panning' as -666 to this api then it will return the current panning. -** int curpan = SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETPANNING); -*/ - - -#define IPC_GETLISTLENGTH 124 -/* (requires Winamp 2.0+) -** int length = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTLENGTH); -** IPC_GETLISTLENGTH returns the length of the current playlist as the number of tracks. -*/ - - -#define IPC_GETLISTPOS 125 -/* (requires Winamp 2.05+) -** int pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS); -** IPC_GETLISTPOS returns the current playlist position (which is shown in the playlist -** editor as a differently coloured text entry e.g is yellow for the classic skin). -** -** This api is a lot like IPC_WRITEPLAYLIST but a lot faster since it does not have to -** write out the whole of the current playlist first. -*/ - - -#define IPC_GETINFO 126 -/* (requires Winamp 2.05+) -** int inf=SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETINFO); -** IPC_GETINFO returns info about the current playing song. The value -** it returns depends on the value of 'mode'. -** Mode Meaning -** ------------------ -** 0 Samplerate, in kilohertz (i.e. 44) -** 1 Bitrate (i.e. 128) -** 2 Channels (i.e. 2) -** 3 (5+) Video LOWORD=w HIWORD=h -** 4 (5+) > 65536, string (video description) -** 5 (5.25+) Samplerate, in hertz (i.e. 44100) -*/ - - -#define IPC_GETEQDATA 127 -/* (requires Winamp 2.05+) -** int data=SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA); -** IPC_GETEQDATA queries the status of the EQ. -** The value returned depends on what 'pos' is set to: -** Value Meaning -** ------------------ -** 0-9 The 10 bands of EQ data. 0-63 (+20db - -20db) -** 10 The preamp value. 0-63 (+20db - -20db) -** 11 Enabled. zero if disabled, nonzero if enabled. -** 12 Autoload. zero if disabled, nonzero if enabled. -*/ - - -#define IPC_SETEQDATA 128 -/* (requires Winamp 2.05+) -** SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA); -** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SETEQDATA); -** IPC_SETEQDATA sets the value of the last position retrieved -** by IPC_GETEQDATA. This is pretty lame, and we should provide -** an extended version that lets you do a MAKELPARAM(pos,value). -** someday... - - new (2.92+): - if the high byte is set to 0xDB, then the third byte specifies - which band, and the bottom word specifies the value. -*/ - - -#define IPC_ADDBOOKMARK 129 -#define IPC_ADDBOOKMARKW 131 -/* (requires Winamp 2.4+) -** This is sent as a WM_COPYDATA using IPC_ADDBOOKMARK as the dwData value and the -** directory you want to change to as the lpData member. This will add the specified -** file / url to the Winamp bookmark list. -** -** COPYDATASTRUCT cds = {0}; -** cds.dwData = IPC_ADDBOOKMARK; -** cds.lpData = (void*)"http://www.blah.com/listen.pls"; -** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char -** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); -** -** -** In Winamp 5.0+ we use this as a normal WM_WA_IPC and the string is null separated as -** the filename and then the title of the entry. -** -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(char*)"filename\0title\0",IPC_ADDBOOKMARK); -** -** This will notify the library / bookmark editor that a bookmark was added. -** Note that using this message in this context does not actually add the bookmark. -** Do not use, it is essentially just a notification type message :) -*/ - - -#define IPC_INSTALLPLUGIN 130 -/* This is not implemented (and is very unlikely to be done due to safety concerns). -** If it was then you could do a WM_COPYDATA with a path to a .wpz and it would then -** install the plugin for you. -** -** COPYDATASTRUCT cds = {0}; -** cds.dwData = IPC_INSTALLPLUGIN; -** cds.lpData = (void*)"c:\\path\\to\\file.wpz"; -** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char -** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); -*/ - - -#define IPC_RESTARTWINAMP 135 -/* (requires Winamp 2.2+) -** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_RESTARTWINAMP); -** IPC_RESTARTWINAMP will restart Winamp (isn't that obvious ? :) ) -** If this fails to make Winamp start after closing then there is a good chance one (or -** more) of the currently installed plugins caused Winamp to crash on exit (either as a -** silent crash or a full crash log report before it could call itself start again. -*/ - - -#define IPC_ISFULLSTOP 400 -/* (requires winamp 2.7+ I think) -** int ret=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISFULLSTOP); -** This is useful for when you're an output plugin and you want to see if the stop/close -** happening is a full stop or if you are just between tracks. This returns non zero if -** it is a full stop or zero if it is just a new track. -** benski> i think it's actually the other way around - -** !0 for EOF and 0 for user pressing stop -*/ - - -#define IPC_INETAVAILABLE 242 -/* (requires Winamp 2.05+) -** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_INETAVAILABLE); -** IPC_INETAVAILABLE will return 1 if an Internet connection is available for Winamp and -** relates to the internet connection type setting on the main general preferences page -** in the Winamp preferences. -*/ - - -#define IPC_UPDTITLE 243 -/* (requires Winamp 2.2+) -** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_UPDTITLE); -** IPC_UPDTITLE will ask Winamp to update the information about the current title and -** causes GetFileInfo(..) in the input plugin associated with the current playlist entry -** to be called. This can be called such as when an input plugin is buffering a file so -** that it can cause the buffer percentage to appear in the playlist. -*/ - - -#define IPC_REFRESHPLCACHE 247 -/* (requires Winamp 2.2+) -** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_REFRESHPLCACHE); -** IPC_REFRESHPLCACHE will flush the playlist cache buffer and you send this if you want -** Winamp to go refetch the titles for all of the entries in the current playlist. -** -** 5.3+: pass a wchar_t * string in wParam, and it'll do a strnicmp() before clearing the cache -*/ - - -#define IPC_GET_SHUFFLE 250 -/* (requires Winamp 2.4+) -** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_SHUFFLE); -** IPC_GET_SHUFFLE returns the status of the shuffle option. -** If set then it will return 1 and if not set then it will return 0. -*/ - - -#define IPC_GET_REPEAT 251 -/* (requires Winamp 2.4+) -** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_REPEAT); -** IPC_GET_REPEAT returns the status of the repeat option. -** If set then it will return 1 and if not set then it will return 0. -*/ - - -#define IPC_SET_SHUFFLE 252 -/* (requires Winamp 2.4+) -** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_SHUFFLE); -** IPC_SET_SHUFFLE sets the status of the shuffle option. -** If 'value' is 1 then shuffle is turned on. -** If 'value' is 0 then shuffle is turned off. -*/ - - -#define IPC_SET_REPEAT 253 -/* (requires Winamp 2.4+) -** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_REPEAT); -** IPC_SET_REPEAT sets the status of the repeat option. -** If 'value' is 1 then shuffle is turned on. -** If 'value' is 0 then shuffle is turned off. -*/ - - -#define IPC_ENABLEDISABLE_ALL_WINDOWS 259 // 0xdeadbeef to disable -/* (requires Winamp 2.9+) -** SendMessage(hwnd_winamp,WM_WA_IPC,(enable?0:0xdeadbeef),IPC_ENABLEDISABLE_ALL_WINDOWS); -** Sending this message with 0xdeadbeef as the param will disable all winamp windows and -** any other values will enable all of the Winamp windows again. When disabled you won't -** get any response on clicking or trying to do anything to the Winamp windows. If the -** taskbar icon is shown then you may still have control ;) -*/ - - -#define IPC_GETWND 260 -/* (requires Winamp 2.9+) -** HWND h=SendMessage(hwnd_winamp,WM_WA_IPC,IPC_GETWND_xxx,IPC_GETWND); -** returns the HWND of the window specified. -*/ - #define IPC_GETWND_EQ 0 // use one of these for the param - #define IPC_GETWND_PE 1 - #define IPC_GETWND_MB 2 - #define IPC_GETWND_VIDEO 3 -#define IPC_ISWNDVISIBLE 261 // same param as IPC_GETWND - - -/************************************************************************ -***************** in-process only (WE LOVE PLUGINS) -************************************************************************/ - -#define IPC_SETSKINW 199 -#define IPC_SETSKIN 200 -/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)"skinname",IPC_SETSKIN); -** IPC_SETSKIN sets the current skin to "skinname". Note that skinname -** can be the name of a skin, a skin .zip file, with or without path. -** If path isn't specified, the default search path is the winamp skins -** directory. -*/ - - -#define IPC_GETSKIN 201 -#define IPC_GETSKINW 1201 -/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)skinname_buffer,IPC_GETSKIN); -** IPC_GETSKIN puts the directory where skin bitmaps can be found -** into skinname_buffer. -** skinname_buffer must be MAX_PATH characters in length. -** When using a .zip'd skin file, it'll return a temporary directory -** where the ZIP was decompressed. -*/ - - -#define IPC_EXECPLUG 202 -/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)"vis_file.dll",IPC_EXECPLUG); -** IPC_EXECPLUG executes a visualization plug-in pointed to by WPARAM. -** the format of this string can be: -** "vis_whatever.dll" -** "vis_whatever.dll,0" // (first mod, file in winamp plug-in dir) -** "C:\\dir\\vis_whatever.dll,1" -*/ - - -#define IPC_GETPLAYLISTFILE 211 -#define IPC_GETPLAYLISTFILEW 214 -/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) -** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTFILE); -** IPC_GETPLAYLISTFILE gets the filename of the playlist entry [index]. -** returns a pointer to it. returns NULL on error. -*/ - - -#define IPC_GETPLAYLISTTITLE 212 -#define IPC_GETPLAYLISTTITLEW 213 -/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) -** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTTITLE); -** -** IPC_GETPLAYLISTTITLE gets the title of the playlist entry [index]. -** returns a pointer to it. returns NULL on error. -*/ - - -#define IPC_GETHTTPGETTER 240 -/* retrieves a function pointer to a HTTP retrieval function. -** if this is unsupported, returns 1 or 0. -** the function should be: -** int (*httpRetrieveFile)(HWND hwnd, char *url, char *file, char *dlgtitle); -** if you call this function, with a parent window, a URL, an output file, and a dialog title, -** it will return 0 on successful download, 1 on error. -*/ - - -#define IPC_GETHTTPGETTERW 1240 -/* int (*httpRetrieveFileW)(HWND hwnd, char *url, wchar_t *file, wchar_t *dlgtitle); */ - - -#define IPC_MBOPEN 241 -/* (requires Winamp 2.05+) -** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_MBOPEN); -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)url,IPC_MBOPEN); -** IPC_MBOPEN will open a new URL in the minibrowser. if url is NULL, it will open the Minibrowser window. -*/ - - -#define IPC_CHANGECURRENTFILE 245 -/* (requires Winamp 2.05+) -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)file,IPC_CHANGECURRENTFILE); -** IPC_CHANGECURRENTFILE will set the current playlist item. -*/ - - -#define IPC_CHANGECURRENTFILEW 1245 -/* (requires Winamp 5.3+) -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)file,IPC_CHANGECURRENTFILEW); -** IPC_CHANGECURRENTFILEW will set the current playlist item. -*/ - - -#define IPC_GETMBURL 246 -/* (requires Winamp 2.2+) -** char buffer[4096]; // Urls can be VERY long -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)buffer,IPC_GETMBURL); -** IPC_GETMBURL will retrieve the current Minibrowser URL into buffer. -** buffer must be at least 4096 bytes long. -*/ - - -#define IPC_MBBLOCK 248 -/* (requires Winamp 2.4+) -** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_MBBLOCK); -** -** IPC_MBBLOCK will block the Minibrowser from updates if value is set to 1 -*/ - - -#define IPC_MBOPENREAL 249 -/* (requires Winamp 2.4+) -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)url,IPC_MBOPENREAL); -** -** IPC_MBOPENREAL works the same as IPC_MBOPEN except that it will works even if -** IPC_MBBLOCK has been set to 1 -*/ - - -#define IPC_ADJUST_OPTIONSMENUPOS 280 -/* (requires Winamp 2.9+) -** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_OPTIONSMENUPOS); -** moves where winamp expects the Options menu in the main menu. Useful if you wish to insert a -** menu item above the options/skins/vis menus. -*/ - - -#define IPC_GET_HMENU 281 -/* (requires Winamp 2.9+) -** HMENU hMenu=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)0,IPC_GET_HMENU); -** values for data: -** 0 : main popup menu -** 1 : main menubar file menu -** 2 : main menubar options menu -** 3 : main menubar windows menu -** 4 : main menubar help menu -** other values will return NULL. -*/ - - -#define IPC_GET_EXTENDED_FILE_INFO 290 //pass a pointer to the following struct in wParam -#define IPC_GET_EXTENDED_FILE_INFO_HOOKABLE 296 -/* (requires Winamp 2.9+) -** to use, create an extendedFileInfoStruct, point the values filename and metadata to the -** filename and metadata field you wish to query, and ret to a buffer, with retlen to the -** length of that buffer, and then SendMessage(hwnd_winamp,WM_WA_IPC,&struct,IPC_GET_EXTENDED_FILE_INFO); -** the results should be in the buffer pointed to by ret. -** returns 1 if the decoder supports a getExtendedFileInfo method -*/ -typedef struct { - const char *filename; - const char *metadata; - char *ret; - size_t retlen; -} extendedFileInfoStruct; - - -#define IPC_GET_BASIC_FILE_INFO 291 //pass a pointer to the following struct in wParam -typedef struct { - const char *filename; - - int quickCheck; // set to 0 to always get, 1 for quick, 2 for default (if 2, quickCheck will be set to 0 if quick wasnot used) - - // filled in by winamp - int length; - char *title; - int titlelen; -} basicFileInfoStruct; - - -#define IPC_GET_BASIC_FILE_INFOW 1291 //pass a pointer to the following struct in wParam -typedef struct { - const wchar_t *filename; - - int quickCheck; // set to 0 to always get, 1 for quick, 2 for default (if 2, quickCheck will be set to 0 if quick wasnot used) - - // filled in by winamp - int length; - wchar_t *title; - int titlelen; -} basicFileInfoStructW; - - -#define IPC_GET_EXTLIST 292 //returns doublenull delimited. GlobalFree() it when done. if data is 0, returns raw extlist, if 1, returns something suitable for getopenfilename -#define IPC_GET_EXTLISTW 1292 // wide char version of above - - -#define IPC_INFOBOX 293 -typedef struct { - HWND parent; - char *filename; -} infoBoxParam; - - -#define IPC_INFOBOXW 1293 -typedef struct { - HWND parent; - const wchar_t *filename; -} infoBoxParamW; - - -#define IPC_SET_EXTENDED_FILE_INFO 294 //pass a pointer to the a extendedFileInfoStruct in wParam -/* (requires Winamp 2.9+) -** to use, create an extendedFileInfoStruct, point the values filename and metadata to the -** filename and metadata field you wish to write in ret. (retlen is not used). and then -** SendMessage(hwnd_winamp,WM_WA_IPC,&struct,IPC_SET_EXTENDED_FILE_INFO); -** returns 1 if the metadata is supported -** Call IPC_WRITE_EXTENDED_FILE_INFO once you're done setting all the metadata you want to update -*/ - - -#define IPC_WRITE_EXTENDED_FILE_INFO 295 -/* (requires Winamp 2.9+) -** writes all the metadata set thru IPC_SET_EXTENDED_FILE_INFO to the file -** returns 1 if the file has been successfully updated, 0 if error -*/ - - -#define IPC_FORMAT_TITLE 297 -typedef struct -{ - char *spec; // NULL=default winamp spec - void *p; - - char *out; - int out_len; - - char * (*TAGFUNC)(const char * tag, void * p); //return 0 if not found - void (*TAGFREEFUNC)(char * tag,void * p); -} waFormatTitle; - - -#define IPC_FORMAT_TITLE_EXTENDED 298 // similiar to IPC_FORMAT_TITLE, but falls back to Winamp's %tags% if your passed tag function doesn't handle it -typedef struct -{ - const wchar_t *filename; - int useExtendedInfo; // set to 1 if you want the Title Formatter to query the input plugins for any tags that your tag function fails on - const wchar_t *spec; // NULL=default winamp spec - void *p; - - wchar_t *out; - int out_len; - - wchar_t * (*TAGFUNC)(const wchar_t * tag, void * p); //return 0 if not found, -1 for empty tag - void (*TAGFREEFUNC)(wchar_t *tag, void *p); -} waFormatTitleExtended; - - -#define IPC_COPY_EXTENDED_FILE_INFO 299 -typedef struct -{ - const char *source; - const char *dest; -} copyFileInfoStruct; - - -#define IPC_COPY_EXTENDED_FILE_INFOW 1299 -typedef struct -{ - const wchar_t *source; - const wchar_t *dest; -} copyFileInfoStructW; - - -typedef struct { - int (*inflateReset)(void *strm); - int (*inflateInit_)(void *strm,const char *version, int stream_size); - int (*inflate)(void *strm, int flush); - int (*inflateEnd)(void *strm); - unsigned long (*crc32)(unsigned long crc, const unsigned char *buf, unsigned int len); -} wa_inflate_struct; - -#define IPC_GETUNCOMPRESSINTERFACE 331 -/* returns a function pointer to uncompress(). -** int (*uncompress)(unsigned char *dest, unsigned long *destLen, const unsigned char *source, unsigned long sourceLen); -** right out of zlib, useful for decompressing zlibbed data. -** if you pass the parm of 0x10100000, it will return a wa_inflate_struct * to an inflate API. -*/ - - -typedef struct _prefsDlgRec { - HINSTANCE hInst; // dll instance containing the dialog resource - int dlgID; // resource identifier of the dialog - void *proc; // window proceedure for handling the dialog defined as - // LRESULT CALLBACK PrefsPage(HWND,UINT,WPARAM,LPARAM) - - char *name; // name shown for the prefs page in the treelist - intptr_t where; // section in the treelist the prefs page is to be added to - // 0 for General Preferences - // 1 for Plugins - // 2 for Skins - // 3 for Bookmarks (no longer in the 5.0+ prefs) - // 4 for Prefs (the old 'Setup' section - no longer in 5.0+) - - intptr_t _id; - struct _prefsDlgRec *next; // no longer implemented as a linked list, now used by Winamp for other means -} prefsDlgRec; - -typedef struct _prefsDlgRecW { - HINSTANCE hInst; // dll instance containing the dialog resource - int dlgID; // resource identifier of the dialog - void *proc; // window proceedure for handling the dialog defined as - // LRESULT CALLBACK PrefsPage(HWND,UINT,WPARAM,LPARAM) - - wchar_t *name; // name shown for the prefs page in the treelist - intptr_t where; // section in the treelist the prefs page is to be added to - // 0 for General Preferences - // 1 for Plugins - // 2 for Skins - // 3 for Bookmarks (no longer in the 5.0+ prefs) - // 4 for Prefs (the old 'Setup' section - no longer in 5.0+) - - intptr_t _id; - struct _prefsDlgRec *next; // no longer implemented as a linked list, now used by Winamp for other means -} prefsDlgRecW; - -#define IPC_ADD_PREFS_DLG 332 -#define IPC_ADD_PREFS_DLGW 1332 -#define IPC_REMOVE_PREFS_DLG 333 -/* (requires Winamp 2.9+) -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_ADD_PREFS_DLG); -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_REMOVE_PREFS_DLG); -** -** IPC_ADD_PREFS_DLG: -** To use this you need to allocate a prefsDlgRec structure (either on the heap or with -** some global data but NOT on the stack) and then initialise the members of the structure -** (see the definition of the prefsDlgRec structure above). -** -** hInst - dll instance of where the dialog resource is located. -** dlgID - id of the dialog resource. -** proc - dialog window procedure for the prefs dialog. -** name - name of the prefs page as shown in the preferences list. -** where - see above for the valid locations the page can be added. -** -** Then you do SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_ADD_PREFS_DLG); -** -** example: -** -** prefsDlgRec* prefsRec = 0; -** prefsRec = GlobalAlloc(GPTR,sizeof(prefsDlgRec)); -** prefsRec->hInst = hInst; -** prefsRec->dlgID = IDD_PREFDIALOG; -** prefsRec->name = "Pref Page"; -** prefsRec->where = 0; -** prefsRec->proc = PrefsPage; -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_ADD_PREFS_DLG); -** -** -** IPC_REMOVE_PREFS_DLG: -** To use you pass the address of the same prefsRec you used when adding the prefs page -** though you shouldn't really ever have to do this but it's good to clean up after you -** when you're plugin is being unloaded. -** -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_REMOVE_PREFS_DLG); -** -** IPC_ADD_PREFS_DLGW -** requires Winamp 5.53+ -*/ - - -#define IPC_OPENPREFSTOPAGE 380 -/* SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_OPENPREFSTOPAGE); -** -** There are two ways of opening a preferences page. -** -** The first is to pass an id of a builtin preferences page (see below for ids) or a -** &prefsDlgRec of the preferences page to open and this is normally done if you are -** opening a prefs page you added yourself. -** -** If the page id does not or the &prefsRec is not valid then the prefs dialog will be -** opened to the first page available (usually the Winamp Pro page). -** -** (requires Winamp 5.04+) -** Passing -1 for param will open the preferences dialog to the last page viewed. -** -** Note: v5.0 to 5.03 had a bug in this api -** -** On the first call then the correct prefs page would be opened to but on the next call -** the prefs dialog would be brought to the front but the page would not be changed to the -** specified. -** In 5.04+ it will change to the prefs page specified if the prefs dialog is already open. -*/ - -/* Builtin Preference page ids (valid for 5.0+) -** (stored in the lParam member of the TVITEM structure from the tree item) -** -** These can be useful if you want to detect a specific prefs page and add things to it -** yourself or something like that ;) -** -** Winamp Pro 20 -** General Preferences 0 -** File Types 1 -** Playlist 23 -** Titles 21 -** Playback 42 (added in 5.25) -** Station Info 41 (added in 5.11 & removed in 5.5) -** Video 24 -** Localization 25 (added in 5.5) -** Skins 40 -** Classic Skins 22 -** Plugins 30 -** Input 31 -** Output 32 -** Visualisation 33 -** DSP/Effect 34 -** General Purpose 35 -** -** Note: -** Custom page ids begin from 60 -** The value of the normal custom pages (Global Hotkeys, Jump To File, etc) is not -** guaranteed since it depends on the order in which the plugins are loaded which can -** change on different systems. -** -** Global Hotkeys, Jump To File, Media Library (under General Preferences and child pages), -** Media Library (under Plugins), Portables, CD Ripping and Modern Skins are custom pages -** created by the plugins shipped with Winamp. -*/ - - -#define IPC_GETINIFILE 334 -/* (requires Winamp 2.9+) -** char *ini=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETINIFILE); -** This returns a pointer to the full file path of winamp.ini. -** -** char ini_path[MAX_PATH] = {0}; -** -** void GetIniFilePath(HWND hwnd){ -** if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION) >= 0x2900){ -** // this gets the string of the full ini file path -** lstrcpyn(ini_path,(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETINIFILE),sizeof(ini_path)); -** } -** else{ -** char* p = ini_path; -** p += GetModuleFileName(0,ini_path,sizeof(ini_path)) - 1; -** while(p && *p != '.'){p--;} -** lstrcpyn(p+1,"ini",sizeof(ini_path)); -** } -** } -*/ - - -#define IPC_GETINIDIRECTORY 335 -/* (requires Winamp 2.9+) -** char *dir=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETINIDIRECTORY); -** This returns a pointer to the directory where winamp.ini can be found and is -** useful if you want store config files but you don't want to use winamp.ini. -*/ - - -#define IPC_GETPLUGINDIRECTORY 336 -/* (requires Winamp 5.11+) -** char *plugdir=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETPLUGINDIRECTORY); -** This returns a pointer to the directory where Winamp has its plugins stored and is -** useful if you want store config files in plugins.ini in the plugins folder or for -** accessing any local files in the plugins folder. -*/ - - -#define IPC_GETM3UDIRECTORY 337 -/* (requires Winamp 5.11+) -** char *m3udir=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETM3UDIRECTORY); -** This returns a pointer to the directory where winamp.m3u (and winamp.m3u8 if supported) is stored in. -*/ - - -#define IPC_GETM3UDIRECTORYW 338 -/* (requires Winamp 5.3+) -** wchar_t *m3udirW=(wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETM3UDIRECTORYW); -** This returns a pointer to the directory where winamp.m3u (and winamp.m3u8 if supported) is stored in. -*/ - - -#define IPC_SPAWNBUTTONPOPUP 361 // param = -// 0 = eject -// 1 = previous -// 2 = next -// 3 = pause -// 4 = play -// 5 = stop - - -#define IPC_OPENURLBOX 360 -/* (requires Winamp 5.0+) -** HGLOBAL hglobal = (HGLOBAL)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_OPENURLBOX); -** You pass a hwnd for the dialog to be parented to (which modern skin support uses). -** This will return a HGLOBAL that needs to be freed with GlobalFree() if this worked. -*/ - - -#define IPC_OPENFILEBOX 362 -/* (requires Winamp 5.0+) -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_OPENFILEBOX); -** You pass a hwnd for the dialog to be parented to (which modern skin support uses). -*/ - - -#define IPC_OPENDIRBOX 363 -/* (requires Winamp 5.0+) -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_OPENDIRBOX); -** You pass a hwnd for the dialog to be parented to (which modern skin support uses). -*/ - - -#define IPC_SETDIALOGBOXPARENT 364 -/* (requires Winamp 5.0+) -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_SETDIALOGBOXPARENT); -** Pass 'parent' as the window which will be used as the parent for a number of the built -** in Winamp dialogs and is useful when you are taking over the whole of the UI so that -** the dialogs will not appear at the bottom right of the screen since the main winamp -** window is located at 3000x3000 by gen_ff when this is used. Call this again with -** parent = null to reset the parent back to the orginal Winamp window. -*/ - -#define IPC_GETDIALOGBOXPARENT 365 -/* (requires Winamp 5.51+) -** HWND hwndParent = SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)0, IPC_GETDIALOGBOXPARENT); -** hwndParent can/must be passed to all modal dialogs (including MessageBox) thats uses winamp as a parent -*/ - -#define IPC_UPDATEDIALOGBOXPARENT 366 -/* (requires Winamp 5.53+) -** if you previous called IPC_SETDIALOGBOXPARENT, call this every time your window resizes -*/ - -#define IPC_DRO_MIN 401 // reserved for DrO -#define IPC_SET_JTF_COMPARATOR 409 -/* pass me an int (__cdecl *)(const char *, const char *) in wParam */ -#define IPC_SET_JTF_COMPARATOR_W 410 -/* pass me an int (__cdecl *)(const wchar_t *, const wchar_t *) in wParam ... maybe someday :) */ -#define IPC_SET_JTF_DRAWTEXT 416 - -#define IPC_DRO_MAX 499 - - -// pass 0 for a copy of the skin HBITMAP -// pass 1 for name of font to use for playlist editor likeness -// pass 2 for font charset -// pass 3 for font size -#define IPC_GET_GENSKINBITMAP 503 - - -typedef struct -{ - HWND me; //hwnd of the window - - #define EMBED_FLAGS_NORESIZE 0x1 - // set this bit to keep window from being resizable - - #define EMBED_FLAGS_NOTRANSPARENCY 0x2 - // set this bit to make gen_ff turn transparency off for this window - - #define EMBED_FLAGS_NOWINDOWMENU 0x4 - // set this bit to prevent gen_ff from automatically adding your window to the right-click menu - - #define EMBED_FLAGS_GUID 0x8 - // (5.31+) call SET_EMBED_GUID(yourEmbedWindowStateStruct, GUID) to define a GUID for this window - - #define SET_EMBED_GUID(windowState, windowGUID) { windowState->flags |= EMBED_FLAGS_GUID; *((GUID *)&windowState->extra_data[4])=windowGUID; } - #define GET_EMBED_GUID(windowState) (*((GUID *)&windowState->extra_data[4])) - - int flags; // see above - - RECT r; - void *user_ptr; // for application use - int extra_data[64]; // for internal winamp use -} embedWindowState; - -#define IPC_GET_EMBEDIF 505 -/* (requires Winamp 2.9+) -** HWND myframe = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&wa_wnd,IPC_GET_EMBEDIF); -** -** or -** -** HWND myframe = 0; -** HWND (*embed)(embedWindowState *params)=0; -** *(void**)&embed = (void*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_EMBEDIF); -** myframe = embed(&wa_wnd); -** -** You pass an embedWindowState* and it will return a hwnd for the frame window or if you -** pass wParam as null then it will return a HWND embedWindow(embedWindowState *); -*/ - -#define IPC_SKINWINDOW 534 - -typedef struct __SKINWINDOWPARAM -{ - HWND hwndToSkin; - GUID windowGuid; -} SKINWINDOWPARAM; - - - -#define IPC_EMBED_ENUM 532 -typedef struct embedEnumStruct -{ - int (*enumProc)(embedWindowState *ws, struct embedEnumStruct *param); // return 1 to abort - int user_data; // or more :) -} embedEnumStruct; - // pass - - -#define IPC_EMBED_ISVALID 533 -/* (requires Winamp 2.9+) -** int valid = SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)embedhwnd,IPC_EMBED_ISVALID); -** Pass a hwnd in the wParam to this to check if the hwnd is a valid embed window or not. -*/ - - -#define IPC_CONVERTFILE 506 -/* (requires Winamp 2.92+) -** Converts a given file to a different format (PCM, MP3, etc...) -** To use, pass a pointer to a waFileConvertStruct struct -** This struct can be either on the heap or some global -** data, but NOT on the stack. At least, until the conversion is done. -** -** eg: SendMessage(hwnd_winamp,WM_WA_IPC,&myConvertStruct,IPC_CONVERTFILE); -** -** Return value: -** 0: Can't start the conversion. Look at myConvertStruct->error for details. -** 1: Conversion started. Status messages will be sent to the specified callbackhwnd. -** Be sure to call IPC_CONVERTFILE_END when your callback window receives the -** IPC_CB_CONVERT_DONE message. -*/ -typedef struct -{ - char *sourcefile; // "c:\\source.mp3" - char *destfile; // "c:\\dest.pcm" - intptr_t destformat[8]; // like 'PCM ',srate,nch,bps. - //hack alert! you can set destformat[6]=mmioFOURCC('I','N','I',' '); and destformat[7]=(int)my_ini_file; (where my_ini_file is a char*) - HWND callbackhwnd; // window that will receive the IPC_CB_CONVERT notification messages - - //filled in by winamp.exe - char *error; //if IPC_CONVERTFILE returns 0, the reason will be here - - int bytes_done; //you can look at both of these values for speed statistics - int bytes_total; - int bytes_out; - - int killswitch; // don't set it manually, use IPC_CONVERTFILE_END - intptr_t extra_data[64]; // for internal winamp use -} convertFileStruct; - - -#define IPC_CONVERTFILEW 515 -// (requires Winamp 5.36+) -typedef struct -{ - wchar_t *sourcefile; // "c:\\source.mp3" - wchar_t *destfile; // "c:\\dest.pcm" - intptr_t destformat[8]; // like 'PCM ',srate,nch,bps. - //hack alert! you can set destformat[6]=mmioFOURCC('I','N','I',' '); and destformat[7]=(int)my_ini_file; (where my_ini_file is a char*) - HWND callbackhwnd; // window that will receive the IPC_CB_CONVERT notification messages - - //filled in by winamp.exe - wchar_t *error; //if IPC_CONVERTFILE returns 0, the reason will be here - - int bytes_done; //you can look at both of these values for speed statistics - int bytes_total; - int bytes_out; - - int killswitch; // don't set it manually, use IPC_CONVERTFILE_END - intptr_t extra_data[64]; // for internal winamp use -} convertFileStructW; - - -#define IPC_CONVERTFILE_END 507 -/* (requires Winamp 2.92+) -** Stop/ends a convert process started from IPC_CONVERTFILE -** You need to call this when you receive the IPC_CB_CONVERTDONE message or when you -** want to abort a conversion process -** -** eg: SendMessage(hwnd_winamp,WM_WA_IPC,&myConvertStruct,IPC_CONVERTFILE_END); -** -** No return value -*/ - - -#define IPC_CONVERTFILEW_END 516 -// (requires Winamp 5.36+) - -typedef struct { - HWND hwndParent; - int format; - - //filled in by winamp.exe - HWND hwndConfig; - int extra_data[8]; - //hack alert! you can set extra_data[6]=mmioFOURCC('I','N','I',' '); and extra_data[7]=(int)my_ini_file; (where my_ini_file is a char*) -} convertConfigStruct; - - -#define IPC_CONVERT_CONFIG 508 -#define IPC_CONVERT_CONFIG_END 509 - -typedef struct -{ - void (*enumProc)(intptr_t user_data, const char *desc, int fourcc); - intptr_t user_data; -} converterEnumFmtStruct; -#define IPC_CONVERT_CONFIG_ENUMFMTS 510 -/* (requires Winamp 2.92+) -*/ - -typedef struct -{ - char cdletter; - char *playlist_file; - HWND callback_hwnd; - - //filled in by winamp.exe - char *error; -} burnCDStruct; -#define IPC_BURN_CD 511 -/* (requires Winamp 5.0+) -*/ - -typedef struct -{ - convertFileStruct *cfs; - int priority; -} convertSetPriority; - - -#define IPC_CONVERT_SET_PRIORITY 512 - -typedef struct -{ - convertFileStructW *cfs; - int priority; -} convertSetPriorityW; - - -#define IPC_CONVERT_SET_PRIORITYW 517 -// (requires Winamp 5.36+) - -typedef struct -{ - unsigned int format; //fourcc value - char *item; // config item, eg "bitrate" - char *data; // buffer to recieve, or buffer that contains the data - int len; // length of the data buffer (only used when getting a config item) - char *configfile; // config file to read from -} convertConfigItem; - - -#define IPC_CONVERT_CONFIG_SET_ITEM 513 // returns TRUE if successful -#define IPC_CONVERT_CONFIG_GET_ITEM 514 // returns TRUE if successful - - -typedef struct -{ - const char *filename; - char *title; // 2048 bytes - int length; - int force_useformatting; // can set this to 1 if you want to force a url to use title formatting shit -} waHookTitleStruct; - -#define IPC_HOOK_TITLES 850 -/* (requires Winamp 5.0+) -** If you hook this message and modify the information then make sure to return TRUE. -** If you don't hook the message then make sure you pass it on through the subclass chain. -** -** LRESULT CALLBACK WinampWndProc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) -** { -** LRESULT ret = CallWindowProc((WNDPROC)WinampProc,hwnd,umsg,wParam,lParam); -** -** if(message==WM_WA_IPC && lParam==IPC_HOOK_TITLES) -** { -** waHookTitleStruct *ht = (waHookTitleStruct *) wParam; -** // Doing ATF stuff with ht->title, whatever... -** return TRUE; -** } -** return ret; -** } -*/ - -typedef struct -{ - const wchar_t *filename; - wchar_t *title; // 2048 characters - int length; - int force_useformatting; // can set this to 1 if you want to force a url to use title formatting shit -} waHookTitleStructW; -#define IPC_HOOK_TITLESW 851 -/* (requires Winamp 5.3+) -** See information on IPC_HOOK_TITLES for how to process this. -*/ - - -#define IPC_GETSADATAFUNC 800 -// 0: returns a char *export_sa_get() that returns 150 bytes of data -// 1: returns a export_sa_setreq(int want); - - -#define IPC_GETVUDATAFUNC 801 -// 0: returns a int export_vu_get(int channel) that returns 0-255 (or -1 for bad channel) - - -#define IPC_ISMAINWNDVISIBLE 900 -/* (requires Winamp 5.0+) -** int visible=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISMAINWNDVISIBLE); -** You send this to Winamp to query if the main window is visible or not such as by -** unchecking the option in the main right-click menu. If the main window is visible then -** this will return 1 otherwise it returns 0. -*/ - - -typedef struct -{ - int numElems; - int *elems; - HBITMAP bm; // set if you want to override -} waSetPlColorsStruct; - -#define IPC_SETPLEDITCOLORS 920 -/* (requires Winamp 5.0+) -** This is sent by gen_ff when a modern skin is being loaded to set the colour scheme for -** the playlist editor. When sent numElems is usually 6 and matches with the 6 possible -** colours which are provided be pledit.txt from the classic skins. The elems array is -** defined as follows: -** -** elems = 0 => normal text -** elems = 1 => current text -** elems = 2 => normal background -** elems = 3 => selected background -** elems = 4 => minibroswer foreground -** elems = 5 => minibroswer background -** -** if(uMsg == WM_WA_IPC && lParam == IPC_SETPLEDITCOLORS) -** { -** waSetPlColorsStruct* colStr = (waSetPlColorsStruct*)wp; -** if(colStr) -** { -** // set or inspect the colours being used (basically for gen_ff's benefit) -** } -** } -*/ - - -typedef struct -{ - HWND wnd; - int xpos; // in screen coordinates - int ypos; -} waSpawnMenuParms; - -// waSpawnMenuParms2 is used by the menubar submenus -typedef struct -{ - HWND wnd; - int xpos; // in screen coordinates - int ypos; - int width; - int height; -} waSpawnMenuParms2; - -// the following IPC use waSpawnMenuParms as parameter -#define IPC_SPAWNEQPRESETMENU 933 -#define IPC_SPAWNFILEMENU 934 //menubar -#define IPC_SPAWNOPTIONSMENU 935 //menubar -#define IPC_SPAWNWINDOWSMENU 936 //menubar -#define IPC_SPAWNHELPMENU 937 //menubar -#define IPC_SPAWNPLAYMENU 938 //menubar -#define IPC_SPAWNPEFILEMENU 939 //menubar -#define IPC_SPAWNPEPLAYLISTMENU 940 //menubar -#define IPC_SPAWNPESORTMENU 941 //menubar -#define IPC_SPAWNPEHELPMENU 942 //menubar -#define IPC_SPAWNMLFILEMENU 943 //menubar -#define IPC_SPAWNMLVIEWMENU 944 //menubar -#define IPC_SPAWNMLHELPMENU 945 //menubar -#define IPC_SPAWNPELISTOFPLAYLISTS 946 - - -#define WM_WA_SYSTRAY WM_USER+1 -/* This is sent by the system tray when an event happens (you might want to simulate it). -** -** if(uMsg == WM_WA_SYSTRAY) -** { -** switch(lParam) -** { -** // process the messages sent from the tray -** } -** } -*/ - - -#define WM_WA_MPEG_EOF WM_USER+2 -/* Input plugins send this when they are done playing back the current file to inform -** Winamp or anyother installed plugins that the current -** -** if(uMsg == WM_WA_MPEG_EOF) -** { -** // do what is needed here -** } -*/ - - -//// video stuff - -#define IPC_IS_PLAYING_VIDEO 501 // returns >1 if playing, 0 if not, 1 if old version (so who knows):) -#define IPC_GET_IVIDEOOUTPUT 500 // see below for IVideoOutput interface -#define VIDEO_MAKETYPE(A,B,C,D) ((A) | ((B)<<8) | ((C)<<16) | ((D)<<24)) -#define VIDUSER_SET_INFOSTRING 0x1000 -#define VIDUSER_GET_VIDEOHWND 0x1001 -#define VIDUSER_SET_VFLIP 0x1002 -#define VIDUSER_SET_TRACKSELINTERFACE 0x1003 // give your ITrackSelector interface as param2 -#define VIDUSER_OPENVIDEORENDERER 0x1004 -#define VIDUSER_CLOSEVIDEORENDERER 0x1005 -#define VIDUSER_GETPOPUPMENU 0x1006 -#define VIDUSER_SET_INFOSTRINGW 0x1007 - -typedef struct -{ - int w; - int h; - int vflip; - double aspectratio; - unsigned int fmt; -} VideoOpenStruct; - -#ifndef NO_IVIDEO_DECLARE -#ifdef __cplusplus - -class VideoOutput; -class SubsItem; - -#ifndef _NSV_DEC_IF_H_ -struct YV12_PLANE { - unsigned char* baseAddr; - long rowBytes; -} ; - -struct YV12_PLANES { - YV12_PLANE y; - YV12_PLANE u; - YV12_PLANE v; -}; -#endif - -class IVideoOutput -{ - public: - virtual ~IVideoOutput() { } - virtual int open(int w, int h, int vflip, double aspectratio, unsigned int fmt)=0; - virtual void setcallback(LRESULT (*msgcallback)(void *token, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam), void *token) { (void)token; (void)msgcallback; /* to eliminate warning C4100 */ } - virtual void close()=0; - virtual void draw(void *frame)=0; - virtual void drawSubtitle(SubsItem *item) {UNREFERENCED_PARAMETER(item); } - virtual void showStatusMsg(const char *text) {UNREFERENCED_PARAMETER(text); } - virtual int get_latency() { return 0; } - virtual void notifyBufferState(int bufferstate) { UNREFERENCED_PARAMETER(bufferstate); } /* 0-255*/ - virtual INT_PTR extended(INT_PTR param1, INT_PTR param2, INT_PTR param3) { UNREFERENCED_PARAMETER(param1); UNREFERENCED_PARAMETER(param2); UNREFERENCED_PARAMETER(param3); return 0; } // Dispatchable, eat this! -}; - -class ITrackSelector -{ - public: - virtual int getNumAudioTracks()=0; - virtual void enumAudioTrackName(int n, const char *buf, int size)=0; - virtual int getCurAudioTrack()=0; - virtual int getNumVideoTracks()=0; - virtual void enumVideoTrackName(int n, const char *buf, int size)=0; - virtual int getCurVideoTrack()=0; - - virtual void setAudioTrack(int n)=0; - virtual void setVideoTrack(int n)=0; -}; - -#endif //cplusplus -#endif//NO_IVIDEO_DECLARE - -// these messages are callbacks that you can grab by subclassing the winamp window - -// wParam = -#define IPC_CB_WND_EQ 0 // use one of these for the param -#define IPC_CB_WND_PE 1 -#define IPC_CB_WND_MB 2 -#define IPC_CB_WND_VIDEO 3 -#define IPC_CB_WND_MAIN 4 - -#define IPC_CB_ONSHOWWND 600 -#define IPC_CB_ONHIDEWND 601 - -#define IPC_CB_GETTOOLTIP 602 - -#define IPC_CB_MISC 603 - #define IPC_CB_MISC_TITLE 0 // start of playing/stop/pause - #define IPC_CB_MISC_VOLUME 1 // volume/pan - #define IPC_CB_MISC_STATUS 2 // start playing/stop/pause/ffwd/rwd - #define IPC_CB_MISC_EQ 3 - #define IPC_CB_MISC_INFO 4 - #define IPC_CB_MISC_VIDEOINFO 5 - #define IPC_CB_MISC_TITLE_RATING 6 // (5.5+ for when the rating is changed via the songticker menu on current file) - -/* Example of using IPC_CB_MISC_STATUS to detect the start of track playback with 5.x -** -** if(lParam == IPC_CB_MISC && wParam == IPC_CB_MISC_STATUS) -** { -** if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISPLAYING) == 1 && -** !SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETOUTPUTTIME)) -** { -** char* file = (char*)SendMessage(hwnd_winamp,WM_WA_IPC, -** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS),IPC_GETPLAYLISTFILE); -** // only output if a valid file was found -** if(file) -** { -** MessageBox(hwnd_winamp,file,"starting",0); -** // or do something else that you need to do -** } -** } -** } -*/ - - -#define IPC_CB_CONVERT_STATUS 604 // param value goes from 0 to 100 (percent) -#define IPC_CB_CONVERT_DONE 605 - - -#define IPC_ADJUST_FFWINDOWSMENUPOS 606 -/* (requires Winamp 2.9+) -** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_FFWINDOWSMENUPOS); -** This will move where Winamp expects the freeform windows in the menubar windows main -** menu. This is useful if you wish to insert a menu item above extra freeform windows. -*/ - - -#define IPC_ISDOUBLESIZE 608 -/* (requires Winamp 5.0+) -** int dsize=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISDOUBLESIZE); -** You send this to Winamp to query if the double size mode is enabled or not. -** If it is on then this will return 1 otherwise it will return 0. -*/ - - -#define IPC_ADJUST_FFOPTIONSMENUPOS 609 -/* (requires Winamp 2.9+) -** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_FFOPTIONSMENUPOS); -** moves where winamp expects the freeform preferences item in the menubar windows main -** menu. This is useful if you wish to insert a menu item above the preferences item. -** -** Note: This setting was ignored by gen_ff until it was fixed in 5.1 -** gen_ff would assume thatthe menu position was 11 in all cases and so when you -** had two plugins attempting to add entries into the main right click menu it -** would cause the 'colour themes' submenu to either be incorrectly duplicated or -** to just disappear.instead. -*/ - - -#define IPC_GETTIMEDISPLAYMODE 610 -/* (requires Winamp 5.0+) -** int mode=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETTIMEDISPLAYMODE); -** This will return the status of the time display i.e. shows time elapsed or remaining. -** This returns 0 if Winamp is displaying time elapsed or 1 for the time remaining. -*/ - - -#define IPC_SETVISWND 611 -/* (requires Winamp 5.0+) -** int viswnd=(HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)viswnd,IPC_SETVISWND); -** This allows you to set a window to receive the following message commands (which are -** used as part of the modern skin integration). -** When you have finished or your visualisation is closed then send wParam as zero to -** ensure that things are correctly tidied up. -*/ - -/* The following messages are received as the LOWORD(wParam) of the WM_COMMAND message. -** See %SDK%\winamp\wa5vis.txt for more info about visualisation integration in Winamp. -*/ -#define ID_VIS_NEXT 40382 -#define ID_VIS_PREV 40383 -#define ID_VIS_RANDOM 40384 -#define ID_VIS_FS 40389 -#define ID_VIS_CFG 40390 -#define ID_VIS_MENU 40391 - - -#define IPC_GETVISWND 612 -/* (requires Winamp 5.0+) -** int viswnd=(HWND)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVISWND); -** This returns a HWND to the visualisation command handler window if set by IPC_SETVISWND. -*/ - - -#define IPC_ISVISRUNNING 613 -/* (requires Winamp 5.0+) -** int visrunning=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISVISRUNNING); -** This will return 1 if a visualisation is currently running and 0 if one is not running. -*/ - - -#define IPC_CB_VISRANDOM 628 // param is status of random - - -#define IPC_SETIDEALVIDEOSIZE 614 -/* (requires Winamp 5.0+) -** This is sent by Winamp back to itself so it can be trapped and adjusted as needed with -** the desired width in HIWORD(wParam) and the desired height in LOWORD(wParam). -** -** if(uMsg == WM_WA_IPC){ -** if(lParam == IPC_SETIDEALVIDEOSIZE){ -** wParam = MAKEWPARAM(height,width); -** } -** } -*/ - - -#define IPC_GETSTOPONVIDEOCLOSE 615 -/* (requires Winamp 5.0+) -** int sovc=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETSTOPONVIDEOCLOSE); -** This will return 1 if 'stop on video close' is enabled and 0 if it is disabled. -*/ - - -#define IPC_SETSTOPONVIDEOCLOSE 616 -/* (requires Winamp 5.0+) -** int sovc=SendMessage(hwnd_winamp,WM_WA_IPC,enabled,IPC_SETSTOPONVIDEOCLOSE); -** Set enabled to 1 to enable and 0 to disable the 'stop on video close' option. -*/ - - -typedef struct { - HWND hwnd; - int uMsg; - WPARAM wParam; - LPARAM lParam; -} transAccelStruct; - -#define IPC_TRANSLATEACCELERATOR 617 -/* (requires Winamp 5.0+) -** (deprecated as of 5.53x+) -*/ - -typedef struct { - int cmd; - int x; - int y; - int align; -} windowCommand; // send this as param to an IPC_PLCMD, IPC_MBCMD, IPC_VIDCMD - - -#define IPC_CB_ONTOGGLEAOT 618 - - -#define IPC_GETPREFSWND 619 -/* (requires Winamp 5.0+) -** HWND prefs = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETPREFSWND); -** This will return a handle to the preferences dialog if it is open otherwise it will -** return zero. A simple check with the OS api IsWindow(..) is a good test if it's valid. -** -** e.g. this will open (or close if already open) the preferences dialog and show if we -** managed to get a valid -** SendMessage(hwnd_winamp,WM_COMMAND,MAKEWPARAM(WINAMP_OPTIONS_PREFS,0),0); -** MessageBox(hwnd_winamp,(IsWindow((HWND)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETPREFSWND))?"Valid":"Not Open"),0,MB_OK); -*/ - - -#define IPC_SET_PE_WIDTHHEIGHT 620 -/* (requires Winamp 5.0+) -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&point,IPC_SET_PE_WIDTHHEIGHT); -** You pass a pointer to a POINT structure which holds the width and height and Winamp -** will set the playlist editor to that size (this is used by gen_ff on skin changes). -** There does not appear to be any bounds limiting with this so it is possible to create -** a zero size playlist editor window (which is a pretty silly thing to do). -*/ - - -#define IPC_GETLANGUAGEPACKINSTANCE 621 -/* (requires Winamp 5.0+) -** HINSTANCE hInst = (HINSTANCE)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLANGUAGEPACKINSTANCE); -** This will return the HINSTANCE to the currently used language pack file for winamp.exe -** -** (5.5+) -** If you pass 1 in wParam then you will have zero returned if a language pack is in use. -** if(!SendMessage(hwnd_winamp,WM_WA_IPC,1,IPC_GETLANGUAGEPACKINSTANCE)){ -** // winamp is currently using a language pack -** } -** -** If you pass 2 in wParam then you will get the path to the language pack folder. -** wchar_t* lngpackfolder = (wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,2,IPC_GETLANGUAGEPACKINSTANCE); -** -** If you pass 3 in wParam then you will get the path to the currently extracted language pack. -** wchar_t* lngpack = (wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,3,IPC_GETLANGUAGEPACKINSTANCE); -** -** If you pass 4 in wParam then you will get the name of the currently used language pack. -** wchar_t* lngname = (char*)SendMessage(hwnd_winamp,WM_WA_IPC,4,IPC_GETLANGUAGEPACKINSTANCE); -*/ -#define LANG_IDENT_STR 0 -#define LANG_LANG_CODE 1 -#define LANG_COUNTRY_CODE 2 -/* -** (5.51+) -** If you pass 5 in LOWORD(wParam) then you will get the ident string/code string -** (based on the param passed in the HIWORD(wParam) of the currently used language pack. -** The string returned with LANG_IDENT_STR is used to represent the language that the -** language pack is intended for following ISO naming conventions for consistancy. -** -** wchar_t* ident_str = (wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,MAKEWPARAM(5,LANG_XXX),IPC_GETLANGUAGEPACKINSTANCE); -** -** e.g. -** For the default language it will return the following for the different LANG_XXX codes -** LANG_IDENT_STR -> "en-US" (max buffer size of this is 9 wchar_t) -** LANG_LANG_CODE -> "en" (language code) -** LANG_COUNTRY_CODE -> "US" (country code) -** -** On pre 5.51 installs you can get LANG_IDENT_STR using the following method -** (you'll have to custom process the string returned if you want the langugage or country but that's easy ;) ) -** -** #define LANG_PACK_LANG_ID 65534 (if you don't have lang.h) -** HINSTANCE hInst = (HINSTANCE)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLANGUAGEPACKINSTANCE); -** TCHAR buffer[9] = {0}; -** LoadString(hInst,LANG_PACK_LANG_ID,buffer,sizeof(buffer)); -** -** -** -** The following example shows how using the basic api will allow you to load the playlist -** context menu resource from the currently loaded language pack or it will fallback to -** the default winamp.exe instance. -** -** HINSTANCE lang = (HINSTANCE)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLANGUAGEPACKINSTANCE); -** HMENU popup = GetSubMenu(GetSubMenu((LoadMenu(lang?lang:GetModuleHandle(0),MAKEINTRESOURCE(101))),2),5); -** // do processing as needed on the menu before displaying it -** TrackPopupMenuEx(orig,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON,rc.left,rc.bottom,hwnd_owner,0); -** DestroyMenu(popup); -** -** If you need a specific menu handle then look at IPC_GET_HMENU for more information. -*/ - - -#define IPC_CB_PEINFOTEXT 622 // data is a string, ie: "04:21/45:02" - - -#define IPC_CB_OUTPUTCHANGED 623 // output plugin was changed in config - - -#define IPC_GETOUTPUTPLUGIN 625 -/* (requires Winamp 5.0+) -** char* outdll = (char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETOUTPUTPLUGIN); -** This returns a string of the current output plugin's dll name. -** e.g. if the directsound plugin was selected then this would return 'out_ds.dll'. -*/ - - -#define IPC_SETDRAWBORDERS 626 -/* (requires Winamp 5.0+) -** SendMessage(hwnd_winamp,WM_WA_IPC,enabled,IPC_SETDRAWBORDERS); -** Set enabled to 1 to enable and 0 to disable drawing of the playlist editor and winamp -** gen class windows (used by gen_ff to allow it to draw its own window borders). -*/ - - -#define IPC_DISABLESKINCURSORS 627 -/* (requires Winamp 5.0+) -** SendMessage(hwnd_winamp,WM_WA_IPC,enabled,IPC_DISABLESKINCURSORS); -** Set enabled to 1 to enable and 0 to disable the use of skinned cursors. -*/ - - -#define IPC_GETSKINCURSORS 628 -/* (requires Winamp 5.36+) -** data = (WACURSOR)cursorId. (check wa_dlg.h for values) -*/ - - -#define IPC_CB_RESETFONT 629 - - -#define IPC_IS_FULLSCREEN 630 -/* (requires Winamp 5.0+) -** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_FULLSCREEN); -** This will return 1 if the video or visualisation is in fullscreen mode or 0 otherwise. -*/ - - -#define IPC_SET_VIS_FS_FLAG 631 -/* (requires Winamp 5.0+) -** A vis should send this message with 1/as param to notify winamp that it has gone to or has come back from fullscreen mode -*/ - - -#define IPC_SHOW_NOTIFICATION 632 - - -#define IPC_GETSKININFO 633 -#define IPC_GETSKININFOW 1633 -/* (requires Winamp 5.0+) -** This is a notification message sent to the main Winamp window by itself whenever it -** needs to get information to be shown about the current skin in the 'Current skin -** information' box on the main Skins page in the Winamp preferences. -** -** When this notification is received and the current skin is one you are providing the -** support for then you return a valid buffer for Winamp to be able to read from with -** information about it such as the name of the skin file. -** -** if(uMsg == WM_WA_IPC && lParam == IPC_GETSKININFO){ -** if(is_our_skin()){ -** return is_our_skin_name(); -** } -** } -*/ - - -#define IPC_GET_MANUALPLADVANCE 634 -/* (requires Winamp 5.03+) -** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_MANUALPLADVANCE); -** IPC_GET_MANUALPLADVANCE returns the status of the Manual Playlist Advance. -** If enabled this will return 1 otherwise it will return 0. -*/ - - -#define IPC_SET_MANUALPLADVANCE 635 -/* (requires Winamp 5.03+) -** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_MANUALPLADVANCE); -** IPC_SET_MANUALPLADVANCE sets the status of the Manual Playlist Advance option. -** Set value = 1 to turn it on and value = 0 to turn it off. -*/ - - -#define IPC_GET_NEXT_PLITEM 636 -/* (requires Winamp 5.04+) -** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_EOF_GET_NEXT_PLITEM); -** -** Sent to Winamp's main window when an item has just finished playback or the next -** button has been pressed and requesting the new playlist item number to go to. -** -** Subclass this message in your application to return the new item number. -** Return -1 for normal Winamp operation (default) or the new item number in -** the playlist to be played instead of the originally selected next track. -** -** This is primarily provided for the JTFE plugin (gen_jumpex.dll). -*/ - - -#define IPC_GET_PREVIOUS_PLITEM 637 -/* (requires Winamp 5.04+) -** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_EOF_GET_PREVIOUS_PLITEM); -** -** Sent to Winamp's main window when the previous button has been pressed and Winamp is -** requesting the new playlist item number to go to. -** -** Return -1 for normal Winamp operation (default) or the new item number in -** the playlist to be played instead of the originally selected previous track. -** -** This is primarily provided for the JTFE plugin (gen_jumpex.dll). -*/ - - -#define IPC_IS_WNDSHADE 638 -/* (requires Winamp 5.04+) -** int is_shaded=SendMessage(hwnd_winamp,WM_WA_IPC,wnd,IPC_IS_WNDSHADE); -** Pass 'wnd' as an id as defined for IPC_GETWND or pass -1 to query the status of the -** main window. This returns 1 if the window is in winshade mode and 0 if it is not. -** Make sure you only test for this on a 5.04+ install otherwise you get a false result. -** (See the notes about unhandled WM_WA_IPC messages). -*/ - - -#define IPC_SETRATING 639 -/* (requires Winamp 5.04+ with ML) -** int rating=SendMessage(hwnd_winamp,WM_WA_IPC,rating,IPC_SETRATING); -** This will allow you to set the 'rating' on the current playlist entry where 'rating' -** is an integer value from 0 (no rating) to 5 (5 stars). -** -** The following example should correctly allow you to set the rating for any specified -** playlist entry assuming of course that you're trying to get a valid playlist entry. -** -** void SetPlaylistItemRating(int item_to_set, int rating_to_set){ -** int cur_pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS); -** SendMessage(hwnd_winamp,WM_WA_IPC,item_to_set,IPC_SETPLAYLISTPOS); -** SendMessage(hwnd_winamp,WM_WA_IPC,rating_to_set,IPC_SETRATING); -** SendMessage(hwnd_winamp,WM_WA_IPC,cur_pos,IPC_SETPLAYLISTPOS); -** } -*/ - - -#define IPC_GETRATING 640 -/* (requires Winamp 5.04+ with ML) -** int rating=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETRATING); -** This returns the current playlist entry's rating between 0 (no rating) to 5 (5 stars). -** -** The following example should correctly allow you to get the rating for any specified -** playlist entry assuming of course that you're trying to get a valid playlist entry. -** -** int GetPlaylistItemRating(int item_to_get, int rating_to_set){ -** int cur_pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS), rating = 0; -** SendMessage(hwnd_winamp,WM_WA_IPC,item_to_get,IPC_SETPLAYLISTPOS); -** rating = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETRATING); -** SendMessage(hwnd_winamp,WM_WA_IPC,cur_pos,IPC_SETPLAYLISTPOS); -** return rating; -** } -*/ - - -#define IPC_GETNUMAUDIOTRACKS 641 -/* (requires Winamp 5.04+) -** int n = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETNUMAUDIOTRACKS); -** This will return the number of audio tracks available from the currently playing item. -*/ - - -#define IPC_GETNUMVIDEOTRACKS 642 -/* (requires Winamp 5.04+) -** int n = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETNUMVIDEOTRACKS); -** This will return the number of video tracks available from the currently playing item. -*/ - - -#define IPC_GETAUDIOTRACK 643 -/* (requires Winamp 5.04+) -** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETAUDIOTRACK); -** This will return the id of the current audio track for the currently playing item. -*/ - - -#define IPC_GETVIDEOTRACK 644 -/* (requires Winamp 5.04+) -** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVIDEOTRACK); -** This will return the id of the current video track for the currently playing item. -*/ - - -#define IPC_SETAUDIOTRACK 645 -/* (requires Winamp 5.04+) -** SendMessage(hwnd_winamp,WM_WA_IPC,track,IPC_SETAUDIOTRACK); -** This allows you to switch to a new audio track (if supported) in the current playing file. -*/ - - -#define IPC_SETVIDEOTRACK 646 -/* (requires Winamp 5.04+) -** SendMessage(hwnd_winamp,WM_WA_IPC,track,IPC_SETVIDEOTRACK); -** This allows you to switch to a new video track (if supported) in the current playing file. -*/ - - -#define IPC_PUSH_DISABLE_EXIT 647 -/* (requires Winamp 5.04+) -** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_PUSH_DISABLE_EXIT); -** This will let you disable or re-enable the UI exit functions (close button, context -** menu, alt-f4). Remember to call IPC_POP_DISABLE_EXIT when you are done doing whatever -** was required that needed to prevent exit otherwise you have to kill the Winamp process. -*/ - - -#define IPC_POP_DISABLE_EXIT 648 -/* (requires Winamp 5.04+) -** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_POP_DISABLE_EXIT); -** See IPC_PUSH_DISABLE_EXIT -*/ - - -#define IPC_IS_EXIT_ENABLED 649 -/* (requires Winamp 5.04+) -** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_EXIT_ENABLED); -** This will return 0 if the 'exit' option of Winamp's menu is disabled and 1 otherwise. -*/ - - -#define IPC_IS_AOT 650 -/* (requires Winamp 5.04+) -** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_AOT); -** This will return the status of the always on top flag. -** Note: This may not match the actual TOPMOST window flag while another fullscreen -** application is focused if the user has the 'Disable always on top while fullscreen -** applications are focused' option under the General Preferences page is checked. -*/ - - -#define IPC_USES_RECYCLEBIN 651 -/* (requires Winamp 5.09+) -** int use_bin=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USES_RECYCLEBIN); -** This will return 1 if the deleted file should be sent to the recycle bin or -** 0 if deleted files should be deleted permanently (default action for < 5.09). -** -** Note: if you use this on pre 5.09 installs of Winamp then it will return 1 which is -** not correct but is due to the way that SendMessage(..) handles un-processed messages. -** Below is a quick case for checking if the returned value is correct. -** -** if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USES_RECYCLEBIN) && -** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION)>=0x5009) -** { -** // can safely follow the option to recycle the file -** } -** else -* { -** // need to do a permanent delete of the file -** } -*/ - - -#define IPC_FLUSHAUDITS 652 -/* -** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_FLUSHAUDITS); -** -** Will flush any pending audits in the global audits queue -** -*/ - -#define IPC_GETPLAYITEM_START 653 -#define IPC_GETPLAYITEM_END 654 - - -#define IPC_GETVIDEORESIZE 655 -#define IPC_SETVIDEORESIZE 656 - - -#define IPC_INITIAL_SHOW_STATE 657 -/* (requires Winamp 5.36+) -** int show_state = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_INITIAL_SHOW_STATE); -** returns the processed value of nCmdShow when Winamp was started -** (see MSDN documentation the values passed to WinMain(..) for what this should be) -** -** e.g. -** if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_INITIAL_SHOW_STATE) == SW_SHOWMINIMIZED){ -** // we are starting minimised so process as needed (keep our window hidden) -** } -** -** Useful for seeing if winamp was run minimised on startup so you can act accordingly. -** On pre-5.36 versions this will effectively return SW_NORMAL/SW_SHOWNORMAL due to the -** handling of unknown apis returning 1 from Winamp. -*/ - -// >>>>>>>>>>> Next is 658 - -#define IPC_PLCMD 1000 - -#define PLCMD_ADD 0 -#define PLCMD_REM 1 -#define PLCMD_SEL 2 -#define PLCMD_MISC 3 -#define PLCMD_LIST 4 - -//#define IPC_MBCMD 1001 - -#define MBCMD_BACK 0 -#define MBCMD_FORWARD 1 -#define MBCMD_STOP 2 -#define MBCMD_RELOAD 3 -#define MBCMD_MISC 4 - -#define IPC_VIDCMD 1002 - -#define VIDCMD_FULLSCREEN 0 -#define VIDCMD_1X 1 -#define VIDCMD_2X 2 -#define VIDCMD_LIB 3 -#define VIDPOPUP_MISC 4 - -//#define IPC_MBURL 1003 //sets the URL -//#define IPC_MBGETCURURL 1004 //copies the current URL into wParam (have a 4096 buffer ready) -//#define IPC_MBGETDESC 1005 //copies the current URL description into wParam (have a 4096 buffer ready) -//#define IPC_MBCHECKLOCFILE 1006 //checks that the link file is up to date (otherwise updates it). wParam=parent HWND -//#define IPC_MBREFRESH 1007 //refreshes the "now playing" view in the library -//#define IPC_MBGETDEFURL 1008 //copies the default URL into wParam (have a 4096 buffer ready) - -#define IPC_STATS_LIBRARY_ITEMCNT 1300 // updates library count status - -/* -** IPC's in the message range 2000 - 3000 are reserved internally for freeform messages. -** These messages are taken from ff_ipc.h which is part of the Modern skin integration. -*/ - -#define IPC_FF_FIRST 2000 - -#define IPC_FF_COLOURTHEME_CHANGE IPC_FF_ONCOLORTHEMECHANGED -#define IPC_FF_ONCOLORTHEMECHANGED IPC_FF_FIRST + 3 -/* -** This is a notification message sent when the user changes the colour theme in a Modern -** skin and can also be detected when the Modern skin is first loaded as the gen_ff plugin -** applies relevant settings and styles (like the colour theme). -** -** The value of wParam is the name of the new color theme being switched to. -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(const char*)colour_theme_name,IPC_FF_ONCOLORTHEMECHANGED); -** -** (IPC_FF_COLOURTHEME_CHANGE is the name i (DrO) was using before getting a copy of -** ff_ipc.h with the proper name in it). -*/ - - -#define IPC_FF_ISMAINWND IPC_FF_FIRST + 4 -/* -** int ismainwnd = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)test_wnd,IPC_FF_ISMAINWND); -** -** This allows you to determine if the window handle passed to it is a modern skin main -** window or not. If it is a main window or any of its windowshade variants then it will -** return 1. -** -** Because of the way modern skins are implemented, it is possible for this message to -** return a positive test result for a number of window handles within the current Winamp -** process. This appears to be because you can have a visible main window, a compact main -** window and also a winshaded version. -** -** The following code example below is one way of seeing how this api works since it will -** enumerate all windows related to Winamp at the time and allows you to process as -** required when a detection happens. -** -** -** EnumThreadWindows(GetCurrentThreadId(),enumWndProc,0); -** -** BOOL CALLBACK enumWndProc(HWND hwnd, LPARAM lParam){ -** -** if(SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)hwnd,IPC_FF_ISMAINWND)){ -** // do processing in here -** // or continue the enum for other main windows (if they exist) -** // and just comment out the line below -** return 0; -** } -** return 1; -** } -*/ - - -#define IPC_FF_GETCONTENTWND IPC_FF_FIRST + 5 -/* -** HWND wa2embed = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)test_wnd,IPC_FF_GETCONTENTWND); -** -** This will return the Winamp 2 window that is embedded in the window's container -** i.e. if hwnd is the playlist editor windowshade hwnd then it will return the Winamp 2 -** playlist editor hwnd. -** -** If no content is found such as the window has nothing embedded then this will return -** the hwnd passed to it. -*/ - - -#define IPC_FF_NOTIFYHOTKEY IPC_FF_FIRST + 6 -/* -** This is a notification message sent when the user uses a global hotkey combination -** which had been registered with the gen_hotkeys plugin. -** -** The value of wParam is the description of the hotkey as passed to gen_hotkeys. -** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(const char*)hotkey_desc,IPC_FF_NOTIFYHOTKEY); -*/ - -#define IPC_FF_LAST 3000 - - -/* -** General IPC messages in Winamp -** -** All notification messages appear in the lParam of the main window message proceedure. -*/ - - -#define IPC_GETDROPTARGET 3001 -/* (requires Winamp 5.0+) -** IDropTarget* IDrop = (IDropTarget*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETDROPTARGET); -** -** You call this to retrieve a copy of the IDropTarget interface which Winamp created for -** handling external drag and drop operations on to it's Windows. This is only really -** useful if you're providing an alternate interface and want your Windows to provide the -** same drag and drop support as Winamp normally provides the user. Check out MSDN or -** your prefered search facility for more information about the IDropTarget interface and -** what's needed to handle it in your own instance. -*/ - - -#define IPC_PLAYLIST_MODIFIED 3002 -/* (requires Winamp 5.0+) -** This is a notification message sent to the main Winamp window whenever the playlist is -** modified in any way e.g. the addition/removal of a playlist entry. -** -** It is not a good idea to do large amounts of processing in this notification since it -** will slow down Winamp as playlist entries are modified (especially when you're adding -** in a large playlist). -** -** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYLIST_MODIFIED) -** { -** // do what you need to do here -** } -*/ - - -#define IPC_PLAYING_FILE 3003 -/* (requires Winamp 5.0+) -** This is a notification message sent to the main Winamp window when playback begins for -** a file. This passes the full filepath in the wParam of the message received. -** -** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYING_FILE) -** { -** // do what you need to do here, e.g. -** process_file((char*)wParam); -** } -*/ - - -#define IPC_PLAYING_FILEW 13003 -/* (requires Winamp 5.0+) -** This is a notification message sent to the main Winamp window when playback begins for -** a file. This passes the full filepath in the wParam of the message received. -** -** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYING_FILEW) -** { -** // do what you need to do here, e.g. -** process_file((wchar_t*)wParam); -** } -*/ - - -#define IPC_FILE_TAG_MAY_HAVE_UPDATED 3004 -#define IPC_FILE_TAG_MAY_HAVE_UPDATEDW 3005 -/* (requires Winamp 5.0+) -** This is a notification message sent to the main Winamp window when a file's tag -** (e.g. id3) may have been updated. This appears to be sent when the InfoBox(..) function -** of the associated input plugin returns a 1 (which is the file information dialog/editor -** call normally). -** -** if(uMsg == WM_WA_IPC && lParam == IPC_FILE_TAG_MAY_HAVE_UPDATED) -** { -** // do what you need to do here, e.g. -** update_info_on_file_update((char*)wParam); -** } -*/ - - -#define IPC_ALLOW_PLAYTRACKING 3007 -/* (requires Winamp 5.0+) -** SendMessage(hwnd_winamp,WM_WA_IPC,allow,IPC_ALLOW_PLAYTRACKING); -** Send allow as nonzero to allow play tracking and zero to disable the mode. -*/ - - -#define IPC_HOOK_OKTOQUIT 3010 -/* (requires Winamp 5.0+) -** This is a notification message sent to the main Winamp window asking if it's okay to -** close or not. Return zero to prevent Winamp from closing or return anything non-zero -** to allow Winamp to close. -** -** The best implementation of this option is to let the message pass through to the -** original window proceedure since another plugin may want to have a say in the matter -** with regards to Winamp closing. -** -** if(uMsg == WM_WA_IPC && lParam == IPC_HOOK_OKTOQUIT) -** { -** // do what you need to do here, e.g. -** if(no_shut_down()) -** { -** return 1; -** } -** } -*/ - - -#define IPC_WRITECONFIG 3011 -/* (requires Winamp 5.0+) -** SendMessage(hwnd_winamp,WM_WA_IPC,write_type,IPC_WRITECONFIG); -** -** Send write_type as 2 to write all config settings and the current playlist. -** -** Send write_type as 1 to write the playlist and common settings. -** This won't save the following ini settings:: -** -** defext, titlefmt, proxy, visplugin_name, dspplugin_name, check_ft_startup, -** visplugin_num, pe_fontsize, visplugin_priority, visplugin_autoexec, dspplugin_num, -** sticon, splash, taskbar, dropaotfs, ascb_new, ttips, riol, minst, whichicon, -** whichicon2, addtolist, snap, snaplen, parent, hilite, disvis, rofiob, shownumsinpl, -** keeponscreen, eqdsize, usecursors, fixtitles, priority, shuffle_morph_rate, -** useexttitles, bifont, inet_mode, ospb, embedwnd_freesize, no_visseh -** (the above was valid for 5.1) -** -** Send write_type as 0 to write the common and less common settings and no playlist. -*/ - - -#define IPC_UPDATE_URL 3012 -// pass the URL (char *) in lparam, will be free()'d on done. - - -#define IPC_GET_RANDFUNC 3015 // returns a function to get a random number -/* (requires Winamp 5.1+) -** int (*randfunc)(void) = (int(*)(void))SendMessage(plugin.hwndParent,WM_WA_IPC,0,IPC_GET_RANDFUNC); -** if(randfunc && randfunc != 1){ -** randfunc(); -** } -** -** This will return a positive 32-bit number (essentially 31-bit). -** The check for a returned value of 1 is because that's the default return value from -** SendMessage(..) when it is not handled so is good to check for it in this situation. -*/ - - -#define IPC_METADATA_CHANGED 3017 -/* (requires Winamp 5.1+) -** int changed=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(char*)field,IPC_METADATA_CHANGED); -** a plugin can SendMessage this to winamp if internal metadata has changes. -** wParam should be a char * of what field changed -** -** Currently used for internal actions (and very few at that) the intent of this api is -** to allow a plugin to call it when metadata has changed in the current playlist entry -** e.g.a new id3v2 tag was found in a stream -** -** The wparam value can either be NULL or a pointer to an ansi string for the metadata -** which has changed. This can be thought of as an advanced version of IPC_UPDTITLE and -** could be used to allow for update of the current title when a specific tag changed. -** -** Not recommended to be used since there is not the complete handling implemented in -** Winamp for it at the moment. -*/ - - -#define IPC_SKIN_CHANGED 3018 -/* (requires Winamp 5.1+) -** This is a notification message sent to the main Winamp window by itself whenever -** the skin in use is changed. There is no information sent by the wParam for this. -** -** if(message == WM_WA_IPC && lparam == IPC_SKIN_CHANGED) -** { -** // do what you need to do to handle skin changes, e.g. call WADlg_init(hwnd_winamp); -** } -*/ - - -#define IPC_REGISTER_LOWORD_COMMAND 3019 -/* (requires Winamp 5.1+) -** WORD id = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_REGISTER_LOWORD_COMMAND); -** This will assign you a unique id for making your own commands such as for extra menu -** entries. The starting value returned by this message will potentially change as and -** when the main resource file of Winamp is updated with extra data so assumptions cannot -** be made on what will be returned and plugin loading order will affect things as well. - -** 5.33+ -** If you want to reserve more than one id, you can pass the number of ids required in wParam -*/ - - -#define IPC_GET_DISPATCH_OBJECT 3020 // gets winamp main IDispatch * (for embedded webpages) -#define IPC_GET_UNIQUE_DISPATCH_ID 3021 // gives you a unique dispatch ID that won't conflict with anything in winamp's IDispatch * -#define IPC_ADD_DISPATCH_OBJECT 3022 // add your own dispatch object into winamp's. This lets embedded webpages access your functions -// pass a pointer to DispatchInfo (see below). Winamp makes a copy of all this data so you can safely delete it later -typedef struct -{ - wchar_t *name; // filled in by plugin, make sure it's a unicode string!! (i.e. L"myObject" instead of "myObject). - struct IDispatch *dispatch; // filled in by plugin - DWORD id; // filled in by winamp on return -} DispatchInfo; - -// see IPC_JSAPI2_GET_DISPATCH_OBJECT for version 2 of the Dispatchable scripting interface - -#define IPC_GET_PROXY_STRING 3023 -/* (requires Winamp 5.11+) -** char* proxy_string=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_PROXY_STRING); -** This will return the same string as is shown on the General Preferences page. -*/ - - -#define IPC_USE_REGISTRY 3024 -/* (requires Winamp 5.11+) -** int reg_enabled=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USE_REGISTRY); -** This will return 0 if you should leave your grubby hands off the registry (i.e. for -** lockdown mode). This is useful if Winamp is run from a USB drive and you can't alter -** system settings, etc. -*/ - - -#define IPC_GET_API_SERVICE 3025 -/* (requires Winamp 5.12+) -** api_service* api_service = (api_service)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_API_SERVICE); -** This api will return Winamp's api_service pointer (which is what Winamp3 used, heh). -** If this api is not supported in the Winamp version that is being used at the time then -** the returned value from this api will be 1 which is a good version check. -** -** As of 5.12 there is support for .w5s plugins which reside in %WinampDir%\System and -** are intended for common code that can be shared amongst other plugins e.g. jnetlib.w5s -** which contains jnetlib in one instance instead of being duplicated multiple times in -** all of the plugins which need internet access. -** -** Details on the .w5s specifications will come at some stage (possibly). -*/ - - -typedef struct { - const wchar_t *filename; - const wchar_t *metadata; - wchar_t *ret; - size_t retlen; -} extendedFileInfoStructW; - -#define IPC_GET_EXTENDED_FILE_INFOW 3026 -/* (requires Winamp 5.13+) -** Pass a pointer to the above struct in wParam -*/ - - -#define IPC_GET_EXTENDED_FILE_INFOW_HOOKABLE 3027 -#define IPC_SET_EXTENDED_FILE_INFOW 3028 -/* (requires Winamp 5.13+) -** Pass a pointer to the above struct in wParam -*/ - - -#define IPC_PLAYLIST_GET_NEXT_SELECTED 3029 -/* (requires 5.2+) -** int pl_item = SendMessage(hwnd_winamp,WM_WA_IPC,start,IPC_PLAYLIST_GET_NEXT_SELECTED); -** -** This works just like the ListView_GetNextItem(..) macro for ListView controls. -** 'start' is the index of the playlist item that you want to begin the search after or -** set this as -1 for the search to begin with the first item of the current playlist. -** -** This will return the index of the selected playlist according to the 'start' value or -** it returns -1 if there is no selection or no more selected items according to 'start'. -** -** Quick example: -** -** int sel = -1; -** // keep incrementing the start of the search so we get all of the selected entries -** while((sel = SendMessage(hwnd_winamp,WM_WA_IPC,sel,IPC_PLAYLIST_GET_NEXT_SELECTED))!=-1){ -** // show the playlist file entry of the selected item(s) if there were any -** MessageBox(hwnd_winamp,(char*)SendMessage(hwnd_winamp,WM_WA_IPC,sel,IPC_GETPLAYLISTFILE),0,0); -** } -*/ - - -#define IPC_PLAYLIST_GET_SELECTED_COUNT 3030 -/* (requires 5.2+) -** int selcnt = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_PLAYLIST_GET_SELECTED_COUNT); -** This will return the number of selected playlist entries. -*/ - - -#define IPC_GET_PLAYING_FILENAME 3031 -// returns wchar_t * of the currently playing filename - -#define IPC_OPEN_URL 3032 -// send either ANSI or Unicode string (it'll figure it out, but it MUST start with "h"!, so don't send ftp:// or anything funny) -// you can also send this one from another process via WM_COPYDATA (unicode only) - - -#define IPC_USE_UXTHEME_FUNC 3033 -/* (requires Winamp 5.35+) -** int ret = SendMessage(hwnd_winamp,WM_WA_IPC,param,IPC_USE_UXTHEME_FUNC); -** param can be IPC_ISWINTHEMEPRESENT or IPC_ISAEROCOMPOSITIONACTIVE or a valid hwnd. -** -** If you pass a hwnd then it will apply EnableThemeDialogTexture(ETDT_ENABLETAB) -** so your tabbed dialogs can use the correct theme (on supporting OSes ie XP+). -** -** Otherwise this will return a value based on the param passed (as defined below). -** For compatability, the return value will be zero on success (as 1 is returned -** for unsupported ipc calls on older Winamp versions) -*/ - #define IPC_ISWINTHEMEPRESENT 0 -/* This will return 0 if uxtheme.dll is present -** int isthemethere = !SendMessage(hwnd_winamp,WM_WA_IPC,IPC_ISWINTHEMEPRESENT,IPC_USE_UXTHEME_FUNC); -*/ - #define IPC_ISAEROCOMPOSITIONACTIVE 1 -/* This will return 0 if aero composition is active -** int isaero = !SendMessage(hwnd_winamp,WM_WA_IPC,IPC_ISAEROCOMPOSITIONACTIVE,IPC_USE_UXTHEME_FUNC); -*/ - - -#define IPC_GET_PLAYING_TITLE 3034 -// returns wchar_t * of the current title - - -#define IPC_CANPLAY 3035 -// pass const wchar_t *, returns an in_mod * or 0 - - -typedef struct { - // fill these in... - size_t size; // init to sizeof(artFetchData) - HWND parent; // parent window of the dialogue - - // fill as much of these in as you can, otherwise leave them 0 - const wchar_t *artist; - const wchar_t *album; - int year, amgArtistId, amgAlbumId; - - int showCancelAll; // if set to 1, this shows a "Cancel All" button on the dialogue - - // winamp will fill these in if the call returns successfully: - void* imgData; // a buffer filled with compressed image data. free with WASABI_API_MEMMGR->sysFree() - int imgDataLen; // the size of the buffer - wchar_t type[10]; // eg: "jpg" - const wchar_t *gracenoteFileId; // if you know it -} artFetchData; - -#define IPC_FETCH_ALBUMART 3036 -/* pass an artFetchData*. This will show a dialog guiding the use through choosing art, and return when it's finished -** return values: -** 1: error showing dialog -** 0: success -** -1: cancel was pressed -** -2: cancel all was pressed -*/ - -#define IPC_JSAPI2_GET_DISPATCH_OBJECT 3037 -/* pass your service's unique ID, as a wchar_t * string, in wParam -** Winamp will copy the string, so don't worry about keeping it around -** An IDispatch * object will be returned (cast the return value from SendMessage) -** This IDispatch can be used for scripting/automation/VB interaction -** Pass to IE via IDocHostUIHandler::GetExternal and it will become window.external in javscript -*/ - -#define IPC_REGISTER_WINAMP_IPCMESSAGE 65536 -/* (requires Winamp 5.0+) -** DWORD id = SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)name,IPC_REGISTER_WINAMP_IPCMESSAGE); -** The value 'id' returned is > 65536 and is incremented on subsequent calls for unique -** 'name' values passed to it. By using the same 'name' in different plugins will allow a -** common runtime api to be provided for the currently running instance of Winamp -** e.g. -** PostMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)my_param,registered_ipc); -** Have a look at wa_hotkeys.h for an example on how this api is used in practice for a -** custom WM_WA_IPC message. -** -** if(uMsg == WM_WA_IPC && lParam == id_from_register_winamp_ipcmessage){ -** // do things -** } -*/ - +/* +** Copyright (C) 1997-2008 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. +** +*/ + +#ifndef _WA_IPC_H_ +#define _WA_IPC_H_ + +#include <windows.h> +#include <stddef.h> +#if (_MSC_VER <= 1200) +typedef int intptr_t; +#endif +/* +** This is the modern replacement for the classic 'frontend.h'. Most of these +** updates are designed for in-process use, i.e. from a plugin. +** +*/ + +/* Most of the IPC_* messages involve sending the message in the form of: +** result = SendMessage(hwnd_winamp,WM_WA_IPC,(parameter),IPC_*); +** Where different then this is specified (typically with WM_COPYDATA variants) +** +** When you use SendMessage(hwnd_winamp,WM_WA_IPC,(parameter),IPC_*) and specify a IPC_* +** which is not currently implemented/supported by the Winamp version being used then it +** will return 1 for 'result'. This is a good way of helping to check if an api being +** used which returns a function pointer, etc is even going to be valid. +*/ + +#define WM_WA_IPC WM_USER + +#define WINAMP_VERSION_MAJOR(winampVersion) ((winampVersion & 0x0000FF00) >> 12) +#define WINAMP_VERSION_MINOR(winampVersion) (winampVersion & 0x000000FF) // returns, i.e. 0x12 for 5.12 and 0x10 for 5.1... + + +#define IPC_GETVERSION 0 +/* int version = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION); +** +** The version returned will be 0x20yx for Winamp 2.yx. +** Versions previous to Winamp 2.0 typically (but not always) use 0x1zyx for 1.zx. +** Just a bit weird but that's the way it goes. +** +** For Winamp 5.x it uses the format 0x50yx for Winamp 5.yx +** e.g. 5.01 -> 0x5001 +** 5.09 -> 0x5009 +** 5.1 -> 0x5010 +** +** Notes: For 5.02 this api will return the same value as for a 5.01 build. +** For 5.07 this api will return the same value as for a 5.06 build. +*/ + + +#define IPC_GETVERSIONSTRING 1 + + +#define IPC_GETREGISTEREDVERSION 770 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETREGISTEREDVERSION); +** +** This will open the Winamp Preferences and show the Winamp Pro page. +*/ + + +typedef struct { + const char *filename; + const char *title; + int length; +} enqueueFileWithMetaStruct; // send this to a IPC_PLAYFILE in a non WM_COPYDATA, +// and you get the nice desired result. if title is NULL, it is treated as a "thing", +// otherwise it's assumed to be a file (for speed) + +typedef struct { + const wchar_t *filename; + const wchar_t *title; + int length; +} enqueueFileWithMetaStructW; + +#define IPC_PLAYFILE 100 // dont be fooled, this is really the same as enqueufile +#define IPC_ENQUEUEFILE 100 +#define IPC_PLAYFILEW 1100 +#define IPC_ENQUEUEFILEW 1100 +/* This is sent as a WM_COPYDATA with IPC_PLAYFILE as the dwData member and the string +** of the file / playlist to be enqueued into the playlist editor as the lpData member. +** This will just enqueue the file or files since you can use this to enqueue a playlist. +** It will not clear the current playlist or change the playback state. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_ENQUEUEFILE; +** cds.lpData = (void*)"c:\\test\\folder\\test.mp3"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +** +** +** With 2.9+ and all of the 5.x versions you can send this as a normal WM_WA_IPC +** (non WM_COPYDATA) with an enqueueFileWithMetaStruct as the param. +** If the title member is null then it is treated as a "thing" otherwise it will be +** assumed to be a file (for speed). +** +** enqueueFileWithMetaStruct eFWMS = {0}; +** eFWMS.filename = "c:\\test\\folder\\test.mp3"; +** eFWMS.title = "Whipping Good"; +** eFWMS.length = 300; // this is the number of seconds for the track +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&eFWMS,IPC_ENQUEUEFILE); +*/ + + +#define IPC_DELETE 101 +#define IPC_DELETE_INT 1101 +/* SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_DELETE); +** Use this api to clear Winamp's internal playlist. +** You should not need to use IPC_DELETE_INT since it is used internally by Winamp when +** it is dealing with some lame Windows Explorer issues (hard to believe that!). +*/ + + +#define IPC_STARTPLAY 102 +#define IPC_STARTPLAY_INT 1102 +/* SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_STARTPLAY); +** Sending this will start playback and is almost the same as hitting the play button. +** The IPC_STARTPLAY_INT version is used internally and you should not need to use it +** since it won't be any fun. +*/ + + +#define IPC_CHDIR 103 +/* This is sent as a WM_COPYDATA type message with IPC_CHDIR as the dwData value and the +** directory you want to change to as the lpData member. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_CHDIR; +** cds.lpData = (void*)"c:\\download"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +** +** The above example will make Winamp change to the directory 'C:\download'. +*/ + + +#define IPC_ISPLAYING 104 +/* int res = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISPLAYING); +** This is sent to retrieve the current playback state of Winamp. +** If it returns 1, Winamp is playing. +** If it returns 3, Winamp is paused. +** If it returns 0, Winamp is not playing. +*/ + + +#define IPC_GETOUTPUTTIME 105 +/* int res = SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETOUTPUTTIME); +** This api can return two different sets of information about current playback status. +** +** If mode = 0 then it will return the position (in ms) of the currently playing track. +** Will return -1 if Winamp is not playing. +** +** If mode = 1 then it will return the current track length (in seconds). +** Will return -1 if there are no tracks (or possibly if Winamp cannot get the length). +** +** If mode = 2 then it will return the current track length (in milliseconds). +** Will return -1 if there are no tracks (or possibly if Winamp cannot get the length). +*/ + + +#define IPC_JUMPTOTIME 106 +/* (requires Winamp 1.60+) +** SendMessage(hwnd_winamp,WM_WA_IPC,ms,IPC_JUMPTOTIME); +** This api sets the current position (in milliseconds) for the currently playing song. +** The resulting playback position may only be an approximate time since some playback +** formats do not provide exact seeking e.g. mp3 +** This returns -1 if Winamp is not playing, 1 on end of file, or 0 if it was successful. +*/ + + +#define IPC_GETMODULENAME 109 +#define IPC_EX_ISRIGHTEXE 666 +/* usually shouldnt bother using these, but here goes: +** send a WM_COPYDATA with IPC_GETMODULENAME, and an internal +** flag gets set, which if you send a normal WM_WA_IPC message with +** IPC_EX_ISRIGHTEXE, it returns whether or not that filename +** matches. lame, I know. +*/ + + +#define IPC_WRITEPLAYLIST 120 +/* (requires Winamp 1.666+) +** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_WRITEPLAYLIST); +** +** IPC_WRITEPLAYLIST will write the current playlist to '<winampdir>\\Winamp.m3u' and +** will also return the current playlist position (see IPC_GETLISTPOS). +** +** This is kinda obsoleted by some of the newer 2.x api items but it still is good for +** use with a front-end program (instead of a plug-in) and you want to see what is in the +** current playlist. +** +** This api will only save out extended file information in the #EXTINF entry if Winamp +** has already read the data such as if the file was played of scrolled into view. If +** Winamp has not read the data then you will only find the file with its filepath entry +** (as is the base requirements for a m3u playlist). +*/ + + +#define IPC_SETPLAYLISTPOS 121 +/* (requires Winamp 2.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,position,IPC_SETPLAYLISTPOS) +** IPC_SETPLAYLISTPOS sets the playlist position to the specified 'position'. +** It will not change playback status or anything else. It will just set the current +** position in the playlist and will update the playlist view if necessary. +** +** If you use SendMessage(hwnd_winamp,WM_COMMAND,MAKEWPARAM(WINAMP_BUTTON2,0),0); +** after using IPC_SETPLAYLISTPOS then Winamp will start playing the file at 'position'. +*/ + + +#define IPC_SETVOLUME 122 +/* (requires Winamp 2.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,volume,IPC_SETVOLUME); +** IPC_SETVOLUME sets the volume of Winamp (between the range of 0 to 255). +** +** If you pass 'volume' as -666 then the message will return the current volume. +** int curvol = SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETVOLUME); +*/ + + +#define IPC_GETVOLUME(hwnd_winamp) SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETVOLUME) +/* (requires Winamp 2.0+) +** int curvol = IPC_GETVOLUME(hwnd_winamp); +** This will return the current volume of Winamp or +*/ + + +#define IPC_SETPANNING 123 +/* (requires Winamp 2.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,panning,IPC_SETPANNING); +** IPC_SETPANNING sets the panning of Winamp from 0 (left) to 255 (right). +** +** At least in 5.x+ this works from -127 (left) to 127 (right). +** +** If you pass 'panning' as -666 to this api then it will return the current panning. +** int curpan = SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETPANNING); +*/ + + +#define IPC_GETLISTLENGTH 124 +/* (requires Winamp 2.0+) +** int length = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTLENGTH); +** IPC_GETLISTLENGTH returns the length of the current playlist as the number of tracks. +*/ + + +#define IPC_GETLISTPOS 125 +/* (requires Winamp 2.05+) +** int pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS); +** IPC_GETLISTPOS returns the current playlist position (which is shown in the playlist +** editor as a differently coloured text entry e.g is yellow for the classic skin). +** +** This api is a lot like IPC_WRITEPLAYLIST but a lot faster since it does not have to +** write out the whole of the current playlist first. +*/ + + +#define IPC_GETINFO 126 +/* (requires Winamp 2.05+) +** int inf=SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETINFO); +** IPC_GETINFO returns info about the current playing song. The value +** it returns depends on the value of 'mode'. +** Mode Meaning +** ------------------ +** 0 Samplerate, in kilohertz (i.e. 44) +** 1 Bitrate (i.e. 128) +** 2 Channels (i.e. 2) +** 3 (5+) Video LOWORD=w HIWORD=h +** 4 (5+) > 65536, string (video description) +** 5 (5.25+) Samplerate, in hertz (i.e. 44100) +*/ + + +#define IPC_GETEQDATA 127 +/* (requires Winamp 2.05+) +** int data=SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA); +** IPC_GETEQDATA queries the status of the EQ. +** The value returned depends on what 'pos' is set to: +** Value Meaning +** ------------------ +** 0-9 The 10 bands of EQ data. 0-63 (+20db - -20db) +** 10 The preamp value. 0-63 (+20db - -20db) +** 11 Enabled. zero if disabled, nonzero if enabled. +** 12 Autoload. zero if disabled, nonzero if enabled. +*/ + + +#define IPC_SETEQDATA 128 +/* (requires Winamp 2.05+) +** SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA); +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SETEQDATA); +** IPC_SETEQDATA sets the value of the last position retrieved +** by IPC_GETEQDATA. This is pretty lame, and we should provide +** an extended version that lets you do a MAKELPARAM(pos,value). +** someday... + + new (2.92+): + if the high byte is set to 0xDB, then the third byte specifies + which band, and the bottom word specifies the value. +*/ + + +#define IPC_ADDBOOKMARK 129 +#define IPC_ADDBOOKMARKW 131 +/* (requires Winamp 2.4+) +** This is sent as a WM_COPYDATA using IPC_ADDBOOKMARK as the dwData value and the +** directory you want to change to as the lpData member. This will add the specified +** file / url to the Winamp bookmark list. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_ADDBOOKMARK; +** cds.lpData = (void*)"http://www.blah.com/listen.pls"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +** +** +** In Winamp 5.0+ we use this as a normal WM_WA_IPC and the string is null separated as +** the filename and then the title of the entry. +** +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(char*)"filename\0title\0",IPC_ADDBOOKMARK); +** +** This will notify the library / bookmark editor that a bookmark was added. +** Note that using this message in this context does not actually add the bookmark. +** Do not use, it is essentially just a notification type message :) +*/ + + +#define IPC_INSTALLPLUGIN 130 +/* This is not implemented (and is very unlikely to be done due to safety concerns). +** If it was then you could do a WM_COPYDATA with a path to a .wpz and it would then +** install the plugin for you. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_INSTALLPLUGIN; +** cds.lpData = (void*)"c:\\path\\to\\file.wpz"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +*/ + + +#define IPC_RESTARTWINAMP 135 +/* (requires Winamp 2.2+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_RESTARTWINAMP); +** IPC_RESTARTWINAMP will restart Winamp (isn't that obvious ? :) ) +** If this fails to make Winamp start after closing then there is a good chance one (or +** more) of the currently installed plugins caused Winamp to crash on exit (either as a +** silent crash or a full crash log report before it could call itself start again. +*/ + + +#define IPC_ISFULLSTOP 400 +/* (requires winamp 2.7+ I think) +** int ret=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISFULLSTOP); +** This is useful for when you're an output plugin and you want to see if the stop/close +** happening is a full stop or if you are just between tracks. This returns non zero if +** it is a full stop or zero if it is just a new track. +** benski> i think it's actually the other way around - +** !0 for EOF and 0 for user pressing stop +*/ + + +#define IPC_INETAVAILABLE 242 +/* (requires Winamp 2.05+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_INETAVAILABLE); +** IPC_INETAVAILABLE will return 1 if an Internet connection is available for Winamp and +** relates to the internet connection type setting on the main general preferences page +** in the Winamp preferences. +*/ + + +#define IPC_UPDTITLE 243 +/* (requires Winamp 2.2+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_UPDTITLE); +** IPC_UPDTITLE will ask Winamp to update the information about the current title and +** causes GetFileInfo(..) in the input plugin associated with the current playlist entry +** to be called. This can be called such as when an input plugin is buffering a file so +** that it can cause the buffer percentage to appear in the playlist. +*/ + + +#define IPC_REFRESHPLCACHE 247 +/* (requires Winamp 2.2+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_REFRESHPLCACHE); +** IPC_REFRESHPLCACHE will flush the playlist cache buffer and you send this if you want +** Winamp to go refetch the titles for all of the entries in the current playlist. +** +** 5.3+: pass a wchar_t * string in wParam, and it'll do a strnicmp() before clearing the cache +*/ + + +#define IPC_GET_SHUFFLE 250 +/* (requires Winamp 2.4+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_SHUFFLE); +** IPC_GET_SHUFFLE returns the status of the shuffle option. +** If set then it will return 1 and if not set then it will return 0. +*/ + + +#define IPC_GET_REPEAT 251 +/* (requires Winamp 2.4+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_REPEAT); +** IPC_GET_REPEAT returns the status of the repeat option. +** If set then it will return 1 and if not set then it will return 0. +*/ + + +#define IPC_SET_SHUFFLE 252 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_SHUFFLE); +** IPC_SET_SHUFFLE sets the status of the shuffle option. +** If 'value' is 1 then shuffle is turned on. +** If 'value' is 0 then shuffle is turned off. +*/ + + +#define IPC_SET_REPEAT 253 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_REPEAT); +** IPC_SET_REPEAT sets the status of the repeat option. +** If 'value' is 1 then shuffle is turned on. +** If 'value' is 0 then shuffle is turned off. +*/ + + +#define IPC_ENABLEDISABLE_ALL_WINDOWS 259 // 0xdeadbeef to disable +/* (requires Winamp 2.9+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(enable?0:0xdeadbeef),IPC_ENABLEDISABLE_ALL_WINDOWS); +** Sending this message with 0xdeadbeef as the param will disable all winamp windows and +** any other values will enable all of the Winamp windows again. When disabled you won't +** get any response on clicking or trying to do anything to the Winamp windows. If the +** taskbar icon is shown then you may still have control ;) +*/ + + +#define IPC_GETWND 260 +/* (requires Winamp 2.9+) +** HWND h=SendMessage(hwnd_winamp,WM_WA_IPC,IPC_GETWND_xxx,IPC_GETWND); +** returns the HWND of the window specified. +*/ + #define IPC_GETWND_EQ 0 // use one of these for the param + #define IPC_GETWND_PE 1 + #define IPC_GETWND_MB 2 + #define IPC_GETWND_VIDEO 3 +#define IPC_ISWNDVISIBLE 261 // same param as IPC_GETWND + + +/************************************************************************ +***************** in-process only (WE LOVE PLUGINS) +************************************************************************/ + +#define IPC_SETSKINW 199 +#define IPC_SETSKIN 200 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)"skinname",IPC_SETSKIN); +** IPC_SETSKIN sets the current skin to "skinname". Note that skinname +** can be the name of a skin, a skin .zip file, with or without path. +** If path isn't specified, the default search path is the winamp skins +** directory. +*/ + + +#define IPC_GETSKIN 201 +#define IPC_GETSKINW 1201 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)skinname_buffer,IPC_GETSKIN); +** IPC_GETSKIN puts the directory where skin bitmaps can be found +** into skinname_buffer. +** skinname_buffer must be MAX_PATH characters in length. +** When using a .zip'd skin file, it'll return a temporary directory +** where the ZIP was decompressed. +*/ + + +#define IPC_EXECPLUG 202 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)"vis_file.dll",IPC_EXECPLUG); +** IPC_EXECPLUG executes a visualization plug-in pointed to by WPARAM. +** the format of this string can be: +** "vis_whatever.dll" +** "vis_whatever.dll,0" // (first mod, file in winamp plug-in dir) +** "C:\\dir\\vis_whatever.dll,1" +*/ + + +#define IPC_GETPLAYLISTFILE 211 +#define IPC_GETPLAYLISTFILEW 214 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTFILE); +** IPC_GETPLAYLISTFILE gets the filename of the playlist entry [index]. +** returns a pointer to it. returns NULL on error. +*/ + + +#define IPC_GETPLAYLISTTITLE 212 +#define IPC_GETPLAYLISTTITLEW 213 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTTITLE); +** +** IPC_GETPLAYLISTTITLE gets the title of the playlist entry [index]. +** returns a pointer to it. returns NULL on error. +*/ + + +#define IPC_GETHTTPGETTER 240 +/* retrieves a function pointer to a HTTP retrieval function. +** if this is unsupported, returns 1 or 0. +** the function should be: +** int (*httpRetrieveFile)(HWND hwnd, char *url, char *file, char *dlgtitle); +** if you call this function, with a parent window, a URL, an output file, and a dialog title, +** it will return 0 on successful download, 1 on error. +*/ + + +#define IPC_GETHTTPGETTERW 1240 +/* int (*httpRetrieveFileW)(HWND hwnd, char *url, wchar_t *file, wchar_t *dlgtitle); */ + + +#define IPC_MBOPEN 241 +/* (requires Winamp 2.05+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_MBOPEN); +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)url,IPC_MBOPEN); +** IPC_MBOPEN will open a new URL in the minibrowser. if url is NULL, it will open the Minibrowser window. +*/ + + +#define IPC_CHANGECURRENTFILE 245 +/* (requires Winamp 2.05+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)file,IPC_CHANGECURRENTFILE); +** IPC_CHANGECURRENTFILE will set the current playlist item. +*/ + + +#define IPC_CHANGECURRENTFILEW 1245 +/* (requires Winamp 5.3+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)file,IPC_CHANGECURRENTFILEW); +** IPC_CHANGECURRENTFILEW will set the current playlist item. +*/ + + +#define IPC_GETMBURL 246 +/* (requires Winamp 2.2+) +** char buffer[4096]; // Urls can be VERY long +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)buffer,IPC_GETMBURL); +** IPC_GETMBURL will retrieve the current Minibrowser URL into buffer. +** buffer must be at least 4096 bytes long. +*/ + + +#define IPC_MBBLOCK 248 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_MBBLOCK); +** +** IPC_MBBLOCK will block the Minibrowser from updates if value is set to 1 +*/ + + +#define IPC_MBOPENREAL 249 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)url,IPC_MBOPENREAL); +** +** IPC_MBOPENREAL works the same as IPC_MBOPEN except that it will works even if +** IPC_MBBLOCK has been set to 1 +*/ + + +#define IPC_ADJUST_OPTIONSMENUPOS 280 +/* (requires Winamp 2.9+) +** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_OPTIONSMENUPOS); +** moves where winamp expects the Options menu in the main menu. Useful if you wish to insert a +** menu item above the options/skins/vis menus. +*/ + + +#define IPC_GET_HMENU 281 +/* (requires Winamp 2.9+) +** HMENU hMenu=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)0,IPC_GET_HMENU); +** values for data: +** 0 : main popup menu +** 1 : main menubar file menu +** 2 : main menubar options menu +** 3 : main menubar windows menu +** 4 : main menubar help menu +** other values will return NULL. +*/ + + +#define IPC_GET_EXTENDED_FILE_INFO 290 //pass a pointer to the following struct in wParam +#define IPC_GET_EXTENDED_FILE_INFO_HOOKABLE 296 +/* (requires Winamp 2.9+) +** to use, create an extendedFileInfoStruct, point the values filename and metadata to the +** filename and metadata field you wish to query, and ret to a buffer, with retlen to the +** length of that buffer, and then SendMessage(hwnd_winamp,WM_WA_IPC,&struct,IPC_GET_EXTENDED_FILE_INFO); +** the results should be in the buffer pointed to by ret. +** returns 1 if the decoder supports a getExtendedFileInfo method +*/ +typedef struct { + const char *filename; + const char *metadata; + char *ret; + size_t retlen; +} extendedFileInfoStruct; + + +#define IPC_GET_BASIC_FILE_INFO 291 //pass a pointer to the following struct in wParam +typedef struct { + const char *filename; + + int quickCheck; // set to 0 to always get, 1 for quick, 2 for default (if 2, quickCheck will be set to 0 if quick wasnot used) + + // filled in by winamp + int length; + char *title; + int titlelen; +} basicFileInfoStruct; + + +#define IPC_GET_BASIC_FILE_INFOW 1291 //pass a pointer to the following struct in wParam +typedef struct { + const wchar_t *filename; + + int quickCheck; // set to 0 to always get, 1 for quick, 2 for default (if 2, quickCheck will be set to 0 if quick wasnot used) + + // filled in by winamp + int length; + wchar_t *title; + int titlelen; +} basicFileInfoStructW; + + +#define IPC_GET_EXTLIST 292 //returns doublenull delimited. GlobalFree() it when done. if data is 0, returns raw extlist, if 1, returns something suitable for getopenfilename +#define IPC_GET_EXTLISTW 1292 // wide char version of above + + +#define IPC_INFOBOX 293 +typedef struct { + HWND parent; + char *filename; +} infoBoxParam; + + +#define IPC_INFOBOXW 1293 +typedef struct { + HWND parent; + const wchar_t *filename; +} infoBoxParamW; + + +#define IPC_SET_EXTENDED_FILE_INFO 294 //pass a pointer to the a extendedFileInfoStruct in wParam +/* (requires Winamp 2.9+) +** to use, create an extendedFileInfoStruct, point the values filename and metadata to the +** filename and metadata field you wish to write in ret. (retlen is not used). and then +** SendMessage(hwnd_winamp,WM_WA_IPC,&struct,IPC_SET_EXTENDED_FILE_INFO); +** returns 1 if the metadata is supported +** Call IPC_WRITE_EXTENDED_FILE_INFO once you're done setting all the metadata you want to update +*/ + + +#define IPC_WRITE_EXTENDED_FILE_INFO 295 +/* (requires Winamp 2.9+) +** writes all the metadata set thru IPC_SET_EXTENDED_FILE_INFO to the file +** returns 1 if the file has been successfully updated, 0 if error +*/ + + +#define IPC_FORMAT_TITLE 297 +typedef struct +{ + char *spec; // NULL=default winamp spec + void *p; + + char *out; + int out_len; + + char * (*TAGFUNC)(const char * tag, void * p); //return 0 if not found + void (*TAGFREEFUNC)(char * tag,void * p); +} waFormatTitle; + + +#define IPC_FORMAT_TITLE_EXTENDED 298 // similiar to IPC_FORMAT_TITLE, but falls back to Winamp's %tags% if your passed tag function doesn't handle it +typedef struct +{ + const wchar_t *filename; + int useExtendedInfo; // set to 1 if you want the Title Formatter to query the input plugins for any tags that your tag function fails on + const wchar_t *spec; // NULL=default winamp spec + void *p; + + wchar_t *out; + int out_len; + + wchar_t * (*TAGFUNC)(const wchar_t * tag, void * p); //return 0 if not found, -1 for empty tag + void (*TAGFREEFUNC)(wchar_t *tag, void *p); +} waFormatTitleExtended; + + +#define IPC_COPY_EXTENDED_FILE_INFO 299 +typedef struct +{ + const char *source; + const char *dest; +} copyFileInfoStruct; + + +#define IPC_COPY_EXTENDED_FILE_INFOW 1299 +typedef struct +{ + const wchar_t *source; + const wchar_t *dest; +} copyFileInfoStructW; + + +typedef struct { + int (*inflateReset)(void *strm); + int (*inflateInit_)(void *strm,const char *version, int stream_size); + int (*inflate)(void *strm, int flush); + int (*inflateEnd)(void *strm); + unsigned long (*crc32)(unsigned long crc, const unsigned char *buf, unsigned int len); +} wa_inflate_struct; + +#define IPC_GETUNCOMPRESSINTERFACE 331 +/* returns a function pointer to uncompress(). +** int (*uncompress)(unsigned char *dest, unsigned long *destLen, const unsigned char *source, unsigned long sourceLen); +** right out of zlib, useful for decompressing zlibbed data. +** if you pass the parm of 0x10100000, it will return a wa_inflate_struct * to an inflate API. +*/ + + +typedef struct _prefsDlgRec { + HINSTANCE hInst; // dll instance containing the dialog resource + int dlgID; // resource identifier of the dialog + void *proc; // window proceedure for handling the dialog defined as + // LRESULT CALLBACK PrefsPage(HWND,UINT,WPARAM,LPARAM) + + char *name; // name shown for the prefs page in the treelist + intptr_t where; // section in the treelist the prefs page is to be added to + // 0 for General Preferences + // 1 for Plugins + // 2 for Skins + // 3 for Bookmarks (no longer in the 5.0+ prefs) + // 4 for Prefs (the old 'Setup' section - no longer in 5.0+) + + intptr_t _id; + struct _prefsDlgRec *next; // no longer implemented as a linked list, now used by Winamp for other means +} prefsDlgRec; + +typedef struct _prefsDlgRecW { + HINSTANCE hInst; // dll instance containing the dialog resource + int dlgID; // resource identifier of the dialog + void *proc; // window proceedure for handling the dialog defined as + // LRESULT CALLBACK PrefsPage(HWND,UINT,WPARAM,LPARAM) + + wchar_t *name; // name shown for the prefs page in the treelist + intptr_t where; // section in the treelist the prefs page is to be added to + // 0 for General Preferences + // 1 for Plugins + // 2 for Skins + // 3 for Bookmarks (no longer in the 5.0+ prefs) + // 4 for Prefs (the old 'Setup' section - no longer in 5.0+) + + intptr_t _id; + struct _prefsDlgRec *next; // no longer implemented as a linked list, now used by Winamp for other means +} prefsDlgRecW; + +#define IPC_ADD_PREFS_DLG 332 +#define IPC_ADD_PREFS_DLGW 1332 +#define IPC_REMOVE_PREFS_DLG 333 +/* (requires Winamp 2.9+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_ADD_PREFS_DLG); +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_REMOVE_PREFS_DLG); +** +** IPC_ADD_PREFS_DLG: +** To use this you need to allocate a prefsDlgRec structure (either on the heap or with +** some global data but NOT on the stack) and then initialise the members of the structure +** (see the definition of the prefsDlgRec structure above). +** +** hInst - dll instance of where the dialog resource is located. +** dlgID - id of the dialog resource. +** proc - dialog window procedure for the prefs dialog. +** name - name of the prefs page as shown in the preferences list. +** where - see above for the valid locations the page can be added. +** +** Then you do SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_ADD_PREFS_DLG); +** +** example: +** +** prefsDlgRec* prefsRec = 0; +** prefsRec = GlobalAlloc(GPTR,sizeof(prefsDlgRec)); +** prefsRec->hInst = hInst; +** prefsRec->dlgID = IDD_PREFDIALOG; +** prefsRec->name = "Pref Page"; +** prefsRec->where = 0; +** prefsRec->proc = PrefsPage; +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_ADD_PREFS_DLG); +** +** +** IPC_REMOVE_PREFS_DLG: +** To use you pass the address of the same prefsRec you used when adding the prefs page +** though you shouldn't really ever have to do this but it's good to clean up after you +** when you're plugin is being unloaded. +** +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_REMOVE_PREFS_DLG); +** +** IPC_ADD_PREFS_DLGW +** requires Winamp 5.53+ +*/ + + +#define IPC_OPENPREFSTOPAGE 380 +/* SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_OPENPREFSTOPAGE); +** +** There are two ways of opening a preferences page. +** +** The first is to pass an id of a builtin preferences page (see below for ids) or a +** &prefsDlgRec of the preferences page to open and this is normally done if you are +** opening a prefs page you added yourself. +** +** If the page id does not or the &prefsRec is not valid then the prefs dialog will be +** opened to the first page available (usually the Winamp Pro page). +** +** (requires Winamp 5.04+) +** Passing -1 for param will open the preferences dialog to the last page viewed. +** +** Note: v5.0 to 5.03 had a bug in this api +** +** On the first call then the correct prefs page would be opened to but on the next call +** the prefs dialog would be brought to the front but the page would not be changed to the +** specified. +** In 5.04+ it will change to the prefs page specified if the prefs dialog is already open. +*/ + +/* Builtin Preference page ids (valid for 5.0+) +** (stored in the lParam member of the TVITEM structure from the tree item) +** +** These can be useful if you want to detect a specific prefs page and add things to it +** yourself or something like that ;) +** +** Winamp Pro 20 +** General Preferences 0 +** File Types 1 +** Playlist 23 +** Titles 21 +** Playback 42 (added in 5.25) +** Station Info 41 (added in 5.11 & removed in 5.5) +** Video 24 +** Localization 25 (added in 5.5) +** Skins 40 +** Classic Skins 22 +** Plugins 30 +** Input 31 +** Output 32 +** Visualisation 33 +** DSP/Effect 34 +** General Purpose 35 +** +** Note: +** Custom page ids begin from 60 +** The value of the normal custom pages (Global Hotkeys, Jump To File, etc) is not +** guaranteed since it depends on the order in which the plugins are loaded which can +** change on different systems. +** +** Global Hotkeys, Jump To File, Media Library (under General Preferences and child pages), +** Media Library (under Plugins), Portables, CD Ripping and Modern Skins are custom pages +** created by the plugins shipped with Winamp. +*/ + + +#define IPC_GETINIFILE 334 +/* (requires Winamp 2.9+) +** char *ini=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETINIFILE); +** This returns a pointer to the full file path of winamp.ini. +** +** char ini_path[MAX_PATH] = {0}; +** +** void GetIniFilePath(HWND hwnd){ +** if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION) >= 0x2900){ +** // this gets the string of the full ini file path +** lstrcpyn(ini_path,(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETINIFILE),sizeof(ini_path)); +** } +** else{ +** char* p = ini_path; +** p += GetModuleFileName(0,ini_path,sizeof(ini_path)) - 1; +** while(p && *p != '.'){p--;} +** lstrcpyn(p+1,"ini",sizeof(ini_path)); +** } +** } +*/ + + +#define IPC_GETINIDIRECTORY 335 +/* (requires Winamp 2.9+) +** char *dir=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETINIDIRECTORY); +** This returns a pointer to the directory where winamp.ini can be found and is +** useful if you want store config files but you don't want to use winamp.ini. +*/ + + +#define IPC_GETPLUGINDIRECTORY 336 +/* (requires Winamp 5.11+) +** char *plugdir=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETPLUGINDIRECTORY); +** This returns a pointer to the directory where Winamp has its plugins stored and is +** useful if you want store config files in plugins.ini in the plugins folder or for +** accessing any local files in the plugins folder. +*/ + + +#define IPC_GETM3UDIRECTORY 337 +/* (requires Winamp 5.11+) +** char *m3udir=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETM3UDIRECTORY); +** This returns a pointer to the directory where winamp.m3u (and winamp.m3u8 if supported) is stored in. +*/ + + +#define IPC_GETM3UDIRECTORYW 338 +/* (requires Winamp 5.3+) +** wchar_t *m3udirW=(wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETM3UDIRECTORYW); +** This returns a pointer to the directory where winamp.m3u (and winamp.m3u8 if supported) is stored in. +*/ + + +#define IPC_SPAWNBUTTONPOPUP 361 // param = +// 0 = eject +// 1 = previous +// 2 = next +// 3 = pause +// 4 = play +// 5 = stop + + +#define IPC_OPENURLBOX 360 +/* (requires Winamp 5.0+) +** HGLOBAL hglobal = (HGLOBAL)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_OPENURLBOX); +** You pass a hwnd for the dialog to be parented to (which modern skin support uses). +** This will return a HGLOBAL that needs to be freed with GlobalFree() if this worked. +*/ + + +#define IPC_OPENFILEBOX 362 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_OPENFILEBOX); +** You pass a hwnd for the dialog to be parented to (which modern skin support uses). +*/ + + +#define IPC_OPENDIRBOX 363 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_OPENDIRBOX); +** You pass a hwnd for the dialog to be parented to (which modern skin support uses). +*/ + + +#define IPC_SETDIALOGBOXPARENT 364 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_SETDIALOGBOXPARENT); +** Pass 'parent' as the window which will be used as the parent for a number of the built +** in Winamp dialogs and is useful when you are taking over the whole of the UI so that +** the dialogs will not appear at the bottom right of the screen since the main winamp +** window is located at 3000x3000 by gen_ff when this is used. Call this again with +** parent = null to reset the parent back to the orginal Winamp window. +*/ + +#define IPC_GETDIALOGBOXPARENT 365 +/* (requires Winamp 5.51+) +** HWND hwndParent = SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)0, IPC_GETDIALOGBOXPARENT); +** hwndParent can/must be passed to all modal dialogs (including MessageBox) thats uses winamp as a parent +*/ + +#define IPC_UPDATEDIALOGBOXPARENT 366 +/* (requires Winamp 5.53+) +** if you previous called IPC_SETDIALOGBOXPARENT, call this every time your window resizes +*/ + +#define IPC_DRO_MIN 401 // reserved for DrO +#define IPC_SET_JTF_COMPARATOR 409 +/* pass me an int (__cdecl *)(const char *, const char *) in wParam */ +#define IPC_SET_JTF_COMPARATOR_W 410 +/* pass me an int (__cdecl *)(const wchar_t *, const wchar_t *) in wParam ... maybe someday :) */ +#define IPC_SET_JTF_DRAWTEXT 416 + +#define IPC_DRO_MAX 499 + + +// pass 0 for a copy of the skin HBITMAP +// pass 1 for name of font to use for playlist editor likeness +// pass 2 for font charset +// pass 3 for font size +#define IPC_GET_GENSKINBITMAP 503 + + +typedef struct +{ + HWND me; //hwnd of the window + + #define EMBED_FLAGS_NORESIZE 0x1 + // set this bit to keep window from being resizable + + #define EMBED_FLAGS_NOTRANSPARENCY 0x2 + // set this bit to make gen_ff turn transparency off for this window + + #define EMBED_FLAGS_NOWINDOWMENU 0x4 + // set this bit to prevent gen_ff from automatically adding your window to the right-click menu + + #define EMBED_FLAGS_GUID 0x8 + // (5.31+) call SET_EMBED_GUID(yourEmbedWindowStateStruct, GUID) to define a GUID for this window + + #define SET_EMBED_GUID(windowState, windowGUID) { windowState->flags |= EMBED_FLAGS_GUID; *((GUID *)&windowState->extra_data[4])=windowGUID; } + #define GET_EMBED_GUID(windowState) (*((GUID *)&windowState->extra_data[4])) + + int flags; // see above + + RECT r; + void *user_ptr; // for application use + int extra_data[64]; // for internal winamp use +} embedWindowState; + +#define IPC_GET_EMBEDIF 505 +/* (requires Winamp 2.9+) +** HWND myframe = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&wa_wnd,IPC_GET_EMBEDIF); +** +** or +** +** HWND myframe = 0; +** HWND (*embed)(embedWindowState *params)=0; +** *(void**)&embed = (void*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_EMBEDIF); +** myframe = embed(&wa_wnd); +** +** You pass an embedWindowState* and it will return a hwnd for the frame window or if you +** pass wParam as null then it will return a HWND embedWindow(embedWindowState *); +*/ + +#define IPC_SKINWINDOW 534 + +typedef struct __SKINWINDOWPARAM +{ + HWND hwndToSkin; + GUID windowGuid; +} SKINWINDOWPARAM; + + + +#define IPC_EMBED_ENUM 532 +typedef struct embedEnumStruct +{ + int (*enumProc)(embedWindowState *ws, struct embedEnumStruct *param); // return 1 to abort + int user_data; // or more :) +} embedEnumStruct; + // pass + + +#define IPC_EMBED_ISVALID 533 +/* (requires Winamp 2.9+) +** int valid = SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)embedhwnd,IPC_EMBED_ISVALID); +** Pass a hwnd in the wParam to this to check if the hwnd is a valid embed window or not. +*/ + + +#define IPC_CONVERTFILE 506 +/* (requires Winamp 2.92+) +** Converts a given file to a different format (PCM, MP3, etc...) +** To use, pass a pointer to a waFileConvertStruct struct +** This struct can be either on the heap or some global +** data, but NOT on the stack. At least, until the conversion is done. +** +** eg: SendMessage(hwnd_winamp,WM_WA_IPC,&myConvertStruct,IPC_CONVERTFILE); +** +** Return value: +** 0: Can't start the conversion. Look at myConvertStruct->error for details. +** 1: Conversion started. Status messages will be sent to the specified callbackhwnd. +** Be sure to call IPC_CONVERTFILE_END when your callback window receives the +** IPC_CB_CONVERT_DONE message. +*/ +typedef struct +{ + char *sourcefile; // "c:\\source.mp3" + char *destfile; // "c:\\dest.pcm" + intptr_t destformat[8]; // like 'PCM ',srate,nch,bps. + //hack alert! you can set destformat[6]=mmioFOURCC('I','N','I',' '); and destformat[7]=(int)my_ini_file; (where my_ini_file is a char*) + HWND callbackhwnd; // window that will receive the IPC_CB_CONVERT notification messages + + //filled in by winamp.exe + char *error; //if IPC_CONVERTFILE returns 0, the reason will be here + + int bytes_done; //you can look at both of these values for speed statistics + int bytes_total; + int bytes_out; + + int killswitch; // don't set it manually, use IPC_CONVERTFILE_END + intptr_t extra_data[64]; // for internal winamp use +} convertFileStruct; + + +#define IPC_CONVERTFILEW 515 +// (requires Winamp 5.36+) +typedef struct +{ + wchar_t *sourcefile; // "c:\\source.mp3" + wchar_t *destfile; // "c:\\dest.pcm" + intptr_t destformat[8]; // like 'PCM ',srate,nch,bps. + //hack alert! you can set destformat[6]=mmioFOURCC('I','N','I',' '); and destformat[7]=(int)my_ini_file; (where my_ini_file is a char*) + HWND callbackhwnd; // window that will receive the IPC_CB_CONVERT notification messages + + //filled in by winamp.exe + wchar_t *error; //if IPC_CONVERTFILE returns 0, the reason will be here + + int bytes_done; //you can look at both of these values for speed statistics + int bytes_total; + int bytes_out; + + int killswitch; // don't set it manually, use IPC_CONVERTFILE_END + intptr_t extra_data[64]; // for internal winamp use +} convertFileStructW; + + +#define IPC_CONVERTFILE_END 507 +/* (requires Winamp 2.92+) +** Stop/ends a convert process started from IPC_CONVERTFILE +** You need to call this when you receive the IPC_CB_CONVERTDONE message or when you +** want to abort a conversion process +** +** eg: SendMessage(hwnd_winamp,WM_WA_IPC,&myConvertStruct,IPC_CONVERTFILE_END); +** +** No return value +*/ + + +#define IPC_CONVERTFILEW_END 516 +// (requires Winamp 5.36+) + +typedef struct { + HWND hwndParent; + int format; + + //filled in by winamp.exe + HWND hwndConfig; + int extra_data[8]; + //hack alert! you can set extra_data[6]=mmioFOURCC('I','N','I',' '); and extra_data[7]=(int)my_ini_file; (where my_ini_file is a char*) +} convertConfigStruct; + + +#define IPC_CONVERT_CONFIG 508 +#define IPC_CONVERT_CONFIG_END 509 + +typedef struct +{ + void (*enumProc)(intptr_t user_data, const char *desc, int fourcc); + intptr_t user_data; +} converterEnumFmtStruct; +#define IPC_CONVERT_CONFIG_ENUMFMTS 510 +/* (requires Winamp 2.92+) +*/ + +typedef struct +{ + char cdletter; + char *playlist_file; + HWND callback_hwnd; + + //filled in by winamp.exe + char *error; +} burnCDStruct; +#define IPC_BURN_CD 511 +/* (requires Winamp 5.0+) +*/ + +typedef struct +{ + convertFileStruct *cfs; + int priority; +} convertSetPriority; + + +#define IPC_CONVERT_SET_PRIORITY 512 + +typedef struct +{ + convertFileStructW *cfs; + int priority; +} convertSetPriorityW; + + +#define IPC_CONVERT_SET_PRIORITYW 517 +// (requires Winamp 5.36+) + +typedef struct +{ + unsigned int format; //fourcc value + char *item; // config item, eg "bitrate" + char *data; // buffer to recieve, or buffer that contains the data + int len; // length of the data buffer (only used when getting a config item) + char *configfile; // config file to read from +} convertConfigItem; + + +#define IPC_CONVERT_CONFIG_SET_ITEM 513 // returns TRUE if successful +#define IPC_CONVERT_CONFIG_GET_ITEM 514 // returns TRUE if successful + + +typedef struct +{ + const char *filename; + char *title; // 2048 bytes + int length; + int force_useformatting; // can set this to 1 if you want to force a url to use title formatting shit +} waHookTitleStruct; + +#define IPC_HOOK_TITLES 850 +/* (requires Winamp 5.0+) +** If you hook this message and modify the information then make sure to return TRUE. +** If you don't hook the message then make sure you pass it on through the subclass chain. +** +** LRESULT CALLBACK WinampWndProc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) +** { +** LRESULT ret = CallWindowProc((WNDPROC)WinampProc,hwnd,umsg,wParam,lParam); +** +** if(message==WM_WA_IPC && lParam==IPC_HOOK_TITLES) +** { +** waHookTitleStruct *ht = (waHookTitleStruct *) wParam; +** // Doing ATF stuff with ht->title, whatever... +** return TRUE; +** } +** return ret; +** } +*/ + +typedef struct +{ + const wchar_t *filename; + wchar_t *title; // 2048 characters + int length; + int force_useformatting; // can set this to 1 if you want to force a url to use title formatting shit +} waHookTitleStructW; +#define IPC_HOOK_TITLESW 851 +/* (requires Winamp 5.3+) +** See information on IPC_HOOK_TITLES for how to process this. +*/ + + +#define IPC_GETSADATAFUNC 800 +// 0: returns a char *export_sa_get() that returns 150 bytes of data +// 1: returns a export_sa_setreq(int want); + + +#define IPC_GETVUDATAFUNC 801 +// 0: returns a int export_vu_get(int channel) that returns 0-255 (or -1 for bad channel) + + +#define IPC_ISMAINWNDVISIBLE 900 +/* (requires Winamp 5.0+) +** int visible=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISMAINWNDVISIBLE); +** You send this to Winamp to query if the main window is visible or not such as by +** unchecking the option in the main right-click menu. If the main window is visible then +** this will return 1 otherwise it returns 0. +*/ + + +typedef struct +{ + int numElems; + int *elems; + HBITMAP bm; // set if you want to override +} waSetPlColorsStruct; + +#define IPC_SETPLEDITCOLORS 920 +/* (requires Winamp 5.0+) +** This is sent by gen_ff when a modern skin is being loaded to set the colour scheme for +** the playlist editor. When sent numElems is usually 6 and matches with the 6 possible +** colours which are provided be pledit.txt from the classic skins. The elems array is +** defined as follows: +** +** elems = 0 => normal text +** elems = 1 => current text +** elems = 2 => normal background +** elems = 3 => selected background +** elems = 4 => minibroswer foreground +** elems = 5 => minibroswer background +** +** if(uMsg == WM_WA_IPC && lParam == IPC_SETPLEDITCOLORS) +** { +** waSetPlColorsStruct* colStr = (waSetPlColorsStruct*)wp; +** if(colStr) +** { +** // set or inspect the colours being used (basically for gen_ff's benefit) +** } +** } +*/ + + +typedef struct +{ + HWND wnd; + int xpos; // in screen coordinates + int ypos; +} waSpawnMenuParms; + +// waSpawnMenuParms2 is used by the menubar submenus +typedef struct +{ + HWND wnd; + int xpos; // in screen coordinates + int ypos; + int width; + int height; +} waSpawnMenuParms2; + +// the following IPC use waSpawnMenuParms as parameter +#define IPC_SPAWNEQPRESETMENU 933 +#define IPC_SPAWNFILEMENU 934 //menubar +#define IPC_SPAWNOPTIONSMENU 935 //menubar +#define IPC_SPAWNWINDOWSMENU 936 //menubar +#define IPC_SPAWNHELPMENU 937 //menubar +#define IPC_SPAWNPLAYMENU 938 //menubar +#define IPC_SPAWNPEFILEMENU 939 //menubar +#define IPC_SPAWNPEPLAYLISTMENU 940 //menubar +#define IPC_SPAWNPESORTMENU 941 //menubar +#define IPC_SPAWNPEHELPMENU 942 //menubar +#define IPC_SPAWNMLFILEMENU 943 //menubar +#define IPC_SPAWNMLVIEWMENU 944 //menubar +#define IPC_SPAWNMLHELPMENU 945 //menubar +#define IPC_SPAWNPELISTOFPLAYLISTS 946 + + +#define WM_WA_SYSTRAY WM_USER+1 +/* This is sent by the system tray when an event happens (you might want to simulate it). +** +** if(uMsg == WM_WA_SYSTRAY) +** { +** switch(lParam) +** { +** // process the messages sent from the tray +** } +** } +*/ + + +#define WM_WA_MPEG_EOF WM_USER+2 +/* Input plugins send this when they are done playing back the current file to inform +** Winamp or anyother installed plugins that the current +** +** if(uMsg == WM_WA_MPEG_EOF) +** { +** // do what is needed here +** } +*/ + + +//// video stuff + +#define IPC_IS_PLAYING_VIDEO 501 // returns >1 if playing, 0 if not, 1 if old version (so who knows):) +#define IPC_GET_IVIDEOOUTPUT 500 // see below for IVideoOutput interface +#define VIDEO_MAKETYPE(A,B,C,D) ((A) | ((B)<<8) | ((C)<<16) | ((D)<<24)) +#define VIDUSER_SET_INFOSTRING 0x1000 +#define VIDUSER_GET_VIDEOHWND 0x1001 +#define VIDUSER_SET_VFLIP 0x1002 +#define VIDUSER_SET_TRACKSELINTERFACE 0x1003 // give your ITrackSelector interface as param2 +#define VIDUSER_OPENVIDEORENDERER 0x1004 +#define VIDUSER_CLOSEVIDEORENDERER 0x1005 +#define VIDUSER_GETPOPUPMENU 0x1006 +#define VIDUSER_SET_INFOSTRINGW 0x1007 + +typedef struct +{ + int w; + int h; + int vflip; + double aspectratio; + unsigned int fmt; +} VideoOpenStruct; + +#ifndef NO_IVIDEO_DECLARE +#ifdef __cplusplus + +class VideoOutput; +class SubsItem; + +#ifndef _NSV_DEC_IF_H_ +struct YV12_PLANE { + unsigned char* baseAddr; + long rowBytes; +} ; + +struct YV12_PLANES { + YV12_PLANE y; + YV12_PLANE u; + YV12_PLANE v; +}; +#endif + +class IVideoOutput +{ + public: + virtual ~IVideoOutput() { } + virtual int open(int w, int h, int vflip, double aspectratio, unsigned int fmt)=0; + virtual void setcallback(LRESULT (*msgcallback)(void *token, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam), void *token) { (void)token; (void)msgcallback; /* to eliminate warning C4100 */ } + virtual void close()=0; + virtual void draw(void *frame)=0; + virtual void drawSubtitle(SubsItem *item) {UNREFERENCED_PARAMETER(item); } + virtual void showStatusMsg(const char *text) {UNREFERENCED_PARAMETER(text); } + virtual int get_latency() { return 0; } + virtual void notifyBufferState(int bufferstate) { UNREFERENCED_PARAMETER(bufferstate); } /* 0-255*/ + virtual INT_PTR extended(INT_PTR param1, INT_PTR param2, INT_PTR param3) { UNREFERENCED_PARAMETER(param1); UNREFERENCED_PARAMETER(param2); UNREFERENCED_PARAMETER(param3); return 0; } // Dispatchable, eat this! +}; + +class ITrackSelector +{ + public: + virtual int getNumAudioTracks()=0; + virtual void enumAudioTrackName(int n, const char *buf, int size)=0; + virtual int getCurAudioTrack()=0; + virtual int getNumVideoTracks()=0; + virtual void enumVideoTrackName(int n, const char *buf, int size)=0; + virtual int getCurVideoTrack()=0; + + virtual void setAudioTrack(int n)=0; + virtual void setVideoTrack(int n)=0; +}; + +#endif //cplusplus +#endif//NO_IVIDEO_DECLARE + +// these messages are callbacks that you can grab by subclassing the winamp window + +// wParam = +#define IPC_CB_WND_EQ 0 // use one of these for the param +#define IPC_CB_WND_PE 1 +#define IPC_CB_WND_MB 2 +#define IPC_CB_WND_VIDEO 3 +#define IPC_CB_WND_MAIN 4 + +#define IPC_CB_ONSHOWWND 600 +#define IPC_CB_ONHIDEWND 601 + +#define IPC_CB_GETTOOLTIP 602 + +#define IPC_CB_MISC 603 + #define IPC_CB_MISC_TITLE 0 // start of playing/stop/pause + #define IPC_CB_MISC_VOLUME 1 // volume/pan + #define IPC_CB_MISC_STATUS 2 // start playing/stop/pause/ffwd/rwd + #define IPC_CB_MISC_EQ 3 + #define IPC_CB_MISC_INFO 4 + #define IPC_CB_MISC_VIDEOINFO 5 + #define IPC_CB_MISC_TITLE_RATING 6 // (5.5+ for when the rating is changed via the songticker menu on current file) + +/* Example of using IPC_CB_MISC_STATUS to detect the start of track playback with 5.x +** +** if(lParam == IPC_CB_MISC && wParam == IPC_CB_MISC_STATUS) +** { +** if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISPLAYING) == 1 && +** !SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETOUTPUTTIME)) +** { +** char* file = (char*)SendMessage(hwnd_winamp,WM_WA_IPC, +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS),IPC_GETPLAYLISTFILE); +** // only output if a valid file was found +** if(file) +** { +** MessageBox(hwnd_winamp,file,"starting",0); +** // or do something else that you need to do +** } +** } +** } +*/ + + +#define IPC_CB_CONVERT_STATUS 604 // param value goes from 0 to 100 (percent) +#define IPC_CB_CONVERT_DONE 605 + + +#define IPC_ADJUST_FFWINDOWSMENUPOS 606 +/* (requires Winamp 2.9+) +** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_FFWINDOWSMENUPOS); +** This will move where Winamp expects the freeform windows in the menubar windows main +** menu. This is useful if you wish to insert a menu item above extra freeform windows. +*/ + + +#define IPC_ISDOUBLESIZE 608 +/* (requires Winamp 5.0+) +** int dsize=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISDOUBLESIZE); +** You send this to Winamp to query if the double size mode is enabled or not. +** If it is on then this will return 1 otherwise it will return 0. +*/ + + +#define IPC_ADJUST_FFOPTIONSMENUPOS 609 +/* (requires Winamp 2.9+) +** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_FFOPTIONSMENUPOS); +** moves where winamp expects the freeform preferences item in the menubar windows main +** menu. This is useful if you wish to insert a menu item above the preferences item. +** +** Note: This setting was ignored by gen_ff until it was fixed in 5.1 +** gen_ff would assume thatthe menu position was 11 in all cases and so when you +** had two plugins attempting to add entries into the main right click menu it +** would cause the 'colour themes' submenu to either be incorrectly duplicated or +** to just disappear.instead. +*/ + + +#define IPC_GETTIMEDISPLAYMODE 610 +/* (requires Winamp 5.0+) +** int mode=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETTIMEDISPLAYMODE); +** This will return the status of the time display i.e. shows time elapsed or remaining. +** This returns 0 if Winamp is displaying time elapsed or 1 for the time remaining. +*/ + + +#define IPC_SETVISWND 611 +/* (requires Winamp 5.0+) +** int viswnd=(HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)viswnd,IPC_SETVISWND); +** This allows you to set a window to receive the following message commands (which are +** used as part of the modern skin integration). +** When you have finished or your visualisation is closed then send wParam as zero to +** ensure that things are correctly tidied up. +*/ + +/* The following messages are received as the LOWORD(wParam) of the WM_COMMAND message. +** See %SDK%\winamp\wa5vis.txt for more info about visualisation integration in Winamp. +*/ +#define ID_VIS_NEXT 40382 +#define ID_VIS_PREV 40383 +#define ID_VIS_RANDOM 40384 +#define ID_VIS_FS 40389 +#define ID_VIS_CFG 40390 +#define ID_VIS_MENU 40391 + + +#define IPC_GETVISWND 612 +/* (requires Winamp 5.0+) +** int viswnd=(HWND)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVISWND); +** This returns a HWND to the visualisation command handler window if set by IPC_SETVISWND. +*/ + + +#define IPC_ISVISRUNNING 613 +/* (requires Winamp 5.0+) +** int visrunning=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISVISRUNNING); +** This will return 1 if a visualisation is currently running and 0 if one is not running. +*/ + + +#define IPC_CB_VISRANDOM 628 // param is status of random + + +#define IPC_SETIDEALVIDEOSIZE 614 +/* (requires Winamp 5.0+) +** This is sent by Winamp back to itself so it can be trapped and adjusted as needed with +** the desired width in HIWORD(wParam) and the desired height in LOWORD(wParam). +** +** if(uMsg == WM_WA_IPC){ +** if(lParam == IPC_SETIDEALVIDEOSIZE){ +** wParam = MAKEWPARAM(height,width); +** } +** } +*/ + + +#define IPC_GETSTOPONVIDEOCLOSE 615 +/* (requires Winamp 5.0+) +** int sovc=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETSTOPONVIDEOCLOSE); +** This will return 1 if 'stop on video close' is enabled and 0 if it is disabled. +*/ + + +#define IPC_SETSTOPONVIDEOCLOSE 616 +/* (requires Winamp 5.0+) +** int sovc=SendMessage(hwnd_winamp,WM_WA_IPC,enabled,IPC_SETSTOPONVIDEOCLOSE); +** Set enabled to 1 to enable and 0 to disable the 'stop on video close' option. +*/ + + +typedef struct { + HWND hwnd; + int uMsg; + WPARAM wParam; + LPARAM lParam; +} transAccelStruct; + +#define IPC_TRANSLATEACCELERATOR 617 +/* (requires Winamp 5.0+) +** (deprecated as of 5.53x+) +*/ + +typedef struct { + int cmd; + int x; + int y; + int align; +} windowCommand; // send this as param to an IPC_PLCMD, IPC_MBCMD, IPC_VIDCMD + + +#define IPC_CB_ONTOGGLEAOT 618 + + +#define IPC_GETPREFSWND 619 +/* (requires Winamp 5.0+) +** HWND prefs = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETPREFSWND); +** This will return a handle to the preferences dialog if it is open otherwise it will +** return zero. A simple check with the OS api IsWindow(..) is a good test if it's valid. +** +** e.g. this will open (or close if already open) the preferences dialog and show if we +** managed to get a valid +** SendMessage(hwnd_winamp,WM_COMMAND,MAKEWPARAM(WINAMP_OPTIONS_PREFS,0),0); +** MessageBox(hwnd_winamp,(IsWindow((HWND)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETPREFSWND))?"Valid":"Not Open"),0,MB_OK); +*/ + + +#define IPC_SET_PE_WIDTHHEIGHT 620 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&point,IPC_SET_PE_WIDTHHEIGHT); +** You pass a pointer to a POINT structure which holds the width and height and Winamp +** will set the playlist editor to that size (this is used by gen_ff on skin changes). +** There does not appear to be any bounds limiting with this so it is possible to create +** a zero size playlist editor window (which is a pretty silly thing to do). +*/ + + +#define IPC_GETLANGUAGEPACKINSTANCE 621 +/* (requires Winamp 5.0+) +** HINSTANCE hInst = (HINSTANCE)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLANGUAGEPACKINSTANCE); +** This will return the HINSTANCE to the currently used language pack file for winamp.exe +** +** (5.5+) +** If you pass 1 in wParam then you will have zero returned if a language pack is in use. +** if(!SendMessage(hwnd_winamp,WM_WA_IPC,1,IPC_GETLANGUAGEPACKINSTANCE)){ +** // winamp is currently using a language pack +** } +** +** If you pass 2 in wParam then you will get the path to the language pack folder. +** wchar_t* lngpackfolder = (wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,2,IPC_GETLANGUAGEPACKINSTANCE); +** +** If you pass 3 in wParam then you will get the path to the currently extracted language pack. +** wchar_t* lngpack = (wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,3,IPC_GETLANGUAGEPACKINSTANCE); +** +** If you pass 4 in wParam then you will get the name of the currently used language pack. +** wchar_t* lngname = (char*)SendMessage(hwnd_winamp,WM_WA_IPC,4,IPC_GETLANGUAGEPACKINSTANCE); +*/ +#define LANG_IDENT_STR 0 +#define LANG_LANG_CODE 1 +#define LANG_COUNTRY_CODE 2 +/* +** (5.51+) +** If you pass 5 in LOWORD(wParam) then you will get the ident string/code string +** (based on the param passed in the HIWORD(wParam) of the currently used language pack. +** The string returned with LANG_IDENT_STR is used to represent the language that the +** language pack is intended for following ISO naming conventions for consistancy. +** +** wchar_t* ident_str = (wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,MAKEWPARAM(5,LANG_XXX),IPC_GETLANGUAGEPACKINSTANCE); +** +** e.g. +** For the default language it will return the following for the different LANG_XXX codes +** LANG_IDENT_STR -> "en-US" (max buffer size of this is 9 wchar_t) +** LANG_LANG_CODE -> "en" (language code) +** LANG_COUNTRY_CODE -> "US" (country code) +** +** On pre 5.51 installs you can get LANG_IDENT_STR using the following method +** (you'll have to custom process the string returned if you want the langugage or country but that's easy ;) ) +** +** #define LANG_PACK_LANG_ID 65534 (if you don't have lang.h) +** HINSTANCE hInst = (HINSTANCE)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLANGUAGEPACKINSTANCE); +** TCHAR buffer[9] = {0}; +** LoadString(hInst,LANG_PACK_LANG_ID,buffer,sizeof(buffer)); +** +** +** +** The following example shows how using the basic api will allow you to load the playlist +** context menu resource from the currently loaded language pack or it will fallback to +** the default winamp.exe instance. +** +** HINSTANCE lang = (HINSTANCE)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLANGUAGEPACKINSTANCE); +** HMENU popup = GetSubMenu(GetSubMenu((LoadMenu(lang?lang:GetModuleHandle(0),MAKEINTRESOURCE(101))),2),5); +** // do processing as needed on the menu before displaying it +** TrackPopupMenuEx(orig,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON,rc.left,rc.bottom,hwnd_owner,0); +** DestroyMenu(popup); +** +** If you need a specific menu handle then look at IPC_GET_HMENU for more information. +*/ + + +#define IPC_CB_PEINFOTEXT 622 // data is a string, ie: "04:21/45:02" + + +#define IPC_CB_OUTPUTCHANGED 623 // output plugin was changed in config + + +#define IPC_GETOUTPUTPLUGIN 625 +/* (requires Winamp 5.0+) +** char* outdll = (char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETOUTPUTPLUGIN); +** This returns a string of the current output plugin's dll name. +** e.g. if the directsound plugin was selected then this would return 'out_ds.dll'. +*/ + + +#define IPC_SETDRAWBORDERS 626 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,enabled,IPC_SETDRAWBORDERS); +** Set enabled to 1 to enable and 0 to disable drawing of the playlist editor and winamp +** gen class windows (used by gen_ff to allow it to draw its own window borders). +*/ + + +#define IPC_DISABLESKINCURSORS 627 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,enabled,IPC_DISABLESKINCURSORS); +** Set enabled to 1 to enable and 0 to disable the use of skinned cursors. +*/ + + +#define IPC_GETSKINCURSORS 628 +/* (requires Winamp 5.36+) +** data = (WACURSOR)cursorId. (check wa_dlg.h for values) +*/ + + +#define IPC_CB_RESETFONT 629 + + +#define IPC_IS_FULLSCREEN 630 +/* (requires Winamp 5.0+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_FULLSCREEN); +** This will return 1 if the video or visualisation is in fullscreen mode or 0 otherwise. +*/ + + +#define IPC_SET_VIS_FS_FLAG 631 +/* (requires Winamp 5.0+) +** A vis should send this message with 1/as param to notify winamp that it has gone to or has come back from fullscreen mode +*/ + + +#define IPC_SHOW_NOTIFICATION 632 + + +#define IPC_GETSKININFO 633 +#define IPC_GETSKININFOW 1633 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window by itself whenever it +** needs to get information to be shown about the current skin in the 'Current skin +** information' box on the main Skins page in the Winamp preferences. +** +** When this notification is received and the current skin is one you are providing the +** support for then you return a valid buffer for Winamp to be able to read from with +** information about it such as the name of the skin file. +** +** if(uMsg == WM_WA_IPC && lParam == IPC_GETSKININFO){ +** if(is_our_skin()){ +** return is_our_skin_name(); +** } +** } +*/ + + +#define IPC_GET_MANUALPLADVANCE 634 +/* (requires Winamp 5.03+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_MANUALPLADVANCE); +** IPC_GET_MANUALPLADVANCE returns the status of the Manual Playlist Advance. +** If enabled this will return 1 otherwise it will return 0. +*/ + + +#define IPC_SET_MANUALPLADVANCE 635 +/* (requires Winamp 5.03+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_MANUALPLADVANCE); +** IPC_SET_MANUALPLADVANCE sets the status of the Manual Playlist Advance option. +** Set value = 1 to turn it on and value = 0 to turn it off. +*/ + + +#define IPC_GET_NEXT_PLITEM 636 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_EOF_GET_NEXT_PLITEM); +** +** Sent to Winamp's main window when an item has just finished playback or the next +** button has been pressed and requesting the new playlist item number to go to. +** +** Subclass this message in your application to return the new item number. +** Return -1 for normal Winamp operation (default) or the new item number in +** the playlist to be played instead of the originally selected next track. +** +** This is primarily provided for the JTFE plugin (gen_jumpex.dll). +*/ + + +#define IPC_GET_PREVIOUS_PLITEM 637 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_EOF_GET_PREVIOUS_PLITEM); +** +** Sent to Winamp's main window when the previous button has been pressed and Winamp is +** requesting the new playlist item number to go to. +** +** Return -1 for normal Winamp operation (default) or the new item number in +** the playlist to be played instead of the originally selected previous track. +** +** This is primarily provided for the JTFE plugin (gen_jumpex.dll). +*/ + + +#define IPC_IS_WNDSHADE 638 +/* (requires Winamp 5.04+) +** int is_shaded=SendMessage(hwnd_winamp,WM_WA_IPC,wnd,IPC_IS_WNDSHADE); +** Pass 'wnd' as an id as defined for IPC_GETWND or pass -1 to query the status of the +** main window. This returns 1 if the window is in winshade mode and 0 if it is not. +** Make sure you only test for this on a 5.04+ install otherwise you get a false result. +** (See the notes about unhandled WM_WA_IPC messages). +*/ + + +#define IPC_SETRATING 639 +/* (requires Winamp 5.04+ with ML) +** int rating=SendMessage(hwnd_winamp,WM_WA_IPC,rating,IPC_SETRATING); +** This will allow you to set the 'rating' on the current playlist entry where 'rating' +** is an integer value from 0 (no rating) to 5 (5 stars). +** +** The following example should correctly allow you to set the rating for any specified +** playlist entry assuming of course that you're trying to get a valid playlist entry. +** +** void SetPlaylistItemRating(int item_to_set, int rating_to_set){ +** int cur_pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS); +** SendMessage(hwnd_winamp,WM_WA_IPC,item_to_set,IPC_SETPLAYLISTPOS); +** SendMessage(hwnd_winamp,WM_WA_IPC,rating_to_set,IPC_SETRATING); +** SendMessage(hwnd_winamp,WM_WA_IPC,cur_pos,IPC_SETPLAYLISTPOS); +** } +*/ + + +#define IPC_GETRATING 640 +/* (requires Winamp 5.04+ with ML) +** int rating=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETRATING); +** This returns the current playlist entry's rating between 0 (no rating) to 5 (5 stars). +** +** The following example should correctly allow you to get the rating for any specified +** playlist entry assuming of course that you're trying to get a valid playlist entry. +** +** int GetPlaylistItemRating(int item_to_get, int rating_to_set){ +** int cur_pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS), rating = 0; +** SendMessage(hwnd_winamp,WM_WA_IPC,item_to_get,IPC_SETPLAYLISTPOS); +** rating = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETRATING); +** SendMessage(hwnd_winamp,WM_WA_IPC,cur_pos,IPC_SETPLAYLISTPOS); +** return rating; +** } +*/ + + +#define IPC_GETNUMAUDIOTRACKS 641 +/* (requires Winamp 5.04+) +** int n = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETNUMAUDIOTRACKS); +** This will return the number of audio tracks available from the currently playing item. +*/ + + +#define IPC_GETNUMVIDEOTRACKS 642 +/* (requires Winamp 5.04+) +** int n = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETNUMVIDEOTRACKS); +** This will return the number of video tracks available from the currently playing item. +*/ + + +#define IPC_GETAUDIOTRACK 643 +/* (requires Winamp 5.04+) +** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETAUDIOTRACK); +** This will return the id of the current audio track for the currently playing item. +*/ + + +#define IPC_GETVIDEOTRACK 644 +/* (requires Winamp 5.04+) +** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVIDEOTRACK); +** This will return the id of the current video track for the currently playing item. +*/ + + +#define IPC_SETAUDIOTRACK 645 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,track,IPC_SETAUDIOTRACK); +** This allows you to switch to a new audio track (if supported) in the current playing file. +*/ + + +#define IPC_SETVIDEOTRACK 646 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,track,IPC_SETVIDEOTRACK); +** This allows you to switch to a new video track (if supported) in the current playing file. +*/ + + +#define IPC_PUSH_DISABLE_EXIT 647 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_PUSH_DISABLE_EXIT); +** This will let you disable or re-enable the UI exit functions (close button, context +** menu, alt-f4). Remember to call IPC_POP_DISABLE_EXIT when you are done doing whatever +** was required that needed to prevent exit otherwise you have to kill the Winamp process. +*/ + + +#define IPC_POP_DISABLE_EXIT 648 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_POP_DISABLE_EXIT); +** See IPC_PUSH_DISABLE_EXIT +*/ + + +#define IPC_IS_EXIT_ENABLED 649 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_EXIT_ENABLED); +** This will return 0 if the 'exit' option of Winamp's menu is disabled and 1 otherwise. +*/ + + +#define IPC_IS_AOT 650 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_AOT); +** This will return the status of the always on top flag. +** Note: This may not match the actual TOPMOST window flag while another fullscreen +** application is focused if the user has the 'Disable always on top while fullscreen +** applications are focused' option under the General Preferences page is checked. +*/ + + +#define IPC_USES_RECYCLEBIN 651 +/* (requires Winamp 5.09+) +** int use_bin=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USES_RECYCLEBIN); +** This will return 1 if the deleted file should be sent to the recycle bin or +** 0 if deleted files should be deleted permanently (default action for < 5.09). +** +** Note: if you use this on pre 5.09 installs of Winamp then it will return 1 which is +** not correct but is due to the way that SendMessage(..) handles un-processed messages. +** Below is a quick case for checking if the returned value is correct. +** +** if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USES_RECYCLEBIN) && +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION)>=0x5009) +** { +** // can safely follow the option to recycle the file +** } +** else +* { +** // need to do a permanent delete of the file +** } +*/ + + +#define IPC_FLUSHAUDITS 652 +/* +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_FLUSHAUDITS); +** +** Will flush any pending audits in the global audits queue +** +*/ + +#define IPC_GETPLAYITEM_START 653 +#define IPC_GETPLAYITEM_END 654 + + +#define IPC_GETVIDEORESIZE 655 +#define IPC_SETVIDEORESIZE 656 + + +#define IPC_INITIAL_SHOW_STATE 657 +/* (requires Winamp 5.36+) +** int show_state = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_INITIAL_SHOW_STATE); +** returns the processed value of nCmdShow when Winamp was started +** (see MSDN documentation the values passed to WinMain(..) for what this should be) +** +** e.g. +** if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_INITIAL_SHOW_STATE) == SW_SHOWMINIMIZED){ +** // we are starting minimised so process as needed (keep our window hidden) +** } +** +** Useful for seeing if winamp was run minimised on startup so you can act accordingly. +** On pre-5.36 versions this will effectively return SW_NORMAL/SW_SHOWNORMAL due to the +** handling of unknown apis returning 1 from Winamp. +*/ + +// >>>>>>>>>>> Next is 658 + +#define IPC_PLCMD 1000 + +#define PLCMD_ADD 0 +#define PLCMD_REM 1 +#define PLCMD_SEL 2 +#define PLCMD_MISC 3 +#define PLCMD_LIST 4 + +//#define IPC_MBCMD 1001 + +#define MBCMD_BACK 0 +#define MBCMD_FORWARD 1 +#define MBCMD_STOP 2 +#define MBCMD_RELOAD 3 +#define MBCMD_MISC 4 + +#define IPC_VIDCMD 1002 + +#define VIDCMD_FULLSCREEN 0 +#define VIDCMD_1X 1 +#define VIDCMD_2X 2 +#define VIDCMD_LIB 3 +#define VIDPOPUP_MISC 4 + +//#define IPC_MBURL 1003 //sets the URL +//#define IPC_MBGETCURURL 1004 //copies the current URL into wParam (have a 4096 buffer ready) +//#define IPC_MBGETDESC 1005 //copies the current URL description into wParam (have a 4096 buffer ready) +//#define IPC_MBCHECKLOCFILE 1006 //checks that the link file is up to date (otherwise updates it). wParam=parent HWND +//#define IPC_MBREFRESH 1007 //refreshes the "now playing" view in the library +//#define IPC_MBGETDEFURL 1008 //copies the default URL into wParam (have a 4096 buffer ready) + +#define IPC_STATS_LIBRARY_ITEMCNT 1300 // updates library count status + +/* +** IPC's in the message range 2000 - 3000 are reserved internally for freeform messages. +** These messages are taken from ff_ipc.h which is part of the Modern skin integration. +*/ + +#define IPC_FF_FIRST 2000 + +#define IPC_FF_COLOURTHEME_CHANGE IPC_FF_ONCOLORTHEMECHANGED +#define IPC_FF_ONCOLORTHEMECHANGED IPC_FF_FIRST + 3 +/* +** This is a notification message sent when the user changes the colour theme in a Modern +** skin and can also be detected when the Modern skin is first loaded as the gen_ff plugin +** applies relevant settings and styles (like the colour theme). +** +** The value of wParam is the name of the new color theme being switched to. +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(const char*)colour_theme_name,IPC_FF_ONCOLORTHEMECHANGED); +** +** (IPC_FF_COLOURTHEME_CHANGE is the name i (DrO) was using before getting a copy of +** ff_ipc.h with the proper name in it). +*/ + + +#define IPC_FF_ISMAINWND IPC_FF_FIRST + 4 +/* +** int ismainwnd = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)test_wnd,IPC_FF_ISMAINWND); +** +** This allows you to determine if the window handle passed to it is a modern skin main +** window or not. If it is a main window or any of its windowshade variants then it will +** return 1. +** +** Because of the way modern skins are implemented, it is possible for this message to +** return a positive test result for a number of window handles within the current Winamp +** process. This appears to be because you can have a visible main window, a compact main +** window and also a winshaded version. +** +** The following code example below is one way of seeing how this api works since it will +** enumerate all windows related to Winamp at the time and allows you to process as +** required when a detection happens. +** +** +** EnumThreadWindows(GetCurrentThreadId(),enumWndProc,0); +** +** BOOL CALLBACK enumWndProc(HWND hwnd, LPARAM lParam){ +** +** if(SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)hwnd,IPC_FF_ISMAINWND)){ +** // do processing in here +** // or continue the enum for other main windows (if they exist) +** // and just comment out the line below +** return 0; +** } +** return 1; +** } +*/ + + +#define IPC_FF_GETCONTENTWND IPC_FF_FIRST + 5 +/* +** HWND wa2embed = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)test_wnd,IPC_FF_GETCONTENTWND); +** +** This will return the Winamp 2 window that is embedded in the window's container +** i.e. if hwnd is the playlist editor windowshade hwnd then it will return the Winamp 2 +** playlist editor hwnd. +** +** If no content is found such as the window has nothing embedded then this will return +** the hwnd passed to it. +*/ + + +#define IPC_FF_NOTIFYHOTKEY IPC_FF_FIRST + 6 +/* +** This is a notification message sent when the user uses a global hotkey combination +** which had been registered with the gen_hotkeys plugin. +** +** The value of wParam is the description of the hotkey as passed to gen_hotkeys. +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(const char*)hotkey_desc,IPC_FF_NOTIFYHOTKEY); +*/ + +#define IPC_FF_LAST 3000 + + +/* +** General IPC messages in Winamp +** +** All notification messages appear in the lParam of the main window message proceedure. +*/ + + +#define IPC_GETDROPTARGET 3001 +/* (requires Winamp 5.0+) +** IDropTarget* IDrop = (IDropTarget*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETDROPTARGET); +** +** You call this to retrieve a copy of the IDropTarget interface which Winamp created for +** handling external drag and drop operations on to it's Windows. This is only really +** useful if you're providing an alternate interface and want your Windows to provide the +** same drag and drop support as Winamp normally provides the user. Check out MSDN or +** your prefered search facility for more information about the IDropTarget interface and +** what's needed to handle it in your own instance. +*/ + + +#define IPC_PLAYLIST_MODIFIED 3002 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window whenever the playlist is +** modified in any way e.g. the addition/removal of a playlist entry. +** +** It is not a good idea to do large amounts of processing in this notification since it +** will slow down Winamp as playlist entries are modified (especially when you're adding +** in a large playlist). +** +** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYLIST_MODIFIED) +** { +** // do what you need to do here +** } +*/ + + +#define IPC_PLAYING_FILE 3003 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window when playback begins for +** a file. This passes the full filepath in the wParam of the message received. +** +** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYING_FILE) +** { +** // do what you need to do here, e.g. +** process_file((char*)wParam); +** } +*/ + + +#define IPC_PLAYING_FILEW 13003 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window when playback begins for +** a file. This passes the full filepath in the wParam of the message received. +** +** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYING_FILEW) +** { +** // do what you need to do here, e.g. +** process_file((wchar_t*)wParam); +** } +*/ + + +#define IPC_FILE_TAG_MAY_HAVE_UPDATED 3004 +#define IPC_FILE_TAG_MAY_HAVE_UPDATEDW 3005 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window when a file's tag +** (e.g. id3) may have been updated. This appears to be sent when the InfoBox(..) function +** of the associated input plugin returns a 1 (which is the file information dialog/editor +** call normally). +** +** if(uMsg == WM_WA_IPC && lParam == IPC_FILE_TAG_MAY_HAVE_UPDATED) +** { +** // do what you need to do here, e.g. +** update_info_on_file_update((char*)wParam); +** } +*/ + + +#define IPC_ALLOW_PLAYTRACKING 3007 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,allow,IPC_ALLOW_PLAYTRACKING); +** Send allow as nonzero to allow play tracking and zero to disable the mode. +*/ + + +#define IPC_HOOK_OKTOQUIT 3010 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window asking if it's okay to +** close or not. Return zero to prevent Winamp from closing or return anything non-zero +** to allow Winamp to close. +** +** The best implementation of this option is to let the message pass through to the +** original window proceedure since another plugin may want to have a say in the matter +** with regards to Winamp closing. +** +** if(uMsg == WM_WA_IPC && lParam == IPC_HOOK_OKTOQUIT) +** { +** // do what you need to do here, e.g. +** if(no_shut_down()) +** { +** return 1; +** } +** } +*/ + + +#define IPC_WRITECONFIG 3011 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,write_type,IPC_WRITECONFIG); +** +** Send write_type as 2 to write all config settings and the current playlist. +** +** Send write_type as 1 to write the playlist and common settings. +** This won't save the following ini settings:: +** +** defext, titlefmt, proxy, visplugin_name, dspplugin_name, check_ft_startup, +** visplugin_num, pe_fontsize, visplugin_priority, visplugin_autoexec, dspplugin_num, +** sticon, splash, taskbar, dropaotfs, ascb_new, ttips, riol, minst, whichicon, +** whichicon2, addtolist, snap, snaplen, parent, hilite, disvis, rofiob, shownumsinpl, +** keeponscreen, eqdsize, usecursors, fixtitles, priority, shuffle_morph_rate, +** useexttitles, bifont, inet_mode, ospb, embedwnd_freesize, no_visseh +** (the above was valid for 5.1) +** +** Send write_type as 0 to write the common and less common settings and no playlist. +*/ + + +#define IPC_UPDATE_URL 3012 +// pass the URL (char *) in lparam, will be free()'d on done. + + +#define IPC_GET_RANDFUNC 3015 // returns a function to get a random number +/* (requires Winamp 5.1+) +** int (*randfunc)(void) = (int(*)(void))SendMessage(plugin.hwndParent,WM_WA_IPC,0,IPC_GET_RANDFUNC); +** if(randfunc && randfunc != 1){ +** randfunc(); +** } +** +** This will return a positive 32-bit number (essentially 31-bit). +** The check for a returned value of 1 is because that's the default return value from +** SendMessage(..) when it is not handled so is good to check for it in this situation. +*/ + + +#define IPC_METADATA_CHANGED 3017 +/* (requires Winamp 5.1+) +** int changed=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(char*)field,IPC_METADATA_CHANGED); +** a plugin can SendMessage this to winamp if internal metadata has changes. +** wParam should be a char * of what field changed +** +** Currently used for internal actions (and very few at that) the intent of this api is +** to allow a plugin to call it when metadata has changed in the current playlist entry +** e.g.a new id3v2 tag was found in a stream +** +** The wparam value can either be NULL or a pointer to an ansi string for the metadata +** which has changed. This can be thought of as an advanced version of IPC_UPDTITLE and +** could be used to allow for update of the current title when a specific tag changed. +** +** Not recommended to be used since there is not the complete handling implemented in +** Winamp for it at the moment. +*/ + + +#define IPC_SKIN_CHANGED 3018 +/* (requires Winamp 5.1+) +** This is a notification message sent to the main Winamp window by itself whenever +** the skin in use is changed. There is no information sent by the wParam for this. +** +** if(message == WM_WA_IPC && lparam == IPC_SKIN_CHANGED) +** { +** // do what you need to do to handle skin changes, e.g. call WADlg_init(hwnd_winamp); +** } +*/ + + +#define IPC_REGISTER_LOWORD_COMMAND 3019 +/* (requires Winamp 5.1+) +** WORD id = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_REGISTER_LOWORD_COMMAND); +** This will assign you a unique id for making your own commands such as for extra menu +** entries. The starting value returned by this message will potentially change as and +** when the main resource file of Winamp is updated with extra data so assumptions cannot +** be made on what will be returned and plugin loading order will affect things as well. + +** 5.33+ +** If you want to reserve more than one id, you can pass the number of ids required in wParam +*/ + + +#define IPC_GET_DISPATCH_OBJECT 3020 // gets winamp main IDispatch * (for embedded webpages) +#define IPC_GET_UNIQUE_DISPATCH_ID 3021 // gives you a unique dispatch ID that won't conflict with anything in winamp's IDispatch * +#define IPC_ADD_DISPATCH_OBJECT 3022 // add your own dispatch object into winamp's. This lets embedded webpages access your functions +// pass a pointer to DispatchInfo (see below). Winamp makes a copy of all this data so you can safely delete it later +typedef struct +{ + wchar_t *name; // filled in by plugin, make sure it's a unicode string!! (i.e. L"myObject" instead of "myObject). + struct IDispatch *dispatch; // filled in by plugin + DWORD id; // filled in by winamp on return +} DispatchInfo; + +// see IPC_JSAPI2_GET_DISPATCH_OBJECT for version 2 of the Dispatchable scripting interface + +#define IPC_GET_PROXY_STRING 3023 +/* (requires Winamp 5.11+) +** char* proxy_string=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_PROXY_STRING); +** This will return the same string as is shown on the General Preferences page. +*/ + + +#define IPC_USE_REGISTRY 3024 +/* (requires Winamp 5.11+) +** int reg_enabled=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USE_REGISTRY); +** This will return 0 if you should leave your grubby hands off the registry (i.e. for +** lockdown mode). This is useful if Winamp is run from a USB drive and you can't alter +** system settings, etc. +*/ + + +#define IPC_GET_API_SERVICE 3025 +/* (requires Winamp 5.12+) +** api_service* api_service = (api_service)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_API_SERVICE); +** This api will return Winamp's api_service pointer (which is what Winamp3 used, heh). +** If this api is not supported in the Winamp version that is being used at the time then +** the returned value from this api will be 1 which is a good version check. +** +** As of 5.12 there is support for .w5s plugins which reside in %WinampDir%\System and +** are intended for common code that can be shared amongst other plugins e.g. jnetlib.w5s +** which contains jnetlib in one instance instead of being duplicated multiple times in +** all of the plugins which need internet access. +** +** Details on the .w5s specifications will come at some stage (possibly). +*/ + + +typedef struct { + const wchar_t *filename; + const wchar_t *metadata; + wchar_t *ret; + size_t retlen; +} extendedFileInfoStructW; + +#define IPC_GET_EXTENDED_FILE_INFOW 3026 +/* (requires Winamp 5.13+) +** Pass a pointer to the above struct in wParam +*/ + + +#define IPC_GET_EXTENDED_FILE_INFOW_HOOKABLE 3027 +#define IPC_SET_EXTENDED_FILE_INFOW 3028 +/* (requires Winamp 5.13+) +** Pass a pointer to the above struct in wParam +*/ + + +#define IPC_PLAYLIST_GET_NEXT_SELECTED 3029 +/* (requires 5.2+) +** int pl_item = SendMessage(hwnd_winamp,WM_WA_IPC,start,IPC_PLAYLIST_GET_NEXT_SELECTED); +** +** This works just like the ListView_GetNextItem(..) macro for ListView controls. +** 'start' is the index of the playlist item that you want to begin the search after or +** set this as -1 for the search to begin with the first item of the current playlist. +** +** This will return the index of the selected playlist according to the 'start' value or +** it returns -1 if there is no selection or no more selected items according to 'start'. +** +** Quick example: +** +** int sel = -1; +** // keep incrementing the start of the search so we get all of the selected entries +** while((sel = SendMessage(hwnd_winamp,WM_WA_IPC,sel,IPC_PLAYLIST_GET_NEXT_SELECTED))!=-1){ +** // show the playlist file entry of the selected item(s) if there were any +** MessageBox(hwnd_winamp,(char*)SendMessage(hwnd_winamp,WM_WA_IPC,sel,IPC_GETPLAYLISTFILE),0,0); +** } +*/ + + +#define IPC_PLAYLIST_GET_SELECTED_COUNT 3030 +/* (requires 5.2+) +** int selcnt = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_PLAYLIST_GET_SELECTED_COUNT); +** This will return the number of selected playlist entries. +*/ + + +#define IPC_GET_PLAYING_FILENAME 3031 +// returns wchar_t * of the currently playing filename + +#define IPC_OPEN_URL 3032 +// send either ANSI or Unicode string (it'll figure it out, but it MUST start with "h"!, so don't send ftp:// or anything funny) +// you can also send this one from another process via WM_COPYDATA (unicode only) + + +#define IPC_USE_UXTHEME_FUNC 3033 +/* (requires Winamp 5.35+) +** int ret = SendMessage(hwnd_winamp,WM_WA_IPC,param,IPC_USE_UXTHEME_FUNC); +** param can be IPC_ISWINTHEMEPRESENT or IPC_ISAEROCOMPOSITIONACTIVE or a valid hwnd. +** +** If you pass a hwnd then it will apply EnableThemeDialogTexture(ETDT_ENABLETAB) +** so your tabbed dialogs can use the correct theme (on supporting OSes ie XP+). +** +** Otherwise this will return a value based on the param passed (as defined below). +** For compatability, the return value will be zero on success (as 1 is returned +** for unsupported ipc calls on older Winamp versions) +*/ + #define IPC_ISWINTHEMEPRESENT 0 +/* This will return 0 if uxtheme.dll is present +** int isthemethere = !SendMessage(hwnd_winamp,WM_WA_IPC,IPC_ISWINTHEMEPRESENT,IPC_USE_UXTHEME_FUNC); +*/ + #define IPC_ISAEROCOMPOSITIONACTIVE 1 +/* This will return 0 if aero composition is active +** int isaero = !SendMessage(hwnd_winamp,WM_WA_IPC,IPC_ISAEROCOMPOSITIONACTIVE,IPC_USE_UXTHEME_FUNC); +*/ + + +#define IPC_GET_PLAYING_TITLE 3034 +// returns wchar_t * of the current title + + +#define IPC_CANPLAY 3035 +// pass const wchar_t *, returns an in_mod * or 0 + + +typedef struct { + // fill these in... + size_t size; // init to sizeof(artFetchData) + HWND parent; // parent window of the dialogue + + // fill as much of these in as you can, otherwise leave them 0 + const wchar_t *artist; + const wchar_t *album; + int year, amgArtistId, amgAlbumId; + + int showCancelAll; // if set to 1, this shows a "Cancel All" button on the dialogue + + // winamp will fill these in if the call returns successfully: + void* imgData; // a buffer filled with compressed image data. free with WASABI_API_MEMMGR->sysFree() + int imgDataLen; // the size of the buffer + wchar_t type[10]; // eg: "jpg" + const wchar_t *gracenoteFileId; // if you know it +} artFetchData; + +#define IPC_FETCH_ALBUMART 3036 +/* pass an artFetchData*. This will show a dialog guiding the use through choosing art, and return when it's finished +** return values: +** 1: error showing dialog +** 0: success +** -1: cancel was pressed +** -2: cancel all was pressed +*/ + +#define IPC_JSAPI2_GET_DISPATCH_OBJECT 3037 +/* pass your service's unique ID, as a wchar_t * string, in wParam +** Winamp will copy the string, so don't worry about keeping it around +** An IDispatch * object will be returned (cast the return value from SendMessage) +** This IDispatch can be used for scripting/automation/VB interaction +** Pass to IE via IDocHostUIHandler::GetExternal and it will become window.external in javscript +*/ + +#define IPC_REGISTER_WINAMP_IPCMESSAGE 65536 +/* (requires Winamp 5.0+) +** DWORD id = SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)name,IPC_REGISTER_WINAMP_IPCMESSAGE); +** The value 'id' returned is > 65536 and is incremented on subsequent calls for unique +** 'name' values passed to it. By using the same 'name' in different plugins will allow a +** common runtime api to be provided for the currently running instance of Winamp +** e.g. +** PostMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)my_param,registered_ipc); +** Have a look at wa_hotkeys.h for an example on how this api is used in practice for a +** custom WM_WA_IPC message. +** +** if(uMsg == WM_WA_IPC && lParam == id_from_register_winamp_ipcmessage){ +** // do things +** } +*/ + #endif//_WA_IPC_H_ \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface.h b/Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface.h index 24440f22..645400b7 100644 --- a/Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface.h +++ b/Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface.h @@ -1,14428 +1,14428 @@ - - -/* this ALWAYS GENERATED file contains the definitions for the interfaces */ - - - /* File created by MIDL compiler version 6.00.0366 */ -/* at Wed Nov 05 13:21:00 2008 - */ -/* Compiler settings for iTunesCOMInterface.idl: - Oicf, W1, Zp8, env=Win32 (32b run) - protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: - __declspec(uuid()), __declspec(selectany), __declspec(novtable) - DECLSPEC_UUID(), MIDL_INTERFACE() -*/ -//@@MIDL_FILE_HEADING( ) - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ - - -/* verify that the <rpcndr.h> version is high enough to compile this file*/ -#ifndef __REQUIRED_RPCNDR_H_VERSION__ -#define __REQUIRED_RPCNDR_H_VERSION__ 475 -#endif - -#include "rpc.h" -#include "rpcndr.h" - -#ifndef __RPCNDR_H_VERSION__ -#error this stub requires an updated version of <rpcndr.h> -#endif // __RPCNDR_H_VERSION__ - - -#ifndef __iTunesCOMInterface_h__ -#define __iTunesCOMInterface_h__ - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -#pragma once -#endif - -/* Forward Declarations */ - -#ifndef __IITObject_FWD_DEFINED__ -#define __IITObject_FWD_DEFINED__ -typedef interface IITObject IITObject; -#endif /* __IITObject_FWD_DEFINED__ */ - - -#ifndef __IITSource_FWD_DEFINED__ -#define __IITSource_FWD_DEFINED__ -typedef interface IITSource IITSource; -#endif /* __IITSource_FWD_DEFINED__ */ - - -#ifndef __IITSourceCollection_FWD_DEFINED__ -#define __IITSourceCollection_FWD_DEFINED__ -typedef interface IITSourceCollection IITSourceCollection; -#endif /* __IITSourceCollection_FWD_DEFINED__ */ - - -#ifndef __IITEncoder_FWD_DEFINED__ -#define __IITEncoder_FWD_DEFINED__ -typedef interface IITEncoder IITEncoder; -#endif /* __IITEncoder_FWD_DEFINED__ */ - - -#ifndef __IITEncoderCollection_FWD_DEFINED__ -#define __IITEncoderCollection_FWD_DEFINED__ -typedef interface IITEncoderCollection IITEncoderCollection; -#endif /* __IITEncoderCollection_FWD_DEFINED__ */ - - -#ifndef __IITEQPreset_FWD_DEFINED__ -#define __IITEQPreset_FWD_DEFINED__ -typedef interface IITEQPreset IITEQPreset; -#endif /* __IITEQPreset_FWD_DEFINED__ */ - - -#ifndef __IITEQPresetCollection_FWD_DEFINED__ -#define __IITEQPresetCollection_FWD_DEFINED__ -typedef interface IITEQPresetCollection IITEQPresetCollection; -#endif /* __IITEQPresetCollection_FWD_DEFINED__ */ - - -#ifndef __IITPlaylist_FWD_DEFINED__ -#define __IITPlaylist_FWD_DEFINED__ -typedef interface IITPlaylist IITPlaylist; -#endif /* __IITPlaylist_FWD_DEFINED__ */ - - -#ifndef __IITOperationStatus_FWD_DEFINED__ -#define __IITOperationStatus_FWD_DEFINED__ -typedef interface IITOperationStatus IITOperationStatus; -#endif /* __IITOperationStatus_FWD_DEFINED__ */ - - -#ifndef __IITConvertOperationStatus_FWD_DEFINED__ -#define __IITConvertOperationStatus_FWD_DEFINED__ -typedef interface IITConvertOperationStatus IITConvertOperationStatus; -#endif /* __IITConvertOperationStatus_FWD_DEFINED__ */ - - -#ifndef __IITLibraryPlaylist_FWD_DEFINED__ -#define __IITLibraryPlaylist_FWD_DEFINED__ -typedef interface IITLibraryPlaylist IITLibraryPlaylist; -#endif /* __IITLibraryPlaylist_FWD_DEFINED__ */ - - -#ifndef __IITUserPlaylist_FWD_DEFINED__ -#define __IITUserPlaylist_FWD_DEFINED__ -typedef interface IITUserPlaylist IITUserPlaylist; -#endif /* __IITUserPlaylist_FWD_DEFINED__ */ - - -#ifndef __IITTrack_FWD_DEFINED__ -#define __IITTrack_FWD_DEFINED__ -typedef interface IITTrack IITTrack; -#endif /* __IITTrack_FWD_DEFINED__ */ - - -#ifndef __IITTrackCollection_FWD_DEFINED__ -#define __IITTrackCollection_FWD_DEFINED__ -typedef interface IITTrackCollection IITTrackCollection; -#endif /* __IITTrackCollection_FWD_DEFINED__ */ - - -#ifndef __IITVisual_FWD_DEFINED__ -#define __IITVisual_FWD_DEFINED__ -typedef interface IITVisual IITVisual; -#endif /* __IITVisual_FWD_DEFINED__ */ - - -#ifndef __IITVisualCollection_FWD_DEFINED__ -#define __IITVisualCollection_FWD_DEFINED__ -typedef interface IITVisualCollection IITVisualCollection; -#endif /* __IITVisualCollection_FWD_DEFINED__ */ - - -#ifndef __IITWindow_FWD_DEFINED__ -#define __IITWindow_FWD_DEFINED__ -typedef interface IITWindow IITWindow; -#endif /* __IITWindow_FWD_DEFINED__ */ - - -#ifndef __IITBrowserWindow_FWD_DEFINED__ -#define __IITBrowserWindow_FWD_DEFINED__ -typedef interface IITBrowserWindow IITBrowserWindow; -#endif /* __IITBrowserWindow_FWD_DEFINED__ */ - - -#ifndef __IITWindowCollection_FWD_DEFINED__ -#define __IITWindowCollection_FWD_DEFINED__ -typedef interface IITWindowCollection IITWindowCollection; -#endif /* __IITWindowCollection_FWD_DEFINED__ */ - - -#ifndef __IiTunes_FWD_DEFINED__ -#define __IiTunes_FWD_DEFINED__ -typedef interface IiTunes IiTunes; -#endif /* __IiTunes_FWD_DEFINED__ */ - - -#ifndef ___IiTunesEvents_FWD_DEFINED__ -#define ___IiTunesEvents_FWD_DEFINED__ -typedef interface _IiTunesEvents _IiTunesEvents; -#endif /* ___IiTunesEvents_FWD_DEFINED__ */ - - -#ifndef ___IITConvertOperationStatusEvents_FWD_DEFINED__ -#define ___IITConvertOperationStatusEvents_FWD_DEFINED__ -typedef interface _IITConvertOperationStatusEvents _IITConvertOperationStatusEvents; -#endif /* ___IITConvertOperationStatusEvents_FWD_DEFINED__ */ - - -#ifndef __iTunesApp_FWD_DEFINED__ -#define __iTunesApp_FWD_DEFINED__ - -#ifdef __cplusplus -typedef class iTunesApp iTunesApp; -#else -typedef struct iTunesApp iTunesApp; -#endif /* __cplusplus */ - -#endif /* __iTunesApp_FWD_DEFINED__ */ - - -#ifndef __iTunesConvertOperationStatus_FWD_DEFINED__ -#define __iTunesConvertOperationStatus_FWD_DEFINED__ - -#ifdef __cplusplus -typedef class iTunesConvertOperationStatus iTunesConvertOperationStatus; -#else -typedef struct iTunesConvertOperationStatus iTunesConvertOperationStatus; -#endif /* __cplusplus */ - -#endif /* __iTunesConvertOperationStatus_FWD_DEFINED__ */ - - -#ifndef __IITArtwork_FWD_DEFINED__ -#define __IITArtwork_FWD_DEFINED__ -typedef interface IITArtwork IITArtwork; -#endif /* __IITArtwork_FWD_DEFINED__ */ - - -#ifndef __IITArtworkCollection_FWD_DEFINED__ -#define __IITArtworkCollection_FWD_DEFINED__ -typedef interface IITArtworkCollection IITArtworkCollection; -#endif /* __IITArtworkCollection_FWD_DEFINED__ */ - - -#ifndef __IITURLTrack_FWD_DEFINED__ -#define __IITURLTrack_FWD_DEFINED__ -typedef interface IITURLTrack IITURLTrack; -#endif /* __IITURLTrack_FWD_DEFINED__ */ - - -#ifndef __IITAudioCDPlaylist_FWD_DEFINED__ -#define __IITAudioCDPlaylist_FWD_DEFINED__ -typedef interface IITAudioCDPlaylist IITAudioCDPlaylist; -#endif /* __IITAudioCDPlaylist_FWD_DEFINED__ */ - - -#ifndef __IITPlaylistCollection_FWD_DEFINED__ -#define __IITPlaylistCollection_FWD_DEFINED__ -typedef interface IITPlaylistCollection IITPlaylistCollection; -#endif /* __IITPlaylistCollection_FWD_DEFINED__ */ - - -#ifndef __IITIPodSource_FWD_DEFINED__ -#define __IITIPodSource_FWD_DEFINED__ -typedef interface IITIPodSource IITIPodSource; -#endif /* __IITIPodSource_FWD_DEFINED__ */ - - -#ifndef __IITFileOrCDTrack_FWD_DEFINED__ -#define __IITFileOrCDTrack_FWD_DEFINED__ -typedef interface IITFileOrCDTrack IITFileOrCDTrack; -#endif /* __IITFileOrCDTrack_FWD_DEFINED__ */ - - -#ifndef __IITPlaylistWindow_FWD_DEFINED__ -#define __IITPlaylistWindow_FWD_DEFINED__ -typedef interface IITPlaylistWindow IITPlaylistWindow; -#endif /* __IITPlaylistWindow_FWD_DEFINED__ */ - - -/* header files for imported files */ -#include "oaidl.h" -#include "ocidl.h" -#include "DispEx.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -void * __RPC_USER MIDL_user_allocate(size_t); -void __RPC_USER MIDL_user_free( void * ); - -/* interface __MIDL_itf_iTunesCOMInterface_0000 */ -/* [local] */ - -typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("4B73428D-2F56-4833-8E5D-65590E45FEAD") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0000_0001 - { kITTypeLibrary_MajorVersion = 1, - kITTypeLibrary_MinorVersion = 12 - } ITVersion; - -typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("4C25623B-F990-4ebd-8970-F29A70084B8C") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0000_0002 - { ITUNES_E_USERCANCEL = 0xa0040201, - ITUNES_E_OBJECTDELETED = 0xa0040202, - ITUNES_E_OBJECTLOCKED = 0xa0040203, - ITUNES_E_CONVERSIONINPROGRESS = 0xa0040204, - ITUNES_E_MUSICSTOREDISABLED = 0xa0040205, - ITUNES_E_OBJECTEXISTS = 0xa0040206, - ITUNES_E_PODCASTSDISABLED = 0xa0040207 - } ITErrors; - - - -extern RPC_IF_HANDLE __MIDL_itf_iTunesCOMInterface_0000_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_iTunesCOMInterface_0000_v0_0_s_ifspec; - - -#ifndef __iTunesLib_LIBRARY_DEFINED__ -#define __iTunesLib_LIBRARY_DEFINED__ - -/* library iTunesLib */ -/* [helpstring][uuid][version] */ - - - - - - - - - - - - - - - - - - - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("3D502ACA-B474-4640-A2A4-C149538345EC") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0001 - { ITPlayerStateStopped = 0, - ITPlayerStatePlaying = ITPlayerStateStopped + 1, - ITPlayerStateFastForward = ITPlayerStatePlaying + 1, - ITPlayerStateRewind = ITPlayerStateFastForward + 1 - } ITPlayerState; - -typedef /* [public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("5319FADA-0F39-4015-82A0-48B8B871C63C") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0002 - { ITVisualSizeSmall = 0, - ITVisualSizeMedium = ITVisualSizeSmall + 1, - ITVisualSizeLarge = ITVisualSizeMedium + 1 - } ITVisualSize; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("C8128C8D-EDE0-4f0e-AEB1-08D24A91C551") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0003 - { ITCOMDisabledReasonOther = 0, - ITCOMDisabledReasonDialog = ITCOMDisabledReasonOther + 1, - ITCOMDisabledReasonQuitting = ITCOMDisabledReasonDialog + 1 - } ITCOMDisabledReason; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("6B1BD814-CA6E-4063-9EDA-4128D31068C1") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0004 - { ITPlayButtonStatePlayDisabled = 0, - ITPlayButtonStatePlayEnabled = ITPlayButtonStatePlayDisabled + 1, - ITPlayButtonStatePauseEnabled = ITPlayButtonStatePlayEnabled + 1, - ITPlayButtonStatePauseDisabled = ITPlayButtonStatePauseEnabled + 1, - ITPlayButtonStateStopEnabled = ITPlayButtonStatePauseDisabled + 1, - ITPlayButtonStateStopDisabled = ITPlayButtonStateStopEnabled + 1 - } ITPlayButtonState; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("8AF85488-2154-4e46-B65B-1972A43493EF") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0005 - { ITPlayerButtonPrevious = 0, - ITPlayerButtonPlay = ITPlayerButtonPrevious + 1, - ITPlayerButtonNext = ITPlayerButtonPlay + 1 - } ITPlayerButton; - -typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("2129AB11-F23F-485e-B15A-3F8573294F9A") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0006 - { ITPlayerButtonModifierKeyNone = 0, - ITPlayerButtonModifierKeyShift = 1, - ITPlayerButtonModifierKeyControl = 2, - ITPlayerButtonModifierKeyAlt = 4, - ITPlayerButtonModifierKeyCapsLock = 8 - } ITPlayerButtonModifierKey; - -typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("3194F5F4-8F52-41e6-AB8E-4221CFE29550") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0275_0001 - { ITEventDatabaseChanged = 1, - ITEventPlayerPlay = 2, - ITEventPlayerStop = 3, - ITEventPlayerPlayingTrackChanged = 4, - ITEventUserInterfaceEnabled = 5, - ITEventCOMCallsDisabled = 6, - ITEventCOMCallsEnabled = 7, - ITEventQuitting = 8, - ITEventAboutToPromptUserToQuit = 9, - ITEventSoundVolumeChanged = 10 - } ITEvent; - -typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("2E4D55FA-1CD3-4831-8751-0C11EC4FF6FD") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0276_0001 - { ITConvertOperationStatusChanged = 1, - ITConvertOperationComplete = 2 - } ITConvertOperationStatusEvent; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("269E36A5-1728-46e4-BF04-93032C3DD51C") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0277_0001 - { ITArtworkFormatUnknown = 0, - ITArtworkFormatJPEG = ITArtworkFormatUnknown + 1, - ITArtworkFormatPNG = ITArtworkFormatJPEG + 1, - ITArtworkFormatBMP = ITArtworkFormatPNG + 1 - } ITArtworkFormat; - - - - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("DDE76D6E-5F8C-4bda-AFA6-69E82218CFF3") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0001 - { ITPlaylistKindUnknown = 0, - ITPlaylistKindLibrary = ITPlaylistKindUnknown + 1, - ITPlaylistKindUser = ITPlaylistKindLibrary + 1, - ITPlaylistKindCD = ITPlaylistKindUser + 1, - ITPlaylistKindDevice = ITPlaylistKindCD + 1, - ITPlaylistKindRadioTuner = ITPlaylistKindDevice + 1 - } ITPlaylistKind; - -typedef /* [public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("4E1D67A4-6C7A-4c7d-821C-03AF7EB10C35") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0002 - { ITPlaylistRepeatModeOff = 0, - ITPlaylistRepeatModeOne = ITPlaylistRepeatModeOff + 1, - ITPlaylistRepeatModeAll = ITPlaylistRepeatModeOne + 1 - } ITPlaylistRepeatMode; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("BB8E7701-1E77-4972-B6C4-C70AC216F468") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0003 - { ITPlaylistPrintKindPlaylist = 0, - ITPlaylistPrintKindAlbumlist = ITPlaylistPrintKindPlaylist + 1, - ITPlaylistPrintKindInsert = ITPlaylistPrintKindAlbumlist + 1 - } ITPlaylistPrintKind; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("58765E77-E34A-4d67-AC12-5B5BA33EA08F") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0004 - { ITPlaylistSearchFieldAll = 0, - ITPlaylistSearchFieldVisible = ITPlaylistSearchFieldAll + 1, - ITPlaylistSearchFieldArtists = ITPlaylistSearchFieldVisible + 1, - ITPlaylistSearchFieldAlbums = ITPlaylistSearchFieldArtists + 1, - ITPlaylistSearchFieldComposers = ITPlaylistSearchFieldAlbums + 1, - ITPlaylistSearchFieldSongNames = ITPlaylistSearchFieldComposers + 1 - } ITPlaylistSearchField; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("62BC24E6-5C77-4fb7-AA6C-B7FA40C6095D") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0285_0001 - { ITUserPlaylistSpecialKindNone = 0, - ITUserPlaylistSpecialKindPurchasedMusic = ITUserPlaylistSpecialKindNone + 1, - ITUserPlaylistSpecialKindPartyShuffle = ITUserPlaylistSpecialKindPurchasedMusic + 1, - ITUserPlaylistSpecialKindPodcasts = ITUserPlaylistSpecialKindPartyShuffle + 1, - ITUserPlaylistSpecialKindFolder = ITUserPlaylistSpecialKindPodcasts + 1, - ITUserPlaylistSpecialKindVideos = ITUserPlaylistSpecialKindFolder + 1, - ITUserPlaylistSpecialKindMusic = ITUserPlaylistSpecialKindVideos + 1, - ITUserPlaylistSpecialKindMovies = ITUserPlaylistSpecialKindMusic + 1, - ITUserPlaylistSpecialKindTVShows = ITUserPlaylistSpecialKindMovies + 1, - ITUserPlaylistSpecialKindAudiobooks = ITUserPlaylistSpecialKindTVShows + 1 - } ITUserPlaylistSpecialKind; - - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("5F35912B-E633-4930-9E25-09489BAED75A") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0288_0001 - { ITSourceKindUnknown = 0, - ITSourceKindLibrary = ITSourceKindUnknown + 1, - ITSourceKindIPod = ITSourceKindLibrary + 1, - ITSourceKindAudioCD = ITSourceKindIPod + 1, - ITSourceKindMP3CD = ITSourceKindAudioCD + 1, - ITSourceKindDevice = ITSourceKindMP3CD + 1, - ITSourceKindRadioTuner = ITSourceKindDevice + 1, - ITSourceKindSharedLibrary = ITSourceKindRadioTuner + 1 - } ITSourceKind; - - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("ACA133C5-4697-4d5f-98B1-D9881B85FE98") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0291_0001 - { ITTrackKindUnknown = 0, - ITTrackKindFile = ITTrackKindUnknown + 1, - ITTrackKindCD = ITTrackKindFile + 1, - ITTrackKindURL = ITTrackKindCD + 1, - ITTrackKindDevice = ITTrackKindURL + 1, - ITTrackKindSharedLibrary = ITTrackKindDevice + 1 - } ITTrackKind; - -typedef /* [public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("735ECC17-38CC-4d4d-A838-24AF7DCB440E") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0291_0002 - { ITVideoKindNone = 0, - ITVideoKindMovie = ITVideoKindNone + 1, - ITVideoKindMusicVideo = ITVideoKindMovie + 1, - ITVideoKindTVShow = ITVideoKindMusicVideo + 1 - } ITVideoKind; - -typedef /* [public][public][public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("5C75B72C-D066-4faa-8732-D9ED71A6CBD9") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0291_0003 - { ITRatingKindUser = 0, - ITRatingKindComputed = ITRatingKindUser + 1 - } ITRatingKind; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("C20CE920-EFD9-4c1a-8036-95A895741214") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0297_0001 - { ITWindowKindUnknown = 0, - ITWindowKindBrowser = ITWindowKindUnknown + 1, - ITWindowKindPlaylist = ITWindowKindBrowser + 1, - ITWindowKindEQ = ITWindowKindPlaylist + 1, - ITWindowKindArtwork = ITWindowKindEQ + 1, - ITWindowKindNowPlaying = ITWindowKindArtwork + 1 - } ITWindowKind; - - -EXTERN_C const IID LIBID_iTunesLib; - -#ifndef __IITObject_INTERFACE_DEFINED__ -#define __IITObject_INTERFACE_DEFINED__ - -/* interface IITObject */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITObject; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("9FAB0E27-70D7-4e3a-9965-B0C8B8869BB6") - IITObject : public IDispatch - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetITObjectIDs( - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( - /* [retval][out] */ BSTR *name) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Name( - /* [in] */ BSTR name) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Index( - /* [retval][out] */ long *index) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SourceID( - /* [retval][out] */ long *sourceID) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlaylistID( - /* [retval][out] */ long *playlistID) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackID( - /* [retval][out] */ long *trackID) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackDatabaseID( - /* [retval][out] */ long *databaseID) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITObjectVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITObject * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITObject * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITObject * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITObject * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITObject * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITObject * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITObject * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITObject * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITObject * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITObject * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITObject * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITObject * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITObject * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITObject * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITObject * This, - /* [retval][out] */ long *databaseID); - - END_INTERFACE - } IITObjectVtbl; - - interface IITObject - { - CONST_VTBL struct IITObjectVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITObject_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITObject_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITObject_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITObject_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITObject_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITObject_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITObject_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITObject_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITObject_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITObject_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITObject_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITObject_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITObject_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITObject_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITObject_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITObject_GetITObjectIDs_Proxy( - IITObject * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - -void __RPC_STUB IITObject_GetITObjectIDs_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_Name_Proxy( - IITObject * This, - /* [retval][out] */ BSTR *name); - - -void __RPC_STUB IITObject_get_Name_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITObject_put_Name_Proxy( - IITObject * This, - /* [in] */ BSTR name); - - -void __RPC_STUB IITObject_put_Name_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_Index_Proxy( - IITObject * This, - /* [retval][out] */ long *index); - - -void __RPC_STUB IITObject_get_Index_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_SourceID_Proxy( - IITObject * This, - /* [retval][out] */ long *sourceID); - - -void __RPC_STUB IITObject_get_SourceID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_PlaylistID_Proxy( - IITObject * This, - /* [retval][out] */ long *playlistID); - - -void __RPC_STUB IITObject_get_PlaylistID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_TrackID_Proxy( - IITObject * This, - /* [retval][out] */ long *trackID); - - -void __RPC_STUB IITObject_get_TrackID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_TrackDatabaseID_Proxy( - IITObject * This, - /* [retval][out] */ long *databaseID); - - -void __RPC_STUB IITObject_get_TrackDatabaseID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITObject_INTERFACE_DEFINED__ */ - - -#ifndef __IITSource_INTERFACE_DEFINED__ -#define __IITSource_INTERFACE_DEFINED__ - -/* interface IITSource */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITSource; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("AEC1C4D3-AEF1-4255-B892-3E3D13ADFDF9") - IITSource : public IITObject - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( - /* [retval][out] */ ITSourceKind *kind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Capacity( - /* [retval][out] */ double *capacity) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_FreeSpace( - /* [retval][out] */ double *freespace) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlists( - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITSourceVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITSource * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITSource * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITSource * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITSource * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITSource * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITSource * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITSource * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITSource * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITSource * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITSource * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITSource * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITSource * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITSource * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITSource * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITSource * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITSource * This, - /* [retval][out] */ ITSourceKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Capacity )( - IITSource * This, - /* [retval][out] */ double *capacity); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_FreeSpace )( - IITSource * This, - /* [retval][out] */ double *freespace); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( - IITSource * This, - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); - - END_INTERFACE - } IITSourceVtbl; - - interface IITSource - { - CONST_VTBL struct IITSourceVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITSource_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITSource_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITSource_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITSource_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITSource_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITSource_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITSource_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITSource_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITSource_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITSource_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITSource_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITSource_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITSource_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITSource_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITSource_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITSource_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITSource_get_Capacity(This,capacity) \ - (This)->lpVtbl -> get_Capacity(This,capacity) - -#define IITSource_get_FreeSpace(This,freespace) \ - (This)->lpVtbl -> get_FreeSpace(This,freespace) - -#define IITSource_get_Playlists(This,iPlaylistCollection) \ - (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_Kind_Proxy( - IITSource * This, - /* [retval][out] */ ITSourceKind *kind); - - -void __RPC_STUB IITSource_get_Kind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_Capacity_Proxy( - IITSource * This, - /* [retval][out] */ double *capacity); - - -void __RPC_STUB IITSource_get_Capacity_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_FreeSpace_Proxy( - IITSource * This, - /* [retval][out] */ double *freespace); - - -void __RPC_STUB IITSource_get_FreeSpace_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_Playlists_Proxy( - IITSource * This, - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); - - -void __RPC_STUB IITSource_get_Playlists_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITSource_INTERFACE_DEFINED__ */ - - -#ifndef __IITSourceCollection_INTERFACE_DEFINED__ -#define __IITSourceCollection_INTERFACE_DEFINED__ - -/* interface IITSourceCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITSourceCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("2FF6CE20-FF87-4183-B0B3-F323D047AF41") - IITSourceCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITSource **iSource) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( - /* [in] */ BSTR name, - /* [retval][out] */ IITSource **iSource) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPersistentID( - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITSource **iSource) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITSourceCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITSourceCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITSourceCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITSourceCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITSourceCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITSourceCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITSourceCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITSourceCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITSourceCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITSourceCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITSource **iSource); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( - IITSourceCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITSource **iSource); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITSourceCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPersistentID )( - IITSourceCollection * This, - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITSource **iSource); - - END_INTERFACE - } IITSourceCollectionVtbl; - - interface IITSourceCollection - { - CONST_VTBL struct IITSourceCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITSourceCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITSourceCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITSourceCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITSourceCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITSourceCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITSourceCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITSourceCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITSourceCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITSourceCollection_get_Item(This,index,iSource) \ - (This)->lpVtbl -> get_Item(This,index,iSource) - -#define IITSourceCollection_get_ItemByName(This,name,iSource) \ - (This)->lpVtbl -> get_ItemByName(This,name,iSource) - -#define IITSourceCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#define IITSourceCollection_get_ItemByPersistentID(This,highID,lowID,iSource) \ - (This)->lpVtbl -> get_ItemByPersistentID(This,highID,lowID,iSource) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_Count_Proxy( - IITSourceCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITSourceCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_Item_Proxy( - IITSourceCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITSource **iSource); - - -void __RPC_STUB IITSourceCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_ItemByName_Proxy( - IITSourceCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITSource **iSource); - - -void __RPC_STUB IITSourceCollection_get_ItemByName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get__NewEnum_Proxy( - IITSourceCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITSourceCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_ItemByPersistentID_Proxy( - IITSourceCollection * This, - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITSource **iSource); - - -void __RPC_STUB IITSourceCollection_get_ItemByPersistentID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITSourceCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IITEncoder_INTERFACE_DEFINED__ -#define __IITEncoder_INTERFACE_DEFINED__ - -/* interface IITEncoder */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITEncoder; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("1CF95A1C-55FE-4f45-A2D3-85AC6C504A73") - IITEncoder : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( - /* [retval][out] */ BSTR *name) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Format( - /* [retval][out] */ BSTR *format) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITEncoderVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITEncoder * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITEncoder * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITEncoder * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITEncoder * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITEncoder * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITEncoder * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITEncoder * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITEncoder * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Format )( - IITEncoder * This, - /* [retval][out] */ BSTR *format); - - END_INTERFACE - } IITEncoderVtbl; - - interface IITEncoder - { - CONST_VTBL struct IITEncoderVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITEncoder_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITEncoder_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITEncoder_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITEncoder_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITEncoder_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITEncoder_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITEncoder_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITEncoder_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITEncoder_get_Format(This,format) \ - (This)->lpVtbl -> get_Format(This,format) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoder_get_Name_Proxy( - IITEncoder * This, - /* [retval][out] */ BSTR *name); - - -void __RPC_STUB IITEncoder_get_Name_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoder_get_Format_Proxy( - IITEncoder * This, - /* [retval][out] */ BSTR *format); - - -void __RPC_STUB IITEncoder_get_Format_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITEncoder_INTERFACE_DEFINED__ */ - - -#ifndef __IITEncoderCollection_INTERFACE_DEFINED__ -#define __IITEncoderCollection_INTERFACE_DEFINED__ - -/* interface IITEncoderCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITEncoderCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("8862BCA9-168D-4549-A9D5-ADB35E553BA6") - IITEncoderCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITEncoder **iEncoder) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( - /* [in] */ BSTR name, - /* [retval][out] */ IITEncoder **iEncoder) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITEncoderCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITEncoderCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITEncoderCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITEncoderCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITEncoderCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITEncoderCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITEncoderCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITEncoderCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITEncoderCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITEncoderCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITEncoder **iEncoder); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( - IITEncoderCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITEncoder **iEncoder); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITEncoderCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - END_INTERFACE - } IITEncoderCollectionVtbl; - - interface IITEncoderCollection - { - CONST_VTBL struct IITEncoderCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITEncoderCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITEncoderCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITEncoderCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITEncoderCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITEncoderCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITEncoderCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITEncoderCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITEncoderCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITEncoderCollection_get_Item(This,index,iEncoder) \ - (This)->lpVtbl -> get_Item(This,index,iEncoder) - -#define IITEncoderCollection_get_ItemByName(This,name,iEncoder) \ - (This)->lpVtbl -> get_ItemByName(This,name,iEncoder) - -#define IITEncoderCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get_Count_Proxy( - IITEncoderCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITEncoderCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get_Item_Proxy( - IITEncoderCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITEncoder **iEncoder); - - -void __RPC_STUB IITEncoderCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get_ItemByName_Proxy( - IITEncoderCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITEncoder **iEncoder); - - -void __RPC_STUB IITEncoderCollection_get_ItemByName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get__NewEnum_Proxy( - IITEncoderCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITEncoderCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITEncoderCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IITEQPreset_INTERFACE_DEFINED__ -#define __IITEQPreset_INTERFACE_DEFINED__ - -/* interface IITEQPreset */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITEQPreset; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("5BE75F4F-68FA-4212-ACB7-BE44EA569759") - IITEQPreset : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( - /* [retval][out] */ BSTR *name) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Modifiable( - /* [retval][out] */ VARIANT_BOOL *isModifiable) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Preamp( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Preamp( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band1( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band1( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band2( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band2( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band3( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band3( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band4( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band4( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band5( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band5( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band6( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band6( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band7( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band7( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band8( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band8( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band9( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band9( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band10( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band10( - /* [in] */ double level) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( - /* [in] */ VARIANT_BOOL updateAllTracks) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Rename( - /* [in] */ BSTR newName, - /* [in] */ VARIANT_BOOL updateAllTracks) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITEQPresetVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITEQPreset * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITEQPreset * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITEQPreset * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITEQPreset * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITEQPreset * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITEQPreset * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITEQPreset * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITEQPreset * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Modifiable )( - IITEQPreset * This, - /* [retval][out] */ VARIANT_BOOL *isModifiable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Preamp )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Preamp )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band1 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band1 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band2 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band2 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band3 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band3 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band4 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band4 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band5 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band5 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band6 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band6 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band7 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band7 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band8 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band8 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band9 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band9 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band10 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band10 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITEQPreset * This, - /* [in] */ VARIANT_BOOL updateAllTracks); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Rename )( - IITEQPreset * This, - /* [in] */ BSTR newName, - /* [in] */ VARIANT_BOOL updateAllTracks); - - END_INTERFACE - } IITEQPresetVtbl; - - interface IITEQPreset - { - CONST_VTBL struct IITEQPresetVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITEQPreset_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITEQPreset_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITEQPreset_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITEQPreset_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITEQPreset_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITEQPreset_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITEQPreset_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITEQPreset_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITEQPreset_get_Modifiable(This,isModifiable) \ - (This)->lpVtbl -> get_Modifiable(This,isModifiable) - -#define IITEQPreset_get_Preamp(This,level) \ - (This)->lpVtbl -> get_Preamp(This,level) - -#define IITEQPreset_put_Preamp(This,level) \ - (This)->lpVtbl -> put_Preamp(This,level) - -#define IITEQPreset_get_Band1(This,level) \ - (This)->lpVtbl -> get_Band1(This,level) - -#define IITEQPreset_put_Band1(This,level) \ - (This)->lpVtbl -> put_Band1(This,level) - -#define IITEQPreset_get_Band2(This,level) \ - (This)->lpVtbl -> get_Band2(This,level) - -#define IITEQPreset_put_Band2(This,level) \ - (This)->lpVtbl -> put_Band2(This,level) - -#define IITEQPreset_get_Band3(This,level) \ - (This)->lpVtbl -> get_Band3(This,level) - -#define IITEQPreset_put_Band3(This,level) \ - (This)->lpVtbl -> put_Band3(This,level) - -#define IITEQPreset_get_Band4(This,level) \ - (This)->lpVtbl -> get_Band4(This,level) - -#define IITEQPreset_put_Band4(This,level) \ - (This)->lpVtbl -> put_Band4(This,level) - -#define IITEQPreset_get_Band5(This,level) \ - (This)->lpVtbl -> get_Band5(This,level) - -#define IITEQPreset_put_Band5(This,level) \ - (This)->lpVtbl -> put_Band5(This,level) - -#define IITEQPreset_get_Band6(This,level) \ - (This)->lpVtbl -> get_Band6(This,level) - -#define IITEQPreset_put_Band6(This,level) \ - (This)->lpVtbl -> put_Band6(This,level) - -#define IITEQPreset_get_Band7(This,level) \ - (This)->lpVtbl -> get_Band7(This,level) - -#define IITEQPreset_put_Band7(This,level) \ - (This)->lpVtbl -> put_Band7(This,level) - -#define IITEQPreset_get_Band8(This,level) \ - (This)->lpVtbl -> get_Band8(This,level) - -#define IITEQPreset_put_Band8(This,level) \ - (This)->lpVtbl -> put_Band8(This,level) - -#define IITEQPreset_get_Band9(This,level) \ - (This)->lpVtbl -> get_Band9(This,level) - -#define IITEQPreset_put_Band9(This,level) \ - (This)->lpVtbl -> put_Band9(This,level) - -#define IITEQPreset_get_Band10(This,level) \ - (This)->lpVtbl -> get_Band10(This,level) - -#define IITEQPreset_put_Band10(This,level) \ - (This)->lpVtbl -> put_Band10(This,level) - -#define IITEQPreset_Delete(This,updateAllTracks) \ - (This)->lpVtbl -> Delete(This,updateAllTracks) - -#define IITEQPreset_Rename(This,newName,updateAllTracks) \ - (This)->lpVtbl -> Rename(This,newName,updateAllTracks) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Name_Proxy( - IITEQPreset * This, - /* [retval][out] */ BSTR *name); - - -void __RPC_STUB IITEQPreset_get_Name_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Modifiable_Proxy( - IITEQPreset * This, - /* [retval][out] */ VARIANT_BOOL *isModifiable); - - -void __RPC_STUB IITEQPreset_get_Modifiable_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Preamp_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Preamp_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Preamp_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Preamp_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band1_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band1_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band1_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band1_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band2_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band2_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band2_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band2_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band3_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band3_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band3_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band3_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band4_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band4_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band4_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band4_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band5_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band5_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band5_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band5_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band6_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band6_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band6_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band6_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band7_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band7_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band7_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band7_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band8_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band8_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band8_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band8_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band9_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band9_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band9_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band9_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band10_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band10_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band10_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band10_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITEQPreset_Delete_Proxy( - IITEQPreset * This, - /* [in] */ VARIANT_BOOL updateAllTracks); - - -void __RPC_STUB IITEQPreset_Delete_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITEQPreset_Rename_Proxy( - IITEQPreset * This, - /* [in] */ BSTR newName, - /* [in] */ VARIANT_BOOL updateAllTracks); - - -void __RPC_STUB IITEQPreset_Rename_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITEQPreset_INTERFACE_DEFINED__ */ - - -#ifndef __IITEQPresetCollection_INTERFACE_DEFINED__ -#define __IITEQPresetCollection_INTERFACE_DEFINED__ - -/* interface IITEQPresetCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITEQPresetCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("AEF4D111-3331-48da-B0C2-B468D5D61D08") - IITEQPresetCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITEQPreset **iEQPreset) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( - /* [in] */ BSTR name, - /* [retval][out] */ IITEQPreset **iEQPreset) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITEQPresetCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITEQPresetCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITEQPresetCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITEQPresetCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITEQPresetCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITEQPresetCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITEQPresetCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITEQPresetCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITEQPresetCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITEQPresetCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITEQPreset **iEQPreset); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( - IITEQPresetCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITEQPreset **iEQPreset); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITEQPresetCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - END_INTERFACE - } IITEQPresetCollectionVtbl; - - interface IITEQPresetCollection - { - CONST_VTBL struct IITEQPresetCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITEQPresetCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITEQPresetCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITEQPresetCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITEQPresetCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITEQPresetCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITEQPresetCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITEQPresetCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITEQPresetCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITEQPresetCollection_get_Item(This,index,iEQPreset) \ - (This)->lpVtbl -> get_Item(This,index,iEQPreset) - -#define IITEQPresetCollection_get_ItemByName(This,name,iEQPreset) \ - (This)->lpVtbl -> get_ItemByName(This,name,iEQPreset) - -#define IITEQPresetCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get_Count_Proxy( - IITEQPresetCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITEQPresetCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get_Item_Proxy( - IITEQPresetCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITEQPreset **iEQPreset); - - -void __RPC_STUB IITEQPresetCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get_ItemByName_Proxy( - IITEQPresetCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITEQPreset **iEQPreset); - - -void __RPC_STUB IITEQPresetCollection_get_ItemByName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get__NewEnum_Proxy( - IITEQPresetCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITEQPresetCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITEQPresetCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IITPlaylist_INTERFACE_DEFINED__ -#define __IITPlaylist_INTERFACE_DEFINED__ - -/* interface IITPlaylist */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITPlaylist; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("3D5E072F-2A77-4b17-9E73-E03B77CCCCA9") - IITPlaylist : public IITObject - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayFirstTrack( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Print( - /* [in] */ VARIANT_BOOL showPrintDialog, - /* [in] */ ITPlaylistPrintKind printKind, - /* [in] */ BSTR theme) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Search( - /* [in] */ BSTR searchText, - /* [in] */ ITPlaylistSearchField searchFields, - /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( - /* [retval][out] */ ITPlaylistKind *kind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Source( - /* [retval][out] */ IITSource **iSource) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Duration( - /* [retval][out] */ long *duration) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Shuffle( - /* [retval][out] */ VARIANT_BOOL *isShuffle) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Shuffle( - /* [in] */ VARIANT_BOOL shouldShuffle) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size( - /* [retval][out] */ double *size) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SongRepeat( - /* [retval][out] */ ITPlaylistRepeatMode *repeatMode) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SongRepeat( - /* [in] */ ITPlaylistRepeatMode repeatMode) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Time( - /* [retval][out] */ BSTR *time) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Visible( - /* [retval][out] */ VARIANT_BOOL *isVisible) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Tracks( - /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITPlaylistVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITPlaylist * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITPlaylist * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITPlaylist * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITPlaylist * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITPlaylist * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITPlaylist * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITPlaylist * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITPlaylist * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITPlaylist * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITPlaylist * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITPlaylist * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITPlaylist * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITPlaylist * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITPlaylist * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITPlaylist * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( - IITPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( - IITPlaylist * This, - /* [in] */ VARIANT_BOOL showPrintDialog, - /* [in] */ ITPlaylistPrintKind printKind, - /* [in] */ BSTR theme); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( - IITPlaylist * This, - /* [in] */ BSTR searchText, - /* [in] */ ITPlaylistSearchField searchFields, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITPlaylist * This, - /* [retval][out] */ ITPlaylistKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( - IITPlaylist * This, - /* [retval][out] */ IITSource **iSource); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( - IITPlaylist * This, - /* [retval][out] */ long *duration); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( - IITPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isShuffle); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( - IITPlaylist * This, - /* [in] */ VARIANT_BOOL shouldShuffle); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( - IITPlaylist * This, - /* [retval][out] */ double *size); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( - IITPlaylist * This, - /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( - IITPlaylist * This, - /* [in] */ ITPlaylistRepeatMode repeatMode); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( - IITPlaylist * This, - /* [retval][out] */ BSTR *time); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( - IITPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( - IITPlaylist * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - END_INTERFACE - } IITPlaylistVtbl; - - interface IITPlaylist - { - CONST_VTBL struct IITPlaylistVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITPlaylist_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITPlaylist_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITPlaylist_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITPlaylist_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITPlaylist_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITPlaylist_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITPlaylist_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITPlaylist_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITPlaylist_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITPlaylist_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITPlaylist_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITPlaylist_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITPlaylist_PlayFirstTrack(This) \ - (This)->lpVtbl -> PlayFirstTrack(This) - -#define IITPlaylist_Print(This,showPrintDialog,printKind,theme) \ - (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) - -#define IITPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ - (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) - -#define IITPlaylist_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITPlaylist_get_Source(This,iSource) \ - (This)->lpVtbl -> get_Source(This,iSource) - -#define IITPlaylist_get_Duration(This,duration) \ - (This)->lpVtbl -> get_Duration(This,duration) - -#define IITPlaylist_get_Shuffle(This,isShuffle) \ - (This)->lpVtbl -> get_Shuffle(This,isShuffle) - -#define IITPlaylist_put_Shuffle(This,shouldShuffle) \ - (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) - -#define IITPlaylist_get_Size(This,size) \ - (This)->lpVtbl -> get_Size(This,size) - -#define IITPlaylist_get_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> get_SongRepeat(This,repeatMode) - -#define IITPlaylist_put_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> put_SongRepeat(This,repeatMode) - -#define IITPlaylist_get_Time(This,time) \ - (This)->lpVtbl -> get_Time(This,time) - -#define IITPlaylist_get_Visible(This,isVisible) \ - (This)->lpVtbl -> get_Visible(This,isVisible) - -#define IITPlaylist_get_Tracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_Tracks(This,iTrackCollection) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_Delete_Proxy( - IITPlaylist * This); - - -void __RPC_STUB IITPlaylist_Delete_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_PlayFirstTrack_Proxy( - IITPlaylist * This); - - -void __RPC_STUB IITPlaylist_PlayFirstTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_Print_Proxy( - IITPlaylist * This, - /* [in] */ VARIANT_BOOL showPrintDialog, - /* [in] */ ITPlaylistPrintKind printKind, - /* [in] */ BSTR theme); - - -void __RPC_STUB IITPlaylist_Print_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_Search_Proxy( - IITPlaylist * This, - /* [in] */ BSTR searchText, - /* [in] */ ITPlaylistSearchField searchFields, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - -void __RPC_STUB IITPlaylist_Search_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Kind_Proxy( - IITPlaylist * This, - /* [retval][out] */ ITPlaylistKind *kind); - - -void __RPC_STUB IITPlaylist_get_Kind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Source_Proxy( - IITPlaylist * This, - /* [retval][out] */ IITSource **iSource); - - -void __RPC_STUB IITPlaylist_get_Source_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Duration_Proxy( - IITPlaylist * This, - /* [retval][out] */ long *duration); - - -void __RPC_STUB IITPlaylist_get_Duration_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Shuffle_Proxy( - IITPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isShuffle); - - -void __RPC_STUB IITPlaylist_get_Shuffle_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITPlaylist_put_Shuffle_Proxy( - IITPlaylist * This, - /* [in] */ VARIANT_BOOL shouldShuffle); - - -void __RPC_STUB IITPlaylist_put_Shuffle_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Size_Proxy( - IITPlaylist * This, - /* [retval][out] */ double *size); - - -void __RPC_STUB IITPlaylist_get_Size_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_SongRepeat_Proxy( - IITPlaylist * This, - /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); - - -void __RPC_STUB IITPlaylist_get_SongRepeat_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITPlaylist_put_SongRepeat_Proxy( - IITPlaylist * This, - /* [in] */ ITPlaylistRepeatMode repeatMode); - - -void __RPC_STUB IITPlaylist_put_SongRepeat_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Time_Proxy( - IITPlaylist * This, - /* [retval][out] */ BSTR *time); - - -void __RPC_STUB IITPlaylist_get_Time_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Visible_Proxy( - IITPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - -void __RPC_STUB IITPlaylist_get_Visible_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Tracks_Proxy( - IITPlaylist * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - -void __RPC_STUB IITPlaylist_get_Tracks_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITPlaylist_INTERFACE_DEFINED__ */ - - -#ifndef __IITOperationStatus_INTERFACE_DEFINED__ -#define __IITOperationStatus_INTERFACE_DEFINED__ - -/* interface IITOperationStatus */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITOperationStatus; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("206479C9-FE32-4f9b-A18A-475AC939B479") - IITOperationStatus : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_InProgress( - /* [retval][out] */ VARIANT_BOOL *isInProgress) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Tracks( - /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITOperationStatusVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITOperationStatus * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITOperationStatus * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITOperationStatus * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITOperationStatus * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITOperationStatus * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITOperationStatus * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITOperationStatus * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InProgress )( - IITOperationStatus * This, - /* [retval][out] */ VARIANT_BOOL *isInProgress); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( - IITOperationStatus * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - END_INTERFACE - } IITOperationStatusVtbl; - - interface IITOperationStatus - { - CONST_VTBL struct IITOperationStatusVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITOperationStatus_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITOperationStatus_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITOperationStatus_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITOperationStatus_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITOperationStatus_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITOperationStatus_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITOperationStatus_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITOperationStatus_get_InProgress(This,isInProgress) \ - (This)->lpVtbl -> get_InProgress(This,isInProgress) - -#define IITOperationStatus_get_Tracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_Tracks(This,iTrackCollection) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITOperationStatus_get_InProgress_Proxy( - IITOperationStatus * This, - /* [retval][out] */ VARIANT_BOOL *isInProgress); - - -void __RPC_STUB IITOperationStatus_get_InProgress_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITOperationStatus_get_Tracks_Proxy( - IITOperationStatus * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - -void __RPC_STUB IITOperationStatus_get_Tracks_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITOperationStatus_INTERFACE_DEFINED__ */ - - -#ifndef __IITConvertOperationStatus_INTERFACE_DEFINED__ -#define __IITConvertOperationStatus_INTERFACE_DEFINED__ - -/* interface IITConvertOperationStatus */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITConvertOperationStatus; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("7063AAF6-ABA0-493b-B4FC-920A9F105875") - IITConvertOperationStatus : public IITOperationStatus - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetConversionStatus( - /* [out] */ BSTR *trackName, - /* [out] */ long *progressValue, - /* [out] */ long *maxProgressValue) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE StopConversion( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackName( - /* [retval][out] */ BSTR *trackName) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ProgressValue( - /* [retval][out] */ long *progressValue) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_MaxProgressValue( - /* [retval][out] */ long *maxProgressValue) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITConvertOperationStatusVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITConvertOperationStatus * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITConvertOperationStatus * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITConvertOperationStatus * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITConvertOperationStatus * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITConvertOperationStatus * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITConvertOperationStatus * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITConvertOperationStatus * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InProgress )( - IITConvertOperationStatus * This, - /* [retval][out] */ VARIANT_BOOL *isInProgress); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( - IITConvertOperationStatus * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetConversionStatus )( - IITConvertOperationStatus * This, - /* [out] */ BSTR *trackName, - /* [out] */ long *progressValue, - /* [out] */ long *maxProgressValue); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *StopConversion )( - IITConvertOperationStatus * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackName )( - IITConvertOperationStatus * This, - /* [retval][out] */ BSTR *trackName); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ProgressValue )( - IITConvertOperationStatus * This, - /* [retval][out] */ long *progressValue); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MaxProgressValue )( - IITConvertOperationStatus * This, - /* [retval][out] */ long *maxProgressValue); - - END_INTERFACE - } IITConvertOperationStatusVtbl; - - interface IITConvertOperationStatus - { - CONST_VTBL struct IITConvertOperationStatusVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITConvertOperationStatus_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITConvertOperationStatus_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITConvertOperationStatus_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITConvertOperationStatus_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITConvertOperationStatus_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITConvertOperationStatus_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITConvertOperationStatus_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITConvertOperationStatus_get_InProgress(This,isInProgress) \ - (This)->lpVtbl -> get_InProgress(This,isInProgress) - -#define IITConvertOperationStatus_get_Tracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_Tracks(This,iTrackCollection) - - -#define IITConvertOperationStatus_GetConversionStatus(This,trackName,progressValue,maxProgressValue) \ - (This)->lpVtbl -> GetConversionStatus(This,trackName,progressValue,maxProgressValue) - -#define IITConvertOperationStatus_StopConversion(This) \ - (This)->lpVtbl -> StopConversion(This) - -#define IITConvertOperationStatus_get_TrackName(This,trackName) \ - (This)->lpVtbl -> get_TrackName(This,trackName) - -#define IITConvertOperationStatus_get_ProgressValue(This,progressValue) \ - (This)->lpVtbl -> get_ProgressValue(This,progressValue) - -#define IITConvertOperationStatus_get_MaxProgressValue(This,maxProgressValue) \ - (This)->lpVtbl -> get_MaxProgressValue(This,maxProgressValue) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_GetConversionStatus_Proxy( - IITConvertOperationStatus * This, - /* [out] */ BSTR *trackName, - /* [out] */ long *progressValue, - /* [out] */ long *maxProgressValue); - - -void __RPC_STUB IITConvertOperationStatus_GetConversionStatus_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_StopConversion_Proxy( - IITConvertOperationStatus * This); - - -void __RPC_STUB IITConvertOperationStatus_StopConversion_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_get_TrackName_Proxy( - IITConvertOperationStatus * This, - /* [retval][out] */ BSTR *trackName); - - -void __RPC_STUB IITConvertOperationStatus_get_TrackName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_get_ProgressValue_Proxy( - IITConvertOperationStatus * This, - /* [retval][out] */ long *progressValue); - - -void __RPC_STUB IITConvertOperationStatus_get_ProgressValue_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_get_MaxProgressValue_Proxy( - IITConvertOperationStatus * This, - /* [retval][out] */ long *maxProgressValue); - - -void __RPC_STUB IITConvertOperationStatus_get_MaxProgressValue_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITConvertOperationStatus_INTERFACE_DEFINED__ */ - - -#ifndef __IITLibraryPlaylist_INTERFACE_DEFINED__ -#define __IITLibraryPlaylist_INTERFACE_DEFINED__ - -/* interface IITLibraryPlaylist */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITLibraryPlaylist; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("53AE1704-491C-4289-94A0-958815675A3D") - IITLibraryPlaylist : public IITPlaylist - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFile( - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFiles( - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddURL( - /* [in] */ BSTR url, - /* [retval][out] */ IITURLTrack **iURLTrack) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddTrack( - /* [in] */ VARIANT *iTrackToAdd, - /* [retval][out] */ IITTrack **iAddedTrack) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITLibraryPlaylistVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITLibraryPlaylist * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITLibraryPlaylist * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITLibraryPlaylist * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITLibraryPlaylist * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITLibraryPlaylist * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITLibraryPlaylist * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITLibraryPlaylist * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITLibraryPlaylist * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITLibraryPlaylist * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITLibraryPlaylist * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITLibraryPlaylist * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITLibraryPlaylist * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITLibraryPlaylist * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITLibraryPlaylist * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITLibraryPlaylist * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITLibraryPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( - IITLibraryPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( - IITLibraryPlaylist * This, - /* [in] */ VARIANT_BOOL showPrintDialog, - /* [in] */ ITPlaylistPrintKind printKind, - /* [in] */ BSTR theme); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( - IITLibraryPlaylist * This, - /* [in] */ BSTR searchText, - /* [in] */ ITPlaylistSearchField searchFields, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITLibraryPlaylist * This, - /* [retval][out] */ ITPlaylistKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( - IITLibraryPlaylist * This, - /* [retval][out] */ IITSource **iSource); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( - IITLibraryPlaylist * This, - /* [retval][out] */ long *duration); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( - IITLibraryPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isShuffle); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( - IITLibraryPlaylist * This, - /* [in] */ VARIANT_BOOL shouldShuffle); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( - IITLibraryPlaylist * This, - /* [retval][out] */ double *size); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( - IITLibraryPlaylist * This, - /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( - IITLibraryPlaylist * This, - /* [in] */ ITPlaylistRepeatMode repeatMode); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( - IITLibraryPlaylist * This, - /* [retval][out] */ BSTR *time); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( - IITLibraryPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( - IITLibraryPlaylist * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFile )( - IITLibraryPlaylist * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFiles )( - IITLibraryPlaylist * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddURL )( - IITLibraryPlaylist * This, - /* [in] */ BSTR url, - /* [retval][out] */ IITURLTrack **iURLTrack); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddTrack )( - IITLibraryPlaylist * This, - /* [in] */ VARIANT *iTrackToAdd, - /* [retval][out] */ IITTrack **iAddedTrack); - - END_INTERFACE - } IITLibraryPlaylistVtbl; - - interface IITLibraryPlaylist - { - CONST_VTBL struct IITLibraryPlaylistVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITLibraryPlaylist_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITLibraryPlaylist_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITLibraryPlaylist_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITLibraryPlaylist_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITLibraryPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITLibraryPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITLibraryPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITLibraryPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITLibraryPlaylist_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITLibraryPlaylist_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITLibraryPlaylist_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITLibraryPlaylist_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITLibraryPlaylist_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITLibraryPlaylist_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITLibraryPlaylist_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITLibraryPlaylist_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITLibraryPlaylist_PlayFirstTrack(This) \ - (This)->lpVtbl -> PlayFirstTrack(This) - -#define IITLibraryPlaylist_Print(This,showPrintDialog,printKind,theme) \ - (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) - -#define IITLibraryPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ - (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) - -#define IITLibraryPlaylist_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITLibraryPlaylist_get_Source(This,iSource) \ - (This)->lpVtbl -> get_Source(This,iSource) - -#define IITLibraryPlaylist_get_Duration(This,duration) \ - (This)->lpVtbl -> get_Duration(This,duration) - -#define IITLibraryPlaylist_get_Shuffle(This,isShuffle) \ - (This)->lpVtbl -> get_Shuffle(This,isShuffle) - -#define IITLibraryPlaylist_put_Shuffle(This,shouldShuffle) \ - (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) - -#define IITLibraryPlaylist_get_Size(This,size) \ - (This)->lpVtbl -> get_Size(This,size) - -#define IITLibraryPlaylist_get_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> get_SongRepeat(This,repeatMode) - -#define IITLibraryPlaylist_put_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> put_SongRepeat(This,repeatMode) - -#define IITLibraryPlaylist_get_Time(This,time) \ - (This)->lpVtbl -> get_Time(This,time) - -#define IITLibraryPlaylist_get_Visible(This,isVisible) \ - (This)->lpVtbl -> get_Visible(This,isVisible) - -#define IITLibraryPlaylist_get_Tracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_Tracks(This,iTrackCollection) - - -#define IITLibraryPlaylist_AddFile(This,filePath,iStatus) \ - (This)->lpVtbl -> AddFile(This,filePath,iStatus) - -#define IITLibraryPlaylist_AddFiles(This,filePaths,iStatus) \ - (This)->lpVtbl -> AddFiles(This,filePaths,iStatus) - -#define IITLibraryPlaylist_AddURL(This,url,iURLTrack) \ - (This)->lpVtbl -> AddURL(This,url,iURLTrack) - -#define IITLibraryPlaylist_AddTrack(This,iTrackToAdd,iAddedTrack) \ - (This)->lpVtbl -> AddTrack(This,iTrackToAdd,iAddedTrack) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddFile_Proxy( - IITLibraryPlaylist * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IITLibraryPlaylist_AddFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddFiles_Proxy( - IITLibraryPlaylist * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IITLibraryPlaylist_AddFiles_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddURL_Proxy( - IITLibraryPlaylist * This, - /* [in] */ BSTR url, - /* [retval][out] */ IITURLTrack **iURLTrack); - - -void __RPC_STUB IITLibraryPlaylist_AddURL_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddTrack_Proxy( - IITLibraryPlaylist * This, - /* [in] */ VARIANT *iTrackToAdd, - /* [retval][out] */ IITTrack **iAddedTrack); - - -void __RPC_STUB IITLibraryPlaylist_AddTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITLibraryPlaylist_INTERFACE_DEFINED__ */ - - -#ifndef __IITUserPlaylist_INTERFACE_DEFINED__ -#define __IITUserPlaylist_INTERFACE_DEFINED__ - -/* interface IITUserPlaylist */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITUserPlaylist; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("0A504DED-A0B5-465a-8A94-50E20D7DF692") - IITUserPlaylist : public IITPlaylist - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFile( - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFiles( - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddURL( - /* [in] */ BSTR url, - /* [retval][out] */ IITURLTrack **iURLTrack) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddTrack( - /* [in] */ VARIANT *iTrackToAdd, - /* [retval][out] */ IITTrack **iAddedTrack) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Shared( - /* [retval][out] */ VARIANT_BOOL *isShared) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Shared( - /* [in] */ VARIANT_BOOL shouldBeShared) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Smart( - /* [retval][out] */ VARIANT_BOOL *isSmart) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SpecialKind( - /* [retval][out] */ ITUserPlaylistSpecialKind *specialKind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Parent( - /* [retval][out] */ IITUserPlaylist **iParentPlayList) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePlaylist( - /* [in] */ BSTR playlistName, - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateFolder( - /* [in] */ BSTR folderName, - /* [retval][out] */ IITPlaylist **iFolder) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Parent( - /* [in] */ VARIANT *iParent) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITUserPlaylistVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITUserPlaylist * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITUserPlaylist * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITUserPlaylist * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITUserPlaylist * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITUserPlaylist * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITUserPlaylist * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITUserPlaylist * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITUserPlaylist * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITUserPlaylist * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITUserPlaylist * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITUserPlaylist * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITUserPlaylist * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITUserPlaylist * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITUserPlaylist * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITUserPlaylist * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITUserPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( - IITUserPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( - IITUserPlaylist * This, - /* [in] */ VARIANT_BOOL showPrintDialog, - /* [in] */ ITPlaylistPrintKind printKind, - /* [in] */ BSTR theme); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( - IITUserPlaylist * This, - /* [in] */ BSTR searchText, - /* [in] */ ITPlaylistSearchField searchFields, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITUserPlaylist * This, - /* [retval][out] */ ITPlaylistKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( - IITUserPlaylist * This, - /* [retval][out] */ IITSource **iSource); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( - IITUserPlaylist * This, - /* [retval][out] */ long *duration); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( - IITUserPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isShuffle); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( - IITUserPlaylist * This, - /* [in] */ VARIANT_BOOL shouldShuffle); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( - IITUserPlaylist * This, - /* [retval][out] */ double *size); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( - IITUserPlaylist * This, - /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( - IITUserPlaylist * This, - /* [in] */ ITPlaylistRepeatMode repeatMode); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( - IITUserPlaylist * This, - /* [retval][out] */ BSTR *time); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( - IITUserPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( - IITUserPlaylist * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFile )( - IITUserPlaylist * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFiles )( - IITUserPlaylist * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddURL )( - IITUserPlaylist * This, - /* [in] */ BSTR url, - /* [retval][out] */ IITURLTrack **iURLTrack); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddTrack )( - IITUserPlaylist * This, - /* [in] */ VARIANT *iTrackToAdd, - /* [retval][out] */ IITTrack **iAddedTrack); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shared )( - IITUserPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isShared); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shared )( - IITUserPlaylist * This, - /* [in] */ VARIANT_BOOL shouldBeShared); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Smart )( - IITUserPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isSmart); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SpecialKind )( - IITUserPlaylist * This, - /* [retval][out] */ ITUserPlaylistSpecialKind *specialKind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Parent )( - IITUserPlaylist * This, - /* [retval][out] */ IITUserPlaylist **iParentPlayList); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreatePlaylist )( - IITUserPlaylist * This, - /* [in] */ BSTR playlistName, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateFolder )( - IITUserPlaylist * This, - /* [in] */ BSTR folderName, - /* [retval][out] */ IITPlaylist **iFolder); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Parent )( - IITUserPlaylist * This, - /* [in] */ VARIANT *iParent); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( - IITUserPlaylist * This); - - END_INTERFACE - } IITUserPlaylistVtbl; - - interface IITUserPlaylist - { - CONST_VTBL struct IITUserPlaylistVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITUserPlaylist_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITUserPlaylist_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITUserPlaylist_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITUserPlaylist_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITUserPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITUserPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITUserPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITUserPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITUserPlaylist_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITUserPlaylist_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITUserPlaylist_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITUserPlaylist_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITUserPlaylist_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITUserPlaylist_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITUserPlaylist_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITUserPlaylist_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITUserPlaylist_PlayFirstTrack(This) \ - (This)->lpVtbl -> PlayFirstTrack(This) - -#define IITUserPlaylist_Print(This,showPrintDialog,printKind,theme) \ - (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) - -#define IITUserPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ - (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) - -#define IITUserPlaylist_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITUserPlaylist_get_Source(This,iSource) \ - (This)->lpVtbl -> get_Source(This,iSource) - -#define IITUserPlaylist_get_Duration(This,duration) \ - (This)->lpVtbl -> get_Duration(This,duration) - -#define IITUserPlaylist_get_Shuffle(This,isShuffle) \ - (This)->lpVtbl -> get_Shuffle(This,isShuffle) - -#define IITUserPlaylist_put_Shuffle(This,shouldShuffle) \ - (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) - -#define IITUserPlaylist_get_Size(This,size) \ - (This)->lpVtbl -> get_Size(This,size) - -#define IITUserPlaylist_get_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> get_SongRepeat(This,repeatMode) - -#define IITUserPlaylist_put_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> put_SongRepeat(This,repeatMode) - -#define IITUserPlaylist_get_Time(This,time) \ - (This)->lpVtbl -> get_Time(This,time) - -#define IITUserPlaylist_get_Visible(This,isVisible) \ - (This)->lpVtbl -> get_Visible(This,isVisible) - -#define IITUserPlaylist_get_Tracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_Tracks(This,iTrackCollection) - - -#define IITUserPlaylist_AddFile(This,filePath,iStatus) \ - (This)->lpVtbl -> AddFile(This,filePath,iStatus) - -#define IITUserPlaylist_AddFiles(This,filePaths,iStatus) \ - (This)->lpVtbl -> AddFiles(This,filePaths,iStatus) - -#define IITUserPlaylist_AddURL(This,url,iURLTrack) \ - (This)->lpVtbl -> AddURL(This,url,iURLTrack) - -#define IITUserPlaylist_AddTrack(This,iTrackToAdd,iAddedTrack) \ - (This)->lpVtbl -> AddTrack(This,iTrackToAdd,iAddedTrack) - -#define IITUserPlaylist_get_Shared(This,isShared) \ - (This)->lpVtbl -> get_Shared(This,isShared) - -#define IITUserPlaylist_put_Shared(This,shouldBeShared) \ - (This)->lpVtbl -> put_Shared(This,shouldBeShared) - -#define IITUserPlaylist_get_Smart(This,isSmart) \ - (This)->lpVtbl -> get_Smart(This,isSmart) - -#define IITUserPlaylist_get_SpecialKind(This,specialKind) \ - (This)->lpVtbl -> get_SpecialKind(This,specialKind) - -#define IITUserPlaylist_get_Parent(This,iParentPlayList) \ - (This)->lpVtbl -> get_Parent(This,iParentPlayList) - -#define IITUserPlaylist_CreatePlaylist(This,playlistName,iPlaylist) \ - (This)->lpVtbl -> CreatePlaylist(This,playlistName,iPlaylist) - -#define IITUserPlaylist_CreateFolder(This,folderName,iFolder) \ - (This)->lpVtbl -> CreateFolder(This,folderName,iFolder) - -#define IITUserPlaylist_put_Parent(This,iParent) \ - (This)->lpVtbl -> put_Parent(This,iParent) - -#define IITUserPlaylist_Reveal(This) \ - (This)->lpVtbl -> Reveal(This) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddFile_Proxy( - IITUserPlaylist * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IITUserPlaylist_AddFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddFiles_Proxy( - IITUserPlaylist * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IITUserPlaylist_AddFiles_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddURL_Proxy( - IITUserPlaylist * This, - /* [in] */ BSTR url, - /* [retval][out] */ IITURLTrack **iURLTrack); - - -void __RPC_STUB IITUserPlaylist_AddURL_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddTrack_Proxy( - IITUserPlaylist * This, - /* [in] */ VARIANT *iTrackToAdd, - /* [retval][out] */ IITTrack **iAddedTrack); - - -void __RPC_STUB IITUserPlaylist_AddTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_Shared_Proxy( - IITUserPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isShared); - - -void __RPC_STUB IITUserPlaylist_get_Shared_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_put_Shared_Proxy( - IITUserPlaylist * This, - /* [in] */ VARIANT_BOOL shouldBeShared); - - -void __RPC_STUB IITUserPlaylist_put_Shared_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_Smart_Proxy( - IITUserPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isSmart); - - -void __RPC_STUB IITUserPlaylist_get_Smart_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_SpecialKind_Proxy( - IITUserPlaylist * This, - /* [retval][out] */ ITUserPlaylistSpecialKind *specialKind); - - -void __RPC_STUB IITUserPlaylist_get_SpecialKind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_Parent_Proxy( - IITUserPlaylist * This, - /* [retval][out] */ IITUserPlaylist **iParentPlayList); - - -void __RPC_STUB IITUserPlaylist_get_Parent_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_CreatePlaylist_Proxy( - IITUserPlaylist * This, - /* [in] */ BSTR playlistName, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IITUserPlaylist_CreatePlaylist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_CreateFolder_Proxy( - IITUserPlaylist * This, - /* [in] */ BSTR folderName, - /* [retval][out] */ IITPlaylist **iFolder); - - -void __RPC_STUB IITUserPlaylist_CreateFolder_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_put_Parent_Proxy( - IITUserPlaylist * This, - /* [in] */ VARIANT *iParent); - - -void __RPC_STUB IITUserPlaylist_put_Parent_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_Reveal_Proxy( - IITUserPlaylist * This); - - -void __RPC_STUB IITUserPlaylist_Reveal_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITUserPlaylist_INTERFACE_DEFINED__ */ - - -#ifndef __IITTrack_INTERFACE_DEFINED__ -#define __IITTrack_INTERFACE_DEFINED__ - -/* interface IITTrack */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITTrack; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("4CB0915D-1E54-4727-BAF3-CE6CC9A225A1") - IITTrack : public IITObject - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Play( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddArtworkFromFile( - /* [in] */ BSTR filePath, - /* [retval][out] */ IITArtwork **iArtwork) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( - /* [retval][out] */ ITTrackKind *kind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlist( - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Album( - /* [retval][out] */ BSTR *album) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Album( - /* [in] */ BSTR album) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Artist( - /* [retval][out] */ BSTR *artist) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Artist( - /* [in] */ BSTR artist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BitRate( - /* [retval][out] */ long *bitrate) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BPM( - /* [retval][out] */ long *beatsPerMinute) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_BPM( - /* [in] */ long beatsPerMinute) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Comment( - /* [retval][out] */ BSTR *comment) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Comment( - /* [in] */ BSTR comment) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Compilation( - /* [retval][out] */ VARIANT_BOOL *isCompilation) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Compilation( - /* [in] */ VARIANT_BOOL shouldBeCompilation) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Composer( - /* [retval][out] */ BSTR *composer) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Composer( - /* [in] */ BSTR composer) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DateAdded( - /* [retval][out] */ DATE *dateAdded) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscCount( - /* [retval][out] */ long *discCount) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DiscCount( - /* [in] */ long discCount) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscNumber( - /* [retval][out] */ long *discNumber) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DiscNumber( - /* [in] */ long discNumber) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Duration( - /* [retval][out] */ long *duration) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Enabled( - /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Enabled( - /* [in] */ VARIANT_BOOL shouldBeEnabled) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQ( - /* [retval][out] */ BSTR *eq) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EQ( - /* [in] */ BSTR eq) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Finish( - /* [in] */ long finish) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Finish( - /* [retval][out] */ long *finish) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Genre( - /* [retval][out] */ BSTR *genre) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Genre( - /* [in] */ BSTR genre) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Grouping( - /* [retval][out] */ BSTR *grouping) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Grouping( - /* [in] */ BSTR grouping) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_KindAsString( - /* [retval][out] */ BSTR *kind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ModificationDate( - /* [retval][out] */ DATE *dateModified) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayedCount( - /* [retval][out] */ long *playedCount) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PlayedCount( - /* [in] */ long playedCount) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayedDate( - /* [retval][out] */ DATE *playedDate) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PlayedDate( - /* [in] */ DATE playedDate) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayOrderIndex( - /* [retval][out] */ long *index) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Rating( - /* [retval][out] */ long *rating) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Rating( - /* [in] */ long rating) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SampleRate( - /* [retval][out] */ long *sampleRate) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size( - /* [retval][out] */ long *size) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Start( - /* [retval][out] */ long *start) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Start( - /* [in] */ long start) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Time( - /* [retval][out] */ BSTR *time) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackCount( - /* [retval][out] */ long *trackCount) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_TrackCount( - /* [in] */ long trackCount) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackNumber( - /* [retval][out] */ long *trackNumber) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_TrackNumber( - /* [in] */ long trackNumber) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VolumeAdjustment( - /* [retval][out] */ long *volumeAdjustment) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VolumeAdjustment( - /* [in] */ long volumeAdjustment) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Year( - /* [retval][out] */ long *year) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Year( - /* [in] */ long year) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Artwork( - /* [retval][out] */ IITArtworkCollection **iArtworkCollection) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITTrackVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITTrack * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITTrack * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITTrack * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITTrack * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITTrack * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITTrack * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITTrack * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITTrack * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITTrack * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITTrack * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITTrack * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITTrack * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITTrack * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITTrack * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITTrack * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITTrack * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( - IITTrack * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddArtworkFromFile )( - IITTrack * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITArtwork **iArtwork); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITTrack * This, - /* [retval][out] */ ITTrackKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( - IITTrack * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Album )( - IITTrack * This, - /* [retval][out] */ BSTR *album); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Album )( - IITTrack * This, - /* [in] */ BSTR album); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( - IITTrack * This, - /* [retval][out] */ BSTR *artist); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Artist )( - IITTrack * This, - /* [in] */ BSTR artist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BitRate )( - IITTrack * This, - /* [retval][out] */ long *bitrate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BPM )( - IITTrack * This, - /* [retval][out] */ long *beatsPerMinute); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BPM )( - IITTrack * This, - /* [in] */ long beatsPerMinute); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Comment )( - IITTrack * This, - /* [retval][out] */ BSTR *comment); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Comment )( - IITTrack * This, - /* [in] */ BSTR comment); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( - IITTrack * This, - /* [retval][out] */ VARIANT_BOOL *isCompilation); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Compilation )( - IITTrack * This, - /* [in] */ VARIANT_BOOL shouldBeCompilation); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( - IITTrack * This, - /* [retval][out] */ BSTR *composer); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Composer )( - IITTrack * This, - /* [in] */ BSTR composer); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DateAdded )( - IITTrack * This, - /* [retval][out] */ DATE *dateAdded); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( - IITTrack * This, - /* [retval][out] */ long *discCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscCount )( - IITTrack * This, - /* [in] */ long discCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( - IITTrack * This, - /* [retval][out] */ long *discNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscNumber )( - IITTrack * This, - /* [in] */ long discNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( - IITTrack * This, - /* [retval][out] */ long *duration); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Enabled )( - IITTrack * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Enabled )( - IITTrack * This, - /* [in] */ VARIANT_BOOL shouldBeEnabled); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQ )( - IITTrack * This, - /* [retval][out] */ BSTR *eq); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQ )( - IITTrack * This, - /* [in] */ BSTR eq); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Finish )( - IITTrack * This, - /* [in] */ long finish); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Finish )( - IITTrack * This, - /* [retval][out] */ long *finish); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( - IITTrack * This, - /* [retval][out] */ BSTR *genre); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Genre )( - IITTrack * This, - /* [in] */ BSTR genre); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Grouping )( - IITTrack * This, - /* [retval][out] */ BSTR *grouping); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Grouping )( - IITTrack * This, - /* [in] */ BSTR grouping); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_KindAsString )( - IITTrack * This, - /* [retval][out] */ BSTR *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ModificationDate )( - IITTrack * This, - /* [retval][out] */ DATE *dateModified); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedCount )( - IITTrack * This, - /* [retval][out] */ long *playedCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedCount )( - IITTrack * This, - /* [in] */ long playedCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedDate )( - IITTrack * This, - /* [retval][out] */ DATE *playedDate); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedDate )( - IITTrack * This, - /* [in] */ DATE playedDate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayOrderIndex )( - IITTrack * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Rating )( - IITTrack * This, - /* [retval][out] */ long *rating); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Rating )( - IITTrack * This, - /* [in] */ long rating); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SampleRate )( - IITTrack * This, - /* [retval][out] */ long *sampleRate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( - IITTrack * This, - /* [retval][out] */ long *size); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Start )( - IITTrack * This, - /* [retval][out] */ long *start); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Start )( - IITTrack * This, - /* [in] */ long start); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( - IITTrack * This, - /* [retval][out] */ BSTR *time); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackCount )( - IITTrack * This, - /* [retval][out] */ long *trackCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackCount )( - IITTrack * This, - /* [in] */ long trackCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackNumber )( - IITTrack * This, - /* [retval][out] */ long *trackNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackNumber )( - IITTrack * This, - /* [in] */ long trackNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VolumeAdjustment )( - IITTrack * This, - /* [retval][out] */ long *volumeAdjustment); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VolumeAdjustment )( - IITTrack * This, - /* [in] */ long volumeAdjustment); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( - IITTrack * This, - /* [retval][out] */ long *year); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Year )( - IITTrack * This, - /* [in] */ long year); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artwork )( - IITTrack * This, - /* [retval][out] */ IITArtworkCollection **iArtworkCollection); - - END_INTERFACE - } IITTrackVtbl; - - interface IITTrack - { - CONST_VTBL struct IITTrackVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITTrack_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITTrack_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITTrack_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITTrack_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITTrack_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITTrack_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITTrack_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITTrack_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITTrack_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITTrack_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITTrack_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITTrack_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITTrack_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITTrack_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITTrack_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITTrack_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITTrack_Play(This) \ - (This)->lpVtbl -> Play(This) - -#define IITTrack_AddArtworkFromFile(This,filePath,iArtwork) \ - (This)->lpVtbl -> AddArtworkFromFile(This,filePath,iArtwork) - -#define IITTrack_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITTrack_get_Playlist(This,iPlaylist) \ - (This)->lpVtbl -> get_Playlist(This,iPlaylist) - -#define IITTrack_get_Album(This,album) \ - (This)->lpVtbl -> get_Album(This,album) - -#define IITTrack_put_Album(This,album) \ - (This)->lpVtbl -> put_Album(This,album) - -#define IITTrack_get_Artist(This,artist) \ - (This)->lpVtbl -> get_Artist(This,artist) - -#define IITTrack_put_Artist(This,artist) \ - (This)->lpVtbl -> put_Artist(This,artist) - -#define IITTrack_get_BitRate(This,bitrate) \ - (This)->lpVtbl -> get_BitRate(This,bitrate) - -#define IITTrack_get_BPM(This,beatsPerMinute) \ - (This)->lpVtbl -> get_BPM(This,beatsPerMinute) - -#define IITTrack_put_BPM(This,beatsPerMinute) \ - (This)->lpVtbl -> put_BPM(This,beatsPerMinute) - -#define IITTrack_get_Comment(This,comment) \ - (This)->lpVtbl -> get_Comment(This,comment) - -#define IITTrack_put_Comment(This,comment) \ - (This)->lpVtbl -> put_Comment(This,comment) - -#define IITTrack_get_Compilation(This,isCompilation) \ - (This)->lpVtbl -> get_Compilation(This,isCompilation) - -#define IITTrack_put_Compilation(This,shouldBeCompilation) \ - (This)->lpVtbl -> put_Compilation(This,shouldBeCompilation) - -#define IITTrack_get_Composer(This,composer) \ - (This)->lpVtbl -> get_Composer(This,composer) - -#define IITTrack_put_Composer(This,composer) \ - (This)->lpVtbl -> put_Composer(This,composer) - -#define IITTrack_get_DateAdded(This,dateAdded) \ - (This)->lpVtbl -> get_DateAdded(This,dateAdded) - -#define IITTrack_get_DiscCount(This,discCount) \ - (This)->lpVtbl -> get_DiscCount(This,discCount) - -#define IITTrack_put_DiscCount(This,discCount) \ - (This)->lpVtbl -> put_DiscCount(This,discCount) - -#define IITTrack_get_DiscNumber(This,discNumber) \ - (This)->lpVtbl -> get_DiscNumber(This,discNumber) - -#define IITTrack_put_DiscNumber(This,discNumber) \ - (This)->lpVtbl -> put_DiscNumber(This,discNumber) - -#define IITTrack_get_Duration(This,duration) \ - (This)->lpVtbl -> get_Duration(This,duration) - -#define IITTrack_get_Enabled(This,isEnabled) \ - (This)->lpVtbl -> get_Enabled(This,isEnabled) - -#define IITTrack_put_Enabled(This,shouldBeEnabled) \ - (This)->lpVtbl -> put_Enabled(This,shouldBeEnabled) - -#define IITTrack_get_EQ(This,eq) \ - (This)->lpVtbl -> get_EQ(This,eq) - -#define IITTrack_put_EQ(This,eq) \ - (This)->lpVtbl -> put_EQ(This,eq) - -#define IITTrack_put_Finish(This,finish) \ - (This)->lpVtbl -> put_Finish(This,finish) - -#define IITTrack_get_Finish(This,finish) \ - (This)->lpVtbl -> get_Finish(This,finish) - -#define IITTrack_get_Genre(This,genre) \ - (This)->lpVtbl -> get_Genre(This,genre) - -#define IITTrack_put_Genre(This,genre) \ - (This)->lpVtbl -> put_Genre(This,genre) - -#define IITTrack_get_Grouping(This,grouping) \ - (This)->lpVtbl -> get_Grouping(This,grouping) - -#define IITTrack_put_Grouping(This,grouping) \ - (This)->lpVtbl -> put_Grouping(This,grouping) - -#define IITTrack_get_KindAsString(This,kind) \ - (This)->lpVtbl -> get_KindAsString(This,kind) - -#define IITTrack_get_ModificationDate(This,dateModified) \ - (This)->lpVtbl -> get_ModificationDate(This,dateModified) - -#define IITTrack_get_PlayedCount(This,playedCount) \ - (This)->lpVtbl -> get_PlayedCount(This,playedCount) - -#define IITTrack_put_PlayedCount(This,playedCount) \ - (This)->lpVtbl -> put_PlayedCount(This,playedCount) - -#define IITTrack_get_PlayedDate(This,playedDate) \ - (This)->lpVtbl -> get_PlayedDate(This,playedDate) - -#define IITTrack_put_PlayedDate(This,playedDate) \ - (This)->lpVtbl -> put_PlayedDate(This,playedDate) - -#define IITTrack_get_PlayOrderIndex(This,index) \ - (This)->lpVtbl -> get_PlayOrderIndex(This,index) - -#define IITTrack_get_Rating(This,rating) \ - (This)->lpVtbl -> get_Rating(This,rating) - -#define IITTrack_put_Rating(This,rating) \ - (This)->lpVtbl -> put_Rating(This,rating) - -#define IITTrack_get_SampleRate(This,sampleRate) \ - (This)->lpVtbl -> get_SampleRate(This,sampleRate) - -#define IITTrack_get_Size(This,size) \ - (This)->lpVtbl -> get_Size(This,size) - -#define IITTrack_get_Start(This,start) \ - (This)->lpVtbl -> get_Start(This,start) - -#define IITTrack_put_Start(This,start) \ - (This)->lpVtbl -> put_Start(This,start) - -#define IITTrack_get_Time(This,time) \ - (This)->lpVtbl -> get_Time(This,time) - -#define IITTrack_get_TrackCount(This,trackCount) \ - (This)->lpVtbl -> get_TrackCount(This,trackCount) - -#define IITTrack_put_TrackCount(This,trackCount) \ - (This)->lpVtbl -> put_TrackCount(This,trackCount) - -#define IITTrack_get_TrackNumber(This,trackNumber) \ - (This)->lpVtbl -> get_TrackNumber(This,trackNumber) - -#define IITTrack_put_TrackNumber(This,trackNumber) \ - (This)->lpVtbl -> put_TrackNumber(This,trackNumber) - -#define IITTrack_get_VolumeAdjustment(This,volumeAdjustment) \ - (This)->lpVtbl -> get_VolumeAdjustment(This,volumeAdjustment) - -#define IITTrack_put_VolumeAdjustment(This,volumeAdjustment) \ - (This)->lpVtbl -> put_VolumeAdjustment(This,volumeAdjustment) - -#define IITTrack_get_Year(This,year) \ - (This)->lpVtbl -> get_Year(This,year) - -#define IITTrack_put_Year(This,year) \ - (This)->lpVtbl -> put_Year(This,year) - -#define IITTrack_get_Artwork(This,iArtworkCollection) \ - (This)->lpVtbl -> get_Artwork(This,iArtworkCollection) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITTrack_Delete_Proxy( - IITTrack * This); - - -void __RPC_STUB IITTrack_Delete_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITTrack_Play_Proxy( - IITTrack * This); - - -void __RPC_STUB IITTrack_Play_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITTrack_AddArtworkFromFile_Proxy( - IITTrack * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITArtwork **iArtwork); - - -void __RPC_STUB IITTrack_AddArtworkFromFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Kind_Proxy( - IITTrack * This, - /* [retval][out] */ ITTrackKind *kind); - - -void __RPC_STUB IITTrack_get_Kind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Playlist_Proxy( - IITTrack * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IITTrack_get_Playlist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Album_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *album); - - -void __RPC_STUB IITTrack_get_Album_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Album_Proxy( - IITTrack * This, - /* [in] */ BSTR album); - - -void __RPC_STUB IITTrack_put_Album_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Artist_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *artist); - - -void __RPC_STUB IITTrack_get_Artist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Artist_Proxy( - IITTrack * This, - /* [in] */ BSTR artist); - - -void __RPC_STUB IITTrack_put_Artist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_BitRate_Proxy( - IITTrack * This, - /* [retval][out] */ long *bitrate); - - -void __RPC_STUB IITTrack_get_BitRate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_BPM_Proxy( - IITTrack * This, - /* [retval][out] */ long *beatsPerMinute); - - -void __RPC_STUB IITTrack_get_BPM_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_BPM_Proxy( - IITTrack * This, - /* [in] */ long beatsPerMinute); - - -void __RPC_STUB IITTrack_put_BPM_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Comment_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *comment); - - -void __RPC_STUB IITTrack_get_Comment_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Comment_Proxy( - IITTrack * This, - /* [in] */ BSTR comment); - - -void __RPC_STUB IITTrack_put_Comment_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Compilation_Proxy( - IITTrack * This, - /* [retval][out] */ VARIANT_BOOL *isCompilation); - - -void __RPC_STUB IITTrack_get_Compilation_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Compilation_Proxy( - IITTrack * This, - /* [in] */ VARIANT_BOOL shouldBeCompilation); - - -void __RPC_STUB IITTrack_put_Compilation_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Composer_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *composer); - - -void __RPC_STUB IITTrack_get_Composer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Composer_Proxy( - IITTrack * This, - /* [in] */ BSTR composer); - - -void __RPC_STUB IITTrack_put_Composer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_DateAdded_Proxy( - IITTrack * This, - /* [retval][out] */ DATE *dateAdded); - - -void __RPC_STUB IITTrack_get_DateAdded_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_DiscCount_Proxy( - IITTrack * This, - /* [retval][out] */ long *discCount); - - -void __RPC_STUB IITTrack_get_DiscCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_DiscCount_Proxy( - IITTrack * This, - /* [in] */ long discCount); - - -void __RPC_STUB IITTrack_put_DiscCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_DiscNumber_Proxy( - IITTrack * This, - /* [retval][out] */ long *discNumber); - - -void __RPC_STUB IITTrack_get_DiscNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_DiscNumber_Proxy( - IITTrack * This, - /* [in] */ long discNumber); - - -void __RPC_STUB IITTrack_put_DiscNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Duration_Proxy( - IITTrack * This, - /* [retval][out] */ long *duration); - - -void __RPC_STUB IITTrack_get_Duration_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Enabled_Proxy( - IITTrack * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - -void __RPC_STUB IITTrack_get_Enabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Enabled_Proxy( - IITTrack * This, - /* [in] */ VARIANT_BOOL shouldBeEnabled); - - -void __RPC_STUB IITTrack_put_Enabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_EQ_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *eq); - - -void __RPC_STUB IITTrack_get_EQ_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_EQ_Proxy( - IITTrack * This, - /* [in] */ BSTR eq); - - -void __RPC_STUB IITTrack_put_EQ_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Finish_Proxy( - IITTrack * This, - /* [in] */ long finish); - - -void __RPC_STUB IITTrack_put_Finish_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Finish_Proxy( - IITTrack * This, - /* [retval][out] */ long *finish); - - -void __RPC_STUB IITTrack_get_Finish_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Genre_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *genre); - - -void __RPC_STUB IITTrack_get_Genre_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Genre_Proxy( - IITTrack * This, - /* [in] */ BSTR genre); - - -void __RPC_STUB IITTrack_put_Genre_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Grouping_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *grouping); - - -void __RPC_STUB IITTrack_get_Grouping_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Grouping_Proxy( - IITTrack * This, - /* [in] */ BSTR grouping); - - -void __RPC_STUB IITTrack_put_Grouping_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_KindAsString_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *kind); - - -void __RPC_STUB IITTrack_get_KindAsString_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_ModificationDate_Proxy( - IITTrack * This, - /* [retval][out] */ DATE *dateModified); - - -void __RPC_STUB IITTrack_get_ModificationDate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_PlayedCount_Proxy( - IITTrack * This, - /* [retval][out] */ long *playedCount); - - -void __RPC_STUB IITTrack_get_PlayedCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_PlayedCount_Proxy( - IITTrack * This, - /* [in] */ long playedCount); - - -void __RPC_STUB IITTrack_put_PlayedCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_PlayedDate_Proxy( - IITTrack * This, - /* [retval][out] */ DATE *playedDate); - - -void __RPC_STUB IITTrack_get_PlayedDate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_PlayedDate_Proxy( - IITTrack * This, - /* [in] */ DATE playedDate); - - -void __RPC_STUB IITTrack_put_PlayedDate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_PlayOrderIndex_Proxy( - IITTrack * This, - /* [retval][out] */ long *index); - - -void __RPC_STUB IITTrack_get_PlayOrderIndex_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Rating_Proxy( - IITTrack * This, - /* [retval][out] */ long *rating); - - -void __RPC_STUB IITTrack_get_Rating_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Rating_Proxy( - IITTrack * This, - /* [in] */ long rating); - - -void __RPC_STUB IITTrack_put_Rating_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_SampleRate_Proxy( - IITTrack * This, - /* [retval][out] */ long *sampleRate); - - -void __RPC_STUB IITTrack_get_SampleRate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Size_Proxy( - IITTrack * This, - /* [retval][out] */ long *size); - - -void __RPC_STUB IITTrack_get_Size_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Start_Proxy( - IITTrack * This, - /* [retval][out] */ long *start); - - -void __RPC_STUB IITTrack_get_Start_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Start_Proxy( - IITTrack * This, - /* [in] */ long start); - - -void __RPC_STUB IITTrack_put_Start_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Time_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *time); - - -void __RPC_STUB IITTrack_get_Time_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_TrackCount_Proxy( - IITTrack * This, - /* [retval][out] */ long *trackCount); - - -void __RPC_STUB IITTrack_get_TrackCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_TrackCount_Proxy( - IITTrack * This, - /* [in] */ long trackCount); - - -void __RPC_STUB IITTrack_put_TrackCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_TrackNumber_Proxy( - IITTrack * This, - /* [retval][out] */ long *trackNumber); - - -void __RPC_STUB IITTrack_get_TrackNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_TrackNumber_Proxy( - IITTrack * This, - /* [in] */ long trackNumber); - - -void __RPC_STUB IITTrack_put_TrackNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_VolumeAdjustment_Proxy( - IITTrack * This, - /* [retval][out] */ long *volumeAdjustment); - - -void __RPC_STUB IITTrack_get_VolumeAdjustment_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_VolumeAdjustment_Proxy( - IITTrack * This, - /* [in] */ long volumeAdjustment); - - -void __RPC_STUB IITTrack_put_VolumeAdjustment_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Year_Proxy( - IITTrack * This, - /* [retval][out] */ long *year); - - -void __RPC_STUB IITTrack_get_Year_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Year_Proxy( - IITTrack * This, - /* [in] */ long year); - - -void __RPC_STUB IITTrack_put_Year_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Artwork_Proxy( - IITTrack * This, - /* [retval][out] */ IITArtworkCollection **iArtworkCollection); - - -void __RPC_STUB IITTrack_get_Artwork_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITTrack_INTERFACE_DEFINED__ */ - - -#ifndef __IITTrackCollection_INTERFACE_DEFINED__ -#define __IITTrackCollection_INTERFACE_DEFINED__ - -/* interface IITTrackCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITTrackCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("755D76F1-6B85-4ce4-8F5F-F88D9743DCD8") - IITTrackCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITTrack **iTrack) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPlayOrder( - /* [in] */ long index, - /* [retval][out] */ IITTrack **iTrack) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( - /* [in] */ BSTR name, - /* [retval][out] */ IITTrack **iTrack) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPersistentID( - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITTrack **iTrack) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITTrackCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITTrackCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITTrackCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITTrackCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITTrackCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITTrackCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITTrackCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITTrackCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITTrackCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITTrackCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITTrack **iTrack); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPlayOrder )( - IITTrackCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITTrack **iTrack); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( - IITTrackCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITTrack **iTrack); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITTrackCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPersistentID )( - IITTrackCollection * This, - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITTrack **iTrack); - - END_INTERFACE - } IITTrackCollectionVtbl; - - interface IITTrackCollection - { - CONST_VTBL struct IITTrackCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITTrackCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITTrackCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITTrackCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITTrackCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITTrackCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITTrackCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITTrackCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITTrackCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITTrackCollection_get_Item(This,index,iTrack) \ - (This)->lpVtbl -> get_Item(This,index,iTrack) - -#define IITTrackCollection_get_ItemByPlayOrder(This,index,iTrack) \ - (This)->lpVtbl -> get_ItemByPlayOrder(This,index,iTrack) - -#define IITTrackCollection_get_ItemByName(This,name,iTrack) \ - (This)->lpVtbl -> get_ItemByName(This,name,iTrack) - -#define IITTrackCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#define IITTrackCollection_get_ItemByPersistentID(This,highID,lowID,iTrack) \ - (This)->lpVtbl -> get_ItemByPersistentID(This,highID,lowID,iTrack) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_Count_Proxy( - IITTrackCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITTrackCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_Item_Proxy( - IITTrackCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITTrack **iTrack); - - -void __RPC_STUB IITTrackCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_ItemByPlayOrder_Proxy( - IITTrackCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITTrack **iTrack); - - -void __RPC_STUB IITTrackCollection_get_ItemByPlayOrder_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_ItemByName_Proxy( - IITTrackCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITTrack **iTrack); - - -void __RPC_STUB IITTrackCollection_get_ItemByName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get__NewEnum_Proxy( - IITTrackCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITTrackCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_ItemByPersistentID_Proxy( - IITTrackCollection * This, - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITTrack **iTrack); - - -void __RPC_STUB IITTrackCollection_get_ItemByPersistentID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITTrackCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IITVisual_INTERFACE_DEFINED__ -#define __IITVisual_INTERFACE_DEFINED__ - -/* interface IITVisual */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITVisual; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("340F3315-ED72-4c09-9ACF-21EB4BDF9931") - IITVisual : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( - /* [retval][out] */ BSTR *name) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITVisualVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITVisual * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITVisual * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITVisual * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITVisual * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITVisual * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITVisual * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITVisual * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITVisual * This, - /* [retval][out] */ BSTR *name); - - END_INTERFACE - } IITVisualVtbl; - - interface IITVisual - { - CONST_VTBL struct IITVisualVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITVisual_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITVisual_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITVisual_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITVisual_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITVisual_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITVisual_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITVisual_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITVisual_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITVisual_get_Name_Proxy( - IITVisual * This, - /* [retval][out] */ BSTR *name); - - -void __RPC_STUB IITVisual_get_Name_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITVisual_INTERFACE_DEFINED__ */ - - -#ifndef __IITVisualCollection_INTERFACE_DEFINED__ -#define __IITVisualCollection_INTERFACE_DEFINED__ - -/* interface IITVisualCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITVisualCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("88A4CCDD-114F-4043-B69B-84D4E6274957") - IITVisualCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITVisual **iVisual) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( - /* [in] */ BSTR name, - /* [retval][out] */ IITVisual **iVisual) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITVisualCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITVisualCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITVisualCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITVisualCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITVisualCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITVisualCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITVisualCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITVisualCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITVisualCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITVisualCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITVisual **iVisual); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( - IITVisualCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITVisual **iVisual); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITVisualCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - END_INTERFACE - } IITVisualCollectionVtbl; - - interface IITVisualCollection - { - CONST_VTBL struct IITVisualCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITVisualCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITVisualCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITVisualCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITVisualCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITVisualCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITVisualCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITVisualCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITVisualCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITVisualCollection_get_Item(This,index,iVisual) \ - (This)->lpVtbl -> get_Item(This,index,iVisual) - -#define IITVisualCollection_get_ItemByName(This,name,iVisual) \ - (This)->lpVtbl -> get_ItemByName(This,name,iVisual) - -#define IITVisualCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get_Count_Proxy( - IITVisualCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITVisualCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get_Item_Proxy( - IITVisualCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITVisual **iVisual); - - -void __RPC_STUB IITVisualCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get_ItemByName_Proxy( - IITVisualCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITVisual **iVisual); - - -void __RPC_STUB IITVisualCollection_get_ItemByName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get__NewEnum_Proxy( - IITVisualCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITVisualCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITVisualCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IITWindow_INTERFACE_DEFINED__ -#define __IITWindow_INTERFACE_DEFINED__ - -/* interface IITWindow */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITWindow; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("370D7BE0-3A89-4a42-B902-C75FC138BE09") - IITWindow : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( - /* [retval][out] */ BSTR *name) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( - /* [retval][out] */ ITWindowKind *kind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Visible( - /* [retval][out] */ VARIANT_BOOL *isVisible) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Visible( - /* [in] */ VARIANT_BOOL shouldBeVisible) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Resizable( - /* [retval][out] */ VARIANT_BOOL *isResizable) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Minimized( - /* [retval][out] */ VARIANT_BOOL *isMinimized) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Minimized( - /* [in] */ VARIANT_BOOL shouldBeMinimized) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Maximizable( - /* [retval][out] */ VARIANT_BOOL *isMaximizable) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Maximized( - /* [retval][out] */ VARIANT_BOOL *isMaximized) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Maximized( - /* [in] */ VARIANT_BOOL shouldBeMaximized) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Zoomable( - /* [retval][out] */ VARIANT_BOOL *isZoomable) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Zoomed( - /* [retval][out] */ VARIANT_BOOL *isZoomed) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Zoomed( - /* [in] */ VARIANT_BOOL shouldBeZoomed) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Top( - /* [retval][out] */ long *top) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Top( - /* [in] */ long top) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Left( - /* [retval][out] */ long *left) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Left( - /* [in] */ long left) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Bottom( - /* [retval][out] */ long *bottom) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Bottom( - /* [in] */ long bottom) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Right( - /* [retval][out] */ long *right) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Right( - /* [in] */ long right) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Width( - /* [retval][out] */ long *width) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Width( - /* [in] */ long width) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Height( - /* [retval][out] */ long *height) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Height( - /* [in] */ long height) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITWindowVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITWindow * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITWindow * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITWindow * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITWindow * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITWindow * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITWindow * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITWindow * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITWindow * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITWindow * This, - /* [retval][out] */ ITWindowKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Visible )( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeVisible); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Resizable )( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isResizable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Minimized )( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMinimized); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Minimized )( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMinimized); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximizable )( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximizable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximized )( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximized); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Maximized )( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMaximized); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomable )( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomed )( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomed); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Zoomed )( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeZoomed); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )( - IITWindow * This, - /* [retval][out] */ long *top); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Top )( - IITWindow * This, - /* [in] */ long top); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )( - IITWindow * This, - /* [retval][out] */ long *left); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Left )( - IITWindow * This, - /* [in] */ long left); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bottom )( - IITWindow * This, - /* [retval][out] */ long *bottom); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bottom )( - IITWindow * This, - /* [in] */ long bottom); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Right )( - IITWindow * This, - /* [retval][out] */ long *right); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Right )( - IITWindow * This, - /* [in] */ long right); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )( - IITWindow * This, - /* [retval][out] */ long *width); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Width )( - IITWindow * This, - /* [in] */ long width); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )( - IITWindow * This, - /* [retval][out] */ long *height); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Height )( - IITWindow * This, - /* [in] */ long height); - - END_INTERFACE - } IITWindowVtbl; - - interface IITWindow - { - CONST_VTBL struct IITWindowVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITWindow_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITWindow_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITWindow_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITWindow_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITWindow_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITWindow_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITWindow_get_Visible(This,isVisible) \ - (This)->lpVtbl -> get_Visible(This,isVisible) - -#define IITWindow_put_Visible(This,shouldBeVisible) \ - (This)->lpVtbl -> put_Visible(This,shouldBeVisible) - -#define IITWindow_get_Resizable(This,isResizable) \ - (This)->lpVtbl -> get_Resizable(This,isResizable) - -#define IITWindow_get_Minimized(This,isMinimized) \ - (This)->lpVtbl -> get_Minimized(This,isMinimized) - -#define IITWindow_put_Minimized(This,shouldBeMinimized) \ - (This)->lpVtbl -> put_Minimized(This,shouldBeMinimized) - -#define IITWindow_get_Maximizable(This,isMaximizable) \ - (This)->lpVtbl -> get_Maximizable(This,isMaximizable) - -#define IITWindow_get_Maximized(This,isMaximized) \ - (This)->lpVtbl -> get_Maximized(This,isMaximized) - -#define IITWindow_put_Maximized(This,shouldBeMaximized) \ - (This)->lpVtbl -> put_Maximized(This,shouldBeMaximized) - -#define IITWindow_get_Zoomable(This,isZoomable) \ - (This)->lpVtbl -> get_Zoomable(This,isZoomable) - -#define IITWindow_get_Zoomed(This,isZoomed) \ - (This)->lpVtbl -> get_Zoomed(This,isZoomed) - -#define IITWindow_put_Zoomed(This,shouldBeZoomed) \ - (This)->lpVtbl -> put_Zoomed(This,shouldBeZoomed) - -#define IITWindow_get_Top(This,top) \ - (This)->lpVtbl -> get_Top(This,top) - -#define IITWindow_put_Top(This,top) \ - (This)->lpVtbl -> put_Top(This,top) - -#define IITWindow_get_Left(This,left) \ - (This)->lpVtbl -> get_Left(This,left) - -#define IITWindow_put_Left(This,left) \ - (This)->lpVtbl -> put_Left(This,left) - -#define IITWindow_get_Bottom(This,bottom) \ - (This)->lpVtbl -> get_Bottom(This,bottom) - -#define IITWindow_put_Bottom(This,bottom) \ - (This)->lpVtbl -> put_Bottom(This,bottom) - -#define IITWindow_get_Right(This,right) \ - (This)->lpVtbl -> get_Right(This,right) - -#define IITWindow_put_Right(This,right) \ - (This)->lpVtbl -> put_Right(This,right) - -#define IITWindow_get_Width(This,width) \ - (This)->lpVtbl -> get_Width(This,width) - -#define IITWindow_put_Width(This,width) \ - (This)->lpVtbl -> put_Width(This,width) - -#define IITWindow_get_Height(This,height) \ - (This)->lpVtbl -> get_Height(This,height) - -#define IITWindow_put_Height(This,height) \ - (This)->lpVtbl -> put_Height(This,height) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Name_Proxy( - IITWindow * This, - /* [retval][out] */ BSTR *name); - - -void __RPC_STUB IITWindow_get_Name_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Kind_Proxy( - IITWindow * This, - /* [retval][out] */ ITWindowKind *kind); - - -void __RPC_STUB IITWindow_get_Kind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Visible_Proxy( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - -void __RPC_STUB IITWindow_get_Visible_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Visible_Proxy( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeVisible); - - -void __RPC_STUB IITWindow_put_Visible_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Resizable_Proxy( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isResizable); - - -void __RPC_STUB IITWindow_get_Resizable_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Minimized_Proxy( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMinimized); - - -void __RPC_STUB IITWindow_get_Minimized_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Minimized_Proxy( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMinimized); - - -void __RPC_STUB IITWindow_put_Minimized_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Maximizable_Proxy( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximizable); - - -void __RPC_STUB IITWindow_get_Maximizable_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Maximized_Proxy( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximized); - - -void __RPC_STUB IITWindow_get_Maximized_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Maximized_Proxy( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMaximized); - - -void __RPC_STUB IITWindow_put_Maximized_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Zoomable_Proxy( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomable); - - -void __RPC_STUB IITWindow_get_Zoomable_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Zoomed_Proxy( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomed); - - -void __RPC_STUB IITWindow_get_Zoomed_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Zoomed_Proxy( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeZoomed); - - -void __RPC_STUB IITWindow_put_Zoomed_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Top_Proxy( - IITWindow * This, - /* [retval][out] */ long *top); - - -void __RPC_STUB IITWindow_get_Top_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Top_Proxy( - IITWindow * This, - /* [in] */ long top); - - -void __RPC_STUB IITWindow_put_Top_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Left_Proxy( - IITWindow * This, - /* [retval][out] */ long *left); - - -void __RPC_STUB IITWindow_get_Left_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Left_Proxy( - IITWindow * This, - /* [in] */ long left); - - -void __RPC_STUB IITWindow_put_Left_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Bottom_Proxy( - IITWindow * This, - /* [retval][out] */ long *bottom); - - -void __RPC_STUB IITWindow_get_Bottom_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Bottom_Proxy( - IITWindow * This, - /* [in] */ long bottom); - - -void __RPC_STUB IITWindow_put_Bottom_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Right_Proxy( - IITWindow * This, - /* [retval][out] */ long *right); - - -void __RPC_STUB IITWindow_get_Right_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Right_Proxy( - IITWindow * This, - /* [in] */ long right); - - -void __RPC_STUB IITWindow_put_Right_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Width_Proxy( - IITWindow * This, - /* [retval][out] */ long *width); - - -void __RPC_STUB IITWindow_get_Width_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Width_Proxy( - IITWindow * This, - /* [in] */ long width); - - -void __RPC_STUB IITWindow_put_Width_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Height_Proxy( - IITWindow * This, - /* [retval][out] */ long *height); - - -void __RPC_STUB IITWindow_get_Height_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Height_Proxy( - IITWindow * This, - /* [in] */ long height); - - -void __RPC_STUB IITWindow_put_Height_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITWindow_INTERFACE_DEFINED__ */ - - -#ifndef __IITBrowserWindow_INTERFACE_DEFINED__ -#define __IITBrowserWindow_INTERFACE_DEFINED__ - -/* interface IITBrowserWindow */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITBrowserWindow; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("C999F455-C4D5-4aa4-8277-F99753699974") - IITBrowserWindow : public IITWindow - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_MiniPlayer( - /* [retval][out] */ VARIANT_BOOL *isMiniPlayer) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_MiniPlayer( - /* [in] */ VARIANT_BOOL shouldBeMiniPlayer) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedTracks( - /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedPlaylist( - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SelectedPlaylist( - /* [in] */ VARIANT *iPlaylist) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITBrowserWindowVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITBrowserWindow * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITBrowserWindow * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITBrowserWindow * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITBrowserWindow * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITBrowserWindow * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITBrowserWindow * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITBrowserWindow * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITBrowserWindow * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITBrowserWindow * This, - /* [retval][out] */ ITWindowKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Visible )( - IITBrowserWindow * This, - /* [in] */ VARIANT_BOOL shouldBeVisible); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Resizable )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isResizable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Minimized )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMinimized); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Minimized )( - IITBrowserWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMinimized); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximizable )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximizable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximized )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximized); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Maximized )( - IITBrowserWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMaximized); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomable )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomed )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomed); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Zoomed )( - IITBrowserWindow * This, - /* [in] */ VARIANT_BOOL shouldBeZoomed); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )( - IITBrowserWindow * This, - /* [retval][out] */ long *top); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Top )( - IITBrowserWindow * This, - /* [in] */ long top); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )( - IITBrowserWindow * This, - /* [retval][out] */ long *left); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Left )( - IITBrowserWindow * This, - /* [in] */ long left); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bottom )( - IITBrowserWindow * This, - /* [retval][out] */ long *bottom); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bottom )( - IITBrowserWindow * This, - /* [in] */ long bottom); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Right )( - IITBrowserWindow * This, - /* [retval][out] */ long *right); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Right )( - IITBrowserWindow * This, - /* [in] */ long right); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )( - IITBrowserWindow * This, - /* [retval][out] */ long *width); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Width )( - IITBrowserWindow * This, - /* [in] */ long width); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )( - IITBrowserWindow * This, - /* [retval][out] */ long *height); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Height )( - IITBrowserWindow * This, - /* [in] */ long height); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MiniPlayer )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMiniPlayer); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_MiniPlayer )( - IITBrowserWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMiniPlayer); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedTracks )( - IITBrowserWindow * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedPlaylist )( - IITBrowserWindow * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SelectedPlaylist )( - IITBrowserWindow * This, - /* [in] */ VARIANT *iPlaylist); - - END_INTERFACE - } IITBrowserWindowVtbl; - - interface IITBrowserWindow - { - CONST_VTBL struct IITBrowserWindowVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITBrowserWindow_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITBrowserWindow_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITBrowserWindow_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITBrowserWindow_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITBrowserWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITBrowserWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITBrowserWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITBrowserWindow_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITBrowserWindow_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITBrowserWindow_get_Visible(This,isVisible) \ - (This)->lpVtbl -> get_Visible(This,isVisible) - -#define IITBrowserWindow_put_Visible(This,shouldBeVisible) \ - (This)->lpVtbl -> put_Visible(This,shouldBeVisible) - -#define IITBrowserWindow_get_Resizable(This,isResizable) \ - (This)->lpVtbl -> get_Resizable(This,isResizable) - -#define IITBrowserWindow_get_Minimized(This,isMinimized) \ - (This)->lpVtbl -> get_Minimized(This,isMinimized) - -#define IITBrowserWindow_put_Minimized(This,shouldBeMinimized) \ - (This)->lpVtbl -> put_Minimized(This,shouldBeMinimized) - -#define IITBrowserWindow_get_Maximizable(This,isMaximizable) \ - (This)->lpVtbl -> get_Maximizable(This,isMaximizable) - -#define IITBrowserWindow_get_Maximized(This,isMaximized) \ - (This)->lpVtbl -> get_Maximized(This,isMaximized) - -#define IITBrowserWindow_put_Maximized(This,shouldBeMaximized) \ - (This)->lpVtbl -> put_Maximized(This,shouldBeMaximized) - -#define IITBrowserWindow_get_Zoomable(This,isZoomable) \ - (This)->lpVtbl -> get_Zoomable(This,isZoomable) - -#define IITBrowserWindow_get_Zoomed(This,isZoomed) \ - (This)->lpVtbl -> get_Zoomed(This,isZoomed) - -#define IITBrowserWindow_put_Zoomed(This,shouldBeZoomed) \ - (This)->lpVtbl -> put_Zoomed(This,shouldBeZoomed) - -#define IITBrowserWindow_get_Top(This,top) \ - (This)->lpVtbl -> get_Top(This,top) - -#define IITBrowserWindow_put_Top(This,top) \ - (This)->lpVtbl -> put_Top(This,top) - -#define IITBrowserWindow_get_Left(This,left) \ - (This)->lpVtbl -> get_Left(This,left) - -#define IITBrowserWindow_put_Left(This,left) \ - (This)->lpVtbl -> put_Left(This,left) - -#define IITBrowserWindow_get_Bottom(This,bottom) \ - (This)->lpVtbl -> get_Bottom(This,bottom) - -#define IITBrowserWindow_put_Bottom(This,bottom) \ - (This)->lpVtbl -> put_Bottom(This,bottom) - -#define IITBrowserWindow_get_Right(This,right) \ - (This)->lpVtbl -> get_Right(This,right) - -#define IITBrowserWindow_put_Right(This,right) \ - (This)->lpVtbl -> put_Right(This,right) - -#define IITBrowserWindow_get_Width(This,width) \ - (This)->lpVtbl -> get_Width(This,width) - -#define IITBrowserWindow_put_Width(This,width) \ - (This)->lpVtbl -> put_Width(This,width) - -#define IITBrowserWindow_get_Height(This,height) \ - (This)->lpVtbl -> get_Height(This,height) - -#define IITBrowserWindow_put_Height(This,height) \ - (This)->lpVtbl -> put_Height(This,height) - - -#define IITBrowserWindow_get_MiniPlayer(This,isMiniPlayer) \ - (This)->lpVtbl -> get_MiniPlayer(This,isMiniPlayer) - -#define IITBrowserWindow_put_MiniPlayer(This,shouldBeMiniPlayer) \ - (This)->lpVtbl -> put_MiniPlayer(This,shouldBeMiniPlayer) - -#define IITBrowserWindow_get_SelectedTracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_SelectedTracks(This,iTrackCollection) - -#define IITBrowserWindow_get_SelectedPlaylist(This,iPlaylist) \ - (This)->lpVtbl -> get_SelectedPlaylist(This,iPlaylist) - -#define IITBrowserWindow_put_SelectedPlaylist(This,iPlaylist) \ - (This)->lpVtbl -> put_SelectedPlaylist(This,iPlaylist) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_get_MiniPlayer_Proxy( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMiniPlayer); - - -void __RPC_STUB IITBrowserWindow_get_MiniPlayer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_put_MiniPlayer_Proxy( - IITBrowserWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMiniPlayer); - - -void __RPC_STUB IITBrowserWindow_put_MiniPlayer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_get_SelectedTracks_Proxy( - IITBrowserWindow * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - -void __RPC_STUB IITBrowserWindow_get_SelectedTracks_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_get_SelectedPlaylist_Proxy( - IITBrowserWindow * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IITBrowserWindow_get_SelectedPlaylist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_put_SelectedPlaylist_Proxy( - IITBrowserWindow * This, - /* [in] */ VARIANT *iPlaylist); - - -void __RPC_STUB IITBrowserWindow_put_SelectedPlaylist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITBrowserWindow_INTERFACE_DEFINED__ */ - - -#ifndef __IITWindowCollection_INTERFACE_DEFINED__ -#define __IITWindowCollection_INTERFACE_DEFINED__ - -/* interface IITWindowCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITWindowCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("3D8DE381-6C0E-481f-A865-E2385F59FA43") - IITWindowCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITWindow **iWindow) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( - /* [in] */ BSTR name, - /* [retval][out] */ IITWindow **iWindow) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITWindowCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITWindowCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITWindowCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITWindowCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITWindowCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITWindowCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITWindowCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITWindowCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITWindowCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITWindowCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITWindow **iWindow); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( - IITWindowCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITWindow **iWindow); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITWindowCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - END_INTERFACE - } IITWindowCollectionVtbl; - - interface IITWindowCollection - { - CONST_VTBL struct IITWindowCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITWindowCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITWindowCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITWindowCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITWindowCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITWindowCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITWindowCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITWindowCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITWindowCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITWindowCollection_get_Item(This,index,iWindow) \ - (This)->lpVtbl -> get_Item(This,index,iWindow) - -#define IITWindowCollection_get_ItemByName(This,name,iWindow) \ - (This)->lpVtbl -> get_ItemByName(This,name,iWindow) - -#define IITWindowCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get_Count_Proxy( - IITWindowCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITWindowCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get_Item_Proxy( - IITWindowCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITWindow **iWindow); - - -void __RPC_STUB IITWindowCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get_ItemByName_Proxy( - IITWindowCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITWindow **iWindow); - - -void __RPC_STUB IITWindowCollection_get_ItemByName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get__NewEnum_Proxy( - IITWindowCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITWindowCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITWindowCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IiTunes_INTERFACE_DEFINED__ -#define __IiTunes_INTERFACE_DEFINED__ - -/* interface IiTunes */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - - - -EXTERN_C const IID IID_IiTunes; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("9DD6680B-3EDC-40db-A771-E6FE4832E34A") - IiTunes : public IDispatch - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE BackTrack( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE FastForward( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE NextTrack( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Pause( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Play( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayFile( - /* [in] */ BSTR filePath) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayPause( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PreviousTrack( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Resume( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Rewind( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Stop( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFile( - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFiles( - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTrack( - /* [in] */ VARIANT *iTrackToConvert, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTracks( - /* [in] */ VARIANT *iTracksToConvert, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CheckVersion( - /* [in] */ long majorVersion, - /* [in] */ long minorVersion, - /* [retval][out] */ VARIANT_BOOL *isCompatible) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetITObjectByID( - /* [in] */ long sourceID, - /* [in] */ long playlistID, - /* [in] */ long trackID, - /* [in] */ long databaseID, - /* [retval][out] */ IITObject **iObject) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePlaylist( - /* [in] */ BSTR playlistName, - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OpenURL( - /* [in] */ BSTR url) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GotoMusicStoreHomePage( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdateIPod( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Authorize( - /* [in] */ long numElems, - /* [size_is][in] */ VARIANT data[ ], - /* [size_is][in] */ BSTR names[ ]) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Quit( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Sources( - /* [retval][out] */ IITSourceCollection **iSourceCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Encoders( - /* [retval][out] */ IITEncoderCollection **iEncoderCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQPresets( - /* [retval][out] */ IITEQPresetCollection **iEQPresetCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Visuals( - /* [retval][out] */ IITVisualCollection **iVisualCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Windows( - /* [retval][out] */ IITWindowCollection **iWindowCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SoundVolume( - /* [retval][out] */ long *volume) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SoundVolume( - /* [in] */ long volume) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Mute( - /* [retval][out] */ VARIANT_BOOL *isMuted) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Mute( - /* [in] */ VARIANT_BOOL shouldMute) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayerState( - /* [retval][out] */ ITPlayerState *playerState) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayerPosition( - /* [retval][out] */ long *playerPos) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PlayerPosition( - /* [in] */ long playerPos) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentEncoder( - /* [retval][out] */ IITEncoder **iEncoder) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentEncoder( - /* [in] */ IITEncoder *iEncoder) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VisualsEnabled( - /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VisualsEnabled( - /* [in] */ VARIANT_BOOL shouldEnable) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_FullScreenVisuals( - /* [retval][out] */ VARIANT_BOOL *isFullScreen) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_FullScreenVisuals( - /* [in] */ VARIANT_BOOL shouldUseFullScreen) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VisualSize( - /* [retval][out] */ ITVisualSize *visualSize) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VisualSize( - /* [in] */ ITVisualSize visualSize) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentVisual( - /* [retval][out] */ IITVisual **iVisual) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentVisual( - /* [in] */ IITVisual *iVisual) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQEnabled( - /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EQEnabled( - /* [in] */ VARIANT_BOOL shouldEnable) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentEQPreset( - /* [retval][out] */ IITEQPreset **iEQPreset) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentEQPreset( - /* [in] */ IITEQPreset *iEQPreset) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentStreamTitle( - /* [retval][out] */ BSTR *streamTitle) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentStreamURL( - /* [retval][out] */ BSTR *streamURL) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BrowserWindow( - /* [retval][out] */ IITBrowserWindow **iBrowserWindow) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQWindow( - /* [retval][out] */ IITWindow **iEQWindow) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LibrarySource( - /* [retval][out] */ IITSource **iLibrarySource) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LibraryPlaylist( - /* [retval][out] */ IITLibraryPlaylist **iLibraryPlaylist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentTrack( - /* [retval][out] */ IITTrack **iTrack) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentPlaylist( - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedTracks( - /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Version( - /* [retval][out] */ BSTR *version) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetOptions( - /* [in] */ long options) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFile2( - /* [in] */ BSTR filePath, - /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFiles2( - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTrack2( - /* [in] */ VARIANT *iTrackToConvert, - /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTracks2( - /* [in] */ VARIANT *iTracksToConvert, - /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AppCommandMessageProcessingEnabled( - /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AppCommandMessageProcessingEnabled( - /* [in] */ VARIANT_BOOL shouldEnable) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ForceToForegroundOnDialog( - /* [retval][out] */ VARIANT_BOOL *forceToForegroundOnDialog) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_ForceToForegroundOnDialog( - /* [in] */ VARIANT_BOOL forceToForegroundOnDialog) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateEQPreset( - /* [in] */ BSTR eqPresetName, - /* [retval][out] */ IITEQPreset **iEQPreset) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePlaylistInSource( - /* [in] */ BSTR playlistName, - /* [in] */ VARIANT *iSource, - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetPlayerButtonsState( - /* [out] */ VARIANT_BOOL *previousEnabled, - /* [out] */ ITPlayButtonState *playPauseStopState, - /* [out] */ VARIANT_BOOL *nextEnabled) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayerButtonClicked( - /* [in] */ ITPlayerButton playerButton, - /* [in] */ long playerButtonModifierKeys) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CanSetShuffle( - /* [in] */ VARIANT *iPlaylist, - /* [retval][out] */ VARIANT_BOOL *canSetShuffle) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CanSetSongRepeat( - /* [in] */ VARIANT *iPlaylist, - /* [retval][out] */ VARIANT_BOOL *canSetSongRepeat) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ConvertOperationStatus( - /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SubscribeToPodcast( - /* [in] */ BSTR url) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdatePodcastFeeds( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateFolder( - /* [in] */ BSTR folderName, - /* [retval][out] */ IITPlaylist **iFolder) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateFolderInSource( - /* [in] */ BSTR folderName, - /* [in] */ VARIANT *iSource, - /* [retval][out] */ IITPlaylist **iFolder) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SoundVolumeControlEnabled( - /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LibraryXMLPath( - /* [retval][out] */ BSTR *filePath) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ITObjectPersistentIDHigh( - /* [in] */ VARIANT *iObject, - /* [retval][out] */ long *highID) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ITObjectPersistentIDLow( - /* [in] */ VARIANT *iObject, - /* [retval][out] */ long *lowID) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetITObjectPersistentIDs( - /* [in] */ VARIANT *iObject, - /* [out] */ long *highID, - /* [out] */ long *lowID) = 0; - - }; - -#else /* C style interface */ - - typedef struct IiTunesVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IiTunes * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IiTunes * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IiTunes * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IiTunes * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IiTunes * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IiTunes * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IiTunes * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *BackTrack )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *FastForward )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *NextTrack )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Pause )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFile )( - IiTunes * This, - /* [in] */ BSTR filePath); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayPause )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PreviousTrack )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Resume )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Rewind )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Stop )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFile )( - IiTunes * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFiles )( - IiTunes * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTrack )( - IiTunes * This, - /* [in] */ VARIANT *iTrackToConvert, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTracks )( - IiTunes * This, - /* [in] */ VARIANT *iTracksToConvert, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CheckVersion )( - IiTunes * This, - /* [in] */ long majorVersion, - /* [in] */ long minorVersion, - /* [retval][out] */ VARIANT_BOOL *isCompatible); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectByID )( - IiTunes * This, - /* [in] */ long sourceID, - /* [in] */ long playlistID, - /* [in] */ long trackID, - /* [in] */ long databaseID, - /* [retval][out] */ IITObject **iObject); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreatePlaylist )( - IiTunes * This, - /* [in] */ BSTR playlistName, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *OpenURL )( - IiTunes * This, - /* [in] */ BSTR url); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GotoMusicStoreHomePage )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdateIPod )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Authorize )( - IiTunes * This, - /* [in] */ long numElems, - /* [size_is][in] */ VARIANT data[ ], - /* [size_is][in] */ BSTR names[ ]); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Quit )( - IiTunes * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Sources )( - IiTunes * This, - /* [retval][out] */ IITSourceCollection **iSourceCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Encoders )( - IiTunes * This, - /* [retval][out] */ IITEncoderCollection **iEncoderCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQPresets )( - IiTunes * This, - /* [retval][out] */ IITEQPresetCollection **iEQPresetCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visuals )( - IiTunes * This, - /* [retval][out] */ IITVisualCollection **iVisualCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Windows )( - IiTunes * This, - /* [retval][out] */ IITWindowCollection **iWindowCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SoundVolume )( - IiTunes * This, - /* [retval][out] */ long *volume); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SoundVolume )( - IiTunes * This, - /* [in] */ long volume); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Mute )( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isMuted); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Mute )( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldMute); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayerState )( - IiTunes * This, - /* [retval][out] */ ITPlayerState *playerState); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayerPosition )( - IiTunes * This, - /* [retval][out] */ long *playerPos); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayerPosition )( - IiTunes * This, - /* [in] */ long playerPos); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentEncoder )( - IiTunes * This, - /* [retval][out] */ IITEncoder **iEncoder); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_CurrentEncoder )( - IiTunes * This, - /* [in] */ IITEncoder *iEncoder); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VisualsEnabled )( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VisualsEnabled )( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldEnable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_FullScreenVisuals )( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isFullScreen); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_FullScreenVisuals )( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldUseFullScreen); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VisualSize )( - IiTunes * This, - /* [retval][out] */ ITVisualSize *visualSize); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VisualSize )( - IiTunes * This, - /* [in] */ ITVisualSize visualSize); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentVisual )( - IiTunes * This, - /* [retval][out] */ IITVisual **iVisual); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_CurrentVisual )( - IiTunes * This, - /* [in] */ IITVisual *iVisual); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQEnabled )( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQEnabled )( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldEnable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentEQPreset )( - IiTunes * This, - /* [retval][out] */ IITEQPreset **iEQPreset); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_CurrentEQPreset )( - IiTunes * This, - /* [in] */ IITEQPreset *iEQPreset); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentStreamTitle )( - IiTunes * This, - /* [retval][out] */ BSTR *streamTitle); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentStreamURL )( - IiTunes * This, - /* [retval][out] */ BSTR *streamURL); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BrowserWindow )( - IiTunes * This, - /* [retval][out] */ IITBrowserWindow **iBrowserWindow); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQWindow )( - IiTunes * This, - /* [retval][out] */ IITWindow **iEQWindow); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LibrarySource )( - IiTunes * This, - /* [retval][out] */ IITSource **iLibrarySource); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LibraryPlaylist )( - IiTunes * This, - /* [retval][out] */ IITLibraryPlaylist **iLibraryPlaylist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentTrack )( - IiTunes * This, - /* [retval][out] */ IITTrack **iTrack); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentPlaylist )( - IiTunes * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedTracks )( - IiTunes * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Version )( - IiTunes * This, - /* [retval][out] */ BSTR *version); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetOptions )( - IiTunes * This, - /* [in] */ long options); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFile2 )( - IiTunes * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFiles2 )( - IiTunes * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTrack2 )( - IiTunes * This, - /* [in] */ VARIANT *iTrackToConvert, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTracks2 )( - IiTunes * This, - /* [in] */ VARIANT *iTracksToConvert, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AppCommandMessageProcessingEnabled )( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AppCommandMessageProcessingEnabled )( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldEnable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ForceToForegroundOnDialog )( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *forceToForegroundOnDialog); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ForceToForegroundOnDialog )( - IiTunes * This, - /* [in] */ VARIANT_BOOL forceToForegroundOnDialog); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateEQPreset )( - IiTunes * This, - /* [in] */ BSTR eqPresetName, - /* [retval][out] */ IITEQPreset **iEQPreset); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreatePlaylistInSource )( - IiTunes * This, - /* [in] */ BSTR playlistName, - /* [in] */ VARIANT *iSource, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPlayerButtonsState )( - IiTunes * This, - /* [out] */ VARIANT_BOOL *previousEnabled, - /* [out] */ ITPlayButtonState *playPauseStopState, - /* [out] */ VARIANT_BOOL *nextEnabled); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayerButtonClicked )( - IiTunes * This, - /* [in] */ ITPlayerButton playerButton, - /* [in] */ long playerButtonModifierKeys); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanSetShuffle )( - IiTunes * This, - /* [in] */ VARIANT *iPlaylist, - /* [retval][out] */ VARIANT_BOOL *canSetShuffle); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanSetSongRepeat )( - IiTunes * This, - /* [in] */ VARIANT *iPlaylist, - /* [retval][out] */ VARIANT_BOOL *canSetSongRepeat); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ConvertOperationStatus )( - IiTunes * This, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SubscribeToPodcast )( - IiTunes * This, - /* [in] */ BSTR url); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdatePodcastFeeds )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateFolder )( - IiTunes * This, - /* [in] */ BSTR folderName, - /* [retval][out] */ IITPlaylist **iFolder); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateFolderInSource )( - IiTunes * This, - /* [in] */ BSTR folderName, - /* [in] */ VARIANT *iSource, - /* [retval][out] */ IITPlaylist **iFolder); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SoundVolumeControlEnabled )( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LibraryXMLPath )( - IiTunes * This, - /* [retval][out] */ BSTR *filePath); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ITObjectPersistentIDHigh )( - IiTunes * This, - /* [in] */ VARIANT *iObject, - /* [retval][out] */ long *highID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ITObjectPersistentIDLow )( - IiTunes * This, - /* [in] */ VARIANT *iObject, - /* [retval][out] */ long *lowID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectPersistentIDs )( - IiTunes * This, - /* [in] */ VARIANT *iObject, - /* [out] */ long *highID, - /* [out] */ long *lowID); - - END_INTERFACE - } IiTunesVtbl; - - interface IiTunes - { - CONST_VTBL struct IiTunesVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IiTunes_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IiTunes_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IiTunes_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IiTunes_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IiTunes_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IiTunes_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IiTunes_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IiTunes_BackTrack(This) \ - (This)->lpVtbl -> BackTrack(This) - -#define IiTunes_FastForward(This) \ - (This)->lpVtbl -> FastForward(This) - -#define IiTunes_NextTrack(This) \ - (This)->lpVtbl -> NextTrack(This) - -#define IiTunes_Pause(This) \ - (This)->lpVtbl -> Pause(This) - -#define IiTunes_Play(This) \ - (This)->lpVtbl -> Play(This) - -#define IiTunes_PlayFile(This,filePath) \ - (This)->lpVtbl -> PlayFile(This,filePath) - -#define IiTunes_PlayPause(This) \ - (This)->lpVtbl -> PlayPause(This) - -#define IiTunes_PreviousTrack(This) \ - (This)->lpVtbl -> PreviousTrack(This) - -#define IiTunes_Resume(This) \ - (This)->lpVtbl -> Resume(This) - -#define IiTunes_Rewind(This) \ - (This)->lpVtbl -> Rewind(This) - -#define IiTunes_Stop(This) \ - (This)->lpVtbl -> Stop(This) - -#define IiTunes_ConvertFile(This,filePath,iStatus) \ - (This)->lpVtbl -> ConvertFile(This,filePath,iStatus) - -#define IiTunes_ConvertFiles(This,filePaths,iStatus) \ - (This)->lpVtbl -> ConvertFiles(This,filePaths,iStatus) - -#define IiTunes_ConvertTrack(This,iTrackToConvert,iStatus) \ - (This)->lpVtbl -> ConvertTrack(This,iTrackToConvert,iStatus) - -#define IiTunes_ConvertTracks(This,iTracksToConvert,iStatus) \ - (This)->lpVtbl -> ConvertTracks(This,iTracksToConvert,iStatus) - -#define IiTunes_CheckVersion(This,majorVersion,minorVersion,isCompatible) \ - (This)->lpVtbl -> CheckVersion(This,majorVersion,minorVersion,isCompatible) - -#define IiTunes_GetITObjectByID(This,sourceID,playlistID,trackID,databaseID,iObject) \ - (This)->lpVtbl -> GetITObjectByID(This,sourceID,playlistID,trackID,databaseID,iObject) - -#define IiTunes_CreatePlaylist(This,playlistName,iPlaylist) \ - (This)->lpVtbl -> CreatePlaylist(This,playlistName,iPlaylist) - -#define IiTunes_OpenURL(This,url) \ - (This)->lpVtbl -> OpenURL(This,url) - -#define IiTunes_GotoMusicStoreHomePage(This) \ - (This)->lpVtbl -> GotoMusicStoreHomePage(This) - -#define IiTunes_UpdateIPod(This) \ - (This)->lpVtbl -> UpdateIPod(This) - -#define IiTunes_Authorize(This,numElems,data,names) \ - (This)->lpVtbl -> Authorize(This,numElems,data,names) - -#define IiTunes_Quit(This) \ - (This)->lpVtbl -> Quit(This) - -#define IiTunes_get_Sources(This,iSourceCollection) \ - (This)->lpVtbl -> get_Sources(This,iSourceCollection) - -#define IiTunes_get_Encoders(This,iEncoderCollection) \ - (This)->lpVtbl -> get_Encoders(This,iEncoderCollection) - -#define IiTunes_get_EQPresets(This,iEQPresetCollection) \ - (This)->lpVtbl -> get_EQPresets(This,iEQPresetCollection) - -#define IiTunes_get_Visuals(This,iVisualCollection) \ - (This)->lpVtbl -> get_Visuals(This,iVisualCollection) - -#define IiTunes_get_Windows(This,iWindowCollection) \ - (This)->lpVtbl -> get_Windows(This,iWindowCollection) - -#define IiTunes_get_SoundVolume(This,volume) \ - (This)->lpVtbl -> get_SoundVolume(This,volume) - -#define IiTunes_put_SoundVolume(This,volume) \ - (This)->lpVtbl -> put_SoundVolume(This,volume) - -#define IiTunes_get_Mute(This,isMuted) \ - (This)->lpVtbl -> get_Mute(This,isMuted) - -#define IiTunes_put_Mute(This,shouldMute) \ - (This)->lpVtbl -> put_Mute(This,shouldMute) - -#define IiTunes_get_PlayerState(This,playerState) \ - (This)->lpVtbl -> get_PlayerState(This,playerState) - -#define IiTunes_get_PlayerPosition(This,playerPos) \ - (This)->lpVtbl -> get_PlayerPosition(This,playerPos) - -#define IiTunes_put_PlayerPosition(This,playerPos) \ - (This)->lpVtbl -> put_PlayerPosition(This,playerPos) - -#define IiTunes_get_CurrentEncoder(This,iEncoder) \ - (This)->lpVtbl -> get_CurrentEncoder(This,iEncoder) - -#define IiTunes_put_CurrentEncoder(This,iEncoder) \ - (This)->lpVtbl -> put_CurrentEncoder(This,iEncoder) - -#define IiTunes_get_VisualsEnabled(This,isEnabled) \ - (This)->lpVtbl -> get_VisualsEnabled(This,isEnabled) - -#define IiTunes_put_VisualsEnabled(This,shouldEnable) \ - (This)->lpVtbl -> put_VisualsEnabled(This,shouldEnable) - -#define IiTunes_get_FullScreenVisuals(This,isFullScreen) \ - (This)->lpVtbl -> get_FullScreenVisuals(This,isFullScreen) - -#define IiTunes_put_FullScreenVisuals(This,shouldUseFullScreen) \ - (This)->lpVtbl -> put_FullScreenVisuals(This,shouldUseFullScreen) - -#define IiTunes_get_VisualSize(This,visualSize) \ - (This)->lpVtbl -> get_VisualSize(This,visualSize) - -#define IiTunes_put_VisualSize(This,visualSize) \ - (This)->lpVtbl -> put_VisualSize(This,visualSize) - -#define IiTunes_get_CurrentVisual(This,iVisual) \ - (This)->lpVtbl -> get_CurrentVisual(This,iVisual) - -#define IiTunes_put_CurrentVisual(This,iVisual) \ - (This)->lpVtbl -> put_CurrentVisual(This,iVisual) - -#define IiTunes_get_EQEnabled(This,isEnabled) \ - (This)->lpVtbl -> get_EQEnabled(This,isEnabled) - -#define IiTunes_put_EQEnabled(This,shouldEnable) \ - (This)->lpVtbl -> put_EQEnabled(This,shouldEnable) - -#define IiTunes_get_CurrentEQPreset(This,iEQPreset) \ - (This)->lpVtbl -> get_CurrentEQPreset(This,iEQPreset) - -#define IiTunes_put_CurrentEQPreset(This,iEQPreset) \ - (This)->lpVtbl -> put_CurrentEQPreset(This,iEQPreset) - -#define IiTunes_get_CurrentStreamTitle(This,streamTitle) \ - (This)->lpVtbl -> get_CurrentStreamTitle(This,streamTitle) - -#define IiTunes_get_CurrentStreamURL(This,streamURL) \ - (This)->lpVtbl -> get_CurrentStreamURL(This,streamURL) - -#define IiTunes_get_BrowserWindow(This,iBrowserWindow) \ - (This)->lpVtbl -> get_BrowserWindow(This,iBrowserWindow) - -#define IiTunes_get_EQWindow(This,iEQWindow) \ - (This)->lpVtbl -> get_EQWindow(This,iEQWindow) - -#define IiTunes_get_LibrarySource(This,iLibrarySource) \ - (This)->lpVtbl -> get_LibrarySource(This,iLibrarySource) - -#define IiTunes_get_LibraryPlaylist(This,iLibraryPlaylist) \ - (This)->lpVtbl -> get_LibraryPlaylist(This,iLibraryPlaylist) - -#define IiTunes_get_CurrentTrack(This,iTrack) \ - (This)->lpVtbl -> get_CurrentTrack(This,iTrack) - -#define IiTunes_get_CurrentPlaylist(This,iPlaylist) \ - (This)->lpVtbl -> get_CurrentPlaylist(This,iPlaylist) - -#define IiTunes_get_SelectedTracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_SelectedTracks(This,iTrackCollection) - -#define IiTunes_get_Version(This,version) \ - (This)->lpVtbl -> get_Version(This,version) - -#define IiTunes_SetOptions(This,options) \ - (This)->lpVtbl -> SetOptions(This,options) - -#define IiTunes_ConvertFile2(This,filePath,iStatus) \ - (This)->lpVtbl -> ConvertFile2(This,filePath,iStatus) - -#define IiTunes_ConvertFiles2(This,filePaths,iStatus) \ - (This)->lpVtbl -> ConvertFiles2(This,filePaths,iStatus) - -#define IiTunes_ConvertTrack2(This,iTrackToConvert,iStatus) \ - (This)->lpVtbl -> ConvertTrack2(This,iTrackToConvert,iStatus) - -#define IiTunes_ConvertTracks2(This,iTracksToConvert,iStatus) \ - (This)->lpVtbl -> ConvertTracks2(This,iTracksToConvert,iStatus) - -#define IiTunes_get_AppCommandMessageProcessingEnabled(This,isEnabled) \ - (This)->lpVtbl -> get_AppCommandMessageProcessingEnabled(This,isEnabled) - -#define IiTunes_put_AppCommandMessageProcessingEnabled(This,shouldEnable) \ - (This)->lpVtbl -> put_AppCommandMessageProcessingEnabled(This,shouldEnable) - -#define IiTunes_get_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) \ - (This)->lpVtbl -> get_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) - -#define IiTunes_put_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) \ - (This)->lpVtbl -> put_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) - -#define IiTunes_CreateEQPreset(This,eqPresetName,iEQPreset) \ - (This)->lpVtbl -> CreateEQPreset(This,eqPresetName,iEQPreset) - -#define IiTunes_CreatePlaylistInSource(This,playlistName,iSource,iPlaylist) \ - (This)->lpVtbl -> CreatePlaylistInSource(This,playlistName,iSource,iPlaylist) - -#define IiTunes_GetPlayerButtonsState(This,previousEnabled,playPauseStopState,nextEnabled) \ - (This)->lpVtbl -> GetPlayerButtonsState(This,previousEnabled,playPauseStopState,nextEnabled) - -#define IiTunes_PlayerButtonClicked(This,playerButton,playerButtonModifierKeys) \ - (This)->lpVtbl -> PlayerButtonClicked(This,playerButton,playerButtonModifierKeys) - -#define IiTunes_get_CanSetShuffle(This,iPlaylist,canSetShuffle) \ - (This)->lpVtbl -> get_CanSetShuffle(This,iPlaylist,canSetShuffle) - -#define IiTunes_get_CanSetSongRepeat(This,iPlaylist,canSetSongRepeat) \ - (This)->lpVtbl -> get_CanSetSongRepeat(This,iPlaylist,canSetSongRepeat) - -#define IiTunes_get_ConvertOperationStatus(This,iStatus) \ - (This)->lpVtbl -> get_ConvertOperationStatus(This,iStatus) - -#define IiTunes_SubscribeToPodcast(This,url) \ - (This)->lpVtbl -> SubscribeToPodcast(This,url) - -#define IiTunes_UpdatePodcastFeeds(This) \ - (This)->lpVtbl -> UpdatePodcastFeeds(This) - -#define IiTunes_CreateFolder(This,folderName,iFolder) \ - (This)->lpVtbl -> CreateFolder(This,folderName,iFolder) - -#define IiTunes_CreateFolderInSource(This,folderName,iSource,iFolder) \ - (This)->lpVtbl -> CreateFolderInSource(This,folderName,iSource,iFolder) - -#define IiTunes_get_SoundVolumeControlEnabled(This,isEnabled) \ - (This)->lpVtbl -> get_SoundVolumeControlEnabled(This,isEnabled) - -#define IiTunes_get_LibraryXMLPath(This,filePath) \ - (This)->lpVtbl -> get_LibraryXMLPath(This,filePath) - -#define IiTunes_get_ITObjectPersistentIDHigh(This,iObject,highID) \ - (This)->lpVtbl -> get_ITObjectPersistentIDHigh(This,iObject,highID) - -#define IiTunes_get_ITObjectPersistentIDLow(This,iObject,lowID) \ - (This)->lpVtbl -> get_ITObjectPersistentIDLow(This,iObject,lowID) - -#define IiTunes_GetITObjectPersistentIDs(This,iObject,highID,lowID) \ - (This)->lpVtbl -> GetITObjectPersistentIDs(This,iObject,highID,lowID) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_BackTrack_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_BackTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_FastForward_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_FastForward_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_NextTrack_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_NextTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Pause_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_Pause_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Play_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_Play_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PlayFile_Proxy( - IiTunes * This, - /* [in] */ BSTR filePath); - - -void __RPC_STUB IiTunes_PlayFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PlayPause_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_PlayPause_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PreviousTrack_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_PreviousTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Resume_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_Resume_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Rewind_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_Rewind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Stop_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_Stop_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFile_Proxy( - IiTunes * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFiles_Proxy( - IiTunes * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertFiles_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTrack_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iTrackToConvert, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTracks_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iTracksToConvert, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertTracks_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CheckVersion_Proxy( - IiTunes * This, - /* [in] */ long majorVersion, - /* [in] */ long minorVersion, - /* [retval][out] */ VARIANT_BOOL *isCompatible); - - -void __RPC_STUB IiTunes_CheckVersion_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GetITObjectByID_Proxy( - IiTunes * This, - /* [in] */ long sourceID, - /* [in] */ long playlistID, - /* [in] */ long trackID, - /* [in] */ long databaseID, - /* [retval][out] */ IITObject **iObject); - - -void __RPC_STUB IiTunes_GetITObjectByID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreatePlaylist_Proxy( - IiTunes * This, - /* [in] */ BSTR playlistName, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IiTunes_CreatePlaylist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_OpenURL_Proxy( - IiTunes * This, - /* [in] */ BSTR url); - - -void __RPC_STUB IiTunes_OpenURL_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GotoMusicStoreHomePage_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_GotoMusicStoreHomePage_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_UpdateIPod_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_UpdateIPod_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Authorize_Proxy( - IiTunes * This, - /* [in] */ long numElems, - /* [size_is][in] */ VARIANT data[ ], - /* [size_is][in] */ BSTR names[ ]); - - -void __RPC_STUB IiTunes_Authorize_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Quit_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_Quit_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Sources_Proxy( - IiTunes * This, - /* [retval][out] */ IITSourceCollection **iSourceCollection); - - -void __RPC_STUB IiTunes_get_Sources_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Encoders_Proxy( - IiTunes * This, - /* [retval][out] */ IITEncoderCollection **iEncoderCollection); - - -void __RPC_STUB IiTunes_get_Encoders_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_EQPresets_Proxy( - IiTunes * This, - /* [retval][out] */ IITEQPresetCollection **iEQPresetCollection); - - -void __RPC_STUB IiTunes_get_EQPresets_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Visuals_Proxy( - IiTunes * This, - /* [retval][out] */ IITVisualCollection **iVisualCollection); - - -void __RPC_STUB IiTunes_get_Visuals_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Windows_Proxy( - IiTunes * This, - /* [retval][out] */ IITWindowCollection **iWindowCollection); - - -void __RPC_STUB IiTunes_get_Windows_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_SoundVolume_Proxy( - IiTunes * This, - /* [retval][out] */ long *volume); - - -void __RPC_STUB IiTunes_get_SoundVolume_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_SoundVolume_Proxy( - IiTunes * This, - /* [in] */ long volume); - - -void __RPC_STUB IiTunes_put_SoundVolume_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Mute_Proxy( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isMuted); - - -void __RPC_STUB IiTunes_get_Mute_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_Mute_Proxy( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldMute); - - -void __RPC_STUB IiTunes_put_Mute_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_PlayerState_Proxy( - IiTunes * This, - /* [retval][out] */ ITPlayerState *playerState); - - -void __RPC_STUB IiTunes_get_PlayerState_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_PlayerPosition_Proxy( - IiTunes * This, - /* [retval][out] */ long *playerPos); - - -void __RPC_STUB IiTunes_get_PlayerPosition_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_PlayerPosition_Proxy( - IiTunes * This, - /* [in] */ long playerPos); - - -void __RPC_STUB IiTunes_put_PlayerPosition_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentEncoder_Proxy( - IiTunes * This, - /* [retval][out] */ IITEncoder **iEncoder); - - -void __RPC_STUB IiTunes_get_CurrentEncoder_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_CurrentEncoder_Proxy( - IiTunes * This, - /* [in] */ IITEncoder *iEncoder); - - -void __RPC_STUB IiTunes_put_CurrentEncoder_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_VisualsEnabled_Proxy( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - -void __RPC_STUB IiTunes_get_VisualsEnabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_VisualsEnabled_Proxy( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldEnable); - - -void __RPC_STUB IiTunes_put_VisualsEnabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_FullScreenVisuals_Proxy( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isFullScreen); - - -void __RPC_STUB IiTunes_get_FullScreenVisuals_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_FullScreenVisuals_Proxy( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldUseFullScreen); - - -void __RPC_STUB IiTunes_put_FullScreenVisuals_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_VisualSize_Proxy( - IiTunes * This, - /* [retval][out] */ ITVisualSize *visualSize); - - -void __RPC_STUB IiTunes_get_VisualSize_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_VisualSize_Proxy( - IiTunes * This, - /* [in] */ ITVisualSize visualSize); - - -void __RPC_STUB IiTunes_put_VisualSize_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentVisual_Proxy( - IiTunes * This, - /* [retval][out] */ IITVisual **iVisual); - - -void __RPC_STUB IiTunes_get_CurrentVisual_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_CurrentVisual_Proxy( - IiTunes * This, - /* [in] */ IITVisual *iVisual); - - -void __RPC_STUB IiTunes_put_CurrentVisual_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_EQEnabled_Proxy( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - -void __RPC_STUB IiTunes_get_EQEnabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_EQEnabled_Proxy( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldEnable); - - -void __RPC_STUB IiTunes_put_EQEnabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentEQPreset_Proxy( - IiTunes * This, - /* [retval][out] */ IITEQPreset **iEQPreset); - - -void __RPC_STUB IiTunes_get_CurrentEQPreset_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_CurrentEQPreset_Proxy( - IiTunes * This, - /* [in] */ IITEQPreset *iEQPreset); - - -void __RPC_STUB IiTunes_put_CurrentEQPreset_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentStreamTitle_Proxy( - IiTunes * This, - /* [retval][out] */ BSTR *streamTitle); - - -void __RPC_STUB IiTunes_get_CurrentStreamTitle_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentStreamURL_Proxy( - IiTunes * This, - /* [retval][out] */ BSTR *streamURL); - - -void __RPC_STUB IiTunes_get_CurrentStreamURL_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_BrowserWindow_Proxy( - IiTunes * This, - /* [retval][out] */ IITBrowserWindow **iBrowserWindow); - - -void __RPC_STUB IiTunes_get_BrowserWindow_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_EQWindow_Proxy( - IiTunes * This, - /* [retval][out] */ IITWindow **iEQWindow); - - -void __RPC_STUB IiTunes_get_EQWindow_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_LibrarySource_Proxy( - IiTunes * This, - /* [retval][out] */ IITSource **iLibrarySource); - - -void __RPC_STUB IiTunes_get_LibrarySource_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_LibraryPlaylist_Proxy( - IiTunes * This, - /* [retval][out] */ IITLibraryPlaylist **iLibraryPlaylist); - - -void __RPC_STUB IiTunes_get_LibraryPlaylist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentTrack_Proxy( - IiTunes * This, - /* [retval][out] */ IITTrack **iTrack); - - -void __RPC_STUB IiTunes_get_CurrentTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentPlaylist_Proxy( - IiTunes * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IiTunes_get_CurrentPlaylist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_SelectedTracks_Proxy( - IiTunes * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - -void __RPC_STUB IiTunes_get_SelectedTracks_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Version_Proxy( - IiTunes * This, - /* [retval][out] */ BSTR *version); - - -void __RPC_STUB IiTunes_get_Version_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_SetOptions_Proxy( - IiTunes * This, - /* [in] */ long options); - - -void __RPC_STUB IiTunes_SetOptions_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFile2_Proxy( - IiTunes * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertFile2_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFiles2_Proxy( - IiTunes * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertFiles2_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTrack2_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iTrackToConvert, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertTrack2_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTracks2_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iTracksToConvert, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertTracks2_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_AppCommandMessageProcessingEnabled_Proxy( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - -void __RPC_STUB IiTunes_get_AppCommandMessageProcessingEnabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_AppCommandMessageProcessingEnabled_Proxy( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldEnable); - - -void __RPC_STUB IiTunes_put_AppCommandMessageProcessingEnabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ForceToForegroundOnDialog_Proxy( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *forceToForegroundOnDialog); - - -void __RPC_STUB IiTunes_get_ForceToForegroundOnDialog_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_ForceToForegroundOnDialog_Proxy( - IiTunes * This, - /* [in] */ VARIANT_BOOL forceToForegroundOnDialog); - - -void __RPC_STUB IiTunes_put_ForceToForegroundOnDialog_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreateEQPreset_Proxy( - IiTunes * This, - /* [in] */ BSTR eqPresetName, - /* [retval][out] */ IITEQPreset **iEQPreset); - - -void __RPC_STUB IiTunes_CreateEQPreset_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreatePlaylistInSource_Proxy( - IiTunes * This, - /* [in] */ BSTR playlistName, - /* [in] */ VARIANT *iSource, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IiTunes_CreatePlaylistInSource_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GetPlayerButtonsState_Proxy( - IiTunes * This, - /* [out] */ VARIANT_BOOL *previousEnabled, - /* [out] */ ITPlayButtonState *playPauseStopState, - /* [out] */ VARIANT_BOOL *nextEnabled); - - -void __RPC_STUB IiTunes_GetPlayerButtonsState_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PlayerButtonClicked_Proxy( - IiTunes * This, - /* [in] */ ITPlayerButton playerButton, - /* [in] */ long playerButtonModifierKeys); - - -void __RPC_STUB IiTunes_PlayerButtonClicked_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CanSetShuffle_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iPlaylist, - /* [retval][out] */ VARIANT_BOOL *canSetShuffle); - - -void __RPC_STUB IiTunes_get_CanSetShuffle_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CanSetSongRepeat_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iPlaylist, - /* [retval][out] */ VARIANT_BOOL *canSetSongRepeat); - - -void __RPC_STUB IiTunes_get_CanSetSongRepeat_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ConvertOperationStatus_Proxy( - IiTunes * This, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_get_ConvertOperationStatus_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_SubscribeToPodcast_Proxy( - IiTunes * This, - /* [in] */ BSTR url); - - -void __RPC_STUB IiTunes_SubscribeToPodcast_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_UpdatePodcastFeeds_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_UpdatePodcastFeeds_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreateFolder_Proxy( - IiTunes * This, - /* [in] */ BSTR folderName, - /* [retval][out] */ IITPlaylist **iFolder); - - -void __RPC_STUB IiTunes_CreateFolder_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreateFolderInSource_Proxy( - IiTunes * This, - /* [in] */ BSTR folderName, - /* [in] */ VARIANT *iSource, - /* [retval][out] */ IITPlaylist **iFolder); - - -void __RPC_STUB IiTunes_CreateFolderInSource_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_SoundVolumeControlEnabled_Proxy( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - -void __RPC_STUB IiTunes_get_SoundVolumeControlEnabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_LibraryXMLPath_Proxy( - IiTunes * This, - /* [retval][out] */ BSTR *filePath); - - -void __RPC_STUB IiTunes_get_LibraryXMLPath_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ITObjectPersistentIDHigh_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iObject, - /* [retval][out] */ long *highID); - - -void __RPC_STUB IiTunes_get_ITObjectPersistentIDHigh_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ITObjectPersistentIDLow_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iObject, - /* [retval][out] */ long *lowID); - - -void __RPC_STUB IiTunes_get_ITObjectPersistentIDLow_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GetITObjectPersistentIDs_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iObject, - /* [out] */ long *highID, - /* [out] */ long *lowID); - - -void __RPC_STUB IiTunes_GetITObjectPersistentIDs_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IiTunes_INTERFACE_DEFINED__ */ - - -#ifndef ___IiTunesEvents_DISPINTERFACE_DEFINED__ -#define ___IiTunesEvents_DISPINTERFACE_DEFINED__ - -/* dispinterface _IiTunesEvents */ -/* [helpstring][uuid] */ - - -EXTERN_C const IID DIID__IiTunesEvents; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("5846EB78-317E-4b6f-B0C3-11EE8C8FEEF2") - _IiTunesEvents : public IDispatch - { - }; - -#else /* C style interface */ - - typedef struct _IiTunesEventsVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - _IiTunesEvents * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - _IiTunesEvents * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - _IiTunesEvents * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - _IiTunesEvents * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - _IiTunesEvents * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - _IiTunesEvents * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - _IiTunesEvents * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - END_INTERFACE - } _IiTunesEventsVtbl; - - interface _IiTunesEvents - { - CONST_VTBL struct _IiTunesEventsVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define _IiTunesEvents_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define _IiTunesEvents_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define _IiTunesEvents_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define _IiTunesEvents_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define _IiTunesEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define _IiTunesEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define _IiTunesEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - -#endif /* ___IiTunesEvents_DISPINTERFACE_DEFINED__ */ - - -#ifndef ___IITConvertOperationStatusEvents_DISPINTERFACE_DEFINED__ -#define ___IITConvertOperationStatusEvents_DISPINTERFACE_DEFINED__ - -/* dispinterface _IITConvertOperationStatusEvents */ -/* [helpstring][uuid] */ - - -EXTERN_C const IID DIID__IITConvertOperationStatusEvents; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("5C47A705-8E8A-45a1-9EED-71C993F0BF60") - _IITConvertOperationStatusEvents : public IDispatch - { - }; - -#else /* C style interface */ - - typedef struct _IITConvertOperationStatusEventsVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - _IITConvertOperationStatusEvents * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - _IITConvertOperationStatusEvents * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - _IITConvertOperationStatusEvents * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - _IITConvertOperationStatusEvents * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - _IITConvertOperationStatusEvents * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - _IITConvertOperationStatusEvents * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - _IITConvertOperationStatusEvents * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - END_INTERFACE - } _IITConvertOperationStatusEventsVtbl; - - interface _IITConvertOperationStatusEvents - { - CONST_VTBL struct _IITConvertOperationStatusEventsVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define _IITConvertOperationStatusEvents_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define _IITConvertOperationStatusEvents_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define _IITConvertOperationStatusEvents_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define _IITConvertOperationStatusEvents_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define _IITConvertOperationStatusEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define _IITConvertOperationStatusEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define _IITConvertOperationStatusEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - -#endif /* ___IITConvertOperationStatusEvents_DISPINTERFACE_DEFINED__ */ - - -EXTERN_C const CLSID CLSID_iTunesApp; - -#ifdef __cplusplus - -class DECLSPEC_UUID("DC0C2640-1415-4644-875C-6F4D769839BA") -iTunesApp; -#endif - -EXTERN_C const CLSID CLSID_iTunesConvertOperationStatus; - -#ifdef __cplusplus - -class DECLSPEC_UUID("D06596AD-C900-41b2-BC68-1B486450FC56") -iTunesConvertOperationStatus; -#endif - -#ifndef __IITArtwork_INTERFACE_DEFINED__ -#define __IITArtwork_INTERFACE_DEFINED__ - -/* interface IITArtwork */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITArtwork; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("D0A6C1F8-BF3D-4cd8-AC47-FE32BDD17257") - IITArtwork : public IDispatch - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetArtworkFromFile( - /* [in] */ BSTR filePath) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SaveArtworkToFile( - /* [in] */ BSTR filePath) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Format( - /* [retval][out] */ ITArtworkFormat *format) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_IsDownloadedArtwork( - /* [retval][out] */ VARIANT_BOOL *isDownloadedArtwork) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Description( - /* [retval][out] */ BSTR *description) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Description( - /* [in] */ BSTR description) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITArtworkVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITArtwork * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITArtwork * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITArtwork * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITArtwork * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITArtwork * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITArtwork * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITArtwork * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITArtwork * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetArtworkFromFile )( - IITArtwork * This, - /* [in] */ BSTR filePath); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SaveArtworkToFile )( - IITArtwork * This, - /* [in] */ BSTR filePath); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Format )( - IITArtwork * This, - /* [retval][out] */ ITArtworkFormat *format); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsDownloadedArtwork )( - IITArtwork * This, - /* [retval][out] */ VARIANT_BOOL *isDownloadedArtwork); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Description )( - IITArtwork * This, - /* [retval][out] */ BSTR *description); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Description )( - IITArtwork * This, - /* [in] */ BSTR description); - - END_INTERFACE - } IITArtworkVtbl; - - interface IITArtwork - { - CONST_VTBL struct IITArtworkVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITArtwork_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITArtwork_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITArtwork_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITArtwork_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITArtwork_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITArtwork_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITArtwork_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITArtwork_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITArtwork_SetArtworkFromFile(This,filePath) \ - (This)->lpVtbl -> SetArtworkFromFile(This,filePath) - -#define IITArtwork_SaveArtworkToFile(This,filePath) \ - (This)->lpVtbl -> SaveArtworkToFile(This,filePath) - -#define IITArtwork_get_Format(This,format) \ - (This)->lpVtbl -> get_Format(This,format) - -#define IITArtwork_get_IsDownloadedArtwork(This,isDownloadedArtwork) \ - (This)->lpVtbl -> get_IsDownloadedArtwork(This,isDownloadedArtwork) - -#define IITArtwork_get_Description(This,description) \ - (This)->lpVtbl -> get_Description(This,description) - -#define IITArtwork_put_Description(This,description) \ - (This)->lpVtbl -> put_Description(This,description) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITArtwork_Delete_Proxy( - IITArtwork * This); - - -void __RPC_STUB IITArtwork_Delete_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITArtwork_SetArtworkFromFile_Proxy( - IITArtwork * This, - /* [in] */ BSTR filePath); - - -void __RPC_STUB IITArtwork_SetArtworkFromFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITArtwork_SaveArtworkToFile_Proxy( - IITArtwork * This, - /* [in] */ BSTR filePath); - - -void __RPC_STUB IITArtwork_SaveArtworkToFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtwork_get_Format_Proxy( - IITArtwork * This, - /* [retval][out] */ ITArtworkFormat *format); - - -void __RPC_STUB IITArtwork_get_Format_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtwork_get_IsDownloadedArtwork_Proxy( - IITArtwork * This, - /* [retval][out] */ VARIANT_BOOL *isDownloadedArtwork); - - -void __RPC_STUB IITArtwork_get_IsDownloadedArtwork_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtwork_get_Description_Proxy( - IITArtwork * This, - /* [retval][out] */ BSTR *description); - - -void __RPC_STUB IITArtwork_get_Description_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITArtwork_put_Description_Proxy( - IITArtwork * This, - /* [in] */ BSTR description); - - -void __RPC_STUB IITArtwork_put_Description_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITArtwork_INTERFACE_DEFINED__ */ - - -#ifndef __IITArtworkCollection_INTERFACE_DEFINED__ -#define __IITArtworkCollection_INTERFACE_DEFINED__ - -/* interface IITArtworkCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITArtworkCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("BF2742D7-418C-4858-9AF9-2981B062D23E") - IITArtworkCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITArtwork **iArtwork) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITArtworkCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITArtworkCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITArtworkCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITArtworkCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITArtworkCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITArtworkCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITArtworkCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITArtworkCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITArtworkCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITArtworkCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITArtwork **iArtwork); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITArtworkCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - END_INTERFACE - } IITArtworkCollectionVtbl; - - interface IITArtworkCollection - { - CONST_VTBL struct IITArtworkCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITArtworkCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITArtworkCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITArtworkCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITArtworkCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITArtworkCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITArtworkCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITArtworkCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITArtworkCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITArtworkCollection_get_Item(This,index,iArtwork) \ - (This)->lpVtbl -> get_Item(This,index,iArtwork) - -#define IITArtworkCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtworkCollection_get_Count_Proxy( - IITArtworkCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITArtworkCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITArtworkCollection_get_Item_Proxy( - IITArtworkCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITArtwork **iArtwork); - - -void __RPC_STUB IITArtworkCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITArtworkCollection_get__NewEnum_Proxy( - IITArtworkCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITArtworkCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITArtworkCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IITURLTrack_INTERFACE_DEFINED__ -#define __IITURLTrack_INTERFACE_DEFINED__ - -/* interface IITURLTrack */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITURLTrack; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("1116E3B5-29FD-4393-A7BD-454E5E327900") - IITURLTrack : public IITTrack - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_URL( - /* [retval][out] */ BSTR *url) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_URL( - /* [in] */ BSTR url) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Podcast( - /* [retval][out] */ VARIANT_BOOL *isPodcast) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdatePodcastFeed( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE DownloadPodcastEpisode( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Category( - /* [retval][out] */ BSTR *category) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Category( - /* [in] */ BSTR category) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Description( - /* [retval][out] */ BSTR *description) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Description( - /* [in] */ BSTR description) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LongDescription( - /* [retval][out] */ BSTR *longDescription) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_LongDescription( - /* [in] */ BSTR longDescription) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRating( - /* [retval][out] */ long *rating) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AlbumRating( - /* [in] */ long rating) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRatingKind( - /* [retval][out] */ ITRatingKind *ratingKind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RatingKind( - /* [retval][out] */ ITRatingKind *ratingKind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlists( - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITURLTrackVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITURLTrack * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITURLTrack * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITURLTrack * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITURLTrack * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITURLTrack * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITURLTrack * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITURLTrack * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITURLTrack * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITURLTrack * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITURLTrack * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITURLTrack * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITURLTrack * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITURLTrack * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITURLTrack * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITURLTrack * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITURLTrack * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( - IITURLTrack * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddArtworkFromFile )( - IITURLTrack * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITArtwork **iArtwork); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITURLTrack * This, - /* [retval][out] */ ITTrackKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( - IITURLTrack * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Album )( - IITURLTrack * This, - /* [retval][out] */ BSTR *album); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Album )( - IITURLTrack * This, - /* [in] */ BSTR album); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( - IITURLTrack * This, - /* [retval][out] */ BSTR *artist); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Artist )( - IITURLTrack * This, - /* [in] */ BSTR artist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BitRate )( - IITURLTrack * This, - /* [retval][out] */ long *bitrate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BPM )( - IITURLTrack * This, - /* [retval][out] */ long *beatsPerMinute); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BPM )( - IITURLTrack * This, - /* [in] */ long beatsPerMinute); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Comment )( - IITURLTrack * This, - /* [retval][out] */ BSTR *comment); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Comment )( - IITURLTrack * This, - /* [in] */ BSTR comment); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( - IITURLTrack * This, - /* [retval][out] */ VARIANT_BOOL *isCompilation); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Compilation )( - IITURLTrack * This, - /* [in] */ VARIANT_BOOL shouldBeCompilation); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( - IITURLTrack * This, - /* [retval][out] */ BSTR *composer); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Composer )( - IITURLTrack * This, - /* [in] */ BSTR composer); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DateAdded )( - IITURLTrack * This, - /* [retval][out] */ DATE *dateAdded); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( - IITURLTrack * This, - /* [retval][out] */ long *discCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscCount )( - IITURLTrack * This, - /* [in] */ long discCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( - IITURLTrack * This, - /* [retval][out] */ long *discNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscNumber )( - IITURLTrack * This, - /* [in] */ long discNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( - IITURLTrack * This, - /* [retval][out] */ long *duration); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Enabled )( - IITURLTrack * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Enabled )( - IITURLTrack * This, - /* [in] */ VARIANT_BOOL shouldBeEnabled); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQ )( - IITURLTrack * This, - /* [retval][out] */ BSTR *eq); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQ )( - IITURLTrack * This, - /* [in] */ BSTR eq); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Finish )( - IITURLTrack * This, - /* [in] */ long finish); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Finish )( - IITURLTrack * This, - /* [retval][out] */ long *finish); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( - IITURLTrack * This, - /* [retval][out] */ BSTR *genre); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Genre )( - IITURLTrack * This, - /* [in] */ BSTR genre); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Grouping )( - IITURLTrack * This, - /* [retval][out] */ BSTR *grouping); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Grouping )( - IITURLTrack * This, - /* [in] */ BSTR grouping); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_KindAsString )( - IITURLTrack * This, - /* [retval][out] */ BSTR *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ModificationDate )( - IITURLTrack * This, - /* [retval][out] */ DATE *dateModified); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedCount )( - IITURLTrack * This, - /* [retval][out] */ long *playedCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedCount )( - IITURLTrack * This, - /* [in] */ long playedCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedDate )( - IITURLTrack * This, - /* [retval][out] */ DATE *playedDate); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedDate )( - IITURLTrack * This, - /* [in] */ DATE playedDate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayOrderIndex )( - IITURLTrack * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Rating )( - IITURLTrack * This, - /* [retval][out] */ long *rating); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Rating )( - IITURLTrack * This, - /* [in] */ long rating); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SampleRate )( - IITURLTrack * This, - /* [retval][out] */ long *sampleRate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( - IITURLTrack * This, - /* [retval][out] */ long *size); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Start )( - IITURLTrack * This, - /* [retval][out] */ long *start); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Start )( - IITURLTrack * This, - /* [in] */ long start); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( - IITURLTrack * This, - /* [retval][out] */ BSTR *time); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackCount )( - IITURLTrack * This, - /* [retval][out] */ long *trackCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackCount )( - IITURLTrack * This, - /* [in] */ long trackCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackNumber )( - IITURLTrack * This, - /* [retval][out] */ long *trackNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackNumber )( - IITURLTrack * This, - /* [in] */ long trackNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VolumeAdjustment )( - IITURLTrack * This, - /* [retval][out] */ long *volumeAdjustment); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VolumeAdjustment )( - IITURLTrack * This, - /* [in] */ long volumeAdjustment); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( - IITURLTrack * This, - /* [retval][out] */ long *year); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Year )( - IITURLTrack * This, - /* [in] */ long year); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artwork )( - IITURLTrack * This, - /* [retval][out] */ IITArtworkCollection **iArtworkCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_URL )( - IITURLTrack * This, - /* [retval][out] */ BSTR *url); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_URL )( - IITURLTrack * This, - /* [in] */ BSTR url); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Podcast )( - IITURLTrack * This, - /* [retval][out] */ VARIANT_BOOL *isPodcast); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdatePodcastFeed )( - IITURLTrack * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *DownloadPodcastEpisode )( - IITURLTrack * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Category )( - IITURLTrack * This, - /* [retval][out] */ BSTR *category); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Category )( - IITURLTrack * This, - /* [in] */ BSTR category); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Description )( - IITURLTrack * This, - /* [retval][out] */ BSTR *description); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Description )( - IITURLTrack * This, - /* [in] */ BSTR description); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LongDescription )( - IITURLTrack * This, - /* [retval][out] */ BSTR *longDescription); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LongDescription )( - IITURLTrack * This, - /* [in] */ BSTR longDescription); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( - IITURLTrack * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRating )( - IITURLTrack * This, - /* [retval][out] */ long *rating); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AlbumRating )( - IITURLTrack * This, - /* [in] */ long rating); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRatingKind )( - IITURLTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RatingKind )( - IITURLTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( - IITURLTrack * This, - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); - - END_INTERFACE - } IITURLTrackVtbl; - - interface IITURLTrack - { - CONST_VTBL struct IITURLTrackVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITURLTrack_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITURLTrack_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITURLTrack_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITURLTrack_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITURLTrack_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITURLTrack_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITURLTrack_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITURLTrack_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITURLTrack_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITURLTrack_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITURLTrack_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITURLTrack_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITURLTrack_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITURLTrack_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITURLTrack_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITURLTrack_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITURLTrack_Play(This) \ - (This)->lpVtbl -> Play(This) - -#define IITURLTrack_AddArtworkFromFile(This,filePath,iArtwork) \ - (This)->lpVtbl -> AddArtworkFromFile(This,filePath,iArtwork) - -#define IITURLTrack_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITURLTrack_get_Playlist(This,iPlaylist) \ - (This)->lpVtbl -> get_Playlist(This,iPlaylist) - -#define IITURLTrack_get_Album(This,album) \ - (This)->lpVtbl -> get_Album(This,album) - -#define IITURLTrack_put_Album(This,album) \ - (This)->lpVtbl -> put_Album(This,album) - -#define IITURLTrack_get_Artist(This,artist) \ - (This)->lpVtbl -> get_Artist(This,artist) - -#define IITURLTrack_put_Artist(This,artist) \ - (This)->lpVtbl -> put_Artist(This,artist) - -#define IITURLTrack_get_BitRate(This,bitrate) \ - (This)->lpVtbl -> get_BitRate(This,bitrate) - -#define IITURLTrack_get_BPM(This,beatsPerMinute) \ - (This)->lpVtbl -> get_BPM(This,beatsPerMinute) - -#define IITURLTrack_put_BPM(This,beatsPerMinute) \ - (This)->lpVtbl -> put_BPM(This,beatsPerMinute) - -#define IITURLTrack_get_Comment(This,comment) \ - (This)->lpVtbl -> get_Comment(This,comment) - -#define IITURLTrack_put_Comment(This,comment) \ - (This)->lpVtbl -> put_Comment(This,comment) - -#define IITURLTrack_get_Compilation(This,isCompilation) \ - (This)->lpVtbl -> get_Compilation(This,isCompilation) - -#define IITURLTrack_put_Compilation(This,shouldBeCompilation) \ - (This)->lpVtbl -> put_Compilation(This,shouldBeCompilation) - -#define IITURLTrack_get_Composer(This,composer) \ - (This)->lpVtbl -> get_Composer(This,composer) - -#define IITURLTrack_put_Composer(This,composer) \ - (This)->lpVtbl -> put_Composer(This,composer) - -#define IITURLTrack_get_DateAdded(This,dateAdded) \ - (This)->lpVtbl -> get_DateAdded(This,dateAdded) - -#define IITURLTrack_get_DiscCount(This,discCount) \ - (This)->lpVtbl -> get_DiscCount(This,discCount) - -#define IITURLTrack_put_DiscCount(This,discCount) \ - (This)->lpVtbl -> put_DiscCount(This,discCount) - -#define IITURLTrack_get_DiscNumber(This,discNumber) \ - (This)->lpVtbl -> get_DiscNumber(This,discNumber) - -#define IITURLTrack_put_DiscNumber(This,discNumber) \ - (This)->lpVtbl -> put_DiscNumber(This,discNumber) - -#define IITURLTrack_get_Duration(This,duration) \ - (This)->lpVtbl -> get_Duration(This,duration) - -#define IITURLTrack_get_Enabled(This,isEnabled) \ - (This)->lpVtbl -> get_Enabled(This,isEnabled) - -#define IITURLTrack_put_Enabled(This,shouldBeEnabled) \ - (This)->lpVtbl -> put_Enabled(This,shouldBeEnabled) - -#define IITURLTrack_get_EQ(This,eq) \ - (This)->lpVtbl -> get_EQ(This,eq) - -#define IITURLTrack_put_EQ(This,eq) \ - (This)->lpVtbl -> put_EQ(This,eq) - -#define IITURLTrack_put_Finish(This,finish) \ - (This)->lpVtbl -> put_Finish(This,finish) - -#define IITURLTrack_get_Finish(This,finish) \ - (This)->lpVtbl -> get_Finish(This,finish) - -#define IITURLTrack_get_Genre(This,genre) \ - (This)->lpVtbl -> get_Genre(This,genre) - -#define IITURLTrack_put_Genre(This,genre) \ - (This)->lpVtbl -> put_Genre(This,genre) - -#define IITURLTrack_get_Grouping(This,grouping) \ - (This)->lpVtbl -> get_Grouping(This,grouping) - -#define IITURLTrack_put_Grouping(This,grouping) \ - (This)->lpVtbl -> put_Grouping(This,grouping) - -#define IITURLTrack_get_KindAsString(This,kind) \ - (This)->lpVtbl -> get_KindAsString(This,kind) - -#define IITURLTrack_get_ModificationDate(This,dateModified) \ - (This)->lpVtbl -> get_ModificationDate(This,dateModified) - -#define IITURLTrack_get_PlayedCount(This,playedCount) \ - (This)->lpVtbl -> get_PlayedCount(This,playedCount) - -#define IITURLTrack_put_PlayedCount(This,playedCount) \ - (This)->lpVtbl -> put_PlayedCount(This,playedCount) - -#define IITURLTrack_get_PlayedDate(This,playedDate) \ - (This)->lpVtbl -> get_PlayedDate(This,playedDate) - -#define IITURLTrack_put_PlayedDate(This,playedDate) \ - (This)->lpVtbl -> put_PlayedDate(This,playedDate) - -#define IITURLTrack_get_PlayOrderIndex(This,index) \ - (This)->lpVtbl -> get_PlayOrderIndex(This,index) - -#define IITURLTrack_get_Rating(This,rating) \ - (This)->lpVtbl -> get_Rating(This,rating) - -#define IITURLTrack_put_Rating(This,rating) \ - (This)->lpVtbl -> put_Rating(This,rating) - -#define IITURLTrack_get_SampleRate(This,sampleRate) \ - (This)->lpVtbl -> get_SampleRate(This,sampleRate) - -#define IITURLTrack_get_Size(This,size) \ - (This)->lpVtbl -> get_Size(This,size) - -#define IITURLTrack_get_Start(This,start) \ - (This)->lpVtbl -> get_Start(This,start) - -#define IITURLTrack_put_Start(This,start) \ - (This)->lpVtbl -> put_Start(This,start) - -#define IITURLTrack_get_Time(This,time) \ - (This)->lpVtbl -> get_Time(This,time) - -#define IITURLTrack_get_TrackCount(This,trackCount) \ - (This)->lpVtbl -> get_TrackCount(This,trackCount) - -#define IITURLTrack_put_TrackCount(This,trackCount) \ - (This)->lpVtbl -> put_TrackCount(This,trackCount) - -#define IITURLTrack_get_TrackNumber(This,trackNumber) \ - (This)->lpVtbl -> get_TrackNumber(This,trackNumber) - -#define IITURLTrack_put_TrackNumber(This,trackNumber) \ - (This)->lpVtbl -> put_TrackNumber(This,trackNumber) - -#define IITURLTrack_get_VolumeAdjustment(This,volumeAdjustment) \ - (This)->lpVtbl -> get_VolumeAdjustment(This,volumeAdjustment) - -#define IITURLTrack_put_VolumeAdjustment(This,volumeAdjustment) \ - (This)->lpVtbl -> put_VolumeAdjustment(This,volumeAdjustment) - -#define IITURLTrack_get_Year(This,year) \ - (This)->lpVtbl -> get_Year(This,year) - -#define IITURLTrack_put_Year(This,year) \ - (This)->lpVtbl -> put_Year(This,year) - -#define IITURLTrack_get_Artwork(This,iArtworkCollection) \ - (This)->lpVtbl -> get_Artwork(This,iArtworkCollection) - - -#define IITURLTrack_get_URL(This,url) \ - (This)->lpVtbl -> get_URL(This,url) - -#define IITURLTrack_put_URL(This,url) \ - (This)->lpVtbl -> put_URL(This,url) - -#define IITURLTrack_get_Podcast(This,isPodcast) \ - (This)->lpVtbl -> get_Podcast(This,isPodcast) - -#define IITURLTrack_UpdatePodcastFeed(This) \ - (This)->lpVtbl -> UpdatePodcastFeed(This) - -#define IITURLTrack_DownloadPodcastEpisode(This) \ - (This)->lpVtbl -> DownloadPodcastEpisode(This) - -#define IITURLTrack_get_Category(This,category) \ - (This)->lpVtbl -> get_Category(This,category) - -#define IITURLTrack_put_Category(This,category) \ - (This)->lpVtbl -> put_Category(This,category) - -#define IITURLTrack_get_Description(This,description) \ - (This)->lpVtbl -> get_Description(This,description) - -#define IITURLTrack_put_Description(This,description) \ - (This)->lpVtbl -> put_Description(This,description) - -#define IITURLTrack_get_LongDescription(This,longDescription) \ - (This)->lpVtbl -> get_LongDescription(This,longDescription) - -#define IITURLTrack_put_LongDescription(This,longDescription) \ - (This)->lpVtbl -> put_LongDescription(This,longDescription) - -#define IITURLTrack_Reveal(This) \ - (This)->lpVtbl -> Reveal(This) - -#define IITURLTrack_get_AlbumRating(This,rating) \ - (This)->lpVtbl -> get_AlbumRating(This,rating) - -#define IITURLTrack_put_AlbumRating(This,rating) \ - (This)->lpVtbl -> put_AlbumRating(This,rating) - -#define IITURLTrack_get_AlbumRatingKind(This,ratingKind) \ - (This)->lpVtbl -> get_AlbumRatingKind(This,ratingKind) - -#define IITURLTrack_get_RatingKind(This,ratingKind) \ - (This)->lpVtbl -> get_RatingKind(This,ratingKind) - -#define IITURLTrack_get_Playlists(This,iPlaylistCollection) \ - (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_URL_Proxy( - IITURLTrack * This, - /* [retval][out] */ BSTR *url); - - -void __RPC_STUB IITURLTrack_get_URL_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_URL_Proxy( - IITURLTrack * This, - /* [in] */ BSTR url); - - -void __RPC_STUB IITURLTrack_put_URL_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Podcast_Proxy( - IITURLTrack * This, - /* [retval][out] */ VARIANT_BOOL *isPodcast); - - -void __RPC_STUB IITURLTrack_get_Podcast_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITURLTrack_UpdatePodcastFeed_Proxy( - IITURLTrack * This); - - -void __RPC_STUB IITURLTrack_UpdatePodcastFeed_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITURLTrack_DownloadPodcastEpisode_Proxy( - IITURLTrack * This); - - -void __RPC_STUB IITURLTrack_DownloadPodcastEpisode_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Category_Proxy( - IITURLTrack * This, - /* [retval][out] */ BSTR *category); - - -void __RPC_STUB IITURLTrack_get_Category_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_Category_Proxy( - IITURLTrack * This, - /* [in] */ BSTR category); - - -void __RPC_STUB IITURLTrack_put_Category_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Description_Proxy( - IITURLTrack * This, - /* [retval][out] */ BSTR *description); - - -void __RPC_STUB IITURLTrack_get_Description_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_Description_Proxy( - IITURLTrack * This, - /* [in] */ BSTR description); - - -void __RPC_STUB IITURLTrack_put_Description_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_LongDescription_Proxy( - IITURLTrack * This, - /* [retval][out] */ BSTR *longDescription); - - -void __RPC_STUB IITURLTrack_get_LongDescription_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_LongDescription_Proxy( - IITURLTrack * This, - /* [in] */ BSTR longDescription); - - -void __RPC_STUB IITURLTrack_put_LongDescription_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITURLTrack_Reveal_Proxy( - IITURLTrack * This); - - -void __RPC_STUB IITURLTrack_Reveal_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_AlbumRating_Proxy( - IITURLTrack * This, - /* [retval][out] */ long *rating); - - -void __RPC_STUB IITURLTrack_get_AlbumRating_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_AlbumRating_Proxy( - IITURLTrack * This, - /* [in] */ long rating); - - -void __RPC_STUB IITURLTrack_put_AlbumRating_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_AlbumRatingKind_Proxy( - IITURLTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - -void __RPC_STUB IITURLTrack_get_AlbumRatingKind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_RatingKind_Proxy( - IITURLTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - -void __RPC_STUB IITURLTrack_get_RatingKind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Playlists_Proxy( - IITURLTrack * This, - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); - - -void __RPC_STUB IITURLTrack_get_Playlists_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITURLTrack_INTERFACE_DEFINED__ */ - - -#ifndef __IITAudioCDPlaylist_INTERFACE_DEFINED__ -#define __IITAudioCDPlaylist_INTERFACE_DEFINED__ - -/* interface IITAudioCDPlaylist */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITAudioCDPlaylist; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("CF496DF3-0FED-4d7d-9BD8-529B6E8A082E") - IITAudioCDPlaylist : public IITPlaylist - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Artist( - /* [retval][out] */ BSTR *artist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Compilation( - /* [retval][out] */ VARIANT_BOOL *isCompiliation) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Composer( - /* [retval][out] */ BSTR *composer) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscCount( - /* [retval][out] */ long *discCount) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscNumber( - /* [retval][out] */ long *discNumber) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Genre( - /* [retval][out] */ BSTR *genre) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Year( - /* [retval][out] */ long *year) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITAudioCDPlaylistVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITAudioCDPlaylist * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITAudioCDPlaylist * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITAudioCDPlaylist * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITAudioCDPlaylist * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITAudioCDPlaylist * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITAudioCDPlaylist * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITAudioCDPlaylist * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITAudioCDPlaylist * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITAudioCDPlaylist * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITAudioCDPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( - IITAudioCDPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( - IITAudioCDPlaylist * This, - /* [in] */ VARIANT_BOOL showPrintDialog, - /* [in] */ ITPlaylistPrintKind printKind, - /* [in] */ BSTR theme); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( - IITAudioCDPlaylist * This, - /* [in] */ BSTR searchText, - /* [in] */ ITPlaylistSearchField searchFields, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITAudioCDPlaylist * This, - /* [retval][out] */ ITPlaylistKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( - IITAudioCDPlaylist * This, - /* [retval][out] */ IITSource **iSource); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *duration); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( - IITAudioCDPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isShuffle); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( - IITAudioCDPlaylist * This, - /* [in] */ VARIANT_BOOL shouldShuffle); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( - IITAudioCDPlaylist * This, - /* [retval][out] */ double *size); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( - IITAudioCDPlaylist * This, - /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( - IITAudioCDPlaylist * This, - /* [in] */ ITPlaylistRepeatMode repeatMode); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *time); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( - IITAudioCDPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( - IITAudioCDPlaylist * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *artist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( - IITAudioCDPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isCompiliation); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *composer); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *discCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *discNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *genre); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *year); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( - IITAudioCDPlaylist * This); - - END_INTERFACE - } IITAudioCDPlaylistVtbl; - - interface IITAudioCDPlaylist - { - CONST_VTBL struct IITAudioCDPlaylistVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITAudioCDPlaylist_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITAudioCDPlaylist_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITAudioCDPlaylist_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITAudioCDPlaylist_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITAudioCDPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITAudioCDPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITAudioCDPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITAudioCDPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITAudioCDPlaylist_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITAudioCDPlaylist_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITAudioCDPlaylist_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITAudioCDPlaylist_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITAudioCDPlaylist_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITAudioCDPlaylist_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITAudioCDPlaylist_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITAudioCDPlaylist_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITAudioCDPlaylist_PlayFirstTrack(This) \ - (This)->lpVtbl -> PlayFirstTrack(This) - -#define IITAudioCDPlaylist_Print(This,showPrintDialog,printKind,theme) \ - (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) - -#define IITAudioCDPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ - (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) - -#define IITAudioCDPlaylist_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITAudioCDPlaylist_get_Source(This,iSource) \ - (This)->lpVtbl -> get_Source(This,iSource) - -#define IITAudioCDPlaylist_get_Duration(This,duration) \ - (This)->lpVtbl -> get_Duration(This,duration) - -#define IITAudioCDPlaylist_get_Shuffle(This,isShuffle) \ - (This)->lpVtbl -> get_Shuffle(This,isShuffle) - -#define IITAudioCDPlaylist_put_Shuffle(This,shouldShuffle) \ - (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) - -#define IITAudioCDPlaylist_get_Size(This,size) \ - (This)->lpVtbl -> get_Size(This,size) - -#define IITAudioCDPlaylist_get_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> get_SongRepeat(This,repeatMode) - -#define IITAudioCDPlaylist_put_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> put_SongRepeat(This,repeatMode) - -#define IITAudioCDPlaylist_get_Time(This,time) \ - (This)->lpVtbl -> get_Time(This,time) - -#define IITAudioCDPlaylist_get_Visible(This,isVisible) \ - (This)->lpVtbl -> get_Visible(This,isVisible) - -#define IITAudioCDPlaylist_get_Tracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_Tracks(This,iTrackCollection) - - -#define IITAudioCDPlaylist_get_Artist(This,artist) \ - (This)->lpVtbl -> get_Artist(This,artist) - -#define IITAudioCDPlaylist_get_Compilation(This,isCompiliation) \ - (This)->lpVtbl -> get_Compilation(This,isCompiliation) - -#define IITAudioCDPlaylist_get_Composer(This,composer) \ - (This)->lpVtbl -> get_Composer(This,composer) - -#define IITAudioCDPlaylist_get_DiscCount(This,discCount) \ - (This)->lpVtbl -> get_DiscCount(This,discCount) - -#define IITAudioCDPlaylist_get_DiscNumber(This,discNumber) \ - (This)->lpVtbl -> get_DiscNumber(This,discNumber) - -#define IITAudioCDPlaylist_get_Genre(This,genre) \ - (This)->lpVtbl -> get_Genre(This,genre) - -#define IITAudioCDPlaylist_get_Year(This,year) \ - (This)->lpVtbl -> get_Year(This,year) - -#define IITAudioCDPlaylist_Reveal(This) \ - (This)->lpVtbl -> Reveal(This) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Artist_Proxy( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *artist); - - -void __RPC_STUB IITAudioCDPlaylist_get_Artist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Compilation_Proxy( - IITAudioCDPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isCompiliation); - - -void __RPC_STUB IITAudioCDPlaylist_get_Compilation_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Composer_Proxy( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *composer); - - -void __RPC_STUB IITAudioCDPlaylist_get_Composer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_DiscCount_Proxy( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *discCount); - - -void __RPC_STUB IITAudioCDPlaylist_get_DiscCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_DiscNumber_Proxy( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *discNumber); - - -void __RPC_STUB IITAudioCDPlaylist_get_DiscNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Genre_Proxy( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *genre); - - -void __RPC_STUB IITAudioCDPlaylist_get_Genre_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Year_Proxy( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *year); - - -void __RPC_STUB IITAudioCDPlaylist_get_Year_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_Reveal_Proxy( - IITAudioCDPlaylist * This); - - -void __RPC_STUB IITAudioCDPlaylist_Reveal_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITAudioCDPlaylist_INTERFACE_DEFINED__ */ - - -#ifndef __IITPlaylistCollection_INTERFACE_DEFINED__ -#define __IITPlaylistCollection_INTERFACE_DEFINED__ - -/* interface IITPlaylistCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITPlaylistCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("FF194254-909D-4437-9C50-3AAC2AE6305C") - IITPlaylistCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( - /* [in] */ BSTR name, - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPersistentID( - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITPlaylistCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITPlaylistCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITPlaylistCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITPlaylistCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITPlaylistCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITPlaylistCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITPlaylistCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITPlaylistCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITPlaylistCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITPlaylistCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( - IITPlaylistCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITPlaylistCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPersistentID )( - IITPlaylistCollection * This, - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITPlaylist **iPlaylist); - - END_INTERFACE - } IITPlaylistCollectionVtbl; - - interface IITPlaylistCollection - { - CONST_VTBL struct IITPlaylistCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITPlaylistCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITPlaylistCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITPlaylistCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITPlaylistCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITPlaylistCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITPlaylistCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITPlaylistCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITPlaylistCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITPlaylistCollection_get_Item(This,index,iPlaylist) \ - (This)->lpVtbl -> get_Item(This,index,iPlaylist) - -#define IITPlaylistCollection_get_ItemByName(This,name,iPlaylist) \ - (This)->lpVtbl -> get_ItemByName(This,name,iPlaylist) - -#define IITPlaylistCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#define IITPlaylistCollection_get_ItemByPersistentID(This,highID,lowID,iPlaylist) \ - (This)->lpVtbl -> get_ItemByPersistentID(This,highID,lowID,iPlaylist) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_Count_Proxy( - IITPlaylistCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITPlaylistCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_Item_Proxy( - IITPlaylistCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IITPlaylistCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_ItemByName_Proxy( - IITPlaylistCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IITPlaylistCollection_get_ItemByName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get__NewEnum_Proxy( - IITPlaylistCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITPlaylistCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_ItemByPersistentID_Proxy( - IITPlaylistCollection * This, - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IITPlaylistCollection_get_ItemByPersistentID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITPlaylistCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IITIPodSource_INTERFACE_DEFINED__ -#define __IITIPodSource_INTERFACE_DEFINED__ - -/* interface IITIPodSource */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITIPodSource; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("CF4D8ACE-1720-4fb9-B0AE-9877249E89B0") - IITIPodSource : public IITSource - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdateIPod( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE EjectIPod( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SoftwareVersion( - /* [retval][out] */ BSTR *softwareVersion) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITIPodSourceVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITIPodSource * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITIPodSource * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITIPodSource * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITIPodSource * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITIPodSource * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITIPodSource * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITIPodSource * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITIPodSource * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITIPodSource * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITIPodSource * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITIPodSource * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITIPodSource * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITIPodSource * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITIPodSource * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITIPodSource * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITIPodSource * This, - /* [retval][out] */ ITSourceKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Capacity )( - IITIPodSource * This, - /* [retval][out] */ double *capacity); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_FreeSpace )( - IITIPodSource * This, - /* [retval][out] */ double *freespace); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( - IITIPodSource * This, - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdateIPod )( - IITIPodSource * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *EjectIPod )( - IITIPodSource * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SoftwareVersion )( - IITIPodSource * This, - /* [retval][out] */ BSTR *softwareVersion); - - END_INTERFACE - } IITIPodSourceVtbl; - - interface IITIPodSource - { - CONST_VTBL struct IITIPodSourceVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITIPodSource_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITIPodSource_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITIPodSource_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITIPodSource_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITIPodSource_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITIPodSource_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITIPodSource_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITIPodSource_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITIPodSource_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITIPodSource_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITIPodSource_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITIPodSource_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITIPodSource_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITIPodSource_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITIPodSource_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITIPodSource_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITIPodSource_get_Capacity(This,capacity) \ - (This)->lpVtbl -> get_Capacity(This,capacity) - -#define IITIPodSource_get_FreeSpace(This,freespace) \ - (This)->lpVtbl -> get_FreeSpace(This,freespace) - -#define IITIPodSource_get_Playlists(This,iPlaylistCollection) \ - (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) - - -#define IITIPodSource_UpdateIPod(This) \ - (This)->lpVtbl -> UpdateIPod(This) - -#define IITIPodSource_EjectIPod(This) \ - (This)->lpVtbl -> EjectIPod(This) - -#define IITIPodSource_get_SoftwareVersion(This,softwareVersion) \ - (This)->lpVtbl -> get_SoftwareVersion(This,softwareVersion) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITIPodSource_UpdateIPod_Proxy( - IITIPodSource * This); - - -void __RPC_STUB IITIPodSource_UpdateIPod_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITIPodSource_EjectIPod_Proxy( - IITIPodSource * This); - - -void __RPC_STUB IITIPodSource_EjectIPod_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITIPodSource_get_SoftwareVersion_Proxy( - IITIPodSource * This, - /* [retval][out] */ BSTR *softwareVersion); - - -void __RPC_STUB IITIPodSource_get_SoftwareVersion_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITIPodSource_INTERFACE_DEFINED__ */ - - -#ifndef __IITFileOrCDTrack_INTERFACE_DEFINED__ -#define __IITFileOrCDTrack_INTERFACE_DEFINED__ - -/* interface IITFileOrCDTrack */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITFileOrCDTrack; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("00D7FE99-7868-4cc7-AD9E-ACFD70D09566") - IITFileOrCDTrack : public IITTrack - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Location( - /* [retval][out] */ BSTR *location) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdateInfoFromFile( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Podcast( - /* [retval][out] */ VARIANT_BOOL *isPodcast) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdatePodcastFeed( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RememberBookmark( - /* [retval][out] */ VARIANT_BOOL *rememberBookmark) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_RememberBookmark( - /* [in] */ VARIANT_BOOL shouldRememberBookmark) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ExcludeFromShuffle( - /* [retval][out] */ VARIANT_BOOL *excludeFromShuffle) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_ExcludeFromShuffle( - /* [in] */ VARIANT_BOOL shouldExcludeFromShuffle) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Lyrics( - /* [retval][out] */ BSTR *lyrics) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Lyrics( - /* [in] */ BSTR lyrics) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Category( - /* [retval][out] */ BSTR *category) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Category( - /* [in] */ BSTR category) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Description( - /* [retval][out] */ BSTR *description) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Description( - /* [in] */ BSTR description) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LongDescription( - /* [retval][out] */ BSTR *longDescription) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_LongDescription( - /* [in] */ BSTR longDescription) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BookmarkTime( - /* [retval][out] */ long *bookmarkTime) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_BookmarkTime( - /* [in] */ long bookmarkTime) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VideoKind( - /* [retval][out] */ ITVideoKind *videoKind) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VideoKind( - /* [in] */ ITVideoKind videoKind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SkippedCount( - /* [retval][out] */ long *skippedCount) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SkippedCount( - /* [in] */ long skippedCount) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SkippedDate( - /* [retval][out] */ DATE *skippedDate) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SkippedDate( - /* [in] */ DATE skippedDate) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PartOfGaplessAlbum( - /* [retval][out] */ VARIANT_BOOL *partOfGaplessAlbum) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PartOfGaplessAlbum( - /* [in] */ VARIANT_BOOL shouldBePartOfGaplessAlbum) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumArtist( - /* [retval][out] */ BSTR *albumArtist) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AlbumArtist( - /* [in] */ BSTR albumArtist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Show( - /* [retval][out] */ BSTR *showName) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Show( - /* [in] */ BSTR showName) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SeasonNumber( - /* [retval][out] */ long *seasonNumber) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SeasonNumber( - /* [in] */ long seasonNumber) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EpisodeID( - /* [retval][out] */ BSTR *episodeID) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EpisodeID( - /* [in] */ BSTR episodeID) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EpisodeNumber( - /* [retval][out] */ long *episodeNumber) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EpisodeNumber( - /* [in] */ long episodeNumber) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size64High( - /* [retval][out] */ long *sizeHigh) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size64Low( - /* [retval][out] */ long *sizeLow) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Unplayed( - /* [retval][out] */ VARIANT_BOOL *isUnplayed) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Unplayed( - /* [in] */ VARIANT_BOOL shouldBeUnplayed) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortAlbum( - /* [retval][out] */ BSTR *album) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortAlbum( - /* [in] */ BSTR album) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortAlbumArtist( - /* [retval][out] */ BSTR *albumArtist) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortAlbumArtist( - /* [in] */ BSTR albumArtist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortArtist( - /* [retval][out] */ BSTR *artist) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortArtist( - /* [in] */ BSTR artist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortComposer( - /* [retval][out] */ BSTR *composer) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortComposer( - /* [in] */ BSTR composer) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortName( - /* [retval][out] */ BSTR *name) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortName( - /* [in] */ BSTR name) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortShow( - /* [retval][out] */ BSTR *showName) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortShow( - /* [in] */ BSTR showName) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRating( - /* [retval][out] */ long *rating) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AlbumRating( - /* [in] */ long rating) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRatingKind( - /* [retval][out] */ ITRatingKind *ratingKind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RatingKind( - /* [retval][out] */ ITRatingKind *ratingKind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlists( - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Location( - /* [in] */ BSTR location) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ReleaseDate( - /* [retval][out] */ DATE *releaseDate) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITFileOrCDTrackVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITFileOrCDTrack * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITFileOrCDTrack * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITFileOrCDTrack * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITFileOrCDTrack * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITFileOrCDTrack * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITFileOrCDTrack * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITFileOrCDTrack * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITFileOrCDTrack * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITFileOrCDTrack * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITFileOrCDTrack * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( - IITFileOrCDTrack * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddArtworkFromFile )( - IITFileOrCDTrack * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITArtwork **iArtwork); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITFileOrCDTrack * This, - /* [retval][out] */ ITTrackKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( - IITFileOrCDTrack * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Album )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *album); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Album )( - IITFileOrCDTrack * This, - /* [in] */ BSTR album); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *artist); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Artist )( - IITFileOrCDTrack * This, - /* [in] */ BSTR artist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BitRate )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *bitrate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BPM )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *beatsPerMinute); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BPM )( - IITFileOrCDTrack * This, - /* [in] */ long beatsPerMinute); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Comment )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *comment); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Comment )( - IITFileOrCDTrack * This, - /* [in] */ BSTR comment); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *isCompilation); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Compilation )( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldBeCompilation); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *composer); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Composer )( - IITFileOrCDTrack * This, - /* [in] */ BSTR composer); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DateAdded )( - IITFileOrCDTrack * This, - /* [retval][out] */ DATE *dateAdded); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *discCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscCount )( - IITFileOrCDTrack * This, - /* [in] */ long discCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *discNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscNumber )( - IITFileOrCDTrack * This, - /* [in] */ long discNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *duration); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Enabled )( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Enabled )( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldBeEnabled); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQ )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *eq); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQ )( - IITFileOrCDTrack * This, - /* [in] */ BSTR eq); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Finish )( - IITFileOrCDTrack * This, - /* [in] */ long finish); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Finish )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *finish); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *genre); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Genre )( - IITFileOrCDTrack * This, - /* [in] */ BSTR genre); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Grouping )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *grouping); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Grouping )( - IITFileOrCDTrack * This, - /* [in] */ BSTR grouping); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_KindAsString )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ModificationDate )( - IITFileOrCDTrack * This, - /* [retval][out] */ DATE *dateModified); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedCount )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *playedCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedCount )( - IITFileOrCDTrack * This, - /* [in] */ long playedCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedDate )( - IITFileOrCDTrack * This, - /* [retval][out] */ DATE *playedDate); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedDate )( - IITFileOrCDTrack * This, - /* [in] */ DATE playedDate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayOrderIndex )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Rating )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *rating); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Rating )( - IITFileOrCDTrack * This, - /* [in] */ long rating); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SampleRate )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *sampleRate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *size); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Start )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *start); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Start )( - IITFileOrCDTrack * This, - /* [in] */ long start); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *time); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackCount )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *trackCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackCount )( - IITFileOrCDTrack * This, - /* [in] */ long trackCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackNumber )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *trackNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackNumber )( - IITFileOrCDTrack * This, - /* [in] */ long trackNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VolumeAdjustment )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *volumeAdjustment); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VolumeAdjustment )( - IITFileOrCDTrack * This, - /* [in] */ long volumeAdjustment); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *year); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Year )( - IITFileOrCDTrack * This, - /* [in] */ long year); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artwork )( - IITFileOrCDTrack * This, - /* [retval][out] */ IITArtworkCollection **iArtworkCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Location )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *location); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdateInfoFromFile )( - IITFileOrCDTrack * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Podcast )( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *isPodcast); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdatePodcastFeed )( - IITFileOrCDTrack * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RememberBookmark )( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *rememberBookmark); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_RememberBookmark )( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldRememberBookmark); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ExcludeFromShuffle )( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *excludeFromShuffle); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ExcludeFromShuffle )( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldExcludeFromShuffle); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Lyrics )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *lyrics); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Lyrics )( - IITFileOrCDTrack * This, - /* [in] */ BSTR lyrics); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Category )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *category); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Category )( - IITFileOrCDTrack * This, - /* [in] */ BSTR category); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Description )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *description); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Description )( - IITFileOrCDTrack * This, - /* [in] */ BSTR description); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LongDescription )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *longDescription); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LongDescription )( - IITFileOrCDTrack * This, - /* [in] */ BSTR longDescription); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BookmarkTime )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *bookmarkTime); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BookmarkTime )( - IITFileOrCDTrack * This, - /* [in] */ long bookmarkTime); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VideoKind )( - IITFileOrCDTrack * This, - /* [retval][out] */ ITVideoKind *videoKind); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VideoKind )( - IITFileOrCDTrack * This, - /* [in] */ ITVideoKind videoKind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SkippedCount )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *skippedCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SkippedCount )( - IITFileOrCDTrack * This, - /* [in] */ long skippedCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SkippedDate )( - IITFileOrCDTrack * This, - /* [retval][out] */ DATE *skippedDate); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SkippedDate )( - IITFileOrCDTrack * This, - /* [in] */ DATE skippedDate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PartOfGaplessAlbum )( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *partOfGaplessAlbum); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PartOfGaplessAlbum )( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldBePartOfGaplessAlbum); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumArtist )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *albumArtist); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AlbumArtist )( - IITFileOrCDTrack * This, - /* [in] */ BSTR albumArtist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Show )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *showName); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Show )( - IITFileOrCDTrack * This, - /* [in] */ BSTR showName); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SeasonNumber )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *seasonNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SeasonNumber )( - IITFileOrCDTrack * This, - /* [in] */ long seasonNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EpisodeID )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *episodeID); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EpisodeID )( - IITFileOrCDTrack * This, - /* [in] */ BSTR episodeID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EpisodeNumber )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *episodeNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EpisodeNumber )( - IITFileOrCDTrack * This, - /* [in] */ long episodeNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size64High )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *sizeHigh); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size64Low )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *sizeLow); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Unplayed )( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *isUnplayed); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Unplayed )( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldBeUnplayed); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortAlbum )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *album); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortAlbum )( - IITFileOrCDTrack * This, - /* [in] */ BSTR album); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortAlbumArtist )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *albumArtist); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortAlbumArtist )( - IITFileOrCDTrack * This, - /* [in] */ BSTR albumArtist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortArtist )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *artist); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortArtist )( - IITFileOrCDTrack * This, - /* [in] */ BSTR artist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortComposer )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *composer); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortComposer )( - IITFileOrCDTrack * This, - /* [in] */ BSTR composer); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortName )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortName )( - IITFileOrCDTrack * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortShow )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *showName); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortShow )( - IITFileOrCDTrack * This, - /* [in] */ BSTR showName); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( - IITFileOrCDTrack * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRating )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *rating); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AlbumRating )( - IITFileOrCDTrack * This, - /* [in] */ long rating); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRatingKind )( - IITFileOrCDTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RatingKind )( - IITFileOrCDTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( - IITFileOrCDTrack * This, - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Location )( - IITFileOrCDTrack * This, - /* [in] */ BSTR location); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ReleaseDate )( - IITFileOrCDTrack * This, - /* [retval][out] */ DATE *releaseDate); - - END_INTERFACE - } IITFileOrCDTrackVtbl; - - interface IITFileOrCDTrack - { - CONST_VTBL struct IITFileOrCDTrackVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITFileOrCDTrack_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITFileOrCDTrack_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITFileOrCDTrack_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITFileOrCDTrack_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITFileOrCDTrack_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITFileOrCDTrack_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITFileOrCDTrack_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITFileOrCDTrack_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITFileOrCDTrack_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITFileOrCDTrack_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITFileOrCDTrack_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITFileOrCDTrack_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITFileOrCDTrack_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITFileOrCDTrack_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITFileOrCDTrack_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITFileOrCDTrack_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITFileOrCDTrack_Play(This) \ - (This)->lpVtbl -> Play(This) - -#define IITFileOrCDTrack_AddArtworkFromFile(This,filePath,iArtwork) \ - (This)->lpVtbl -> AddArtworkFromFile(This,filePath,iArtwork) - -#define IITFileOrCDTrack_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITFileOrCDTrack_get_Playlist(This,iPlaylist) \ - (This)->lpVtbl -> get_Playlist(This,iPlaylist) - -#define IITFileOrCDTrack_get_Album(This,album) \ - (This)->lpVtbl -> get_Album(This,album) - -#define IITFileOrCDTrack_put_Album(This,album) \ - (This)->lpVtbl -> put_Album(This,album) - -#define IITFileOrCDTrack_get_Artist(This,artist) \ - (This)->lpVtbl -> get_Artist(This,artist) - -#define IITFileOrCDTrack_put_Artist(This,artist) \ - (This)->lpVtbl -> put_Artist(This,artist) - -#define IITFileOrCDTrack_get_BitRate(This,bitrate) \ - (This)->lpVtbl -> get_BitRate(This,bitrate) - -#define IITFileOrCDTrack_get_BPM(This,beatsPerMinute) \ - (This)->lpVtbl -> get_BPM(This,beatsPerMinute) - -#define IITFileOrCDTrack_put_BPM(This,beatsPerMinute) \ - (This)->lpVtbl -> put_BPM(This,beatsPerMinute) - -#define IITFileOrCDTrack_get_Comment(This,comment) \ - (This)->lpVtbl -> get_Comment(This,comment) - -#define IITFileOrCDTrack_put_Comment(This,comment) \ - (This)->lpVtbl -> put_Comment(This,comment) - -#define IITFileOrCDTrack_get_Compilation(This,isCompilation) \ - (This)->lpVtbl -> get_Compilation(This,isCompilation) - -#define IITFileOrCDTrack_put_Compilation(This,shouldBeCompilation) \ - (This)->lpVtbl -> put_Compilation(This,shouldBeCompilation) - -#define IITFileOrCDTrack_get_Composer(This,composer) \ - (This)->lpVtbl -> get_Composer(This,composer) - -#define IITFileOrCDTrack_put_Composer(This,composer) \ - (This)->lpVtbl -> put_Composer(This,composer) - -#define IITFileOrCDTrack_get_DateAdded(This,dateAdded) \ - (This)->lpVtbl -> get_DateAdded(This,dateAdded) - -#define IITFileOrCDTrack_get_DiscCount(This,discCount) \ - (This)->lpVtbl -> get_DiscCount(This,discCount) - -#define IITFileOrCDTrack_put_DiscCount(This,discCount) \ - (This)->lpVtbl -> put_DiscCount(This,discCount) - -#define IITFileOrCDTrack_get_DiscNumber(This,discNumber) \ - (This)->lpVtbl -> get_DiscNumber(This,discNumber) - -#define IITFileOrCDTrack_put_DiscNumber(This,discNumber) \ - (This)->lpVtbl -> put_DiscNumber(This,discNumber) - -#define IITFileOrCDTrack_get_Duration(This,duration) \ - (This)->lpVtbl -> get_Duration(This,duration) - -#define IITFileOrCDTrack_get_Enabled(This,isEnabled) \ - (This)->lpVtbl -> get_Enabled(This,isEnabled) - -#define IITFileOrCDTrack_put_Enabled(This,shouldBeEnabled) \ - (This)->lpVtbl -> put_Enabled(This,shouldBeEnabled) - -#define IITFileOrCDTrack_get_EQ(This,eq) \ - (This)->lpVtbl -> get_EQ(This,eq) - -#define IITFileOrCDTrack_put_EQ(This,eq) \ - (This)->lpVtbl -> put_EQ(This,eq) - -#define IITFileOrCDTrack_put_Finish(This,finish) \ - (This)->lpVtbl -> put_Finish(This,finish) - -#define IITFileOrCDTrack_get_Finish(This,finish) \ - (This)->lpVtbl -> get_Finish(This,finish) - -#define IITFileOrCDTrack_get_Genre(This,genre) \ - (This)->lpVtbl -> get_Genre(This,genre) - -#define IITFileOrCDTrack_put_Genre(This,genre) \ - (This)->lpVtbl -> put_Genre(This,genre) - -#define IITFileOrCDTrack_get_Grouping(This,grouping) \ - (This)->lpVtbl -> get_Grouping(This,grouping) - -#define IITFileOrCDTrack_put_Grouping(This,grouping) \ - (This)->lpVtbl -> put_Grouping(This,grouping) - -#define IITFileOrCDTrack_get_KindAsString(This,kind) \ - (This)->lpVtbl -> get_KindAsString(This,kind) - -#define IITFileOrCDTrack_get_ModificationDate(This,dateModified) \ - (This)->lpVtbl -> get_ModificationDate(This,dateModified) - -#define IITFileOrCDTrack_get_PlayedCount(This,playedCount) \ - (This)->lpVtbl -> get_PlayedCount(This,playedCount) - -#define IITFileOrCDTrack_put_PlayedCount(This,playedCount) \ - (This)->lpVtbl -> put_PlayedCount(This,playedCount) - -#define IITFileOrCDTrack_get_PlayedDate(This,playedDate) \ - (This)->lpVtbl -> get_PlayedDate(This,playedDate) - -#define IITFileOrCDTrack_put_PlayedDate(This,playedDate) \ - (This)->lpVtbl -> put_PlayedDate(This,playedDate) - -#define IITFileOrCDTrack_get_PlayOrderIndex(This,index) \ - (This)->lpVtbl -> get_PlayOrderIndex(This,index) - -#define IITFileOrCDTrack_get_Rating(This,rating) \ - (This)->lpVtbl -> get_Rating(This,rating) - -#define IITFileOrCDTrack_put_Rating(This,rating) \ - (This)->lpVtbl -> put_Rating(This,rating) - -#define IITFileOrCDTrack_get_SampleRate(This,sampleRate) \ - (This)->lpVtbl -> get_SampleRate(This,sampleRate) - -#define IITFileOrCDTrack_get_Size(This,size) \ - (This)->lpVtbl -> get_Size(This,size) - -#define IITFileOrCDTrack_get_Start(This,start) \ - (This)->lpVtbl -> get_Start(This,start) - -#define IITFileOrCDTrack_put_Start(This,start) \ - (This)->lpVtbl -> put_Start(This,start) - -#define IITFileOrCDTrack_get_Time(This,time) \ - (This)->lpVtbl -> get_Time(This,time) - -#define IITFileOrCDTrack_get_TrackCount(This,trackCount) \ - (This)->lpVtbl -> get_TrackCount(This,trackCount) - -#define IITFileOrCDTrack_put_TrackCount(This,trackCount) \ - (This)->lpVtbl -> put_TrackCount(This,trackCount) - -#define IITFileOrCDTrack_get_TrackNumber(This,trackNumber) \ - (This)->lpVtbl -> get_TrackNumber(This,trackNumber) - -#define IITFileOrCDTrack_put_TrackNumber(This,trackNumber) \ - (This)->lpVtbl -> put_TrackNumber(This,trackNumber) - -#define IITFileOrCDTrack_get_VolumeAdjustment(This,volumeAdjustment) \ - (This)->lpVtbl -> get_VolumeAdjustment(This,volumeAdjustment) - -#define IITFileOrCDTrack_put_VolumeAdjustment(This,volumeAdjustment) \ - (This)->lpVtbl -> put_VolumeAdjustment(This,volumeAdjustment) - -#define IITFileOrCDTrack_get_Year(This,year) \ - (This)->lpVtbl -> get_Year(This,year) - -#define IITFileOrCDTrack_put_Year(This,year) \ - (This)->lpVtbl -> put_Year(This,year) - -#define IITFileOrCDTrack_get_Artwork(This,iArtworkCollection) \ - (This)->lpVtbl -> get_Artwork(This,iArtworkCollection) - - -#define IITFileOrCDTrack_get_Location(This,location) \ - (This)->lpVtbl -> get_Location(This,location) - -#define IITFileOrCDTrack_UpdateInfoFromFile(This) \ - (This)->lpVtbl -> UpdateInfoFromFile(This) - -#define IITFileOrCDTrack_get_Podcast(This,isPodcast) \ - (This)->lpVtbl -> get_Podcast(This,isPodcast) - -#define IITFileOrCDTrack_UpdatePodcastFeed(This) \ - (This)->lpVtbl -> UpdatePodcastFeed(This) - -#define IITFileOrCDTrack_get_RememberBookmark(This,rememberBookmark) \ - (This)->lpVtbl -> get_RememberBookmark(This,rememberBookmark) - -#define IITFileOrCDTrack_put_RememberBookmark(This,shouldRememberBookmark) \ - (This)->lpVtbl -> put_RememberBookmark(This,shouldRememberBookmark) - -#define IITFileOrCDTrack_get_ExcludeFromShuffle(This,excludeFromShuffle) \ - (This)->lpVtbl -> get_ExcludeFromShuffle(This,excludeFromShuffle) - -#define IITFileOrCDTrack_put_ExcludeFromShuffle(This,shouldExcludeFromShuffle) \ - (This)->lpVtbl -> put_ExcludeFromShuffle(This,shouldExcludeFromShuffle) - -#define IITFileOrCDTrack_get_Lyrics(This,lyrics) \ - (This)->lpVtbl -> get_Lyrics(This,lyrics) - -#define IITFileOrCDTrack_put_Lyrics(This,lyrics) \ - (This)->lpVtbl -> put_Lyrics(This,lyrics) - -#define IITFileOrCDTrack_get_Category(This,category) \ - (This)->lpVtbl -> get_Category(This,category) - -#define IITFileOrCDTrack_put_Category(This,category) \ - (This)->lpVtbl -> put_Category(This,category) - -#define IITFileOrCDTrack_get_Description(This,description) \ - (This)->lpVtbl -> get_Description(This,description) - -#define IITFileOrCDTrack_put_Description(This,description) \ - (This)->lpVtbl -> put_Description(This,description) - -#define IITFileOrCDTrack_get_LongDescription(This,longDescription) \ - (This)->lpVtbl -> get_LongDescription(This,longDescription) - -#define IITFileOrCDTrack_put_LongDescription(This,longDescription) \ - (This)->lpVtbl -> put_LongDescription(This,longDescription) - -#define IITFileOrCDTrack_get_BookmarkTime(This,bookmarkTime) \ - (This)->lpVtbl -> get_BookmarkTime(This,bookmarkTime) - -#define IITFileOrCDTrack_put_BookmarkTime(This,bookmarkTime) \ - (This)->lpVtbl -> put_BookmarkTime(This,bookmarkTime) - -#define IITFileOrCDTrack_get_VideoKind(This,videoKind) \ - (This)->lpVtbl -> get_VideoKind(This,videoKind) - -#define IITFileOrCDTrack_put_VideoKind(This,videoKind) \ - (This)->lpVtbl -> put_VideoKind(This,videoKind) - -#define IITFileOrCDTrack_get_SkippedCount(This,skippedCount) \ - (This)->lpVtbl -> get_SkippedCount(This,skippedCount) - -#define IITFileOrCDTrack_put_SkippedCount(This,skippedCount) \ - (This)->lpVtbl -> put_SkippedCount(This,skippedCount) - -#define IITFileOrCDTrack_get_SkippedDate(This,skippedDate) \ - (This)->lpVtbl -> get_SkippedDate(This,skippedDate) - -#define IITFileOrCDTrack_put_SkippedDate(This,skippedDate) \ - (This)->lpVtbl -> put_SkippedDate(This,skippedDate) - -#define IITFileOrCDTrack_get_PartOfGaplessAlbum(This,partOfGaplessAlbum) \ - (This)->lpVtbl -> get_PartOfGaplessAlbum(This,partOfGaplessAlbum) - -#define IITFileOrCDTrack_put_PartOfGaplessAlbum(This,shouldBePartOfGaplessAlbum) \ - (This)->lpVtbl -> put_PartOfGaplessAlbum(This,shouldBePartOfGaplessAlbum) - -#define IITFileOrCDTrack_get_AlbumArtist(This,albumArtist) \ - (This)->lpVtbl -> get_AlbumArtist(This,albumArtist) - -#define IITFileOrCDTrack_put_AlbumArtist(This,albumArtist) \ - (This)->lpVtbl -> put_AlbumArtist(This,albumArtist) - -#define IITFileOrCDTrack_get_Show(This,showName) \ - (This)->lpVtbl -> get_Show(This,showName) - -#define IITFileOrCDTrack_put_Show(This,showName) \ - (This)->lpVtbl -> put_Show(This,showName) - -#define IITFileOrCDTrack_get_SeasonNumber(This,seasonNumber) \ - (This)->lpVtbl -> get_SeasonNumber(This,seasonNumber) - -#define IITFileOrCDTrack_put_SeasonNumber(This,seasonNumber) \ - (This)->lpVtbl -> put_SeasonNumber(This,seasonNumber) - -#define IITFileOrCDTrack_get_EpisodeID(This,episodeID) \ - (This)->lpVtbl -> get_EpisodeID(This,episodeID) - -#define IITFileOrCDTrack_put_EpisodeID(This,episodeID) \ - (This)->lpVtbl -> put_EpisodeID(This,episodeID) - -#define IITFileOrCDTrack_get_EpisodeNumber(This,episodeNumber) \ - (This)->lpVtbl -> get_EpisodeNumber(This,episodeNumber) - -#define IITFileOrCDTrack_put_EpisodeNumber(This,episodeNumber) \ - (This)->lpVtbl -> put_EpisodeNumber(This,episodeNumber) - -#define IITFileOrCDTrack_get_Size64High(This,sizeHigh) \ - (This)->lpVtbl -> get_Size64High(This,sizeHigh) - -#define IITFileOrCDTrack_get_Size64Low(This,sizeLow) \ - (This)->lpVtbl -> get_Size64Low(This,sizeLow) - -#define IITFileOrCDTrack_get_Unplayed(This,isUnplayed) \ - (This)->lpVtbl -> get_Unplayed(This,isUnplayed) - -#define IITFileOrCDTrack_put_Unplayed(This,shouldBeUnplayed) \ - (This)->lpVtbl -> put_Unplayed(This,shouldBeUnplayed) - -#define IITFileOrCDTrack_get_SortAlbum(This,album) \ - (This)->lpVtbl -> get_SortAlbum(This,album) - -#define IITFileOrCDTrack_put_SortAlbum(This,album) \ - (This)->lpVtbl -> put_SortAlbum(This,album) - -#define IITFileOrCDTrack_get_SortAlbumArtist(This,albumArtist) \ - (This)->lpVtbl -> get_SortAlbumArtist(This,albumArtist) - -#define IITFileOrCDTrack_put_SortAlbumArtist(This,albumArtist) \ - (This)->lpVtbl -> put_SortAlbumArtist(This,albumArtist) - -#define IITFileOrCDTrack_get_SortArtist(This,artist) \ - (This)->lpVtbl -> get_SortArtist(This,artist) - -#define IITFileOrCDTrack_put_SortArtist(This,artist) \ - (This)->lpVtbl -> put_SortArtist(This,artist) - -#define IITFileOrCDTrack_get_SortComposer(This,composer) \ - (This)->lpVtbl -> get_SortComposer(This,composer) - -#define IITFileOrCDTrack_put_SortComposer(This,composer) \ - (This)->lpVtbl -> put_SortComposer(This,composer) - -#define IITFileOrCDTrack_get_SortName(This,name) \ - (This)->lpVtbl -> get_SortName(This,name) - -#define IITFileOrCDTrack_put_SortName(This,name) \ - (This)->lpVtbl -> put_SortName(This,name) - -#define IITFileOrCDTrack_get_SortShow(This,showName) \ - (This)->lpVtbl -> get_SortShow(This,showName) - -#define IITFileOrCDTrack_put_SortShow(This,showName) \ - (This)->lpVtbl -> put_SortShow(This,showName) - -#define IITFileOrCDTrack_Reveal(This) \ - (This)->lpVtbl -> Reveal(This) - -#define IITFileOrCDTrack_get_AlbumRating(This,rating) \ - (This)->lpVtbl -> get_AlbumRating(This,rating) - -#define IITFileOrCDTrack_put_AlbumRating(This,rating) \ - (This)->lpVtbl -> put_AlbumRating(This,rating) - -#define IITFileOrCDTrack_get_AlbumRatingKind(This,ratingKind) \ - (This)->lpVtbl -> get_AlbumRatingKind(This,ratingKind) - -#define IITFileOrCDTrack_get_RatingKind(This,ratingKind) \ - (This)->lpVtbl -> get_RatingKind(This,ratingKind) - -#define IITFileOrCDTrack_get_Playlists(This,iPlaylistCollection) \ - (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) - -#define IITFileOrCDTrack_put_Location(This,location) \ - (This)->lpVtbl -> put_Location(This,location) - -#define IITFileOrCDTrack_get_ReleaseDate(This,releaseDate) \ - (This)->lpVtbl -> get_ReleaseDate(This,releaseDate) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Location_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *location); - - -void __RPC_STUB IITFileOrCDTrack_get_Location_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_UpdateInfoFromFile_Proxy( - IITFileOrCDTrack * This); - - -void __RPC_STUB IITFileOrCDTrack_UpdateInfoFromFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Podcast_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *isPodcast); - - -void __RPC_STUB IITFileOrCDTrack_get_Podcast_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_UpdatePodcastFeed_Proxy( - IITFileOrCDTrack * This); - - -void __RPC_STUB IITFileOrCDTrack_UpdatePodcastFeed_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_RememberBookmark_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *rememberBookmark); - - -void __RPC_STUB IITFileOrCDTrack_get_RememberBookmark_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_RememberBookmark_Proxy( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldRememberBookmark); - - -void __RPC_STUB IITFileOrCDTrack_put_RememberBookmark_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_ExcludeFromShuffle_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *excludeFromShuffle); - - -void __RPC_STUB IITFileOrCDTrack_get_ExcludeFromShuffle_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_ExcludeFromShuffle_Proxy( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldExcludeFromShuffle); - - -void __RPC_STUB IITFileOrCDTrack_put_ExcludeFromShuffle_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Lyrics_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *lyrics); - - -void __RPC_STUB IITFileOrCDTrack_get_Lyrics_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Lyrics_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR lyrics); - - -void __RPC_STUB IITFileOrCDTrack_put_Lyrics_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Category_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *category); - - -void __RPC_STUB IITFileOrCDTrack_get_Category_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Category_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR category); - - -void __RPC_STUB IITFileOrCDTrack_put_Category_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Description_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *description); - - -void __RPC_STUB IITFileOrCDTrack_get_Description_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Description_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR description); - - -void __RPC_STUB IITFileOrCDTrack_put_Description_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_LongDescription_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *longDescription); - - -void __RPC_STUB IITFileOrCDTrack_get_LongDescription_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_LongDescription_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR longDescription); - - -void __RPC_STUB IITFileOrCDTrack_put_LongDescription_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_BookmarkTime_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ long *bookmarkTime); - - -void __RPC_STUB IITFileOrCDTrack_get_BookmarkTime_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_BookmarkTime_Proxy( - IITFileOrCDTrack * This, - /* [in] */ long bookmarkTime); - - -void __RPC_STUB IITFileOrCDTrack_put_BookmarkTime_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_VideoKind_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ ITVideoKind *videoKind); - - -void __RPC_STUB IITFileOrCDTrack_get_VideoKind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_VideoKind_Proxy( - IITFileOrCDTrack * This, - /* [in] */ ITVideoKind videoKind); - - -void __RPC_STUB IITFileOrCDTrack_put_VideoKind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SkippedCount_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ long *skippedCount); - - -void __RPC_STUB IITFileOrCDTrack_get_SkippedCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SkippedCount_Proxy( - IITFileOrCDTrack * This, - /* [in] */ long skippedCount); - - -void __RPC_STUB IITFileOrCDTrack_put_SkippedCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SkippedDate_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ DATE *skippedDate); - - -void __RPC_STUB IITFileOrCDTrack_get_SkippedDate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SkippedDate_Proxy( - IITFileOrCDTrack * This, - /* [in] */ DATE skippedDate); - - -void __RPC_STUB IITFileOrCDTrack_put_SkippedDate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_PartOfGaplessAlbum_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *partOfGaplessAlbum); - - -void __RPC_STUB IITFileOrCDTrack_get_PartOfGaplessAlbum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_PartOfGaplessAlbum_Proxy( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldBePartOfGaplessAlbum); - - -void __RPC_STUB IITFileOrCDTrack_put_PartOfGaplessAlbum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_AlbumArtist_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *albumArtist); - - -void __RPC_STUB IITFileOrCDTrack_get_AlbumArtist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_AlbumArtist_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR albumArtist); - - -void __RPC_STUB IITFileOrCDTrack_put_AlbumArtist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Show_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *showName); - - -void __RPC_STUB IITFileOrCDTrack_get_Show_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Show_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR showName); - - -void __RPC_STUB IITFileOrCDTrack_put_Show_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SeasonNumber_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ long *seasonNumber); - - -void __RPC_STUB IITFileOrCDTrack_get_SeasonNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SeasonNumber_Proxy( - IITFileOrCDTrack * This, - /* [in] */ long seasonNumber); - - -void __RPC_STUB IITFileOrCDTrack_put_SeasonNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_EpisodeID_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *episodeID); - - -void __RPC_STUB IITFileOrCDTrack_get_EpisodeID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_EpisodeID_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR episodeID); - - -void __RPC_STUB IITFileOrCDTrack_put_EpisodeID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_EpisodeNumber_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ long *episodeNumber); - - -void __RPC_STUB IITFileOrCDTrack_get_EpisodeNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_EpisodeNumber_Proxy( - IITFileOrCDTrack * This, - /* [in] */ long episodeNumber); - - -void __RPC_STUB IITFileOrCDTrack_put_EpisodeNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Size64High_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ long *sizeHigh); - - -void __RPC_STUB IITFileOrCDTrack_get_Size64High_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Size64Low_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ long *sizeLow); - - -void __RPC_STUB IITFileOrCDTrack_get_Size64Low_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Unplayed_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *isUnplayed); - - -void __RPC_STUB IITFileOrCDTrack_get_Unplayed_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Unplayed_Proxy( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldBeUnplayed); - - -void __RPC_STUB IITFileOrCDTrack_put_Unplayed_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortAlbum_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *album); - - -void __RPC_STUB IITFileOrCDTrack_get_SortAlbum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortAlbum_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR album); - - -void __RPC_STUB IITFileOrCDTrack_put_SortAlbum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortAlbumArtist_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *albumArtist); - - -void __RPC_STUB IITFileOrCDTrack_get_SortAlbumArtist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortAlbumArtist_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR albumArtist); - - -void __RPC_STUB IITFileOrCDTrack_put_SortAlbumArtist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortArtist_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *artist); - - -void __RPC_STUB IITFileOrCDTrack_get_SortArtist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortArtist_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR artist); - - -void __RPC_STUB IITFileOrCDTrack_put_SortArtist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortComposer_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *composer); - - -void __RPC_STUB IITFileOrCDTrack_get_SortComposer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortComposer_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR composer); - - -void __RPC_STUB IITFileOrCDTrack_put_SortComposer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortName_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *name); - - -void __RPC_STUB IITFileOrCDTrack_get_SortName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortName_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR name); - - -void __RPC_STUB IITFileOrCDTrack_put_SortName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortShow_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *showName); - - -void __RPC_STUB IITFileOrCDTrack_get_SortShow_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortShow_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR showName); - - -void __RPC_STUB IITFileOrCDTrack_put_SortShow_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_Reveal_Proxy( - IITFileOrCDTrack * This); - - -void __RPC_STUB IITFileOrCDTrack_Reveal_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_AlbumRating_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ long *rating); - - -void __RPC_STUB IITFileOrCDTrack_get_AlbumRating_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_AlbumRating_Proxy( - IITFileOrCDTrack * This, - /* [in] */ long rating); - - -void __RPC_STUB IITFileOrCDTrack_put_AlbumRating_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_AlbumRatingKind_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - -void __RPC_STUB IITFileOrCDTrack_get_AlbumRatingKind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_RatingKind_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - -void __RPC_STUB IITFileOrCDTrack_get_RatingKind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Playlists_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); - - -void __RPC_STUB IITFileOrCDTrack_get_Playlists_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Location_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR location); - - -void __RPC_STUB IITFileOrCDTrack_put_Location_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_ReleaseDate_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ DATE *releaseDate); - - -void __RPC_STUB IITFileOrCDTrack_get_ReleaseDate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITFileOrCDTrack_INTERFACE_DEFINED__ */ - - -#ifndef __IITPlaylistWindow_INTERFACE_DEFINED__ -#define __IITPlaylistWindow_INTERFACE_DEFINED__ - -/* interface IITPlaylistWindow */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITPlaylistWindow; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("349CBB45-2E5A-4822-8E4A-A75555A186F7") - IITPlaylistWindow : public IITWindow - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedTracks( - /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlist( - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITPlaylistWindowVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITPlaylistWindow * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITPlaylistWindow * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITPlaylistWindow * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITPlaylistWindow * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITPlaylistWindow * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITPlaylistWindow * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITPlaylistWindow * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITPlaylistWindow * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITPlaylistWindow * This, - /* [retval][out] */ ITWindowKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( - IITPlaylistWindow * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Visible )( - IITPlaylistWindow * This, - /* [in] */ VARIANT_BOOL shouldBeVisible); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Resizable )( - IITPlaylistWindow * This, - /* [retval][out] */ VARIANT_BOOL *isResizable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Minimized )( - IITPlaylistWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMinimized); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Minimized )( - IITPlaylistWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMinimized); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximizable )( - IITPlaylistWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximizable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximized )( - IITPlaylistWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximized); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Maximized )( - IITPlaylistWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMaximized); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomable )( - IITPlaylistWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomed )( - IITPlaylistWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomed); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Zoomed )( - IITPlaylistWindow * This, - /* [in] */ VARIANT_BOOL shouldBeZoomed); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )( - IITPlaylistWindow * This, - /* [retval][out] */ long *top); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Top )( - IITPlaylistWindow * This, - /* [in] */ long top); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )( - IITPlaylistWindow * This, - /* [retval][out] */ long *left); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Left )( - IITPlaylistWindow * This, - /* [in] */ long left); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bottom )( - IITPlaylistWindow * This, - /* [retval][out] */ long *bottom); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bottom )( - IITPlaylistWindow * This, - /* [in] */ long bottom); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Right )( - IITPlaylistWindow * This, - /* [retval][out] */ long *right); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Right )( - IITPlaylistWindow * This, - /* [in] */ long right); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )( - IITPlaylistWindow * This, - /* [retval][out] */ long *width); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Width )( - IITPlaylistWindow * This, - /* [in] */ long width); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )( - IITPlaylistWindow * This, - /* [retval][out] */ long *height); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Height )( - IITPlaylistWindow * This, - /* [in] */ long height); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedTracks )( - IITPlaylistWindow * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( - IITPlaylistWindow * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - END_INTERFACE - } IITPlaylistWindowVtbl; - - interface IITPlaylistWindow - { - CONST_VTBL struct IITPlaylistWindowVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITPlaylistWindow_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITPlaylistWindow_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITPlaylistWindow_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITPlaylistWindow_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITPlaylistWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITPlaylistWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITPlaylistWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITPlaylistWindow_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITPlaylistWindow_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITPlaylistWindow_get_Visible(This,isVisible) \ - (This)->lpVtbl -> get_Visible(This,isVisible) - -#define IITPlaylistWindow_put_Visible(This,shouldBeVisible) \ - (This)->lpVtbl -> put_Visible(This,shouldBeVisible) - -#define IITPlaylistWindow_get_Resizable(This,isResizable) \ - (This)->lpVtbl -> get_Resizable(This,isResizable) - -#define IITPlaylistWindow_get_Minimized(This,isMinimized) \ - (This)->lpVtbl -> get_Minimized(This,isMinimized) - -#define IITPlaylistWindow_put_Minimized(This,shouldBeMinimized) \ - (This)->lpVtbl -> put_Minimized(This,shouldBeMinimized) - -#define IITPlaylistWindow_get_Maximizable(This,isMaximizable) \ - (This)->lpVtbl -> get_Maximizable(This,isMaximizable) - -#define IITPlaylistWindow_get_Maximized(This,isMaximized) \ - (This)->lpVtbl -> get_Maximized(This,isMaximized) - -#define IITPlaylistWindow_put_Maximized(This,shouldBeMaximized) \ - (This)->lpVtbl -> put_Maximized(This,shouldBeMaximized) - -#define IITPlaylistWindow_get_Zoomable(This,isZoomable) \ - (This)->lpVtbl -> get_Zoomable(This,isZoomable) - -#define IITPlaylistWindow_get_Zoomed(This,isZoomed) \ - (This)->lpVtbl -> get_Zoomed(This,isZoomed) - -#define IITPlaylistWindow_put_Zoomed(This,shouldBeZoomed) \ - (This)->lpVtbl -> put_Zoomed(This,shouldBeZoomed) - -#define IITPlaylistWindow_get_Top(This,top) \ - (This)->lpVtbl -> get_Top(This,top) - -#define IITPlaylistWindow_put_Top(This,top) \ - (This)->lpVtbl -> put_Top(This,top) - -#define IITPlaylistWindow_get_Left(This,left) \ - (This)->lpVtbl -> get_Left(This,left) - -#define IITPlaylistWindow_put_Left(This,left) \ - (This)->lpVtbl -> put_Left(This,left) - -#define IITPlaylistWindow_get_Bottom(This,bottom) \ - (This)->lpVtbl -> get_Bottom(This,bottom) - -#define IITPlaylistWindow_put_Bottom(This,bottom) \ - (This)->lpVtbl -> put_Bottom(This,bottom) - -#define IITPlaylistWindow_get_Right(This,right) \ - (This)->lpVtbl -> get_Right(This,right) - -#define IITPlaylistWindow_put_Right(This,right) \ - (This)->lpVtbl -> put_Right(This,right) - -#define IITPlaylistWindow_get_Width(This,width) \ - (This)->lpVtbl -> get_Width(This,width) - -#define IITPlaylistWindow_put_Width(This,width) \ - (This)->lpVtbl -> put_Width(This,width) - -#define IITPlaylistWindow_get_Height(This,height) \ - (This)->lpVtbl -> get_Height(This,height) - -#define IITPlaylistWindow_put_Height(This,height) \ - (This)->lpVtbl -> put_Height(This,height) - - -#define IITPlaylistWindow_get_SelectedTracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_SelectedTracks(This,iTrackCollection) - -#define IITPlaylistWindow_get_Playlist(This,iPlaylist) \ - (This)->lpVtbl -> get_Playlist(This,iPlaylist) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistWindow_get_SelectedTracks_Proxy( - IITPlaylistWindow * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - -void __RPC_STUB IITPlaylistWindow_get_SelectedTracks_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistWindow_get_Playlist_Proxy( - IITPlaylistWindow * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IITPlaylistWindow_get_Playlist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITPlaylistWindow_INTERFACE_DEFINED__ */ - -#endif /* __iTunesLib_LIBRARY_DEFINED__ */ - -/* Additional Prototypes for ALL interfaces */ - -/* end of Additional Prototypes */ - -#ifdef __cplusplus -} -#endif - -#endif - - + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 6.00.0366 */ +/* at Wed Nov 05 13:21:00 2008 + */ +/* Compiler settings for iTunesCOMInterface.idl: + Oicf, W1, Zp8, env=Win32 (32b run) + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +//@@MIDL_FILE_HEADING( ) + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the <rpcndr.h> version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of <rpcndr.h> +#endif // __RPCNDR_H_VERSION__ + + +#ifndef __iTunesCOMInterface_h__ +#define __iTunesCOMInterface_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __IITObject_FWD_DEFINED__ +#define __IITObject_FWD_DEFINED__ +typedef interface IITObject IITObject; +#endif /* __IITObject_FWD_DEFINED__ */ + + +#ifndef __IITSource_FWD_DEFINED__ +#define __IITSource_FWD_DEFINED__ +typedef interface IITSource IITSource; +#endif /* __IITSource_FWD_DEFINED__ */ + + +#ifndef __IITSourceCollection_FWD_DEFINED__ +#define __IITSourceCollection_FWD_DEFINED__ +typedef interface IITSourceCollection IITSourceCollection; +#endif /* __IITSourceCollection_FWD_DEFINED__ */ + + +#ifndef __IITEncoder_FWD_DEFINED__ +#define __IITEncoder_FWD_DEFINED__ +typedef interface IITEncoder IITEncoder; +#endif /* __IITEncoder_FWD_DEFINED__ */ + + +#ifndef __IITEncoderCollection_FWD_DEFINED__ +#define __IITEncoderCollection_FWD_DEFINED__ +typedef interface IITEncoderCollection IITEncoderCollection; +#endif /* __IITEncoderCollection_FWD_DEFINED__ */ + + +#ifndef __IITEQPreset_FWD_DEFINED__ +#define __IITEQPreset_FWD_DEFINED__ +typedef interface IITEQPreset IITEQPreset; +#endif /* __IITEQPreset_FWD_DEFINED__ */ + + +#ifndef __IITEQPresetCollection_FWD_DEFINED__ +#define __IITEQPresetCollection_FWD_DEFINED__ +typedef interface IITEQPresetCollection IITEQPresetCollection; +#endif /* __IITEQPresetCollection_FWD_DEFINED__ */ + + +#ifndef __IITPlaylist_FWD_DEFINED__ +#define __IITPlaylist_FWD_DEFINED__ +typedef interface IITPlaylist IITPlaylist; +#endif /* __IITPlaylist_FWD_DEFINED__ */ + + +#ifndef __IITOperationStatus_FWD_DEFINED__ +#define __IITOperationStatus_FWD_DEFINED__ +typedef interface IITOperationStatus IITOperationStatus; +#endif /* __IITOperationStatus_FWD_DEFINED__ */ + + +#ifndef __IITConvertOperationStatus_FWD_DEFINED__ +#define __IITConvertOperationStatus_FWD_DEFINED__ +typedef interface IITConvertOperationStatus IITConvertOperationStatus; +#endif /* __IITConvertOperationStatus_FWD_DEFINED__ */ + + +#ifndef __IITLibraryPlaylist_FWD_DEFINED__ +#define __IITLibraryPlaylist_FWD_DEFINED__ +typedef interface IITLibraryPlaylist IITLibraryPlaylist; +#endif /* __IITLibraryPlaylist_FWD_DEFINED__ */ + + +#ifndef __IITUserPlaylist_FWD_DEFINED__ +#define __IITUserPlaylist_FWD_DEFINED__ +typedef interface IITUserPlaylist IITUserPlaylist; +#endif /* __IITUserPlaylist_FWD_DEFINED__ */ + + +#ifndef __IITTrack_FWD_DEFINED__ +#define __IITTrack_FWD_DEFINED__ +typedef interface IITTrack IITTrack; +#endif /* __IITTrack_FWD_DEFINED__ */ + + +#ifndef __IITTrackCollection_FWD_DEFINED__ +#define __IITTrackCollection_FWD_DEFINED__ +typedef interface IITTrackCollection IITTrackCollection; +#endif /* __IITTrackCollection_FWD_DEFINED__ */ + + +#ifndef __IITVisual_FWD_DEFINED__ +#define __IITVisual_FWD_DEFINED__ +typedef interface IITVisual IITVisual; +#endif /* __IITVisual_FWD_DEFINED__ */ + + +#ifndef __IITVisualCollection_FWD_DEFINED__ +#define __IITVisualCollection_FWD_DEFINED__ +typedef interface IITVisualCollection IITVisualCollection; +#endif /* __IITVisualCollection_FWD_DEFINED__ */ + + +#ifndef __IITWindow_FWD_DEFINED__ +#define __IITWindow_FWD_DEFINED__ +typedef interface IITWindow IITWindow; +#endif /* __IITWindow_FWD_DEFINED__ */ + + +#ifndef __IITBrowserWindow_FWD_DEFINED__ +#define __IITBrowserWindow_FWD_DEFINED__ +typedef interface IITBrowserWindow IITBrowserWindow; +#endif /* __IITBrowserWindow_FWD_DEFINED__ */ + + +#ifndef __IITWindowCollection_FWD_DEFINED__ +#define __IITWindowCollection_FWD_DEFINED__ +typedef interface IITWindowCollection IITWindowCollection; +#endif /* __IITWindowCollection_FWD_DEFINED__ */ + + +#ifndef __IiTunes_FWD_DEFINED__ +#define __IiTunes_FWD_DEFINED__ +typedef interface IiTunes IiTunes; +#endif /* __IiTunes_FWD_DEFINED__ */ + + +#ifndef ___IiTunesEvents_FWD_DEFINED__ +#define ___IiTunesEvents_FWD_DEFINED__ +typedef interface _IiTunesEvents _IiTunesEvents; +#endif /* ___IiTunesEvents_FWD_DEFINED__ */ + + +#ifndef ___IITConvertOperationStatusEvents_FWD_DEFINED__ +#define ___IITConvertOperationStatusEvents_FWD_DEFINED__ +typedef interface _IITConvertOperationStatusEvents _IITConvertOperationStatusEvents; +#endif /* ___IITConvertOperationStatusEvents_FWD_DEFINED__ */ + + +#ifndef __iTunesApp_FWD_DEFINED__ +#define __iTunesApp_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class iTunesApp iTunesApp; +#else +typedef struct iTunesApp iTunesApp; +#endif /* __cplusplus */ + +#endif /* __iTunesApp_FWD_DEFINED__ */ + + +#ifndef __iTunesConvertOperationStatus_FWD_DEFINED__ +#define __iTunesConvertOperationStatus_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class iTunesConvertOperationStatus iTunesConvertOperationStatus; +#else +typedef struct iTunesConvertOperationStatus iTunesConvertOperationStatus; +#endif /* __cplusplus */ + +#endif /* __iTunesConvertOperationStatus_FWD_DEFINED__ */ + + +#ifndef __IITArtwork_FWD_DEFINED__ +#define __IITArtwork_FWD_DEFINED__ +typedef interface IITArtwork IITArtwork; +#endif /* __IITArtwork_FWD_DEFINED__ */ + + +#ifndef __IITArtworkCollection_FWD_DEFINED__ +#define __IITArtworkCollection_FWD_DEFINED__ +typedef interface IITArtworkCollection IITArtworkCollection; +#endif /* __IITArtworkCollection_FWD_DEFINED__ */ + + +#ifndef __IITURLTrack_FWD_DEFINED__ +#define __IITURLTrack_FWD_DEFINED__ +typedef interface IITURLTrack IITURLTrack; +#endif /* __IITURLTrack_FWD_DEFINED__ */ + + +#ifndef __IITAudioCDPlaylist_FWD_DEFINED__ +#define __IITAudioCDPlaylist_FWD_DEFINED__ +typedef interface IITAudioCDPlaylist IITAudioCDPlaylist; +#endif /* __IITAudioCDPlaylist_FWD_DEFINED__ */ + + +#ifndef __IITPlaylistCollection_FWD_DEFINED__ +#define __IITPlaylistCollection_FWD_DEFINED__ +typedef interface IITPlaylistCollection IITPlaylistCollection; +#endif /* __IITPlaylistCollection_FWD_DEFINED__ */ + + +#ifndef __IITIPodSource_FWD_DEFINED__ +#define __IITIPodSource_FWD_DEFINED__ +typedef interface IITIPodSource IITIPodSource; +#endif /* __IITIPodSource_FWD_DEFINED__ */ + + +#ifndef __IITFileOrCDTrack_FWD_DEFINED__ +#define __IITFileOrCDTrack_FWD_DEFINED__ +typedef interface IITFileOrCDTrack IITFileOrCDTrack; +#endif /* __IITFileOrCDTrack_FWD_DEFINED__ */ + + +#ifndef __IITPlaylistWindow_FWD_DEFINED__ +#define __IITPlaylistWindow_FWD_DEFINED__ +typedef interface IITPlaylistWindow IITPlaylistWindow; +#endif /* __IITPlaylistWindow_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "oaidl.h" +#include "ocidl.h" +#include "DispEx.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +void * __RPC_USER MIDL_user_allocate(size_t); +void __RPC_USER MIDL_user_free( void * ); + +/* interface __MIDL_itf_iTunesCOMInterface_0000 */ +/* [local] */ + +typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("4B73428D-2F56-4833-8E5D-65590E45FEAD") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0000_0001 + { kITTypeLibrary_MajorVersion = 1, + kITTypeLibrary_MinorVersion = 12 + } ITVersion; + +typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("4C25623B-F990-4ebd-8970-F29A70084B8C") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0000_0002 + { ITUNES_E_USERCANCEL = 0xa0040201, + ITUNES_E_OBJECTDELETED = 0xa0040202, + ITUNES_E_OBJECTLOCKED = 0xa0040203, + ITUNES_E_CONVERSIONINPROGRESS = 0xa0040204, + ITUNES_E_MUSICSTOREDISABLED = 0xa0040205, + ITUNES_E_OBJECTEXISTS = 0xa0040206, + ITUNES_E_PODCASTSDISABLED = 0xa0040207 + } ITErrors; + + + +extern RPC_IF_HANDLE __MIDL_itf_iTunesCOMInterface_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_iTunesCOMInterface_0000_v0_0_s_ifspec; + + +#ifndef __iTunesLib_LIBRARY_DEFINED__ +#define __iTunesLib_LIBRARY_DEFINED__ + +/* library iTunesLib */ +/* [helpstring][uuid][version] */ + + + + + + + + + + + + + + + + + + + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("3D502ACA-B474-4640-A2A4-C149538345EC") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0001 + { ITPlayerStateStopped = 0, + ITPlayerStatePlaying = ITPlayerStateStopped + 1, + ITPlayerStateFastForward = ITPlayerStatePlaying + 1, + ITPlayerStateRewind = ITPlayerStateFastForward + 1 + } ITPlayerState; + +typedef /* [public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("5319FADA-0F39-4015-82A0-48B8B871C63C") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0002 + { ITVisualSizeSmall = 0, + ITVisualSizeMedium = ITVisualSizeSmall + 1, + ITVisualSizeLarge = ITVisualSizeMedium + 1 + } ITVisualSize; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("C8128C8D-EDE0-4f0e-AEB1-08D24A91C551") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0003 + { ITCOMDisabledReasonOther = 0, + ITCOMDisabledReasonDialog = ITCOMDisabledReasonOther + 1, + ITCOMDisabledReasonQuitting = ITCOMDisabledReasonDialog + 1 + } ITCOMDisabledReason; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("6B1BD814-CA6E-4063-9EDA-4128D31068C1") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0004 + { ITPlayButtonStatePlayDisabled = 0, + ITPlayButtonStatePlayEnabled = ITPlayButtonStatePlayDisabled + 1, + ITPlayButtonStatePauseEnabled = ITPlayButtonStatePlayEnabled + 1, + ITPlayButtonStatePauseDisabled = ITPlayButtonStatePauseEnabled + 1, + ITPlayButtonStateStopEnabled = ITPlayButtonStatePauseDisabled + 1, + ITPlayButtonStateStopDisabled = ITPlayButtonStateStopEnabled + 1 + } ITPlayButtonState; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("8AF85488-2154-4e46-B65B-1972A43493EF") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0005 + { ITPlayerButtonPrevious = 0, + ITPlayerButtonPlay = ITPlayerButtonPrevious + 1, + ITPlayerButtonNext = ITPlayerButtonPlay + 1 + } ITPlayerButton; + +typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("2129AB11-F23F-485e-B15A-3F8573294F9A") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0006 + { ITPlayerButtonModifierKeyNone = 0, + ITPlayerButtonModifierKeyShift = 1, + ITPlayerButtonModifierKeyControl = 2, + ITPlayerButtonModifierKeyAlt = 4, + ITPlayerButtonModifierKeyCapsLock = 8 + } ITPlayerButtonModifierKey; + +typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("3194F5F4-8F52-41e6-AB8E-4221CFE29550") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0275_0001 + { ITEventDatabaseChanged = 1, + ITEventPlayerPlay = 2, + ITEventPlayerStop = 3, + ITEventPlayerPlayingTrackChanged = 4, + ITEventUserInterfaceEnabled = 5, + ITEventCOMCallsDisabled = 6, + ITEventCOMCallsEnabled = 7, + ITEventQuitting = 8, + ITEventAboutToPromptUserToQuit = 9, + ITEventSoundVolumeChanged = 10 + } ITEvent; + +typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("2E4D55FA-1CD3-4831-8751-0C11EC4FF6FD") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0276_0001 + { ITConvertOperationStatusChanged = 1, + ITConvertOperationComplete = 2 + } ITConvertOperationStatusEvent; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("269E36A5-1728-46e4-BF04-93032C3DD51C") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0277_0001 + { ITArtworkFormatUnknown = 0, + ITArtworkFormatJPEG = ITArtworkFormatUnknown + 1, + ITArtworkFormatPNG = ITArtworkFormatJPEG + 1, + ITArtworkFormatBMP = ITArtworkFormatPNG + 1 + } ITArtworkFormat; + + + + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("DDE76D6E-5F8C-4bda-AFA6-69E82218CFF3") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0001 + { ITPlaylistKindUnknown = 0, + ITPlaylistKindLibrary = ITPlaylistKindUnknown + 1, + ITPlaylistKindUser = ITPlaylistKindLibrary + 1, + ITPlaylistKindCD = ITPlaylistKindUser + 1, + ITPlaylistKindDevice = ITPlaylistKindCD + 1, + ITPlaylistKindRadioTuner = ITPlaylistKindDevice + 1 + } ITPlaylistKind; + +typedef /* [public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("4E1D67A4-6C7A-4c7d-821C-03AF7EB10C35") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0002 + { ITPlaylistRepeatModeOff = 0, + ITPlaylistRepeatModeOne = ITPlaylistRepeatModeOff + 1, + ITPlaylistRepeatModeAll = ITPlaylistRepeatModeOne + 1 + } ITPlaylistRepeatMode; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("BB8E7701-1E77-4972-B6C4-C70AC216F468") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0003 + { ITPlaylistPrintKindPlaylist = 0, + ITPlaylistPrintKindAlbumlist = ITPlaylistPrintKindPlaylist + 1, + ITPlaylistPrintKindInsert = ITPlaylistPrintKindAlbumlist + 1 + } ITPlaylistPrintKind; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("58765E77-E34A-4d67-AC12-5B5BA33EA08F") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0004 + { ITPlaylistSearchFieldAll = 0, + ITPlaylistSearchFieldVisible = ITPlaylistSearchFieldAll + 1, + ITPlaylistSearchFieldArtists = ITPlaylistSearchFieldVisible + 1, + ITPlaylistSearchFieldAlbums = ITPlaylistSearchFieldArtists + 1, + ITPlaylistSearchFieldComposers = ITPlaylistSearchFieldAlbums + 1, + ITPlaylistSearchFieldSongNames = ITPlaylistSearchFieldComposers + 1 + } ITPlaylistSearchField; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("62BC24E6-5C77-4fb7-AA6C-B7FA40C6095D") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0285_0001 + { ITUserPlaylistSpecialKindNone = 0, + ITUserPlaylistSpecialKindPurchasedMusic = ITUserPlaylistSpecialKindNone + 1, + ITUserPlaylistSpecialKindPartyShuffle = ITUserPlaylistSpecialKindPurchasedMusic + 1, + ITUserPlaylistSpecialKindPodcasts = ITUserPlaylistSpecialKindPartyShuffle + 1, + ITUserPlaylistSpecialKindFolder = ITUserPlaylistSpecialKindPodcasts + 1, + ITUserPlaylistSpecialKindVideos = ITUserPlaylistSpecialKindFolder + 1, + ITUserPlaylistSpecialKindMusic = ITUserPlaylistSpecialKindVideos + 1, + ITUserPlaylistSpecialKindMovies = ITUserPlaylistSpecialKindMusic + 1, + ITUserPlaylistSpecialKindTVShows = ITUserPlaylistSpecialKindMovies + 1, + ITUserPlaylistSpecialKindAudiobooks = ITUserPlaylistSpecialKindTVShows + 1 + } ITUserPlaylistSpecialKind; + + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("5F35912B-E633-4930-9E25-09489BAED75A") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0288_0001 + { ITSourceKindUnknown = 0, + ITSourceKindLibrary = ITSourceKindUnknown + 1, + ITSourceKindIPod = ITSourceKindLibrary + 1, + ITSourceKindAudioCD = ITSourceKindIPod + 1, + ITSourceKindMP3CD = ITSourceKindAudioCD + 1, + ITSourceKindDevice = ITSourceKindMP3CD + 1, + ITSourceKindRadioTuner = ITSourceKindDevice + 1, + ITSourceKindSharedLibrary = ITSourceKindRadioTuner + 1 + } ITSourceKind; + + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("ACA133C5-4697-4d5f-98B1-D9881B85FE98") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0291_0001 + { ITTrackKindUnknown = 0, + ITTrackKindFile = ITTrackKindUnknown + 1, + ITTrackKindCD = ITTrackKindFile + 1, + ITTrackKindURL = ITTrackKindCD + 1, + ITTrackKindDevice = ITTrackKindURL + 1, + ITTrackKindSharedLibrary = ITTrackKindDevice + 1 + } ITTrackKind; + +typedef /* [public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("735ECC17-38CC-4d4d-A838-24AF7DCB440E") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0291_0002 + { ITVideoKindNone = 0, + ITVideoKindMovie = ITVideoKindNone + 1, + ITVideoKindMusicVideo = ITVideoKindMovie + 1, + ITVideoKindTVShow = ITVideoKindMusicVideo + 1 + } ITVideoKind; + +typedef /* [public][public][public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("5C75B72C-D066-4faa-8732-D9ED71A6CBD9") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0291_0003 + { ITRatingKindUser = 0, + ITRatingKindComputed = ITRatingKindUser + 1 + } ITRatingKind; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("C20CE920-EFD9-4c1a-8036-95A895741214") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0297_0001 + { ITWindowKindUnknown = 0, + ITWindowKindBrowser = ITWindowKindUnknown + 1, + ITWindowKindPlaylist = ITWindowKindBrowser + 1, + ITWindowKindEQ = ITWindowKindPlaylist + 1, + ITWindowKindArtwork = ITWindowKindEQ + 1, + ITWindowKindNowPlaying = ITWindowKindArtwork + 1 + } ITWindowKind; + + +EXTERN_C const IID LIBID_iTunesLib; + +#ifndef __IITObject_INTERFACE_DEFINED__ +#define __IITObject_INTERFACE_DEFINED__ + +/* interface IITObject */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITObject; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9FAB0E27-70D7-4e3a-9965-B0C8B8869BB6") + IITObject : public IDispatch + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetITObjectIDs( + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Name( + /* [in] */ BSTR name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Index( + /* [retval][out] */ long *index) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SourceID( + /* [retval][out] */ long *sourceID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlaylistID( + /* [retval][out] */ long *playlistID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackID( + /* [retval][out] */ long *trackID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackDatabaseID( + /* [retval][out] */ long *databaseID) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITObjectVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITObject * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITObject * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITObject * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITObject * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITObject * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITObject * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITObject * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITObject * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITObject * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITObject * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITObject * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITObject * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITObject * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITObject * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITObject * This, + /* [retval][out] */ long *databaseID); + + END_INTERFACE + } IITObjectVtbl; + + interface IITObject + { + CONST_VTBL struct IITObjectVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITObject_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITObject_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITObject_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITObject_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITObject_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITObject_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITObject_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITObject_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITObject_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITObject_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITObject_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITObject_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITObject_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITObject_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITObject_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITObject_GetITObjectIDs_Proxy( + IITObject * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + +void __RPC_STUB IITObject_GetITObjectIDs_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_Name_Proxy( + IITObject * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITObject_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITObject_put_Name_Proxy( + IITObject * This, + /* [in] */ BSTR name); + + +void __RPC_STUB IITObject_put_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_Index_Proxy( + IITObject * This, + /* [retval][out] */ long *index); + + +void __RPC_STUB IITObject_get_Index_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_SourceID_Proxy( + IITObject * This, + /* [retval][out] */ long *sourceID); + + +void __RPC_STUB IITObject_get_SourceID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_PlaylistID_Proxy( + IITObject * This, + /* [retval][out] */ long *playlistID); + + +void __RPC_STUB IITObject_get_PlaylistID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_TrackID_Proxy( + IITObject * This, + /* [retval][out] */ long *trackID); + + +void __RPC_STUB IITObject_get_TrackID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_TrackDatabaseID_Proxy( + IITObject * This, + /* [retval][out] */ long *databaseID); + + +void __RPC_STUB IITObject_get_TrackDatabaseID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITObject_INTERFACE_DEFINED__ */ + + +#ifndef __IITSource_INTERFACE_DEFINED__ +#define __IITSource_INTERFACE_DEFINED__ + +/* interface IITSource */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITSource; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("AEC1C4D3-AEF1-4255-B892-3E3D13ADFDF9") + IITSource : public IITObject + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( + /* [retval][out] */ ITSourceKind *kind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Capacity( + /* [retval][out] */ double *capacity) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_FreeSpace( + /* [retval][out] */ double *freespace) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlists( + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITSourceVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITSource * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITSource * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITSource * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITSource * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITSource * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITSource * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITSource * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITSource * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITSource * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITSource * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITSource * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITSource * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITSource * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITSource * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITSource * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITSource * This, + /* [retval][out] */ ITSourceKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Capacity )( + IITSource * This, + /* [retval][out] */ double *capacity); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_FreeSpace )( + IITSource * This, + /* [retval][out] */ double *freespace); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( + IITSource * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + END_INTERFACE + } IITSourceVtbl; + + interface IITSource + { + CONST_VTBL struct IITSourceVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITSource_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITSource_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITSource_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITSource_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITSource_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITSource_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITSource_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITSource_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITSource_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITSource_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITSource_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITSource_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITSource_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITSource_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITSource_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITSource_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITSource_get_Capacity(This,capacity) \ + (This)->lpVtbl -> get_Capacity(This,capacity) + +#define IITSource_get_FreeSpace(This,freespace) \ + (This)->lpVtbl -> get_FreeSpace(This,freespace) + +#define IITSource_get_Playlists(This,iPlaylistCollection) \ + (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_Kind_Proxy( + IITSource * This, + /* [retval][out] */ ITSourceKind *kind); + + +void __RPC_STUB IITSource_get_Kind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_Capacity_Proxy( + IITSource * This, + /* [retval][out] */ double *capacity); + + +void __RPC_STUB IITSource_get_Capacity_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_FreeSpace_Proxy( + IITSource * This, + /* [retval][out] */ double *freespace); + + +void __RPC_STUB IITSource_get_FreeSpace_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_Playlists_Proxy( + IITSource * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + +void __RPC_STUB IITSource_get_Playlists_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITSource_INTERFACE_DEFINED__ */ + + +#ifndef __IITSourceCollection_INTERFACE_DEFINED__ +#define __IITSourceCollection_INTERFACE_DEFINED__ + +/* interface IITSourceCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITSourceCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2FF6CE20-FF87-4183-B0B3-F323D047AF41") + IITSourceCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITSource **iSource) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITSource **iSource) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPersistentID( + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITSource **iSource) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITSourceCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITSourceCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITSourceCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITSourceCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITSourceCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITSourceCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITSourceCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITSourceCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITSourceCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITSourceCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITSourceCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITSourceCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPersistentID )( + IITSourceCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITSource **iSource); + + END_INTERFACE + } IITSourceCollectionVtbl; + + interface IITSourceCollection + { + CONST_VTBL struct IITSourceCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITSourceCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITSourceCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITSourceCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITSourceCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITSourceCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITSourceCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITSourceCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITSourceCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITSourceCollection_get_Item(This,index,iSource) \ + (This)->lpVtbl -> get_Item(This,index,iSource) + +#define IITSourceCollection_get_ItemByName(This,name,iSource) \ + (This)->lpVtbl -> get_ItemByName(This,name,iSource) + +#define IITSourceCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#define IITSourceCollection_get_ItemByPersistentID(This,highID,lowID,iSource) \ + (This)->lpVtbl -> get_ItemByPersistentID(This,highID,lowID,iSource) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_Count_Proxy( + IITSourceCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITSourceCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_Item_Proxy( + IITSourceCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITSource **iSource); + + +void __RPC_STUB IITSourceCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_ItemByName_Proxy( + IITSourceCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITSource **iSource); + + +void __RPC_STUB IITSourceCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get__NewEnum_Proxy( + IITSourceCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITSourceCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_ItemByPersistentID_Proxy( + IITSourceCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITSource **iSource); + + +void __RPC_STUB IITSourceCollection_get_ItemByPersistentID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITSourceCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITEncoder_INTERFACE_DEFINED__ +#define __IITEncoder_INTERFACE_DEFINED__ + +/* interface IITEncoder */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITEncoder; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("1CF95A1C-55FE-4f45-A2D3-85AC6C504A73") + IITEncoder : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Format( + /* [retval][out] */ BSTR *format) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITEncoderVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITEncoder * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITEncoder * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITEncoder * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITEncoder * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITEncoder * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITEncoder * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITEncoder * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITEncoder * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Format )( + IITEncoder * This, + /* [retval][out] */ BSTR *format); + + END_INTERFACE + } IITEncoderVtbl; + + interface IITEncoder + { + CONST_VTBL struct IITEncoderVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITEncoder_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITEncoder_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITEncoder_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITEncoder_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITEncoder_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITEncoder_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITEncoder_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITEncoder_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITEncoder_get_Format(This,format) \ + (This)->lpVtbl -> get_Format(This,format) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoder_get_Name_Proxy( + IITEncoder * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITEncoder_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoder_get_Format_Proxy( + IITEncoder * This, + /* [retval][out] */ BSTR *format); + + +void __RPC_STUB IITEncoder_get_Format_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITEncoder_INTERFACE_DEFINED__ */ + + +#ifndef __IITEncoderCollection_INTERFACE_DEFINED__ +#define __IITEncoderCollection_INTERFACE_DEFINED__ + +/* interface IITEncoderCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITEncoderCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("8862BCA9-168D-4549-A9D5-ADB35E553BA6") + IITEncoderCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITEncoder **iEncoder) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITEncoder **iEncoder) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITEncoderCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITEncoderCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITEncoderCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITEncoderCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITEncoderCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITEncoderCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITEncoderCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITEncoderCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITEncoderCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITEncoderCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITEncoder **iEncoder); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITEncoderCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITEncoder **iEncoder); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITEncoderCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + END_INTERFACE + } IITEncoderCollectionVtbl; + + interface IITEncoderCollection + { + CONST_VTBL struct IITEncoderCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITEncoderCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITEncoderCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITEncoderCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITEncoderCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITEncoderCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITEncoderCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITEncoderCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITEncoderCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITEncoderCollection_get_Item(This,index,iEncoder) \ + (This)->lpVtbl -> get_Item(This,index,iEncoder) + +#define IITEncoderCollection_get_ItemByName(This,name,iEncoder) \ + (This)->lpVtbl -> get_ItemByName(This,name,iEncoder) + +#define IITEncoderCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get_Count_Proxy( + IITEncoderCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITEncoderCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get_Item_Proxy( + IITEncoderCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITEncoder **iEncoder); + + +void __RPC_STUB IITEncoderCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get_ItemByName_Proxy( + IITEncoderCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITEncoder **iEncoder); + + +void __RPC_STUB IITEncoderCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get__NewEnum_Proxy( + IITEncoderCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITEncoderCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITEncoderCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITEQPreset_INTERFACE_DEFINED__ +#define __IITEQPreset_INTERFACE_DEFINED__ + +/* interface IITEQPreset */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITEQPreset; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5BE75F4F-68FA-4212-ACB7-BE44EA569759") + IITEQPreset : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Modifiable( + /* [retval][out] */ VARIANT_BOOL *isModifiable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Preamp( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Preamp( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band1( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band1( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band2( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band2( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band3( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band3( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band4( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band4( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band5( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band5( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band6( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band6( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band7( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band7( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band8( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band8( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band9( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band9( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band10( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band10( + /* [in] */ double level) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( + /* [in] */ VARIANT_BOOL updateAllTracks) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Rename( + /* [in] */ BSTR newName, + /* [in] */ VARIANT_BOOL updateAllTracks) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITEQPresetVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITEQPreset * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITEQPreset * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITEQPreset * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITEQPreset * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITEQPreset * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITEQPreset * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITEQPreset * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITEQPreset * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Modifiable )( + IITEQPreset * This, + /* [retval][out] */ VARIANT_BOOL *isModifiable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Preamp )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Preamp )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band1 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band1 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band2 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band2 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band3 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band3 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band4 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band4 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band5 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band5 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band6 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band6 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band7 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band7 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band8 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band8 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band9 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band9 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band10 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band10 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITEQPreset * This, + /* [in] */ VARIANT_BOOL updateAllTracks); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Rename )( + IITEQPreset * This, + /* [in] */ BSTR newName, + /* [in] */ VARIANT_BOOL updateAllTracks); + + END_INTERFACE + } IITEQPresetVtbl; + + interface IITEQPreset + { + CONST_VTBL struct IITEQPresetVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITEQPreset_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITEQPreset_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITEQPreset_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITEQPreset_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITEQPreset_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITEQPreset_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITEQPreset_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITEQPreset_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITEQPreset_get_Modifiable(This,isModifiable) \ + (This)->lpVtbl -> get_Modifiable(This,isModifiable) + +#define IITEQPreset_get_Preamp(This,level) \ + (This)->lpVtbl -> get_Preamp(This,level) + +#define IITEQPreset_put_Preamp(This,level) \ + (This)->lpVtbl -> put_Preamp(This,level) + +#define IITEQPreset_get_Band1(This,level) \ + (This)->lpVtbl -> get_Band1(This,level) + +#define IITEQPreset_put_Band1(This,level) \ + (This)->lpVtbl -> put_Band1(This,level) + +#define IITEQPreset_get_Band2(This,level) \ + (This)->lpVtbl -> get_Band2(This,level) + +#define IITEQPreset_put_Band2(This,level) \ + (This)->lpVtbl -> put_Band2(This,level) + +#define IITEQPreset_get_Band3(This,level) \ + (This)->lpVtbl -> get_Band3(This,level) + +#define IITEQPreset_put_Band3(This,level) \ + (This)->lpVtbl -> put_Band3(This,level) + +#define IITEQPreset_get_Band4(This,level) \ + (This)->lpVtbl -> get_Band4(This,level) + +#define IITEQPreset_put_Band4(This,level) \ + (This)->lpVtbl -> put_Band4(This,level) + +#define IITEQPreset_get_Band5(This,level) \ + (This)->lpVtbl -> get_Band5(This,level) + +#define IITEQPreset_put_Band5(This,level) \ + (This)->lpVtbl -> put_Band5(This,level) + +#define IITEQPreset_get_Band6(This,level) \ + (This)->lpVtbl -> get_Band6(This,level) + +#define IITEQPreset_put_Band6(This,level) \ + (This)->lpVtbl -> put_Band6(This,level) + +#define IITEQPreset_get_Band7(This,level) \ + (This)->lpVtbl -> get_Band7(This,level) + +#define IITEQPreset_put_Band7(This,level) \ + (This)->lpVtbl -> put_Band7(This,level) + +#define IITEQPreset_get_Band8(This,level) \ + (This)->lpVtbl -> get_Band8(This,level) + +#define IITEQPreset_put_Band8(This,level) \ + (This)->lpVtbl -> put_Band8(This,level) + +#define IITEQPreset_get_Band9(This,level) \ + (This)->lpVtbl -> get_Band9(This,level) + +#define IITEQPreset_put_Band9(This,level) \ + (This)->lpVtbl -> put_Band9(This,level) + +#define IITEQPreset_get_Band10(This,level) \ + (This)->lpVtbl -> get_Band10(This,level) + +#define IITEQPreset_put_Band10(This,level) \ + (This)->lpVtbl -> put_Band10(This,level) + +#define IITEQPreset_Delete(This,updateAllTracks) \ + (This)->lpVtbl -> Delete(This,updateAllTracks) + +#define IITEQPreset_Rename(This,newName,updateAllTracks) \ + (This)->lpVtbl -> Rename(This,newName,updateAllTracks) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Name_Proxy( + IITEQPreset * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITEQPreset_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Modifiable_Proxy( + IITEQPreset * This, + /* [retval][out] */ VARIANT_BOOL *isModifiable); + + +void __RPC_STUB IITEQPreset_get_Modifiable_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Preamp_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Preamp_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Preamp_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Preamp_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band1_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band1_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band1_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band1_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band2_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band2_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band3_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band3_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band3_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band3_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band4_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band4_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band4_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band4_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band5_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band5_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band5_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band5_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band6_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band6_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band6_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band6_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band7_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band7_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band7_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band7_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band8_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band8_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band8_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band8_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band9_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band9_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band9_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band9_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band10_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band10_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band10_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band10_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITEQPreset_Delete_Proxy( + IITEQPreset * This, + /* [in] */ VARIANT_BOOL updateAllTracks); + + +void __RPC_STUB IITEQPreset_Delete_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITEQPreset_Rename_Proxy( + IITEQPreset * This, + /* [in] */ BSTR newName, + /* [in] */ VARIANT_BOOL updateAllTracks); + + +void __RPC_STUB IITEQPreset_Rename_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITEQPreset_INTERFACE_DEFINED__ */ + + +#ifndef __IITEQPresetCollection_INTERFACE_DEFINED__ +#define __IITEQPresetCollection_INTERFACE_DEFINED__ + +/* interface IITEQPresetCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITEQPresetCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("AEF4D111-3331-48da-B0C2-B468D5D61D08") + IITEQPresetCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITEQPreset **iEQPreset) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITEQPreset **iEQPreset) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITEQPresetCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITEQPresetCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITEQPresetCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITEQPresetCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITEQPresetCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITEQPresetCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITEQPresetCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITEQPresetCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITEQPresetCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITEQPresetCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITEQPreset **iEQPreset); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITEQPresetCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITEQPreset **iEQPreset); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITEQPresetCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + END_INTERFACE + } IITEQPresetCollectionVtbl; + + interface IITEQPresetCollection + { + CONST_VTBL struct IITEQPresetCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITEQPresetCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITEQPresetCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITEQPresetCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITEQPresetCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITEQPresetCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITEQPresetCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITEQPresetCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITEQPresetCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITEQPresetCollection_get_Item(This,index,iEQPreset) \ + (This)->lpVtbl -> get_Item(This,index,iEQPreset) + +#define IITEQPresetCollection_get_ItemByName(This,name,iEQPreset) \ + (This)->lpVtbl -> get_ItemByName(This,name,iEQPreset) + +#define IITEQPresetCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get_Count_Proxy( + IITEQPresetCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITEQPresetCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get_Item_Proxy( + IITEQPresetCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITEQPreset **iEQPreset); + + +void __RPC_STUB IITEQPresetCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get_ItemByName_Proxy( + IITEQPresetCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITEQPreset **iEQPreset); + + +void __RPC_STUB IITEQPresetCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get__NewEnum_Proxy( + IITEQPresetCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITEQPresetCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITEQPresetCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITPlaylist_INTERFACE_DEFINED__ +#define __IITPlaylist_INTERFACE_DEFINED__ + +/* interface IITPlaylist */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITPlaylist; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3D5E072F-2A77-4b17-9E73-E03B77CCCCA9") + IITPlaylist : public IITObject + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayFirstTrack( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Print( + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Search( + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( + /* [retval][out] */ ITPlaylistKind *kind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Source( + /* [retval][out] */ IITSource **iSource) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Duration( + /* [retval][out] */ long *duration) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Shuffle( + /* [retval][out] */ VARIANT_BOOL *isShuffle) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Shuffle( + /* [in] */ VARIANT_BOOL shouldShuffle) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size( + /* [retval][out] */ double *size) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SongRepeat( + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SongRepeat( + /* [in] */ ITPlaylistRepeatMode repeatMode) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Time( + /* [retval][out] */ BSTR *time) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Visible( + /* [retval][out] */ VARIANT_BOOL *isVisible) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Tracks( + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITPlaylistVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITPlaylist * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITPlaylist * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITPlaylist * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITPlaylist * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITPlaylist * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITPlaylist * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITPlaylist * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITPlaylist * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITPlaylist * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITPlaylist * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITPlaylist * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITPlaylist * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITPlaylist * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITPlaylist * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITPlaylist * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( + IITPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( + IITPlaylist * This, + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( + IITPlaylist * This, + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITPlaylist * This, + /* [retval][out] */ ITPlaylistKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( + IITPlaylist * This, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITPlaylist * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( + IITPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShuffle); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( + IITPlaylist * This, + /* [in] */ VARIANT_BOOL shouldShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITPlaylist * This, + /* [retval][out] */ double *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( + IITPlaylist * This, + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( + IITPlaylist * This, + /* [in] */ ITPlaylistRepeatMode repeatMode); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITPlaylist * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITPlaylist * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + END_INTERFACE + } IITPlaylistVtbl; + + interface IITPlaylist + { + CONST_VTBL struct IITPlaylistVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITPlaylist_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITPlaylist_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITPlaylist_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITPlaylist_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITPlaylist_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITPlaylist_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITPlaylist_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITPlaylist_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITPlaylist_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITPlaylist_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITPlaylist_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITPlaylist_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITPlaylist_PlayFirstTrack(This) \ + (This)->lpVtbl -> PlayFirstTrack(This) + +#define IITPlaylist_Print(This,showPrintDialog,printKind,theme) \ + (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) + +#define IITPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ + (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) + +#define IITPlaylist_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITPlaylist_get_Source(This,iSource) \ + (This)->lpVtbl -> get_Source(This,iSource) + +#define IITPlaylist_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITPlaylist_get_Shuffle(This,isShuffle) \ + (This)->lpVtbl -> get_Shuffle(This,isShuffle) + +#define IITPlaylist_put_Shuffle(This,shouldShuffle) \ + (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) + +#define IITPlaylist_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITPlaylist_get_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> get_SongRepeat(This,repeatMode) + +#define IITPlaylist_put_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> put_SongRepeat(This,repeatMode) + +#define IITPlaylist_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITPlaylist_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITPlaylist_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_Delete_Proxy( + IITPlaylist * This); + + +void __RPC_STUB IITPlaylist_Delete_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_PlayFirstTrack_Proxy( + IITPlaylist * This); + + +void __RPC_STUB IITPlaylist_PlayFirstTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_Print_Proxy( + IITPlaylist * This, + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme); + + +void __RPC_STUB IITPlaylist_Print_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_Search_Proxy( + IITPlaylist * This, + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IITPlaylist_Search_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Kind_Proxy( + IITPlaylist * This, + /* [retval][out] */ ITPlaylistKind *kind); + + +void __RPC_STUB IITPlaylist_get_Kind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Source_Proxy( + IITPlaylist * This, + /* [retval][out] */ IITSource **iSource); + + +void __RPC_STUB IITPlaylist_get_Source_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Duration_Proxy( + IITPlaylist * This, + /* [retval][out] */ long *duration); + + +void __RPC_STUB IITPlaylist_get_Duration_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Shuffle_Proxy( + IITPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShuffle); + + +void __RPC_STUB IITPlaylist_get_Shuffle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITPlaylist_put_Shuffle_Proxy( + IITPlaylist * This, + /* [in] */ VARIANT_BOOL shouldShuffle); + + +void __RPC_STUB IITPlaylist_put_Shuffle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Size_Proxy( + IITPlaylist * This, + /* [retval][out] */ double *size); + + +void __RPC_STUB IITPlaylist_get_Size_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_SongRepeat_Proxy( + IITPlaylist * This, + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); + + +void __RPC_STUB IITPlaylist_get_SongRepeat_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITPlaylist_put_SongRepeat_Proxy( + IITPlaylist * This, + /* [in] */ ITPlaylistRepeatMode repeatMode); + + +void __RPC_STUB IITPlaylist_put_SongRepeat_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Time_Proxy( + IITPlaylist * This, + /* [retval][out] */ BSTR *time); + + +void __RPC_STUB IITPlaylist_get_Time_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Visible_Proxy( + IITPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + +void __RPC_STUB IITPlaylist_get_Visible_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Tracks_Proxy( + IITPlaylist * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IITPlaylist_get_Tracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITPlaylist_INTERFACE_DEFINED__ */ + + +#ifndef __IITOperationStatus_INTERFACE_DEFINED__ +#define __IITOperationStatus_INTERFACE_DEFINED__ + +/* interface IITOperationStatus */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITOperationStatus; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("206479C9-FE32-4f9b-A18A-475AC939B479") + IITOperationStatus : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_InProgress( + /* [retval][out] */ VARIANT_BOOL *isInProgress) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Tracks( + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITOperationStatusVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITOperationStatus * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITOperationStatus * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITOperationStatus * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITOperationStatus * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITOperationStatus * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITOperationStatus * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITOperationStatus * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InProgress )( + IITOperationStatus * This, + /* [retval][out] */ VARIANT_BOOL *isInProgress); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITOperationStatus * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + END_INTERFACE + } IITOperationStatusVtbl; + + interface IITOperationStatus + { + CONST_VTBL struct IITOperationStatusVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITOperationStatus_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITOperationStatus_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITOperationStatus_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITOperationStatus_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITOperationStatus_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITOperationStatus_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITOperationStatus_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITOperationStatus_get_InProgress(This,isInProgress) \ + (This)->lpVtbl -> get_InProgress(This,isInProgress) + +#define IITOperationStatus_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITOperationStatus_get_InProgress_Proxy( + IITOperationStatus * This, + /* [retval][out] */ VARIANT_BOOL *isInProgress); + + +void __RPC_STUB IITOperationStatus_get_InProgress_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITOperationStatus_get_Tracks_Proxy( + IITOperationStatus * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IITOperationStatus_get_Tracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITOperationStatus_INTERFACE_DEFINED__ */ + + +#ifndef __IITConvertOperationStatus_INTERFACE_DEFINED__ +#define __IITConvertOperationStatus_INTERFACE_DEFINED__ + +/* interface IITConvertOperationStatus */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITConvertOperationStatus; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7063AAF6-ABA0-493b-B4FC-920A9F105875") + IITConvertOperationStatus : public IITOperationStatus + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetConversionStatus( + /* [out] */ BSTR *trackName, + /* [out] */ long *progressValue, + /* [out] */ long *maxProgressValue) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE StopConversion( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackName( + /* [retval][out] */ BSTR *trackName) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ProgressValue( + /* [retval][out] */ long *progressValue) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_MaxProgressValue( + /* [retval][out] */ long *maxProgressValue) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITConvertOperationStatusVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITConvertOperationStatus * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITConvertOperationStatus * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITConvertOperationStatus * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITConvertOperationStatus * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITConvertOperationStatus * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITConvertOperationStatus * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITConvertOperationStatus * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InProgress )( + IITConvertOperationStatus * This, + /* [retval][out] */ VARIANT_BOOL *isInProgress); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITConvertOperationStatus * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetConversionStatus )( + IITConvertOperationStatus * This, + /* [out] */ BSTR *trackName, + /* [out] */ long *progressValue, + /* [out] */ long *maxProgressValue); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *StopConversion )( + IITConvertOperationStatus * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackName )( + IITConvertOperationStatus * This, + /* [retval][out] */ BSTR *trackName); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ProgressValue )( + IITConvertOperationStatus * This, + /* [retval][out] */ long *progressValue); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MaxProgressValue )( + IITConvertOperationStatus * This, + /* [retval][out] */ long *maxProgressValue); + + END_INTERFACE + } IITConvertOperationStatusVtbl; + + interface IITConvertOperationStatus + { + CONST_VTBL struct IITConvertOperationStatusVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITConvertOperationStatus_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITConvertOperationStatus_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITConvertOperationStatus_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITConvertOperationStatus_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITConvertOperationStatus_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITConvertOperationStatus_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITConvertOperationStatus_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITConvertOperationStatus_get_InProgress(This,isInProgress) \ + (This)->lpVtbl -> get_InProgress(This,isInProgress) + +#define IITConvertOperationStatus_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + + +#define IITConvertOperationStatus_GetConversionStatus(This,trackName,progressValue,maxProgressValue) \ + (This)->lpVtbl -> GetConversionStatus(This,trackName,progressValue,maxProgressValue) + +#define IITConvertOperationStatus_StopConversion(This) \ + (This)->lpVtbl -> StopConversion(This) + +#define IITConvertOperationStatus_get_TrackName(This,trackName) \ + (This)->lpVtbl -> get_TrackName(This,trackName) + +#define IITConvertOperationStatus_get_ProgressValue(This,progressValue) \ + (This)->lpVtbl -> get_ProgressValue(This,progressValue) + +#define IITConvertOperationStatus_get_MaxProgressValue(This,maxProgressValue) \ + (This)->lpVtbl -> get_MaxProgressValue(This,maxProgressValue) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_GetConversionStatus_Proxy( + IITConvertOperationStatus * This, + /* [out] */ BSTR *trackName, + /* [out] */ long *progressValue, + /* [out] */ long *maxProgressValue); + + +void __RPC_STUB IITConvertOperationStatus_GetConversionStatus_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_StopConversion_Proxy( + IITConvertOperationStatus * This); + + +void __RPC_STUB IITConvertOperationStatus_StopConversion_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_get_TrackName_Proxy( + IITConvertOperationStatus * This, + /* [retval][out] */ BSTR *trackName); + + +void __RPC_STUB IITConvertOperationStatus_get_TrackName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_get_ProgressValue_Proxy( + IITConvertOperationStatus * This, + /* [retval][out] */ long *progressValue); + + +void __RPC_STUB IITConvertOperationStatus_get_ProgressValue_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_get_MaxProgressValue_Proxy( + IITConvertOperationStatus * This, + /* [retval][out] */ long *maxProgressValue); + + +void __RPC_STUB IITConvertOperationStatus_get_MaxProgressValue_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITConvertOperationStatus_INTERFACE_DEFINED__ */ + + +#ifndef __IITLibraryPlaylist_INTERFACE_DEFINED__ +#define __IITLibraryPlaylist_INTERFACE_DEFINED__ + +/* interface IITLibraryPlaylist */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITLibraryPlaylist; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("53AE1704-491C-4289-94A0-958815675A3D") + IITLibraryPlaylist : public IITPlaylist + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFile( + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFiles( + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddURL( + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddTrack( + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITLibraryPlaylistVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITLibraryPlaylist * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITLibraryPlaylist * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITLibraryPlaylist * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITLibraryPlaylist * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITLibraryPlaylist * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITLibraryPlaylist * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITLibraryPlaylist * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITLibraryPlaylist * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITLibraryPlaylist * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITLibraryPlaylist * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITLibraryPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( + IITLibraryPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( + IITLibraryPlaylist * This, + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( + IITLibraryPlaylist * This, + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITLibraryPlaylist * This, + /* [retval][out] */ ITPlaylistKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( + IITLibraryPlaylist * This, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( + IITLibraryPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShuffle); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( + IITLibraryPlaylist * This, + /* [in] */ VARIANT_BOOL shouldShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITLibraryPlaylist * This, + /* [retval][out] */ double *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( + IITLibraryPlaylist * This, + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( + IITLibraryPlaylist * This, + /* [in] */ ITPlaylistRepeatMode repeatMode); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITLibraryPlaylist * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITLibraryPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITLibraryPlaylist * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFile )( + IITLibraryPlaylist * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFiles )( + IITLibraryPlaylist * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddURL )( + IITLibraryPlaylist * This, + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddTrack )( + IITLibraryPlaylist * This, + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack); + + END_INTERFACE + } IITLibraryPlaylistVtbl; + + interface IITLibraryPlaylist + { + CONST_VTBL struct IITLibraryPlaylistVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITLibraryPlaylist_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITLibraryPlaylist_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITLibraryPlaylist_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITLibraryPlaylist_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITLibraryPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITLibraryPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITLibraryPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITLibraryPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITLibraryPlaylist_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITLibraryPlaylist_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITLibraryPlaylist_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITLibraryPlaylist_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITLibraryPlaylist_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITLibraryPlaylist_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITLibraryPlaylist_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITLibraryPlaylist_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITLibraryPlaylist_PlayFirstTrack(This) \ + (This)->lpVtbl -> PlayFirstTrack(This) + +#define IITLibraryPlaylist_Print(This,showPrintDialog,printKind,theme) \ + (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) + +#define IITLibraryPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ + (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) + +#define IITLibraryPlaylist_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITLibraryPlaylist_get_Source(This,iSource) \ + (This)->lpVtbl -> get_Source(This,iSource) + +#define IITLibraryPlaylist_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITLibraryPlaylist_get_Shuffle(This,isShuffle) \ + (This)->lpVtbl -> get_Shuffle(This,isShuffle) + +#define IITLibraryPlaylist_put_Shuffle(This,shouldShuffle) \ + (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) + +#define IITLibraryPlaylist_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITLibraryPlaylist_get_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> get_SongRepeat(This,repeatMode) + +#define IITLibraryPlaylist_put_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> put_SongRepeat(This,repeatMode) + +#define IITLibraryPlaylist_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITLibraryPlaylist_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITLibraryPlaylist_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + + +#define IITLibraryPlaylist_AddFile(This,filePath,iStatus) \ + (This)->lpVtbl -> AddFile(This,filePath,iStatus) + +#define IITLibraryPlaylist_AddFiles(This,filePaths,iStatus) \ + (This)->lpVtbl -> AddFiles(This,filePaths,iStatus) + +#define IITLibraryPlaylist_AddURL(This,url,iURLTrack) \ + (This)->lpVtbl -> AddURL(This,url,iURLTrack) + +#define IITLibraryPlaylist_AddTrack(This,iTrackToAdd,iAddedTrack) \ + (This)->lpVtbl -> AddTrack(This,iTrackToAdd,iAddedTrack) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddFile_Proxy( + IITLibraryPlaylist * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IITLibraryPlaylist_AddFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddFiles_Proxy( + IITLibraryPlaylist * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IITLibraryPlaylist_AddFiles_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddURL_Proxy( + IITLibraryPlaylist * This, + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack); + + +void __RPC_STUB IITLibraryPlaylist_AddURL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddTrack_Proxy( + IITLibraryPlaylist * This, + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack); + + +void __RPC_STUB IITLibraryPlaylist_AddTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITLibraryPlaylist_INTERFACE_DEFINED__ */ + + +#ifndef __IITUserPlaylist_INTERFACE_DEFINED__ +#define __IITUserPlaylist_INTERFACE_DEFINED__ + +/* interface IITUserPlaylist */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITUserPlaylist; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("0A504DED-A0B5-465a-8A94-50E20D7DF692") + IITUserPlaylist : public IITPlaylist + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFile( + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFiles( + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddURL( + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddTrack( + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Shared( + /* [retval][out] */ VARIANT_BOOL *isShared) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Shared( + /* [in] */ VARIANT_BOOL shouldBeShared) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Smart( + /* [retval][out] */ VARIANT_BOOL *isSmart) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SpecialKind( + /* [retval][out] */ ITUserPlaylistSpecialKind *specialKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Parent( + /* [retval][out] */ IITUserPlaylist **iParentPlayList) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePlaylist( + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateFolder( + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Parent( + /* [in] */ VARIANT *iParent) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITUserPlaylistVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITUserPlaylist * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITUserPlaylist * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITUserPlaylist * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITUserPlaylist * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITUserPlaylist * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITUserPlaylist * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITUserPlaylist * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITUserPlaylist * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITUserPlaylist * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITUserPlaylist * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITUserPlaylist * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITUserPlaylist * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITUserPlaylist * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITUserPlaylist * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITUserPlaylist * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITUserPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( + IITUserPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( + IITUserPlaylist * This, + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( + IITUserPlaylist * This, + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITUserPlaylist * This, + /* [retval][out] */ ITPlaylistKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( + IITUserPlaylist * This, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITUserPlaylist * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShuffle); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( + IITUserPlaylist * This, + /* [in] */ VARIANT_BOOL shouldShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITUserPlaylist * This, + /* [retval][out] */ double *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( + IITUserPlaylist * This, + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( + IITUserPlaylist * This, + /* [in] */ ITPlaylistRepeatMode repeatMode); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITUserPlaylist * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITUserPlaylist * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFile )( + IITUserPlaylist * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFiles )( + IITUserPlaylist * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddURL )( + IITUserPlaylist * This, + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddTrack )( + IITUserPlaylist * This, + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shared )( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShared); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shared )( + IITUserPlaylist * This, + /* [in] */ VARIANT_BOOL shouldBeShared); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Smart )( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isSmart); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SpecialKind )( + IITUserPlaylist * This, + /* [retval][out] */ ITUserPlaylistSpecialKind *specialKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Parent )( + IITUserPlaylist * This, + /* [retval][out] */ IITUserPlaylist **iParentPlayList); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreatePlaylist )( + IITUserPlaylist * This, + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateFolder )( + IITUserPlaylist * This, + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Parent )( + IITUserPlaylist * This, + /* [in] */ VARIANT *iParent); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( + IITUserPlaylist * This); + + END_INTERFACE + } IITUserPlaylistVtbl; + + interface IITUserPlaylist + { + CONST_VTBL struct IITUserPlaylistVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITUserPlaylist_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITUserPlaylist_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITUserPlaylist_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITUserPlaylist_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITUserPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITUserPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITUserPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITUserPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITUserPlaylist_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITUserPlaylist_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITUserPlaylist_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITUserPlaylist_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITUserPlaylist_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITUserPlaylist_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITUserPlaylist_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITUserPlaylist_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITUserPlaylist_PlayFirstTrack(This) \ + (This)->lpVtbl -> PlayFirstTrack(This) + +#define IITUserPlaylist_Print(This,showPrintDialog,printKind,theme) \ + (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) + +#define IITUserPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ + (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) + +#define IITUserPlaylist_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITUserPlaylist_get_Source(This,iSource) \ + (This)->lpVtbl -> get_Source(This,iSource) + +#define IITUserPlaylist_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITUserPlaylist_get_Shuffle(This,isShuffle) \ + (This)->lpVtbl -> get_Shuffle(This,isShuffle) + +#define IITUserPlaylist_put_Shuffle(This,shouldShuffle) \ + (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) + +#define IITUserPlaylist_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITUserPlaylist_get_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> get_SongRepeat(This,repeatMode) + +#define IITUserPlaylist_put_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> put_SongRepeat(This,repeatMode) + +#define IITUserPlaylist_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITUserPlaylist_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITUserPlaylist_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + + +#define IITUserPlaylist_AddFile(This,filePath,iStatus) \ + (This)->lpVtbl -> AddFile(This,filePath,iStatus) + +#define IITUserPlaylist_AddFiles(This,filePaths,iStatus) \ + (This)->lpVtbl -> AddFiles(This,filePaths,iStatus) + +#define IITUserPlaylist_AddURL(This,url,iURLTrack) \ + (This)->lpVtbl -> AddURL(This,url,iURLTrack) + +#define IITUserPlaylist_AddTrack(This,iTrackToAdd,iAddedTrack) \ + (This)->lpVtbl -> AddTrack(This,iTrackToAdd,iAddedTrack) + +#define IITUserPlaylist_get_Shared(This,isShared) \ + (This)->lpVtbl -> get_Shared(This,isShared) + +#define IITUserPlaylist_put_Shared(This,shouldBeShared) \ + (This)->lpVtbl -> put_Shared(This,shouldBeShared) + +#define IITUserPlaylist_get_Smart(This,isSmart) \ + (This)->lpVtbl -> get_Smart(This,isSmart) + +#define IITUserPlaylist_get_SpecialKind(This,specialKind) \ + (This)->lpVtbl -> get_SpecialKind(This,specialKind) + +#define IITUserPlaylist_get_Parent(This,iParentPlayList) \ + (This)->lpVtbl -> get_Parent(This,iParentPlayList) + +#define IITUserPlaylist_CreatePlaylist(This,playlistName,iPlaylist) \ + (This)->lpVtbl -> CreatePlaylist(This,playlistName,iPlaylist) + +#define IITUserPlaylist_CreateFolder(This,folderName,iFolder) \ + (This)->lpVtbl -> CreateFolder(This,folderName,iFolder) + +#define IITUserPlaylist_put_Parent(This,iParent) \ + (This)->lpVtbl -> put_Parent(This,iParent) + +#define IITUserPlaylist_Reveal(This) \ + (This)->lpVtbl -> Reveal(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddFile_Proxy( + IITUserPlaylist * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IITUserPlaylist_AddFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddFiles_Proxy( + IITUserPlaylist * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IITUserPlaylist_AddFiles_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddURL_Proxy( + IITUserPlaylist * This, + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack); + + +void __RPC_STUB IITUserPlaylist_AddURL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddTrack_Proxy( + IITUserPlaylist * This, + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack); + + +void __RPC_STUB IITUserPlaylist_AddTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_Shared_Proxy( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShared); + + +void __RPC_STUB IITUserPlaylist_get_Shared_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_put_Shared_Proxy( + IITUserPlaylist * This, + /* [in] */ VARIANT_BOOL shouldBeShared); + + +void __RPC_STUB IITUserPlaylist_put_Shared_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_Smart_Proxy( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isSmart); + + +void __RPC_STUB IITUserPlaylist_get_Smart_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_SpecialKind_Proxy( + IITUserPlaylist * This, + /* [retval][out] */ ITUserPlaylistSpecialKind *specialKind); + + +void __RPC_STUB IITUserPlaylist_get_SpecialKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_Parent_Proxy( + IITUserPlaylist * This, + /* [retval][out] */ IITUserPlaylist **iParentPlayList); + + +void __RPC_STUB IITUserPlaylist_get_Parent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_CreatePlaylist_Proxy( + IITUserPlaylist * This, + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITUserPlaylist_CreatePlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_CreateFolder_Proxy( + IITUserPlaylist * This, + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder); + + +void __RPC_STUB IITUserPlaylist_CreateFolder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_put_Parent_Proxy( + IITUserPlaylist * This, + /* [in] */ VARIANT *iParent); + + +void __RPC_STUB IITUserPlaylist_put_Parent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_Reveal_Proxy( + IITUserPlaylist * This); + + +void __RPC_STUB IITUserPlaylist_Reveal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITUserPlaylist_INTERFACE_DEFINED__ */ + + +#ifndef __IITTrack_INTERFACE_DEFINED__ +#define __IITTrack_INTERFACE_DEFINED__ + +/* interface IITTrack */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITTrack; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("4CB0915D-1E54-4727-BAF3-CE6CC9A225A1") + IITTrack : public IITObject + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Play( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddArtworkFromFile( + /* [in] */ BSTR filePath, + /* [retval][out] */ IITArtwork **iArtwork) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( + /* [retval][out] */ ITTrackKind *kind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlist( + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Album( + /* [retval][out] */ BSTR *album) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Album( + /* [in] */ BSTR album) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Artist( + /* [retval][out] */ BSTR *artist) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Artist( + /* [in] */ BSTR artist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BitRate( + /* [retval][out] */ long *bitrate) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BPM( + /* [retval][out] */ long *beatsPerMinute) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_BPM( + /* [in] */ long beatsPerMinute) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Comment( + /* [retval][out] */ BSTR *comment) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Comment( + /* [in] */ BSTR comment) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Compilation( + /* [retval][out] */ VARIANT_BOOL *isCompilation) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Compilation( + /* [in] */ VARIANT_BOOL shouldBeCompilation) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Composer( + /* [retval][out] */ BSTR *composer) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Composer( + /* [in] */ BSTR composer) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DateAdded( + /* [retval][out] */ DATE *dateAdded) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscCount( + /* [retval][out] */ long *discCount) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DiscCount( + /* [in] */ long discCount) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscNumber( + /* [retval][out] */ long *discNumber) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DiscNumber( + /* [in] */ long discNumber) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Duration( + /* [retval][out] */ long *duration) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Enabled( + /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Enabled( + /* [in] */ VARIANT_BOOL shouldBeEnabled) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQ( + /* [retval][out] */ BSTR *eq) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EQ( + /* [in] */ BSTR eq) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Finish( + /* [in] */ long finish) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Finish( + /* [retval][out] */ long *finish) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Genre( + /* [retval][out] */ BSTR *genre) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Genre( + /* [in] */ BSTR genre) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Grouping( + /* [retval][out] */ BSTR *grouping) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Grouping( + /* [in] */ BSTR grouping) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_KindAsString( + /* [retval][out] */ BSTR *kind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ModificationDate( + /* [retval][out] */ DATE *dateModified) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayedCount( + /* [retval][out] */ long *playedCount) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PlayedCount( + /* [in] */ long playedCount) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayedDate( + /* [retval][out] */ DATE *playedDate) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PlayedDate( + /* [in] */ DATE playedDate) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayOrderIndex( + /* [retval][out] */ long *index) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Rating( + /* [retval][out] */ long *rating) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Rating( + /* [in] */ long rating) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SampleRate( + /* [retval][out] */ long *sampleRate) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size( + /* [retval][out] */ long *size) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Start( + /* [retval][out] */ long *start) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Start( + /* [in] */ long start) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Time( + /* [retval][out] */ BSTR *time) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackCount( + /* [retval][out] */ long *trackCount) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_TrackCount( + /* [in] */ long trackCount) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackNumber( + /* [retval][out] */ long *trackNumber) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_TrackNumber( + /* [in] */ long trackNumber) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VolumeAdjustment( + /* [retval][out] */ long *volumeAdjustment) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VolumeAdjustment( + /* [in] */ long volumeAdjustment) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Year( + /* [retval][out] */ long *year) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Year( + /* [in] */ long year) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Artwork( + /* [retval][out] */ IITArtworkCollection **iArtworkCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITTrackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITTrack * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITTrack * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITTrack * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITTrack * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITTrack * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITTrack * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITTrack * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITTrack * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITTrack * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITTrack * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITTrack * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITTrack * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITTrack * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITTrack * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( + IITTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddArtworkFromFile )( + IITTrack * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITArtwork **iArtwork); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITTrack * This, + /* [retval][out] */ ITTrackKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( + IITTrack * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Album )( + IITTrack * This, + /* [retval][out] */ BSTR *album); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Album )( + IITTrack * This, + /* [in] */ BSTR album); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( + IITTrack * This, + /* [retval][out] */ BSTR *artist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Artist )( + IITTrack * This, + /* [in] */ BSTR artist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BitRate )( + IITTrack * This, + /* [retval][out] */ long *bitrate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BPM )( + IITTrack * This, + /* [retval][out] */ long *beatsPerMinute); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BPM )( + IITTrack * This, + /* [in] */ long beatsPerMinute); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Comment )( + IITTrack * This, + /* [retval][out] */ BSTR *comment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Comment )( + IITTrack * This, + /* [in] */ BSTR comment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( + IITTrack * This, + /* [retval][out] */ VARIANT_BOOL *isCompilation); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Compilation )( + IITTrack * This, + /* [in] */ VARIANT_BOOL shouldBeCompilation); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( + IITTrack * This, + /* [retval][out] */ BSTR *composer); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Composer )( + IITTrack * This, + /* [in] */ BSTR composer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DateAdded )( + IITTrack * This, + /* [retval][out] */ DATE *dateAdded); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( + IITTrack * This, + /* [retval][out] */ long *discCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscCount )( + IITTrack * This, + /* [in] */ long discCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( + IITTrack * This, + /* [retval][out] */ long *discNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscNumber )( + IITTrack * This, + /* [in] */ long discNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITTrack * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Enabled )( + IITTrack * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Enabled )( + IITTrack * This, + /* [in] */ VARIANT_BOOL shouldBeEnabled); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQ )( + IITTrack * This, + /* [retval][out] */ BSTR *eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQ )( + IITTrack * This, + /* [in] */ BSTR eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Finish )( + IITTrack * This, + /* [in] */ long finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Finish )( + IITTrack * This, + /* [retval][out] */ long *finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( + IITTrack * This, + /* [retval][out] */ BSTR *genre); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Genre )( + IITTrack * This, + /* [in] */ BSTR genre); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Grouping )( + IITTrack * This, + /* [retval][out] */ BSTR *grouping); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Grouping )( + IITTrack * This, + /* [in] */ BSTR grouping); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_KindAsString )( + IITTrack * This, + /* [retval][out] */ BSTR *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ModificationDate )( + IITTrack * This, + /* [retval][out] */ DATE *dateModified); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedCount )( + IITTrack * This, + /* [retval][out] */ long *playedCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedCount )( + IITTrack * This, + /* [in] */ long playedCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedDate )( + IITTrack * This, + /* [retval][out] */ DATE *playedDate); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedDate )( + IITTrack * This, + /* [in] */ DATE playedDate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayOrderIndex )( + IITTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Rating )( + IITTrack * This, + /* [retval][out] */ long *rating); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Rating )( + IITTrack * This, + /* [in] */ long rating); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SampleRate )( + IITTrack * This, + /* [retval][out] */ long *sampleRate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITTrack * This, + /* [retval][out] */ long *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Start )( + IITTrack * This, + /* [retval][out] */ long *start); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Start )( + IITTrack * This, + /* [in] */ long start); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITTrack * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackCount )( + IITTrack * This, + /* [retval][out] */ long *trackCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackCount )( + IITTrack * This, + /* [in] */ long trackCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackNumber )( + IITTrack * This, + /* [retval][out] */ long *trackNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackNumber )( + IITTrack * This, + /* [in] */ long trackNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VolumeAdjustment )( + IITTrack * This, + /* [retval][out] */ long *volumeAdjustment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VolumeAdjustment )( + IITTrack * This, + /* [in] */ long volumeAdjustment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( + IITTrack * This, + /* [retval][out] */ long *year); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Year )( + IITTrack * This, + /* [in] */ long year); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artwork )( + IITTrack * This, + /* [retval][out] */ IITArtworkCollection **iArtworkCollection); + + END_INTERFACE + } IITTrackVtbl; + + interface IITTrack + { + CONST_VTBL struct IITTrackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITTrack_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITTrack_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITTrack_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITTrack_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITTrack_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITTrack_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITTrack_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITTrack_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITTrack_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITTrack_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITTrack_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITTrack_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITTrack_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITTrack_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITTrack_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITTrack_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITTrack_Play(This) \ + (This)->lpVtbl -> Play(This) + +#define IITTrack_AddArtworkFromFile(This,filePath,iArtwork) \ + (This)->lpVtbl -> AddArtworkFromFile(This,filePath,iArtwork) + +#define IITTrack_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITTrack_get_Playlist(This,iPlaylist) \ + (This)->lpVtbl -> get_Playlist(This,iPlaylist) + +#define IITTrack_get_Album(This,album) \ + (This)->lpVtbl -> get_Album(This,album) + +#define IITTrack_put_Album(This,album) \ + (This)->lpVtbl -> put_Album(This,album) + +#define IITTrack_get_Artist(This,artist) \ + (This)->lpVtbl -> get_Artist(This,artist) + +#define IITTrack_put_Artist(This,artist) \ + (This)->lpVtbl -> put_Artist(This,artist) + +#define IITTrack_get_BitRate(This,bitrate) \ + (This)->lpVtbl -> get_BitRate(This,bitrate) + +#define IITTrack_get_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> get_BPM(This,beatsPerMinute) + +#define IITTrack_put_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> put_BPM(This,beatsPerMinute) + +#define IITTrack_get_Comment(This,comment) \ + (This)->lpVtbl -> get_Comment(This,comment) + +#define IITTrack_put_Comment(This,comment) \ + (This)->lpVtbl -> put_Comment(This,comment) + +#define IITTrack_get_Compilation(This,isCompilation) \ + (This)->lpVtbl -> get_Compilation(This,isCompilation) + +#define IITTrack_put_Compilation(This,shouldBeCompilation) \ + (This)->lpVtbl -> put_Compilation(This,shouldBeCompilation) + +#define IITTrack_get_Composer(This,composer) \ + (This)->lpVtbl -> get_Composer(This,composer) + +#define IITTrack_put_Composer(This,composer) \ + (This)->lpVtbl -> put_Composer(This,composer) + +#define IITTrack_get_DateAdded(This,dateAdded) \ + (This)->lpVtbl -> get_DateAdded(This,dateAdded) + +#define IITTrack_get_DiscCount(This,discCount) \ + (This)->lpVtbl -> get_DiscCount(This,discCount) + +#define IITTrack_put_DiscCount(This,discCount) \ + (This)->lpVtbl -> put_DiscCount(This,discCount) + +#define IITTrack_get_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> get_DiscNumber(This,discNumber) + +#define IITTrack_put_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> put_DiscNumber(This,discNumber) + +#define IITTrack_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITTrack_get_Enabled(This,isEnabled) \ + (This)->lpVtbl -> get_Enabled(This,isEnabled) + +#define IITTrack_put_Enabled(This,shouldBeEnabled) \ + (This)->lpVtbl -> put_Enabled(This,shouldBeEnabled) + +#define IITTrack_get_EQ(This,eq) \ + (This)->lpVtbl -> get_EQ(This,eq) + +#define IITTrack_put_EQ(This,eq) \ + (This)->lpVtbl -> put_EQ(This,eq) + +#define IITTrack_put_Finish(This,finish) \ + (This)->lpVtbl -> put_Finish(This,finish) + +#define IITTrack_get_Finish(This,finish) \ + (This)->lpVtbl -> get_Finish(This,finish) + +#define IITTrack_get_Genre(This,genre) \ + (This)->lpVtbl -> get_Genre(This,genre) + +#define IITTrack_put_Genre(This,genre) \ + (This)->lpVtbl -> put_Genre(This,genre) + +#define IITTrack_get_Grouping(This,grouping) \ + (This)->lpVtbl -> get_Grouping(This,grouping) + +#define IITTrack_put_Grouping(This,grouping) \ + (This)->lpVtbl -> put_Grouping(This,grouping) + +#define IITTrack_get_KindAsString(This,kind) \ + (This)->lpVtbl -> get_KindAsString(This,kind) + +#define IITTrack_get_ModificationDate(This,dateModified) \ + (This)->lpVtbl -> get_ModificationDate(This,dateModified) + +#define IITTrack_get_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> get_PlayedCount(This,playedCount) + +#define IITTrack_put_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> put_PlayedCount(This,playedCount) + +#define IITTrack_get_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> get_PlayedDate(This,playedDate) + +#define IITTrack_put_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> put_PlayedDate(This,playedDate) + +#define IITTrack_get_PlayOrderIndex(This,index) \ + (This)->lpVtbl -> get_PlayOrderIndex(This,index) + +#define IITTrack_get_Rating(This,rating) \ + (This)->lpVtbl -> get_Rating(This,rating) + +#define IITTrack_put_Rating(This,rating) \ + (This)->lpVtbl -> put_Rating(This,rating) + +#define IITTrack_get_SampleRate(This,sampleRate) \ + (This)->lpVtbl -> get_SampleRate(This,sampleRate) + +#define IITTrack_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITTrack_get_Start(This,start) \ + (This)->lpVtbl -> get_Start(This,start) + +#define IITTrack_put_Start(This,start) \ + (This)->lpVtbl -> put_Start(This,start) + +#define IITTrack_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITTrack_get_TrackCount(This,trackCount) \ + (This)->lpVtbl -> get_TrackCount(This,trackCount) + +#define IITTrack_put_TrackCount(This,trackCount) \ + (This)->lpVtbl -> put_TrackCount(This,trackCount) + +#define IITTrack_get_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> get_TrackNumber(This,trackNumber) + +#define IITTrack_put_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> put_TrackNumber(This,trackNumber) + +#define IITTrack_get_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> get_VolumeAdjustment(This,volumeAdjustment) + +#define IITTrack_put_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> put_VolumeAdjustment(This,volumeAdjustment) + +#define IITTrack_get_Year(This,year) \ + (This)->lpVtbl -> get_Year(This,year) + +#define IITTrack_put_Year(This,year) \ + (This)->lpVtbl -> put_Year(This,year) + +#define IITTrack_get_Artwork(This,iArtworkCollection) \ + (This)->lpVtbl -> get_Artwork(This,iArtworkCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITTrack_Delete_Proxy( + IITTrack * This); + + +void __RPC_STUB IITTrack_Delete_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITTrack_Play_Proxy( + IITTrack * This); + + +void __RPC_STUB IITTrack_Play_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITTrack_AddArtworkFromFile_Proxy( + IITTrack * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITArtwork **iArtwork); + + +void __RPC_STUB IITTrack_AddArtworkFromFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Kind_Proxy( + IITTrack * This, + /* [retval][out] */ ITTrackKind *kind); + + +void __RPC_STUB IITTrack_get_Kind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Playlist_Proxy( + IITTrack * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITTrack_get_Playlist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Album_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *album); + + +void __RPC_STUB IITTrack_get_Album_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Album_Proxy( + IITTrack * This, + /* [in] */ BSTR album); + + +void __RPC_STUB IITTrack_put_Album_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Artist_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *artist); + + +void __RPC_STUB IITTrack_get_Artist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Artist_Proxy( + IITTrack * This, + /* [in] */ BSTR artist); + + +void __RPC_STUB IITTrack_put_Artist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_BitRate_Proxy( + IITTrack * This, + /* [retval][out] */ long *bitrate); + + +void __RPC_STUB IITTrack_get_BitRate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_BPM_Proxy( + IITTrack * This, + /* [retval][out] */ long *beatsPerMinute); + + +void __RPC_STUB IITTrack_get_BPM_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_BPM_Proxy( + IITTrack * This, + /* [in] */ long beatsPerMinute); + + +void __RPC_STUB IITTrack_put_BPM_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Comment_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *comment); + + +void __RPC_STUB IITTrack_get_Comment_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Comment_Proxy( + IITTrack * This, + /* [in] */ BSTR comment); + + +void __RPC_STUB IITTrack_put_Comment_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Compilation_Proxy( + IITTrack * This, + /* [retval][out] */ VARIANT_BOOL *isCompilation); + + +void __RPC_STUB IITTrack_get_Compilation_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Compilation_Proxy( + IITTrack * This, + /* [in] */ VARIANT_BOOL shouldBeCompilation); + + +void __RPC_STUB IITTrack_put_Compilation_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Composer_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *composer); + + +void __RPC_STUB IITTrack_get_Composer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Composer_Proxy( + IITTrack * This, + /* [in] */ BSTR composer); + + +void __RPC_STUB IITTrack_put_Composer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_DateAdded_Proxy( + IITTrack * This, + /* [retval][out] */ DATE *dateAdded); + + +void __RPC_STUB IITTrack_get_DateAdded_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_DiscCount_Proxy( + IITTrack * This, + /* [retval][out] */ long *discCount); + + +void __RPC_STUB IITTrack_get_DiscCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_DiscCount_Proxy( + IITTrack * This, + /* [in] */ long discCount); + + +void __RPC_STUB IITTrack_put_DiscCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_DiscNumber_Proxy( + IITTrack * This, + /* [retval][out] */ long *discNumber); + + +void __RPC_STUB IITTrack_get_DiscNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_DiscNumber_Proxy( + IITTrack * This, + /* [in] */ long discNumber); + + +void __RPC_STUB IITTrack_put_DiscNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Duration_Proxy( + IITTrack * This, + /* [retval][out] */ long *duration); + + +void __RPC_STUB IITTrack_get_Duration_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Enabled_Proxy( + IITTrack * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + +void __RPC_STUB IITTrack_get_Enabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Enabled_Proxy( + IITTrack * This, + /* [in] */ VARIANT_BOOL shouldBeEnabled); + + +void __RPC_STUB IITTrack_put_Enabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_EQ_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *eq); + + +void __RPC_STUB IITTrack_get_EQ_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_EQ_Proxy( + IITTrack * This, + /* [in] */ BSTR eq); + + +void __RPC_STUB IITTrack_put_EQ_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Finish_Proxy( + IITTrack * This, + /* [in] */ long finish); + + +void __RPC_STUB IITTrack_put_Finish_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Finish_Proxy( + IITTrack * This, + /* [retval][out] */ long *finish); + + +void __RPC_STUB IITTrack_get_Finish_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Genre_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *genre); + + +void __RPC_STUB IITTrack_get_Genre_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Genre_Proxy( + IITTrack * This, + /* [in] */ BSTR genre); + + +void __RPC_STUB IITTrack_put_Genre_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Grouping_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *grouping); + + +void __RPC_STUB IITTrack_get_Grouping_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Grouping_Proxy( + IITTrack * This, + /* [in] */ BSTR grouping); + + +void __RPC_STUB IITTrack_put_Grouping_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_KindAsString_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *kind); + + +void __RPC_STUB IITTrack_get_KindAsString_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_ModificationDate_Proxy( + IITTrack * This, + /* [retval][out] */ DATE *dateModified); + + +void __RPC_STUB IITTrack_get_ModificationDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_PlayedCount_Proxy( + IITTrack * This, + /* [retval][out] */ long *playedCount); + + +void __RPC_STUB IITTrack_get_PlayedCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_PlayedCount_Proxy( + IITTrack * This, + /* [in] */ long playedCount); + + +void __RPC_STUB IITTrack_put_PlayedCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_PlayedDate_Proxy( + IITTrack * This, + /* [retval][out] */ DATE *playedDate); + + +void __RPC_STUB IITTrack_get_PlayedDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_PlayedDate_Proxy( + IITTrack * This, + /* [in] */ DATE playedDate); + + +void __RPC_STUB IITTrack_put_PlayedDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_PlayOrderIndex_Proxy( + IITTrack * This, + /* [retval][out] */ long *index); + + +void __RPC_STUB IITTrack_get_PlayOrderIndex_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Rating_Proxy( + IITTrack * This, + /* [retval][out] */ long *rating); + + +void __RPC_STUB IITTrack_get_Rating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Rating_Proxy( + IITTrack * This, + /* [in] */ long rating); + + +void __RPC_STUB IITTrack_put_Rating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_SampleRate_Proxy( + IITTrack * This, + /* [retval][out] */ long *sampleRate); + + +void __RPC_STUB IITTrack_get_SampleRate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Size_Proxy( + IITTrack * This, + /* [retval][out] */ long *size); + + +void __RPC_STUB IITTrack_get_Size_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Start_Proxy( + IITTrack * This, + /* [retval][out] */ long *start); + + +void __RPC_STUB IITTrack_get_Start_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Start_Proxy( + IITTrack * This, + /* [in] */ long start); + + +void __RPC_STUB IITTrack_put_Start_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Time_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *time); + + +void __RPC_STUB IITTrack_get_Time_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_TrackCount_Proxy( + IITTrack * This, + /* [retval][out] */ long *trackCount); + + +void __RPC_STUB IITTrack_get_TrackCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_TrackCount_Proxy( + IITTrack * This, + /* [in] */ long trackCount); + + +void __RPC_STUB IITTrack_put_TrackCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_TrackNumber_Proxy( + IITTrack * This, + /* [retval][out] */ long *trackNumber); + + +void __RPC_STUB IITTrack_get_TrackNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_TrackNumber_Proxy( + IITTrack * This, + /* [in] */ long trackNumber); + + +void __RPC_STUB IITTrack_put_TrackNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_VolumeAdjustment_Proxy( + IITTrack * This, + /* [retval][out] */ long *volumeAdjustment); + + +void __RPC_STUB IITTrack_get_VolumeAdjustment_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_VolumeAdjustment_Proxy( + IITTrack * This, + /* [in] */ long volumeAdjustment); + + +void __RPC_STUB IITTrack_put_VolumeAdjustment_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Year_Proxy( + IITTrack * This, + /* [retval][out] */ long *year); + + +void __RPC_STUB IITTrack_get_Year_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Year_Proxy( + IITTrack * This, + /* [in] */ long year); + + +void __RPC_STUB IITTrack_put_Year_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Artwork_Proxy( + IITTrack * This, + /* [retval][out] */ IITArtworkCollection **iArtworkCollection); + + +void __RPC_STUB IITTrack_get_Artwork_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITTrack_INTERFACE_DEFINED__ */ + + +#ifndef __IITTrackCollection_INTERFACE_DEFINED__ +#define __IITTrackCollection_INTERFACE_DEFINED__ + +/* interface IITTrackCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITTrackCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("755D76F1-6B85-4ce4-8F5F-F88D9743DCD8") + IITTrackCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPlayOrder( + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITTrack **iTrack) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPersistentID( + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITTrack **iTrack) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITTrackCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITTrackCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITTrackCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITTrackCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITTrackCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITTrackCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITTrackCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITTrackCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITTrackCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITTrackCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPlayOrder )( + IITTrackCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITTrackCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITTrack **iTrack); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITTrackCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPersistentID )( + IITTrackCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITTrack **iTrack); + + END_INTERFACE + } IITTrackCollectionVtbl; + + interface IITTrackCollection + { + CONST_VTBL struct IITTrackCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITTrackCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITTrackCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITTrackCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITTrackCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITTrackCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITTrackCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITTrackCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITTrackCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITTrackCollection_get_Item(This,index,iTrack) \ + (This)->lpVtbl -> get_Item(This,index,iTrack) + +#define IITTrackCollection_get_ItemByPlayOrder(This,index,iTrack) \ + (This)->lpVtbl -> get_ItemByPlayOrder(This,index,iTrack) + +#define IITTrackCollection_get_ItemByName(This,name,iTrack) \ + (This)->lpVtbl -> get_ItemByName(This,name,iTrack) + +#define IITTrackCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#define IITTrackCollection_get_ItemByPersistentID(This,highID,lowID,iTrack) \ + (This)->lpVtbl -> get_ItemByPersistentID(This,highID,lowID,iTrack) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_Count_Proxy( + IITTrackCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITTrackCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_Item_Proxy( + IITTrackCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack); + + +void __RPC_STUB IITTrackCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_ItemByPlayOrder_Proxy( + IITTrackCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack); + + +void __RPC_STUB IITTrackCollection_get_ItemByPlayOrder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_ItemByName_Proxy( + IITTrackCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITTrack **iTrack); + + +void __RPC_STUB IITTrackCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get__NewEnum_Proxy( + IITTrackCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITTrackCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_ItemByPersistentID_Proxy( + IITTrackCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITTrack **iTrack); + + +void __RPC_STUB IITTrackCollection_get_ItemByPersistentID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITTrackCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITVisual_INTERFACE_DEFINED__ +#define __IITVisual_INTERFACE_DEFINED__ + +/* interface IITVisual */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITVisual; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("340F3315-ED72-4c09-9ACF-21EB4BDF9931") + IITVisual : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITVisualVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITVisual * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITVisual * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITVisual * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITVisual * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITVisual * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITVisual * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITVisual * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITVisual * This, + /* [retval][out] */ BSTR *name); + + END_INTERFACE + } IITVisualVtbl; + + interface IITVisual + { + CONST_VTBL struct IITVisualVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITVisual_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITVisual_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITVisual_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITVisual_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITVisual_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITVisual_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITVisual_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITVisual_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITVisual_get_Name_Proxy( + IITVisual * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITVisual_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITVisual_INTERFACE_DEFINED__ */ + + +#ifndef __IITVisualCollection_INTERFACE_DEFINED__ +#define __IITVisualCollection_INTERFACE_DEFINED__ + +/* interface IITVisualCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITVisualCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("88A4CCDD-114F-4043-B69B-84D4E6274957") + IITVisualCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITVisual **iVisual) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITVisual **iVisual) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITVisualCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITVisualCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITVisualCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITVisualCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITVisualCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITVisualCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITVisualCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITVisualCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITVisualCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITVisualCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITVisual **iVisual); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITVisualCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITVisual **iVisual); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITVisualCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + END_INTERFACE + } IITVisualCollectionVtbl; + + interface IITVisualCollection + { + CONST_VTBL struct IITVisualCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITVisualCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITVisualCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITVisualCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITVisualCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITVisualCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITVisualCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITVisualCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITVisualCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITVisualCollection_get_Item(This,index,iVisual) \ + (This)->lpVtbl -> get_Item(This,index,iVisual) + +#define IITVisualCollection_get_ItemByName(This,name,iVisual) \ + (This)->lpVtbl -> get_ItemByName(This,name,iVisual) + +#define IITVisualCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get_Count_Proxy( + IITVisualCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITVisualCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get_Item_Proxy( + IITVisualCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITVisual **iVisual); + + +void __RPC_STUB IITVisualCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get_ItemByName_Proxy( + IITVisualCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITVisual **iVisual); + + +void __RPC_STUB IITVisualCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get__NewEnum_Proxy( + IITVisualCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITVisualCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITVisualCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITWindow_INTERFACE_DEFINED__ +#define __IITWindow_INTERFACE_DEFINED__ + +/* interface IITWindow */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITWindow; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("370D7BE0-3A89-4a42-B902-C75FC138BE09") + IITWindow : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( + /* [retval][out] */ ITWindowKind *kind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Visible( + /* [retval][out] */ VARIANT_BOOL *isVisible) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Visible( + /* [in] */ VARIANT_BOOL shouldBeVisible) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Resizable( + /* [retval][out] */ VARIANT_BOOL *isResizable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Minimized( + /* [retval][out] */ VARIANT_BOOL *isMinimized) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Minimized( + /* [in] */ VARIANT_BOOL shouldBeMinimized) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Maximizable( + /* [retval][out] */ VARIANT_BOOL *isMaximizable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Maximized( + /* [retval][out] */ VARIANT_BOOL *isMaximized) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Maximized( + /* [in] */ VARIANT_BOOL shouldBeMaximized) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Zoomable( + /* [retval][out] */ VARIANT_BOOL *isZoomable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Zoomed( + /* [retval][out] */ VARIANT_BOOL *isZoomed) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Zoomed( + /* [in] */ VARIANT_BOOL shouldBeZoomed) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Top( + /* [retval][out] */ long *top) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Top( + /* [in] */ long top) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Left( + /* [retval][out] */ long *left) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Left( + /* [in] */ long left) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Bottom( + /* [retval][out] */ long *bottom) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Bottom( + /* [in] */ long bottom) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Right( + /* [retval][out] */ long *right) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Right( + /* [in] */ long right) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Width( + /* [retval][out] */ long *width) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Width( + /* [in] */ long width) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Height( + /* [retval][out] */ long *height) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Height( + /* [in] */ long height) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITWindowVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITWindow * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITWindow * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITWindow * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITWindow * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITWindow * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITWindow * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITWindow * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITWindow * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITWindow * This, + /* [retval][out] */ ITWindowKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Visible )( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Resizable )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isResizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Minimized )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMinimized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Minimized )( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMinimized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximizable )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximized )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Maximized )( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMaximized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomable )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomed )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomed); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Zoomed )( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeZoomed); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )( + IITWindow * This, + /* [retval][out] */ long *top); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Top )( + IITWindow * This, + /* [in] */ long top); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )( + IITWindow * This, + /* [retval][out] */ long *left); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Left )( + IITWindow * This, + /* [in] */ long left); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bottom )( + IITWindow * This, + /* [retval][out] */ long *bottom); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bottom )( + IITWindow * This, + /* [in] */ long bottom); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Right )( + IITWindow * This, + /* [retval][out] */ long *right); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Right )( + IITWindow * This, + /* [in] */ long right); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )( + IITWindow * This, + /* [retval][out] */ long *width); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Width )( + IITWindow * This, + /* [in] */ long width); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )( + IITWindow * This, + /* [retval][out] */ long *height); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Height )( + IITWindow * This, + /* [in] */ long height); + + END_INTERFACE + } IITWindowVtbl; + + interface IITWindow + { + CONST_VTBL struct IITWindowVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITWindow_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITWindow_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITWindow_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITWindow_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITWindow_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITWindow_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITWindow_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITWindow_put_Visible(This,shouldBeVisible) \ + (This)->lpVtbl -> put_Visible(This,shouldBeVisible) + +#define IITWindow_get_Resizable(This,isResizable) \ + (This)->lpVtbl -> get_Resizable(This,isResizable) + +#define IITWindow_get_Minimized(This,isMinimized) \ + (This)->lpVtbl -> get_Minimized(This,isMinimized) + +#define IITWindow_put_Minimized(This,shouldBeMinimized) \ + (This)->lpVtbl -> put_Minimized(This,shouldBeMinimized) + +#define IITWindow_get_Maximizable(This,isMaximizable) \ + (This)->lpVtbl -> get_Maximizable(This,isMaximizable) + +#define IITWindow_get_Maximized(This,isMaximized) \ + (This)->lpVtbl -> get_Maximized(This,isMaximized) + +#define IITWindow_put_Maximized(This,shouldBeMaximized) \ + (This)->lpVtbl -> put_Maximized(This,shouldBeMaximized) + +#define IITWindow_get_Zoomable(This,isZoomable) \ + (This)->lpVtbl -> get_Zoomable(This,isZoomable) + +#define IITWindow_get_Zoomed(This,isZoomed) \ + (This)->lpVtbl -> get_Zoomed(This,isZoomed) + +#define IITWindow_put_Zoomed(This,shouldBeZoomed) \ + (This)->lpVtbl -> put_Zoomed(This,shouldBeZoomed) + +#define IITWindow_get_Top(This,top) \ + (This)->lpVtbl -> get_Top(This,top) + +#define IITWindow_put_Top(This,top) \ + (This)->lpVtbl -> put_Top(This,top) + +#define IITWindow_get_Left(This,left) \ + (This)->lpVtbl -> get_Left(This,left) + +#define IITWindow_put_Left(This,left) \ + (This)->lpVtbl -> put_Left(This,left) + +#define IITWindow_get_Bottom(This,bottom) \ + (This)->lpVtbl -> get_Bottom(This,bottom) + +#define IITWindow_put_Bottom(This,bottom) \ + (This)->lpVtbl -> put_Bottom(This,bottom) + +#define IITWindow_get_Right(This,right) \ + (This)->lpVtbl -> get_Right(This,right) + +#define IITWindow_put_Right(This,right) \ + (This)->lpVtbl -> put_Right(This,right) + +#define IITWindow_get_Width(This,width) \ + (This)->lpVtbl -> get_Width(This,width) + +#define IITWindow_put_Width(This,width) \ + (This)->lpVtbl -> put_Width(This,width) + +#define IITWindow_get_Height(This,height) \ + (This)->lpVtbl -> get_Height(This,height) + +#define IITWindow_put_Height(This,height) \ + (This)->lpVtbl -> put_Height(This,height) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Name_Proxy( + IITWindow * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITWindow_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Kind_Proxy( + IITWindow * This, + /* [retval][out] */ ITWindowKind *kind); + + +void __RPC_STUB IITWindow_get_Kind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Visible_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + +void __RPC_STUB IITWindow_get_Visible_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Visible_Proxy( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeVisible); + + +void __RPC_STUB IITWindow_put_Visible_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Resizable_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isResizable); + + +void __RPC_STUB IITWindow_get_Resizable_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Minimized_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMinimized); + + +void __RPC_STUB IITWindow_get_Minimized_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Minimized_Proxy( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMinimized); + + +void __RPC_STUB IITWindow_put_Minimized_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Maximizable_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximizable); + + +void __RPC_STUB IITWindow_get_Maximizable_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Maximized_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximized); + + +void __RPC_STUB IITWindow_get_Maximized_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Maximized_Proxy( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMaximized); + + +void __RPC_STUB IITWindow_put_Maximized_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Zoomable_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomable); + + +void __RPC_STUB IITWindow_get_Zoomable_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Zoomed_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomed); + + +void __RPC_STUB IITWindow_get_Zoomed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Zoomed_Proxy( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeZoomed); + + +void __RPC_STUB IITWindow_put_Zoomed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Top_Proxy( + IITWindow * This, + /* [retval][out] */ long *top); + + +void __RPC_STUB IITWindow_get_Top_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Top_Proxy( + IITWindow * This, + /* [in] */ long top); + + +void __RPC_STUB IITWindow_put_Top_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Left_Proxy( + IITWindow * This, + /* [retval][out] */ long *left); + + +void __RPC_STUB IITWindow_get_Left_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Left_Proxy( + IITWindow * This, + /* [in] */ long left); + + +void __RPC_STUB IITWindow_put_Left_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Bottom_Proxy( + IITWindow * This, + /* [retval][out] */ long *bottom); + + +void __RPC_STUB IITWindow_get_Bottom_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Bottom_Proxy( + IITWindow * This, + /* [in] */ long bottom); + + +void __RPC_STUB IITWindow_put_Bottom_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Right_Proxy( + IITWindow * This, + /* [retval][out] */ long *right); + + +void __RPC_STUB IITWindow_get_Right_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Right_Proxy( + IITWindow * This, + /* [in] */ long right); + + +void __RPC_STUB IITWindow_put_Right_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Width_Proxy( + IITWindow * This, + /* [retval][out] */ long *width); + + +void __RPC_STUB IITWindow_get_Width_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Width_Proxy( + IITWindow * This, + /* [in] */ long width); + + +void __RPC_STUB IITWindow_put_Width_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Height_Proxy( + IITWindow * This, + /* [retval][out] */ long *height); + + +void __RPC_STUB IITWindow_get_Height_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Height_Proxy( + IITWindow * This, + /* [in] */ long height); + + +void __RPC_STUB IITWindow_put_Height_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITWindow_INTERFACE_DEFINED__ */ + + +#ifndef __IITBrowserWindow_INTERFACE_DEFINED__ +#define __IITBrowserWindow_INTERFACE_DEFINED__ + +/* interface IITBrowserWindow */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITBrowserWindow; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C999F455-C4D5-4aa4-8277-F99753699974") + IITBrowserWindow : public IITWindow + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_MiniPlayer( + /* [retval][out] */ VARIANT_BOOL *isMiniPlayer) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_MiniPlayer( + /* [in] */ VARIANT_BOOL shouldBeMiniPlayer) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedTracks( + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedPlaylist( + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SelectedPlaylist( + /* [in] */ VARIANT *iPlaylist) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITBrowserWindowVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITBrowserWindow * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITBrowserWindow * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITBrowserWindow * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITBrowserWindow * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITBrowserWindow * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITBrowserWindow * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITBrowserWindow * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITBrowserWindow * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITBrowserWindow * This, + /* [retval][out] */ ITWindowKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Visible )( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Resizable )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isResizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Minimized )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMinimized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Minimized )( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMinimized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximizable )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximized )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Maximized )( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMaximized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomable )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomed )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomed); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Zoomed )( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeZoomed); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )( + IITBrowserWindow * This, + /* [retval][out] */ long *top); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Top )( + IITBrowserWindow * This, + /* [in] */ long top); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )( + IITBrowserWindow * This, + /* [retval][out] */ long *left); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Left )( + IITBrowserWindow * This, + /* [in] */ long left); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bottom )( + IITBrowserWindow * This, + /* [retval][out] */ long *bottom); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bottom )( + IITBrowserWindow * This, + /* [in] */ long bottom); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Right )( + IITBrowserWindow * This, + /* [retval][out] */ long *right); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Right )( + IITBrowserWindow * This, + /* [in] */ long right); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )( + IITBrowserWindow * This, + /* [retval][out] */ long *width); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Width )( + IITBrowserWindow * This, + /* [in] */ long width); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )( + IITBrowserWindow * This, + /* [retval][out] */ long *height); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Height )( + IITBrowserWindow * This, + /* [in] */ long height); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MiniPlayer )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMiniPlayer); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_MiniPlayer )( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMiniPlayer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedTracks )( + IITBrowserWindow * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedPlaylist )( + IITBrowserWindow * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SelectedPlaylist )( + IITBrowserWindow * This, + /* [in] */ VARIANT *iPlaylist); + + END_INTERFACE + } IITBrowserWindowVtbl; + + interface IITBrowserWindow + { + CONST_VTBL struct IITBrowserWindowVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITBrowserWindow_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITBrowserWindow_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITBrowserWindow_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITBrowserWindow_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITBrowserWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITBrowserWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITBrowserWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITBrowserWindow_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITBrowserWindow_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITBrowserWindow_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITBrowserWindow_put_Visible(This,shouldBeVisible) \ + (This)->lpVtbl -> put_Visible(This,shouldBeVisible) + +#define IITBrowserWindow_get_Resizable(This,isResizable) \ + (This)->lpVtbl -> get_Resizable(This,isResizable) + +#define IITBrowserWindow_get_Minimized(This,isMinimized) \ + (This)->lpVtbl -> get_Minimized(This,isMinimized) + +#define IITBrowserWindow_put_Minimized(This,shouldBeMinimized) \ + (This)->lpVtbl -> put_Minimized(This,shouldBeMinimized) + +#define IITBrowserWindow_get_Maximizable(This,isMaximizable) \ + (This)->lpVtbl -> get_Maximizable(This,isMaximizable) + +#define IITBrowserWindow_get_Maximized(This,isMaximized) \ + (This)->lpVtbl -> get_Maximized(This,isMaximized) + +#define IITBrowserWindow_put_Maximized(This,shouldBeMaximized) \ + (This)->lpVtbl -> put_Maximized(This,shouldBeMaximized) + +#define IITBrowserWindow_get_Zoomable(This,isZoomable) \ + (This)->lpVtbl -> get_Zoomable(This,isZoomable) + +#define IITBrowserWindow_get_Zoomed(This,isZoomed) \ + (This)->lpVtbl -> get_Zoomed(This,isZoomed) + +#define IITBrowserWindow_put_Zoomed(This,shouldBeZoomed) \ + (This)->lpVtbl -> put_Zoomed(This,shouldBeZoomed) + +#define IITBrowserWindow_get_Top(This,top) \ + (This)->lpVtbl -> get_Top(This,top) + +#define IITBrowserWindow_put_Top(This,top) \ + (This)->lpVtbl -> put_Top(This,top) + +#define IITBrowserWindow_get_Left(This,left) \ + (This)->lpVtbl -> get_Left(This,left) + +#define IITBrowserWindow_put_Left(This,left) \ + (This)->lpVtbl -> put_Left(This,left) + +#define IITBrowserWindow_get_Bottom(This,bottom) \ + (This)->lpVtbl -> get_Bottom(This,bottom) + +#define IITBrowserWindow_put_Bottom(This,bottom) \ + (This)->lpVtbl -> put_Bottom(This,bottom) + +#define IITBrowserWindow_get_Right(This,right) \ + (This)->lpVtbl -> get_Right(This,right) + +#define IITBrowserWindow_put_Right(This,right) \ + (This)->lpVtbl -> put_Right(This,right) + +#define IITBrowserWindow_get_Width(This,width) \ + (This)->lpVtbl -> get_Width(This,width) + +#define IITBrowserWindow_put_Width(This,width) \ + (This)->lpVtbl -> put_Width(This,width) + +#define IITBrowserWindow_get_Height(This,height) \ + (This)->lpVtbl -> get_Height(This,height) + +#define IITBrowserWindow_put_Height(This,height) \ + (This)->lpVtbl -> put_Height(This,height) + + +#define IITBrowserWindow_get_MiniPlayer(This,isMiniPlayer) \ + (This)->lpVtbl -> get_MiniPlayer(This,isMiniPlayer) + +#define IITBrowserWindow_put_MiniPlayer(This,shouldBeMiniPlayer) \ + (This)->lpVtbl -> put_MiniPlayer(This,shouldBeMiniPlayer) + +#define IITBrowserWindow_get_SelectedTracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_SelectedTracks(This,iTrackCollection) + +#define IITBrowserWindow_get_SelectedPlaylist(This,iPlaylist) \ + (This)->lpVtbl -> get_SelectedPlaylist(This,iPlaylist) + +#define IITBrowserWindow_put_SelectedPlaylist(This,iPlaylist) \ + (This)->lpVtbl -> put_SelectedPlaylist(This,iPlaylist) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_get_MiniPlayer_Proxy( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMiniPlayer); + + +void __RPC_STUB IITBrowserWindow_get_MiniPlayer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_put_MiniPlayer_Proxy( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMiniPlayer); + + +void __RPC_STUB IITBrowserWindow_put_MiniPlayer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_get_SelectedTracks_Proxy( + IITBrowserWindow * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IITBrowserWindow_get_SelectedTracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_get_SelectedPlaylist_Proxy( + IITBrowserWindow * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITBrowserWindow_get_SelectedPlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_put_SelectedPlaylist_Proxy( + IITBrowserWindow * This, + /* [in] */ VARIANT *iPlaylist); + + +void __RPC_STUB IITBrowserWindow_put_SelectedPlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITBrowserWindow_INTERFACE_DEFINED__ */ + + +#ifndef __IITWindowCollection_INTERFACE_DEFINED__ +#define __IITWindowCollection_INTERFACE_DEFINED__ + +/* interface IITWindowCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITWindowCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3D8DE381-6C0E-481f-A865-E2385F59FA43") + IITWindowCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITWindow **iWindow) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITWindow **iWindow) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITWindowCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITWindowCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITWindowCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITWindowCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITWindowCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITWindowCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITWindowCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITWindowCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITWindowCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITWindowCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITWindow **iWindow); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITWindowCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITWindow **iWindow); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITWindowCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + END_INTERFACE + } IITWindowCollectionVtbl; + + interface IITWindowCollection + { + CONST_VTBL struct IITWindowCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITWindowCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITWindowCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITWindowCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITWindowCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITWindowCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITWindowCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITWindowCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITWindowCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITWindowCollection_get_Item(This,index,iWindow) \ + (This)->lpVtbl -> get_Item(This,index,iWindow) + +#define IITWindowCollection_get_ItemByName(This,name,iWindow) \ + (This)->lpVtbl -> get_ItemByName(This,name,iWindow) + +#define IITWindowCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get_Count_Proxy( + IITWindowCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITWindowCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get_Item_Proxy( + IITWindowCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITWindow **iWindow); + + +void __RPC_STUB IITWindowCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get_ItemByName_Proxy( + IITWindowCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITWindow **iWindow); + + +void __RPC_STUB IITWindowCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get__NewEnum_Proxy( + IITWindowCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITWindowCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITWindowCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IiTunes_INTERFACE_DEFINED__ +#define __IiTunes_INTERFACE_DEFINED__ + +/* interface IiTunes */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + + + +EXTERN_C const IID IID_IiTunes; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9DD6680B-3EDC-40db-A771-E6FE4832E34A") + IiTunes : public IDispatch + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE BackTrack( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE FastForward( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE NextTrack( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Pause( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Play( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayFile( + /* [in] */ BSTR filePath) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayPause( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PreviousTrack( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Resume( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Rewind( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Stop( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFile( + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFiles( + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTrack( + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTracks( + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CheckVersion( + /* [in] */ long majorVersion, + /* [in] */ long minorVersion, + /* [retval][out] */ VARIANT_BOOL *isCompatible) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetITObjectByID( + /* [in] */ long sourceID, + /* [in] */ long playlistID, + /* [in] */ long trackID, + /* [in] */ long databaseID, + /* [retval][out] */ IITObject **iObject) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePlaylist( + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OpenURL( + /* [in] */ BSTR url) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GotoMusicStoreHomePage( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdateIPod( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Authorize( + /* [in] */ long numElems, + /* [size_is][in] */ VARIANT data[ ], + /* [size_is][in] */ BSTR names[ ]) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Quit( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Sources( + /* [retval][out] */ IITSourceCollection **iSourceCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Encoders( + /* [retval][out] */ IITEncoderCollection **iEncoderCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQPresets( + /* [retval][out] */ IITEQPresetCollection **iEQPresetCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Visuals( + /* [retval][out] */ IITVisualCollection **iVisualCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Windows( + /* [retval][out] */ IITWindowCollection **iWindowCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SoundVolume( + /* [retval][out] */ long *volume) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SoundVolume( + /* [in] */ long volume) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Mute( + /* [retval][out] */ VARIANT_BOOL *isMuted) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Mute( + /* [in] */ VARIANT_BOOL shouldMute) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayerState( + /* [retval][out] */ ITPlayerState *playerState) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayerPosition( + /* [retval][out] */ long *playerPos) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PlayerPosition( + /* [in] */ long playerPos) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentEncoder( + /* [retval][out] */ IITEncoder **iEncoder) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentEncoder( + /* [in] */ IITEncoder *iEncoder) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VisualsEnabled( + /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VisualsEnabled( + /* [in] */ VARIANT_BOOL shouldEnable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_FullScreenVisuals( + /* [retval][out] */ VARIANT_BOOL *isFullScreen) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_FullScreenVisuals( + /* [in] */ VARIANT_BOOL shouldUseFullScreen) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VisualSize( + /* [retval][out] */ ITVisualSize *visualSize) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VisualSize( + /* [in] */ ITVisualSize visualSize) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentVisual( + /* [retval][out] */ IITVisual **iVisual) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentVisual( + /* [in] */ IITVisual *iVisual) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQEnabled( + /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EQEnabled( + /* [in] */ VARIANT_BOOL shouldEnable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentEQPreset( + /* [retval][out] */ IITEQPreset **iEQPreset) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentEQPreset( + /* [in] */ IITEQPreset *iEQPreset) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentStreamTitle( + /* [retval][out] */ BSTR *streamTitle) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentStreamURL( + /* [retval][out] */ BSTR *streamURL) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BrowserWindow( + /* [retval][out] */ IITBrowserWindow **iBrowserWindow) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQWindow( + /* [retval][out] */ IITWindow **iEQWindow) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LibrarySource( + /* [retval][out] */ IITSource **iLibrarySource) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LibraryPlaylist( + /* [retval][out] */ IITLibraryPlaylist **iLibraryPlaylist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentTrack( + /* [retval][out] */ IITTrack **iTrack) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentPlaylist( + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedTracks( + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Version( + /* [retval][out] */ BSTR *version) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetOptions( + /* [in] */ long options) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFile2( + /* [in] */ BSTR filePath, + /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFiles2( + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTrack2( + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTracks2( + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AppCommandMessageProcessingEnabled( + /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AppCommandMessageProcessingEnabled( + /* [in] */ VARIANT_BOOL shouldEnable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ForceToForegroundOnDialog( + /* [retval][out] */ VARIANT_BOOL *forceToForegroundOnDialog) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_ForceToForegroundOnDialog( + /* [in] */ VARIANT_BOOL forceToForegroundOnDialog) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateEQPreset( + /* [in] */ BSTR eqPresetName, + /* [retval][out] */ IITEQPreset **iEQPreset) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePlaylistInSource( + /* [in] */ BSTR playlistName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetPlayerButtonsState( + /* [out] */ VARIANT_BOOL *previousEnabled, + /* [out] */ ITPlayButtonState *playPauseStopState, + /* [out] */ VARIANT_BOOL *nextEnabled) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayerButtonClicked( + /* [in] */ ITPlayerButton playerButton, + /* [in] */ long playerButtonModifierKeys) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CanSetShuffle( + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetShuffle) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CanSetSongRepeat( + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetSongRepeat) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ConvertOperationStatus( + /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SubscribeToPodcast( + /* [in] */ BSTR url) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdatePodcastFeeds( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateFolder( + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateFolderInSource( + /* [in] */ BSTR folderName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iFolder) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SoundVolumeControlEnabled( + /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LibraryXMLPath( + /* [retval][out] */ BSTR *filePath) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ITObjectPersistentIDHigh( + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *highID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ITObjectPersistentIDLow( + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *lowID) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetITObjectPersistentIDs( + /* [in] */ VARIANT *iObject, + /* [out] */ long *highID, + /* [out] */ long *lowID) = 0; + + }; + +#else /* C style interface */ + + typedef struct IiTunesVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IiTunes * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IiTunes * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IiTunes * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IiTunes * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IiTunes * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IiTunes * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IiTunes * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *BackTrack )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *FastForward )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *NextTrack )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Pause )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFile )( + IiTunes * This, + /* [in] */ BSTR filePath); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayPause )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PreviousTrack )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Resume )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Rewind )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Stop )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFile )( + IiTunes * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFiles )( + IiTunes * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTrack )( + IiTunes * This, + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTracks )( + IiTunes * This, + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CheckVersion )( + IiTunes * This, + /* [in] */ long majorVersion, + /* [in] */ long minorVersion, + /* [retval][out] */ VARIANT_BOOL *isCompatible); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectByID )( + IiTunes * This, + /* [in] */ long sourceID, + /* [in] */ long playlistID, + /* [in] */ long trackID, + /* [in] */ long databaseID, + /* [retval][out] */ IITObject **iObject); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreatePlaylist )( + IiTunes * This, + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *OpenURL )( + IiTunes * This, + /* [in] */ BSTR url); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GotoMusicStoreHomePage )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdateIPod )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Authorize )( + IiTunes * This, + /* [in] */ long numElems, + /* [size_is][in] */ VARIANT data[ ], + /* [size_is][in] */ BSTR names[ ]); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Quit )( + IiTunes * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Sources )( + IiTunes * This, + /* [retval][out] */ IITSourceCollection **iSourceCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Encoders )( + IiTunes * This, + /* [retval][out] */ IITEncoderCollection **iEncoderCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQPresets )( + IiTunes * This, + /* [retval][out] */ IITEQPresetCollection **iEQPresetCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visuals )( + IiTunes * This, + /* [retval][out] */ IITVisualCollection **iVisualCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Windows )( + IiTunes * This, + /* [retval][out] */ IITWindowCollection **iWindowCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SoundVolume )( + IiTunes * This, + /* [retval][out] */ long *volume); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SoundVolume )( + IiTunes * This, + /* [in] */ long volume); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Mute )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isMuted); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Mute )( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldMute); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayerState )( + IiTunes * This, + /* [retval][out] */ ITPlayerState *playerState); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayerPosition )( + IiTunes * This, + /* [retval][out] */ long *playerPos); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayerPosition )( + IiTunes * This, + /* [in] */ long playerPos); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentEncoder )( + IiTunes * This, + /* [retval][out] */ IITEncoder **iEncoder); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_CurrentEncoder )( + IiTunes * This, + /* [in] */ IITEncoder *iEncoder); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VisualsEnabled )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VisualsEnabled )( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_FullScreenVisuals )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isFullScreen); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_FullScreenVisuals )( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldUseFullScreen); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VisualSize )( + IiTunes * This, + /* [retval][out] */ ITVisualSize *visualSize); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VisualSize )( + IiTunes * This, + /* [in] */ ITVisualSize visualSize); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentVisual )( + IiTunes * This, + /* [retval][out] */ IITVisual **iVisual); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_CurrentVisual )( + IiTunes * This, + /* [in] */ IITVisual *iVisual); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQEnabled )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQEnabled )( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentEQPreset )( + IiTunes * This, + /* [retval][out] */ IITEQPreset **iEQPreset); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_CurrentEQPreset )( + IiTunes * This, + /* [in] */ IITEQPreset *iEQPreset); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentStreamTitle )( + IiTunes * This, + /* [retval][out] */ BSTR *streamTitle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentStreamURL )( + IiTunes * This, + /* [retval][out] */ BSTR *streamURL); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BrowserWindow )( + IiTunes * This, + /* [retval][out] */ IITBrowserWindow **iBrowserWindow); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQWindow )( + IiTunes * This, + /* [retval][out] */ IITWindow **iEQWindow); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LibrarySource )( + IiTunes * This, + /* [retval][out] */ IITSource **iLibrarySource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LibraryPlaylist )( + IiTunes * This, + /* [retval][out] */ IITLibraryPlaylist **iLibraryPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentTrack )( + IiTunes * This, + /* [retval][out] */ IITTrack **iTrack); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentPlaylist )( + IiTunes * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedTracks )( + IiTunes * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Version )( + IiTunes * This, + /* [retval][out] */ BSTR *version); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetOptions )( + IiTunes * This, + /* [in] */ long options); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFile2 )( + IiTunes * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFiles2 )( + IiTunes * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTrack2 )( + IiTunes * This, + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTracks2 )( + IiTunes * This, + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AppCommandMessageProcessingEnabled )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AppCommandMessageProcessingEnabled )( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ForceToForegroundOnDialog )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *forceToForegroundOnDialog); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ForceToForegroundOnDialog )( + IiTunes * This, + /* [in] */ VARIANT_BOOL forceToForegroundOnDialog); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateEQPreset )( + IiTunes * This, + /* [in] */ BSTR eqPresetName, + /* [retval][out] */ IITEQPreset **iEQPreset); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreatePlaylistInSource )( + IiTunes * This, + /* [in] */ BSTR playlistName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPlayerButtonsState )( + IiTunes * This, + /* [out] */ VARIANT_BOOL *previousEnabled, + /* [out] */ ITPlayButtonState *playPauseStopState, + /* [out] */ VARIANT_BOOL *nextEnabled); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayerButtonClicked )( + IiTunes * This, + /* [in] */ ITPlayerButton playerButton, + /* [in] */ long playerButtonModifierKeys); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanSetShuffle )( + IiTunes * This, + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanSetSongRepeat )( + IiTunes * This, + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetSongRepeat); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ConvertOperationStatus )( + IiTunes * This, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SubscribeToPodcast )( + IiTunes * This, + /* [in] */ BSTR url); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdatePodcastFeeds )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateFolder )( + IiTunes * This, + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateFolderInSource )( + IiTunes * This, + /* [in] */ BSTR folderName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iFolder); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SoundVolumeControlEnabled )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LibraryXMLPath )( + IiTunes * This, + /* [retval][out] */ BSTR *filePath); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ITObjectPersistentIDHigh )( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *highID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ITObjectPersistentIDLow )( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *lowID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectPersistentIDs )( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [out] */ long *highID, + /* [out] */ long *lowID); + + END_INTERFACE + } IiTunesVtbl; + + interface IiTunes + { + CONST_VTBL struct IiTunesVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IiTunes_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IiTunes_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IiTunes_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IiTunes_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IiTunes_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IiTunes_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IiTunes_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IiTunes_BackTrack(This) \ + (This)->lpVtbl -> BackTrack(This) + +#define IiTunes_FastForward(This) \ + (This)->lpVtbl -> FastForward(This) + +#define IiTunes_NextTrack(This) \ + (This)->lpVtbl -> NextTrack(This) + +#define IiTunes_Pause(This) \ + (This)->lpVtbl -> Pause(This) + +#define IiTunes_Play(This) \ + (This)->lpVtbl -> Play(This) + +#define IiTunes_PlayFile(This,filePath) \ + (This)->lpVtbl -> PlayFile(This,filePath) + +#define IiTunes_PlayPause(This) \ + (This)->lpVtbl -> PlayPause(This) + +#define IiTunes_PreviousTrack(This) \ + (This)->lpVtbl -> PreviousTrack(This) + +#define IiTunes_Resume(This) \ + (This)->lpVtbl -> Resume(This) + +#define IiTunes_Rewind(This) \ + (This)->lpVtbl -> Rewind(This) + +#define IiTunes_Stop(This) \ + (This)->lpVtbl -> Stop(This) + +#define IiTunes_ConvertFile(This,filePath,iStatus) \ + (This)->lpVtbl -> ConvertFile(This,filePath,iStatus) + +#define IiTunes_ConvertFiles(This,filePaths,iStatus) \ + (This)->lpVtbl -> ConvertFiles(This,filePaths,iStatus) + +#define IiTunes_ConvertTrack(This,iTrackToConvert,iStatus) \ + (This)->lpVtbl -> ConvertTrack(This,iTrackToConvert,iStatus) + +#define IiTunes_ConvertTracks(This,iTracksToConvert,iStatus) \ + (This)->lpVtbl -> ConvertTracks(This,iTracksToConvert,iStatus) + +#define IiTunes_CheckVersion(This,majorVersion,minorVersion,isCompatible) \ + (This)->lpVtbl -> CheckVersion(This,majorVersion,minorVersion,isCompatible) + +#define IiTunes_GetITObjectByID(This,sourceID,playlistID,trackID,databaseID,iObject) \ + (This)->lpVtbl -> GetITObjectByID(This,sourceID,playlistID,trackID,databaseID,iObject) + +#define IiTunes_CreatePlaylist(This,playlistName,iPlaylist) \ + (This)->lpVtbl -> CreatePlaylist(This,playlistName,iPlaylist) + +#define IiTunes_OpenURL(This,url) \ + (This)->lpVtbl -> OpenURL(This,url) + +#define IiTunes_GotoMusicStoreHomePage(This) \ + (This)->lpVtbl -> GotoMusicStoreHomePage(This) + +#define IiTunes_UpdateIPod(This) \ + (This)->lpVtbl -> UpdateIPod(This) + +#define IiTunes_Authorize(This,numElems,data,names) \ + (This)->lpVtbl -> Authorize(This,numElems,data,names) + +#define IiTunes_Quit(This) \ + (This)->lpVtbl -> Quit(This) + +#define IiTunes_get_Sources(This,iSourceCollection) \ + (This)->lpVtbl -> get_Sources(This,iSourceCollection) + +#define IiTunes_get_Encoders(This,iEncoderCollection) \ + (This)->lpVtbl -> get_Encoders(This,iEncoderCollection) + +#define IiTunes_get_EQPresets(This,iEQPresetCollection) \ + (This)->lpVtbl -> get_EQPresets(This,iEQPresetCollection) + +#define IiTunes_get_Visuals(This,iVisualCollection) \ + (This)->lpVtbl -> get_Visuals(This,iVisualCollection) + +#define IiTunes_get_Windows(This,iWindowCollection) \ + (This)->lpVtbl -> get_Windows(This,iWindowCollection) + +#define IiTunes_get_SoundVolume(This,volume) \ + (This)->lpVtbl -> get_SoundVolume(This,volume) + +#define IiTunes_put_SoundVolume(This,volume) \ + (This)->lpVtbl -> put_SoundVolume(This,volume) + +#define IiTunes_get_Mute(This,isMuted) \ + (This)->lpVtbl -> get_Mute(This,isMuted) + +#define IiTunes_put_Mute(This,shouldMute) \ + (This)->lpVtbl -> put_Mute(This,shouldMute) + +#define IiTunes_get_PlayerState(This,playerState) \ + (This)->lpVtbl -> get_PlayerState(This,playerState) + +#define IiTunes_get_PlayerPosition(This,playerPos) \ + (This)->lpVtbl -> get_PlayerPosition(This,playerPos) + +#define IiTunes_put_PlayerPosition(This,playerPos) \ + (This)->lpVtbl -> put_PlayerPosition(This,playerPos) + +#define IiTunes_get_CurrentEncoder(This,iEncoder) \ + (This)->lpVtbl -> get_CurrentEncoder(This,iEncoder) + +#define IiTunes_put_CurrentEncoder(This,iEncoder) \ + (This)->lpVtbl -> put_CurrentEncoder(This,iEncoder) + +#define IiTunes_get_VisualsEnabled(This,isEnabled) \ + (This)->lpVtbl -> get_VisualsEnabled(This,isEnabled) + +#define IiTunes_put_VisualsEnabled(This,shouldEnable) \ + (This)->lpVtbl -> put_VisualsEnabled(This,shouldEnable) + +#define IiTunes_get_FullScreenVisuals(This,isFullScreen) \ + (This)->lpVtbl -> get_FullScreenVisuals(This,isFullScreen) + +#define IiTunes_put_FullScreenVisuals(This,shouldUseFullScreen) \ + (This)->lpVtbl -> put_FullScreenVisuals(This,shouldUseFullScreen) + +#define IiTunes_get_VisualSize(This,visualSize) \ + (This)->lpVtbl -> get_VisualSize(This,visualSize) + +#define IiTunes_put_VisualSize(This,visualSize) \ + (This)->lpVtbl -> put_VisualSize(This,visualSize) + +#define IiTunes_get_CurrentVisual(This,iVisual) \ + (This)->lpVtbl -> get_CurrentVisual(This,iVisual) + +#define IiTunes_put_CurrentVisual(This,iVisual) \ + (This)->lpVtbl -> put_CurrentVisual(This,iVisual) + +#define IiTunes_get_EQEnabled(This,isEnabled) \ + (This)->lpVtbl -> get_EQEnabled(This,isEnabled) + +#define IiTunes_put_EQEnabled(This,shouldEnable) \ + (This)->lpVtbl -> put_EQEnabled(This,shouldEnable) + +#define IiTunes_get_CurrentEQPreset(This,iEQPreset) \ + (This)->lpVtbl -> get_CurrentEQPreset(This,iEQPreset) + +#define IiTunes_put_CurrentEQPreset(This,iEQPreset) \ + (This)->lpVtbl -> put_CurrentEQPreset(This,iEQPreset) + +#define IiTunes_get_CurrentStreamTitle(This,streamTitle) \ + (This)->lpVtbl -> get_CurrentStreamTitle(This,streamTitle) + +#define IiTunes_get_CurrentStreamURL(This,streamURL) \ + (This)->lpVtbl -> get_CurrentStreamURL(This,streamURL) + +#define IiTunes_get_BrowserWindow(This,iBrowserWindow) \ + (This)->lpVtbl -> get_BrowserWindow(This,iBrowserWindow) + +#define IiTunes_get_EQWindow(This,iEQWindow) \ + (This)->lpVtbl -> get_EQWindow(This,iEQWindow) + +#define IiTunes_get_LibrarySource(This,iLibrarySource) \ + (This)->lpVtbl -> get_LibrarySource(This,iLibrarySource) + +#define IiTunes_get_LibraryPlaylist(This,iLibraryPlaylist) \ + (This)->lpVtbl -> get_LibraryPlaylist(This,iLibraryPlaylist) + +#define IiTunes_get_CurrentTrack(This,iTrack) \ + (This)->lpVtbl -> get_CurrentTrack(This,iTrack) + +#define IiTunes_get_CurrentPlaylist(This,iPlaylist) \ + (This)->lpVtbl -> get_CurrentPlaylist(This,iPlaylist) + +#define IiTunes_get_SelectedTracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_SelectedTracks(This,iTrackCollection) + +#define IiTunes_get_Version(This,version) \ + (This)->lpVtbl -> get_Version(This,version) + +#define IiTunes_SetOptions(This,options) \ + (This)->lpVtbl -> SetOptions(This,options) + +#define IiTunes_ConvertFile2(This,filePath,iStatus) \ + (This)->lpVtbl -> ConvertFile2(This,filePath,iStatus) + +#define IiTunes_ConvertFiles2(This,filePaths,iStatus) \ + (This)->lpVtbl -> ConvertFiles2(This,filePaths,iStatus) + +#define IiTunes_ConvertTrack2(This,iTrackToConvert,iStatus) \ + (This)->lpVtbl -> ConvertTrack2(This,iTrackToConvert,iStatus) + +#define IiTunes_ConvertTracks2(This,iTracksToConvert,iStatus) \ + (This)->lpVtbl -> ConvertTracks2(This,iTracksToConvert,iStatus) + +#define IiTunes_get_AppCommandMessageProcessingEnabled(This,isEnabled) \ + (This)->lpVtbl -> get_AppCommandMessageProcessingEnabled(This,isEnabled) + +#define IiTunes_put_AppCommandMessageProcessingEnabled(This,shouldEnable) \ + (This)->lpVtbl -> put_AppCommandMessageProcessingEnabled(This,shouldEnable) + +#define IiTunes_get_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) \ + (This)->lpVtbl -> get_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) + +#define IiTunes_put_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) \ + (This)->lpVtbl -> put_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) + +#define IiTunes_CreateEQPreset(This,eqPresetName,iEQPreset) \ + (This)->lpVtbl -> CreateEQPreset(This,eqPresetName,iEQPreset) + +#define IiTunes_CreatePlaylistInSource(This,playlistName,iSource,iPlaylist) \ + (This)->lpVtbl -> CreatePlaylistInSource(This,playlistName,iSource,iPlaylist) + +#define IiTunes_GetPlayerButtonsState(This,previousEnabled,playPauseStopState,nextEnabled) \ + (This)->lpVtbl -> GetPlayerButtonsState(This,previousEnabled,playPauseStopState,nextEnabled) + +#define IiTunes_PlayerButtonClicked(This,playerButton,playerButtonModifierKeys) \ + (This)->lpVtbl -> PlayerButtonClicked(This,playerButton,playerButtonModifierKeys) + +#define IiTunes_get_CanSetShuffle(This,iPlaylist,canSetShuffle) \ + (This)->lpVtbl -> get_CanSetShuffle(This,iPlaylist,canSetShuffle) + +#define IiTunes_get_CanSetSongRepeat(This,iPlaylist,canSetSongRepeat) \ + (This)->lpVtbl -> get_CanSetSongRepeat(This,iPlaylist,canSetSongRepeat) + +#define IiTunes_get_ConvertOperationStatus(This,iStatus) \ + (This)->lpVtbl -> get_ConvertOperationStatus(This,iStatus) + +#define IiTunes_SubscribeToPodcast(This,url) \ + (This)->lpVtbl -> SubscribeToPodcast(This,url) + +#define IiTunes_UpdatePodcastFeeds(This) \ + (This)->lpVtbl -> UpdatePodcastFeeds(This) + +#define IiTunes_CreateFolder(This,folderName,iFolder) \ + (This)->lpVtbl -> CreateFolder(This,folderName,iFolder) + +#define IiTunes_CreateFolderInSource(This,folderName,iSource,iFolder) \ + (This)->lpVtbl -> CreateFolderInSource(This,folderName,iSource,iFolder) + +#define IiTunes_get_SoundVolumeControlEnabled(This,isEnabled) \ + (This)->lpVtbl -> get_SoundVolumeControlEnabled(This,isEnabled) + +#define IiTunes_get_LibraryXMLPath(This,filePath) \ + (This)->lpVtbl -> get_LibraryXMLPath(This,filePath) + +#define IiTunes_get_ITObjectPersistentIDHigh(This,iObject,highID) \ + (This)->lpVtbl -> get_ITObjectPersistentIDHigh(This,iObject,highID) + +#define IiTunes_get_ITObjectPersistentIDLow(This,iObject,lowID) \ + (This)->lpVtbl -> get_ITObjectPersistentIDLow(This,iObject,lowID) + +#define IiTunes_GetITObjectPersistentIDs(This,iObject,highID,lowID) \ + (This)->lpVtbl -> GetITObjectPersistentIDs(This,iObject,highID,lowID) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_BackTrack_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_BackTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_FastForward_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_FastForward_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_NextTrack_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_NextTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Pause_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Pause_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Play_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Play_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PlayFile_Proxy( + IiTunes * This, + /* [in] */ BSTR filePath); + + +void __RPC_STUB IiTunes_PlayFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PlayPause_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_PlayPause_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PreviousTrack_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_PreviousTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Resume_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Resume_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Rewind_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Rewind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Stop_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Stop_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFile_Proxy( + IiTunes * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFiles_Proxy( + IiTunes * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertFiles_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTrack_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTracks_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertTracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CheckVersion_Proxy( + IiTunes * This, + /* [in] */ long majorVersion, + /* [in] */ long minorVersion, + /* [retval][out] */ VARIANT_BOOL *isCompatible); + + +void __RPC_STUB IiTunes_CheckVersion_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GetITObjectByID_Proxy( + IiTunes * This, + /* [in] */ long sourceID, + /* [in] */ long playlistID, + /* [in] */ long trackID, + /* [in] */ long databaseID, + /* [retval][out] */ IITObject **iObject); + + +void __RPC_STUB IiTunes_GetITObjectByID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreatePlaylist_Proxy( + IiTunes * This, + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IiTunes_CreatePlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_OpenURL_Proxy( + IiTunes * This, + /* [in] */ BSTR url); + + +void __RPC_STUB IiTunes_OpenURL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GotoMusicStoreHomePage_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_GotoMusicStoreHomePage_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_UpdateIPod_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_UpdateIPod_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Authorize_Proxy( + IiTunes * This, + /* [in] */ long numElems, + /* [size_is][in] */ VARIANT data[ ], + /* [size_is][in] */ BSTR names[ ]); + + +void __RPC_STUB IiTunes_Authorize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Quit_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Quit_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Sources_Proxy( + IiTunes * This, + /* [retval][out] */ IITSourceCollection **iSourceCollection); + + +void __RPC_STUB IiTunes_get_Sources_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Encoders_Proxy( + IiTunes * This, + /* [retval][out] */ IITEncoderCollection **iEncoderCollection); + + +void __RPC_STUB IiTunes_get_Encoders_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_EQPresets_Proxy( + IiTunes * This, + /* [retval][out] */ IITEQPresetCollection **iEQPresetCollection); + + +void __RPC_STUB IiTunes_get_EQPresets_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Visuals_Proxy( + IiTunes * This, + /* [retval][out] */ IITVisualCollection **iVisualCollection); + + +void __RPC_STUB IiTunes_get_Visuals_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Windows_Proxy( + IiTunes * This, + /* [retval][out] */ IITWindowCollection **iWindowCollection); + + +void __RPC_STUB IiTunes_get_Windows_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_SoundVolume_Proxy( + IiTunes * This, + /* [retval][out] */ long *volume); + + +void __RPC_STUB IiTunes_get_SoundVolume_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_SoundVolume_Proxy( + IiTunes * This, + /* [in] */ long volume); + + +void __RPC_STUB IiTunes_put_SoundVolume_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Mute_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isMuted); + + +void __RPC_STUB IiTunes_get_Mute_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_Mute_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldMute); + + +void __RPC_STUB IiTunes_put_Mute_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_PlayerState_Proxy( + IiTunes * This, + /* [retval][out] */ ITPlayerState *playerState); + + +void __RPC_STUB IiTunes_get_PlayerState_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_PlayerPosition_Proxy( + IiTunes * This, + /* [retval][out] */ long *playerPos); + + +void __RPC_STUB IiTunes_get_PlayerPosition_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_PlayerPosition_Proxy( + IiTunes * This, + /* [in] */ long playerPos); + + +void __RPC_STUB IiTunes_put_PlayerPosition_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentEncoder_Proxy( + IiTunes * This, + /* [retval][out] */ IITEncoder **iEncoder); + + +void __RPC_STUB IiTunes_get_CurrentEncoder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_CurrentEncoder_Proxy( + IiTunes * This, + /* [in] */ IITEncoder *iEncoder); + + +void __RPC_STUB IiTunes_put_CurrentEncoder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_VisualsEnabled_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + +void __RPC_STUB IiTunes_get_VisualsEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_VisualsEnabled_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + +void __RPC_STUB IiTunes_put_VisualsEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_FullScreenVisuals_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isFullScreen); + + +void __RPC_STUB IiTunes_get_FullScreenVisuals_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_FullScreenVisuals_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldUseFullScreen); + + +void __RPC_STUB IiTunes_put_FullScreenVisuals_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_VisualSize_Proxy( + IiTunes * This, + /* [retval][out] */ ITVisualSize *visualSize); + + +void __RPC_STUB IiTunes_get_VisualSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_VisualSize_Proxy( + IiTunes * This, + /* [in] */ ITVisualSize visualSize); + + +void __RPC_STUB IiTunes_put_VisualSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentVisual_Proxy( + IiTunes * This, + /* [retval][out] */ IITVisual **iVisual); + + +void __RPC_STUB IiTunes_get_CurrentVisual_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_CurrentVisual_Proxy( + IiTunes * This, + /* [in] */ IITVisual *iVisual); + + +void __RPC_STUB IiTunes_put_CurrentVisual_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_EQEnabled_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + +void __RPC_STUB IiTunes_get_EQEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_EQEnabled_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + +void __RPC_STUB IiTunes_put_EQEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentEQPreset_Proxy( + IiTunes * This, + /* [retval][out] */ IITEQPreset **iEQPreset); + + +void __RPC_STUB IiTunes_get_CurrentEQPreset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_CurrentEQPreset_Proxy( + IiTunes * This, + /* [in] */ IITEQPreset *iEQPreset); + + +void __RPC_STUB IiTunes_put_CurrentEQPreset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentStreamTitle_Proxy( + IiTunes * This, + /* [retval][out] */ BSTR *streamTitle); + + +void __RPC_STUB IiTunes_get_CurrentStreamTitle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentStreamURL_Proxy( + IiTunes * This, + /* [retval][out] */ BSTR *streamURL); + + +void __RPC_STUB IiTunes_get_CurrentStreamURL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_BrowserWindow_Proxy( + IiTunes * This, + /* [retval][out] */ IITBrowserWindow **iBrowserWindow); + + +void __RPC_STUB IiTunes_get_BrowserWindow_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_EQWindow_Proxy( + IiTunes * This, + /* [retval][out] */ IITWindow **iEQWindow); + + +void __RPC_STUB IiTunes_get_EQWindow_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_LibrarySource_Proxy( + IiTunes * This, + /* [retval][out] */ IITSource **iLibrarySource); + + +void __RPC_STUB IiTunes_get_LibrarySource_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_LibraryPlaylist_Proxy( + IiTunes * This, + /* [retval][out] */ IITLibraryPlaylist **iLibraryPlaylist); + + +void __RPC_STUB IiTunes_get_LibraryPlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentTrack_Proxy( + IiTunes * This, + /* [retval][out] */ IITTrack **iTrack); + + +void __RPC_STUB IiTunes_get_CurrentTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentPlaylist_Proxy( + IiTunes * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IiTunes_get_CurrentPlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_SelectedTracks_Proxy( + IiTunes * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IiTunes_get_SelectedTracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Version_Proxy( + IiTunes * This, + /* [retval][out] */ BSTR *version); + + +void __RPC_STUB IiTunes_get_Version_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_SetOptions_Proxy( + IiTunes * This, + /* [in] */ long options); + + +void __RPC_STUB IiTunes_SetOptions_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFile2_Proxy( + IiTunes * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertFile2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFiles2_Proxy( + IiTunes * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertFiles2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTrack2_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertTrack2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTracks2_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertTracks2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_AppCommandMessageProcessingEnabled_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + +void __RPC_STUB IiTunes_get_AppCommandMessageProcessingEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_AppCommandMessageProcessingEnabled_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + +void __RPC_STUB IiTunes_put_AppCommandMessageProcessingEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ForceToForegroundOnDialog_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *forceToForegroundOnDialog); + + +void __RPC_STUB IiTunes_get_ForceToForegroundOnDialog_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_ForceToForegroundOnDialog_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL forceToForegroundOnDialog); + + +void __RPC_STUB IiTunes_put_ForceToForegroundOnDialog_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreateEQPreset_Proxy( + IiTunes * This, + /* [in] */ BSTR eqPresetName, + /* [retval][out] */ IITEQPreset **iEQPreset); + + +void __RPC_STUB IiTunes_CreateEQPreset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreatePlaylistInSource_Proxy( + IiTunes * This, + /* [in] */ BSTR playlistName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IiTunes_CreatePlaylistInSource_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GetPlayerButtonsState_Proxy( + IiTunes * This, + /* [out] */ VARIANT_BOOL *previousEnabled, + /* [out] */ ITPlayButtonState *playPauseStopState, + /* [out] */ VARIANT_BOOL *nextEnabled); + + +void __RPC_STUB IiTunes_GetPlayerButtonsState_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PlayerButtonClicked_Proxy( + IiTunes * This, + /* [in] */ ITPlayerButton playerButton, + /* [in] */ long playerButtonModifierKeys); + + +void __RPC_STUB IiTunes_PlayerButtonClicked_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CanSetShuffle_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetShuffle); + + +void __RPC_STUB IiTunes_get_CanSetShuffle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CanSetSongRepeat_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetSongRepeat); + + +void __RPC_STUB IiTunes_get_CanSetSongRepeat_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ConvertOperationStatus_Proxy( + IiTunes * This, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_get_ConvertOperationStatus_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_SubscribeToPodcast_Proxy( + IiTunes * This, + /* [in] */ BSTR url); + + +void __RPC_STUB IiTunes_SubscribeToPodcast_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_UpdatePodcastFeeds_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_UpdatePodcastFeeds_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreateFolder_Proxy( + IiTunes * This, + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder); + + +void __RPC_STUB IiTunes_CreateFolder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreateFolderInSource_Proxy( + IiTunes * This, + /* [in] */ BSTR folderName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iFolder); + + +void __RPC_STUB IiTunes_CreateFolderInSource_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_SoundVolumeControlEnabled_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + +void __RPC_STUB IiTunes_get_SoundVolumeControlEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_LibraryXMLPath_Proxy( + IiTunes * This, + /* [retval][out] */ BSTR *filePath); + + +void __RPC_STUB IiTunes_get_LibraryXMLPath_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ITObjectPersistentIDHigh_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *highID); + + +void __RPC_STUB IiTunes_get_ITObjectPersistentIDHigh_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ITObjectPersistentIDLow_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *lowID); + + +void __RPC_STUB IiTunes_get_ITObjectPersistentIDLow_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GetITObjectPersistentIDs_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [out] */ long *highID, + /* [out] */ long *lowID); + + +void __RPC_STUB IiTunes_GetITObjectPersistentIDs_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IiTunes_INTERFACE_DEFINED__ */ + + +#ifndef ___IiTunesEvents_DISPINTERFACE_DEFINED__ +#define ___IiTunesEvents_DISPINTERFACE_DEFINED__ + +/* dispinterface _IiTunesEvents */ +/* [helpstring][uuid] */ + + +EXTERN_C const IID DIID__IiTunesEvents; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5846EB78-317E-4b6f-B0C3-11EE8C8FEEF2") + _IiTunesEvents : public IDispatch + { + }; + +#else /* C style interface */ + + typedef struct _IiTunesEventsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + _IiTunesEvents * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + _IiTunesEvents * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + _IiTunesEvents * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + _IiTunesEvents * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + _IiTunesEvents * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + _IiTunesEvents * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + _IiTunesEvents * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + END_INTERFACE + } _IiTunesEventsVtbl; + + interface _IiTunesEvents + { + CONST_VTBL struct _IiTunesEventsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define _IiTunesEvents_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define _IiTunesEvents_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define _IiTunesEvents_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define _IiTunesEvents_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define _IiTunesEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define _IiTunesEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define _IiTunesEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + +#endif /* ___IiTunesEvents_DISPINTERFACE_DEFINED__ */ + + +#ifndef ___IITConvertOperationStatusEvents_DISPINTERFACE_DEFINED__ +#define ___IITConvertOperationStatusEvents_DISPINTERFACE_DEFINED__ + +/* dispinterface _IITConvertOperationStatusEvents */ +/* [helpstring][uuid] */ + + +EXTERN_C const IID DIID__IITConvertOperationStatusEvents; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5C47A705-8E8A-45a1-9EED-71C993F0BF60") + _IITConvertOperationStatusEvents : public IDispatch + { + }; + +#else /* C style interface */ + + typedef struct _IITConvertOperationStatusEventsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + _IITConvertOperationStatusEvents * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + _IITConvertOperationStatusEvents * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + _IITConvertOperationStatusEvents * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + _IITConvertOperationStatusEvents * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + _IITConvertOperationStatusEvents * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + _IITConvertOperationStatusEvents * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + _IITConvertOperationStatusEvents * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + END_INTERFACE + } _IITConvertOperationStatusEventsVtbl; + + interface _IITConvertOperationStatusEvents + { + CONST_VTBL struct _IITConvertOperationStatusEventsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define _IITConvertOperationStatusEvents_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define _IITConvertOperationStatusEvents_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define _IITConvertOperationStatusEvents_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define _IITConvertOperationStatusEvents_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define _IITConvertOperationStatusEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define _IITConvertOperationStatusEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define _IITConvertOperationStatusEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + +#endif /* ___IITConvertOperationStatusEvents_DISPINTERFACE_DEFINED__ */ + + +EXTERN_C const CLSID CLSID_iTunesApp; + +#ifdef __cplusplus + +class DECLSPEC_UUID("DC0C2640-1415-4644-875C-6F4D769839BA") +iTunesApp; +#endif + +EXTERN_C const CLSID CLSID_iTunesConvertOperationStatus; + +#ifdef __cplusplus + +class DECLSPEC_UUID("D06596AD-C900-41b2-BC68-1B486450FC56") +iTunesConvertOperationStatus; +#endif + +#ifndef __IITArtwork_INTERFACE_DEFINED__ +#define __IITArtwork_INTERFACE_DEFINED__ + +/* interface IITArtwork */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITArtwork; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("D0A6C1F8-BF3D-4cd8-AC47-FE32BDD17257") + IITArtwork : public IDispatch + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetArtworkFromFile( + /* [in] */ BSTR filePath) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SaveArtworkToFile( + /* [in] */ BSTR filePath) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Format( + /* [retval][out] */ ITArtworkFormat *format) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_IsDownloadedArtwork( + /* [retval][out] */ VARIANT_BOOL *isDownloadedArtwork) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Description( + /* [retval][out] */ BSTR *description) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Description( + /* [in] */ BSTR description) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITArtworkVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITArtwork * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITArtwork * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITArtwork * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITArtwork * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITArtwork * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITArtwork * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITArtwork * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITArtwork * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetArtworkFromFile )( + IITArtwork * This, + /* [in] */ BSTR filePath); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SaveArtworkToFile )( + IITArtwork * This, + /* [in] */ BSTR filePath); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Format )( + IITArtwork * This, + /* [retval][out] */ ITArtworkFormat *format); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsDownloadedArtwork )( + IITArtwork * This, + /* [retval][out] */ VARIANT_BOOL *isDownloadedArtwork); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Description )( + IITArtwork * This, + /* [retval][out] */ BSTR *description); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Description )( + IITArtwork * This, + /* [in] */ BSTR description); + + END_INTERFACE + } IITArtworkVtbl; + + interface IITArtwork + { + CONST_VTBL struct IITArtworkVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITArtwork_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITArtwork_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITArtwork_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITArtwork_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITArtwork_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITArtwork_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITArtwork_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITArtwork_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITArtwork_SetArtworkFromFile(This,filePath) \ + (This)->lpVtbl -> SetArtworkFromFile(This,filePath) + +#define IITArtwork_SaveArtworkToFile(This,filePath) \ + (This)->lpVtbl -> SaveArtworkToFile(This,filePath) + +#define IITArtwork_get_Format(This,format) \ + (This)->lpVtbl -> get_Format(This,format) + +#define IITArtwork_get_IsDownloadedArtwork(This,isDownloadedArtwork) \ + (This)->lpVtbl -> get_IsDownloadedArtwork(This,isDownloadedArtwork) + +#define IITArtwork_get_Description(This,description) \ + (This)->lpVtbl -> get_Description(This,description) + +#define IITArtwork_put_Description(This,description) \ + (This)->lpVtbl -> put_Description(This,description) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITArtwork_Delete_Proxy( + IITArtwork * This); + + +void __RPC_STUB IITArtwork_Delete_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITArtwork_SetArtworkFromFile_Proxy( + IITArtwork * This, + /* [in] */ BSTR filePath); + + +void __RPC_STUB IITArtwork_SetArtworkFromFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITArtwork_SaveArtworkToFile_Proxy( + IITArtwork * This, + /* [in] */ BSTR filePath); + + +void __RPC_STUB IITArtwork_SaveArtworkToFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtwork_get_Format_Proxy( + IITArtwork * This, + /* [retval][out] */ ITArtworkFormat *format); + + +void __RPC_STUB IITArtwork_get_Format_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtwork_get_IsDownloadedArtwork_Proxy( + IITArtwork * This, + /* [retval][out] */ VARIANT_BOOL *isDownloadedArtwork); + + +void __RPC_STUB IITArtwork_get_IsDownloadedArtwork_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtwork_get_Description_Proxy( + IITArtwork * This, + /* [retval][out] */ BSTR *description); + + +void __RPC_STUB IITArtwork_get_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITArtwork_put_Description_Proxy( + IITArtwork * This, + /* [in] */ BSTR description); + + +void __RPC_STUB IITArtwork_put_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITArtwork_INTERFACE_DEFINED__ */ + + +#ifndef __IITArtworkCollection_INTERFACE_DEFINED__ +#define __IITArtworkCollection_INTERFACE_DEFINED__ + +/* interface IITArtworkCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITArtworkCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("BF2742D7-418C-4858-9AF9-2981B062D23E") + IITArtworkCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITArtwork **iArtwork) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITArtworkCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITArtworkCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITArtworkCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITArtworkCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITArtworkCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITArtworkCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITArtworkCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITArtworkCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITArtworkCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITArtworkCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITArtwork **iArtwork); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITArtworkCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + END_INTERFACE + } IITArtworkCollectionVtbl; + + interface IITArtworkCollection + { + CONST_VTBL struct IITArtworkCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITArtworkCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITArtworkCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITArtworkCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITArtworkCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITArtworkCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITArtworkCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITArtworkCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITArtworkCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITArtworkCollection_get_Item(This,index,iArtwork) \ + (This)->lpVtbl -> get_Item(This,index,iArtwork) + +#define IITArtworkCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtworkCollection_get_Count_Proxy( + IITArtworkCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITArtworkCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITArtworkCollection_get_Item_Proxy( + IITArtworkCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITArtwork **iArtwork); + + +void __RPC_STUB IITArtworkCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITArtworkCollection_get__NewEnum_Proxy( + IITArtworkCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITArtworkCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITArtworkCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITURLTrack_INTERFACE_DEFINED__ +#define __IITURLTrack_INTERFACE_DEFINED__ + +/* interface IITURLTrack */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITURLTrack; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("1116E3B5-29FD-4393-A7BD-454E5E327900") + IITURLTrack : public IITTrack + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_URL( + /* [retval][out] */ BSTR *url) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_URL( + /* [in] */ BSTR url) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Podcast( + /* [retval][out] */ VARIANT_BOOL *isPodcast) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdatePodcastFeed( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE DownloadPodcastEpisode( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Category( + /* [retval][out] */ BSTR *category) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Category( + /* [in] */ BSTR category) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Description( + /* [retval][out] */ BSTR *description) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Description( + /* [in] */ BSTR description) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LongDescription( + /* [retval][out] */ BSTR *longDescription) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_LongDescription( + /* [in] */ BSTR longDescription) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRating( + /* [retval][out] */ long *rating) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AlbumRating( + /* [in] */ long rating) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRatingKind( + /* [retval][out] */ ITRatingKind *ratingKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RatingKind( + /* [retval][out] */ ITRatingKind *ratingKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlists( + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITURLTrackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITURLTrack * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITURLTrack * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITURLTrack * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITURLTrack * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITURLTrack * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITURLTrack * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITURLTrack * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITURLTrack * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITURLTrack * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITURLTrack * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITURLTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITURLTrack * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITURLTrack * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITURLTrack * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITURLTrack * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITURLTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( + IITURLTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddArtworkFromFile )( + IITURLTrack * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITArtwork **iArtwork); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITURLTrack * This, + /* [retval][out] */ ITTrackKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( + IITURLTrack * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Album )( + IITURLTrack * This, + /* [retval][out] */ BSTR *album); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Album )( + IITURLTrack * This, + /* [in] */ BSTR album); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( + IITURLTrack * This, + /* [retval][out] */ BSTR *artist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Artist )( + IITURLTrack * This, + /* [in] */ BSTR artist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BitRate )( + IITURLTrack * This, + /* [retval][out] */ long *bitrate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BPM )( + IITURLTrack * This, + /* [retval][out] */ long *beatsPerMinute); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BPM )( + IITURLTrack * This, + /* [in] */ long beatsPerMinute); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Comment )( + IITURLTrack * This, + /* [retval][out] */ BSTR *comment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Comment )( + IITURLTrack * This, + /* [in] */ BSTR comment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( + IITURLTrack * This, + /* [retval][out] */ VARIANT_BOOL *isCompilation); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Compilation )( + IITURLTrack * This, + /* [in] */ VARIANT_BOOL shouldBeCompilation); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( + IITURLTrack * This, + /* [retval][out] */ BSTR *composer); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Composer )( + IITURLTrack * This, + /* [in] */ BSTR composer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DateAdded )( + IITURLTrack * This, + /* [retval][out] */ DATE *dateAdded); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( + IITURLTrack * This, + /* [retval][out] */ long *discCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscCount )( + IITURLTrack * This, + /* [in] */ long discCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( + IITURLTrack * This, + /* [retval][out] */ long *discNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscNumber )( + IITURLTrack * This, + /* [in] */ long discNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITURLTrack * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Enabled )( + IITURLTrack * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Enabled )( + IITURLTrack * This, + /* [in] */ VARIANT_BOOL shouldBeEnabled); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQ )( + IITURLTrack * This, + /* [retval][out] */ BSTR *eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQ )( + IITURLTrack * This, + /* [in] */ BSTR eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Finish )( + IITURLTrack * This, + /* [in] */ long finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Finish )( + IITURLTrack * This, + /* [retval][out] */ long *finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( + IITURLTrack * This, + /* [retval][out] */ BSTR *genre); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Genre )( + IITURLTrack * This, + /* [in] */ BSTR genre); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Grouping )( + IITURLTrack * This, + /* [retval][out] */ BSTR *grouping); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Grouping )( + IITURLTrack * This, + /* [in] */ BSTR grouping); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_KindAsString )( + IITURLTrack * This, + /* [retval][out] */ BSTR *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ModificationDate )( + IITURLTrack * This, + /* [retval][out] */ DATE *dateModified); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedCount )( + IITURLTrack * This, + /* [retval][out] */ long *playedCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedCount )( + IITURLTrack * This, + /* [in] */ long playedCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedDate )( + IITURLTrack * This, + /* [retval][out] */ DATE *playedDate); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedDate )( + IITURLTrack * This, + /* [in] */ DATE playedDate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayOrderIndex )( + IITURLTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Rating )( + IITURLTrack * This, + /* [retval][out] */ long *rating); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Rating )( + IITURLTrack * This, + /* [in] */ long rating); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SampleRate )( + IITURLTrack * This, + /* [retval][out] */ long *sampleRate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITURLTrack * This, + /* [retval][out] */ long *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Start )( + IITURLTrack * This, + /* [retval][out] */ long *start); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Start )( + IITURLTrack * This, + /* [in] */ long start); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITURLTrack * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackCount )( + IITURLTrack * This, + /* [retval][out] */ long *trackCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackCount )( + IITURLTrack * This, + /* [in] */ long trackCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackNumber )( + IITURLTrack * This, + /* [retval][out] */ long *trackNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackNumber )( + IITURLTrack * This, + /* [in] */ long trackNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VolumeAdjustment )( + IITURLTrack * This, + /* [retval][out] */ long *volumeAdjustment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VolumeAdjustment )( + IITURLTrack * This, + /* [in] */ long volumeAdjustment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( + IITURLTrack * This, + /* [retval][out] */ long *year); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Year )( + IITURLTrack * This, + /* [in] */ long year); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artwork )( + IITURLTrack * This, + /* [retval][out] */ IITArtworkCollection **iArtworkCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_URL )( + IITURLTrack * This, + /* [retval][out] */ BSTR *url); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_URL )( + IITURLTrack * This, + /* [in] */ BSTR url); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Podcast )( + IITURLTrack * This, + /* [retval][out] */ VARIANT_BOOL *isPodcast); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdatePodcastFeed )( + IITURLTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *DownloadPodcastEpisode )( + IITURLTrack * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Category )( + IITURLTrack * This, + /* [retval][out] */ BSTR *category); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Category )( + IITURLTrack * This, + /* [in] */ BSTR category); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Description )( + IITURLTrack * This, + /* [retval][out] */ BSTR *description); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Description )( + IITURLTrack * This, + /* [in] */ BSTR description); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LongDescription )( + IITURLTrack * This, + /* [retval][out] */ BSTR *longDescription); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LongDescription )( + IITURLTrack * This, + /* [in] */ BSTR longDescription); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( + IITURLTrack * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRating )( + IITURLTrack * This, + /* [retval][out] */ long *rating); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AlbumRating )( + IITURLTrack * This, + /* [in] */ long rating); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRatingKind )( + IITURLTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RatingKind )( + IITURLTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( + IITURLTrack * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + END_INTERFACE + } IITURLTrackVtbl; + + interface IITURLTrack + { + CONST_VTBL struct IITURLTrackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITURLTrack_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITURLTrack_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITURLTrack_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITURLTrack_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITURLTrack_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITURLTrack_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITURLTrack_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITURLTrack_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITURLTrack_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITURLTrack_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITURLTrack_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITURLTrack_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITURLTrack_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITURLTrack_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITURLTrack_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITURLTrack_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITURLTrack_Play(This) \ + (This)->lpVtbl -> Play(This) + +#define IITURLTrack_AddArtworkFromFile(This,filePath,iArtwork) \ + (This)->lpVtbl -> AddArtworkFromFile(This,filePath,iArtwork) + +#define IITURLTrack_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITURLTrack_get_Playlist(This,iPlaylist) \ + (This)->lpVtbl -> get_Playlist(This,iPlaylist) + +#define IITURLTrack_get_Album(This,album) \ + (This)->lpVtbl -> get_Album(This,album) + +#define IITURLTrack_put_Album(This,album) \ + (This)->lpVtbl -> put_Album(This,album) + +#define IITURLTrack_get_Artist(This,artist) \ + (This)->lpVtbl -> get_Artist(This,artist) + +#define IITURLTrack_put_Artist(This,artist) \ + (This)->lpVtbl -> put_Artist(This,artist) + +#define IITURLTrack_get_BitRate(This,bitrate) \ + (This)->lpVtbl -> get_BitRate(This,bitrate) + +#define IITURLTrack_get_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> get_BPM(This,beatsPerMinute) + +#define IITURLTrack_put_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> put_BPM(This,beatsPerMinute) + +#define IITURLTrack_get_Comment(This,comment) \ + (This)->lpVtbl -> get_Comment(This,comment) + +#define IITURLTrack_put_Comment(This,comment) \ + (This)->lpVtbl -> put_Comment(This,comment) + +#define IITURLTrack_get_Compilation(This,isCompilation) \ + (This)->lpVtbl -> get_Compilation(This,isCompilation) + +#define IITURLTrack_put_Compilation(This,shouldBeCompilation) \ + (This)->lpVtbl -> put_Compilation(This,shouldBeCompilation) + +#define IITURLTrack_get_Composer(This,composer) \ + (This)->lpVtbl -> get_Composer(This,composer) + +#define IITURLTrack_put_Composer(This,composer) \ + (This)->lpVtbl -> put_Composer(This,composer) + +#define IITURLTrack_get_DateAdded(This,dateAdded) \ + (This)->lpVtbl -> get_DateAdded(This,dateAdded) + +#define IITURLTrack_get_DiscCount(This,discCount) \ + (This)->lpVtbl -> get_DiscCount(This,discCount) + +#define IITURLTrack_put_DiscCount(This,discCount) \ + (This)->lpVtbl -> put_DiscCount(This,discCount) + +#define IITURLTrack_get_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> get_DiscNumber(This,discNumber) + +#define IITURLTrack_put_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> put_DiscNumber(This,discNumber) + +#define IITURLTrack_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITURLTrack_get_Enabled(This,isEnabled) \ + (This)->lpVtbl -> get_Enabled(This,isEnabled) + +#define IITURLTrack_put_Enabled(This,shouldBeEnabled) \ + (This)->lpVtbl -> put_Enabled(This,shouldBeEnabled) + +#define IITURLTrack_get_EQ(This,eq) \ + (This)->lpVtbl -> get_EQ(This,eq) + +#define IITURLTrack_put_EQ(This,eq) \ + (This)->lpVtbl -> put_EQ(This,eq) + +#define IITURLTrack_put_Finish(This,finish) \ + (This)->lpVtbl -> put_Finish(This,finish) + +#define IITURLTrack_get_Finish(This,finish) \ + (This)->lpVtbl -> get_Finish(This,finish) + +#define IITURLTrack_get_Genre(This,genre) \ + (This)->lpVtbl -> get_Genre(This,genre) + +#define IITURLTrack_put_Genre(This,genre) \ + (This)->lpVtbl -> put_Genre(This,genre) + +#define IITURLTrack_get_Grouping(This,grouping) \ + (This)->lpVtbl -> get_Grouping(This,grouping) + +#define IITURLTrack_put_Grouping(This,grouping) \ + (This)->lpVtbl -> put_Grouping(This,grouping) + +#define IITURLTrack_get_KindAsString(This,kind) \ + (This)->lpVtbl -> get_KindAsString(This,kind) + +#define IITURLTrack_get_ModificationDate(This,dateModified) \ + (This)->lpVtbl -> get_ModificationDate(This,dateModified) + +#define IITURLTrack_get_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> get_PlayedCount(This,playedCount) + +#define IITURLTrack_put_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> put_PlayedCount(This,playedCount) + +#define IITURLTrack_get_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> get_PlayedDate(This,playedDate) + +#define IITURLTrack_put_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> put_PlayedDate(This,playedDate) + +#define IITURLTrack_get_PlayOrderIndex(This,index) \ + (This)->lpVtbl -> get_PlayOrderIndex(This,index) + +#define IITURLTrack_get_Rating(This,rating) \ + (This)->lpVtbl -> get_Rating(This,rating) + +#define IITURLTrack_put_Rating(This,rating) \ + (This)->lpVtbl -> put_Rating(This,rating) + +#define IITURLTrack_get_SampleRate(This,sampleRate) \ + (This)->lpVtbl -> get_SampleRate(This,sampleRate) + +#define IITURLTrack_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITURLTrack_get_Start(This,start) \ + (This)->lpVtbl -> get_Start(This,start) + +#define IITURLTrack_put_Start(This,start) \ + (This)->lpVtbl -> put_Start(This,start) + +#define IITURLTrack_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITURLTrack_get_TrackCount(This,trackCount) \ + (This)->lpVtbl -> get_TrackCount(This,trackCount) + +#define IITURLTrack_put_TrackCount(This,trackCount) \ + (This)->lpVtbl -> put_TrackCount(This,trackCount) + +#define IITURLTrack_get_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> get_TrackNumber(This,trackNumber) + +#define IITURLTrack_put_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> put_TrackNumber(This,trackNumber) + +#define IITURLTrack_get_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> get_VolumeAdjustment(This,volumeAdjustment) + +#define IITURLTrack_put_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> put_VolumeAdjustment(This,volumeAdjustment) + +#define IITURLTrack_get_Year(This,year) \ + (This)->lpVtbl -> get_Year(This,year) + +#define IITURLTrack_put_Year(This,year) \ + (This)->lpVtbl -> put_Year(This,year) + +#define IITURLTrack_get_Artwork(This,iArtworkCollection) \ + (This)->lpVtbl -> get_Artwork(This,iArtworkCollection) + + +#define IITURLTrack_get_URL(This,url) \ + (This)->lpVtbl -> get_URL(This,url) + +#define IITURLTrack_put_URL(This,url) \ + (This)->lpVtbl -> put_URL(This,url) + +#define IITURLTrack_get_Podcast(This,isPodcast) \ + (This)->lpVtbl -> get_Podcast(This,isPodcast) + +#define IITURLTrack_UpdatePodcastFeed(This) \ + (This)->lpVtbl -> UpdatePodcastFeed(This) + +#define IITURLTrack_DownloadPodcastEpisode(This) \ + (This)->lpVtbl -> DownloadPodcastEpisode(This) + +#define IITURLTrack_get_Category(This,category) \ + (This)->lpVtbl -> get_Category(This,category) + +#define IITURLTrack_put_Category(This,category) \ + (This)->lpVtbl -> put_Category(This,category) + +#define IITURLTrack_get_Description(This,description) \ + (This)->lpVtbl -> get_Description(This,description) + +#define IITURLTrack_put_Description(This,description) \ + (This)->lpVtbl -> put_Description(This,description) + +#define IITURLTrack_get_LongDescription(This,longDescription) \ + (This)->lpVtbl -> get_LongDescription(This,longDescription) + +#define IITURLTrack_put_LongDescription(This,longDescription) \ + (This)->lpVtbl -> put_LongDescription(This,longDescription) + +#define IITURLTrack_Reveal(This) \ + (This)->lpVtbl -> Reveal(This) + +#define IITURLTrack_get_AlbumRating(This,rating) \ + (This)->lpVtbl -> get_AlbumRating(This,rating) + +#define IITURLTrack_put_AlbumRating(This,rating) \ + (This)->lpVtbl -> put_AlbumRating(This,rating) + +#define IITURLTrack_get_AlbumRatingKind(This,ratingKind) \ + (This)->lpVtbl -> get_AlbumRatingKind(This,ratingKind) + +#define IITURLTrack_get_RatingKind(This,ratingKind) \ + (This)->lpVtbl -> get_RatingKind(This,ratingKind) + +#define IITURLTrack_get_Playlists(This,iPlaylistCollection) \ + (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_URL_Proxy( + IITURLTrack * This, + /* [retval][out] */ BSTR *url); + + +void __RPC_STUB IITURLTrack_get_URL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_URL_Proxy( + IITURLTrack * This, + /* [in] */ BSTR url); + + +void __RPC_STUB IITURLTrack_put_URL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Podcast_Proxy( + IITURLTrack * This, + /* [retval][out] */ VARIANT_BOOL *isPodcast); + + +void __RPC_STUB IITURLTrack_get_Podcast_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITURLTrack_UpdatePodcastFeed_Proxy( + IITURLTrack * This); + + +void __RPC_STUB IITURLTrack_UpdatePodcastFeed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITURLTrack_DownloadPodcastEpisode_Proxy( + IITURLTrack * This); + + +void __RPC_STUB IITURLTrack_DownloadPodcastEpisode_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Category_Proxy( + IITURLTrack * This, + /* [retval][out] */ BSTR *category); + + +void __RPC_STUB IITURLTrack_get_Category_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_Category_Proxy( + IITURLTrack * This, + /* [in] */ BSTR category); + + +void __RPC_STUB IITURLTrack_put_Category_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Description_Proxy( + IITURLTrack * This, + /* [retval][out] */ BSTR *description); + + +void __RPC_STUB IITURLTrack_get_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_Description_Proxy( + IITURLTrack * This, + /* [in] */ BSTR description); + + +void __RPC_STUB IITURLTrack_put_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_LongDescription_Proxy( + IITURLTrack * This, + /* [retval][out] */ BSTR *longDescription); + + +void __RPC_STUB IITURLTrack_get_LongDescription_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_LongDescription_Proxy( + IITURLTrack * This, + /* [in] */ BSTR longDescription); + + +void __RPC_STUB IITURLTrack_put_LongDescription_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITURLTrack_Reveal_Proxy( + IITURLTrack * This); + + +void __RPC_STUB IITURLTrack_Reveal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_AlbumRating_Proxy( + IITURLTrack * This, + /* [retval][out] */ long *rating); + + +void __RPC_STUB IITURLTrack_get_AlbumRating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_AlbumRating_Proxy( + IITURLTrack * This, + /* [in] */ long rating); + + +void __RPC_STUB IITURLTrack_put_AlbumRating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_AlbumRatingKind_Proxy( + IITURLTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + +void __RPC_STUB IITURLTrack_get_AlbumRatingKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_RatingKind_Proxy( + IITURLTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + +void __RPC_STUB IITURLTrack_get_RatingKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Playlists_Proxy( + IITURLTrack * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + +void __RPC_STUB IITURLTrack_get_Playlists_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITURLTrack_INTERFACE_DEFINED__ */ + + +#ifndef __IITAudioCDPlaylist_INTERFACE_DEFINED__ +#define __IITAudioCDPlaylist_INTERFACE_DEFINED__ + +/* interface IITAudioCDPlaylist */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITAudioCDPlaylist; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CF496DF3-0FED-4d7d-9BD8-529B6E8A082E") + IITAudioCDPlaylist : public IITPlaylist + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Artist( + /* [retval][out] */ BSTR *artist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Compilation( + /* [retval][out] */ VARIANT_BOOL *isCompiliation) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Composer( + /* [retval][out] */ BSTR *composer) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscCount( + /* [retval][out] */ long *discCount) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscNumber( + /* [retval][out] */ long *discNumber) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Genre( + /* [retval][out] */ BSTR *genre) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Year( + /* [retval][out] */ long *year) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITAudioCDPlaylistVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITAudioCDPlaylist * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITAudioCDPlaylist * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITAudioCDPlaylist * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITAudioCDPlaylist * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITAudioCDPlaylist * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITAudioCDPlaylist * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITAudioCDPlaylist * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITAudioCDPlaylist * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITAudioCDPlaylist * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITAudioCDPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( + IITAudioCDPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( + IITAudioCDPlaylist * This, + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( + IITAudioCDPlaylist * This, + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITAudioCDPlaylist * This, + /* [retval][out] */ ITPlaylistKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( + IITAudioCDPlaylist * This, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( + IITAudioCDPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShuffle); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( + IITAudioCDPlaylist * This, + /* [in] */ VARIANT_BOOL shouldShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITAudioCDPlaylist * This, + /* [retval][out] */ double *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( + IITAudioCDPlaylist * This, + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( + IITAudioCDPlaylist * This, + /* [in] */ ITPlaylistRepeatMode repeatMode); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITAudioCDPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITAudioCDPlaylist * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *artist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( + IITAudioCDPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isCompiliation); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *composer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *discCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *discNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *genre); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *year); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( + IITAudioCDPlaylist * This); + + END_INTERFACE + } IITAudioCDPlaylistVtbl; + + interface IITAudioCDPlaylist + { + CONST_VTBL struct IITAudioCDPlaylistVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITAudioCDPlaylist_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITAudioCDPlaylist_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITAudioCDPlaylist_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITAudioCDPlaylist_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITAudioCDPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITAudioCDPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITAudioCDPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITAudioCDPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITAudioCDPlaylist_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITAudioCDPlaylist_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITAudioCDPlaylist_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITAudioCDPlaylist_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITAudioCDPlaylist_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITAudioCDPlaylist_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITAudioCDPlaylist_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITAudioCDPlaylist_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITAudioCDPlaylist_PlayFirstTrack(This) \ + (This)->lpVtbl -> PlayFirstTrack(This) + +#define IITAudioCDPlaylist_Print(This,showPrintDialog,printKind,theme) \ + (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) + +#define IITAudioCDPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ + (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) + +#define IITAudioCDPlaylist_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITAudioCDPlaylist_get_Source(This,iSource) \ + (This)->lpVtbl -> get_Source(This,iSource) + +#define IITAudioCDPlaylist_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITAudioCDPlaylist_get_Shuffle(This,isShuffle) \ + (This)->lpVtbl -> get_Shuffle(This,isShuffle) + +#define IITAudioCDPlaylist_put_Shuffle(This,shouldShuffle) \ + (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) + +#define IITAudioCDPlaylist_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITAudioCDPlaylist_get_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> get_SongRepeat(This,repeatMode) + +#define IITAudioCDPlaylist_put_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> put_SongRepeat(This,repeatMode) + +#define IITAudioCDPlaylist_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITAudioCDPlaylist_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITAudioCDPlaylist_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + + +#define IITAudioCDPlaylist_get_Artist(This,artist) \ + (This)->lpVtbl -> get_Artist(This,artist) + +#define IITAudioCDPlaylist_get_Compilation(This,isCompiliation) \ + (This)->lpVtbl -> get_Compilation(This,isCompiliation) + +#define IITAudioCDPlaylist_get_Composer(This,composer) \ + (This)->lpVtbl -> get_Composer(This,composer) + +#define IITAudioCDPlaylist_get_DiscCount(This,discCount) \ + (This)->lpVtbl -> get_DiscCount(This,discCount) + +#define IITAudioCDPlaylist_get_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> get_DiscNumber(This,discNumber) + +#define IITAudioCDPlaylist_get_Genre(This,genre) \ + (This)->lpVtbl -> get_Genre(This,genre) + +#define IITAudioCDPlaylist_get_Year(This,year) \ + (This)->lpVtbl -> get_Year(This,year) + +#define IITAudioCDPlaylist_Reveal(This) \ + (This)->lpVtbl -> Reveal(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Artist_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *artist); + + +void __RPC_STUB IITAudioCDPlaylist_get_Artist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Compilation_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isCompiliation); + + +void __RPC_STUB IITAudioCDPlaylist_get_Compilation_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Composer_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *composer); + + +void __RPC_STUB IITAudioCDPlaylist_get_Composer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_DiscCount_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *discCount); + + +void __RPC_STUB IITAudioCDPlaylist_get_DiscCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_DiscNumber_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *discNumber); + + +void __RPC_STUB IITAudioCDPlaylist_get_DiscNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Genre_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *genre); + + +void __RPC_STUB IITAudioCDPlaylist_get_Genre_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Year_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *year); + + +void __RPC_STUB IITAudioCDPlaylist_get_Year_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_Reveal_Proxy( + IITAudioCDPlaylist * This); + + +void __RPC_STUB IITAudioCDPlaylist_Reveal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITAudioCDPlaylist_INTERFACE_DEFINED__ */ + + +#ifndef __IITPlaylistCollection_INTERFACE_DEFINED__ +#define __IITPlaylistCollection_INTERFACE_DEFINED__ + +/* interface IITPlaylistCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITPlaylistCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("FF194254-909D-4437-9C50-3AAC2AE6305C") + IITPlaylistCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPersistentID( + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITPlaylistCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITPlaylistCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITPlaylistCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITPlaylistCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITPlaylistCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITPlaylistCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITPlaylistCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITPlaylistCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITPlaylistCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITPlaylistCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITPlaylistCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITPlaylistCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPersistentID )( + IITPlaylistCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITPlaylist **iPlaylist); + + END_INTERFACE + } IITPlaylistCollectionVtbl; + + interface IITPlaylistCollection + { + CONST_VTBL struct IITPlaylistCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITPlaylistCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITPlaylistCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITPlaylistCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITPlaylistCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITPlaylistCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITPlaylistCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITPlaylistCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITPlaylistCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITPlaylistCollection_get_Item(This,index,iPlaylist) \ + (This)->lpVtbl -> get_Item(This,index,iPlaylist) + +#define IITPlaylistCollection_get_ItemByName(This,name,iPlaylist) \ + (This)->lpVtbl -> get_ItemByName(This,name,iPlaylist) + +#define IITPlaylistCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#define IITPlaylistCollection_get_ItemByPersistentID(This,highID,lowID,iPlaylist) \ + (This)->lpVtbl -> get_ItemByPersistentID(This,highID,lowID,iPlaylist) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_Count_Proxy( + IITPlaylistCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITPlaylistCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_Item_Proxy( + IITPlaylistCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITPlaylistCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_ItemByName_Proxy( + IITPlaylistCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITPlaylistCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get__NewEnum_Proxy( + IITPlaylistCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITPlaylistCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_ItemByPersistentID_Proxy( + IITPlaylistCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITPlaylistCollection_get_ItemByPersistentID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITPlaylistCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITIPodSource_INTERFACE_DEFINED__ +#define __IITIPodSource_INTERFACE_DEFINED__ + +/* interface IITIPodSource */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITIPodSource; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CF4D8ACE-1720-4fb9-B0AE-9877249E89B0") + IITIPodSource : public IITSource + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdateIPod( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE EjectIPod( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SoftwareVersion( + /* [retval][out] */ BSTR *softwareVersion) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITIPodSourceVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITIPodSource * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITIPodSource * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITIPodSource * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITIPodSource * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITIPodSource * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITIPodSource * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITIPodSource * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITIPodSource * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITIPodSource * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITIPodSource * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITIPodSource * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITIPodSource * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITIPodSource * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITIPodSource * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITIPodSource * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITIPodSource * This, + /* [retval][out] */ ITSourceKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Capacity )( + IITIPodSource * This, + /* [retval][out] */ double *capacity); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_FreeSpace )( + IITIPodSource * This, + /* [retval][out] */ double *freespace); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( + IITIPodSource * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdateIPod )( + IITIPodSource * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *EjectIPod )( + IITIPodSource * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SoftwareVersion )( + IITIPodSource * This, + /* [retval][out] */ BSTR *softwareVersion); + + END_INTERFACE + } IITIPodSourceVtbl; + + interface IITIPodSource + { + CONST_VTBL struct IITIPodSourceVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITIPodSource_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITIPodSource_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITIPodSource_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITIPodSource_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITIPodSource_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITIPodSource_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITIPodSource_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITIPodSource_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITIPodSource_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITIPodSource_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITIPodSource_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITIPodSource_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITIPodSource_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITIPodSource_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITIPodSource_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITIPodSource_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITIPodSource_get_Capacity(This,capacity) \ + (This)->lpVtbl -> get_Capacity(This,capacity) + +#define IITIPodSource_get_FreeSpace(This,freespace) \ + (This)->lpVtbl -> get_FreeSpace(This,freespace) + +#define IITIPodSource_get_Playlists(This,iPlaylistCollection) \ + (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) + + +#define IITIPodSource_UpdateIPod(This) \ + (This)->lpVtbl -> UpdateIPod(This) + +#define IITIPodSource_EjectIPod(This) \ + (This)->lpVtbl -> EjectIPod(This) + +#define IITIPodSource_get_SoftwareVersion(This,softwareVersion) \ + (This)->lpVtbl -> get_SoftwareVersion(This,softwareVersion) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITIPodSource_UpdateIPod_Proxy( + IITIPodSource * This); + + +void __RPC_STUB IITIPodSource_UpdateIPod_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITIPodSource_EjectIPod_Proxy( + IITIPodSource * This); + + +void __RPC_STUB IITIPodSource_EjectIPod_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITIPodSource_get_SoftwareVersion_Proxy( + IITIPodSource * This, + /* [retval][out] */ BSTR *softwareVersion); + + +void __RPC_STUB IITIPodSource_get_SoftwareVersion_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITIPodSource_INTERFACE_DEFINED__ */ + + +#ifndef __IITFileOrCDTrack_INTERFACE_DEFINED__ +#define __IITFileOrCDTrack_INTERFACE_DEFINED__ + +/* interface IITFileOrCDTrack */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITFileOrCDTrack; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("00D7FE99-7868-4cc7-AD9E-ACFD70D09566") + IITFileOrCDTrack : public IITTrack + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Location( + /* [retval][out] */ BSTR *location) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdateInfoFromFile( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Podcast( + /* [retval][out] */ VARIANT_BOOL *isPodcast) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdatePodcastFeed( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RememberBookmark( + /* [retval][out] */ VARIANT_BOOL *rememberBookmark) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_RememberBookmark( + /* [in] */ VARIANT_BOOL shouldRememberBookmark) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ExcludeFromShuffle( + /* [retval][out] */ VARIANT_BOOL *excludeFromShuffle) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_ExcludeFromShuffle( + /* [in] */ VARIANT_BOOL shouldExcludeFromShuffle) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Lyrics( + /* [retval][out] */ BSTR *lyrics) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Lyrics( + /* [in] */ BSTR lyrics) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Category( + /* [retval][out] */ BSTR *category) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Category( + /* [in] */ BSTR category) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Description( + /* [retval][out] */ BSTR *description) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Description( + /* [in] */ BSTR description) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LongDescription( + /* [retval][out] */ BSTR *longDescription) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_LongDescription( + /* [in] */ BSTR longDescription) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BookmarkTime( + /* [retval][out] */ long *bookmarkTime) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_BookmarkTime( + /* [in] */ long bookmarkTime) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VideoKind( + /* [retval][out] */ ITVideoKind *videoKind) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VideoKind( + /* [in] */ ITVideoKind videoKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SkippedCount( + /* [retval][out] */ long *skippedCount) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SkippedCount( + /* [in] */ long skippedCount) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SkippedDate( + /* [retval][out] */ DATE *skippedDate) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SkippedDate( + /* [in] */ DATE skippedDate) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PartOfGaplessAlbum( + /* [retval][out] */ VARIANT_BOOL *partOfGaplessAlbum) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PartOfGaplessAlbum( + /* [in] */ VARIANT_BOOL shouldBePartOfGaplessAlbum) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumArtist( + /* [retval][out] */ BSTR *albumArtist) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AlbumArtist( + /* [in] */ BSTR albumArtist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Show( + /* [retval][out] */ BSTR *showName) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Show( + /* [in] */ BSTR showName) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SeasonNumber( + /* [retval][out] */ long *seasonNumber) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SeasonNumber( + /* [in] */ long seasonNumber) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EpisodeID( + /* [retval][out] */ BSTR *episodeID) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EpisodeID( + /* [in] */ BSTR episodeID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EpisodeNumber( + /* [retval][out] */ long *episodeNumber) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EpisodeNumber( + /* [in] */ long episodeNumber) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size64High( + /* [retval][out] */ long *sizeHigh) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size64Low( + /* [retval][out] */ long *sizeLow) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Unplayed( + /* [retval][out] */ VARIANT_BOOL *isUnplayed) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Unplayed( + /* [in] */ VARIANT_BOOL shouldBeUnplayed) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortAlbum( + /* [retval][out] */ BSTR *album) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortAlbum( + /* [in] */ BSTR album) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortAlbumArtist( + /* [retval][out] */ BSTR *albumArtist) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortAlbumArtist( + /* [in] */ BSTR albumArtist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortArtist( + /* [retval][out] */ BSTR *artist) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortArtist( + /* [in] */ BSTR artist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortComposer( + /* [retval][out] */ BSTR *composer) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortComposer( + /* [in] */ BSTR composer) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortName( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortName( + /* [in] */ BSTR name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortShow( + /* [retval][out] */ BSTR *showName) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortShow( + /* [in] */ BSTR showName) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRating( + /* [retval][out] */ long *rating) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AlbumRating( + /* [in] */ long rating) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRatingKind( + /* [retval][out] */ ITRatingKind *ratingKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RatingKind( + /* [retval][out] */ ITRatingKind *ratingKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlists( + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Location( + /* [in] */ BSTR location) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ReleaseDate( + /* [retval][out] */ DATE *releaseDate) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITFileOrCDTrackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITFileOrCDTrack * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITFileOrCDTrack * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITFileOrCDTrack * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITFileOrCDTrack * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITFileOrCDTrack * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITFileOrCDTrack * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITFileOrCDTrack * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITFileOrCDTrack * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITFileOrCDTrack * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITFileOrCDTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( + IITFileOrCDTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddArtworkFromFile )( + IITFileOrCDTrack * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITArtwork **iArtwork); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITFileOrCDTrack * This, + /* [retval][out] */ ITTrackKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( + IITFileOrCDTrack * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Album )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *album); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Album )( + IITFileOrCDTrack * This, + /* [in] */ BSTR album); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *artist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Artist )( + IITFileOrCDTrack * This, + /* [in] */ BSTR artist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BitRate )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *bitrate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BPM )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *beatsPerMinute); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BPM )( + IITFileOrCDTrack * This, + /* [in] */ long beatsPerMinute); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Comment )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *comment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Comment )( + IITFileOrCDTrack * This, + /* [in] */ BSTR comment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isCompilation); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Compilation )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBeCompilation); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *composer); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Composer )( + IITFileOrCDTrack * This, + /* [in] */ BSTR composer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DateAdded )( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *dateAdded); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *discCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscCount )( + IITFileOrCDTrack * This, + /* [in] */ long discCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *discNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscNumber )( + IITFileOrCDTrack * This, + /* [in] */ long discNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Enabled )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Enabled )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBeEnabled); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQ )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQ )( + IITFileOrCDTrack * This, + /* [in] */ BSTR eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Finish )( + IITFileOrCDTrack * This, + /* [in] */ long finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Finish )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *genre); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Genre )( + IITFileOrCDTrack * This, + /* [in] */ BSTR genre); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Grouping )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *grouping); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Grouping )( + IITFileOrCDTrack * This, + /* [in] */ BSTR grouping); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_KindAsString )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ModificationDate )( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *dateModified); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedCount )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *playedCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedCount )( + IITFileOrCDTrack * This, + /* [in] */ long playedCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedDate )( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *playedDate); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedDate )( + IITFileOrCDTrack * This, + /* [in] */ DATE playedDate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayOrderIndex )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Rating )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *rating); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Rating )( + IITFileOrCDTrack * This, + /* [in] */ long rating); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SampleRate )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sampleRate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Start )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *start); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Start )( + IITFileOrCDTrack * This, + /* [in] */ long start); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackCount )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *trackCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackCount )( + IITFileOrCDTrack * This, + /* [in] */ long trackCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackNumber )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *trackNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackNumber )( + IITFileOrCDTrack * This, + /* [in] */ long trackNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VolumeAdjustment )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *volumeAdjustment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VolumeAdjustment )( + IITFileOrCDTrack * This, + /* [in] */ long volumeAdjustment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *year); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Year )( + IITFileOrCDTrack * This, + /* [in] */ long year); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artwork )( + IITFileOrCDTrack * This, + /* [retval][out] */ IITArtworkCollection **iArtworkCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Location )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *location); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdateInfoFromFile )( + IITFileOrCDTrack * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Podcast )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isPodcast); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdatePodcastFeed )( + IITFileOrCDTrack * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RememberBookmark )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *rememberBookmark); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_RememberBookmark )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldRememberBookmark); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ExcludeFromShuffle )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *excludeFromShuffle); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ExcludeFromShuffle )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldExcludeFromShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Lyrics )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *lyrics); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Lyrics )( + IITFileOrCDTrack * This, + /* [in] */ BSTR lyrics); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Category )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *category); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Category )( + IITFileOrCDTrack * This, + /* [in] */ BSTR category); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Description )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *description); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Description )( + IITFileOrCDTrack * This, + /* [in] */ BSTR description); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LongDescription )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *longDescription); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LongDescription )( + IITFileOrCDTrack * This, + /* [in] */ BSTR longDescription); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BookmarkTime )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *bookmarkTime); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BookmarkTime )( + IITFileOrCDTrack * This, + /* [in] */ long bookmarkTime); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VideoKind )( + IITFileOrCDTrack * This, + /* [retval][out] */ ITVideoKind *videoKind); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VideoKind )( + IITFileOrCDTrack * This, + /* [in] */ ITVideoKind videoKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SkippedCount )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *skippedCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SkippedCount )( + IITFileOrCDTrack * This, + /* [in] */ long skippedCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SkippedDate )( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *skippedDate); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SkippedDate )( + IITFileOrCDTrack * This, + /* [in] */ DATE skippedDate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PartOfGaplessAlbum )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *partOfGaplessAlbum); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PartOfGaplessAlbum )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBePartOfGaplessAlbum); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumArtist )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *albumArtist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AlbumArtist )( + IITFileOrCDTrack * This, + /* [in] */ BSTR albumArtist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Show )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *showName); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Show )( + IITFileOrCDTrack * This, + /* [in] */ BSTR showName); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SeasonNumber )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *seasonNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SeasonNumber )( + IITFileOrCDTrack * This, + /* [in] */ long seasonNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EpisodeID )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *episodeID); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EpisodeID )( + IITFileOrCDTrack * This, + /* [in] */ BSTR episodeID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EpisodeNumber )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *episodeNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EpisodeNumber )( + IITFileOrCDTrack * This, + /* [in] */ long episodeNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size64High )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sizeHigh); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size64Low )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sizeLow); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Unplayed )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isUnplayed); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Unplayed )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBeUnplayed); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortAlbum )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *album); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortAlbum )( + IITFileOrCDTrack * This, + /* [in] */ BSTR album); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortAlbumArtist )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *albumArtist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortAlbumArtist )( + IITFileOrCDTrack * This, + /* [in] */ BSTR albumArtist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortArtist )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *artist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortArtist )( + IITFileOrCDTrack * This, + /* [in] */ BSTR artist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortComposer )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *composer); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortComposer )( + IITFileOrCDTrack * This, + /* [in] */ BSTR composer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortName )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortName )( + IITFileOrCDTrack * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortShow )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *showName); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortShow )( + IITFileOrCDTrack * This, + /* [in] */ BSTR showName); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( + IITFileOrCDTrack * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRating )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *rating); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AlbumRating )( + IITFileOrCDTrack * This, + /* [in] */ long rating); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRatingKind )( + IITFileOrCDTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RatingKind )( + IITFileOrCDTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( + IITFileOrCDTrack * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Location )( + IITFileOrCDTrack * This, + /* [in] */ BSTR location); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ReleaseDate )( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *releaseDate); + + END_INTERFACE + } IITFileOrCDTrackVtbl; + + interface IITFileOrCDTrack + { + CONST_VTBL struct IITFileOrCDTrackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITFileOrCDTrack_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITFileOrCDTrack_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITFileOrCDTrack_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITFileOrCDTrack_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITFileOrCDTrack_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITFileOrCDTrack_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITFileOrCDTrack_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITFileOrCDTrack_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITFileOrCDTrack_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITFileOrCDTrack_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITFileOrCDTrack_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITFileOrCDTrack_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITFileOrCDTrack_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITFileOrCDTrack_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITFileOrCDTrack_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITFileOrCDTrack_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITFileOrCDTrack_Play(This) \ + (This)->lpVtbl -> Play(This) + +#define IITFileOrCDTrack_AddArtworkFromFile(This,filePath,iArtwork) \ + (This)->lpVtbl -> AddArtworkFromFile(This,filePath,iArtwork) + +#define IITFileOrCDTrack_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITFileOrCDTrack_get_Playlist(This,iPlaylist) \ + (This)->lpVtbl -> get_Playlist(This,iPlaylist) + +#define IITFileOrCDTrack_get_Album(This,album) \ + (This)->lpVtbl -> get_Album(This,album) + +#define IITFileOrCDTrack_put_Album(This,album) \ + (This)->lpVtbl -> put_Album(This,album) + +#define IITFileOrCDTrack_get_Artist(This,artist) \ + (This)->lpVtbl -> get_Artist(This,artist) + +#define IITFileOrCDTrack_put_Artist(This,artist) \ + (This)->lpVtbl -> put_Artist(This,artist) + +#define IITFileOrCDTrack_get_BitRate(This,bitrate) \ + (This)->lpVtbl -> get_BitRate(This,bitrate) + +#define IITFileOrCDTrack_get_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> get_BPM(This,beatsPerMinute) + +#define IITFileOrCDTrack_put_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> put_BPM(This,beatsPerMinute) + +#define IITFileOrCDTrack_get_Comment(This,comment) \ + (This)->lpVtbl -> get_Comment(This,comment) + +#define IITFileOrCDTrack_put_Comment(This,comment) \ + (This)->lpVtbl -> put_Comment(This,comment) + +#define IITFileOrCDTrack_get_Compilation(This,isCompilation) \ + (This)->lpVtbl -> get_Compilation(This,isCompilation) + +#define IITFileOrCDTrack_put_Compilation(This,shouldBeCompilation) \ + (This)->lpVtbl -> put_Compilation(This,shouldBeCompilation) + +#define IITFileOrCDTrack_get_Composer(This,composer) \ + (This)->lpVtbl -> get_Composer(This,composer) + +#define IITFileOrCDTrack_put_Composer(This,composer) \ + (This)->lpVtbl -> put_Composer(This,composer) + +#define IITFileOrCDTrack_get_DateAdded(This,dateAdded) \ + (This)->lpVtbl -> get_DateAdded(This,dateAdded) + +#define IITFileOrCDTrack_get_DiscCount(This,discCount) \ + (This)->lpVtbl -> get_DiscCount(This,discCount) + +#define IITFileOrCDTrack_put_DiscCount(This,discCount) \ + (This)->lpVtbl -> put_DiscCount(This,discCount) + +#define IITFileOrCDTrack_get_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> get_DiscNumber(This,discNumber) + +#define IITFileOrCDTrack_put_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> put_DiscNumber(This,discNumber) + +#define IITFileOrCDTrack_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITFileOrCDTrack_get_Enabled(This,isEnabled) \ + (This)->lpVtbl -> get_Enabled(This,isEnabled) + +#define IITFileOrCDTrack_put_Enabled(This,shouldBeEnabled) \ + (This)->lpVtbl -> put_Enabled(This,shouldBeEnabled) + +#define IITFileOrCDTrack_get_EQ(This,eq) \ + (This)->lpVtbl -> get_EQ(This,eq) + +#define IITFileOrCDTrack_put_EQ(This,eq) \ + (This)->lpVtbl -> put_EQ(This,eq) + +#define IITFileOrCDTrack_put_Finish(This,finish) \ + (This)->lpVtbl -> put_Finish(This,finish) + +#define IITFileOrCDTrack_get_Finish(This,finish) \ + (This)->lpVtbl -> get_Finish(This,finish) + +#define IITFileOrCDTrack_get_Genre(This,genre) \ + (This)->lpVtbl -> get_Genre(This,genre) + +#define IITFileOrCDTrack_put_Genre(This,genre) \ + (This)->lpVtbl -> put_Genre(This,genre) + +#define IITFileOrCDTrack_get_Grouping(This,grouping) \ + (This)->lpVtbl -> get_Grouping(This,grouping) + +#define IITFileOrCDTrack_put_Grouping(This,grouping) \ + (This)->lpVtbl -> put_Grouping(This,grouping) + +#define IITFileOrCDTrack_get_KindAsString(This,kind) \ + (This)->lpVtbl -> get_KindAsString(This,kind) + +#define IITFileOrCDTrack_get_ModificationDate(This,dateModified) \ + (This)->lpVtbl -> get_ModificationDate(This,dateModified) + +#define IITFileOrCDTrack_get_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> get_PlayedCount(This,playedCount) + +#define IITFileOrCDTrack_put_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> put_PlayedCount(This,playedCount) + +#define IITFileOrCDTrack_get_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> get_PlayedDate(This,playedDate) + +#define IITFileOrCDTrack_put_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> put_PlayedDate(This,playedDate) + +#define IITFileOrCDTrack_get_PlayOrderIndex(This,index) \ + (This)->lpVtbl -> get_PlayOrderIndex(This,index) + +#define IITFileOrCDTrack_get_Rating(This,rating) \ + (This)->lpVtbl -> get_Rating(This,rating) + +#define IITFileOrCDTrack_put_Rating(This,rating) \ + (This)->lpVtbl -> put_Rating(This,rating) + +#define IITFileOrCDTrack_get_SampleRate(This,sampleRate) \ + (This)->lpVtbl -> get_SampleRate(This,sampleRate) + +#define IITFileOrCDTrack_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITFileOrCDTrack_get_Start(This,start) \ + (This)->lpVtbl -> get_Start(This,start) + +#define IITFileOrCDTrack_put_Start(This,start) \ + (This)->lpVtbl -> put_Start(This,start) + +#define IITFileOrCDTrack_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITFileOrCDTrack_get_TrackCount(This,trackCount) \ + (This)->lpVtbl -> get_TrackCount(This,trackCount) + +#define IITFileOrCDTrack_put_TrackCount(This,trackCount) \ + (This)->lpVtbl -> put_TrackCount(This,trackCount) + +#define IITFileOrCDTrack_get_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> get_TrackNumber(This,trackNumber) + +#define IITFileOrCDTrack_put_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> put_TrackNumber(This,trackNumber) + +#define IITFileOrCDTrack_get_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> get_VolumeAdjustment(This,volumeAdjustment) + +#define IITFileOrCDTrack_put_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> put_VolumeAdjustment(This,volumeAdjustment) + +#define IITFileOrCDTrack_get_Year(This,year) \ + (This)->lpVtbl -> get_Year(This,year) + +#define IITFileOrCDTrack_put_Year(This,year) \ + (This)->lpVtbl -> put_Year(This,year) + +#define IITFileOrCDTrack_get_Artwork(This,iArtworkCollection) \ + (This)->lpVtbl -> get_Artwork(This,iArtworkCollection) + + +#define IITFileOrCDTrack_get_Location(This,location) \ + (This)->lpVtbl -> get_Location(This,location) + +#define IITFileOrCDTrack_UpdateInfoFromFile(This) \ + (This)->lpVtbl -> UpdateInfoFromFile(This) + +#define IITFileOrCDTrack_get_Podcast(This,isPodcast) \ + (This)->lpVtbl -> get_Podcast(This,isPodcast) + +#define IITFileOrCDTrack_UpdatePodcastFeed(This) \ + (This)->lpVtbl -> UpdatePodcastFeed(This) + +#define IITFileOrCDTrack_get_RememberBookmark(This,rememberBookmark) \ + (This)->lpVtbl -> get_RememberBookmark(This,rememberBookmark) + +#define IITFileOrCDTrack_put_RememberBookmark(This,shouldRememberBookmark) \ + (This)->lpVtbl -> put_RememberBookmark(This,shouldRememberBookmark) + +#define IITFileOrCDTrack_get_ExcludeFromShuffle(This,excludeFromShuffle) \ + (This)->lpVtbl -> get_ExcludeFromShuffle(This,excludeFromShuffle) + +#define IITFileOrCDTrack_put_ExcludeFromShuffle(This,shouldExcludeFromShuffle) \ + (This)->lpVtbl -> put_ExcludeFromShuffle(This,shouldExcludeFromShuffle) + +#define IITFileOrCDTrack_get_Lyrics(This,lyrics) \ + (This)->lpVtbl -> get_Lyrics(This,lyrics) + +#define IITFileOrCDTrack_put_Lyrics(This,lyrics) \ + (This)->lpVtbl -> put_Lyrics(This,lyrics) + +#define IITFileOrCDTrack_get_Category(This,category) \ + (This)->lpVtbl -> get_Category(This,category) + +#define IITFileOrCDTrack_put_Category(This,category) \ + (This)->lpVtbl -> put_Category(This,category) + +#define IITFileOrCDTrack_get_Description(This,description) \ + (This)->lpVtbl -> get_Description(This,description) + +#define IITFileOrCDTrack_put_Description(This,description) \ + (This)->lpVtbl -> put_Description(This,description) + +#define IITFileOrCDTrack_get_LongDescription(This,longDescription) \ + (This)->lpVtbl -> get_LongDescription(This,longDescription) + +#define IITFileOrCDTrack_put_LongDescription(This,longDescription) \ + (This)->lpVtbl -> put_LongDescription(This,longDescription) + +#define IITFileOrCDTrack_get_BookmarkTime(This,bookmarkTime) \ + (This)->lpVtbl -> get_BookmarkTime(This,bookmarkTime) + +#define IITFileOrCDTrack_put_BookmarkTime(This,bookmarkTime) \ + (This)->lpVtbl -> put_BookmarkTime(This,bookmarkTime) + +#define IITFileOrCDTrack_get_VideoKind(This,videoKind) \ + (This)->lpVtbl -> get_VideoKind(This,videoKind) + +#define IITFileOrCDTrack_put_VideoKind(This,videoKind) \ + (This)->lpVtbl -> put_VideoKind(This,videoKind) + +#define IITFileOrCDTrack_get_SkippedCount(This,skippedCount) \ + (This)->lpVtbl -> get_SkippedCount(This,skippedCount) + +#define IITFileOrCDTrack_put_SkippedCount(This,skippedCount) \ + (This)->lpVtbl -> put_SkippedCount(This,skippedCount) + +#define IITFileOrCDTrack_get_SkippedDate(This,skippedDate) \ + (This)->lpVtbl -> get_SkippedDate(This,skippedDate) + +#define IITFileOrCDTrack_put_SkippedDate(This,skippedDate) \ + (This)->lpVtbl -> put_SkippedDate(This,skippedDate) + +#define IITFileOrCDTrack_get_PartOfGaplessAlbum(This,partOfGaplessAlbum) \ + (This)->lpVtbl -> get_PartOfGaplessAlbum(This,partOfGaplessAlbum) + +#define IITFileOrCDTrack_put_PartOfGaplessAlbum(This,shouldBePartOfGaplessAlbum) \ + (This)->lpVtbl -> put_PartOfGaplessAlbum(This,shouldBePartOfGaplessAlbum) + +#define IITFileOrCDTrack_get_AlbumArtist(This,albumArtist) \ + (This)->lpVtbl -> get_AlbumArtist(This,albumArtist) + +#define IITFileOrCDTrack_put_AlbumArtist(This,albumArtist) \ + (This)->lpVtbl -> put_AlbumArtist(This,albumArtist) + +#define IITFileOrCDTrack_get_Show(This,showName) \ + (This)->lpVtbl -> get_Show(This,showName) + +#define IITFileOrCDTrack_put_Show(This,showName) \ + (This)->lpVtbl -> put_Show(This,showName) + +#define IITFileOrCDTrack_get_SeasonNumber(This,seasonNumber) \ + (This)->lpVtbl -> get_SeasonNumber(This,seasonNumber) + +#define IITFileOrCDTrack_put_SeasonNumber(This,seasonNumber) \ + (This)->lpVtbl -> put_SeasonNumber(This,seasonNumber) + +#define IITFileOrCDTrack_get_EpisodeID(This,episodeID) \ + (This)->lpVtbl -> get_EpisodeID(This,episodeID) + +#define IITFileOrCDTrack_put_EpisodeID(This,episodeID) \ + (This)->lpVtbl -> put_EpisodeID(This,episodeID) + +#define IITFileOrCDTrack_get_EpisodeNumber(This,episodeNumber) \ + (This)->lpVtbl -> get_EpisodeNumber(This,episodeNumber) + +#define IITFileOrCDTrack_put_EpisodeNumber(This,episodeNumber) \ + (This)->lpVtbl -> put_EpisodeNumber(This,episodeNumber) + +#define IITFileOrCDTrack_get_Size64High(This,sizeHigh) \ + (This)->lpVtbl -> get_Size64High(This,sizeHigh) + +#define IITFileOrCDTrack_get_Size64Low(This,sizeLow) \ + (This)->lpVtbl -> get_Size64Low(This,sizeLow) + +#define IITFileOrCDTrack_get_Unplayed(This,isUnplayed) \ + (This)->lpVtbl -> get_Unplayed(This,isUnplayed) + +#define IITFileOrCDTrack_put_Unplayed(This,shouldBeUnplayed) \ + (This)->lpVtbl -> put_Unplayed(This,shouldBeUnplayed) + +#define IITFileOrCDTrack_get_SortAlbum(This,album) \ + (This)->lpVtbl -> get_SortAlbum(This,album) + +#define IITFileOrCDTrack_put_SortAlbum(This,album) \ + (This)->lpVtbl -> put_SortAlbum(This,album) + +#define IITFileOrCDTrack_get_SortAlbumArtist(This,albumArtist) \ + (This)->lpVtbl -> get_SortAlbumArtist(This,albumArtist) + +#define IITFileOrCDTrack_put_SortAlbumArtist(This,albumArtist) \ + (This)->lpVtbl -> put_SortAlbumArtist(This,albumArtist) + +#define IITFileOrCDTrack_get_SortArtist(This,artist) \ + (This)->lpVtbl -> get_SortArtist(This,artist) + +#define IITFileOrCDTrack_put_SortArtist(This,artist) \ + (This)->lpVtbl -> put_SortArtist(This,artist) + +#define IITFileOrCDTrack_get_SortComposer(This,composer) \ + (This)->lpVtbl -> get_SortComposer(This,composer) + +#define IITFileOrCDTrack_put_SortComposer(This,composer) \ + (This)->lpVtbl -> put_SortComposer(This,composer) + +#define IITFileOrCDTrack_get_SortName(This,name) \ + (This)->lpVtbl -> get_SortName(This,name) + +#define IITFileOrCDTrack_put_SortName(This,name) \ + (This)->lpVtbl -> put_SortName(This,name) + +#define IITFileOrCDTrack_get_SortShow(This,showName) \ + (This)->lpVtbl -> get_SortShow(This,showName) + +#define IITFileOrCDTrack_put_SortShow(This,showName) \ + (This)->lpVtbl -> put_SortShow(This,showName) + +#define IITFileOrCDTrack_Reveal(This) \ + (This)->lpVtbl -> Reveal(This) + +#define IITFileOrCDTrack_get_AlbumRating(This,rating) \ + (This)->lpVtbl -> get_AlbumRating(This,rating) + +#define IITFileOrCDTrack_put_AlbumRating(This,rating) \ + (This)->lpVtbl -> put_AlbumRating(This,rating) + +#define IITFileOrCDTrack_get_AlbumRatingKind(This,ratingKind) \ + (This)->lpVtbl -> get_AlbumRatingKind(This,ratingKind) + +#define IITFileOrCDTrack_get_RatingKind(This,ratingKind) \ + (This)->lpVtbl -> get_RatingKind(This,ratingKind) + +#define IITFileOrCDTrack_get_Playlists(This,iPlaylistCollection) \ + (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) + +#define IITFileOrCDTrack_put_Location(This,location) \ + (This)->lpVtbl -> put_Location(This,location) + +#define IITFileOrCDTrack_get_ReleaseDate(This,releaseDate) \ + (This)->lpVtbl -> get_ReleaseDate(This,releaseDate) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Location_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *location); + + +void __RPC_STUB IITFileOrCDTrack_get_Location_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_UpdateInfoFromFile_Proxy( + IITFileOrCDTrack * This); + + +void __RPC_STUB IITFileOrCDTrack_UpdateInfoFromFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Podcast_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isPodcast); + + +void __RPC_STUB IITFileOrCDTrack_get_Podcast_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_UpdatePodcastFeed_Proxy( + IITFileOrCDTrack * This); + + +void __RPC_STUB IITFileOrCDTrack_UpdatePodcastFeed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_RememberBookmark_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *rememberBookmark); + + +void __RPC_STUB IITFileOrCDTrack_get_RememberBookmark_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_RememberBookmark_Proxy( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldRememberBookmark); + + +void __RPC_STUB IITFileOrCDTrack_put_RememberBookmark_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_ExcludeFromShuffle_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *excludeFromShuffle); + + +void __RPC_STUB IITFileOrCDTrack_get_ExcludeFromShuffle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_ExcludeFromShuffle_Proxy( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldExcludeFromShuffle); + + +void __RPC_STUB IITFileOrCDTrack_put_ExcludeFromShuffle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Lyrics_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *lyrics); + + +void __RPC_STUB IITFileOrCDTrack_get_Lyrics_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Lyrics_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR lyrics); + + +void __RPC_STUB IITFileOrCDTrack_put_Lyrics_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Category_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *category); + + +void __RPC_STUB IITFileOrCDTrack_get_Category_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Category_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR category); + + +void __RPC_STUB IITFileOrCDTrack_put_Category_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Description_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *description); + + +void __RPC_STUB IITFileOrCDTrack_get_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Description_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR description); + + +void __RPC_STUB IITFileOrCDTrack_put_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_LongDescription_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *longDescription); + + +void __RPC_STUB IITFileOrCDTrack_get_LongDescription_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_LongDescription_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR longDescription); + + +void __RPC_STUB IITFileOrCDTrack_put_LongDescription_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_BookmarkTime_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *bookmarkTime); + + +void __RPC_STUB IITFileOrCDTrack_get_BookmarkTime_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_BookmarkTime_Proxy( + IITFileOrCDTrack * This, + /* [in] */ long bookmarkTime); + + +void __RPC_STUB IITFileOrCDTrack_put_BookmarkTime_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_VideoKind_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ ITVideoKind *videoKind); + + +void __RPC_STUB IITFileOrCDTrack_get_VideoKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_VideoKind_Proxy( + IITFileOrCDTrack * This, + /* [in] */ ITVideoKind videoKind); + + +void __RPC_STUB IITFileOrCDTrack_put_VideoKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SkippedCount_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *skippedCount); + + +void __RPC_STUB IITFileOrCDTrack_get_SkippedCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SkippedCount_Proxy( + IITFileOrCDTrack * This, + /* [in] */ long skippedCount); + + +void __RPC_STUB IITFileOrCDTrack_put_SkippedCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SkippedDate_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *skippedDate); + + +void __RPC_STUB IITFileOrCDTrack_get_SkippedDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SkippedDate_Proxy( + IITFileOrCDTrack * This, + /* [in] */ DATE skippedDate); + + +void __RPC_STUB IITFileOrCDTrack_put_SkippedDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_PartOfGaplessAlbum_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *partOfGaplessAlbum); + + +void __RPC_STUB IITFileOrCDTrack_get_PartOfGaplessAlbum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_PartOfGaplessAlbum_Proxy( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBePartOfGaplessAlbum); + + +void __RPC_STUB IITFileOrCDTrack_put_PartOfGaplessAlbum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_AlbumArtist_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *albumArtist); + + +void __RPC_STUB IITFileOrCDTrack_get_AlbumArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_AlbumArtist_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR albumArtist); + + +void __RPC_STUB IITFileOrCDTrack_put_AlbumArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Show_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *showName); + + +void __RPC_STUB IITFileOrCDTrack_get_Show_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Show_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR showName); + + +void __RPC_STUB IITFileOrCDTrack_put_Show_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SeasonNumber_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *seasonNumber); + + +void __RPC_STUB IITFileOrCDTrack_get_SeasonNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SeasonNumber_Proxy( + IITFileOrCDTrack * This, + /* [in] */ long seasonNumber); + + +void __RPC_STUB IITFileOrCDTrack_put_SeasonNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_EpisodeID_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *episodeID); + + +void __RPC_STUB IITFileOrCDTrack_get_EpisodeID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_EpisodeID_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR episodeID); + + +void __RPC_STUB IITFileOrCDTrack_put_EpisodeID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_EpisodeNumber_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *episodeNumber); + + +void __RPC_STUB IITFileOrCDTrack_get_EpisodeNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_EpisodeNumber_Proxy( + IITFileOrCDTrack * This, + /* [in] */ long episodeNumber); + + +void __RPC_STUB IITFileOrCDTrack_put_EpisodeNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Size64High_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sizeHigh); + + +void __RPC_STUB IITFileOrCDTrack_get_Size64High_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Size64Low_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sizeLow); + + +void __RPC_STUB IITFileOrCDTrack_get_Size64Low_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Unplayed_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isUnplayed); + + +void __RPC_STUB IITFileOrCDTrack_get_Unplayed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Unplayed_Proxy( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBeUnplayed); + + +void __RPC_STUB IITFileOrCDTrack_put_Unplayed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortAlbum_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *album); + + +void __RPC_STUB IITFileOrCDTrack_get_SortAlbum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortAlbum_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR album); + + +void __RPC_STUB IITFileOrCDTrack_put_SortAlbum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortAlbumArtist_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *albumArtist); + + +void __RPC_STUB IITFileOrCDTrack_get_SortAlbumArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortAlbumArtist_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR albumArtist); + + +void __RPC_STUB IITFileOrCDTrack_put_SortAlbumArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortArtist_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *artist); + + +void __RPC_STUB IITFileOrCDTrack_get_SortArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortArtist_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR artist); + + +void __RPC_STUB IITFileOrCDTrack_put_SortArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortComposer_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *composer); + + +void __RPC_STUB IITFileOrCDTrack_get_SortComposer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortComposer_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR composer); + + +void __RPC_STUB IITFileOrCDTrack_put_SortComposer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortName_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITFileOrCDTrack_get_SortName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortName_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR name); + + +void __RPC_STUB IITFileOrCDTrack_put_SortName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortShow_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *showName); + + +void __RPC_STUB IITFileOrCDTrack_get_SortShow_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortShow_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR showName); + + +void __RPC_STUB IITFileOrCDTrack_put_SortShow_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_Reveal_Proxy( + IITFileOrCDTrack * This); + + +void __RPC_STUB IITFileOrCDTrack_Reveal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_AlbumRating_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *rating); + + +void __RPC_STUB IITFileOrCDTrack_get_AlbumRating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_AlbumRating_Proxy( + IITFileOrCDTrack * This, + /* [in] */ long rating); + + +void __RPC_STUB IITFileOrCDTrack_put_AlbumRating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_AlbumRatingKind_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + +void __RPC_STUB IITFileOrCDTrack_get_AlbumRatingKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_RatingKind_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + +void __RPC_STUB IITFileOrCDTrack_get_RatingKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Playlists_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + +void __RPC_STUB IITFileOrCDTrack_get_Playlists_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Location_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR location); + + +void __RPC_STUB IITFileOrCDTrack_put_Location_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_ReleaseDate_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *releaseDate); + + +void __RPC_STUB IITFileOrCDTrack_get_ReleaseDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITFileOrCDTrack_INTERFACE_DEFINED__ */ + + +#ifndef __IITPlaylistWindow_INTERFACE_DEFINED__ +#define __IITPlaylistWindow_INTERFACE_DEFINED__ + +/* interface IITPlaylistWindow */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITPlaylistWindow; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("349CBB45-2E5A-4822-8E4A-A75555A186F7") + IITPlaylistWindow : public IITWindow + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedTracks( + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlist( + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITPlaylistWindowVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITPlaylistWindow * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITPlaylistWindow * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITPlaylistWindow * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITPlaylistWindow * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITPlaylistWindow * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITPlaylistWindow * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITPlaylistWindow * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITPlaylistWindow * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITPlaylistWindow * This, + /* [retval][out] */ ITWindowKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Visible )( + IITPlaylistWindow * This, + /* [in] */ VARIANT_BOOL shouldBeVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Resizable )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isResizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Minimized )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMinimized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Minimized )( + IITPlaylistWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMinimized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximizable )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximized )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Maximized )( + IITPlaylistWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMaximized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomable )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomed )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomed); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Zoomed )( + IITPlaylistWindow * This, + /* [in] */ VARIANT_BOOL shouldBeZoomed); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )( + IITPlaylistWindow * This, + /* [retval][out] */ long *top); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Top )( + IITPlaylistWindow * This, + /* [in] */ long top); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )( + IITPlaylistWindow * This, + /* [retval][out] */ long *left); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Left )( + IITPlaylistWindow * This, + /* [in] */ long left); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bottom )( + IITPlaylistWindow * This, + /* [retval][out] */ long *bottom); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bottom )( + IITPlaylistWindow * This, + /* [in] */ long bottom); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Right )( + IITPlaylistWindow * This, + /* [retval][out] */ long *right); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Right )( + IITPlaylistWindow * This, + /* [in] */ long right); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )( + IITPlaylistWindow * This, + /* [retval][out] */ long *width); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Width )( + IITPlaylistWindow * This, + /* [in] */ long width); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )( + IITPlaylistWindow * This, + /* [retval][out] */ long *height); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Height )( + IITPlaylistWindow * This, + /* [in] */ long height); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedTracks )( + IITPlaylistWindow * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( + IITPlaylistWindow * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + END_INTERFACE + } IITPlaylistWindowVtbl; + + interface IITPlaylistWindow + { + CONST_VTBL struct IITPlaylistWindowVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITPlaylistWindow_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITPlaylistWindow_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITPlaylistWindow_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITPlaylistWindow_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITPlaylistWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITPlaylistWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITPlaylistWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITPlaylistWindow_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITPlaylistWindow_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITPlaylistWindow_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITPlaylistWindow_put_Visible(This,shouldBeVisible) \ + (This)->lpVtbl -> put_Visible(This,shouldBeVisible) + +#define IITPlaylistWindow_get_Resizable(This,isResizable) \ + (This)->lpVtbl -> get_Resizable(This,isResizable) + +#define IITPlaylistWindow_get_Minimized(This,isMinimized) \ + (This)->lpVtbl -> get_Minimized(This,isMinimized) + +#define IITPlaylistWindow_put_Minimized(This,shouldBeMinimized) \ + (This)->lpVtbl -> put_Minimized(This,shouldBeMinimized) + +#define IITPlaylistWindow_get_Maximizable(This,isMaximizable) \ + (This)->lpVtbl -> get_Maximizable(This,isMaximizable) + +#define IITPlaylistWindow_get_Maximized(This,isMaximized) \ + (This)->lpVtbl -> get_Maximized(This,isMaximized) + +#define IITPlaylistWindow_put_Maximized(This,shouldBeMaximized) \ + (This)->lpVtbl -> put_Maximized(This,shouldBeMaximized) + +#define IITPlaylistWindow_get_Zoomable(This,isZoomable) \ + (This)->lpVtbl -> get_Zoomable(This,isZoomable) + +#define IITPlaylistWindow_get_Zoomed(This,isZoomed) \ + (This)->lpVtbl -> get_Zoomed(This,isZoomed) + +#define IITPlaylistWindow_put_Zoomed(This,shouldBeZoomed) \ + (This)->lpVtbl -> put_Zoomed(This,shouldBeZoomed) + +#define IITPlaylistWindow_get_Top(This,top) \ + (This)->lpVtbl -> get_Top(This,top) + +#define IITPlaylistWindow_put_Top(This,top) \ + (This)->lpVtbl -> put_Top(This,top) + +#define IITPlaylistWindow_get_Left(This,left) \ + (This)->lpVtbl -> get_Left(This,left) + +#define IITPlaylistWindow_put_Left(This,left) \ + (This)->lpVtbl -> put_Left(This,left) + +#define IITPlaylistWindow_get_Bottom(This,bottom) \ + (This)->lpVtbl -> get_Bottom(This,bottom) + +#define IITPlaylistWindow_put_Bottom(This,bottom) \ + (This)->lpVtbl -> put_Bottom(This,bottom) + +#define IITPlaylistWindow_get_Right(This,right) \ + (This)->lpVtbl -> get_Right(This,right) + +#define IITPlaylistWindow_put_Right(This,right) \ + (This)->lpVtbl -> put_Right(This,right) + +#define IITPlaylistWindow_get_Width(This,width) \ + (This)->lpVtbl -> get_Width(This,width) + +#define IITPlaylistWindow_put_Width(This,width) \ + (This)->lpVtbl -> put_Width(This,width) + +#define IITPlaylistWindow_get_Height(This,height) \ + (This)->lpVtbl -> get_Height(This,height) + +#define IITPlaylistWindow_put_Height(This,height) \ + (This)->lpVtbl -> put_Height(This,height) + + +#define IITPlaylistWindow_get_SelectedTracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_SelectedTracks(This,iTrackCollection) + +#define IITPlaylistWindow_get_Playlist(This,iPlaylist) \ + (This)->lpVtbl -> get_Playlist(This,iPlaylist) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistWindow_get_SelectedTracks_Proxy( + IITPlaylistWindow * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IITPlaylistWindow_get_SelectedTracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistWindow_get_Playlist_Proxy( + IITPlaylistWindow * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITPlaylistWindow_get_Playlist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITPlaylistWindow_INTERFACE_DEFINED__ */ + +#endif /* __iTunesLib_LIBRARY_DEFINED__ */ + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface_i.c b/Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface_i.c deleted file mode 100644 index 92e9c4c2..00000000 --- a/Plugins/PluginNowPlaying/SDKs/iTunes/iTunesCOMInterface_i.c +++ /dev/null @@ -1,175 +0,0 @@ - - -/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ - -/* link this file in with the server and any clients */ - - - /* File created by MIDL compiler version 6.00.0366 */ -/* at Wed Nov 05 13:21:00 2008 - */ -/* Compiler settings for iTunesCOMInterface.idl: - Oicf, W1, Zp8, env=Win32 (32b run) - protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: - __declspec(uuid()), __declspec(selectany), __declspec(novtable) - DECLSPEC_UUID(), MIDL_INTERFACE() -*/ -//@@MIDL_FILE_HEADING( ) - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ - - -#ifdef __cplusplus -extern "C"{ -#endif - - -#include <rpc.h> -#include <rpcndr.h> - -#ifdef _MIDL_USE_GUIDDEF_ - -#ifndef INITGUID -#define INITGUID -#include <guiddef.h> -#undef INITGUID -#else -#include <guiddef.h> -#endif - -#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ - DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) - -#else // !_MIDL_USE_GUIDDEF_ - -#ifndef __IID_DEFINED__ -#define __IID_DEFINED__ - -typedef struct _IID -{ - unsigned long x; - unsigned short s1; - unsigned short s2; - unsigned char c[8]; -} IID; - -#endif // __IID_DEFINED__ - -#ifndef CLSID_DEFINED -#define CLSID_DEFINED -typedef IID CLSID; -#endif // CLSID_DEFINED - -#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ - const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} - -#endif !_MIDL_USE_GUIDDEF_ - -MIDL_DEFINE_GUID(IID, LIBID_iTunesLib,0x9E93C96F,0xCF0D,0x43f6,0x8B,0xA8,0xB8,0x07,0xA3,0x37,0x07,0x12); - - -MIDL_DEFINE_GUID(IID, IID_IITObject,0x9FAB0E27,0x70D7,0x4e3a,0x99,0x65,0xB0,0xC8,0xB8,0x86,0x9B,0xB6); - - -MIDL_DEFINE_GUID(IID, IID_IITSource,0xAEC1C4D3,0xAEF1,0x4255,0xB8,0x92,0x3E,0x3D,0x13,0xAD,0xFD,0xF9); - - -MIDL_DEFINE_GUID(IID, IID_IITSourceCollection,0x2FF6CE20,0xFF87,0x4183,0xB0,0xB3,0xF3,0x23,0xD0,0x47,0xAF,0x41); - - -MIDL_DEFINE_GUID(IID, IID_IITEncoder,0x1CF95A1C,0x55FE,0x4f45,0xA2,0xD3,0x85,0xAC,0x6C,0x50,0x4A,0x73); - - -MIDL_DEFINE_GUID(IID, IID_IITEncoderCollection,0x8862BCA9,0x168D,0x4549,0xA9,0xD5,0xAD,0xB3,0x5E,0x55,0x3B,0xA6); - - -MIDL_DEFINE_GUID(IID, IID_IITEQPreset,0x5BE75F4F,0x68FA,0x4212,0xAC,0xB7,0xBE,0x44,0xEA,0x56,0x97,0x59); - - -MIDL_DEFINE_GUID(IID, IID_IITEQPresetCollection,0xAEF4D111,0x3331,0x48da,0xB0,0xC2,0xB4,0x68,0xD5,0xD6,0x1D,0x08); - - -MIDL_DEFINE_GUID(IID, IID_IITPlaylist,0x3D5E072F,0x2A77,0x4b17,0x9E,0x73,0xE0,0x3B,0x77,0xCC,0xCC,0xA9); - - -MIDL_DEFINE_GUID(IID, IID_IITOperationStatus,0x206479C9,0xFE32,0x4f9b,0xA1,0x8A,0x47,0x5A,0xC9,0x39,0xB4,0x79); - - -MIDL_DEFINE_GUID(IID, IID_IITConvertOperationStatus,0x7063AAF6,0xABA0,0x493b,0xB4,0xFC,0x92,0x0A,0x9F,0x10,0x58,0x75); - - -MIDL_DEFINE_GUID(IID, IID_IITLibraryPlaylist,0x53AE1704,0x491C,0x4289,0x94,0xA0,0x95,0x88,0x15,0x67,0x5A,0x3D); - - -MIDL_DEFINE_GUID(IID, IID_IITUserPlaylist,0x0A504DED,0xA0B5,0x465a,0x8A,0x94,0x50,0xE2,0x0D,0x7D,0xF6,0x92); - - -MIDL_DEFINE_GUID(IID, IID_IITTrack,0x4CB0915D,0x1E54,0x4727,0xBA,0xF3,0xCE,0x6C,0xC9,0xA2,0x25,0xA1); - - -MIDL_DEFINE_GUID(IID, IID_IITTrackCollection,0x755D76F1,0x6B85,0x4ce4,0x8F,0x5F,0xF8,0x8D,0x97,0x43,0xDC,0xD8); - - -MIDL_DEFINE_GUID(IID, IID_IITVisual,0x340F3315,0xED72,0x4c09,0x9A,0xCF,0x21,0xEB,0x4B,0xDF,0x99,0x31); - - -MIDL_DEFINE_GUID(IID, IID_IITVisualCollection,0x88A4CCDD,0x114F,0x4043,0xB6,0x9B,0x84,0xD4,0xE6,0x27,0x49,0x57); - - -MIDL_DEFINE_GUID(IID, IID_IITWindow,0x370D7BE0,0x3A89,0x4a42,0xB9,0x02,0xC7,0x5F,0xC1,0x38,0xBE,0x09); - - -MIDL_DEFINE_GUID(IID, IID_IITBrowserWindow,0xC999F455,0xC4D5,0x4aa4,0x82,0x77,0xF9,0x97,0x53,0x69,0x99,0x74); - - -MIDL_DEFINE_GUID(IID, IID_IITWindowCollection,0x3D8DE381,0x6C0E,0x481f,0xA8,0x65,0xE2,0x38,0x5F,0x59,0xFA,0x43); - - -MIDL_DEFINE_GUID(IID, IID_IiTunes,0x9DD6680B,0x3EDC,0x40db,0xA7,0x71,0xE6,0xFE,0x48,0x32,0xE3,0x4A); - - -MIDL_DEFINE_GUID(IID, DIID__IiTunesEvents,0x5846EB78,0x317E,0x4b6f,0xB0,0xC3,0x11,0xEE,0x8C,0x8F,0xEE,0xF2); - - -MIDL_DEFINE_GUID(IID, DIID__IITConvertOperationStatusEvents,0x5C47A705,0x8E8A,0x45a1,0x9E,0xED,0x71,0xC9,0x93,0xF0,0xBF,0x60); - - -MIDL_DEFINE_GUID(CLSID, CLSID_iTunesApp,0xDC0C2640,0x1415,0x4644,0x87,0x5C,0x6F,0x4D,0x76,0x98,0x39,0xBA); - - -MIDL_DEFINE_GUID(CLSID, CLSID_iTunesConvertOperationStatus,0xD06596AD,0xC900,0x41b2,0xBC,0x68,0x1B,0x48,0x64,0x50,0xFC,0x56); - - -MIDL_DEFINE_GUID(IID, IID_IITArtwork,0xD0A6C1F8,0xBF3D,0x4cd8,0xAC,0x47,0xFE,0x32,0xBD,0xD1,0x72,0x57); - - -MIDL_DEFINE_GUID(IID, IID_IITArtworkCollection,0xBF2742D7,0x418C,0x4858,0x9A,0xF9,0x29,0x81,0xB0,0x62,0xD2,0x3E); - - -MIDL_DEFINE_GUID(IID, IID_IITURLTrack,0x1116E3B5,0x29FD,0x4393,0xA7,0xBD,0x45,0x4E,0x5E,0x32,0x79,0x00); - - -MIDL_DEFINE_GUID(IID, IID_IITAudioCDPlaylist,0xCF496DF3,0x0FED,0x4d7d,0x9B,0xD8,0x52,0x9B,0x6E,0x8A,0x08,0x2E); - - -MIDL_DEFINE_GUID(IID, IID_IITPlaylistCollection,0xFF194254,0x909D,0x4437,0x9C,0x50,0x3A,0xAC,0x2A,0xE6,0x30,0x5C); - - -MIDL_DEFINE_GUID(IID, IID_IITIPodSource,0xCF4D8ACE,0x1720,0x4fb9,0xB0,0xAE,0x98,0x77,0x24,0x9E,0x89,0xB0); - - -MIDL_DEFINE_GUID(IID, IID_IITFileOrCDTrack,0x00D7FE99,0x7868,0x4cc7,0xAD,0x9E,0xAC,0xFD,0x70,0xD0,0x95,0x66); - - -MIDL_DEFINE_GUID(IID, IID_IITPlaylistWindow,0x349CBB45,0x2E5A,0x4822,0x8E,0x4A,0xA7,0x55,0x55,0xA1,0x86,0xF7); - -#undef MIDL_DEFINE_GUID - -#ifdef __cplusplus -} -#endif - - - diff --git a/Plugins/PluginNowPlaying/StdAfx.cpp b/Plugins/PluginNowPlaying/StdAfx.cpp index 0d342cbc..366024d4 100644 --- a/Plugins/PluginNowPlaying/StdAfx.cpp +++ b/Plugins/PluginNowPlaying/StdAfx.cpp @@ -1,19 +1,19 @@ -/* - Copyright (C) 2010-2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" +/* + Copyright (C) 2010-2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" diff --git a/Plugins/PluginNowPlaying/StdAfx.h b/Plugins/PluginNowPlaying/StdAfx.h index ab410e85..01f18db7 100644 --- a/Plugins/PluginNowPlaying/StdAfx.h +++ b/Plugins/PluginNowPlaying/StdAfx.h @@ -1,39 +1,39 @@ -/* - Copyright (C) 2010-2011 Birunthan Mohanathas (www.poiru.net) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __STDAFX_H__ -#define __STDAFX_H__ - -// WinAPI -#include <Windows.h> -#include <WinInet.h> -#include <Psapi.h> -#include <comutil.h> -#include <ShellAPI.h> - -// STL -#include <string> -#include <map> - -// Runtime -#include <process.h> - -// Rainmeter's exported functions -#include "../../Library/Export.h" - -#endif +/* + Copyright (C) 2010-2011 Birunthan Mohanathas (www.poiru.net) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __STDAFX_H__ +#define __STDAFX_H__ + +// WinAPI +#include <Windows.h> +#include <WinInet.h> +#include <Psapi.h> +#include <comutil.h> +#include <ShellAPI.h> + +// STL +#include <string> +#include <map> + +// Runtime +#include <process.h> + +// Rainmeter's exported functions +#include "../../Library/Export.h" + +#endif diff --git a/Plugins/PluginNowPlaying/readme.txt b/Plugins/PluginNowPlaying/readme.txt index 993073fa..79e905c8 100644 --- a/Plugins/PluginNowPlaying/readme.txt +++ b/Plugins/PluginNowPlaying/readme.txt @@ -1,7 +1,7 @@ -* iTunes implementation based on - - onlylyric by zlbruce (onlylyric.googlecode.com) - - iTunesPlugin by Elestel (rainmeter.googlecode.com) - -* WMP implementation based on - - onlylyric by zlbruce (onlylyric.googlecode.com) +* iTunes implementation based on + - onlylyric by zlbruce (onlylyric.googlecode.com) + - iTunesPlugin by Elestel (rainmeter.googlecode.com) + +* WMP implementation based on + - onlylyric by zlbruce (onlylyric.googlecode.com) - Last.fm WMP plugin (www.last.fm) \ No newline at end of file diff --git a/Plugins/PluginNowPlaying/taglib/taglib_config.h b/Plugins/PluginNowPlaying/taglib/taglib_config.h index 9d882258..0f499e2c 100644 --- a/Plugins/PluginNowPlaying/taglib/taglib_config.h +++ b/Plugins/PluginNowPlaying/taglib/taglib_config.h @@ -1,4 +1,4 @@ -/* taglib_config.h. Generated by cmake from taglib_config.h.cmake */ - -#define TAGLIB_WITH_ASF 1 -#define TAGLIB_WITH_MP4 1 +/* taglib_config.h. Generated by cmake from taglib_config.h.cmake */ + +#define TAGLIB_WITH_ASF 1 +#define TAGLIB_WITH_MP4 1 diff --git a/Plugins/PluginPerfMon/MakePtr.h b/Plugins/PluginPerfMon/MakePtr.h index d82f8ae1..e183f75d 100644 --- a/Plugins/PluginPerfMon/MakePtr.h +++ b/Plugins/PluginPerfMon/MakePtr.h @@ -1,10 +1,10 @@ -// MakePtr is a macro that allows you to easily add two values (including -// pointers) together without dealing with C's pointer arithmetic. It -// essentially treats the last two parameters as DWORDs. The first -// parameter is used to typecast the result to the appropriate pointer type. -#ifdef _WIN64 -#define MakePtr(cast, ptr, addValue) (cast)( (DWORD64)(ptr) + (DWORD64)(addValue)) -#else -#define MakePtr(cast, ptr, addValue) (cast)( (DWORD)(ptr) + (DWORD)(addValue)) -#endif - +// MakePtr is a macro that allows you to easily add two values (including +// pointers) together without dealing with C's pointer arithmetic. It +// essentially treats the last two parameters as DWORDs. The first +// parameter is used to typecast the result to the appropriate pointer type. +#ifdef _WIN64 +#define MakePtr(cast, ptr, addValue) (cast)( (DWORD64)(ptr) + (DWORD64)(addValue)) +#else +#define MakePtr(cast, ptr, addValue) (cast)( (DWORD)(ptr) + (DWORD)(addValue)) +#endif + diff --git a/Plugins/PluginPerfMon/ObjInst.cpp b/Plugins/PluginPerfMon/ObjInst.cpp index a29f2afa..9951eb82 100644 --- a/Plugins/PluginPerfMon/ObjInst.cpp +++ b/Plugins/PluginPerfMon/ObjInst.cpp @@ -1,137 +1,137 @@ -//==================================== -// File: OBJINST.CPP -// Author: Matt Pietrek -// From: Microsoft Systems Journal -// "Under the Hood", April 1996 -//==================================== - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include <windows.h> -#include <winperf.h> -#include <stdlib.h> -#pragma hdrstop -#include "titledb.h" -#include "objinst.h" -#include "perfcntr.h" -#include "makeptr.h" - -CPerfObjectInstance::CPerfObjectInstance( - PPERF_INSTANCE_DEFINITION const pPerfInstDef, - PPERF_COUNTER_DEFINITION const pPerfCntrDef, - DWORD nCounters, CPerfTitleDatabase * const pPerfCounterTitles, - BOOL fDummy) -{ - m_pPerfInstDef = pPerfInstDef; - m_pPerfCntrDef = pPerfCntrDef; - m_nCounters = nCounters; - m_pPerfCounterTitles = pPerfCounterTitles; - - m_fDummy = fDummy; -} - -BOOL -CPerfObjectInstance::GetObjectInstanceName( - PTSTR pszObjInstName, DWORD nSize ) -{ - if ( m_fDummy ) - { - *pszObjInstName = 0; // Return an empty string - return FALSE; - } - - if ( nSize < (m_pPerfInstDef->NameLength / sizeof(TCHAR)) ) - return FALSE; - - PWSTR pszName = MakePtr(PWSTR, m_pPerfInstDef, m_pPerfInstDef->NameOffset); - - #ifdef UNICODE - lstrcpy( pszObjInstName, pszName ); - #else - wcstombs( pszObjInstName, pszName, nSize ); - #endif - - return TRUE; -} - -CPerfCounter * -CPerfObjectInstance::MakeCounter( PPERF_COUNTER_DEFINITION const pCounterDef ) -{ - // Look up the name of this counter in the title database - PTSTR pszName = m_pPerfCounterTitles->GetTitleStringFromIndex( - pCounterDef->CounterNameTitleIndex ); - - DWORD nInstanceDefSize = m_fDummy ? 0 : m_pPerfInstDef->ByteLength; - - // Create a new CPerfCounter. The caller is responsible for deleting it. - return new CPerfCounter(pszName, - pCounterDef->CounterType, - MakePtr( PBYTE, m_pPerfInstDef, - nInstanceDefSize + - pCounterDef->CounterOffset ), - pCounterDef->CounterSize ); -} - -CPerfCounter * -CPerfObjectInstance::GetCounterByIndex( DWORD index ) -{ - PPERF_COUNTER_DEFINITION pCurrentCounter; - - if ( index >= m_nCounters ) - return 0; - - pCurrentCounter = m_pPerfCntrDef; - - // Find the correct PERF_COUNTER_DEFINITION by looping - for ( DWORD i = 0; i < index; i++ ) - { - pCurrentCounter = MakePtr( PPERF_COUNTER_DEFINITION, - pCurrentCounter, - pCurrentCounter->ByteLength ); - } - - if ( pCurrentCounter->ByteLength == 0 ) - return 0; - - return MakeCounter( pCurrentCounter ); -} - -CPerfCounter * -CPerfObjectInstance::GetFirstCounter( void ) -{ - m_currentCounter = 0; - return GetCounterByIndex( m_currentCounter ); -} - -CPerfCounter * -CPerfObjectInstance::GetNextCounter( void ) -{ - m_currentCounter++; - return GetCounterByIndex( m_currentCounter ); -} - -CPerfCounter * -CPerfObjectInstance::GetCounterByName( PCTSTR const pszName ) -{ - DWORD cntrIdx = m_pPerfCounterTitles->GetIndexFromTitleString(pszName); - if ( cntrIdx == 0 ) - return 0; - - PPERF_COUNTER_DEFINITION pCurrentCounter = m_pPerfCntrDef; - - // Find the correct PERF_COUNTER_DEFINITION by looping and comparing - for ( DWORD i = 0; i < m_nCounters; i++ ) - { - if ( pCurrentCounter->CounterNameTitleIndex == cntrIdx ) - return MakeCounter( pCurrentCounter ); - - // Nope. Not this one. Advance to the next counter - pCurrentCounter = MakePtr( PPERF_COUNTER_DEFINITION, - pCurrentCounter, - pCurrentCounter->ByteLength ); - } - - return 0; +//==================================== +// File: OBJINST.CPP +// Author: Matt Pietrek +// From: Microsoft Systems Journal +// "Under the Hood", April 1996 +//==================================== + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include <windows.h> +#include <winperf.h> +#include <stdlib.h> +#pragma hdrstop +#include "titledb.h" +#include "objinst.h" +#include "perfcntr.h" +#include "makeptr.h" + +CPerfObjectInstance::CPerfObjectInstance( + PPERF_INSTANCE_DEFINITION const pPerfInstDef, + PPERF_COUNTER_DEFINITION const pPerfCntrDef, + DWORD nCounters, CPerfTitleDatabase * const pPerfCounterTitles, + BOOL fDummy) +{ + m_pPerfInstDef = pPerfInstDef; + m_pPerfCntrDef = pPerfCntrDef; + m_nCounters = nCounters; + m_pPerfCounterTitles = pPerfCounterTitles; + + m_fDummy = fDummy; +} + +BOOL +CPerfObjectInstance::GetObjectInstanceName( + PTSTR pszObjInstName, DWORD nSize ) +{ + if ( m_fDummy ) + { + *pszObjInstName = 0; // Return an empty string + return FALSE; + } + + if ( nSize < (m_pPerfInstDef->NameLength / sizeof(TCHAR)) ) + return FALSE; + + PWSTR pszName = MakePtr(PWSTR, m_pPerfInstDef, m_pPerfInstDef->NameOffset); + + #ifdef UNICODE + lstrcpy( pszObjInstName, pszName ); + #else + wcstombs( pszObjInstName, pszName, nSize ); + #endif + + return TRUE; +} + +CPerfCounter * +CPerfObjectInstance::MakeCounter( PPERF_COUNTER_DEFINITION const pCounterDef ) +{ + // Look up the name of this counter in the title database + PTSTR pszName = m_pPerfCounterTitles->GetTitleStringFromIndex( + pCounterDef->CounterNameTitleIndex ); + + DWORD nInstanceDefSize = m_fDummy ? 0 : m_pPerfInstDef->ByteLength; + + // Create a new CPerfCounter. The caller is responsible for deleting it. + return new CPerfCounter(pszName, + pCounterDef->CounterType, + MakePtr( PBYTE, m_pPerfInstDef, + nInstanceDefSize + + pCounterDef->CounterOffset ), + pCounterDef->CounterSize ); +} + +CPerfCounter * +CPerfObjectInstance::GetCounterByIndex( DWORD index ) +{ + PPERF_COUNTER_DEFINITION pCurrentCounter; + + if ( index >= m_nCounters ) + return 0; + + pCurrentCounter = m_pPerfCntrDef; + + // Find the correct PERF_COUNTER_DEFINITION by looping + for ( DWORD i = 0; i < index; i++ ) + { + pCurrentCounter = MakePtr( PPERF_COUNTER_DEFINITION, + pCurrentCounter, + pCurrentCounter->ByteLength ); + } + + if ( pCurrentCounter->ByteLength == 0 ) + return 0; + + return MakeCounter( pCurrentCounter ); +} + +CPerfCounter * +CPerfObjectInstance::GetFirstCounter( void ) +{ + m_currentCounter = 0; + return GetCounterByIndex( m_currentCounter ); +} + +CPerfCounter * +CPerfObjectInstance::GetNextCounter( void ) +{ + m_currentCounter++; + return GetCounterByIndex( m_currentCounter ); +} + +CPerfCounter * +CPerfObjectInstance::GetCounterByName( PCTSTR const pszName ) +{ + DWORD cntrIdx = m_pPerfCounterTitles->GetIndexFromTitleString(pszName); + if ( cntrIdx == 0 ) + return 0; + + PPERF_COUNTER_DEFINITION pCurrentCounter = m_pPerfCntrDef; + + // Find the correct PERF_COUNTER_DEFINITION by looping and comparing + for ( DWORD i = 0; i < m_nCounters; i++ ) + { + if ( pCurrentCounter->CounterNameTitleIndex == cntrIdx ) + return MakeCounter( pCurrentCounter ); + + // Nope. Not this one. Advance to the next counter + pCurrentCounter = MakePtr( PPERF_COUNTER_DEFINITION, + pCurrentCounter, + pCurrentCounter->ByteLength ); + } + + return 0; } \ No newline at end of file diff --git a/Plugins/PluginPerfMon/ObjInst.h b/Plugins/PluginPerfMon/ObjInst.h index bb4bda55..8a6bd698 100644 --- a/Plugins/PluginPerfMon/ObjInst.h +++ b/Plugins/PluginPerfMon/ObjInst.h @@ -1,59 +1,59 @@ -#ifndef __Obinst_h__ -#define __Objinst_h__ - -#ifndef _WINDOWS_ -#include <windows.h> -#endif -#ifndef _WINPERF_ -#include <winperf.h> -#endif - -class CPerfTitleDatabase; -class CPerfCounter; - -class CPerfObjectInstance -{ - public: - - CPerfObjectInstance( - PPERF_INSTANCE_DEFINITION const pPerfInstDef, - PPERF_COUNTER_DEFINITION const pPerfCntrDef, DWORD nCounters, - CPerfTitleDatabase * const pPerfTitleDatabase, BOOL fDummy ); - - ~CPerfObjectInstance( void ){ } - - BOOL GetObjectInstanceName( PTSTR pszObjInstName, DWORD nSize ); - - // Functions that return CPerfCounter pointers. Caller is - // responsible for deleting the CPerfCounter * when done with it. - - CPerfCounter * GetFirstCounter( void ); - - CPerfCounter * GetNextCounter( void ); - - CPerfCounter * GetCounterByName( PCTSTR const pszName ); - - protected: - - PPERF_INSTANCE_DEFINITION m_pPerfInstDef; - - unsigned m_nCounters; - - unsigned m_currentCounter; - - PPERF_COUNTER_DEFINITION m_pPerfCntrDef; - - CPerfTitleDatabase * m_pPerfCounterTitles; - - CPerfCounter * MakeCounter( PPERF_COUNTER_DEFINITION const pCounter ); - - CPerfCounter * GetCounterByIndex( DWORD index ); - - CPerfTitleDatabase *m_pCounterTitleDatabase; - - BOOL m_fDummy; // FALSE normally, TRUE when an object with no instances -}; - -typedef CPerfObjectInstance * PCPerfObjectInstance; - +#ifndef __Obinst_h__ +#define __Objinst_h__ + +#ifndef _WINDOWS_ +#include <windows.h> +#endif +#ifndef _WINPERF_ +#include <winperf.h> +#endif + +class CPerfTitleDatabase; +class CPerfCounter; + +class CPerfObjectInstance +{ + public: + + CPerfObjectInstance( + PPERF_INSTANCE_DEFINITION const pPerfInstDef, + PPERF_COUNTER_DEFINITION const pPerfCntrDef, DWORD nCounters, + CPerfTitleDatabase * const pPerfTitleDatabase, BOOL fDummy ); + + ~CPerfObjectInstance( void ){ } + + BOOL GetObjectInstanceName( PTSTR pszObjInstName, DWORD nSize ); + + // Functions that return CPerfCounter pointers. Caller is + // responsible for deleting the CPerfCounter * when done with it. + + CPerfCounter * GetFirstCounter( void ); + + CPerfCounter * GetNextCounter( void ); + + CPerfCounter * GetCounterByName( PCTSTR const pszName ); + + protected: + + PPERF_INSTANCE_DEFINITION m_pPerfInstDef; + + unsigned m_nCounters; + + unsigned m_currentCounter; + + PPERF_COUNTER_DEFINITION m_pPerfCntrDef; + + CPerfTitleDatabase * m_pPerfCounterTitles; + + CPerfCounter * MakeCounter( PPERF_COUNTER_DEFINITION const pCounter ); + + CPerfCounter * GetCounterByIndex( DWORD index ); + + CPerfTitleDatabase *m_pCounterTitleDatabase; + + BOOL m_fDummy; // FALSE normally, TRUE when an object with no instances +}; + +typedef CPerfObjectInstance * PCPerfObjectInstance; + #endif \ No newline at end of file diff --git a/Plugins/PluginPerfMon/ObjList.cpp b/Plugins/PluginPerfMon/ObjList.cpp index 06caceee..fd165fba 100644 --- a/Plugins/PluginPerfMon/ObjList.cpp +++ b/Plugins/PluginPerfMon/ObjList.cpp @@ -1,83 +1,83 @@ -//==================================== -// File: OBJLIST.CPP -// Author: Matt Pietrek -// From: Microsoft Systems Journal -// "Under the Hood", April 1996 -//==================================== - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include <windows.h> -#include <winperf.h> -#include <stdlib.h> -#pragma hdrstop -#include "titledb.h" -#include "objlist.h" -#include "perfobj.h" -#include "makeptr.h" - -CPerfObjectList::CPerfObjectList( - CPerfSnapshot * const pPerfSnapshot, - CPerfTitleDatabase * const pPerfTitleDatabase ) -{ - m_pPerfSnapshot = pPerfSnapshot; - m_pPerfCounterTitles = pPerfTitleDatabase; -} - -CPerfObject * -CPerfObjectList::GetFirstPerfObject( void ) -{ - m_currentObjectListIndex = 0; - if ( m_currentObjectListIndex >= m_pPerfSnapshot->GetNumObjectTypes() ) - return 0; - - m_pCurrObjectType = - (PPERF_OBJECT_TYPE)m_pPerfSnapshot->GetPostHeaderPointer(); - - return new CPerfObject( m_pCurrObjectType, m_pPerfCounterTitles ); -} - -CPerfObject * -CPerfObjectList::GetNextPerfObject( void ) -{ - // Are we at the last object in the list? Return nullptr if so. - if ( ++m_currentObjectListIndex >= m_pPerfSnapshot->GetNumObjectTypes() ) - return 0; - - // Advance to the next PERF_OBJECT_TYPE structure - m_pCurrObjectType = MakePtr(PPERF_OBJECT_TYPE, - m_pCurrObjectType, - m_pCurrObjectType->TotalByteLength ); - - return new CPerfObject( m_pCurrObjectType, m_pPerfCounterTitles ); -} - -CPerfObject * -CPerfObjectList::GetPerfObject( PCTSTR const pszObjListName ) -{ - DWORD objListIdx - = m_pPerfCounterTitles->GetIndexFromTitleString( pszObjListName ); - if ( 0 == objListIdx ) - return 0; - - // Point at first PERF_OBJECT_TYPE, and loop through the list, looking - // for one that matches. - PPERF_OBJECT_TYPE pCurrObjectType = - (PPERF_OBJECT_TYPE)m_pPerfSnapshot->GetPostHeaderPointer(); - - for ( unsigned i=0; i < m_pPerfSnapshot->GetNumObjectTypes(); i++ ) - { - // Is this the one that matches? - if ( pCurrObjectType->ObjectNameTitleIndex == objListIdx ) - return new CPerfObject(pCurrObjectType, m_pPerfCounterTitles); - - // Nope... try the next object type - pCurrObjectType = MakePtr( PPERF_OBJECT_TYPE, - pCurrObjectType, - pCurrObjectType->TotalByteLength ); - } - - return 0; +//==================================== +// File: OBJLIST.CPP +// Author: Matt Pietrek +// From: Microsoft Systems Journal +// "Under the Hood", April 1996 +//==================================== + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include <windows.h> +#include <winperf.h> +#include <stdlib.h> +#pragma hdrstop +#include "titledb.h" +#include "objlist.h" +#include "perfobj.h" +#include "makeptr.h" + +CPerfObjectList::CPerfObjectList( + CPerfSnapshot * const pPerfSnapshot, + CPerfTitleDatabase * const pPerfTitleDatabase ) +{ + m_pPerfSnapshot = pPerfSnapshot; + m_pPerfCounterTitles = pPerfTitleDatabase; +} + +CPerfObject * +CPerfObjectList::GetFirstPerfObject( void ) +{ + m_currentObjectListIndex = 0; + if ( m_currentObjectListIndex >= m_pPerfSnapshot->GetNumObjectTypes() ) + return 0; + + m_pCurrObjectType = + (PPERF_OBJECT_TYPE)m_pPerfSnapshot->GetPostHeaderPointer(); + + return new CPerfObject( m_pCurrObjectType, m_pPerfCounterTitles ); +} + +CPerfObject * +CPerfObjectList::GetNextPerfObject( void ) +{ + // Are we at the last object in the list? Return nullptr if so. + if ( ++m_currentObjectListIndex >= m_pPerfSnapshot->GetNumObjectTypes() ) + return 0; + + // Advance to the next PERF_OBJECT_TYPE structure + m_pCurrObjectType = MakePtr(PPERF_OBJECT_TYPE, + m_pCurrObjectType, + m_pCurrObjectType->TotalByteLength ); + + return new CPerfObject( m_pCurrObjectType, m_pPerfCounterTitles ); +} + +CPerfObject * +CPerfObjectList::GetPerfObject( PCTSTR const pszObjListName ) +{ + DWORD objListIdx + = m_pPerfCounterTitles->GetIndexFromTitleString( pszObjListName ); + if ( 0 == objListIdx ) + return 0; + + // Point at first PERF_OBJECT_TYPE, and loop through the list, looking + // for one that matches. + PPERF_OBJECT_TYPE pCurrObjectType = + (PPERF_OBJECT_TYPE)m_pPerfSnapshot->GetPostHeaderPointer(); + + for ( unsigned i=0; i < m_pPerfSnapshot->GetNumObjectTypes(); i++ ) + { + // Is this the one that matches? + if ( pCurrObjectType->ObjectNameTitleIndex == objListIdx ) + return new CPerfObject(pCurrObjectType, m_pPerfCounterTitles); + + // Nope... try the next object type + pCurrObjectType = MakePtr( PPERF_OBJECT_TYPE, + pCurrObjectType, + pCurrObjectType->TotalByteLength ); + } + + return 0; } \ No newline at end of file diff --git a/Plugins/PluginPerfMon/ObjList.h b/Plugins/PluginPerfMon/ObjList.h index ae24f189..b8dcb868 100644 --- a/Plugins/PluginPerfMon/ObjList.h +++ b/Plugins/PluginPerfMon/ObjList.h @@ -1,46 +1,46 @@ -#ifndef __Objlist_h__ -#define __Objlist_h__ - -#ifndef _WINDOWS_ -#include <windows.h> -#endif -#ifndef _WINPERF_ -#include <winperf.h> -#endif -#ifndef __Perfsnap_h__ -#include "perfsnap.h" -#endif - -class CPerfObject; - -class CPerfObjectList -{ - public: - - CPerfObjectList(CPerfSnapshot * const pPerfSnapshot, - CPerfTitleDatabase * const pPerfTitleDatabase ); - - ~CPerfObjectList( void ){ }; - - // Functions that return CPerfObject pointers. Caller is responsible - // for deleting the CPerfObject * when done with it. - - CPerfObject * GetFirstPerfObject( void ); - - CPerfObject * GetNextPerfObject( void ); - - CPerfObject * GetPerfObject( PCTSTR const pszObjListName ); - - protected: - - CPerfSnapshot * m_pPerfSnapshot; - - CPerfTitleDatabase * m_pPerfCounterTitles; - - unsigned m_currentObjectListIndex; - - PPERF_OBJECT_TYPE m_pCurrObjectType; // current first/next object ptr -}; - -typedef CPerfObjectList * PCPerfObjectList; +#ifndef __Objlist_h__ +#define __Objlist_h__ + +#ifndef _WINDOWS_ +#include <windows.h> +#endif +#ifndef _WINPERF_ +#include <winperf.h> +#endif +#ifndef __Perfsnap_h__ +#include "perfsnap.h" +#endif + +class CPerfObject; + +class CPerfObjectList +{ + public: + + CPerfObjectList(CPerfSnapshot * const pPerfSnapshot, + CPerfTitleDatabase * const pPerfTitleDatabase ); + + ~CPerfObjectList( void ){ }; + + // Functions that return CPerfObject pointers. Caller is responsible + // for deleting the CPerfObject * when done with it. + + CPerfObject * GetFirstPerfObject( void ); + + CPerfObject * GetNextPerfObject( void ); + + CPerfObject * GetPerfObject( PCTSTR const pszObjListName ); + + protected: + + CPerfSnapshot * m_pPerfSnapshot; + + CPerfTitleDatabase * m_pPerfCounterTitles; + + unsigned m_currentObjectListIndex; + + PPERF_OBJECT_TYPE m_pCurrObjectType; // current first/next object ptr +}; + +typedef CPerfObjectList * PCPerfObjectList; #endif \ No newline at end of file diff --git a/Plugins/PluginPerfMon/PerfCntr.cpp b/Plugins/PluginPerfMon/PerfCntr.cpp index aa9a7848..a2576e20 100644 --- a/Plugins/PluginPerfMon/PerfCntr.cpp +++ b/Plugins/PluginPerfMon/PerfCntr.cpp @@ -1,123 +1,123 @@ -//==================================== -// File: PERFCNTR.CPP -// Author: Matt Pietrek -// From: Microsoft Systems Journal -// "Under the Hood", APRIL 1996 -//==================================== - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include <windows.h> -#include <winperf.h> -#include <stdlib.h> -#include <stdio.h> -#include <malloc.h> -#include <tchar.h> -#pragma hdrstop -#include "perfcntr.h" - -CPerfCounter::CPerfCounter( PTSTR const pszName, DWORD type, - PBYTE const pData, DWORD cbData ) -{ - m_pszName = _tcsdup( pszName ); - m_type = type; - m_cbData = cbData; - m_pData = new BYTE[m_cbData]; - memcpy( m_pData, pData, m_cbData ); -} - -CPerfCounter::~CPerfCounter( void ) -{ - free( m_pszName ); - delete []m_pData; -} - -BOOL -CPerfCounter::GetData( PBYTE pBuffer, DWORD cbBuffer, DWORD *pType ) -{ - if ( cbBuffer < m_cbData ) // Make sure the buffer is big enough - return FALSE; - - memcpy( pBuffer, m_pData, m_cbData ); // copy the data - - if ( pType ) // If the user wants the type, give it to them - *pType = m_type; - - return TRUE; -} - -BOOL -CPerfCounter::Format( PTSTR pszBuffer, DWORD nSize, BOOL fHex ) -{ - // Do better formatting!!! Check length!!! - - PTSTR pszPrefix = TEXT(""); - TCHAR szTemp[512]; - - // First, ascertain the basic type (number, counter, text, or zero) - switch ( m_type & 0x00000C00 ) - { - case PERF_TYPE_ZERO: - { - wsprintf( pszBuffer, TEXT("ZERO") ); return TRUE; - } - case PERF_TYPE_TEXT: - { - wsprintf( pszBuffer, TEXT("text counter") ); return TRUE; - } - case PERF_TYPE_COUNTER: - { - switch( m_type & 0x00070000 ) - { - case PERF_COUNTER_RATE: - pszPrefix = TEXT("counter rate "); break; - case PERF_COUNTER_FRACTION: - pszPrefix = TEXT("counter fraction "); break; - case PERF_COUNTER_BASE: - pszPrefix = TEXT("counter base "); break; - case PERF_COUNTER_ELAPSED: - pszPrefix = TEXT("counter elapsed "); break; - case PERF_COUNTER_QUEUELEN: - pszPrefix = TEXT("counter queuelen "); break; - case PERF_COUNTER_HISTOGRAM: - pszPrefix = TEXT("counter histogram "); break; - default: - pszPrefix = TEXT("counter value "); break; - } - } - } - - PTSTR pszFmt = fHex ? TEXT("%s%Xh") : TEXT("%s%u"); - - switch ( m_cbData ) - { - case 1: wsprintf(szTemp, pszFmt, pszPrefix, *(PBYTE)m_pData); - break; - case 2: wsprintf(szTemp, pszFmt, pszPrefix, *(PWORD)m_pData); - break; - case 4: wsprintf(szTemp, pszFmt, pszPrefix, *(PDWORD)m_pData); - break; - case 8: // Danger! Assumes little-endian (X86) byte ordering - wsprintf( szTemp, TEXT("%s%X%X"), pszPrefix, - *(PDWORD)(m_pData+4), *(PDWORD)m_pData ); break; - break; - - default: wsprintf( szTemp, TEXT("<unhandled size %u>"), m_cbData ); - } - - switch ( m_type & 0x70000000 ) - { - case PERF_DISPLAY_SECONDS: - _tcscat( szTemp, TEXT(" secs") ); break; - case PERF_DISPLAY_PERCENT: - _tcscat( szTemp, TEXT(" %") ); break; - case PERF_DISPLAY_PER_SEC: - _tcscat( szTemp, TEXT(" /sec") ); break; - } - - lstrcpyn( pszBuffer, szTemp, nSize ); - - return TRUE; +//==================================== +// File: PERFCNTR.CPP +// Author: Matt Pietrek +// From: Microsoft Systems Journal +// "Under the Hood", APRIL 1996 +//==================================== + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include <windows.h> +#include <winperf.h> +#include <stdlib.h> +#include <stdio.h> +#include <malloc.h> +#include <tchar.h> +#pragma hdrstop +#include "perfcntr.h" + +CPerfCounter::CPerfCounter( PTSTR const pszName, DWORD type, + PBYTE const pData, DWORD cbData ) +{ + m_pszName = _tcsdup( pszName ); + m_type = type; + m_cbData = cbData; + m_pData = new BYTE[m_cbData]; + memcpy( m_pData, pData, m_cbData ); +} + +CPerfCounter::~CPerfCounter( void ) +{ + free( m_pszName ); + delete []m_pData; +} + +BOOL +CPerfCounter::GetData( PBYTE pBuffer, DWORD cbBuffer, DWORD *pType ) +{ + if ( cbBuffer < m_cbData ) // Make sure the buffer is big enough + return FALSE; + + memcpy( pBuffer, m_pData, m_cbData ); // copy the data + + if ( pType ) // If the user wants the type, give it to them + *pType = m_type; + + return TRUE; +} + +BOOL +CPerfCounter::Format( PTSTR pszBuffer, DWORD nSize, BOOL fHex ) +{ + // Do better formatting!!! Check length!!! + + PTSTR pszPrefix = TEXT(""); + TCHAR szTemp[512]; + + // First, ascertain the basic type (number, counter, text, or zero) + switch ( m_type & 0x00000C00 ) + { + case PERF_TYPE_ZERO: + { + wsprintf( pszBuffer, TEXT("ZERO") ); return TRUE; + } + case PERF_TYPE_TEXT: + { + wsprintf( pszBuffer, TEXT("text counter") ); return TRUE; + } + case PERF_TYPE_COUNTER: + { + switch( m_type & 0x00070000 ) + { + case PERF_COUNTER_RATE: + pszPrefix = TEXT("counter rate "); break; + case PERF_COUNTER_FRACTION: + pszPrefix = TEXT("counter fraction "); break; + case PERF_COUNTER_BASE: + pszPrefix = TEXT("counter base "); break; + case PERF_COUNTER_ELAPSED: + pszPrefix = TEXT("counter elapsed "); break; + case PERF_COUNTER_QUEUELEN: + pszPrefix = TEXT("counter queuelen "); break; + case PERF_COUNTER_HISTOGRAM: + pszPrefix = TEXT("counter histogram "); break; + default: + pszPrefix = TEXT("counter value "); break; + } + } + } + + PTSTR pszFmt = fHex ? TEXT("%s%Xh") : TEXT("%s%u"); + + switch ( m_cbData ) + { + case 1: wsprintf(szTemp, pszFmt, pszPrefix, *(PBYTE)m_pData); + break; + case 2: wsprintf(szTemp, pszFmt, pszPrefix, *(PWORD)m_pData); + break; + case 4: wsprintf(szTemp, pszFmt, pszPrefix, *(PDWORD)m_pData); + break; + case 8: // Danger! Assumes little-endian (X86) byte ordering + wsprintf( szTemp, TEXT("%s%X%X"), pszPrefix, + *(PDWORD)(m_pData+4), *(PDWORD)m_pData ); break; + break; + + default: wsprintf( szTemp, TEXT("<unhandled size %u>"), m_cbData ); + } + + switch ( m_type & 0x70000000 ) + { + case PERF_DISPLAY_SECONDS: + _tcscat( szTemp, TEXT(" secs") ); break; + case PERF_DISPLAY_PERCENT: + _tcscat( szTemp, TEXT(" %") ); break; + case PERF_DISPLAY_PER_SEC: + _tcscat( szTemp, TEXT(" /sec") ); break; + } + + lstrcpyn( pszBuffer, szTemp, nSize ); + + return TRUE; } \ No newline at end of file diff --git a/Plugins/PluginPerfMon/PerfCntr.h b/Plugins/PluginPerfMon/PerfCntr.h index 7aab5560..e48d458b 100644 --- a/Plugins/PluginPerfMon/PerfCntr.h +++ b/Plugins/PluginPerfMon/PerfCntr.h @@ -1,35 +1,35 @@ -#ifndef __Perfcntr_h__ -#define __Perfcntr_h__ - -class CPerfCounter -{ - public: - - CPerfCounter( PTSTR const pszName, DWORD type, - PBYTE const pData, DWORD cbData ); - - ~CPerfCounter( void ); - - PTSTR GetName( void ) { return m_pszName; } - - DWORD GetType( void ) { return m_type; } - - DWORD GetSize( void ) { return m_cbData; } - - BOOL GetData( PBYTE pBuffer, DWORD cbBuffer, DWORD *pType ); - - BOOL Format( PTSTR pszBuffer, DWORD nSize, BOOL fHex = FALSE ); - - protected: - - PTSTR m_pszName; - - DWORD m_type; - - PBYTE m_pData; - - DWORD m_cbData; -}; - -typedef CPerfCounter * PCPerfCounter; +#ifndef __Perfcntr_h__ +#define __Perfcntr_h__ + +class CPerfCounter +{ + public: + + CPerfCounter( PTSTR const pszName, DWORD type, + PBYTE const pData, DWORD cbData ); + + ~CPerfCounter( void ); + + PTSTR GetName( void ) { return m_pszName; } + + DWORD GetType( void ) { return m_type; } + + DWORD GetSize( void ) { return m_cbData; } + + BOOL GetData( PBYTE pBuffer, DWORD cbBuffer, DWORD *pType ); + + BOOL Format( PTSTR pszBuffer, DWORD nSize, BOOL fHex = FALSE ); + + protected: + + PTSTR m_pszName; + + DWORD m_type; + + PBYTE m_pData; + + DWORD m_cbData; +}; + +typedef CPerfCounter * PCPerfCounter; #endif \ No newline at end of file diff --git a/Plugins/PluginPerfMon/PerfData.cpp b/Plugins/PluginPerfMon/PerfData.cpp index c4caa197..963912c3 100644 --- a/Plugins/PluginPerfMon/PerfData.cpp +++ b/Plugins/PluginPerfMon/PerfData.cpp @@ -1,206 +1,206 @@ -/* - Copyright (C) 2004 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include <windows.h> -#include <vector> -#include "Titledb.h" -#include "PerfSnap.h" -#include "PerfObj.h" -#include "PerfCntr.h" -#include "ObjList.h" -#include "ObjInst.h" -#include "../API/RainmeterAPI.h" -#include "../../Common/RawString.h" - -struct MeasureData -{ - RawString objectName; - RawString counterName; - RawString instanceName; - ULONGLONG oldValue; - bool difference; - bool firstTime; - - MeasureData() : - oldValue(), - difference(false), - firstTime(true) - { - } -}; - -static CPerfTitleDatabase g_TitleCounter(PERF_TITLE_COUNTER); - -ULONGLONG GetPerfData(PCTSTR ObjectName, PCTSTR InstanceName, PCTSTR CounterName); - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - MeasureData* measure = new MeasureData; - *data = measure; -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - MeasureData* measure = (MeasureData*)data; - bool changed = false; - - LPCWSTR value = RmReadString(rm, L"PerfMonObject", L""); - if (_wcsicmp(value, measure->objectName.c_str()) != 0) - { - measure->objectName = value; - changed = true; - } - - value = RmReadString(rm, L"PerfMonCounter", L""); - if (_wcsicmp(value, measure->counterName.c_str()) != 0) - { - measure->counterName = value; - changed = true; - } - - value = RmReadString(rm, L"PerfMonInstance", L""); - if (_wcsicmp(value, measure->instanceName.c_str()) != 0) - { - measure->instanceName = value; - changed = true; - } - - bool diff = RmReadInt(rm, L"PerfMonDifference", 1) == 1; - if (diff != measure->difference) - { - measure->difference = diff; - changed = true; - } - - if (changed) - { - measure->oldValue = 0; - measure->firstTime = true; - *maxValue = 0.0; - } -} - -PLUGIN_EXPORT double Update(void* data) -{ - MeasureData* measure = (MeasureData*)data; - double value = 0; - - ULONGLONG longValue = GetPerfData( - measure->objectName.c_str(), - measure->instanceName.c_str(), - measure->counterName.c_str()); - - if (measure->difference) - { - // Compare with the old value - if (!measure->firstTime) - { - value = (double)(longValue - measure->oldValue); - } - - measure->oldValue = longValue; - measure->firstTime = false; - } - else - { - value = (double)longValue; - } - - return value; -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - MeasureData* measure = (MeasureData*)data; - delete measure; - - CPerfSnapshot::CleanUp(); -} - -ULONGLONG GetPerfData(LPCWSTR objectName, LPCWSTR instanceName, LPCWSTR counterName) -{ - BYTE data[256]; - WCHAR name[256]; - ULONGLONG value = 0; - - CPerfSnapshot snapshot(&g_TitleCounter); - CPerfObjectList objList(&snapshot, &g_TitleCounter); - - if (snapshot.TakeSnapshot(objectName)) - { - CPerfObject* pPerfObj = objList.GetPerfObject(objectName); - - if (pPerfObj) - { - for (CPerfObjectInstance* pObjInst = pPerfObj->GetFirstObjectInstance(); - pObjInst != nullptr; - pObjInst = pPerfObj->GetNextObjectInstance()) - { - if (*instanceName) - { - if (pObjInst->GetObjectInstanceName(name, 256)) - { - if (_wcsicmp(instanceName, name) != 0) - { - delete pObjInst; - continue; - } - } - else - { - delete pObjInst; - continue; - } - } - - CPerfCounter* pPerfCntr = pObjInst->GetCounterByName(counterName); - if (pPerfCntr != nullptr) - { - pPerfCntr->GetData(data, 256, nullptr); - - if (pPerfCntr->GetSize() == 1) - { - value = *(BYTE*)data; - } - else if (pPerfCntr->GetSize() == 2) - { - value = *(WORD*)data; - } - else if (pPerfCntr->GetSize() == 4) - { - value = *(DWORD*)data; - } - else if (pPerfCntr->GetSize() == 8) - { - value = *(ULONGLONG*)data; - } - - delete pPerfCntr; - delete pObjInst; - break; // No need to continue - } - - delete pObjInst; - } - - delete pPerfObj; - } - } - - return value; -} +/* + Copyright (C) 2004 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <windows.h> +#include <vector> +#include "Titledb.h" +#include "PerfSnap.h" +#include "PerfObj.h" +#include "PerfCntr.h" +#include "ObjList.h" +#include "ObjInst.h" +#include "../API/RainmeterAPI.h" +#include "../../Common/RawString.h" + +struct MeasureData +{ + RawString objectName; + RawString counterName; + RawString instanceName; + ULONGLONG oldValue; + bool difference; + bool firstTime; + + MeasureData() : + oldValue(), + difference(false), + firstTime(true) + { + } +}; + +static CPerfTitleDatabase g_TitleCounter(PERF_TITLE_COUNTER); + +ULONGLONG GetPerfData(PCTSTR ObjectName, PCTSTR InstanceName, PCTSTR CounterName); + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + MeasureData* measure = new MeasureData; + *data = measure; +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + MeasureData* measure = (MeasureData*)data; + bool changed = false; + + LPCWSTR value = RmReadString(rm, L"PerfMonObject", L""); + if (_wcsicmp(value, measure->objectName.c_str()) != 0) + { + measure->objectName = value; + changed = true; + } + + value = RmReadString(rm, L"PerfMonCounter", L""); + if (_wcsicmp(value, measure->counterName.c_str()) != 0) + { + measure->counterName = value; + changed = true; + } + + value = RmReadString(rm, L"PerfMonInstance", L""); + if (_wcsicmp(value, measure->instanceName.c_str()) != 0) + { + measure->instanceName = value; + changed = true; + } + + bool diff = RmReadInt(rm, L"PerfMonDifference", 1) == 1; + if (diff != measure->difference) + { + measure->difference = diff; + changed = true; + } + + if (changed) + { + measure->oldValue = 0; + measure->firstTime = true; + *maxValue = 0.0; + } +} + +PLUGIN_EXPORT double Update(void* data) +{ + MeasureData* measure = (MeasureData*)data; + double value = 0; + + ULONGLONG longValue = GetPerfData( + measure->objectName.c_str(), + measure->instanceName.c_str(), + measure->counterName.c_str()); + + if (measure->difference) + { + // Compare with the old value + if (!measure->firstTime) + { + value = (double)(longValue - measure->oldValue); + } + + measure->oldValue = longValue; + measure->firstTime = false; + } + else + { + value = (double)longValue; + } + + return value; +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + MeasureData* measure = (MeasureData*)data; + delete measure; + + CPerfSnapshot::CleanUp(); +} + +ULONGLONG GetPerfData(LPCWSTR objectName, LPCWSTR instanceName, LPCWSTR counterName) +{ + BYTE data[256]; + WCHAR name[256]; + ULONGLONG value = 0; + + CPerfSnapshot snapshot(&g_TitleCounter); + CPerfObjectList objList(&snapshot, &g_TitleCounter); + + if (snapshot.TakeSnapshot(objectName)) + { + CPerfObject* pPerfObj = objList.GetPerfObject(objectName); + + if (pPerfObj) + { + for (CPerfObjectInstance* pObjInst = pPerfObj->GetFirstObjectInstance(); + pObjInst != nullptr; + pObjInst = pPerfObj->GetNextObjectInstance()) + { + if (*instanceName) + { + if (pObjInst->GetObjectInstanceName(name, 256)) + { + if (_wcsicmp(instanceName, name) != 0) + { + delete pObjInst; + continue; + } + } + else + { + delete pObjInst; + continue; + } + } + + CPerfCounter* pPerfCntr = pObjInst->GetCounterByName(counterName); + if (pPerfCntr != nullptr) + { + pPerfCntr->GetData(data, 256, nullptr); + + if (pPerfCntr->GetSize() == 1) + { + value = *(BYTE*)data; + } + else if (pPerfCntr->GetSize() == 2) + { + value = *(WORD*)data; + } + else if (pPerfCntr->GetSize() == 4) + { + value = *(DWORD*)data; + } + else if (pPerfCntr->GetSize() == 8) + { + value = *(ULONGLONG*)data; + } + + delete pPerfCntr; + delete pObjInst; + break; // No need to continue + } + + delete pObjInst; + } + + delete pPerfObj; + } + } + + return value; +} diff --git a/Plugins/PluginPerfMon/PerfObj.cpp b/Plugins/PluginPerfMon/PerfObj.cpp index 67bf5670..2ca97295 100644 --- a/Plugins/PluginPerfMon/PerfObj.cpp +++ b/Plugins/PluginPerfMon/PerfObj.cpp @@ -1,96 +1,96 @@ -//==================================== -// File: PERFOBJ.CPP -// Author: Matt Pietrek -// From: Microsoft Systems Journal -// "Under the Hood", APRIL 1996 -//==================================== - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include <windows.h> -#include <winperf.h> -#include <stdlib.h> -#pragma hdrstop -#include "titledb.h" -#include "perfobj.h" -#include "objinst.h" -#include "makeptr.h" - -CPerfObject::CPerfObject( PPERF_OBJECT_TYPE const pObjectList, - CPerfTitleDatabase * const pPerfCounterTitles) -{ - m_pObjectList = pObjectList; - m_pPerfCounterTitles = pPerfCounterTitles; -} - -CPerfObjectInstance * -CPerfObject::GetFirstObjectInstance( void ) -{ - m_currentObjectInstance = 0; - if ( m_currentObjectInstance >= GetObjectInstanceCount() ) - return 0; - - // Point at the first PERF_INSTANCE_DEFINITION - m_pCurrentObjectInstanceDefinition = - MakePtr( PPERF_INSTANCE_DEFINITION, m_pObjectList, - m_pObjectList->DefinitionLength ); - - return new CPerfObjectInstance( - m_pCurrentObjectInstanceDefinition, - MakePtr(PPERF_COUNTER_DEFINITION, - m_pObjectList, m_pObjectList->HeaderLength), - m_pObjectList->NumCounters, - m_pPerfCounterTitles, - m_pObjectList->NumInstances == - PERF_NO_INSTANCES ? TRUE : FALSE ); -} - -CPerfObjectInstance * -CPerfObject::GetNextObjectInstance( void ) -{ - if ( m_pObjectList->NumInstances == PERF_NO_INSTANCES ) - return 0; - - if ( ++m_currentObjectInstance >= GetObjectInstanceCount() ) - return 0; - - // Advance to the next PERF_INSTANCE_DEFINITION in the list. However, - // following the current PERF_INSTANCE_DEFINITION is the counter data, - // which is also of variable length. So, we gotta take that into - // account when finding the next PERF_INSTANCE_DEFINITION - - // First, get a pointer to the counter data size field - PDWORD pCounterDataSize - = MakePtr(PDWORD, m_pCurrentObjectInstanceDefinition, - m_pCurrentObjectInstanceDefinition->ByteLength); - - // Now we can point at the next PPERF_INSTANCE_DEFINITION - m_pCurrentObjectInstanceDefinition = MakePtr(PPERF_INSTANCE_DEFINITION, - m_pCurrentObjectInstanceDefinition, - m_pCurrentObjectInstanceDefinition->ByteLength - + *pCounterDataSize); - - // Create a CPerfObjectInstance based around the PPERF_INSTANCE_DEFINITION - return new CPerfObjectInstance(m_pCurrentObjectInstanceDefinition, - MakePtr(PPERF_COUNTER_DEFINITION, - m_pObjectList, - m_pObjectList->HeaderLength), - m_pObjectList->NumCounters, - m_pPerfCounterTitles, - FALSE ); -} - -BOOL -CPerfObject::GetObjectTypeName( PTSTR pszObjTypeName, DWORD nSize ) -{ - PTSTR pszName = m_pPerfCounterTitles->GetTitleStringFromIndex( - m_pObjectList->ObjectNameTitleIndex ); - - if ( !pszName ) - return FALSE; - - lstrcpyn( pszObjTypeName, pszName, nSize ); - return TRUE; +//==================================== +// File: PERFOBJ.CPP +// Author: Matt Pietrek +// From: Microsoft Systems Journal +// "Under the Hood", APRIL 1996 +//==================================== + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include <windows.h> +#include <winperf.h> +#include <stdlib.h> +#pragma hdrstop +#include "titledb.h" +#include "perfobj.h" +#include "objinst.h" +#include "makeptr.h" + +CPerfObject::CPerfObject( PPERF_OBJECT_TYPE const pObjectList, + CPerfTitleDatabase * const pPerfCounterTitles) +{ + m_pObjectList = pObjectList; + m_pPerfCounterTitles = pPerfCounterTitles; +} + +CPerfObjectInstance * +CPerfObject::GetFirstObjectInstance( void ) +{ + m_currentObjectInstance = 0; + if ( m_currentObjectInstance >= GetObjectInstanceCount() ) + return 0; + + // Point at the first PERF_INSTANCE_DEFINITION + m_pCurrentObjectInstanceDefinition = + MakePtr( PPERF_INSTANCE_DEFINITION, m_pObjectList, + m_pObjectList->DefinitionLength ); + + return new CPerfObjectInstance( + m_pCurrentObjectInstanceDefinition, + MakePtr(PPERF_COUNTER_DEFINITION, + m_pObjectList, m_pObjectList->HeaderLength), + m_pObjectList->NumCounters, + m_pPerfCounterTitles, + m_pObjectList->NumInstances == + PERF_NO_INSTANCES ? TRUE : FALSE ); +} + +CPerfObjectInstance * +CPerfObject::GetNextObjectInstance( void ) +{ + if ( m_pObjectList->NumInstances == PERF_NO_INSTANCES ) + return 0; + + if ( ++m_currentObjectInstance >= GetObjectInstanceCount() ) + return 0; + + // Advance to the next PERF_INSTANCE_DEFINITION in the list. However, + // following the current PERF_INSTANCE_DEFINITION is the counter data, + // which is also of variable length. So, we gotta take that into + // account when finding the next PERF_INSTANCE_DEFINITION + + // First, get a pointer to the counter data size field + PDWORD pCounterDataSize + = MakePtr(PDWORD, m_pCurrentObjectInstanceDefinition, + m_pCurrentObjectInstanceDefinition->ByteLength); + + // Now we can point at the next PPERF_INSTANCE_DEFINITION + m_pCurrentObjectInstanceDefinition = MakePtr(PPERF_INSTANCE_DEFINITION, + m_pCurrentObjectInstanceDefinition, + m_pCurrentObjectInstanceDefinition->ByteLength + + *pCounterDataSize); + + // Create a CPerfObjectInstance based around the PPERF_INSTANCE_DEFINITION + return new CPerfObjectInstance(m_pCurrentObjectInstanceDefinition, + MakePtr(PPERF_COUNTER_DEFINITION, + m_pObjectList, + m_pObjectList->HeaderLength), + m_pObjectList->NumCounters, + m_pPerfCounterTitles, + FALSE ); +} + +BOOL +CPerfObject::GetObjectTypeName( PTSTR pszObjTypeName, DWORD nSize ) +{ + PTSTR pszName = m_pPerfCounterTitles->GetTitleStringFromIndex( + m_pObjectList->ObjectNameTitleIndex ); + + if ( !pszName ) + return FALSE; + + lstrcpyn( pszObjTypeName, pszName, nSize ); + return TRUE; } \ No newline at end of file diff --git a/Plugins/PluginPerfMon/PerfObj.h b/Plugins/PluginPerfMon/PerfObj.h index df2c3e4f..acc4125f 100644 --- a/Plugins/PluginPerfMon/PerfObj.h +++ b/Plugins/PluginPerfMon/PerfObj.h @@ -1,45 +1,45 @@ -#ifndef __Perfobj_h__ -#define __Perfobj_h__ - -#ifndef _WINDOWS_ -#include <windows.h> -#endif -#ifndef _WINPERF_ -#include <winperf.h> -#endif - -class CPerfObjectInstance; - -class CPerfObject -{ - public: - - CPerfObject( PPERF_OBJECT_TYPE const pObjectList, - CPerfTitleDatabase * const pPerfTitleDatabase ); - - ~CPerfObject( void ){ } - - // Functions that return CPerfObjectInstance pointers. Caller is - // responsible for deleting the CPerfObjectInstance * when done with it. - - CPerfObjectInstance * GetFirstObjectInstance( void ); - - CPerfObjectInstance * GetNextObjectInstance( void ); - - unsigned GetObjectInstanceCount(void){return m_pObjectList->NumInstances;} - - BOOL GetObjectTypeName( PTSTR pszObjTypeName, DWORD nSize ); - - protected: - - PPERF_OBJECT_TYPE m_pObjectList; - - unsigned m_currentObjectInstance; - - PPERF_INSTANCE_DEFINITION m_pCurrentObjectInstanceDefinition; - - CPerfTitleDatabase * m_pPerfCounterTitles; -}; - -typedef CPerfObject * PCPerfObject; +#ifndef __Perfobj_h__ +#define __Perfobj_h__ + +#ifndef _WINDOWS_ +#include <windows.h> +#endif +#ifndef _WINPERF_ +#include <winperf.h> +#endif + +class CPerfObjectInstance; + +class CPerfObject +{ + public: + + CPerfObject( PPERF_OBJECT_TYPE const pObjectList, + CPerfTitleDatabase * const pPerfTitleDatabase ); + + ~CPerfObject( void ){ } + + // Functions that return CPerfObjectInstance pointers. Caller is + // responsible for deleting the CPerfObjectInstance * when done with it. + + CPerfObjectInstance * GetFirstObjectInstance( void ); + + CPerfObjectInstance * GetNextObjectInstance( void ); + + unsigned GetObjectInstanceCount(void){return m_pObjectList->NumInstances;} + + BOOL GetObjectTypeName( PTSTR pszObjTypeName, DWORD nSize ); + + protected: + + PPERF_OBJECT_TYPE m_pObjectList; + + unsigned m_currentObjectInstance; + + PPERF_INSTANCE_DEFINITION m_pCurrentObjectInstanceDefinition; + + CPerfTitleDatabase * m_pPerfCounterTitles; +}; + +typedef CPerfObject * PCPerfObject; #endif \ No newline at end of file diff --git a/Plugins/PluginPerfMon/PerfSnap.cpp b/Plugins/PluginPerfMon/PerfSnap.cpp index 7bd2e7fc..453a8fe8 100644 --- a/Plugins/PluginPerfMon/PerfSnap.cpp +++ b/Plugins/PluginPerfMon/PerfSnap.cpp @@ -1,165 +1,165 @@ -//============================================================================ -// File: PERFSNAP.CPP -// Author: Matt Pietrek -// From: Microsoft Systems Journal, "Under the Hood", March 1996 -//============================================================================ - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include <windows.h> -#include <winperf.h> -#include <stdlib.h> -#include <tchar.h> -#pragma hdrstop -#include "titledb.h" -#include "perfsnap.h" -#include "makeptr.h" - -PBYTE CPerfSnapshot::c_pBuffer = nullptr; -DWORD CPerfSnapshot::c_cbBufferSize = 0; - -CPerfSnapshot::CPerfSnapshot( - CPerfTitleDatabase * pCounterTitles ) -{ - m_pPerfDataHeader = 0; - m_pCounterTitles = pCounterTitles; -} - -CPerfSnapshot::~CPerfSnapshot( void ) -{ - DisposeSnapshot(); -} - -BOOL -CPerfSnapshot::TakeSnapshot( PCTSTR pszSnapshotItems ) -{ - DisposeSnapshot(); // Clear out any current snapshot - - // Convert the input string (e.g., "Process") into the form required - // by the HKEY_PERFORMANCE_DATA key (e.g., "232") - - TCHAR szConvertedItemNames[ 256 ]; - if ( !ConvertSnapshotItemName( pszSnapshotItems, szConvertedItemNames, - sizeof(szConvertedItemNames) ) ) - return FALSE; - - DWORD cbAllocSize = 0; - LONG retValue; - - while ( 1 ) // Loop until we get the data, or we fail unexpectedly - { - retValue = RegQueryValueEx( HKEY_PERFORMANCE_DATA, - szConvertedItemNames, 0, 0, - c_pBuffer, &c_cbBufferSize ); - - if ( retValue == ERROR_SUCCESS ) // We apparently got the snapshot - { - m_pPerfDataHeader = (PPERF_DATA_BLOCK)c_pBuffer; - - // Verify that the signature is a unicode "PERF" - if ( memcmp( m_pPerfDataHeader->Signature, L"PERF", 8 ) ) - break; - - return TRUE; - } - else if ( retValue != ERROR_MORE_DATA ) // Anything other failure - break; // code means something - // bad happened, so bail out. - - // If we get here, our buffer wasn't big enough. Delete it and - // try again with a bigger buffer. - delete [] c_pBuffer; - - // The new buffer size will be 4096 bytes bigger than the larger - // of: 1) The previous allocation size, or 2) The size that the - // RegQueryValueEx call said was necessary. - if ( c_cbBufferSize > cbAllocSize ) - cbAllocSize = c_cbBufferSize + 4096; - else - cbAllocSize += 4096; - - // Allocate a new, larger buffer in preparation to try again. - c_pBuffer = new BYTE[ cbAllocSize ]; - if ( !c_pBuffer ) - break; - - c_cbBufferSize = cbAllocSize; - } - - // If we get here, the RegQueryValueEx failed unexpectedly. - return FALSE; -} - -void -CPerfSnapshot::DisposeSnapshot( void ) -{ - m_pPerfDataHeader = 0; -} - -void -CPerfSnapshot::CleanUp( void ) -{ - delete [] c_pBuffer; - c_pBuffer = 0; - c_cbBufferSize = 0; -} - -DWORD -CPerfSnapshot::GetNumObjectTypes( void ) -{ - return m_pPerfDataHeader ? m_pPerfDataHeader->NumObjectTypes: 0; -} - -BOOL -CPerfSnapshot::GetSystemName( PTSTR pszSystemName, DWORD nSize ) -{ - if ( !m_pPerfDataHeader ) // If no snapshot data, bail out. - return FALSE; - - // Make sure the input buffer size is big enough - if ( nSize < m_pPerfDataHeader->SystemNameLength ) - return FALSE; - - // Make a unicode string point to the system name string - // that's stored in the PERF_DATA_BLOCK - LPWSTR lpwszName = MakePtr( LPWSTR, m_pPerfDataHeader, - m_pPerfDataHeader->SystemNameOffset ); - - #ifdef UNICODE // Copy the PERF_DATA_BLOCK string to the input buffer - lstrcpy( pszSystemName, lpwszName ); - #else - wcstombs( pszSystemName, lpwszName, nSize ); - #endif - - return TRUE; -} - -PVOID -CPerfSnapshot::GetPostHeaderPointer( void ) -{ - // Returns a header to the first byte following the PERF_DATA_BLOCK - // (including the variable length system name string at the end) - return m_pPerfDataHeader ? - MakePtr(PVOID, m_pPerfDataHeader,m_pPerfDataHeader->HeaderLength) - : 0; -} - -BOOL -CPerfSnapshot::ConvertSnapshotItemName( PCTSTR pszIn, - PTSTR pszOut, DWORD nSize ) -{ - if ( IsBadStringPtr( pszIn, 0xFFFFFFFF ) ) - return FALSE; - - - DWORD objectID = m_pCounterTitles->GetIndexFromTitleString(pszIn); - - if ( objectID ) - pszOut += wsprintf( pszOut, TEXT("%u "), objectID ); - else - pszOut += wsprintf( pszOut, TEXT("%s "), pszIn ); - - return TRUE; +//============================================================================ +// File: PERFSNAP.CPP +// Author: Matt Pietrek +// From: Microsoft Systems Journal, "Under the Hood", March 1996 +//============================================================================ + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include <windows.h> +#include <winperf.h> +#include <stdlib.h> +#include <tchar.h> +#pragma hdrstop +#include "titledb.h" +#include "perfsnap.h" +#include "makeptr.h" + +PBYTE CPerfSnapshot::c_pBuffer = nullptr; +DWORD CPerfSnapshot::c_cbBufferSize = 0; + +CPerfSnapshot::CPerfSnapshot( + CPerfTitleDatabase * pCounterTitles ) +{ + m_pPerfDataHeader = 0; + m_pCounterTitles = pCounterTitles; +} + +CPerfSnapshot::~CPerfSnapshot( void ) +{ + DisposeSnapshot(); +} + +BOOL +CPerfSnapshot::TakeSnapshot( PCTSTR pszSnapshotItems ) +{ + DisposeSnapshot(); // Clear out any current snapshot + + // Convert the input string (e.g., "Process") into the form required + // by the HKEY_PERFORMANCE_DATA key (e.g., "232") + + TCHAR szConvertedItemNames[ 256 ]; + if ( !ConvertSnapshotItemName( pszSnapshotItems, szConvertedItemNames, + sizeof(szConvertedItemNames) ) ) + return FALSE; + + DWORD cbAllocSize = 0; + LONG retValue; + + while ( 1 ) // Loop until we get the data, or we fail unexpectedly + { + retValue = RegQueryValueEx( HKEY_PERFORMANCE_DATA, + szConvertedItemNames, 0, 0, + c_pBuffer, &c_cbBufferSize ); + + if ( retValue == ERROR_SUCCESS ) // We apparently got the snapshot + { + m_pPerfDataHeader = (PPERF_DATA_BLOCK)c_pBuffer; + + // Verify that the signature is a unicode "PERF" + if ( memcmp( m_pPerfDataHeader->Signature, L"PERF", 8 ) ) + break; + + return TRUE; + } + else if ( retValue != ERROR_MORE_DATA ) // Anything other failure + break; // code means something + // bad happened, so bail out. + + // If we get here, our buffer wasn't big enough. Delete it and + // try again with a bigger buffer. + delete [] c_pBuffer; + + // The new buffer size will be 4096 bytes bigger than the larger + // of: 1) The previous allocation size, or 2) The size that the + // RegQueryValueEx call said was necessary. + if ( c_cbBufferSize > cbAllocSize ) + cbAllocSize = c_cbBufferSize + 4096; + else + cbAllocSize += 4096; + + // Allocate a new, larger buffer in preparation to try again. + c_pBuffer = new BYTE[ cbAllocSize ]; + if ( !c_pBuffer ) + break; + + c_cbBufferSize = cbAllocSize; + } + + // If we get here, the RegQueryValueEx failed unexpectedly. + return FALSE; +} + +void +CPerfSnapshot::DisposeSnapshot( void ) +{ + m_pPerfDataHeader = 0; +} + +void +CPerfSnapshot::CleanUp( void ) +{ + delete [] c_pBuffer; + c_pBuffer = 0; + c_cbBufferSize = 0; +} + +DWORD +CPerfSnapshot::GetNumObjectTypes( void ) +{ + return m_pPerfDataHeader ? m_pPerfDataHeader->NumObjectTypes: 0; +} + +BOOL +CPerfSnapshot::GetSystemName( PTSTR pszSystemName, DWORD nSize ) +{ + if ( !m_pPerfDataHeader ) // If no snapshot data, bail out. + return FALSE; + + // Make sure the input buffer size is big enough + if ( nSize < m_pPerfDataHeader->SystemNameLength ) + return FALSE; + + // Make a unicode string point to the system name string + // that's stored in the PERF_DATA_BLOCK + LPWSTR lpwszName = MakePtr( LPWSTR, m_pPerfDataHeader, + m_pPerfDataHeader->SystemNameOffset ); + + #ifdef UNICODE // Copy the PERF_DATA_BLOCK string to the input buffer + lstrcpy( pszSystemName, lpwszName ); + #else + wcstombs( pszSystemName, lpwszName, nSize ); + #endif + + return TRUE; +} + +PVOID +CPerfSnapshot::GetPostHeaderPointer( void ) +{ + // Returns a header to the first byte following the PERF_DATA_BLOCK + // (including the variable length system name string at the end) + return m_pPerfDataHeader ? + MakePtr(PVOID, m_pPerfDataHeader,m_pPerfDataHeader->HeaderLength) + : 0; +} + +BOOL +CPerfSnapshot::ConvertSnapshotItemName( PCTSTR pszIn, + PTSTR pszOut, DWORD nSize ) +{ + if ( IsBadStringPtr( pszIn, 0xFFFFFFFF ) ) + return FALSE; + + + DWORD objectID = m_pCounterTitles->GetIndexFromTitleString(pszIn); + + if ( objectID ) + pszOut += wsprintf( pszOut, TEXT("%u "), objectID ); + else + pszOut += wsprintf( pszOut, TEXT("%s "), pszIn ); + + return TRUE; } \ No newline at end of file diff --git a/Plugins/PluginPerfMon/PerfSnap.h b/Plugins/PluginPerfMon/PerfSnap.h index 1c6c9376..7a10c736 100644 --- a/Plugins/PluginPerfMon/PerfSnap.h +++ b/Plugins/PluginPerfMon/PerfSnap.h @@ -1,43 +1,43 @@ -#ifndef __Perfsnap_h__ -#define __Perfsnap_h__ - -#ifndef _WINPERF_ -#include <winperf.h> -#endif - -class CPerfTitleDatabase; - -class CPerfSnapshot -{ - private: - - static PBYTE c_pBuffer; - static DWORD c_cbBufferSize; - - PPERF_DATA_BLOCK m_pPerfDataHeader; // Points to snapshot data - CPerfTitleDatabase * m_pCounterTitles; // The title conversion object - - // Private function to convert the ASCII strings passedto TakeSnapshot() - // into a suitable form for the RegQueryValue call - BOOL ConvertSnapshotItemName( PCTSTR pszIn, PTSTR pszOut, DWORD nSize ); - - public: - - CPerfSnapshot( CPerfTitleDatabase * pCounterTitles ); - - ~CPerfSnapshot( void ); - - BOOL TakeSnapshot( PCTSTR pszSnapshotItems ); - - void DisposeSnapshot( void ); - - DWORD GetNumObjectTypes( void ); // # of objects the snapshot includes - - BOOL GetSystemName( PTSTR pszSystemName, DWORD nSize ); - - PVOID GetPostHeaderPointer( void ); // Pointer to data following header - - static void CleanUp( void ); -}; - +#ifndef __Perfsnap_h__ +#define __Perfsnap_h__ + +#ifndef _WINPERF_ +#include <winperf.h> +#endif + +class CPerfTitleDatabase; + +class CPerfSnapshot +{ + private: + + static PBYTE c_pBuffer; + static DWORD c_cbBufferSize; + + PPERF_DATA_BLOCK m_pPerfDataHeader; // Points to snapshot data + CPerfTitleDatabase * m_pCounterTitles; // The title conversion object + + // Private function to convert the ASCII strings passedto TakeSnapshot() + // into a suitable form for the RegQueryValue call + BOOL ConvertSnapshotItemName( PCTSTR pszIn, PTSTR pszOut, DWORD nSize ); + + public: + + CPerfSnapshot( CPerfTitleDatabase * pCounterTitles ); + + ~CPerfSnapshot( void ); + + BOOL TakeSnapshot( PCTSTR pszSnapshotItems ); + + void DisposeSnapshot( void ); + + DWORD GetNumObjectTypes( void ); // # of objects the snapshot includes + + BOOL GetSystemName( PTSTR pszSystemName, DWORD nSize ); + + PVOID GetPostHeaderPointer( void ); // Pointer to data following header + + static void CleanUp( void ); +}; + #endif \ No newline at end of file diff --git a/Plugins/PluginPerfMon/PluginPerfMon.rc b/Plugins/PluginPerfMon/PluginPerfMon.rc index b07006e9..406f5c9e 100644 --- a/Plugins/PluginPerfMon/PluginPerfMon.rc +++ b/Plugins/PluginPerfMon/PluginPerfMon.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,2,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.2.0.0" - VALUE "LegalCopyright", " 2010 - Rainy" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,2,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.2.0.0" + VALUE "LegalCopyright", " 2010 - Rainy" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginPerfMon/PluginPerfMon.vcxproj b/Plugins/PluginPerfMon/PluginPerfMon.vcxproj index 257768ca..ddfe9886 100644 --- a/Plugins/PluginPerfMon/PluginPerfMon.vcxproj +++ b/Plugins/PluginPerfMon/PluginPerfMon.vcxproj @@ -1,50 +1,50 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{5344B52B-BAC3-479C-B41D-D465B8BDA1AD}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>PerfMon</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClInclude Include="MakePtr.h" /> - <ClInclude Include="ObjInst.h" /> - <ClInclude Include="ObjList.h" /> - <ClInclude Include="PerfCntr.h" /> - <ClInclude Include="PerfObj.h" /> - <ClInclude Include="PerfSnap.h" /> - <ClInclude Include="Titledb.h" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="ObjInst.cpp" /> - <ClCompile Include="ObjList.cpp" /> - <ClCompile Include="PerfCntr.cpp" /> - <ClCompile Include="PerfData.cpp" /> - <ClCompile Include="PerfObj.cpp" /> - <ClCompile Include="PerfSnap.cpp" /> - <ClCompile Include="Titledb.cpp" /> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="PluginPerfMon.rc" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{5344B52B-BAC3-479C-B41D-D465B8BDA1AD}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>PerfMon</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="MakePtr.h" /> + <ClInclude Include="ObjInst.h" /> + <ClInclude Include="ObjList.h" /> + <ClInclude Include="PerfCntr.h" /> + <ClInclude Include="PerfObj.h" /> + <ClInclude Include="PerfSnap.h" /> + <ClInclude Include="Titledb.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="ObjInst.cpp" /> + <ClCompile Include="ObjList.cpp" /> + <ClCompile Include="PerfCntr.cpp" /> + <ClCompile Include="PerfData.cpp" /> + <ClCompile Include="PerfObj.cpp" /> + <ClCompile Include="PerfSnap.cpp" /> + <ClCompile Include="Titledb.cpp" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="PluginPerfMon.rc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginPerfMon/Titledb.cpp b/Plugins/PluginPerfMon/Titledb.cpp index 9535baa1..b6a66e50 100644 --- a/Plugins/PluginPerfMon/Titledb.cpp +++ b/Plugins/PluginPerfMon/Titledb.cpp @@ -1,158 +1,158 @@ -//=========================================================================== -// File: CTITLEDB.CPP -// Author: Matt Pietrek -// From: Microsoft Systems Journal, "Under the Hood", March 1996 -//=========================================================================== - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include <windows.h> -#include <stdlib.h> -#include <winperf.h> -#include <tchar.h> -#pragma hdrstop -#include "Titledb.h" - -CPerfTitleDatabase::CPerfTitleDatabase( - PERFORMANCE_TITLE_TYPE titleType ) -{ - m_nLastIndex = 0; - m_TitleStrings = 0; - m_pszRawStrings = 0; - - // Determine the appropriate strings to pass to RegOpenKeyEx - PTSTR psz009RegValue, pszLastIndexRegValue; - if ( PERF_TITLE_COUNTER == titleType ) - { - psz009RegValue = TEXT("Counter 009"); - pszLastIndexRegValue = TEXT("Last Counter"); - } - else if ( PERF_TITLE_EXPLAIN == titleType ) - { - psz009RegValue = TEXT("Explain 009"); - pszLastIndexRegValue = TEXT("Last Help"); - } - else - return; - - // Find out the max number of entries - HKEY hKeyPerflib = 0; - - // Open the registry key that has the values for the maximum number - // of title strings - if ( ERROR_SUCCESS != RegOpenKeyEx( - HKEY_LOCAL_MACHINE, - TEXT("software\\microsoft\\windows nt\\currentversion\\perflib"), - 0, KEY_READ, &hKeyPerflib ) ) - return; - - // Read in the number of title strings - DWORD cbLastIndex = sizeof(m_nLastIndex); - if ( ERROR_SUCCESS != RegQueryValueEx( - hKeyPerflib, pszLastIndexRegValue, 0, 0, - (PBYTE)&m_nLastIndex, &cbLastIndex ) ) - { - RegCloseKey( hKeyPerflib ); - return; - } - - RegCloseKey( hKeyPerflib ); - - // - // Now go find and process the raw string data - // - - // Determine how big the raw data in the REG_MULTI_SZ value is - DWORD cbTitleStrings; - if ( ERROR_SUCCESS != RegQueryValueEx( HKEY_PERFORMANCE_DATA, psz009RegValue, 0,0,0, &cbTitleStrings)) - return; - - // Allocate memory for the raw registry title string data - m_pszRawStrings = new TCHAR[cbTitleStrings]; - - // Read in the raw title strings - if ( ERROR_SUCCESS != RegQueryValueEx( HKEY_PERFORMANCE_DATA, - psz009RegValue, 0, 0, (PBYTE)m_pszRawStrings, - &cbTitleStrings ) ) - { - delete []m_pszRawStrings; - return; - } - - // allocate memory for an array of string pointers. - m_TitleStrings = new PTSTR[ m_nLastIndex+1 ]; - if ( !m_TitleStrings ) - { - delete []m_pszRawStrings; - return; - } - - // Initialize the m_TitleStrings to all NULLs, since there may - // be some array slots that aren't used. - memset( m_TitleStrings, 0, sizeof(PTSTR) * (m_nLastIndex+1) ); - - // The raw data entries are an ASCII string index (e.g., "242"), followed - // by the corresponding string. Fill in the appropriate slot in the - // m_TitleStrings array with the pointer to the string name. The end - // of the list is indicated by a double nullptr. - - PTSTR pszWorkStr = (PTSTR)m_pszRawStrings; - unsigned cbCurrStr; - - // While the length of the current string isn't 0... - while ( 0 != (cbCurrStr = lstrlen( pszWorkStr)) ) - { - // Convert the first string to a binary representation - unsigned index = _ttoi( pszWorkStr ); // _ttoi -> atoi() - - if ( index > m_nLastIndex ) - break; - - // Now point to the string following it. This is the title string - pszWorkStr += cbCurrStr + 1; - - // Fill in the appropriate slot in the title strings array. - m_TitleStrings[index] = pszWorkStr; - - // Advance to the next index/title pair - pszWorkStr += lstrlen(pszWorkStr) + 1; - } -} - -CPerfTitleDatabase::~CPerfTitleDatabase( ) -{ - delete []m_TitleStrings; - m_TitleStrings = 0; - delete []m_pszRawStrings; - m_pszRawStrings = 0; - m_nLastIndex = 0; -} - -PTSTR -CPerfTitleDatabase::GetTitleStringFromIndex( unsigned index ) -{ - if ( index > m_nLastIndex ) // Is index within range? - return 0; - - return m_TitleStrings[ index ]; -} - -unsigned -CPerfTitleDatabase::GetIndexFromTitleString( PCTSTR pszTitleString ) -{ - if ( IsBadStringPtr(pszTitleString, 0xFFFFFFFF) ) - return 0; - - // Loop through all the non-null string array entries, doing a case- - // insensitive comparison. If found, return the correpsonding index - for ( unsigned i = 1; i <= m_nLastIndex; i++ ) - { - if ( m_TitleStrings[i] ) - if ( 0 == _tcsicmp( pszTitleString, m_TitleStrings[i] ) ) - return i; - } - - return 0; -} +//=========================================================================== +// File: CTITLEDB.CPP +// Author: Matt Pietrek +// From: Microsoft Systems Journal, "Under the Hood", March 1996 +//=========================================================================== + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include <windows.h> +#include <stdlib.h> +#include <winperf.h> +#include <tchar.h> +#pragma hdrstop +#include "Titledb.h" + +CPerfTitleDatabase::CPerfTitleDatabase( + PERFORMANCE_TITLE_TYPE titleType ) +{ + m_nLastIndex = 0; + m_TitleStrings = 0; + m_pszRawStrings = 0; + + // Determine the appropriate strings to pass to RegOpenKeyEx + PTSTR psz009RegValue, pszLastIndexRegValue; + if ( PERF_TITLE_COUNTER == titleType ) + { + psz009RegValue = TEXT("Counter 009"); + pszLastIndexRegValue = TEXT("Last Counter"); + } + else if ( PERF_TITLE_EXPLAIN == titleType ) + { + psz009RegValue = TEXT("Explain 009"); + pszLastIndexRegValue = TEXT("Last Help"); + } + else + return; + + // Find out the max number of entries + HKEY hKeyPerflib = 0; + + // Open the registry key that has the values for the maximum number + // of title strings + if ( ERROR_SUCCESS != RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + TEXT("software\\microsoft\\windows nt\\currentversion\\perflib"), + 0, KEY_READ, &hKeyPerflib ) ) + return; + + // Read in the number of title strings + DWORD cbLastIndex = sizeof(m_nLastIndex); + if ( ERROR_SUCCESS != RegQueryValueEx( + hKeyPerflib, pszLastIndexRegValue, 0, 0, + (PBYTE)&m_nLastIndex, &cbLastIndex ) ) + { + RegCloseKey( hKeyPerflib ); + return; + } + + RegCloseKey( hKeyPerflib ); + + // + // Now go find and process the raw string data + // + + // Determine how big the raw data in the REG_MULTI_SZ value is + DWORD cbTitleStrings; + if ( ERROR_SUCCESS != RegQueryValueEx( HKEY_PERFORMANCE_DATA, psz009RegValue, 0,0,0, &cbTitleStrings)) + return; + + // Allocate memory for the raw registry title string data + m_pszRawStrings = new TCHAR[cbTitleStrings]; + + // Read in the raw title strings + if ( ERROR_SUCCESS != RegQueryValueEx( HKEY_PERFORMANCE_DATA, + psz009RegValue, 0, 0, (PBYTE)m_pszRawStrings, + &cbTitleStrings ) ) + { + delete []m_pszRawStrings; + return; + } + + // allocate memory for an array of string pointers. + m_TitleStrings = new PTSTR[ m_nLastIndex+1 ]; + if ( !m_TitleStrings ) + { + delete []m_pszRawStrings; + return; + } + + // Initialize the m_TitleStrings to all NULLs, since there may + // be some array slots that aren't used. + memset( m_TitleStrings, 0, sizeof(PTSTR) * (m_nLastIndex+1) ); + + // The raw data entries are an ASCII string index (e.g., "242"), followed + // by the corresponding string. Fill in the appropriate slot in the + // m_TitleStrings array with the pointer to the string name. The end + // of the list is indicated by a double nullptr. + + PTSTR pszWorkStr = (PTSTR)m_pszRawStrings; + unsigned cbCurrStr; + + // While the length of the current string isn't 0... + while ( 0 != (cbCurrStr = lstrlen( pszWorkStr)) ) + { + // Convert the first string to a binary representation + unsigned index = _ttoi( pszWorkStr ); // _ttoi -> atoi() + + if ( index > m_nLastIndex ) + break; + + // Now point to the string following it. This is the title string + pszWorkStr += cbCurrStr + 1; + + // Fill in the appropriate slot in the title strings array. + m_TitleStrings[index] = pszWorkStr; + + // Advance to the next index/title pair + pszWorkStr += lstrlen(pszWorkStr) + 1; + } +} + +CPerfTitleDatabase::~CPerfTitleDatabase( ) +{ + delete []m_TitleStrings; + m_TitleStrings = 0; + delete []m_pszRawStrings; + m_pszRawStrings = 0; + m_nLastIndex = 0; +} + +PTSTR +CPerfTitleDatabase::GetTitleStringFromIndex( unsigned index ) +{ + if ( index > m_nLastIndex ) // Is index within range? + return 0; + + return m_TitleStrings[ index ]; +} + +unsigned +CPerfTitleDatabase::GetIndexFromTitleString( PCTSTR pszTitleString ) +{ + if ( IsBadStringPtr(pszTitleString, 0xFFFFFFFF) ) + return 0; + + // Loop through all the non-null string array entries, doing a case- + // insensitive comparison. If found, return the correpsonding index + for ( unsigned i = 1; i <= m_nLastIndex; i++ ) + { + if ( m_TitleStrings[i] ) + if ( 0 == _tcsicmp( pszTitleString, m_TitleStrings[i] ) ) + return i; + } + + return 0; +} diff --git a/Plugins/PluginPerfMon/Titledb.h b/Plugins/PluginPerfMon/Titledb.h index 48b3831b..d3c5c5aa 100644 --- a/Plugins/PluginPerfMon/Titledb.h +++ b/Plugins/PluginPerfMon/Titledb.h @@ -1,24 +1,24 @@ -#ifndef __Ctitledb_h__ -#define __Ctitledb_h__ - -enum PERFORMANCE_TITLE_TYPE { PERF_TITLE_COUNTER, PERF_TITLE_EXPLAIN }; - -class CPerfTitleDatabase -{ - private: - - unsigned m_nLastIndex; - PTSTR * m_TitleStrings; - PTSTR m_pszRawStrings; - - public: - - CPerfTitleDatabase( PERFORMANCE_TITLE_TYPE titleType ); - ~CPerfTitleDatabase( ); - - unsigned GetLastTitleIndex(void) { return m_nLastIndex; } - PTSTR GetTitleStringFromIndex( unsigned index ); - unsigned GetIndexFromTitleString( PCTSTR pszTitleString ); -}; - -#endif +#ifndef __Ctitledb_h__ +#define __Ctitledb_h__ + +enum PERFORMANCE_TITLE_TYPE { PERF_TITLE_COUNTER, PERF_TITLE_EXPLAIN }; + +class CPerfTitleDatabase +{ + private: + + unsigned m_nLastIndex; + PTSTR * m_TitleStrings; + PTSTR m_pszRawStrings; + + public: + + CPerfTitleDatabase( PERFORMANCE_TITLE_TYPE titleType ); + ~CPerfTitleDatabase( ); + + unsigned GetLastTitleIndex(void) { return m_nLastIndex; } + PTSTR GetTitleStringFromIndex( unsigned index ); + unsigned GetIndexFromTitleString( PCTSTR pszTitleString ); +}; + +#endif diff --git a/Plugins/PluginPing/Ping.cpp b/Plugins/PluginPing/Ping.cpp index 16f57437..e512877f 100644 --- a/Plugins/PluginPing/Ping.cpp +++ b/Plugins/PluginPing/Ping.cpp @@ -1,234 +1,234 @@ -/* - Copyright (C) 2005 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include <windows.h> -#include <Winsock2.h> -#include <string> -#include <Ipexport.h> -#include <Icmpapi.h> -#include "../../Library/Export.h" // Rainmeter's exported functions - -struct MeasureData -{ - IPAddr destAddr; - DWORD timeout; - double timeoutValue; - DWORD updateRate; - DWORD updateCounter; - bool threadActive; - double value; - std::wstring finishAction; - void* skin; - - MeasureData() : - destAddr(), - timeout(), - timeoutValue(), - updateRate(), - updateCounter(), - threadActive(false), - value(), - finishAction(), - skin(nullptr) - { - } -}; - -static CRITICAL_SECTION g_CriticalSection; - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - switch (fdwReason) - { - case DLL_PROCESS_ATTACH: - InitializeCriticalSection(&g_CriticalSection); - - // Disable DLL_THREAD_ATTACH and DLL_THREAD_DETACH notification calls. - DisableThreadLibraryCalls(hinstDLL); - break; - - case DLL_PROCESS_DETACH: - DeleteCriticalSection(&g_CriticalSection); - break; - } - - return TRUE; -} - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - MeasureData* measure = new MeasureData; - *data = measure; -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - MeasureData* measure = (MeasureData*)data; - - LPCWSTR value = RmReadString(rm, L"DestAddress", L""); - if (*value) - { - int strLen = (int)wcslen(value) + 1; - int bufLen = WideCharToMultiByte(CP_ACP, 0, value, strLen, nullptr, 0, nullptr, nullptr); - if (bufLen > 0) - { - char* buffer = new char[bufLen]; - WideCharToMultiByte(CP_ACP, 0, value, strLen, buffer, bufLen, nullptr, nullptr); - - measure->destAddr = inet_addr(buffer); - if (measure->destAddr == INADDR_NONE) - { - WSADATA wsaData; - if (WSAStartup(0x0101, &wsaData) == 0) - { - LPHOSTENT pHost = gethostbyname(buffer); - if (pHost) - { - measure->destAddr = *(DWORD*)pHost->h_addr; - } - else - { - RmLog(LOG_WARNING, L"PingPlugin.dll: Unable to get host by name"); - } - - WSACleanup(); - } - else - { - RmLog(LOG_WARNING, L"PingPlugin.dll: Unable to start WSA"); - } - } - - delete [] buffer; - } - } - - measure->updateRate = RmReadInt(rm, L"UpdateRate", 32); - measure->timeout = RmReadInt(rm, L"Timeout", 30000); - measure->timeoutValue = RmReadDouble(rm, L"TimeoutValue", 30000.0); - measure->finishAction = RmReadString(rm, L"FinishAction", L"", false); - measure->skin = RmGetSkin(rm); -} - -DWORD WINAPI NetworkThreadProc(void* pParam) -{ - // NOTE: Do not use CRT functions (since thread was created by CreateThread())! - - MeasureData* measure = (MeasureData*)pParam; - const DWORD bufferSize = sizeof(ICMP_ECHO_REPLY) + 32; - BYTE buffer[bufferSize]; - - double value = 0.0; - HANDLE hIcmpFile = IcmpCreateFile(); - if (hIcmpFile != INVALID_HANDLE_VALUE) - { - IcmpSendEcho(hIcmpFile, measure->destAddr, nullptr, 0, nullptr, buffer, bufferSize, measure->timeout); - IcmpCloseHandle(hIcmpFile); - - ICMP_ECHO_REPLY* reply = (ICMP_ECHO_REPLY*)buffer; - value = (reply->Status != IP_SUCCESS) ? measure->timeoutValue : reply->RoundTripTime; - - if (!measure->finishAction.empty()) - { - RmExecute(measure->skin, measure->finishAction.c_str()); - } - } - - HMODULE module = nullptr; - - EnterCriticalSection(&g_CriticalSection); - if (measure->threadActive) - { - measure->value = value; - measure->threadActive = false; - } - else - { - // Thread is not attached to an existing measure any longer, so delete - // unreferenced data. - delete measure; - - DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; - GetModuleHandleEx(flags, (LPCWSTR)DllMain, &module); - } - LeaveCriticalSection(&g_CriticalSection); - - if (module) - { - // Decrement the ref count and possibly unload the module if this is - // the last instance. - FreeLibraryAndExitThread(module, 0); - } - - return 0; -} - -PLUGIN_EXPORT double Update(void* data) -{ - MeasureData* measure = (MeasureData*)data; - - EnterCriticalSection(&g_CriticalSection); - if (!measure->threadActive) - { - if (measure->updateCounter == 0) - { - // Launch a new thread to fetch the web data - DWORD id; - HANDLE thread = CreateThread(nullptr, 0, NetworkThreadProc, measure, 0, &id); - if (thread) - { - CloseHandle(thread); - measure->threadActive = true; - } - } - - measure->updateCounter++; - if (measure->updateCounter >= measure->updateRate) - { - measure->updateCounter = 0; - } - } - - double value = measure->value; - LeaveCriticalSection(&g_CriticalSection); - - return value; -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - MeasureData* measure = (MeasureData*)data; - - EnterCriticalSection(&g_CriticalSection); - if (measure->threadActive) - { - // Increment ref count of this module so that it will not be unloaded prior to - // thread completion. - DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS; - HMODULE module; - GetModuleHandleEx(flags, (LPCWSTR)DllMain, &module); - - // Thread will perform cleanup. - measure->threadActive = false; - } - else - { - delete measure; - } - LeaveCriticalSection(&g_CriticalSection); -} +/* + Copyright (C) 2005 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <windows.h> +#include <Winsock2.h> +#include <string> +#include <Ipexport.h> +#include <Icmpapi.h> +#include "../../Library/Export.h" // Rainmeter's exported functions + +struct MeasureData +{ + IPAddr destAddr; + DWORD timeout; + double timeoutValue; + DWORD updateRate; + DWORD updateCounter; + bool threadActive; + double value; + std::wstring finishAction; + void* skin; + + MeasureData() : + destAddr(), + timeout(), + timeoutValue(), + updateRate(), + updateCounter(), + threadActive(false), + value(), + finishAction(), + skin(nullptr) + { + } +}; + +static CRITICAL_SECTION g_CriticalSection; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + InitializeCriticalSection(&g_CriticalSection); + + // Disable DLL_THREAD_ATTACH and DLL_THREAD_DETACH notification calls. + DisableThreadLibraryCalls(hinstDLL); + break; + + case DLL_PROCESS_DETACH: + DeleteCriticalSection(&g_CriticalSection); + break; + } + + return TRUE; +} + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + MeasureData* measure = new MeasureData; + *data = measure; +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + MeasureData* measure = (MeasureData*)data; + + LPCWSTR value = RmReadString(rm, L"DestAddress", L""); + if (*value) + { + int strLen = (int)wcslen(value) + 1; + int bufLen = WideCharToMultiByte(CP_ACP, 0, value, strLen, nullptr, 0, nullptr, nullptr); + if (bufLen > 0) + { + char* buffer = new char[bufLen]; + WideCharToMultiByte(CP_ACP, 0, value, strLen, buffer, bufLen, nullptr, nullptr); + + measure->destAddr = inet_addr(buffer); + if (measure->destAddr == INADDR_NONE) + { + WSADATA wsaData; + if (WSAStartup(0x0101, &wsaData) == 0) + { + LPHOSTENT pHost = gethostbyname(buffer); + if (pHost) + { + measure->destAddr = *(DWORD*)pHost->h_addr; + } + else + { + RmLog(LOG_WARNING, L"PingPlugin.dll: Unable to get host by name"); + } + + WSACleanup(); + } + else + { + RmLog(LOG_WARNING, L"PingPlugin.dll: Unable to start WSA"); + } + } + + delete [] buffer; + } + } + + measure->updateRate = RmReadInt(rm, L"UpdateRate", 32); + measure->timeout = RmReadInt(rm, L"Timeout", 30000); + measure->timeoutValue = RmReadDouble(rm, L"TimeoutValue", 30000.0); + measure->finishAction = RmReadString(rm, L"FinishAction", L"", false); + measure->skin = RmGetSkin(rm); +} + +DWORD WINAPI NetworkThreadProc(void* pParam) +{ + // NOTE: Do not use CRT functions (since thread was created by CreateThread())! + + MeasureData* measure = (MeasureData*)pParam; + const DWORD bufferSize = sizeof(ICMP_ECHO_REPLY) + 32; + BYTE buffer[bufferSize]; + + double value = 0.0; + HANDLE hIcmpFile = IcmpCreateFile(); + if (hIcmpFile != INVALID_HANDLE_VALUE) + { + IcmpSendEcho(hIcmpFile, measure->destAddr, nullptr, 0, nullptr, buffer, bufferSize, measure->timeout); + IcmpCloseHandle(hIcmpFile); + + ICMP_ECHO_REPLY* reply = (ICMP_ECHO_REPLY*)buffer; + value = (reply->Status != IP_SUCCESS) ? measure->timeoutValue : reply->RoundTripTime; + + if (!measure->finishAction.empty()) + { + RmExecute(measure->skin, measure->finishAction.c_str()); + } + } + + HMODULE module = nullptr; + + EnterCriticalSection(&g_CriticalSection); + if (measure->threadActive) + { + measure->value = value; + measure->threadActive = false; + } + else + { + // Thread is not attached to an existing measure any longer, so delete + // unreferenced data. + delete measure; + + DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; + GetModuleHandleEx(flags, (LPCWSTR)DllMain, &module); + } + LeaveCriticalSection(&g_CriticalSection); + + if (module) + { + // Decrement the ref count and possibly unload the module if this is + // the last instance. + FreeLibraryAndExitThread(module, 0); + } + + return 0; +} + +PLUGIN_EXPORT double Update(void* data) +{ + MeasureData* measure = (MeasureData*)data; + + EnterCriticalSection(&g_CriticalSection); + if (!measure->threadActive) + { + if (measure->updateCounter == 0) + { + // Launch a new thread to fetch the web data + DWORD id; + HANDLE thread = CreateThread(nullptr, 0, NetworkThreadProc, measure, 0, &id); + if (thread) + { + CloseHandle(thread); + measure->threadActive = true; + } + } + + measure->updateCounter++; + if (measure->updateCounter >= measure->updateRate) + { + measure->updateCounter = 0; + } + } + + double value = measure->value; + LeaveCriticalSection(&g_CriticalSection); + + return value; +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + MeasureData* measure = (MeasureData*)data; + + EnterCriticalSection(&g_CriticalSection); + if (measure->threadActive) + { + // Increment ref count of this module so that it will not be unloaded prior to + // thread completion. + DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS; + HMODULE module; + GetModuleHandleEx(flags, (LPCWSTR)DllMain, &module); + + // Thread will perform cleanup. + measure->threadActive = false; + } + else + { + delete measure; + } + LeaveCriticalSection(&g_CriticalSection); +} diff --git a/Plugins/PluginPing/PluginPing.rc b/Plugins/PluginPing/PluginPing.rc index b07006e9..406f5c9e 100644 --- a/Plugins/PluginPing/PluginPing.rc +++ b/Plugins/PluginPing/PluginPing.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,2,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.2.0.0" - VALUE "LegalCopyright", " 2010 - Rainy" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,2,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.2.0.0" + VALUE "LegalCopyright", " 2010 - Rainy" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginPing/PluginPing.vcxproj b/Plugins/PluginPing/PluginPing.vcxproj index 39bc42a8..862553e9 100644 --- a/Plugins/PluginPing/PluginPing.vcxproj +++ b/Plugins/PluginPing/PluginPing.vcxproj @@ -1,36 +1,36 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{C862B662-5CC6-4E79-B1B3-905E0B98D627}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>PingPlugin</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <PreprocessorDefinitions>_USRDLL;PluginPing_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - <AdditionalDependencies>Ws2_32.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClCompile Include="Ping.cpp" /> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="PluginPing.rc" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{C862B662-5CC6-4E79-B1B3-905E0B98D627}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>PingPlugin</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <PreprocessorDefinitions>_USRDLL;PluginPing_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <AdditionalDependencies>Ws2_32.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="Ping.cpp" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="PluginPing.rc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginPower/PluginPower.rc b/Plugins/PluginPower/PluginPower.rc index 0fdff9df..3e4b0c16 100644 --- a/Plugins/PluginPower/PluginPower.rc +++ b/Plugins/PluginPower/PluginPower.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,4,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.4.0.0" - VALUE "LegalCopyright", " 2010 - Rainy" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,4,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.4.0.0" + VALUE "LegalCopyright", " 2010 - Rainy" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginPower/PluginPower.vcxproj b/Plugins/PluginPower/PluginPower.vcxproj index fe6a90ea..77fb4241 100644 --- a/Plugins/PluginPower/PluginPower.vcxproj +++ b/Plugins/PluginPower/PluginPower.vcxproj @@ -1,37 +1,37 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>PowerPlugin</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - <AdditionalDependencies>PowrProf.lib;%(AdditionalDependencies)</AdditionalDependencies> - <DelayLoadDLLs>PowrProf.dll</DelayLoadDLLs> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ResourceCompile Include="PluginPower.rc" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="PowerPlugin.cpp" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>PowerPlugin</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <AdditionalDependencies>PowrProf.lib;%(AdditionalDependencies)</AdditionalDependencies> + <DelayLoadDLLs>PowrProf.dll</DelayLoadDLLs> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ResourceCompile Include="PluginPower.rc" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="PowerPlugin.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginPower/PowerPlugin.cpp b/Plugins/PluginPower/PowerPlugin.cpp index cce3b956..0a8a657c 100644 --- a/Plugins/PluginPower/PowerPlugin.cpp +++ b/Plugins/PluginPower/PowerPlugin.cpp @@ -1,233 +1,233 @@ -/* - Copyright (C) 2002 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include <windows.h> -#include <Powrprof.h> -#include <time.h> -#include <errno.h> -#include <crtdbg.h> -#include <stdlib.h> -#include "../../Common/RawString.h" -#include "../../Library/Export.h" // Rainmeter's exported functions - -typedef struct _PROCESSOR_POWER_INFORMATION -{ - ULONG Number; - ULONG MaxMhz; - ULONG CurrentMhz; - ULONG MhzLimit; - ULONG MaxIdleState; - ULONG CurrentIdleState; -} PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION; - -enum MeasureType -{ - POWER_UNKNOWN, - POWER_ACLINE, - POWER_STATUS, - POWER_STATUS2, - POWER_LIFETIME, - POWER_PERCENT, - POWER_MHZ, - POWER_HZ -}; - -struct MeasureData -{ - MeasureType type; - RawString format; - - MeasureData() : type(POWER_UNKNOWN) {} -}; - -UINT g_NumOfProcessors = 0; - -void NullCRTInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved) -{ - // Do nothing. -} - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - MeasureData* measure = new MeasureData; - *data = measure; - - if (!g_NumOfProcessors) - { - SYSTEM_INFO si; - GetSystemInfo(&si); - g_NumOfProcessors = (UINT)si.dwNumberOfProcessors; - } -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - MeasureData* measure = (MeasureData*)data; - - LPCWSTR value = RmReadString(rm, L"PowerState", L""); - if (_wcsicmp(L"ACLINE", value) == 0) - { - measure->type = POWER_ACLINE; - *maxValue = 1.0; - } - else if (_wcsicmp(L"STATUS", value) == 0) - { - measure->type = POWER_STATUS; - *maxValue = 4.0; - } - else if (_wcsicmp(L"STATUS2", value) == 0) - { - measure->type = POWER_STATUS2; - *maxValue = 255.0; - } - else if (_wcsicmp(L"LIFETIME", value) == 0) - { - measure->type= POWER_LIFETIME; - - value = RmReadString(rm, L"Format", L"%H:%M"); - measure->format = value; - - SYSTEM_POWER_STATUS sps; - if (GetSystemPowerStatus(&sps)) - { - *maxValue = sps.BatteryFullLifeTime; - } - } - else if (_wcsicmp(L"MHZ", value) == 0) - { - measure->type = POWER_MHZ; - } - else if (_wcsicmp(L"HZ", value) == 0) - { - measure->type = POWER_HZ; - } - else if (_wcsicmp(L"PERCENT", value) == 0) - { - measure->type = POWER_PERCENT; - *maxValue = 100.0; - } -} - -PLUGIN_EXPORT double Update(void* data) -{ - MeasureData* measure = (MeasureData*)data; - - SYSTEM_POWER_STATUS sps; - if (GetSystemPowerStatus(&sps)) - { - switch (measure->type) - { - case POWER_ACLINE: - return sps.ACLineStatus == 1 ? 1.0 : 0.0; - - case POWER_STATUS: - if (sps.BatteryFlag & 128) - { - return 0.0; // No battery - } - else if (sps.BatteryFlag & 8) - { - return 1.0; // Charging - } - else if (sps.BatteryFlag & 4) - { - return 2.0; // Critical - } - else if (sps.BatteryFlag & 2) - { - return 3.0; // Low - } - else if (sps.BatteryFlag == 0 || sps.BatteryFlag & 1) - { - return 4.0; // Medium/High - } - break; - - case POWER_STATUS2: - return sps.BatteryFlag; - - case POWER_LIFETIME: - return sps.BatteryLifeTime; - - case POWER_PERCENT: - return sps.BatteryLifePercent == 255 ? 100.0 : sps.BatteryLifePercent; - - case POWER_MHZ: - case POWER_HZ: - if (g_NumOfProcessors > 0) - { - PROCESSOR_POWER_INFORMATION* ppi = new PROCESSOR_POWER_INFORMATION[g_NumOfProcessors]; - memset(ppi, 0, sizeof(PROCESSOR_POWER_INFORMATION) * g_NumOfProcessors); - CallNtPowerInformation(ProcessorInformation, nullptr, 0, ppi, sizeof(PROCESSOR_POWER_INFORMATION) * g_NumOfProcessors); - double value = (measure->type == POWER_MHZ) ? ppi[0].CurrentMhz : ppi[0].CurrentMhz * 1000000.0; - delete [] ppi; - return value; - } - } - } - - return 0.0; -} - -PLUGIN_EXPORT LPCWSTR GetString(void* data) -{ - static WCHAR buffer[128]; - MeasureData* measure = (MeasureData*)data; - - if (measure->type == POWER_LIFETIME) - { - SYSTEM_POWER_STATUS sps; - if (GetSystemPowerStatus(&sps)) - { - // Change it to time string - if (sps.BatteryLifeTime == -1) - { - return L"Unknown"; - } - else - { - tm time = {0}; - time.tm_sec = sps.BatteryLifeTime % 60; - time.tm_min = (sps.BatteryLifeTime / 60) % 60; - time.tm_hour = sps.BatteryLifeTime / 60 / 60; - - _invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(NullCRTInvalidParameterHandler); - _CrtSetReportMode(_CRT_ASSERT, 0); - - errno = 0; - wcsftime(buffer, 128, measure->format.c_str(), &time); - if (errno == EINVAL) - { - buffer[0] = L'\0'; - } - - _set_invalid_parameter_handler(oldHandler); - - return buffer; - } - } - } - - return nullptr; -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - MeasureData* measure = (MeasureData*)data; - delete measure; -} +/* + Copyright (C) 2002 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <windows.h> +#include <Powrprof.h> +#include <time.h> +#include <errno.h> +#include <crtdbg.h> +#include <stdlib.h> +#include "../../Common/RawString.h" +#include "../../Library/Export.h" // Rainmeter's exported functions + +typedef struct _PROCESSOR_POWER_INFORMATION +{ + ULONG Number; + ULONG MaxMhz; + ULONG CurrentMhz; + ULONG MhzLimit; + ULONG MaxIdleState; + ULONG CurrentIdleState; +} PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION; + +enum MeasureType +{ + POWER_UNKNOWN, + POWER_ACLINE, + POWER_STATUS, + POWER_STATUS2, + POWER_LIFETIME, + POWER_PERCENT, + POWER_MHZ, + POWER_HZ +}; + +struct MeasureData +{ + MeasureType type; + RawString format; + + MeasureData() : type(POWER_UNKNOWN) {} +}; + +UINT g_NumOfProcessors = 0; + +void NullCRTInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved) +{ + // Do nothing. +} + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + MeasureData* measure = new MeasureData; + *data = measure; + + if (!g_NumOfProcessors) + { + SYSTEM_INFO si; + GetSystemInfo(&si); + g_NumOfProcessors = (UINT)si.dwNumberOfProcessors; + } +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + MeasureData* measure = (MeasureData*)data; + + LPCWSTR value = RmReadString(rm, L"PowerState", L""); + if (_wcsicmp(L"ACLINE", value) == 0) + { + measure->type = POWER_ACLINE; + *maxValue = 1.0; + } + else if (_wcsicmp(L"STATUS", value) == 0) + { + measure->type = POWER_STATUS; + *maxValue = 4.0; + } + else if (_wcsicmp(L"STATUS2", value) == 0) + { + measure->type = POWER_STATUS2; + *maxValue = 255.0; + } + else if (_wcsicmp(L"LIFETIME", value) == 0) + { + measure->type= POWER_LIFETIME; + + value = RmReadString(rm, L"Format", L"%H:%M"); + measure->format = value; + + SYSTEM_POWER_STATUS sps; + if (GetSystemPowerStatus(&sps)) + { + *maxValue = sps.BatteryFullLifeTime; + } + } + else if (_wcsicmp(L"MHZ", value) == 0) + { + measure->type = POWER_MHZ; + } + else if (_wcsicmp(L"HZ", value) == 0) + { + measure->type = POWER_HZ; + } + else if (_wcsicmp(L"PERCENT", value) == 0) + { + measure->type = POWER_PERCENT; + *maxValue = 100.0; + } +} + +PLUGIN_EXPORT double Update(void* data) +{ + MeasureData* measure = (MeasureData*)data; + + SYSTEM_POWER_STATUS sps; + if (GetSystemPowerStatus(&sps)) + { + switch (measure->type) + { + case POWER_ACLINE: + return sps.ACLineStatus == 1 ? 1.0 : 0.0; + + case POWER_STATUS: + if (sps.BatteryFlag & 128) + { + return 0.0; // No battery + } + else if (sps.BatteryFlag & 8) + { + return 1.0; // Charging + } + else if (sps.BatteryFlag & 4) + { + return 2.0; // Critical + } + else if (sps.BatteryFlag & 2) + { + return 3.0; // Low + } + else if (sps.BatteryFlag == 0 || sps.BatteryFlag & 1) + { + return 4.0; // Medium/High + } + break; + + case POWER_STATUS2: + return sps.BatteryFlag; + + case POWER_LIFETIME: + return sps.BatteryLifeTime; + + case POWER_PERCENT: + return sps.BatteryLifePercent == 255 ? 100.0 : sps.BatteryLifePercent; + + case POWER_MHZ: + case POWER_HZ: + if (g_NumOfProcessors > 0) + { + PROCESSOR_POWER_INFORMATION* ppi = new PROCESSOR_POWER_INFORMATION[g_NumOfProcessors]; + memset(ppi, 0, sizeof(PROCESSOR_POWER_INFORMATION) * g_NumOfProcessors); + CallNtPowerInformation(ProcessorInformation, nullptr, 0, ppi, sizeof(PROCESSOR_POWER_INFORMATION) * g_NumOfProcessors); + double value = (measure->type == POWER_MHZ) ? ppi[0].CurrentMhz : ppi[0].CurrentMhz * 1000000.0; + delete [] ppi; + return value; + } + } + } + + return 0.0; +} + +PLUGIN_EXPORT LPCWSTR GetString(void* data) +{ + static WCHAR buffer[128]; + MeasureData* measure = (MeasureData*)data; + + if (measure->type == POWER_LIFETIME) + { + SYSTEM_POWER_STATUS sps; + if (GetSystemPowerStatus(&sps)) + { + // Change it to time string + if (sps.BatteryLifeTime == -1) + { + return L"Unknown"; + } + else + { + tm time = {0}; + time.tm_sec = sps.BatteryLifeTime % 60; + time.tm_min = (sps.BatteryLifeTime / 60) % 60; + time.tm_hour = sps.BatteryLifeTime / 60 / 60; + + _invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(NullCRTInvalidParameterHandler); + _CrtSetReportMode(_CRT_ASSERT, 0); + + errno = 0; + wcsftime(buffer, 128, measure->format.c_str(), &time); + if (errno == EINVAL) + { + buffer[0] = L'\0'; + } + + _set_invalid_parameter_handler(oldHandler); + + return buffer; + } + } + } + + return nullptr; +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + MeasureData* measure = (MeasureData*)data; + delete measure; +} diff --git a/Plugins/PluginProcess/PluginProcess.cpp b/Plugins/PluginProcess/PluginProcess.cpp index 3059d4a5..75668e6a 100644 --- a/Plugins/PluginProcess/PluginProcess.cpp +++ b/Plugins/PluginProcess/PluginProcess.cpp @@ -1,109 +1,109 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include <windows.h> -#include <TlHelp32.h> -#include <algorithm> -#include <vector> -#include "../../Common/RawString.h" -#include "../../Library/Export.h" // Rainmeter's exported functions - -struct MeasureData -{ - RawString processName; - bool isRunning; - - MeasureData() : isRunning(false) {} -}; - -static UINT g_UpdateCount = 0; -static std::vector<MeasureData*> g_Measures; - -void CheckProcesses(); - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - MeasureData* measure = new MeasureData; - g_Measures.push_back(measure); - - *data = measure; -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - MeasureData* measure = (MeasureData*)data; - - LPCWSTR value = RmReadString(rm, L"ProcessName", L""); - measure->processName = value; -} - -PLUGIN_EXPORT double Update(void* data) -{ - MeasureData* measure = (MeasureData*)data; - - // Updates the measure only once per combined updates of all measures - ++g_UpdateCount; - if (g_UpdateCount >= g_Measures.size()) - { - CheckProcesses(); - g_UpdateCount = 0; - } - - return measure->isRunning ? 1.0 : -1.0; -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - MeasureData* measure = (MeasureData*)data; - std::vector<MeasureData*>::iterator iter = std::find(g_Measures.begin(), g_Measures.end(), measure); - g_Measures.erase(iter); - - delete measure; -} - -void CheckProcesses() -{ - // Set everything to false - std::vector<MeasureData*>::iterator iter = g_Measures.begin(); - for ( ; iter != g_Measures.end(); ++iter) - { - (*iter)->isRunning = false; - } - - HANDLE thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (thSnapshot != INVALID_HANDLE_VALUE) - { - PROCESSENTRY32 processEntry = {sizeof(processEntry)}; - if (Process32First(thSnapshot, &processEntry)) - { - do - { - for (MeasureData* data : g_Measures) - { - if (_wcsicmp(processEntry.szExeFile, data->processName.c_str()) == 0) - { - data->isRunning = true; - } - } - } - while (Process32Next(thSnapshot, &processEntry)); - } - - CloseHandle(thSnapshot); - } -} +/* + Copyright (C) 2011 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <windows.h> +#include <TlHelp32.h> +#include <algorithm> +#include <vector> +#include "../../Common/RawString.h" +#include "../../Library/Export.h" // Rainmeter's exported functions + +struct MeasureData +{ + RawString processName; + bool isRunning; + + MeasureData() : isRunning(false) {} +}; + +static UINT g_UpdateCount = 0; +static std::vector<MeasureData*> g_Measures; + +void CheckProcesses(); + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + MeasureData* measure = new MeasureData; + g_Measures.push_back(measure); + + *data = measure; +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + MeasureData* measure = (MeasureData*)data; + + LPCWSTR value = RmReadString(rm, L"ProcessName", L""); + measure->processName = value; +} + +PLUGIN_EXPORT double Update(void* data) +{ + MeasureData* measure = (MeasureData*)data; + + // Updates the measure only once per combined updates of all measures + ++g_UpdateCount; + if (g_UpdateCount >= g_Measures.size()) + { + CheckProcesses(); + g_UpdateCount = 0; + } + + return measure->isRunning ? 1.0 : -1.0; +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + MeasureData* measure = (MeasureData*)data; + std::vector<MeasureData*>::iterator iter = std::find(g_Measures.begin(), g_Measures.end(), measure); + g_Measures.erase(iter); + + delete measure; +} + +void CheckProcesses() +{ + // Set everything to false + std::vector<MeasureData*>::iterator iter = g_Measures.begin(); + for ( ; iter != g_Measures.end(); ++iter) + { + (*iter)->isRunning = false; + } + + HANDLE thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (thSnapshot != INVALID_HANDLE_VALUE) + { + PROCESSENTRY32 processEntry = {sizeof(processEntry)}; + if (Process32First(thSnapshot, &processEntry)) + { + do + { + for (MeasureData* data : g_Measures) + { + if (_wcsicmp(processEntry.szExeFile, data->processName.c_str()) == 0) + { + data->isRunning = true; + } + } + } + while (Process32Next(thSnapshot, &processEntry)); + } + + CloseHandle(thSnapshot); + } +} diff --git a/Plugins/PluginProcess/PluginProcess.rc b/Plugins/PluginProcess/PluginProcess.rc index f6bf6716..12114a60 100644 --- a/Plugins/PluginProcess/PluginProcess.rc +++ b/Plugins/PluginProcess/PluginProcess.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.0.0.0" - VALUE "LegalCopyright", " 2011 - Birunthan Mohanathas" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.0.0.0" + VALUE "LegalCopyright", " 2011 - Birunthan Mohanathas" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginProcess/PluginProcess.vcxproj b/Plugins/PluginProcess/PluginProcess.vcxproj index 4b27efd8..c3d7115b 100644 --- a/Plugins/PluginProcess/PluginProcess.vcxproj +++ b/Plugins/PluginProcess/PluginProcess.vcxproj @@ -1,36 +1,36 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{05203741-CD80-4060-8218-EC5D1120FE3E}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>Process</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - <AdditionalDependencies>Psapi.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ResourceCompile Include="PluginProcess.rc" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="PluginProcess.cpp" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{05203741-CD80-4060-8218-EC5D1120FE3E}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>Process</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <AdditionalDependencies>Psapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ResourceCompile Include="PluginProcess.rc" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="PluginProcess.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginQuote/PluginQuote.rc b/Plugins/PluginQuote/PluginQuote.rc index ee2ccd61..e2e5c01d 100644 --- a/Plugins/PluginQuote/PluginQuote.rc +++ b/Plugins/PluginQuote/PluginQuote.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,1,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.1.0.0" - VALUE "LegalCopyright", " 2010 - Rainy" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,1,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.1.0.0" + VALUE "LegalCopyright", " 2010 - Rainy" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginQuote/PluginQuote.vcxproj b/Plugins/PluginQuote/PluginQuote.vcxproj index 1adce0cb..4b4e8627 100644 --- a/Plugins/PluginQuote/PluginQuote.vcxproj +++ b/Plugins/PluginQuote/PluginQuote.vcxproj @@ -1,40 +1,40 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>QuotePlugin</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ResourceCompile Include="PluginQuote.rc" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="..\..\Common\StringUtil.cpp" /> - <ClCompile Include="Quote.cpp" /> - </ItemGroup> - <ItemGroup> - <ClInclude Include="..\..\Common\StringUtil.h" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>QuotePlugin</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ResourceCompile Include="PluginQuote.rc" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\..\Common\StringUtil.cpp" /> + <ClCompile Include="Quote.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\..\Common\StringUtil.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginQuote/Quote.cpp b/Plugins/PluginQuote/Quote.cpp index f8963bde..b21a7b24 100644 --- a/Plugins/PluginQuote/Quote.cpp +++ b/Plugins/PluginQuote/Quote.cpp @@ -1,329 +1,329 @@ -/* - Copyright (C) 2005 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include <windows.h> -#include <string> -#include <vector> -#include <time.h> -#include <shlwapi.h> -#include "../API/RainmeterAPI.h" -#include "../../Common/StringUtil.h" - -#define BUFFER_SIZE 4096 - -struct MeasureData -{ - std::wstring pathname; - std::wstring separator; - std::vector<std::wstring> files; - std::wstring value; -}; - -void ScanFolder(std::vector<std::wstring>& files, std::vector<std::wstring>& filters, bool bSubfolders, const std::wstring& path) -{ - // Get folder listing - WIN32_FIND_DATA fileData; // Data structure describes the file found - HANDLE hSearch; // Search handle returned by FindFirstFile - - std::wstring searchPath = path + L"*"; - - hSearch = FindFirstFile(searchPath.c_str(), &fileData); - if (hSearch == INVALID_HANDLE_VALUE) return; // No more files found - - do - { - if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - if (bSubfolders && - wcscmp(fileData.cFileName, L".") != 0 && - wcscmp(fileData.cFileName, L"..") != 0) - { - ScanFolder(files, filters, bSubfolders, path + fileData.cFileName + L"\\"); - } - } - else - { - if (!filters.empty()) - { - for (size_t i = 0; i < filters.size(); ++i) - { - if (!filters[i].empty() && PathMatchSpec(fileData.cFileName, filters[i].c_str())) - { - files.push_back(path + fileData.cFileName); - break; - } - } - } - else - { - files.push_back(path + fileData.cFileName); - } - } - } - while (FindNextFile(hSearch, &fileData)); - - FindClose(hSearch); -} - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - MeasureData* measure = new MeasureData; - *data = measure; -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - MeasureData* measure = (MeasureData*)data; - - measure->pathname = RmReadPath(rm, L"PathName", L""); - - if (PathIsDirectory(measure->pathname.c_str())) - { - std::vector<std::wstring> fileFilters; - LPCWSTR filter = RmReadString(rm, L"FileFilter", L""); - if (*filter) - { - std::wstring ext = filter; - - size_t start = 0; - size_t pos = ext.find(L';'); - while (pos != std::wstring::npos) - { - fileFilters.push_back(ext.substr(start, pos - start)); - start = pos + 1; - pos = ext.find(L';', pos + 1); - } - fileFilters.push_back(ext.substr(start)); - } - - if (measure->pathname[measure->pathname.size() - 1] != L'\\') - { - measure->pathname += L"\\"; - } - - // Scan files - measure->files.clear(); - bool bSubfolders = RmReadInt(rm, L"Subfolders", 1) == 1; - ScanFolder(measure->files, fileFilters, bSubfolders, measure->pathname); - } - else - { - measure->separator = RmReadString(rm, L"Separator", L"\n"); - } - - srand((unsigned)time(nullptr)); -} - -PLUGIN_EXPORT double Update(void* data) -{ - MeasureData* measure = (MeasureData*)data; - - if (measure->files.empty()) - { - BYTE buffer[BUFFER_SIZE + 2]; - buffer[BUFFER_SIZE] = 0; - - // Read the file - FILE* file = _wfopen(measure->pathname.c_str(), L"r"); - if (file) - { - // Check if the file is unicode or ascii - fread(buffer, sizeof(WCHAR), 1, file); - - fseek(file, 0, SEEK_END); - long size = ftell(file); - - if (size > 0) - { - // Go to a random place - int pos = rand() % size; - fseek(file, (pos / 2) * 2, SEEK_SET); - - measure->value.clear(); - - if (0xFEFF == *(WCHAR*)buffer) - { - // It's unicode - WCHAR* wBuffer = (WCHAR*)buffer; - - // Read until we find the first separator - WCHAR* sepPos1 = nullptr; - WCHAR* sepPos2 = nullptr; - do - { - size_t len = fread(buffer, sizeof(BYTE), BUFFER_SIZE, file); - buffer[len] = 0; - buffer[len + 1] = 0; - - sepPos1 = wcsstr(wBuffer, measure->separator.c_str()); - if (sepPos1 == nullptr) - { - // The separator wasn't found - if (feof(file)) - { - // End of file reached -> read from start - fseek(file, 2, SEEK_SET); - len = fread(buffer, sizeof(BYTE), BUFFER_SIZE, file); - buffer[len] = 0; - buffer[len + 1] = 0; - sepPos1 = wBuffer; - } - // else continue reading - } - else - { - sepPos1 += measure->separator.size(); - } - } - while (sepPos1 == nullptr); - - // Find the second separator - do - { - sepPos2 = wcsstr(sepPos1, measure->separator.c_str()); - if (sepPos2 == nullptr) - { - // The separator wasn't found - if (feof(file)) - { - // End of file reached -> read the rest - measure->value += sepPos1; - break; - } - else - { - measure->value += sepPos1; - - // else continue reading - size_t len = fread(buffer, sizeof(BYTE), BUFFER_SIZE, file); - buffer[len] = 0; - buffer[len + 1] = 0; - sepPos1 = wBuffer; - } - } - else - { - if (sepPos2) - { - *sepPos2 = 0; - } - - // Read until we find the second separator - measure->value += sepPos1; - } - } - while (sepPos2 == nullptr); - } - else - { - // It's ascii - char* aBuffer = (char*)buffer; - - const std::string separator = StringUtil::Narrow(measure->separator); - const char* separatorSz = separator.c_str(); - - // Read until we find the first separator - char* sepPos1 = nullptr; - char* sepPos2 = nullptr; - do - { - size_t len = fread(buffer, sizeof(char), BUFFER_SIZE, file); - aBuffer[len] = 0; - - sepPos1 = strstr(aBuffer, separatorSz); - if (sepPos1 == nullptr) - { - // The separator wasn't found - if (feof(file)) - { - // End of file reached -> read from start - fseek(file, 0, SEEK_SET); - len = fread(buffer, sizeof(char), BUFFER_SIZE, file); - aBuffer[len] = 0; - sepPos1 = aBuffer; - } - // else continue reading - } - else - { - sepPos1 += separator.size(); - } - } - while (sepPos1 == nullptr); - - // Find the second separator - do - { - sepPos2 = strstr(sepPos1, separatorSz); - if (sepPos2 == nullptr) - { - // The separator wasn't found - if (feof(file)) - { - // End of file reached -> read the rest - measure->value += StringUtil::Widen(sepPos1); - break; - } - else - { - measure->value += StringUtil::Widen(sepPos1); - - // else continue reading - size_t len = fread(buffer, sizeof(char), BUFFER_SIZE, file); - aBuffer[len] = 0; - sepPos1 = aBuffer; - } - } - else - { - if (sepPos2) - { - *sepPos2 = 0; - } - - // Read until we find the second separator - measure->value += StringUtil::Widen(sepPos1); - } - } - while (sepPos2 == nullptr); - } - } - - fclose(file); - } - } - else - { - // Select the filename - measure->value = measure->files[rand() % measure->files.size()]; - } - - return 0; -} - -PLUGIN_EXPORT LPCWSTR GetString(void* data) -{ - MeasureData* measure = (MeasureData*)data; - return measure->value.c_str(); -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - MeasureData* measure = (MeasureData*)data; - delete measure; +/* + Copyright (C) 2005 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <windows.h> +#include <string> +#include <vector> +#include <time.h> +#include <shlwapi.h> +#include "../API/RainmeterAPI.h" +#include "../../Common/StringUtil.h" + +#define BUFFER_SIZE 4096 + +struct MeasureData +{ + std::wstring pathname; + std::wstring separator; + std::vector<std::wstring> files; + std::wstring value; +}; + +void ScanFolder(std::vector<std::wstring>& files, std::vector<std::wstring>& filters, bool bSubfolders, const std::wstring& path) +{ + // Get folder listing + WIN32_FIND_DATA fileData; // Data structure describes the file found + HANDLE hSearch; // Search handle returned by FindFirstFile + + std::wstring searchPath = path + L"*"; + + hSearch = FindFirstFile(searchPath.c_str(), &fileData); + if (hSearch == INVALID_HANDLE_VALUE) return; // No more files found + + do + { + if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (bSubfolders && + wcscmp(fileData.cFileName, L".") != 0 && + wcscmp(fileData.cFileName, L"..") != 0) + { + ScanFolder(files, filters, bSubfolders, path + fileData.cFileName + L"\\"); + } + } + else + { + if (!filters.empty()) + { + for (size_t i = 0; i < filters.size(); ++i) + { + if (!filters[i].empty() && PathMatchSpec(fileData.cFileName, filters[i].c_str())) + { + files.push_back(path + fileData.cFileName); + break; + } + } + } + else + { + files.push_back(path + fileData.cFileName); + } + } + } + while (FindNextFile(hSearch, &fileData)); + + FindClose(hSearch); +} + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + MeasureData* measure = new MeasureData; + *data = measure; +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + MeasureData* measure = (MeasureData*)data; + + measure->pathname = RmReadPath(rm, L"PathName", L""); + + if (PathIsDirectory(measure->pathname.c_str())) + { + std::vector<std::wstring> fileFilters; + LPCWSTR filter = RmReadString(rm, L"FileFilter", L""); + if (*filter) + { + std::wstring ext = filter; + + size_t start = 0; + size_t pos = ext.find(L';'); + while (pos != std::wstring::npos) + { + fileFilters.push_back(ext.substr(start, pos - start)); + start = pos + 1; + pos = ext.find(L';', pos + 1); + } + fileFilters.push_back(ext.substr(start)); + } + + if (measure->pathname[measure->pathname.size() - 1] != L'\\') + { + measure->pathname += L"\\"; + } + + // Scan files + measure->files.clear(); + bool bSubfolders = RmReadInt(rm, L"Subfolders", 1) == 1; + ScanFolder(measure->files, fileFilters, bSubfolders, measure->pathname); + } + else + { + measure->separator = RmReadString(rm, L"Separator", L"\n"); + } + + srand((unsigned)time(nullptr)); +} + +PLUGIN_EXPORT double Update(void* data) +{ + MeasureData* measure = (MeasureData*)data; + + if (measure->files.empty()) + { + BYTE buffer[BUFFER_SIZE + 2]; + buffer[BUFFER_SIZE] = 0; + + // Read the file + FILE* file = _wfopen(measure->pathname.c_str(), L"r"); + if (file) + { + // Check if the file is unicode or ascii + fread(buffer, sizeof(WCHAR), 1, file); + + fseek(file, 0, SEEK_END); + long size = ftell(file); + + if (size > 0) + { + // Go to a random place + int pos = rand() % size; + fseek(file, (pos / 2) * 2, SEEK_SET); + + measure->value.clear(); + + if (0xFEFF == *(WCHAR*)buffer) + { + // It's unicode + WCHAR* wBuffer = (WCHAR*)buffer; + + // Read until we find the first separator + WCHAR* sepPos1 = nullptr; + WCHAR* sepPos2 = nullptr; + do + { + size_t len = fread(buffer, sizeof(BYTE), BUFFER_SIZE, file); + buffer[len] = 0; + buffer[len + 1] = 0; + + sepPos1 = wcsstr(wBuffer, measure->separator.c_str()); + if (sepPos1 == nullptr) + { + // The separator wasn't found + if (feof(file)) + { + // End of file reached -> read from start + fseek(file, 2, SEEK_SET); + len = fread(buffer, sizeof(BYTE), BUFFER_SIZE, file); + buffer[len] = 0; + buffer[len + 1] = 0; + sepPos1 = wBuffer; + } + // else continue reading + } + else + { + sepPos1 += measure->separator.size(); + } + } + while (sepPos1 == nullptr); + + // Find the second separator + do + { + sepPos2 = wcsstr(sepPos1, measure->separator.c_str()); + if (sepPos2 == nullptr) + { + // The separator wasn't found + if (feof(file)) + { + // End of file reached -> read the rest + measure->value += sepPos1; + break; + } + else + { + measure->value += sepPos1; + + // else continue reading + size_t len = fread(buffer, sizeof(BYTE), BUFFER_SIZE, file); + buffer[len] = 0; + buffer[len + 1] = 0; + sepPos1 = wBuffer; + } + } + else + { + if (sepPos2) + { + *sepPos2 = 0; + } + + // Read until we find the second separator + measure->value += sepPos1; + } + } + while (sepPos2 == nullptr); + } + else + { + // It's ascii + char* aBuffer = (char*)buffer; + + const std::string separator = StringUtil::Narrow(measure->separator); + const char* separatorSz = separator.c_str(); + + // Read until we find the first separator + char* sepPos1 = nullptr; + char* sepPos2 = nullptr; + do + { + size_t len = fread(buffer, sizeof(char), BUFFER_SIZE, file); + aBuffer[len] = 0; + + sepPos1 = strstr(aBuffer, separatorSz); + if (sepPos1 == nullptr) + { + // The separator wasn't found + if (feof(file)) + { + // End of file reached -> read from start + fseek(file, 0, SEEK_SET); + len = fread(buffer, sizeof(char), BUFFER_SIZE, file); + aBuffer[len] = 0; + sepPos1 = aBuffer; + } + // else continue reading + } + else + { + sepPos1 += separator.size(); + } + } + while (sepPos1 == nullptr); + + // Find the second separator + do + { + sepPos2 = strstr(sepPos1, separatorSz); + if (sepPos2 == nullptr) + { + // The separator wasn't found + if (feof(file)) + { + // End of file reached -> read the rest + measure->value += StringUtil::Widen(sepPos1); + break; + } + else + { + measure->value += StringUtil::Widen(sepPos1); + + // else continue reading + size_t len = fread(buffer, sizeof(char), BUFFER_SIZE, file); + aBuffer[len] = 0; + sepPos1 = aBuffer; + } + } + else + { + if (sepPos2) + { + *sepPos2 = 0; + } + + // Read until we find the second separator + measure->value += StringUtil::Widen(sepPos1); + } + } + while (sepPos2 == nullptr); + } + } + + fclose(file); + } + } + else + { + // Select the filename + measure->value = measure->files[rand() % measure->files.size()]; + } + + return 0; +} + +PLUGIN_EXPORT LPCWSTR GetString(void* data) +{ + MeasureData* measure = (MeasureData*)data; + return measure->value.c_str(); +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + MeasureData* measure = (MeasureData*)data; + delete measure; } \ No newline at end of file diff --git a/Plugins/PluginRecycleManager/PluginRecycleManager.rc b/Plugins/PluginRecycleManager/PluginRecycleManager.rc index d586291b..a9d0fb86 100644 --- a/Plugins/PluginRecycleManager/PluginRecycleManager.rc +++ b/Plugins/PluginRecycleManager/PluginRecycleManager.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,1,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.0.1.0" - VALUE "LegalCopyright", " 2010 - gschoppe" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,1,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.0.1.0" + VALUE "LegalCopyright", " 2010 - gschoppe" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginRecycleManager/PluginRecycleManager.vcxproj b/Plugins/PluginRecycleManager/PluginRecycleManager.vcxproj index 255fae07..68ab9066 100644 --- a/Plugins/PluginRecycleManager/PluginRecycleManager.vcxproj +++ b/Plugins/PluginRecycleManager/PluginRecycleManager.vcxproj @@ -1,35 +1,35 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{4F8C4C09-431C-45C4-830B-32006E783C3A}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>RecycleManager</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ResourceCompile Include="PluginRecycleManager.rc" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="RecycleManager.cpp" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{4F8C4C09-431C-45C4-830B-32006E783C3A}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>RecycleManager</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ResourceCompile Include="PluginRecycleManager.rc" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="RecycleManager.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginRecycleManager/RecycleManager.cpp b/Plugins/PluginRecycleManager/RecycleManager.cpp index b9233ec5..cd56a695 100644 --- a/Plugins/PluginRecycleManager/RecycleManager.cpp +++ b/Plugins/PluginRecycleManager/RecycleManager.cpp @@ -1,291 +1,291 @@ -/* - Copyright (C) 2005 Kimmo Pekkola, 2009 Greg Schoppe - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include <Windows.h> -#include <ShellAPI.h> -#include <process.h> -#include <cstdio> -#include <cstdlib> -#include "../../Library/Export.h" // Rainmeter's exported functions - -struct MeasureData -{ - bool count; - - MeasureData() : count(false) {} -}; - -DWORD WINAPI QueryRecycleBinThreadProc(void* pParam); -bool HasRecycleBinChanged(); - -double g_BinCount = 0; -double g_BinSize = 0; - -int g_UpdateCount = 0; -int g_InstanceCount = 0; -bool g_Thread = false; -bool g_FreeInstanceInThread = false; -CRITICAL_SECTION g_CriticalSection; - -bool g_IsPlatformXP = false; - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - switch (fdwReason) - { - case DLL_PROCESS_ATTACH: - InitializeCriticalSection(&g_CriticalSection); - - // Disable DLL_THREAD_ATTACH and DLL_THREAD_DETACH notification calls - DisableThreadLibraryCalls(hinstDLL); - break; - - case DLL_PROCESS_DETACH: - DeleteCriticalSection(&g_CriticalSection); - break; - } - - return TRUE; -} - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - MeasureData* measure = new MeasureData; - *data = measure; - - if (g_InstanceCount == 0) - { - OSVERSIONINFOEX osvi = {sizeof(OSVERSIONINFOEX)}; - GetVersionEx((OSVERSIONINFO*)&osvi); - - // Not checking for osvi.dwMinorVersion >= 1 because pre-XP is not supported. - g_IsPlatformXP = (osvi.dwMajorVersion == 5); - } - - ++g_InstanceCount; -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - MeasureData* measure = (MeasureData*)data; - - LPCWSTR value = RmReadString(rm, L"RecycleType", L"COUNT"); - if (_wcsicmp(L"COUNT", value) == 0) - { - measure->count = true; - } - else if (_wcsicmp(L"SIZE", value) == 0) - { - measure->count = false; - } - else - { - WCHAR buffer[256]; - _snwprintf_s(buffer, _TRUNCATE, L"RecycleManager.dll: RecycleType=%s is not valid in [%s]", value, RmGetMeasureName(rm)); - RmLog(LOG_ERROR, buffer); - } -} - -PLUGIN_EXPORT double Update(void* data) -{ - MeasureData* measure = (MeasureData*)data; - - if (TryEnterCriticalSection(&g_CriticalSection)) - { - if (!g_Thread) - { - ++g_UpdateCount; - if (g_UpdateCount > g_InstanceCount) - { - if (HasRecycleBinChanged()) - { - // Delay next check. - g_UpdateCount = g_InstanceCount * -2; - - DWORD id; - HANDLE thread = CreateThread(nullptr, 0, QueryRecycleBinThreadProc, nullptr, 0, &id); - if (thread) - { - CloseHandle(thread); - g_Thread = true; - } - } - else - { - g_UpdateCount = 0; - } - } - } - - LeaveCriticalSection(&g_CriticalSection); - } - - return measure->count ? g_BinCount : g_BinSize; -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - MeasureData* measure = (MeasureData*)data; - delete measure; - - --g_InstanceCount; - if (g_InstanceCount == 0) - { - EnterCriticalSection(&g_CriticalSection); - if (g_Thread && !g_FreeInstanceInThread) - { - // Increment ref count of this module so that it will not be unloaded prior to - // thread completion. - DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS; - HMODULE module; - GetModuleHandleEx(flags, (LPCWSTR)DllMain, &module); - g_FreeInstanceInThread = true; - } - LeaveCriticalSection(&g_CriticalSection); - } -} - -PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) -{ - MeasureData* measure = (MeasureData*)data; - - if (_wcsicmp(args, L"EmptyBin") == 0) - { - SHEmptyRecycleBin(nullptr, nullptr, 0); - } - else if (_wcsicmp(args, L"EmptyBinSilent") == 0) - { - SHEmptyRecycleBin(nullptr, nullptr, SHERB_NOCONFIRMATION | SHERB_NOPROGRESSUI | SHERB_NOSOUND); - } - else if (_wcsicmp(args, L"OpenBin") == 0) - { - ShellExecute(nullptr, L"open", L"explorer.exe", L"/N,::{645FF040-5081-101B-9F08-00AA002F954E}", nullptr, SW_SHOW); - } -} - -DWORD WINAPI QueryRecycleBinThreadProc(void* pParam) -{ - // NOTE: Do not use CRT functions (since thread was created with CreateThread())! - - SHQUERYRBINFO rbi = {0}; - rbi.cbSize = sizeof(SHQUERYRBINFO); - SHQueryRecycleBin(nullptr, &rbi); - g_BinCount = (double)rbi.i64NumItems; - g_BinSize = (double)rbi.i64Size; - - EnterCriticalSection(&g_CriticalSection); - HMODULE module = nullptr; - if (g_FreeInstanceInThread) - { - DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; - GetModuleHandleEx(flags, (LPCWSTR)DllMain, &module); - g_FreeInstanceInThread = false; - } - - g_Thread = false; - LeaveCriticalSection(&g_CriticalSection); - - if (module) - { - // Decrement the ref count and possibly unload the module if this is - // the last instance. - FreeLibraryAndExitThread(module, 0); - } - - return 0; -} - -bool HasRecycleBinChanged() -{ - static DWORD s_LastVolumeCount = 0; - static ULONGLONG s_LastWriteTime = 0; - - bool changed = false; - - // Check if items have been added to recycle bin since last check. - HKEY volumeKey; - const WCHAR* subKey = g_IsPlatformXP ? - L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\BitBucket" : - L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\BitBucket\\Volume"; - LSTATUS ls = RegOpenKeyEx(HKEY_CURRENT_USER, subKey, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &volumeKey); - if (ls == ERROR_SUCCESS) - { - DWORD volumeCount = 0; - RegQueryInfoKey(volumeKey, nullptr, nullptr, nullptr, &volumeCount, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); - if (volumeCount != s_LastVolumeCount) - { - s_LastVolumeCount = volumeCount; - changed = true; - } - - WCHAR buffer[64]; - DWORD bufferSize = _countof(buffer); - DWORD index = 0; - - while ((ls = RegEnumKeyEx(volumeKey, index, buffer, &bufferSize, nullptr, nullptr, nullptr, nullptr)) == ERROR_SUCCESS) - { - HKEY volumeSubKey; - ls = RegOpenKeyEx(volumeKey, buffer, 0, KEY_QUERY_VALUE, &volumeSubKey); - if (ls == ERROR_SUCCESS) - { - ULONGLONG lastWriteTime; - ls = RegQueryInfoKey(volumeSubKey, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, (FILETIME*)&lastWriteTime); - if (ls == ERROR_SUCCESS) - { - if (lastWriteTime > s_LastWriteTime) - { - s_LastWriteTime = lastWriteTime; - changed = true; - } - } - - RegCloseKey(volumeSubKey); - } - - bufferSize = _countof(buffer); - ++index; - } - - RegCloseKey(volumeKey); - } - - if (!changed) - { - // Check if recycle bin has been emptied. - HKEY iconKey; - const WCHAR* subKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\DefaultIcon"; - ls = RegOpenKeyEx(HKEY_CURRENT_USER, subKey, 0, KEY_QUERY_VALUE, &iconKey); - if (ls == ERROR_SUCCESS) - { - ULONGLONG lastWriteTime; - ls = RegQueryInfoKey(iconKey, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, (FILETIME*)&lastWriteTime); - if (ls == ERROR_SUCCESS) - { - if (lastWriteTime > s_LastWriteTime) - { - s_LastWriteTime = lastWriteTime; - changed = true; - } - } - - RegCloseKey(iconKey); - } - } - - return changed; -} +/* + Copyright (C) 2005 Kimmo Pekkola, 2009 Greg Schoppe + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <Windows.h> +#include <ShellAPI.h> +#include <process.h> +#include <cstdio> +#include <cstdlib> +#include "../../Library/Export.h" // Rainmeter's exported functions + +struct MeasureData +{ + bool count; + + MeasureData() : count(false) {} +}; + +DWORD WINAPI QueryRecycleBinThreadProc(void* pParam); +bool HasRecycleBinChanged(); + +double g_BinCount = 0; +double g_BinSize = 0; + +int g_UpdateCount = 0; +int g_InstanceCount = 0; +bool g_Thread = false; +bool g_FreeInstanceInThread = false; +CRITICAL_SECTION g_CriticalSection; + +bool g_IsPlatformXP = false; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + InitializeCriticalSection(&g_CriticalSection); + + // Disable DLL_THREAD_ATTACH and DLL_THREAD_DETACH notification calls + DisableThreadLibraryCalls(hinstDLL); + break; + + case DLL_PROCESS_DETACH: + DeleteCriticalSection(&g_CriticalSection); + break; + } + + return TRUE; +} + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + MeasureData* measure = new MeasureData; + *data = measure; + + if (g_InstanceCount == 0) + { + OSVERSIONINFOEX osvi = {sizeof(OSVERSIONINFOEX)}; + GetVersionEx((OSVERSIONINFO*)&osvi); + + // Not checking for osvi.dwMinorVersion >= 1 because pre-XP is not supported. + g_IsPlatformXP = (osvi.dwMajorVersion == 5); + } + + ++g_InstanceCount; +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + MeasureData* measure = (MeasureData*)data; + + LPCWSTR value = RmReadString(rm, L"RecycleType", L"COUNT"); + if (_wcsicmp(L"COUNT", value) == 0) + { + measure->count = true; + } + else if (_wcsicmp(L"SIZE", value) == 0) + { + measure->count = false; + } + else + { + WCHAR buffer[256]; + _snwprintf_s(buffer, _TRUNCATE, L"RecycleManager.dll: RecycleType=%s is not valid in [%s]", value, RmGetMeasureName(rm)); + RmLog(LOG_ERROR, buffer); + } +} + +PLUGIN_EXPORT double Update(void* data) +{ + MeasureData* measure = (MeasureData*)data; + + if (TryEnterCriticalSection(&g_CriticalSection)) + { + if (!g_Thread) + { + ++g_UpdateCount; + if (g_UpdateCount > g_InstanceCount) + { + if (HasRecycleBinChanged()) + { + // Delay next check. + g_UpdateCount = g_InstanceCount * -2; + + DWORD id; + HANDLE thread = CreateThread(nullptr, 0, QueryRecycleBinThreadProc, nullptr, 0, &id); + if (thread) + { + CloseHandle(thread); + g_Thread = true; + } + } + else + { + g_UpdateCount = 0; + } + } + } + + LeaveCriticalSection(&g_CriticalSection); + } + + return measure->count ? g_BinCount : g_BinSize; +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + MeasureData* measure = (MeasureData*)data; + delete measure; + + --g_InstanceCount; + if (g_InstanceCount == 0) + { + EnterCriticalSection(&g_CriticalSection); + if (g_Thread && !g_FreeInstanceInThread) + { + // Increment ref count of this module so that it will not be unloaded prior to + // thread completion. + DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS; + HMODULE module; + GetModuleHandleEx(flags, (LPCWSTR)DllMain, &module); + g_FreeInstanceInThread = true; + } + LeaveCriticalSection(&g_CriticalSection); + } +} + +PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) +{ + MeasureData* measure = (MeasureData*)data; + + if (_wcsicmp(args, L"EmptyBin") == 0) + { + SHEmptyRecycleBin(nullptr, nullptr, 0); + } + else if (_wcsicmp(args, L"EmptyBinSilent") == 0) + { + SHEmptyRecycleBin(nullptr, nullptr, SHERB_NOCONFIRMATION | SHERB_NOPROGRESSUI | SHERB_NOSOUND); + } + else if (_wcsicmp(args, L"OpenBin") == 0) + { + ShellExecute(nullptr, L"open", L"explorer.exe", L"/N,::{645FF040-5081-101B-9F08-00AA002F954E}", nullptr, SW_SHOW); + } +} + +DWORD WINAPI QueryRecycleBinThreadProc(void* pParam) +{ + // NOTE: Do not use CRT functions (since thread was created with CreateThread())! + + SHQUERYRBINFO rbi = {0}; + rbi.cbSize = sizeof(SHQUERYRBINFO); + SHQueryRecycleBin(nullptr, &rbi); + g_BinCount = (double)rbi.i64NumItems; + g_BinSize = (double)rbi.i64Size; + + EnterCriticalSection(&g_CriticalSection); + HMODULE module = nullptr; + if (g_FreeInstanceInThread) + { + DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; + GetModuleHandleEx(flags, (LPCWSTR)DllMain, &module); + g_FreeInstanceInThread = false; + } + + g_Thread = false; + LeaveCriticalSection(&g_CriticalSection); + + if (module) + { + // Decrement the ref count and possibly unload the module if this is + // the last instance. + FreeLibraryAndExitThread(module, 0); + } + + return 0; +} + +bool HasRecycleBinChanged() +{ + static DWORD s_LastVolumeCount = 0; + static ULONGLONG s_LastWriteTime = 0; + + bool changed = false; + + // Check if items have been added to recycle bin since last check. + HKEY volumeKey; + const WCHAR* subKey = g_IsPlatformXP ? + L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\BitBucket" : + L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\BitBucket\\Volume"; + LSTATUS ls = RegOpenKeyEx(HKEY_CURRENT_USER, subKey, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &volumeKey); + if (ls == ERROR_SUCCESS) + { + DWORD volumeCount = 0; + RegQueryInfoKey(volumeKey, nullptr, nullptr, nullptr, &volumeCount, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); + if (volumeCount != s_LastVolumeCount) + { + s_LastVolumeCount = volumeCount; + changed = true; + } + + WCHAR buffer[64]; + DWORD bufferSize = _countof(buffer); + DWORD index = 0; + + while ((ls = RegEnumKeyEx(volumeKey, index, buffer, &bufferSize, nullptr, nullptr, nullptr, nullptr)) == ERROR_SUCCESS) + { + HKEY volumeSubKey; + ls = RegOpenKeyEx(volumeKey, buffer, 0, KEY_QUERY_VALUE, &volumeSubKey); + if (ls == ERROR_SUCCESS) + { + ULONGLONG lastWriteTime; + ls = RegQueryInfoKey(volumeSubKey, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, (FILETIME*)&lastWriteTime); + if (ls == ERROR_SUCCESS) + { + if (lastWriteTime > s_LastWriteTime) + { + s_LastWriteTime = lastWriteTime; + changed = true; + } + } + + RegCloseKey(volumeSubKey); + } + + bufferSize = _countof(buffer); + ++index; + } + + RegCloseKey(volumeKey); + } + + if (!changed) + { + // Check if recycle bin has been emptied. + HKEY iconKey; + const WCHAR* subKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\DefaultIcon"; + ls = RegOpenKeyEx(HKEY_CURRENT_USER, subKey, 0, KEY_QUERY_VALUE, &iconKey); + if (ls == ERROR_SUCCESS) + { + ULONGLONG lastWriteTime; + ls = RegQueryInfoKey(iconKey, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, (FILETIME*)&lastWriteTime); + if (ls == ERROR_SUCCESS) + { + if (lastWriteTime > s_LastWriteTime) + { + s_LastWriteTime = lastWriteTime; + changed = true; + } + } + + RegCloseKey(iconKey); + } + } + + return changed; +} diff --git a/Plugins/PluginResMon/PluginResMon.rc b/Plugins/PluginResMon/PluginResMon.rc index f6dc2214..3bdf14f5 100644 --- a/Plugins/PluginResMon/PluginResMon.rc +++ b/Plugins/PluginResMon/PluginResMon.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.3.0.0" - VALUE "LegalCopyright", " 2010 - David Negstad" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,3,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.3.0.0" + VALUE "LegalCopyright", " 2010 - David Negstad" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginResMon/PluginResMon.vcxproj b/Plugins/PluginResMon/PluginResMon.vcxproj index 337556d6..8479e1e5 100644 --- a/Plugins/PluginResMon/PluginResMon.vcxproj +++ b/Plugins/PluginResMon/PluginResMon.vcxproj @@ -1,36 +1,36 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{17D3BD92-6F5D-438C-A89B-88F4CE06DB94}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>ResMon</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - <AdditionalDependencies>Psapi.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ResourceCompile Include="PluginResMon.rc" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="ResMon.cpp" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{17D3BD92-6F5D-438C-A89B-88F4CE06DB94}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>ResMon</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <AdditionalDependencies>Psapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ResourceCompile Include="PluginResMon.rc" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="ResMon.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginResMon/ResMon.cpp b/Plugins/PluginResMon/ResMon.cpp index e720c359..b6fb408f 100644 --- a/Plugins/PluginResMon/ResMon.cpp +++ b/Plugins/PluginResMon/ResMon.cpp @@ -1,187 +1,187 @@ -/* - Copyright (C) 2004 David Negstad - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/* - Requires Win2k or later. Sorry to anyone still using 9x or ME. - All my results seem to agree with Task Manager (it gets tedious adding up - the different process values). Already proved useful in identifying - resource leaks in itself (all fixed). There's irony for you! -*/ - -#include <windows.h> -#include <stdio.h> -#include <psapi.h> -#include "../../Common/RawString.h" -#include "../../Library/Export.h" // Rainmeter's exported functions - -// system resources that can be counted -enum MEASURETYPE -{ - GDI_COUNT, - USER_COUNT, - HANDLE_COUNT, - WINDOW_COUNT -}; - -struct MeasureData -{ - MEASURETYPE type; - RawString process; - - MeasureData() : type(GDI_COUNT) {} -}; - -// used to track the number of existing windows -UINT g_WindowCount = 0; - -// count the windows -BOOL CALLBACK EnumWindowProc(HWND hWnd, LPARAM lParam) -{ - ++g_WindowCount; - return TRUE; -} - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - MeasureData* measure = new MeasureData; - *data = measure; -} - - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - MeasureData* measure = (MeasureData*)data; - - LPCWSTR type = RmReadString(rm, L"ResCountType", L"GDI"); - if (_wcsicmp(L"GDI", type) == 0) - { - measure->type = GDI_COUNT; - } - else if (_wcsicmp(L"USER", type) == 0) - { - measure->type = USER_COUNT; - } - else if (_wcsicmp(L"HANDLE", type) == 0) - { - measure->type = HANDLE_COUNT; - } - else if (_wcsicmp(L"WINDOW", type) == 0) - { - measure->type = WINDOW_COUNT; - } - else - { - WCHAR buffer[256]; - _snwprintf_s(buffer, _TRUNCATE, L"ResMon.dll: GDICountType=%s is not valid in [%s]", type, RmGetMeasureName(rm)); - RmLog(LOG_ERROR, buffer); - } - - measure->process = RmReadString(rm, L"ProcessName", L""); -} - -PLUGIN_EXPORT double Update(void* data) -{ - MeasureData* measure = (MeasureData*)data; - - // count the existing window objects - if (measure->type == WINDOW_COUNT) - { - g_WindowCount = 0; - EnumChildWindows(nullptr, EnumWindowProc, 0); - return g_WindowCount; - } - - const WCHAR* processName = measure->process.c_str(); - bool name = !measure->process.empty(); - - DWORD aProcesses[1024]; - DWORD bytesNeeded; - WCHAR buffer[1024]; - HMODULE hMod[1024]; - DWORD cbNeeded; - - if (!EnumProcesses(aProcesses, sizeof(aProcesses), &bytesNeeded)) - { - return 0.0; - } - - // step through the running processes - DWORD flags = PROCESS_QUERY_INFORMATION; - - if (name) - { - flags |= PROCESS_VM_READ; - } - - UINT resourceCount = 0; - for (UINT i = 0, isize = bytesNeeded / sizeof(DWORD); i < isize; ++i) - { - HANDLE hProcess = OpenProcess(flags, true, aProcesses[i]); - if (hProcess != nullptr) - { - if (name) - { - if (EnumProcessModules(hProcess, hMod, sizeof(hMod), &cbNeeded)) - { - if (GetModuleBaseName(hProcess, hMod[0], buffer, sizeof(buffer))) - { - if (_wcsicmp(buffer, processName) != 0) - { - CloseHandle(hProcess); - continue; - } - } - else - { - CloseHandle(hProcess); - continue; - } - } - else - { - CloseHandle(hProcess); - continue; - } - } - - if (measure->type == GDI_COUNT) - { - resourceCount += GetGuiResources(hProcess, GR_GDIOBJECTS); - } - else if (measure->type == USER_COUNT) - { - resourceCount += GetGuiResources(hProcess, GR_USEROBJECTS); - } - else if (measure->type == HANDLE_COUNT) - { - DWORD tempHandleCount = 0; - GetProcessHandleCount(hProcess, &tempHandleCount); - resourceCount += tempHandleCount; - } - } - CloseHandle(hProcess); - } - - return resourceCount; -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - MeasureData* measure = (MeasureData*)data; - delete measure; -} +/* + Copyright (C) 2004 David Negstad + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* + Requires Win2k or later. Sorry to anyone still using 9x or ME. + All my results seem to agree with Task Manager (it gets tedious adding up + the different process values). Already proved useful in identifying + resource leaks in itself (all fixed). There's irony for you! +*/ + +#include <windows.h> +#include <stdio.h> +#include <psapi.h> +#include "../../Common/RawString.h" +#include "../../Library/Export.h" // Rainmeter's exported functions + +// system resources that can be counted +enum MEASURETYPE +{ + GDI_COUNT, + USER_COUNT, + HANDLE_COUNT, + WINDOW_COUNT +}; + +struct MeasureData +{ + MEASURETYPE type; + RawString process; + + MeasureData() : type(GDI_COUNT) {} +}; + +// used to track the number of existing windows +UINT g_WindowCount = 0; + +// count the windows +BOOL CALLBACK EnumWindowProc(HWND hWnd, LPARAM lParam) +{ + ++g_WindowCount; + return TRUE; +} + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + MeasureData* measure = new MeasureData; + *data = measure; +} + + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + MeasureData* measure = (MeasureData*)data; + + LPCWSTR type = RmReadString(rm, L"ResCountType", L"GDI"); + if (_wcsicmp(L"GDI", type) == 0) + { + measure->type = GDI_COUNT; + } + else if (_wcsicmp(L"USER", type) == 0) + { + measure->type = USER_COUNT; + } + else if (_wcsicmp(L"HANDLE", type) == 0) + { + measure->type = HANDLE_COUNT; + } + else if (_wcsicmp(L"WINDOW", type) == 0) + { + measure->type = WINDOW_COUNT; + } + else + { + WCHAR buffer[256]; + _snwprintf_s(buffer, _TRUNCATE, L"ResMon.dll: GDICountType=%s is not valid in [%s]", type, RmGetMeasureName(rm)); + RmLog(LOG_ERROR, buffer); + } + + measure->process = RmReadString(rm, L"ProcessName", L""); +} + +PLUGIN_EXPORT double Update(void* data) +{ + MeasureData* measure = (MeasureData*)data; + + // count the existing window objects + if (measure->type == WINDOW_COUNT) + { + g_WindowCount = 0; + EnumChildWindows(nullptr, EnumWindowProc, 0); + return g_WindowCount; + } + + const WCHAR* processName = measure->process.c_str(); + bool name = !measure->process.empty(); + + DWORD aProcesses[1024]; + DWORD bytesNeeded; + WCHAR buffer[1024]; + HMODULE hMod[1024]; + DWORD cbNeeded; + + if (!EnumProcesses(aProcesses, sizeof(aProcesses), &bytesNeeded)) + { + return 0.0; + } + + // step through the running processes + DWORD flags = PROCESS_QUERY_INFORMATION; + + if (name) + { + flags |= PROCESS_VM_READ; + } + + UINT resourceCount = 0; + for (UINT i = 0, isize = bytesNeeded / sizeof(DWORD); i < isize; ++i) + { + HANDLE hProcess = OpenProcess(flags, true, aProcesses[i]); + if (hProcess != nullptr) + { + if (name) + { + if (EnumProcessModules(hProcess, hMod, sizeof(hMod), &cbNeeded)) + { + if (GetModuleBaseName(hProcess, hMod[0], buffer, sizeof(buffer))) + { + if (_wcsicmp(buffer, processName) != 0) + { + CloseHandle(hProcess); + continue; + } + } + else + { + CloseHandle(hProcess); + continue; + } + } + else + { + CloseHandle(hProcess); + continue; + } + } + + if (measure->type == GDI_COUNT) + { + resourceCount += GetGuiResources(hProcess, GR_GDIOBJECTS); + } + else if (measure->type == USER_COUNT) + { + resourceCount += GetGuiResources(hProcess, GR_USEROBJECTS); + } + else if (measure->type == HANDLE_COUNT) + { + DWORD tempHandleCount = 0; + GetProcessHandleCount(hProcess, &tempHandleCount); + resourceCount += tempHandleCount; + } + } + CloseHandle(hProcess); + } + + return resourceCount; +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + MeasureData* measure = (MeasureData*)data; + delete measure; +} diff --git a/Plugins/PluginSpeedFan/PluginSpeedFan.rc b/Plugins/PluginSpeedFan/PluginSpeedFan.rc index b07006e9..406f5c9e 100644 --- a/Plugins/PluginSpeedFan/PluginSpeedFan.rc +++ b/Plugins/PluginSpeedFan/PluginSpeedFan.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,2,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.2.0.0" - VALUE "LegalCopyright", " 2010 - Rainy" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,2,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.2.0.0" + VALUE "LegalCopyright", " 2010 - Rainy" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginSpeedFan/PluginSpeedFan.vcxproj b/Plugins/PluginSpeedFan/PluginSpeedFan.vcxproj index 0ee4e2c4..13031a17 100644 --- a/Plugins/PluginSpeedFan/PluginSpeedFan.vcxproj +++ b/Plugins/PluginSpeedFan/PluginSpeedFan.vcxproj @@ -1,35 +1,35 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{D10AB316-0F7A-4551-BE4F-385E04CCF1E8}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>SpeedFanPlugin</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ResourceCompile Include="PluginSpeedFan.rc" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="SpeedFanPlugin.cpp" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{D10AB316-0F7A-4551-BE4F-385E04CCF1E8}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>SpeedFanPlugin</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ResourceCompile Include="PluginSpeedFan.rc" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="SpeedFanPlugin.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginSpeedFan/SpeedFanPlugin.cpp b/Plugins/PluginSpeedFan/SpeedFanPlugin.cpp index 83ddfb2d..35606874 100644 --- a/Plugins/PluginSpeedFan/SpeedFanPlugin.cpp +++ b/Plugins/PluginSpeedFan/SpeedFanPlugin.cpp @@ -1,195 +1,195 @@ -/* - Copyright (C) 2004 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include <windows.h> -#include <stdio.h> -#include "../../Library/Export.h" // Rainmeter's exported functions - - -#pragma pack(push, 1) -struct SpeedFanData -{ - WORD version; - WORD flags; - INT MemSize; - DWORD handle; - WORD NumTemps; - WORD NumFans; - WORD NumVolts; - INT temps[32]; - INT fans[32]; - INT volts[32]; -}; -#pragma pack(pop) - -enum SensorType -{ - TYPE_TEMP, - TYPE_FAN, - TYPE_VOLT -}; - -enum ScaleType -{ - SCALE_SOURCE, - SCALE_CENTIGRADE, - SCALE_FARENHEIT, - SCALE_KELVIN -}; - -struct MeasureData -{ - SensorType type; - ScaleType scale; - UINT number; - - MeasureData() : type(TYPE_TEMP), scale(SCALE_SOURCE), number() {} -}; - -void ReadSharedData(SensorType type, ScaleType scale, UINT number, double* value); - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - MeasureData* measure = new MeasureData; - *data = measure; -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - MeasureData* measure = (MeasureData*)data; - - LPCWSTR type = RmReadString(rm, L"SpeedFanType", L"TEMPERATURE"); - if (_wcsicmp(L"TEMPERATURE", type) == 0) - { - measure->type = TYPE_TEMP; - - LPCWSTR scale = RmReadString(rm, L"SpeedFanScale", L"C"); - if (_wcsicmp(L"C", scale) == 0) - { - measure->scale = SCALE_CENTIGRADE; - } - else if (_wcsicmp(L"F", scale) == 0) - { - measure->scale = SCALE_FARENHEIT; - } - else if (_wcsicmp(L"K", scale) == 0) - { - measure->scale = SCALE_KELVIN; - } - else - { - WCHAR buffer[256]; - _snwprintf_s(buffer, _TRUNCATE, L"SpeedFanPlugin.dll: SpeedFanScale=%s is not valid in [%s]", scale, RmGetMeasureName(rm)); - RmLog(LOG_ERROR, buffer); - } - } - else if (_wcsicmp(L"FAN", type) == 0) - { - measure->type = TYPE_FAN; - } - else if (_wcsicmp(L"VOLTAGE", type) == 0) - { - measure->type = TYPE_VOLT; - } - else - { - WCHAR buffer[256]; - _snwprintf_s(buffer, _TRUNCATE, L"SpeedFanPlugin.dll: SpeedFanType=%s is not valid in [%s]", type, RmGetMeasureName(rm)); - RmLog(LOG_ERROR, buffer); - } - - measure->number = RmReadInt(rm, L"SpeedFanNumber", 0); -} - -PLUGIN_EXPORT double Update(void* data) -{ - MeasureData* measure = (MeasureData*)data; - double value = 0.0; - - ReadSharedData(measure->type, measure->scale, measure->number, &value); - - return value; -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - MeasureData* measure = (MeasureData*)data; - delete measure; -} - -/* - Get the data from shared memory. -*/ -void ReadSharedData(SensorType type, ScaleType scale, UINT number, double* value) -{ - HANDLE hData = OpenFileMapping(FILE_MAP_READ, FALSE, L"SFSharedMemory_ALM"); - if (hData == nullptr) return; - - SpeedFanData* ptr = (SpeedFanData*)MapViewOfFile(hData, FILE_MAP_READ, 0, 0, 0); - if (ptr == 0) - { - CloseHandle(hData); - return; - } - - if (ptr->version == 1) - { - switch(type) - { - case TYPE_TEMP: - if (number < ptr->NumTemps) - { - *value = ptr->temps[number]; - *value /= 100.0; - - if (scale == SCALE_FARENHEIT) - { - *value *= 1.8; - *value += 32.0; - } - else if (scale == SCALE_KELVIN) - { - *value += 273.15; - } - } - break; - - case TYPE_FAN: - if (number < ptr->NumTemps) - { - *value = ptr->fans[number]; - } - break; - - case TYPE_VOLT: - if (number < ptr->NumVolts) - { - *value = ptr->volts[number]; - *value /= 100.0; - } - break; - } - } - else - { - RmLog(LOG_ERROR, L"SpeedFanPlugin.dll: Incorrect shared memory version"); - } - - UnmapViewOfFile(ptr); - CloseHandle(hData); -} +/* + Copyright (C) 2004 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <windows.h> +#include <stdio.h> +#include "../../Library/Export.h" // Rainmeter's exported functions + + +#pragma pack(push, 1) +struct SpeedFanData +{ + WORD version; + WORD flags; + INT MemSize; + DWORD handle; + WORD NumTemps; + WORD NumFans; + WORD NumVolts; + INT temps[32]; + INT fans[32]; + INT volts[32]; +}; +#pragma pack(pop) + +enum SensorType +{ + TYPE_TEMP, + TYPE_FAN, + TYPE_VOLT +}; + +enum ScaleType +{ + SCALE_SOURCE, + SCALE_CENTIGRADE, + SCALE_FARENHEIT, + SCALE_KELVIN +}; + +struct MeasureData +{ + SensorType type; + ScaleType scale; + UINT number; + + MeasureData() : type(TYPE_TEMP), scale(SCALE_SOURCE), number() {} +}; + +void ReadSharedData(SensorType type, ScaleType scale, UINT number, double* value); + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + MeasureData* measure = new MeasureData; + *data = measure; +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + MeasureData* measure = (MeasureData*)data; + + LPCWSTR type = RmReadString(rm, L"SpeedFanType", L"TEMPERATURE"); + if (_wcsicmp(L"TEMPERATURE", type) == 0) + { + measure->type = TYPE_TEMP; + + LPCWSTR scale = RmReadString(rm, L"SpeedFanScale", L"C"); + if (_wcsicmp(L"C", scale) == 0) + { + measure->scale = SCALE_CENTIGRADE; + } + else if (_wcsicmp(L"F", scale) == 0) + { + measure->scale = SCALE_FARENHEIT; + } + else if (_wcsicmp(L"K", scale) == 0) + { + measure->scale = SCALE_KELVIN; + } + else + { + WCHAR buffer[256]; + _snwprintf_s(buffer, _TRUNCATE, L"SpeedFanPlugin.dll: SpeedFanScale=%s is not valid in [%s]", scale, RmGetMeasureName(rm)); + RmLog(LOG_ERROR, buffer); + } + } + else if (_wcsicmp(L"FAN", type) == 0) + { + measure->type = TYPE_FAN; + } + else if (_wcsicmp(L"VOLTAGE", type) == 0) + { + measure->type = TYPE_VOLT; + } + else + { + WCHAR buffer[256]; + _snwprintf_s(buffer, _TRUNCATE, L"SpeedFanPlugin.dll: SpeedFanType=%s is not valid in [%s]", type, RmGetMeasureName(rm)); + RmLog(LOG_ERROR, buffer); + } + + measure->number = RmReadInt(rm, L"SpeedFanNumber", 0); +} + +PLUGIN_EXPORT double Update(void* data) +{ + MeasureData* measure = (MeasureData*)data; + double value = 0.0; + + ReadSharedData(measure->type, measure->scale, measure->number, &value); + + return value; +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + MeasureData* measure = (MeasureData*)data; + delete measure; +} + +/* + Get the data from shared memory. +*/ +void ReadSharedData(SensorType type, ScaleType scale, UINT number, double* value) +{ + HANDLE hData = OpenFileMapping(FILE_MAP_READ, FALSE, L"SFSharedMemory_ALM"); + if (hData == nullptr) return; + + SpeedFanData* ptr = (SpeedFanData*)MapViewOfFile(hData, FILE_MAP_READ, 0, 0, 0); + if (ptr == 0) + { + CloseHandle(hData); + return; + } + + if (ptr->version == 1) + { + switch(type) + { + case TYPE_TEMP: + if (number < ptr->NumTemps) + { + *value = ptr->temps[number]; + *value /= 100.0; + + if (scale == SCALE_FARENHEIT) + { + *value *= 1.8; + *value += 32.0; + } + else if (scale == SCALE_KELVIN) + { + *value += 273.15; + } + } + break; + + case TYPE_FAN: + if (number < ptr->NumTemps) + { + *value = ptr->fans[number]; + } + break; + + case TYPE_VOLT: + if (number < ptr->NumVolts) + { + *value = ptr->volts[number]; + *value /= 100.0; + } + break; + } + } + else + { + RmLog(LOG_ERROR, L"SpeedFanPlugin.dll: Incorrect shared memory version"); + } + + UnmapViewOfFile(ptr); + CloseHandle(hData); +} diff --git a/Plugins/PluginSysInfo/PluginSysInfo.rc b/Plugins/PluginSysInfo/PluginSysInfo.rc index c4d45c51..198a3648 100644 --- a/Plugins/PluginSysInfo/PluginSysInfo.rc +++ b/Plugins/PluginSysInfo/PluginSysInfo.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,4,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.4.0.0" - VALUE "LegalCopyright", " 2010 - Rainy, Mordred" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,4,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.4.0.0" + VALUE "LegalCopyright", " 2010 - Rainy, Mordred" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginSysInfo/PluginSysInfo.vcxproj b/Plugins/PluginSysInfo/PluginSysInfo.vcxproj index 78809d57..6d97818b 100644 --- a/Plugins/PluginSysInfo/PluginSysInfo.vcxproj +++ b/Plugins/PluginSysInfo/PluginSysInfo.vcxproj @@ -1,41 +1,41 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{6EBCA4DA-8CC7-42FE-8F45-878ABE165078}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>SysInfo</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - <AdditionalDependencies>Rasapi32.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ResourceCompile Include="PluginSysInfo.rc" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="SysInfo.cpp" /> - </ItemGroup> - <ItemGroup> - <ProjectReference Include="..\..\Common\Common.vcxproj"> - <Project>{19312085-aa51-4bd6-be92-4b6098cca539}</Project> - </ProjectReference> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{6EBCA4DA-8CC7-42FE-8F45-878ABE165078}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>SysInfo</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <AdditionalDependencies>Rasapi32.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ResourceCompile Include="PluginSysInfo.rc" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="SysInfo.cpp" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\Common\Common.vcxproj"> + <Project>{19312085-aa51-4bd6-be92-4b6098cca539}</Project> + </ProjectReference> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginSysInfo/SysInfo.cpp b/Plugins/PluginSysInfo/SysInfo.cpp index dc4bb66b..0dd35bc4 100644 --- a/Plugins/PluginSysInfo/SysInfo.cpp +++ b/Plugins/PluginSysInfo/SysInfo.cpp @@ -1,500 +1,500 @@ -/* - Copyright (C) 2004 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include <windows.h> -#include <Iphlpapi.h> -#include <Netlistmgr.h> -#include <stdio.h> -#include <stdlib.h> -#include "../API/RainmeterAPI.h" -#include "../../Library/Export.h" -#include"../../Common/Platform.h" - -typedef struct -{ - int count; // Number of monitors - HMONITOR m_Monitors[32]; // Monitor info - RECT m_MonitorRect[32]; // Monitor rect on virtual screen - MONITORINFO m_MonitorInfo[32]; // Monitor information -} MULTIMONITOR_INFO; - -MULTIMONITOR_INFO m_Monitors = {0}; - -enum MeasureType -{ - MEASURE_COMPUTER_NAME, - MEASURE_USER_NAME, - MEASURE_WORK_AREA, - MEASURE_SCREEN_SIZE, - MEASURE_RAS_STATUS, - MEASURE_OS_VERSION, - MEASURE_OS_BITS, - MEASURE_IDLE_TIME, - MEASURE_ADAPTER_DESCRIPTION, - MEASURE_NET_MASK, - MEASURE_IP_ADDRESS, - MEASURE_GATEWAY_ADDRESS, - MEASURE_HOST_NAME, - MEASURE_DOMAIN_NAME, - MEASURE_DNS_SERVER, - MEASURE_INTERNET_CONNECTIVITY, - MEASURE_LAN_CONNECTIVITY, - MEASURE_WORK_AREA_TOP, - MEASURE_WORK_AREA_LEFT, - MEASURE_WORK_AREA_WIDTH, - MEASURE_WORK_AREA_HEIGHT, - MEASURE_SCREEN_WIDTH, - MEASURE_SCREEN_HEIGHT, - MEASURE_NUM_MONITORS, - MEASURE_VIRTUAL_SCREEN_TOP, - MEASURE_VIRTUAL_SCREEN_LEFT, - MEASURE_VIRTUAL_SCREEN_WIDTH, - MEASURE_VIRTUAL_SCREEN_HEIGHT -}; - -struct MeasureData -{ - MeasureType type; - int data; - - MeasureData() : type(), data() {} -}; - -NLM_CONNECTIVITY GetNetworkConnectivity(); -BOOL CALLBACK MyInfoEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData); - -bool g_Initialized = false; - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - MeasureData* measure = new MeasureData; - *data = measure; - - if (!g_Initialized) - { - if (GetSystemMetrics(SM_CMONITORS) > 32) - { - LSLog(LOG_ERROR, nullptr, L"SysInfo.dll: Max amount of monitors supported is 32."); - } - - m_Monitors.count = 0; - EnumDisplayMonitors(nullptr, nullptr, MyInfoEnumProc, (LPARAM)(&m_Monitors)); - g_Initialized = true; - } -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - MeasureData* measure = (MeasureData*)data; - - int defaultData = -1; - - LPCTSTR type = RmReadString(rm, L"SysInfoType", L""); - if (_wcsicmp(L"COMPUTER_NAME", type) == 0) - { - measure->type = MEASURE_COMPUTER_NAME; - } - else if (_wcsicmp(L"USER_NAME", type) == 0) - { - measure->type = MEASURE_USER_NAME; - } - else if (_wcsicmp(L"WORK_AREA", type) == 0) - { - measure->type = MEASURE_WORK_AREA; - } - else if (_wcsicmp(L"SCREEN_SIZE", type) == 0) - { - measure->type = MEASURE_SCREEN_SIZE; - } - else if (_wcsicmp(L"RAS_STATUS", type) == 0) - { - measure->type = MEASURE_RAS_STATUS; - } - else if (_wcsicmp(L"OS_VERSION", type) == 0) - { - measure->type = MEASURE_OS_VERSION; - } - else if (_wcsicmp(L"OS_BITS", type) == 0) - { - measure->type = MEASURE_OS_BITS; - } - else if (_wcsicmp(L"IDLE_TIME", type) == 0) - { - measure->type = MEASURE_IDLE_TIME; - } - else if (_wcsicmp(L"ADAPTER_DESCRIPTION", type) == 0) - { - defaultData = 0; - measure->type = MEASURE_ADAPTER_DESCRIPTION; - } - else if (_wcsicmp(L"NET_MASK", type) == 0) - { - defaultData = 0; - measure->type = MEASURE_NET_MASK; - } - else if (_wcsicmp(L"IP_ADDRESS", type) == 0) - { - defaultData = 0; - measure->type = MEASURE_IP_ADDRESS; - } - else if (_wcsicmp(L"GATEWAY_ADDRESS", type) == 0) - { - defaultData = 0; - measure->type = MEASURE_GATEWAY_ADDRESS; - } - else if (_wcsicmp(L"HOST_NAME", type) == 0) - { - measure->type = MEASURE_HOST_NAME; - } - else if (_wcsicmp(L"DOMAIN_NAME", type) == 0) - { - measure->type = MEASURE_DOMAIN_NAME; - } - else if (_wcsicmp(L"DNS_SERVER", type) == 0) - { - measure->type = MEASURE_DNS_SERVER; - } - else if (_wcsicmp(L"INTERNET_CONNECTIVITY", type) == 0) - { - measure->type = MEASURE_INTERNET_CONNECTIVITY; - } - else if (_wcsicmp(L"LAN_CONNECTIVITY", type) == 0) - { - measure->type = MEASURE_LAN_CONNECTIVITY; - } - else if (_wcsicmp(L"WORK_AREA_TOP", type) == 0) - { - measure->type = MEASURE_WORK_AREA_TOP; - } - else if (_wcsicmp(L"WORK_AREA_LEFT", type) == 0) - { - measure->type = MEASURE_WORK_AREA_LEFT; - } - else if (_wcsicmp(L"WORK_AREA_WIDTH", type) == 0) - { - measure->type = MEASURE_WORK_AREA_WIDTH; - } - else if (_wcsicmp(L"WORK_AREA_HEIGHT", type) == 0) - { - measure->type = MEASURE_WORK_AREA_HEIGHT; - } - else if (_wcsicmp(L"SCREEN_WIDTH", type) == 0) - { - measure->type = MEASURE_SCREEN_WIDTH; - } - else if (_wcsicmp(L"SCREEN_HEIGHT", type) == 0) - { - measure->type = MEASURE_SCREEN_HEIGHT; - } - else if (_wcsicmp(L"NUM_MONITORS", type) == 0) - { - measure->type = MEASURE_NUM_MONITORS; - } - else if (_wcsicmp(L"VIRTUAL_SCREEN_TOP", type) == 0) - { - measure->type = MEASURE_VIRTUAL_SCREEN_TOP; - } - else if (_wcsicmp(L"VIRTUAL_SCREEN_LEFT", type) == 0) - { - measure->type = MEASURE_VIRTUAL_SCREEN_LEFT; - } - else if (_wcsicmp(L"VIRTUAL_SCREEN_WIDTH", type) == 0) - { - measure->type = MEASURE_VIRTUAL_SCREEN_WIDTH; - } - else if (_wcsicmp(L"VIRTUAL_SCREEN_HEIGHT", type) == 0) - { - measure->type = MEASURE_VIRTUAL_SCREEN_HEIGHT; - } - else - { - WCHAR buffer[256]; - _snwprintf_s(buffer, _TRUNCATE, L"SysInfo.dll: SysInfoType=%s is not valid in [%s]", type, RmGetMeasureName(rm)); - RmLog(LOG_ERROR, buffer); - } - - measure->data = RmReadInt(rm, L"SysInfoData", defaultData); -} - -PLUGIN_EXPORT LPCWSTR GetString(void* data) -{ - MeasureData* measure = (MeasureData*)data; - - static WCHAR sBuffer[256]; - DWORD sBufferLen = _countof(sBuffer); - - BYTE tmpBuffer[7168]; - ULONG tmpBufferLen = _countof(tmpBuffer); - - auto convertToWide = [&](LPCSTR str)->LPCWSTR - { - MultiByteToWideChar(CP_ACP, 0, str, -1, sBuffer, 256); - return sBuffer; - }; - - switch (measure->type) - { - case MEASURE_COMPUTER_NAME: - GetComputerName(sBuffer, &sBufferLen); - return sBuffer; - - case MEASURE_USER_NAME: - GetUserName(sBuffer, &sBufferLen); - return sBuffer; - - case MEASURE_WORK_AREA: - wsprintf(sBuffer, L"%i x %i", GetSystemMetrics(SM_CXFULLSCREEN), GetSystemMetrics(SM_CYFULLSCREEN)); - return sBuffer; - - case MEASURE_SCREEN_SIZE: - wsprintf(sBuffer, L"%i x %i", GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); - return sBuffer; - - case MEASURE_OS_VERSION: - return Platform::GetPlatformName(); - - case MEASURE_ADAPTER_DESCRIPTION: - if (ERROR_SUCCESS == GetAdaptersInfo((IP_ADAPTER_INFO*)tmpBuffer, &tmpBufferLen)) - { - PIP_ADAPTER_INFO info = (IP_ADAPTER_INFO*)tmpBuffer; - int i = 0; - while (info) - { - if (i == measure->data) - { - return convertToWide(info->Description); - } - - info = info->Next; - i++; - } - } - break; - - case MEASURE_IP_ADDRESS: - if (NO_ERROR == GetIpAddrTable((PMIB_IPADDRTABLE)tmpBuffer, &tmpBufferLen, FALSE)) - { - PMIB_IPADDRTABLE ipTable = (PMIB_IPADDRTABLE)tmpBuffer; - if (measure->data >= 1000) - { - measure->data = measure->data - 999; - for (UINT i = 0; i < ipTable->dwNumEntries; ++i) - { - if ((ipTable->table[i].wType) & MIB_IPADDR_DISCONNECTED) continue; - --measure->data; - if (measure->data == 0) - { - DWORD ip = ipTable->table[i].dwAddr; - wsprintf(sBuffer, L"%i.%i.%i.%i", ip % 256, (ip >> 8) % 256, (ip >> 16) % 256, (ip >> 24) % 256); - return sBuffer; - } - } - } - else if (measure->data < (int)ipTable->dwNumEntries) - { - DWORD ip = ipTable->table[measure->data].dwAddr; - wsprintf(sBuffer, L"%i.%i.%i.%i", ip % 256, (ip >> 8) % 256, (ip >> 16) % 256, (ip >> 24) % 256); - return sBuffer; - } - } - return L""; - - case MEASURE_NET_MASK: - if (NO_ERROR == GetIpAddrTable((PMIB_IPADDRTABLE)tmpBuffer, &tmpBufferLen, FALSE)) - { - PMIB_IPADDRTABLE ipTable = (PMIB_IPADDRTABLE)tmpBuffer; - if (measure->data < (int)ipTable->dwNumEntries) - { - DWORD ip = ipTable->table[measure->data].dwMask; - wsprintf(sBuffer, L"%i.%i.%i.%i", ip % 256, (ip >> 8) % 256, (ip >> 16) % 256, (ip >> 24) % 256); - return sBuffer; - } - } - break; - - case MEASURE_GATEWAY_ADDRESS: - if (ERROR_SUCCESS == GetAdaptersInfo((IP_ADAPTER_INFO*)tmpBuffer, &tmpBufferLen)) - { - PIP_ADAPTER_INFO info = (IP_ADAPTER_INFO*)tmpBuffer; - int i = 0; - while (info) - { - if (i == measure->data) - { - return convertToWide(info->GatewayList.IpAddress.String); - } - info = info->Next; - ++i; - } - } - break; - - case MEASURE_HOST_NAME: - if (ERROR_SUCCESS == GetNetworkParams((PFIXED_INFO)tmpBuffer, &tmpBufferLen)) - { - PFIXED_INFO info = (PFIXED_INFO)tmpBuffer; - return convertToWide(info->HostName); - } - break; - - case MEASURE_DOMAIN_NAME: - if (ERROR_SUCCESS == GetNetworkParams((PFIXED_INFO)tmpBuffer, &tmpBufferLen)) - { - PFIXED_INFO info = (PFIXED_INFO)tmpBuffer; - return convertToWide(info->DomainName); - } - break; - - case MEASURE_DNS_SERVER: - if (ERROR_SUCCESS == GetNetworkParams((PFIXED_INFO)tmpBuffer, &tmpBufferLen)) - { - PFIXED_INFO info = (PFIXED_INFO)tmpBuffer; - if (info->CurrentDnsServer) - { - return convertToWide(info->CurrentDnsServer->IpAddress.String); - } - else - { - return convertToWide(info->DnsServerList.IpAddress.String); - } - } - break; - } - - return nullptr; -} - -PLUGIN_EXPORT double Update(void* data) -{ - MeasureData* measure = (MeasureData*)data; - - switch (measure->type) - { - case MEASURE_OS_BITS: - { - SYSTEM_INFO si = {0}; - GetNativeSystemInfo(&si); - return (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || - si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) ? 64.0 : 32.0; - } - - case MEASURE_IDLE_TIME: - { - LASTINPUTINFO idle = { sizeof(LASTINPUTINFO) }; - GetLastInputInfo(&idle); - return (double)((GetTickCount() - idle.dwTime) / 1000); - } - - case MEASURE_INTERNET_CONNECTIVITY: - { - const auto connectivity = GetNetworkConnectivity(); - return (connectivity & NLM_CONNECTIVITY_IPV4_INTERNET || - connectivity & NLM_CONNECTIVITY_IPV6_INTERNET) ? 1.0 : -1.0; - } - - case MEASURE_LAN_CONNECTIVITY: - return GetNetworkConnectivity() != NLM_CONNECTIVITY_DISCONNECTED ? 1.0 : -1.0; - - case MEASURE_WORK_AREA_WIDTH: - return (measure->data != -1) - ? m_Monitors.m_MonitorInfo[measure->data - 1].rcWork.right - m_Monitors.m_MonitorInfo[measure->data - 1].rcWork.left - : GetSystemMetrics(SM_CXFULLSCREEN); - - case MEASURE_WORK_AREA_HEIGHT: - return (measure->data != -1) - ? m_Monitors.m_MonitorInfo[measure->data - 1].rcWork.bottom - m_Monitors.m_MonitorInfo[measure->data - 1].rcWork.top - : GetSystemMetrics(SM_CYFULLSCREEN); - - case MEASURE_SCREEN_WIDTH: - return (measure->data != -1) - ? m_Monitors.m_MonitorInfo[measure->data - 1].rcMonitor.right - m_Monitors.m_MonitorInfo[measure->data - 1].rcMonitor.left - : GetSystemMetrics(SM_CXSCREEN); - - case MEASURE_SCREEN_HEIGHT: - return (measure->data != -1) - ? m_Monitors.m_MonitorInfo[measure->data - 1].rcMonitor.bottom - m_Monitors.m_MonitorInfo[measure->data - 1].rcMonitor.top - : GetSystemMetrics(SM_CYSCREEN); - - case MEASURE_VIRTUAL_SCREEN_WIDTH: - return GetSystemMetrics(SM_CXVIRTUALSCREEN); - - case MEASURE_VIRTUAL_SCREEN_HEIGHT: - return GetSystemMetrics(SM_CYVIRTUALSCREEN); - - case MEASURE_NUM_MONITORS: - return GetSystemMetrics(SM_CMONITORS); - - case MEASURE_WORK_AREA_TOP: - return (measure->data != -1) - ? m_Monitors.m_MonitorInfo[measure->data - 1].rcWork.top - : m_Monitors.m_MonitorInfo[0].rcWork.top; - - case MEASURE_WORK_AREA_LEFT: - return (measure->data != -1) - ? m_Monitors.m_MonitorInfo[measure->data - 1].rcWork.left - : m_Monitors.m_MonitorInfo[0].rcWork.left; - - case MEASURE_VIRTUAL_SCREEN_TOP: - return (measure->data != -1) - ? m_Monitors.m_MonitorInfo[measure->data - 1].rcMonitor.top - : GetSystemMetrics(SM_YVIRTUALSCREEN); - - case MEASURE_VIRTUAL_SCREEN_LEFT: - return (measure->data != -1) - ? m_Monitors.m_MonitorInfo[measure->data - 1].rcMonitor.left - : GetSystemMetrics(SM_XVIRTUALSCREEN); - } - - return 0.0; -} - -BOOL CALLBACK MyInfoEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -{ - MULTIMONITOR_INFO* m = (MULTIMONITOR_INFO*)dwData; - m->m_Monitors[m->count] = hMonitor; - memcpy(&(m->m_MonitorRect[m->count]), lprcMonitor, sizeof(RECT)); - m->m_MonitorInfo[m->count].cbSize = sizeof(MONITORINFO); - GetMonitorInfo(hMonitor, &(m->m_MonitorInfo[m->count])); - ++m->count; - return true; -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - MeasureData* measure = (MeasureData*)data; - delete measure; -} - -NLM_CONNECTIVITY GetNetworkConnectivity() -{ - // This is initialized like this in case INetworkListManager is not available (i.e. on WinXP). - // In such cases, we simply assume that there is an internet connection. - NLM_CONNECTIVITY connectivity = - (NLM_CONNECTIVITY)((int)NLM_CONNECTIVITY_IPV4_INTERNET | (int)NLM_CONNECTIVITY_IPV4_LOCALNETWORK); - - INetworkListManager* nlm; - HRESULT hr = CoCreateInstance( - CLSID_NetworkListManager, NULL, CLSCTX_INPROC_SERVER, __uuidof(INetworkListManager), (void**)&nlm); - if (SUCCEEDED(hr)) - { - nlm->GetConnectivity(&connectivity); - nlm->Release(); - } - - return connectivity; -} +/* + Copyright (C) 2004 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <windows.h> +#include <Iphlpapi.h> +#include <Netlistmgr.h> +#include <stdio.h> +#include <stdlib.h> +#include "../API/RainmeterAPI.h" +#include "../../Library/Export.h" +#include"../../Common/Platform.h" + +typedef struct +{ + int count; // Number of monitors + HMONITOR m_Monitors[32]; // Monitor info + RECT m_MonitorRect[32]; // Monitor rect on virtual screen + MONITORINFO m_MonitorInfo[32]; // Monitor information +} MULTIMONITOR_INFO; + +MULTIMONITOR_INFO m_Monitors = {0}; + +enum MeasureType +{ + MEASURE_COMPUTER_NAME, + MEASURE_USER_NAME, + MEASURE_WORK_AREA, + MEASURE_SCREEN_SIZE, + MEASURE_RAS_STATUS, + MEASURE_OS_VERSION, + MEASURE_OS_BITS, + MEASURE_IDLE_TIME, + MEASURE_ADAPTER_DESCRIPTION, + MEASURE_NET_MASK, + MEASURE_IP_ADDRESS, + MEASURE_GATEWAY_ADDRESS, + MEASURE_HOST_NAME, + MEASURE_DOMAIN_NAME, + MEASURE_DNS_SERVER, + MEASURE_INTERNET_CONNECTIVITY, + MEASURE_LAN_CONNECTIVITY, + MEASURE_WORK_AREA_TOP, + MEASURE_WORK_AREA_LEFT, + MEASURE_WORK_AREA_WIDTH, + MEASURE_WORK_AREA_HEIGHT, + MEASURE_SCREEN_WIDTH, + MEASURE_SCREEN_HEIGHT, + MEASURE_NUM_MONITORS, + MEASURE_VIRTUAL_SCREEN_TOP, + MEASURE_VIRTUAL_SCREEN_LEFT, + MEASURE_VIRTUAL_SCREEN_WIDTH, + MEASURE_VIRTUAL_SCREEN_HEIGHT +}; + +struct MeasureData +{ + MeasureType type; + int data; + + MeasureData() : type(), data() {} +}; + +NLM_CONNECTIVITY GetNetworkConnectivity(); +BOOL CALLBACK MyInfoEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData); + +bool g_Initialized = false; + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + MeasureData* measure = new MeasureData; + *data = measure; + + if (!g_Initialized) + { + if (GetSystemMetrics(SM_CMONITORS) > 32) + { + LSLog(LOG_ERROR, nullptr, L"SysInfo.dll: Max amount of monitors supported is 32."); + } + + m_Monitors.count = 0; + EnumDisplayMonitors(nullptr, nullptr, MyInfoEnumProc, (LPARAM)(&m_Monitors)); + g_Initialized = true; + } +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + MeasureData* measure = (MeasureData*)data; + + int defaultData = -1; + + LPCTSTR type = RmReadString(rm, L"SysInfoType", L""); + if (_wcsicmp(L"COMPUTER_NAME", type) == 0) + { + measure->type = MEASURE_COMPUTER_NAME; + } + else if (_wcsicmp(L"USER_NAME", type) == 0) + { + measure->type = MEASURE_USER_NAME; + } + else if (_wcsicmp(L"WORK_AREA", type) == 0) + { + measure->type = MEASURE_WORK_AREA; + } + else if (_wcsicmp(L"SCREEN_SIZE", type) == 0) + { + measure->type = MEASURE_SCREEN_SIZE; + } + else if (_wcsicmp(L"RAS_STATUS", type) == 0) + { + measure->type = MEASURE_RAS_STATUS; + } + else if (_wcsicmp(L"OS_VERSION", type) == 0) + { + measure->type = MEASURE_OS_VERSION; + } + else if (_wcsicmp(L"OS_BITS", type) == 0) + { + measure->type = MEASURE_OS_BITS; + } + else if (_wcsicmp(L"IDLE_TIME", type) == 0) + { + measure->type = MEASURE_IDLE_TIME; + } + else if (_wcsicmp(L"ADAPTER_DESCRIPTION", type) == 0) + { + defaultData = 0; + measure->type = MEASURE_ADAPTER_DESCRIPTION; + } + else if (_wcsicmp(L"NET_MASK", type) == 0) + { + defaultData = 0; + measure->type = MEASURE_NET_MASK; + } + else if (_wcsicmp(L"IP_ADDRESS", type) == 0) + { + defaultData = 0; + measure->type = MEASURE_IP_ADDRESS; + } + else if (_wcsicmp(L"GATEWAY_ADDRESS", type) == 0) + { + defaultData = 0; + measure->type = MEASURE_GATEWAY_ADDRESS; + } + else if (_wcsicmp(L"HOST_NAME", type) == 0) + { + measure->type = MEASURE_HOST_NAME; + } + else if (_wcsicmp(L"DOMAIN_NAME", type) == 0) + { + measure->type = MEASURE_DOMAIN_NAME; + } + else if (_wcsicmp(L"DNS_SERVER", type) == 0) + { + measure->type = MEASURE_DNS_SERVER; + } + else if (_wcsicmp(L"INTERNET_CONNECTIVITY", type) == 0) + { + measure->type = MEASURE_INTERNET_CONNECTIVITY; + } + else if (_wcsicmp(L"LAN_CONNECTIVITY", type) == 0) + { + measure->type = MEASURE_LAN_CONNECTIVITY; + } + else if (_wcsicmp(L"WORK_AREA_TOP", type) == 0) + { + measure->type = MEASURE_WORK_AREA_TOP; + } + else if (_wcsicmp(L"WORK_AREA_LEFT", type) == 0) + { + measure->type = MEASURE_WORK_AREA_LEFT; + } + else if (_wcsicmp(L"WORK_AREA_WIDTH", type) == 0) + { + measure->type = MEASURE_WORK_AREA_WIDTH; + } + else if (_wcsicmp(L"WORK_AREA_HEIGHT", type) == 0) + { + measure->type = MEASURE_WORK_AREA_HEIGHT; + } + else if (_wcsicmp(L"SCREEN_WIDTH", type) == 0) + { + measure->type = MEASURE_SCREEN_WIDTH; + } + else if (_wcsicmp(L"SCREEN_HEIGHT", type) == 0) + { + measure->type = MEASURE_SCREEN_HEIGHT; + } + else if (_wcsicmp(L"NUM_MONITORS", type) == 0) + { + measure->type = MEASURE_NUM_MONITORS; + } + else if (_wcsicmp(L"VIRTUAL_SCREEN_TOP", type) == 0) + { + measure->type = MEASURE_VIRTUAL_SCREEN_TOP; + } + else if (_wcsicmp(L"VIRTUAL_SCREEN_LEFT", type) == 0) + { + measure->type = MEASURE_VIRTUAL_SCREEN_LEFT; + } + else if (_wcsicmp(L"VIRTUAL_SCREEN_WIDTH", type) == 0) + { + measure->type = MEASURE_VIRTUAL_SCREEN_WIDTH; + } + else if (_wcsicmp(L"VIRTUAL_SCREEN_HEIGHT", type) == 0) + { + measure->type = MEASURE_VIRTUAL_SCREEN_HEIGHT; + } + else + { + WCHAR buffer[256]; + _snwprintf_s(buffer, _TRUNCATE, L"SysInfo.dll: SysInfoType=%s is not valid in [%s]", type, RmGetMeasureName(rm)); + RmLog(LOG_ERROR, buffer); + } + + measure->data = RmReadInt(rm, L"SysInfoData", defaultData); +} + +PLUGIN_EXPORT LPCWSTR GetString(void* data) +{ + MeasureData* measure = (MeasureData*)data; + + static WCHAR sBuffer[256]; + DWORD sBufferLen = _countof(sBuffer); + + BYTE tmpBuffer[7168]; + ULONG tmpBufferLen = _countof(tmpBuffer); + + auto convertToWide = [&](LPCSTR str)->LPCWSTR + { + MultiByteToWideChar(CP_ACP, 0, str, -1, sBuffer, 256); + return sBuffer; + }; + + switch (measure->type) + { + case MEASURE_COMPUTER_NAME: + GetComputerName(sBuffer, &sBufferLen); + return sBuffer; + + case MEASURE_USER_NAME: + GetUserName(sBuffer, &sBufferLen); + return sBuffer; + + case MEASURE_WORK_AREA: + wsprintf(sBuffer, L"%i x %i", GetSystemMetrics(SM_CXFULLSCREEN), GetSystemMetrics(SM_CYFULLSCREEN)); + return sBuffer; + + case MEASURE_SCREEN_SIZE: + wsprintf(sBuffer, L"%i x %i", GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + return sBuffer; + + case MEASURE_OS_VERSION: + return Platform::GetPlatformName(); + + case MEASURE_ADAPTER_DESCRIPTION: + if (ERROR_SUCCESS == GetAdaptersInfo((IP_ADAPTER_INFO*)tmpBuffer, &tmpBufferLen)) + { + PIP_ADAPTER_INFO info = (IP_ADAPTER_INFO*)tmpBuffer; + int i = 0; + while (info) + { + if (i == measure->data) + { + return convertToWide(info->Description); + } + + info = info->Next; + i++; + } + } + break; + + case MEASURE_IP_ADDRESS: + if (NO_ERROR == GetIpAddrTable((PMIB_IPADDRTABLE)tmpBuffer, &tmpBufferLen, FALSE)) + { + PMIB_IPADDRTABLE ipTable = (PMIB_IPADDRTABLE)tmpBuffer; + if (measure->data >= 1000) + { + measure->data = measure->data - 999; + for (UINT i = 0; i < ipTable->dwNumEntries; ++i) + { + if ((ipTable->table[i].wType) & MIB_IPADDR_DISCONNECTED) continue; + --measure->data; + if (measure->data == 0) + { + DWORD ip = ipTable->table[i].dwAddr; + wsprintf(sBuffer, L"%i.%i.%i.%i", ip % 256, (ip >> 8) % 256, (ip >> 16) % 256, (ip >> 24) % 256); + return sBuffer; + } + } + } + else if (measure->data < (int)ipTable->dwNumEntries) + { + DWORD ip = ipTable->table[measure->data].dwAddr; + wsprintf(sBuffer, L"%i.%i.%i.%i", ip % 256, (ip >> 8) % 256, (ip >> 16) % 256, (ip >> 24) % 256); + return sBuffer; + } + } + return L""; + + case MEASURE_NET_MASK: + if (NO_ERROR == GetIpAddrTable((PMIB_IPADDRTABLE)tmpBuffer, &tmpBufferLen, FALSE)) + { + PMIB_IPADDRTABLE ipTable = (PMIB_IPADDRTABLE)tmpBuffer; + if (measure->data < (int)ipTable->dwNumEntries) + { + DWORD ip = ipTable->table[measure->data].dwMask; + wsprintf(sBuffer, L"%i.%i.%i.%i", ip % 256, (ip >> 8) % 256, (ip >> 16) % 256, (ip >> 24) % 256); + return sBuffer; + } + } + break; + + case MEASURE_GATEWAY_ADDRESS: + if (ERROR_SUCCESS == GetAdaptersInfo((IP_ADAPTER_INFO*)tmpBuffer, &tmpBufferLen)) + { + PIP_ADAPTER_INFO info = (IP_ADAPTER_INFO*)tmpBuffer; + int i = 0; + while (info) + { + if (i == measure->data) + { + return convertToWide(info->GatewayList.IpAddress.String); + } + info = info->Next; + ++i; + } + } + break; + + case MEASURE_HOST_NAME: + if (ERROR_SUCCESS == GetNetworkParams((PFIXED_INFO)tmpBuffer, &tmpBufferLen)) + { + PFIXED_INFO info = (PFIXED_INFO)tmpBuffer; + return convertToWide(info->HostName); + } + break; + + case MEASURE_DOMAIN_NAME: + if (ERROR_SUCCESS == GetNetworkParams((PFIXED_INFO)tmpBuffer, &tmpBufferLen)) + { + PFIXED_INFO info = (PFIXED_INFO)tmpBuffer; + return convertToWide(info->DomainName); + } + break; + + case MEASURE_DNS_SERVER: + if (ERROR_SUCCESS == GetNetworkParams((PFIXED_INFO)tmpBuffer, &tmpBufferLen)) + { + PFIXED_INFO info = (PFIXED_INFO)tmpBuffer; + if (info->CurrentDnsServer) + { + return convertToWide(info->CurrentDnsServer->IpAddress.String); + } + else + { + return convertToWide(info->DnsServerList.IpAddress.String); + } + } + break; + } + + return nullptr; +} + +PLUGIN_EXPORT double Update(void* data) +{ + MeasureData* measure = (MeasureData*)data; + + switch (measure->type) + { + case MEASURE_OS_BITS: + { + SYSTEM_INFO si = {0}; + GetNativeSystemInfo(&si); + return (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || + si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) ? 64.0 : 32.0; + } + + case MEASURE_IDLE_TIME: + { + LASTINPUTINFO idle = { sizeof(LASTINPUTINFO) }; + GetLastInputInfo(&idle); + return (double)((GetTickCount() - idle.dwTime) / 1000); + } + + case MEASURE_INTERNET_CONNECTIVITY: + { + const auto connectivity = GetNetworkConnectivity(); + return (connectivity & NLM_CONNECTIVITY_IPV4_INTERNET || + connectivity & NLM_CONNECTIVITY_IPV6_INTERNET) ? 1.0 : -1.0; + } + + case MEASURE_LAN_CONNECTIVITY: + return GetNetworkConnectivity() != NLM_CONNECTIVITY_DISCONNECTED ? 1.0 : -1.0; + + case MEASURE_WORK_AREA_WIDTH: + return (measure->data != -1) + ? m_Monitors.m_MonitorInfo[measure->data - 1].rcWork.right - m_Monitors.m_MonitorInfo[measure->data - 1].rcWork.left + : GetSystemMetrics(SM_CXFULLSCREEN); + + case MEASURE_WORK_AREA_HEIGHT: + return (measure->data != -1) + ? m_Monitors.m_MonitorInfo[measure->data - 1].rcWork.bottom - m_Monitors.m_MonitorInfo[measure->data - 1].rcWork.top + : GetSystemMetrics(SM_CYFULLSCREEN); + + case MEASURE_SCREEN_WIDTH: + return (measure->data != -1) + ? m_Monitors.m_MonitorInfo[measure->data - 1].rcMonitor.right - m_Monitors.m_MonitorInfo[measure->data - 1].rcMonitor.left + : GetSystemMetrics(SM_CXSCREEN); + + case MEASURE_SCREEN_HEIGHT: + return (measure->data != -1) + ? m_Monitors.m_MonitorInfo[measure->data - 1].rcMonitor.bottom - m_Monitors.m_MonitorInfo[measure->data - 1].rcMonitor.top + : GetSystemMetrics(SM_CYSCREEN); + + case MEASURE_VIRTUAL_SCREEN_WIDTH: + return GetSystemMetrics(SM_CXVIRTUALSCREEN); + + case MEASURE_VIRTUAL_SCREEN_HEIGHT: + return GetSystemMetrics(SM_CYVIRTUALSCREEN); + + case MEASURE_NUM_MONITORS: + return GetSystemMetrics(SM_CMONITORS); + + case MEASURE_WORK_AREA_TOP: + return (measure->data != -1) + ? m_Monitors.m_MonitorInfo[measure->data - 1].rcWork.top + : m_Monitors.m_MonitorInfo[0].rcWork.top; + + case MEASURE_WORK_AREA_LEFT: + return (measure->data != -1) + ? m_Monitors.m_MonitorInfo[measure->data - 1].rcWork.left + : m_Monitors.m_MonitorInfo[0].rcWork.left; + + case MEASURE_VIRTUAL_SCREEN_TOP: + return (measure->data != -1) + ? m_Monitors.m_MonitorInfo[measure->data - 1].rcMonitor.top + : GetSystemMetrics(SM_YVIRTUALSCREEN); + + case MEASURE_VIRTUAL_SCREEN_LEFT: + return (measure->data != -1) + ? m_Monitors.m_MonitorInfo[measure->data - 1].rcMonitor.left + : GetSystemMetrics(SM_XVIRTUALSCREEN); + } + + return 0.0; +} + +BOOL CALLBACK MyInfoEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) +{ + MULTIMONITOR_INFO* m = (MULTIMONITOR_INFO*)dwData; + m->m_Monitors[m->count] = hMonitor; + memcpy(&(m->m_MonitorRect[m->count]), lprcMonitor, sizeof(RECT)); + m->m_MonitorInfo[m->count].cbSize = sizeof(MONITORINFO); + GetMonitorInfo(hMonitor, &(m->m_MonitorInfo[m->count])); + ++m->count; + return true; +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + MeasureData* measure = (MeasureData*)data; + delete measure; +} + +NLM_CONNECTIVITY GetNetworkConnectivity() +{ + // This is initialized like this in case INetworkListManager is not available (i.e. on WinXP). + // In such cases, we simply assume that there is an internet connection. + NLM_CONNECTIVITY connectivity = + (NLM_CONNECTIVITY)((int)NLM_CONNECTIVITY_IPV4_INTERNET | (int)NLM_CONNECTIVITY_IPV4_LOCALNETWORK); + + INetworkListManager* nlm; + HRESULT hr = CoCreateInstance( + CLSID_NetworkListManager, NULL, CLSCTX_INPROC_SERVER, __uuidof(INetworkListManager), (void**)&nlm); + if (SUCCEEDED(hr)) + { + nlm->GetConnectivity(&connectivity); + nlm->Release(); + } + + return connectivity; +} diff --git a/Plugins/PluginVirtualDesktops/DexpotConstants.h b/Plugins/PluginVirtualDesktops/DexpotConstants.h index eea52ad1..8a718060 100644 --- a/Plugins/PluginVirtualDesktops/DexpotConstants.h +++ b/Plugins/PluginVirtualDesktops/DexpotConstants.h @@ -1,117 +1,117 @@ -#ifndef _DEXPOT_CONSTANTS_H_ -#define _DEXPOT_CONSTANTS_H_ - -#define DEXPOTTITLE _T("Dexpot - Main Menu") -#define DEXPOTCLASS _T("ThunderRT6FormDC") -#define DEXPOTCLASS2 _T("ThunderFormDC") - -#define WM_HOOXPOTRUFT 1802 - -#define DEX_SWITCHDESKTOP (WM_HOOXPOTRUFT + 1) -#define DEX_DEXPOTCOMMAND (WM_HOOXPOTRUFT + 2) - -#define DEX_MOVEICONS (WM_HOOXPOTRUFT + 13) -#define DEX_COPYICONS (WM_HOOXPOTRUFT + 14) -#define DEX_REMOVEICONS (WM_HOOXPOTRUFT + 15) - -#define DEX_REGISTERPLUGIN (WM_HOOXPOTRUFT + 200) -#define DEX_UNREGISTERPLUGIN (WM_HOOXPOTRUFT + 217) -#define DEX_SETFILEMAP (WM_HOOXPOTRUFT + 218) - -#define DEX_REGISTERHOTKEY (WM_HOOXPOTRUFT + 211) -#define DEX_LOADSETTINGS (WM_HOOXPOTRUFT + 212) -#define DEX_REGISTEROPTION (WM_HOOXPOTRUFT + 213) -#define DEX_SETOPTIONVALUE (WM_HOOXPOTRUFT + 214) -#define DEX_SETHOTKEYVALUE (WM_HOOXPOTRUFT + 215) -#define DEX_SAVESETTINGS (WM_HOOXPOTRUFT + 216) - -#define DEX_GETSCREENSHOT (WM_HOOXPOTRUFT + 201) -#define DEX_GETDESKTOPWIDTH (WM_HOOXPOTRUFT + 202) -#define DEX_GETDESKTOPHEIGHT (WM_HOOXPOTRUFT + 203) -#define DEX_GETCURRENTDESKTOP (WM_HOOXPOTRUFT + 204) -#define DEX_GETDESKTOPCOUNT (WM_HOOXPOTRUFT + 205) -#define DEX_SETSWITCHINGEXCEPTION (WM_HOOXPOTRUFT + 206) -#define DEX_GETSWITCHINGEXCEPTION (WM_HOOXPOTRUFT + 207) -#define DEX_SETMINANIMATION (WM_HOOXPOTRUFT + 208) -#define DEX_DEBUGOUTPUT (WM_HOOXPOTRUFT + 209) -#define DEX_GETDEBUGMODE (WM_HOOXPOTRUFT + 210) -#define DEX_GETLANGUAGEFILE (WM_HOOXPOTRUFT + 219) -#define DEX_INSERTMAINMENUITEM (WM_HOOXPOTRUFT + 220) -#define DEX_GETDESKTOPTITLE (WM_HOOXPOTRUFT + 221) -#define DEX_GETDESKTOPWALLPAPER (WM_HOOXPOTRUFT + 222) -#define DEX_ISPORTABLE (WM_HOOXPOTRUFT + 223) -#define DEX_GETDEXPOTHOME (WM_HOOXPOTRUFT + 224) -#define DEX_GETAPPDATAPATH (WM_HOOXPOTRUFT + 225) -#define DEX_GETTRAYICONMODE (WM_HOOXPOTRUFT + 226) -#define DEX_SETTRAYICONMODE (WM_HOOXPOTRUFT + 227) -#define DEX_GATHERWINDOWS (WM_HOOXPOTRUFT + 228) -#define DEX_MOVEWINDOW (WM_HOOXPOTRUFT + 229) -#define DEX_COPYWINDOW (WM_HOOXPOTRUFT + 230) -#define DEX_SETFOREGROUNDWINDOW (WM_HOOXPOTRUFT + 231) -#define DEX_ASSIGNWINDOW (WM_HOOXPOTRUFT + 232) -#define DEX_SWITCHTOWINDOW (WM_HOOXPOTRUFT + 233) -#define DEX_SHOWWINDOW (WM_HOOXPOTRUFT + 234) -#define DEX_UPDATESCREENSHOT (WM_HOOXPOTRUFT + 235) -#define DEX_REMOVEMAINMENUITEM (WM_HOOXPOTRUFT + 236) -#define DEX_SUBSCRIBEHOOXPOT (WM_HOOXPOTRUFT + 237) -#define DEX_UNSUBSCRIBEHOOXPOT (WM_HOOXPOTRUFT + 238) -#define DEX_GETACTIVEWINDOW (WM_HOOXPOTRUFT + 239) -#define DEX_GETWINDOWSONDESKTOP (WM_HOOXPOTRUFT + 240) -#define DEX_OPENWINDOWMENU (WM_HOOXPOTRUFT + 241) -#define DEX_OPENMAINMENU (WM_HOOXPOTRUFT + 242) - -#define DEX_SWITCHING (WM_HOOXPOTRUFT + 100) -#define DEX_SWITCHED (WM_HOOXPOTRUFT + 101) -#define DEX_SHUTDOWN (WM_HOOXPOTRUFT + 102) -#define DEX_LOAD (WM_HOOXPOTRUFT + 103) -#define DEX_HOTKEY (WM_HOOXPOTRUFT + 104) -#define DEX_SETOPTION (WM_HOOXPOTRUFT + 105) -#define DEX_CONFIGURE (WM_HOOXPOTRUFT + 106) -#define DEX_MENUCOMMAND (WM_HOOXPOTRUFT + 107) -#define DEX_SWITCHREQUEST (WM_HOOXPOTRUFT + 108) -#define DEX_DESKTOPCOUNTCHANGED (WM_HOOXPOTRUFT + 109) -#define DEX_DESKTOPCONTENTCHANGED (WM_HOOXPOTRUFT + 111) -#define DEX_DESKTOPCONFIGURATIONCHANGED (WM_HOOXPOTRUFT + 112) -#define DEX_DEXPOTSETTINGSCHANGED (WM_HOOXPOTRUFT + 113) - -#define DEX_SWITCH_NOSCREENSHOT 0x0001 -#define DEX_SWITCH_DONTSWITCH 0x0002 -#define DEX_SWITCH_NOANIMATION 0x0004 - -#define DEX_OPTION_TYPE_INTEGER 1 -#define DEX_OPTION_TYPE_STRING 2 - -#define DEX_COMMAND_SETTINGS 1 -#define DEX_COMMAND_DESKTOPWINDOWS 2 -#define DEX_COMMAND_MANAGER 3 -#define DEX_COMMAND_CONFIGUREDESKTOPS 4 -#define DEX_COMMAND_PREVIEW 6 -#define DEX_COMMAND_RULES 7 -#define DEX_COMMAND_ABOUT 8 -#define DEX_COMMAND_EXIT 9 -#define DEX_COMMAND_QUICKEXIT 10 -#define DEX_COMMAND_FULLSCREENPREVIEW 11 -#define DEX_COMMAND_WINDOWCATALOG 12 -#define DEX_COMMAND_APPLYRULES 13 - -#define DEX_TRAYICON_NONE 0 -#define DEX_TRAYICON_NORMAL 1 -#define DEX_TRAYICON_CURRENTDESKTOP 2 -#define DEX_TRAYICON_NEXTPREVIOUS 3 -#define DEX_TRAYICON_ONEPERDESKTOP 4 - -#define DEX_EXCEPTION_UNKNOWN 0 -#define DEX_EXCEPTION_NORMAL 1 -#define DEX_EXCEPTION_MOVE 2 -#define DEX_EXCEPTION_STICKY 3 -#define DEX_EXCEPTION_CLOSE 6 -#define DEX_EXCEPTION_IGNORE 4 -#define DEX_EXCEPTION_HIDE 5 -#define DEX_EXCEPTION_DONTMOVE 7 - -#define DEX_DEBUG_LOGFILE 0x0001 -#define DEX_DEBUG_IMAGING 0x0002 -#define DEX_DEBUG_TASKBAR 0x0004 -#define DEX_DEBUG_RECOVERY 0x0008 - -#endif +#ifndef _DEXPOT_CONSTANTS_H_ +#define _DEXPOT_CONSTANTS_H_ + +#define DEXPOTTITLE _T("Dexpot - Main Menu") +#define DEXPOTCLASS _T("ThunderRT6FormDC") +#define DEXPOTCLASS2 _T("ThunderFormDC") + +#define WM_HOOXPOTRUFT 1802 + +#define DEX_SWITCHDESKTOP (WM_HOOXPOTRUFT + 1) +#define DEX_DEXPOTCOMMAND (WM_HOOXPOTRUFT + 2) + +#define DEX_MOVEICONS (WM_HOOXPOTRUFT + 13) +#define DEX_COPYICONS (WM_HOOXPOTRUFT + 14) +#define DEX_REMOVEICONS (WM_HOOXPOTRUFT + 15) + +#define DEX_REGISTERPLUGIN (WM_HOOXPOTRUFT + 200) +#define DEX_UNREGISTERPLUGIN (WM_HOOXPOTRUFT + 217) +#define DEX_SETFILEMAP (WM_HOOXPOTRUFT + 218) + +#define DEX_REGISTERHOTKEY (WM_HOOXPOTRUFT + 211) +#define DEX_LOADSETTINGS (WM_HOOXPOTRUFT + 212) +#define DEX_REGISTEROPTION (WM_HOOXPOTRUFT + 213) +#define DEX_SETOPTIONVALUE (WM_HOOXPOTRUFT + 214) +#define DEX_SETHOTKEYVALUE (WM_HOOXPOTRUFT + 215) +#define DEX_SAVESETTINGS (WM_HOOXPOTRUFT + 216) + +#define DEX_GETSCREENSHOT (WM_HOOXPOTRUFT + 201) +#define DEX_GETDESKTOPWIDTH (WM_HOOXPOTRUFT + 202) +#define DEX_GETDESKTOPHEIGHT (WM_HOOXPOTRUFT + 203) +#define DEX_GETCURRENTDESKTOP (WM_HOOXPOTRUFT + 204) +#define DEX_GETDESKTOPCOUNT (WM_HOOXPOTRUFT + 205) +#define DEX_SETSWITCHINGEXCEPTION (WM_HOOXPOTRUFT + 206) +#define DEX_GETSWITCHINGEXCEPTION (WM_HOOXPOTRUFT + 207) +#define DEX_SETMINANIMATION (WM_HOOXPOTRUFT + 208) +#define DEX_DEBUGOUTPUT (WM_HOOXPOTRUFT + 209) +#define DEX_GETDEBUGMODE (WM_HOOXPOTRUFT + 210) +#define DEX_GETLANGUAGEFILE (WM_HOOXPOTRUFT + 219) +#define DEX_INSERTMAINMENUITEM (WM_HOOXPOTRUFT + 220) +#define DEX_GETDESKTOPTITLE (WM_HOOXPOTRUFT + 221) +#define DEX_GETDESKTOPWALLPAPER (WM_HOOXPOTRUFT + 222) +#define DEX_ISPORTABLE (WM_HOOXPOTRUFT + 223) +#define DEX_GETDEXPOTHOME (WM_HOOXPOTRUFT + 224) +#define DEX_GETAPPDATAPATH (WM_HOOXPOTRUFT + 225) +#define DEX_GETTRAYICONMODE (WM_HOOXPOTRUFT + 226) +#define DEX_SETTRAYICONMODE (WM_HOOXPOTRUFT + 227) +#define DEX_GATHERWINDOWS (WM_HOOXPOTRUFT + 228) +#define DEX_MOVEWINDOW (WM_HOOXPOTRUFT + 229) +#define DEX_COPYWINDOW (WM_HOOXPOTRUFT + 230) +#define DEX_SETFOREGROUNDWINDOW (WM_HOOXPOTRUFT + 231) +#define DEX_ASSIGNWINDOW (WM_HOOXPOTRUFT + 232) +#define DEX_SWITCHTOWINDOW (WM_HOOXPOTRUFT + 233) +#define DEX_SHOWWINDOW (WM_HOOXPOTRUFT + 234) +#define DEX_UPDATESCREENSHOT (WM_HOOXPOTRUFT + 235) +#define DEX_REMOVEMAINMENUITEM (WM_HOOXPOTRUFT + 236) +#define DEX_SUBSCRIBEHOOXPOT (WM_HOOXPOTRUFT + 237) +#define DEX_UNSUBSCRIBEHOOXPOT (WM_HOOXPOTRUFT + 238) +#define DEX_GETACTIVEWINDOW (WM_HOOXPOTRUFT + 239) +#define DEX_GETWINDOWSONDESKTOP (WM_HOOXPOTRUFT + 240) +#define DEX_OPENWINDOWMENU (WM_HOOXPOTRUFT + 241) +#define DEX_OPENMAINMENU (WM_HOOXPOTRUFT + 242) + +#define DEX_SWITCHING (WM_HOOXPOTRUFT + 100) +#define DEX_SWITCHED (WM_HOOXPOTRUFT + 101) +#define DEX_SHUTDOWN (WM_HOOXPOTRUFT + 102) +#define DEX_LOAD (WM_HOOXPOTRUFT + 103) +#define DEX_HOTKEY (WM_HOOXPOTRUFT + 104) +#define DEX_SETOPTION (WM_HOOXPOTRUFT + 105) +#define DEX_CONFIGURE (WM_HOOXPOTRUFT + 106) +#define DEX_MENUCOMMAND (WM_HOOXPOTRUFT + 107) +#define DEX_SWITCHREQUEST (WM_HOOXPOTRUFT + 108) +#define DEX_DESKTOPCOUNTCHANGED (WM_HOOXPOTRUFT + 109) +#define DEX_DESKTOPCONTENTCHANGED (WM_HOOXPOTRUFT + 111) +#define DEX_DESKTOPCONFIGURATIONCHANGED (WM_HOOXPOTRUFT + 112) +#define DEX_DEXPOTSETTINGSCHANGED (WM_HOOXPOTRUFT + 113) + +#define DEX_SWITCH_NOSCREENSHOT 0x0001 +#define DEX_SWITCH_DONTSWITCH 0x0002 +#define DEX_SWITCH_NOANIMATION 0x0004 + +#define DEX_OPTION_TYPE_INTEGER 1 +#define DEX_OPTION_TYPE_STRING 2 + +#define DEX_COMMAND_SETTINGS 1 +#define DEX_COMMAND_DESKTOPWINDOWS 2 +#define DEX_COMMAND_MANAGER 3 +#define DEX_COMMAND_CONFIGUREDESKTOPS 4 +#define DEX_COMMAND_PREVIEW 6 +#define DEX_COMMAND_RULES 7 +#define DEX_COMMAND_ABOUT 8 +#define DEX_COMMAND_EXIT 9 +#define DEX_COMMAND_QUICKEXIT 10 +#define DEX_COMMAND_FULLSCREENPREVIEW 11 +#define DEX_COMMAND_WINDOWCATALOG 12 +#define DEX_COMMAND_APPLYRULES 13 + +#define DEX_TRAYICON_NONE 0 +#define DEX_TRAYICON_NORMAL 1 +#define DEX_TRAYICON_CURRENTDESKTOP 2 +#define DEX_TRAYICON_NEXTPREVIOUS 3 +#define DEX_TRAYICON_ONEPERDESKTOP 4 + +#define DEX_EXCEPTION_UNKNOWN 0 +#define DEX_EXCEPTION_NORMAL 1 +#define DEX_EXCEPTION_MOVE 2 +#define DEX_EXCEPTION_STICKY 3 +#define DEX_EXCEPTION_CLOSE 6 +#define DEX_EXCEPTION_IGNORE 4 +#define DEX_EXCEPTION_HIDE 5 +#define DEX_EXCEPTION_DONTMOVE 7 + +#define DEX_DEBUG_LOGFILE 0x0001 +#define DEX_DEBUG_IMAGING 0x0002 +#define DEX_DEBUG_TASKBAR 0x0004 +#define DEX_DEBUG_RECOVERY 0x0008 + +#endif diff --git a/Plugins/PluginVirtualDesktops/DexpotMeasure.cpp b/Plugins/PluginVirtualDesktops/DexpotMeasure.cpp index 02d12fcf..6baf45d8 100644 --- a/Plugins/PluginVirtualDesktops/DexpotMeasure.cpp +++ b/Plugins/PluginVirtualDesktops/DexpotMeasure.cpp @@ -1,629 +1,629 @@ -/* - Copyright (C) 2010-2011 Patrick Dubbert - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "DexpotMeasure.h" - -#include <tchar.h> - -#include "DexpotConstants.h" -#include "../../Library/Export.h" - -int DexpotMeasure::InstanceCount = 0; -HWND DexpotMeasure::hWndDexpot = nullptr; -HWND DexpotMeasure::hWndMessageWindow = nullptr; -std::set<DexpotMeasure*> DexpotMeasure::DexpotMeasures; -TCHAR DexpotMeasure::StringBuffer[STRINGBUFFER_SIZE]; -UINT DexpotMeasure::WM_DEXPOTSTARTED = RegisterWindowMessage(_T("DexpotStarted")); -BOOL DexpotMeasure::PluginRegistered = FALSE; -HWND DexpotMeasure::hWndRainmeterControl = nullptr; -int DexpotMeasure::CurrentDesktop = 0; - -std::vector<std::wstring> DexpotDesktopNameMeasure::DesktopNames; -std::vector<std::wstring> DexpotDesktopWallpaperMeasure::DesktopWallpapers; - -DexpotMeasure::DexpotMeasure(HMODULE instance, UINT _id) : VDMeasure(instance, _id) -{ -} - -DexpotMeasure* DexpotMeasure::CreateMeasure(HMODULE instance, UINT id, LPCTSTR iniFile, LPCTSTR section) -{ - std::wstring TypeString(ReadConfigString(section, _T("VDMeasureType"), _T(""))); - - if (TypeString == _T("VDMActive")) return new DexpotVDMActiveMeasure(instance, id); - else if (TypeString == _T("DesktopCount")) return new DexpotDesktopCountMeasure(instance, id); - else if (TypeString == _T("CurrentDesktop")) return new DexpotCurrentDesktopMeasure(instance, id); - else if (TypeString == _T("SwitchDesktop")) return new DexpotSwitchDesktopMeasure(instance, id); - else if (TypeString == _T("Screenshot")) return new DexpotScreenshotMeasure(instance, id); - else if (TypeString == _T("DesktopName")) return new DexpotDesktopNameMeasure(instance, id); - else if (TypeString == _T("DesktopWallpaper")) return new DexpotDesktopWallpaperMeasure(instance, id); - else if (TypeString == _T("Command")) return new DexpotCommandMeasure(instance, id); - - return nullptr; -} - -UINT DexpotMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) -{ - if (InstanceCount == 0) - { - hWndRainmeterControl = FindWindow(_T("DummyRainWClass"), _T("Rainmeter control window")); - hWndMessageWindow = CreateMessageWindow(); - } - InstanceCount++; - - if (!PluginRegistered && FindDexpotWindow()) - { - SendNotifyMessage(hWndDexpot, DEX_REGISTERPLUGIN, 0, (LPARAM) hWndMessageWindow); - CurrentDesktop = (int) SendMessage(hWndDexpot, DEX_GETCURRENTDESKTOP, 0, 0); - PluginRegistered = TRUE; - } - - InitializeData(); - DexpotMeasures.insert(this); - - return 0; -} - -void DexpotMeasure::Finalize() -{ - InstanceCount--; - if (InstanceCount == 0) - { - if (PluginRegistered) - { - SendNotifyMessage(hWndDexpot, DEX_UNREGISTERPLUGIN, 0, (LPARAM) hWndMessageWindow); - PluginRegistered = FALSE; - } - DestroyWindow(hWndMessageWindow); - UnregisterClass(_T("DexpotPluginWindowClass"), hInstance); - } - DexpotMeasures.erase(this); -} - -UINT DexpotMeasure::Update() -{ - return 0; -} - -LPCTSTR DexpotMeasure::GetString(UINT flags) -{ - _stprintf_s(StringBuffer, STRINGBUFFER_SIZE, _T("%i"), Update()); - return StringBuffer; -} - -void DexpotMeasure::OnDexpotStarted() -{ - InitializeData(); -} - -BOOL DexpotMeasure::FindDexpotWindow() -{ - if (IsWindow(hWndDexpot)) return TRUE; - hWndDexpot = FindWindow(DEXPOTCLASS, DEXPOTTITLE); - return hWndDexpot != nullptr; -} - -HWND DexpotMeasure::CreateMessageWindow() -{ - WNDCLASS wc; - - ZeroMemory(&wc, sizeof(wc)); - wc.hInstance = hInstance; - wc.lpszClassName = _T("DexpotPluginWindowClass"); - wc.lpfnWndProc = WindowProc; - RegisterClass(&wc); - - HWND hWnd = CreateWindowEx(0, _T("DexpotPluginWindowClass"), _T("Dexpot Rainmeter Plugin"), 0, 0, 0, 0, 0, nullptr, nullptr, hInstance, nullptr); - SetWindowLong(hWnd, GWL_STYLE, 0); - SetWindowPos(hWnd, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); - MoveWindow(hWnd, 0, 0, 0, 0, FALSE); - - return hWnd; -} - -void DexpotMeasure::SendBang(std::wstring &Bang) -{ - COPYDATASTRUCT cds; - - cds.dwData = 1; - cds.cbData = (DWORD) (Bang.length() + 1) * sizeof(wchar_t); - cds.lpData = (PVOID) Bang.c_str(); - - SendMessage(hWndRainmeterControl, WM_COPYDATA, (WPARAM) hWndMessageWindow, (LPARAM) &cds); -} - -LRESULT CALLBACK DexpotMeasure::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch(message) - { - case DEX_SWITCHED: - CurrentDesktop = HIWORD(lParam); - for (std::set<DexpotMeasure*>::iterator i = DexpotMeasures.begin(); i != DexpotMeasures.end(); ++i) - { - (*i)->OnSwitched(LOWORD(lParam), HIWORD(lParam), LOWORD(wParam), HIWORD(wParam)); - } - return 0; - - case DEX_DESKTOPCOUNTCHANGED: - for (std::set<DexpotMeasure*>::iterator i = DexpotMeasures.begin(); i != DexpotMeasures.end(); ++i) - { - (*i)->OnDesktopCountChanged((int)wParam); - } - return 0; - - case DEX_SHUTDOWN: - PluginRegistered = FALSE; - for (std::set<DexpotMeasure*>::iterator i = DexpotMeasures.begin(); i != DexpotMeasures.end(); ++i) - { - (*i)->OnShutdown(); - } - return 0; - - case DEX_DESKTOPCONFIGURATIONCHANGED: - for (std::set<DexpotMeasure*>::iterator i = DexpotMeasures.begin(); i != DexpotMeasures.end(); ++i) - { - (*i)->OnDesktopConfigurationChanged(); - } - return 0; - - case WM_COPYDATA: - if ((HWND) wParam == hWndDexpot) - { - COPYDATASTRUCT *cds = (COPYDATASTRUCT*) lParam; - switch(LOWORD(cds->dwData)) - { - case DEX_GETDESKTOPTITLE: - DexpotDesktopNameMeasure::SetDesktopName(HIWORD(cds->dwData), std::wstring((LPTSTR) cds->lpData)); - break; - case DEX_GETDESKTOPWALLPAPER: - DexpotDesktopWallpaperMeasure::SetDesktopWallpaper(HIWORD(cds->dwData), std::wstring((LPTSTR) cds->lpData)); - break; - } - } - return 0; - - default: - if (message == WM_DEXPOTSTARTED) - { - hWndDexpot = (HWND) wParam; - if (!hWndDexpot) FindDexpotWindow(); - if (hWndDexpot) - { - SendMessage(hWndDexpot, DEX_REGISTERPLUGIN, 0, (LPARAM) hWndMessageWindow); - CurrentDesktop = (int) SendMessage(hWndDexpot, DEX_GETCURRENTDESKTOP, 0, 0); - PluginRegistered = TRUE; - } - for (std::set<DexpotMeasure*>::iterator i = DexpotMeasures.begin(); i != DexpotMeasures.end(); ++i) - { - (*i)->OnDexpotStarted(); - } - return 0; - } - } - - return DefWindowProc(hWnd, message, wParam, lParam); -} - - -/* - * DexpotDesktopCountMeasure - * - */ -DexpotDesktopCountMeasure::DexpotDesktopCountMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {} - -UINT DexpotDesktopCountMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) -{ - DesktopCount = 0; - OnChange = ReadConfigString(section, _T("VDOnChange"), _T("")); - - CountType = Total; - LPCTSTR TypeString = ReadConfigString(section, _T("VDDesktopCount"), _T("")); - if (_tcsicmp(TypeString, _T("X")) == 0) CountType = Columns; - else if (_tcsicmp(TypeString, _T("Y")) == 0) CountType = Rows; - - DexpotMeasure::Initialize(iniFile, section); - return 20; -} - -void DexpotDesktopCountMeasure::InitializeData() -{ - if (PluginRegistered) DesktopCount = (int) SendMessage(hWndDexpot, DEX_GETDESKTOPCOUNT, 0, 0); -} - -UINT DexpotDesktopCountMeasure::Update() -{ - if (CountType == Rows) return 1; - else return DesktopCount; -} - -void DexpotDesktopCountMeasure::OnDesktopCountChanged(int NewCount) -{ - DesktopCount = NewCount; - if (OnChange.length()) SendBang(OnChange); -} - - -/* - * DexpotCurrentDesktopMeasure - * - */ -DexpotCurrentDesktopMeasure::DexpotCurrentDesktopMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {} - -UINT DexpotCurrentDesktopMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) -{ - OnChange = ReadConfigString(section, _T("VDOnChange"), _T("")); - - DexpotMeasure::Initialize(iniFile, section); - return 0; -} - -UINT DexpotCurrentDesktopMeasure::Update() -{ - return CurrentDesktop; -} - -void DexpotCurrentDesktopMeasure::OnSwitched(int FromDesktop, int ToDesktop, WORD Flags, WORD Trigger) -{ - if (OnChange.length()) SendBang(OnChange); -} - - -/* - * DexpotVDMActiveMeasure - * - */ -DexpotVDMActiveMeasure::DexpotVDMActiveMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {}; - -UINT DexpotVDMActiveMeasure::Update() -{ - return PluginRegistered ? 1 : 0; -} - -UINT DexpotVDMActiveMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) -{ - OnActivate = ReadConfigString(section, _T("VDOnActivate"), _T("")); - OnDeactivate = ReadConfigString(section, _T("VDOnDeactivate"), _T("")); - - DexpotMeasure::Initialize(iniFile, section); - return 1; -} - -void DexpotVDMActiveMeasure::OnShutdown() -{ - if (OnDeactivate.length()) SendBang(OnDeactivate); -} - -void DexpotVDMActiveMeasure::OnDexpotStarted() -{ - if (OnActivate.length()) SendBang(OnActivate); -} - - -/* - * DexpotSwitchDesktopMeasure - * - */ -DexpotSwitchDesktopMeasure::DexpotSwitchDesktopMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {} - -void DexpotSwitchDesktopMeasure::ExecuteBang(LPCTSTR args) -{ - if (PluginRegistered) - { - DWORD Desktop; - - if (_tcsicmp(args, _T("next")) == 0) Desktop = MAKELPARAM(0, 1); - else if (_tcsicmp(args, _T("prev")) == 0) Desktop = MAKELPARAM(0, 2); - else if (_tcsicmp(args, _T("back")) == 0) Desktop = MAKELPARAM(0, 3); - else Desktop = _ttoi(args); - - SendNotifyMessage(hWndDexpot, DEX_SWITCHDESKTOP, 0, Desktop); - } -} - - -/* - * DexpotScreenshotMeasure - * - */ -DexpotScreenshotMeasure::DexpotScreenshotMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {} - -UINT DexpotScreenshotMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) -{ - OutputFile = ReadConfigString(section, _T("VDOutputFile"), _T("")); - DesktopNumber = _ttoi(ReadConfigString(section, _T("VDDesktop"), _T("0"))); - Width = _ttoi(ReadConfigString(section, _T("VDWidth"), _T("0"))); - Height = _ttoi(ReadConfigString(section, _T("VDHeight"), _T("0"))); - RefreshOnUpdate = _ttoi(ReadConfigString(section, _T("VDRefreshOnUpdate"), _T("0"))); - - DexpotMeasure::Initialize(iniFile, section); - return 0; -} - -UINT DexpotScreenshotMeasure::Update() -{ - if (RefreshOnUpdate && (DesktopNumber == 0 || DesktopNumber == CurrentDesktop)) - { - UpdateScreenshot(); - } - return 0; -} - -LPCTSTR DexpotScreenshotMeasure::GetString(UINT flags) -{ - return OutputFile.c_str(); -} - -void DexpotScreenshotMeasure::InitializeData() -{ - UpdateScreenshot(); -} - -void DexpotScreenshotMeasure::OnSwitched(int FromDesktop, int ToDesktop, WORD Flags, WORD Trigger) -{ - if (DesktopNumber == FromDesktop || DesktopNumber == 0) - { - UpdateScreenshot(); - } -} - -void DexpotScreenshotMeasure::UpdateScreenshot() -{ - int Desktop = DesktopNumber == 0 ? CurrentDesktop : DesktopNumber; - int nBytes = 0; - BYTE *pBytes = nullptr; - HANDLE fm; - HANDLE mutex; - - if (!IsWindow(hWndDexpot)) return; - - int DesktopWidth = (int) SendMessage(hWndDexpot, DEX_GETDESKTOPWIDTH, Desktop, 0); - int DesktopHeight = (int) SendMessage(hWndDexpot, DEX_GETDESKTOPHEIGHT, Desktop, 0); - - mutex = OpenMutex(SYNCHRONIZE, FALSE, _T("DexpotScreenshotMutex")); - WaitForSingleObject(mutex, 2000); - fm = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, DesktopWidth * DesktopHeight * 4, L"Local\\DexpotScreenshotFilemap"); - pBytes = (BYTE*) MapViewOfFile(fm, FILE_MAP_ALL_ACCESS, 0, 0, 0); - if (pBytes) nBytes = (int) SendMessage(hWndDexpot, DEX_GETSCREENSHOT, Desktop, 0); - - if (nBytes > 0 && nBytes == DesktopWidth * DesktopHeight * 4) - { - HDC ScreenDC; - HDC MemDC; - HDC MemDC2; - HBITMAP OriginalBitmap; - HBITMAP ScaledBitmap; - HGDIOBJ OldBitmap; - HGDIOBJ OldBitmap2; - BYTE *ScaledBytes; - BITMAPINFO bmi; - BITMAPFILEHEADER bmfh; - int ScaledHeight = Height; - int ScaledWidth = Width; - - if (ScaledHeight == 0) ScaledHeight = (int) ((float) DesktopHeight * (ScaledWidth / (float) DesktopWidth) + .5f); - if (ScaledWidth == 0) ScaledWidth = (int) ((float) DesktopWidth * (ScaledHeight / (float) DesktopHeight) + .5f); - if (ScaledHeight == 0) ScaledHeight = DesktopHeight; - if (ScaledWidth == 0) ScaledWidth = DesktopWidth; - - ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = DesktopWidth; - bmi.bmiHeader.biHeight = DesktopHeight; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = nBytes; - - ScreenDC = GetDC(nullptr); - MemDC = CreateCompatibleDC(ScreenDC); - MemDC2 = CreateCompatibleDC(ScreenDC); - OriginalBitmap = CreateCompatibleBitmap(ScreenDC, DesktopWidth, DesktopHeight); - SetDIBits(MemDC2, OriginalBitmap, 0, DesktopHeight, pBytes, &bmi, 0); - OldBitmap2 = SelectObject(MemDC2, (HGDIOBJ) OriginalBitmap); - - nBytes = ScaledWidth * ScaledHeight * 4; - bmi.bmiHeader.biWidth = ScaledWidth; - bmi.bmiHeader.biHeight = ScaledHeight; - bmi.bmiHeader.biSizeImage = nBytes; - - ScaledBitmap = CreateDIBSection(MemDC, &bmi, 0, (void**) &ScaledBytes, nullptr, 0); - OldBitmap = SelectObject(MemDC, (HGDIOBJ) ScaledBitmap); - SetStretchBltMode(MemDC, HALFTONE); - StretchBlt(MemDC, 0, 0, ScaledWidth, ScaledHeight, MemDC2, 0, 0, DesktopWidth, DesktopHeight, SRCCOPY); - GdiFlush(); - - ZeroMemory(&bmfh, sizeof(BITMAPFILEHEADER)); - bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); - bmfh.bfSize = bmfh.bfOffBits + nBytes; - bmfh.bfType = 0x4d42; - - FILE* file = _wfopen(OutputFile.c_str(), L"wb"); - if (file) - { - fwrite(&bmfh, sizeof(BITMAPFILEHEADER), 1, file); - fwrite(&bmi, sizeof(BITMAPINFOHEADER), 1, file); - fwrite(ScaledBytes, nBytes, 1, file); - fclose(file); - } - - SelectObject(MemDC, OldBitmap); - SelectObject(MemDC2, OldBitmap2); - DeleteObject(ScaledBitmap); - DeleteObject(OriginalBitmap); - DeleteDC(MemDC); - DeleteDC(MemDC2); - ReleaseDC(nullptr, ScreenDC); - } - - UnmapViewOfFile(pBytes); - CloseHandle(fm); - ReleaseMutex(mutex); - CloseHandle(mutex); -} - - -/* - * DexpotDesktopNameMeasure - * - */ -DexpotDesktopNameMeasure::DexpotDesktopNameMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {} - -UINT DexpotDesktopNameMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) -{ - DesktopNumber = _ttoi(ReadConfigString(section, _T("VDDesktop"), _T("0"))); - return DexpotMeasure::Initialize(iniFile, section); -} - -LPCTSTR DexpotDesktopNameMeasure::GetString(UINT flags) -{ - UINT Desktop = (DesktopNumber == 0 ? CurrentDesktop : DesktopNumber) - 1; - if (Desktop >= 0 && Desktop < DesktopNames.size()) - { - return DesktopNames[Desktop].c_str(); - } - else - { - StringBuffer[0] = _T('\0'); - return StringBuffer; - } -} - -void DexpotDesktopNameMeasure::InitializeData() -{ - if (PluginRegistered) - { - int DesktopCount = (int) SendMessage(hWndDexpot, DEX_GETDESKTOPCOUNT, 0, 0); - DesktopNames.resize(DesktopCount); - if (DesktopNumber == 0) - { - for (int i = 1; i <= DesktopCount; i++) - { - SendMessage(hWndDexpot, DEX_GETDESKTOPTITLE, i, (LPARAM) hWndMessageWindow); - } - } - else if (DesktopNumber > 0 && DesktopNumber <= DesktopCount) - { - SendMessage(hWndDexpot, DEX_GETDESKTOPTITLE, DesktopNumber, (LPARAM) hWndMessageWindow); - } - } -} - -void DexpotDesktopNameMeasure::OnDesktopConfigurationChanged() -{ - InitializeData(); -} - -void DexpotDesktopNameMeasure::OnDesktopCountChanged(int NewCount) -{ - InitializeData(); -} - -void DexpotDesktopNameMeasure::SetDesktopName(UINT Desktop, std::wstring &Name) -{ - if (--Desktop >= DesktopNames.size()) DesktopNames.resize(Desktop + 1); - if (Desktop >= 0) DesktopNames[Desktop] = Name; -} - - -/* - * DexpotDesktopWallpaperMeasure - * - */ -DexpotDesktopWallpaperMeasure::DexpotDesktopWallpaperMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {} - -UINT DexpotDesktopWallpaperMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) -{ - DesktopNumber = _ttoi(ReadConfigString(section, _T("VDDesktop"), _T("0"))); - return DexpotMeasure::Initialize(iniFile, section); -} - -LPCTSTR DexpotDesktopWallpaperMeasure::GetString(UINT flags) -{ - if (DesktopNumber == 0) - { - SystemParametersInfo(SPI_GETDESKWALLPAPER, STRINGBUFFER_SIZE, StringBuffer, 0); - return StringBuffer; - } - else if (DesktopNumber > 0 && (UINT) DesktopNumber <= DesktopWallpapers.size()) - { - return DesktopWallpapers[DesktopNumber - 1].c_str(); - } - - StringBuffer[0] = _T('\0'); - return StringBuffer; -} - -void DexpotDesktopWallpaperMeasure::InitializeData() -{ - if (PluginRegistered) - { - int DesktopCount = (int) SendMessage(hWndDexpot, DEX_GETDESKTOPCOUNT, 0, 0); - DesktopWallpapers.resize(DesktopCount); - if (DesktopNumber == 0) - { - for (int i = 1; i <= DesktopCount; i++) - { - SendMessage(hWndDexpot, DEX_GETDESKTOPWALLPAPER, i, (LPARAM) hWndMessageWindow); - } - } - else if (DesktopNumber > 0 && DesktopNumber <= DesktopCount) - { - SendMessage(hWndDexpot, DEX_GETDESKTOPWALLPAPER, DesktopNumber, (LPARAM) hWndMessageWindow); - } - } -} -void DexpotDesktopWallpaperMeasure::OnSwitched(int FromDesktop, int ToDesktop, WORD Flags, WORD Trigger) -{ - SendMessage(hWndDexpot, DEX_GETDESKTOPWALLPAPER, FromDesktop, (LPARAM) hWndMessageWindow); -} - -void DexpotDesktopWallpaperMeasure::OnDesktopConfigurationChanged() -{ - InitializeData(); -} - -void DexpotDesktopWallpaperMeasure::OnDesktopCountChanged(int NewCount) -{ - InitializeData(); -} - -void DexpotDesktopWallpaperMeasure::SetDesktopWallpaper(UINT Desktop, std::wstring &Wallpaper) -{ - if (--Desktop >= DesktopWallpapers.size()) DesktopWallpapers.resize(Desktop + 1); - if (Desktop >= 0) DesktopWallpapers[Desktop] = Wallpaper; -} - - -/* - * DexpotCommandMeasure - * - */ -DexpotCommandMeasure::DexpotCommandMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {} - -void DexpotCommandMeasure::ExecuteBang(LPCTSTR args) -{ - if (PluginRegistered) - { - COPYDATASTRUCT cds; - - cds.dwData = DEX_DEXPOTCOMMAND; - cds.lpData = (PVOID) args; - cds.cbData = (DWORD) (_tcslen(args) + 1) * sizeof(TCHAR); - - SendMessage(hWndDexpot, WM_COPYDATA, (WPARAM) hWndMessageWindow, (LPARAM) &cds); - } -} +/* + Copyright (C) 2010-2011 Patrick Dubbert + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "DexpotMeasure.h" + +#include <tchar.h> + +#include "DexpotConstants.h" +#include "../../Library/Export.h" + +int DexpotMeasure::InstanceCount = 0; +HWND DexpotMeasure::hWndDexpot = nullptr; +HWND DexpotMeasure::hWndMessageWindow = nullptr; +std::set<DexpotMeasure*> DexpotMeasure::DexpotMeasures; +TCHAR DexpotMeasure::StringBuffer[STRINGBUFFER_SIZE]; +UINT DexpotMeasure::WM_DEXPOTSTARTED = RegisterWindowMessage(_T("DexpotStarted")); +BOOL DexpotMeasure::PluginRegistered = FALSE; +HWND DexpotMeasure::hWndRainmeterControl = nullptr; +int DexpotMeasure::CurrentDesktop = 0; + +std::vector<std::wstring> DexpotDesktopNameMeasure::DesktopNames; +std::vector<std::wstring> DexpotDesktopWallpaperMeasure::DesktopWallpapers; + +DexpotMeasure::DexpotMeasure(HMODULE instance, UINT _id) : VDMeasure(instance, _id) +{ +} + +DexpotMeasure* DexpotMeasure::CreateMeasure(HMODULE instance, UINT id, LPCTSTR iniFile, LPCTSTR section) +{ + std::wstring TypeString(ReadConfigString(section, _T("VDMeasureType"), _T(""))); + + if (TypeString == _T("VDMActive")) return new DexpotVDMActiveMeasure(instance, id); + else if (TypeString == _T("DesktopCount")) return new DexpotDesktopCountMeasure(instance, id); + else if (TypeString == _T("CurrentDesktop")) return new DexpotCurrentDesktopMeasure(instance, id); + else if (TypeString == _T("SwitchDesktop")) return new DexpotSwitchDesktopMeasure(instance, id); + else if (TypeString == _T("Screenshot")) return new DexpotScreenshotMeasure(instance, id); + else if (TypeString == _T("DesktopName")) return new DexpotDesktopNameMeasure(instance, id); + else if (TypeString == _T("DesktopWallpaper")) return new DexpotDesktopWallpaperMeasure(instance, id); + else if (TypeString == _T("Command")) return new DexpotCommandMeasure(instance, id); + + return nullptr; +} + +UINT DexpotMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) +{ + if (InstanceCount == 0) + { + hWndRainmeterControl = FindWindow(_T("DummyRainWClass"), _T("Rainmeter control window")); + hWndMessageWindow = CreateMessageWindow(); + } + InstanceCount++; + + if (!PluginRegistered && FindDexpotWindow()) + { + SendNotifyMessage(hWndDexpot, DEX_REGISTERPLUGIN, 0, (LPARAM) hWndMessageWindow); + CurrentDesktop = (int) SendMessage(hWndDexpot, DEX_GETCURRENTDESKTOP, 0, 0); + PluginRegistered = TRUE; + } + + InitializeData(); + DexpotMeasures.insert(this); + + return 0; +} + +void DexpotMeasure::Finalize() +{ + InstanceCount--; + if (InstanceCount == 0) + { + if (PluginRegistered) + { + SendNotifyMessage(hWndDexpot, DEX_UNREGISTERPLUGIN, 0, (LPARAM) hWndMessageWindow); + PluginRegistered = FALSE; + } + DestroyWindow(hWndMessageWindow); + UnregisterClass(_T("DexpotPluginWindowClass"), hInstance); + } + DexpotMeasures.erase(this); +} + +UINT DexpotMeasure::Update() +{ + return 0; +} + +LPCTSTR DexpotMeasure::GetString(UINT flags) +{ + _stprintf_s(StringBuffer, STRINGBUFFER_SIZE, _T("%i"), Update()); + return StringBuffer; +} + +void DexpotMeasure::OnDexpotStarted() +{ + InitializeData(); +} + +BOOL DexpotMeasure::FindDexpotWindow() +{ + if (IsWindow(hWndDexpot)) return TRUE; + hWndDexpot = FindWindow(DEXPOTCLASS, DEXPOTTITLE); + return hWndDexpot != nullptr; +} + +HWND DexpotMeasure::CreateMessageWindow() +{ + WNDCLASS wc; + + ZeroMemory(&wc, sizeof(wc)); + wc.hInstance = hInstance; + wc.lpszClassName = _T("DexpotPluginWindowClass"); + wc.lpfnWndProc = WindowProc; + RegisterClass(&wc); + + HWND hWnd = CreateWindowEx(0, _T("DexpotPluginWindowClass"), _T("Dexpot Rainmeter Plugin"), 0, 0, 0, 0, 0, nullptr, nullptr, hInstance, nullptr); + SetWindowLong(hWnd, GWL_STYLE, 0); + SetWindowPos(hWnd, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); + MoveWindow(hWnd, 0, 0, 0, 0, FALSE); + + return hWnd; +} + +void DexpotMeasure::SendBang(std::wstring &Bang) +{ + COPYDATASTRUCT cds; + + cds.dwData = 1; + cds.cbData = (DWORD) (Bang.length() + 1) * sizeof(wchar_t); + cds.lpData = (PVOID) Bang.c_str(); + + SendMessage(hWndRainmeterControl, WM_COPYDATA, (WPARAM) hWndMessageWindow, (LPARAM) &cds); +} + +LRESULT CALLBACK DexpotMeasure::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case DEX_SWITCHED: + CurrentDesktop = HIWORD(lParam); + for (std::set<DexpotMeasure*>::iterator i = DexpotMeasures.begin(); i != DexpotMeasures.end(); ++i) + { + (*i)->OnSwitched(LOWORD(lParam), HIWORD(lParam), LOWORD(wParam), HIWORD(wParam)); + } + return 0; + + case DEX_DESKTOPCOUNTCHANGED: + for (std::set<DexpotMeasure*>::iterator i = DexpotMeasures.begin(); i != DexpotMeasures.end(); ++i) + { + (*i)->OnDesktopCountChanged((int)wParam); + } + return 0; + + case DEX_SHUTDOWN: + PluginRegistered = FALSE; + for (std::set<DexpotMeasure*>::iterator i = DexpotMeasures.begin(); i != DexpotMeasures.end(); ++i) + { + (*i)->OnShutdown(); + } + return 0; + + case DEX_DESKTOPCONFIGURATIONCHANGED: + for (std::set<DexpotMeasure*>::iterator i = DexpotMeasures.begin(); i != DexpotMeasures.end(); ++i) + { + (*i)->OnDesktopConfigurationChanged(); + } + return 0; + + case WM_COPYDATA: + if ((HWND) wParam == hWndDexpot) + { + COPYDATASTRUCT *cds = (COPYDATASTRUCT*) lParam; + switch(LOWORD(cds->dwData)) + { + case DEX_GETDESKTOPTITLE: + DexpotDesktopNameMeasure::SetDesktopName(HIWORD(cds->dwData), std::wstring((LPTSTR) cds->lpData)); + break; + case DEX_GETDESKTOPWALLPAPER: + DexpotDesktopWallpaperMeasure::SetDesktopWallpaper(HIWORD(cds->dwData), std::wstring((LPTSTR) cds->lpData)); + break; + } + } + return 0; + + default: + if (message == WM_DEXPOTSTARTED) + { + hWndDexpot = (HWND) wParam; + if (!hWndDexpot) FindDexpotWindow(); + if (hWndDexpot) + { + SendMessage(hWndDexpot, DEX_REGISTERPLUGIN, 0, (LPARAM) hWndMessageWindow); + CurrentDesktop = (int) SendMessage(hWndDexpot, DEX_GETCURRENTDESKTOP, 0, 0); + PluginRegistered = TRUE; + } + for (std::set<DexpotMeasure*>::iterator i = DexpotMeasures.begin(); i != DexpotMeasures.end(); ++i) + { + (*i)->OnDexpotStarted(); + } + return 0; + } + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} + + +/* + * DexpotDesktopCountMeasure + * + */ +DexpotDesktopCountMeasure::DexpotDesktopCountMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {} + +UINT DexpotDesktopCountMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) +{ + DesktopCount = 0; + OnChange = ReadConfigString(section, _T("VDOnChange"), _T("")); + + CountType = Total; + LPCTSTR TypeString = ReadConfigString(section, _T("VDDesktopCount"), _T("")); + if (_tcsicmp(TypeString, _T("X")) == 0) CountType = Columns; + else if (_tcsicmp(TypeString, _T("Y")) == 0) CountType = Rows; + + DexpotMeasure::Initialize(iniFile, section); + return 20; +} + +void DexpotDesktopCountMeasure::InitializeData() +{ + if (PluginRegistered) DesktopCount = (int) SendMessage(hWndDexpot, DEX_GETDESKTOPCOUNT, 0, 0); +} + +UINT DexpotDesktopCountMeasure::Update() +{ + if (CountType == Rows) return 1; + else return DesktopCount; +} + +void DexpotDesktopCountMeasure::OnDesktopCountChanged(int NewCount) +{ + DesktopCount = NewCount; + if (OnChange.length()) SendBang(OnChange); +} + + +/* + * DexpotCurrentDesktopMeasure + * + */ +DexpotCurrentDesktopMeasure::DexpotCurrentDesktopMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {} + +UINT DexpotCurrentDesktopMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) +{ + OnChange = ReadConfigString(section, _T("VDOnChange"), _T("")); + + DexpotMeasure::Initialize(iniFile, section); + return 0; +} + +UINT DexpotCurrentDesktopMeasure::Update() +{ + return CurrentDesktop; +} + +void DexpotCurrentDesktopMeasure::OnSwitched(int FromDesktop, int ToDesktop, WORD Flags, WORD Trigger) +{ + if (OnChange.length()) SendBang(OnChange); +} + + +/* + * DexpotVDMActiveMeasure + * + */ +DexpotVDMActiveMeasure::DexpotVDMActiveMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {}; + +UINT DexpotVDMActiveMeasure::Update() +{ + return PluginRegistered ? 1 : 0; +} + +UINT DexpotVDMActiveMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) +{ + OnActivate = ReadConfigString(section, _T("VDOnActivate"), _T("")); + OnDeactivate = ReadConfigString(section, _T("VDOnDeactivate"), _T("")); + + DexpotMeasure::Initialize(iniFile, section); + return 1; +} + +void DexpotVDMActiveMeasure::OnShutdown() +{ + if (OnDeactivate.length()) SendBang(OnDeactivate); +} + +void DexpotVDMActiveMeasure::OnDexpotStarted() +{ + if (OnActivate.length()) SendBang(OnActivate); +} + + +/* + * DexpotSwitchDesktopMeasure + * + */ +DexpotSwitchDesktopMeasure::DexpotSwitchDesktopMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {} + +void DexpotSwitchDesktopMeasure::ExecuteBang(LPCTSTR args) +{ + if (PluginRegistered) + { + DWORD Desktop; + + if (_tcsicmp(args, _T("next")) == 0) Desktop = MAKELPARAM(0, 1); + else if (_tcsicmp(args, _T("prev")) == 0) Desktop = MAKELPARAM(0, 2); + else if (_tcsicmp(args, _T("back")) == 0) Desktop = MAKELPARAM(0, 3); + else Desktop = _ttoi(args); + + SendNotifyMessage(hWndDexpot, DEX_SWITCHDESKTOP, 0, Desktop); + } +} + + +/* + * DexpotScreenshotMeasure + * + */ +DexpotScreenshotMeasure::DexpotScreenshotMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {} + +UINT DexpotScreenshotMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) +{ + OutputFile = ReadConfigString(section, _T("VDOutputFile"), _T("")); + DesktopNumber = _ttoi(ReadConfigString(section, _T("VDDesktop"), _T("0"))); + Width = _ttoi(ReadConfigString(section, _T("VDWidth"), _T("0"))); + Height = _ttoi(ReadConfigString(section, _T("VDHeight"), _T("0"))); + RefreshOnUpdate = _ttoi(ReadConfigString(section, _T("VDRefreshOnUpdate"), _T("0"))); + + DexpotMeasure::Initialize(iniFile, section); + return 0; +} + +UINT DexpotScreenshotMeasure::Update() +{ + if (RefreshOnUpdate && (DesktopNumber == 0 || DesktopNumber == CurrentDesktop)) + { + UpdateScreenshot(); + } + return 0; +} + +LPCTSTR DexpotScreenshotMeasure::GetString(UINT flags) +{ + return OutputFile.c_str(); +} + +void DexpotScreenshotMeasure::InitializeData() +{ + UpdateScreenshot(); +} + +void DexpotScreenshotMeasure::OnSwitched(int FromDesktop, int ToDesktop, WORD Flags, WORD Trigger) +{ + if (DesktopNumber == FromDesktop || DesktopNumber == 0) + { + UpdateScreenshot(); + } +} + +void DexpotScreenshotMeasure::UpdateScreenshot() +{ + int Desktop = DesktopNumber == 0 ? CurrentDesktop : DesktopNumber; + int nBytes = 0; + BYTE *pBytes = nullptr; + HANDLE fm; + HANDLE mutex; + + if (!IsWindow(hWndDexpot)) return; + + int DesktopWidth = (int) SendMessage(hWndDexpot, DEX_GETDESKTOPWIDTH, Desktop, 0); + int DesktopHeight = (int) SendMessage(hWndDexpot, DEX_GETDESKTOPHEIGHT, Desktop, 0); + + mutex = OpenMutex(SYNCHRONIZE, FALSE, _T("DexpotScreenshotMutex")); + WaitForSingleObject(mutex, 2000); + fm = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, DesktopWidth * DesktopHeight * 4, L"Local\\DexpotScreenshotFilemap"); + pBytes = (BYTE*) MapViewOfFile(fm, FILE_MAP_ALL_ACCESS, 0, 0, 0); + if (pBytes) nBytes = (int) SendMessage(hWndDexpot, DEX_GETSCREENSHOT, Desktop, 0); + + if (nBytes > 0 && nBytes == DesktopWidth * DesktopHeight * 4) + { + HDC ScreenDC; + HDC MemDC; + HDC MemDC2; + HBITMAP OriginalBitmap; + HBITMAP ScaledBitmap; + HGDIOBJ OldBitmap; + HGDIOBJ OldBitmap2; + BYTE *ScaledBytes; + BITMAPINFO bmi; + BITMAPFILEHEADER bmfh; + int ScaledHeight = Height; + int ScaledWidth = Width; + + if (ScaledHeight == 0) ScaledHeight = (int) ((float) DesktopHeight * (ScaledWidth / (float) DesktopWidth) + .5f); + if (ScaledWidth == 0) ScaledWidth = (int) ((float) DesktopWidth * (ScaledHeight / (float) DesktopHeight) + .5f); + if (ScaledHeight == 0) ScaledHeight = DesktopHeight; + if (ScaledWidth == 0) ScaledWidth = DesktopWidth; + + ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER)); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = DesktopWidth; + bmi.bmiHeader.biHeight = DesktopHeight; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = nBytes; + + ScreenDC = GetDC(nullptr); + MemDC = CreateCompatibleDC(ScreenDC); + MemDC2 = CreateCompatibleDC(ScreenDC); + OriginalBitmap = CreateCompatibleBitmap(ScreenDC, DesktopWidth, DesktopHeight); + SetDIBits(MemDC2, OriginalBitmap, 0, DesktopHeight, pBytes, &bmi, 0); + OldBitmap2 = SelectObject(MemDC2, (HGDIOBJ) OriginalBitmap); + + nBytes = ScaledWidth * ScaledHeight * 4; + bmi.bmiHeader.biWidth = ScaledWidth; + bmi.bmiHeader.biHeight = ScaledHeight; + bmi.bmiHeader.biSizeImage = nBytes; + + ScaledBitmap = CreateDIBSection(MemDC, &bmi, 0, (void**) &ScaledBytes, nullptr, 0); + OldBitmap = SelectObject(MemDC, (HGDIOBJ) ScaledBitmap); + SetStretchBltMode(MemDC, HALFTONE); + StretchBlt(MemDC, 0, 0, ScaledWidth, ScaledHeight, MemDC2, 0, 0, DesktopWidth, DesktopHeight, SRCCOPY); + GdiFlush(); + + ZeroMemory(&bmfh, sizeof(BITMAPFILEHEADER)); + bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); + bmfh.bfSize = bmfh.bfOffBits + nBytes; + bmfh.bfType = 0x4d42; + + FILE* file = _wfopen(OutputFile.c_str(), L"wb"); + if (file) + { + fwrite(&bmfh, sizeof(BITMAPFILEHEADER), 1, file); + fwrite(&bmi, sizeof(BITMAPINFOHEADER), 1, file); + fwrite(ScaledBytes, nBytes, 1, file); + fclose(file); + } + + SelectObject(MemDC, OldBitmap); + SelectObject(MemDC2, OldBitmap2); + DeleteObject(ScaledBitmap); + DeleteObject(OriginalBitmap); + DeleteDC(MemDC); + DeleteDC(MemDC2); + ReleaseDC(nullptr, ScreenDC); + } + + UnmapViewOfFile(pBytes); + CloseHandle(fm); + ReleaseMutex(mutex); + CloseHandle(mutex); +} + + +/* + * DexpotDesktopNameMeasure + * + */ +DexpotDesktopNameMeasure::DexpotDesktopNameMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {} + +UINT DexpotDesktopNameMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) +{ + DesktopNumber = _ttoi(ReadConfigString(section, _T("VDDesktop"), _T("0"))); + return DexpotMeasure::Initialize(iniFile, section); +} + +LPCTSTR DexpotDesktopNameMeasure::GetString(UINT flags) +{ + UINT Desktop = (DesktopNumber == 0 ? CurrentDesktop : DesktopNumber) - 1; + if (Desktop >= 0 && Desktop < DesktopNames.size()) + { + return DesktopNames[Desktop].c_str(); + } + else + { + StringBuffer[0] = _T('\0'); + return StringBuffer; + } +} + +void DexpotDesktopNameMeasure::InitializeData() +{ + if (PluginRegistered) + { + int DesktopCount = (int) SendMessage(hWndDexpot, DEX_GETDESKTOPCOUNT, 0, 0); + DesktopNames.resize(DesktopCount); + if (DesktopNumber == 0) + { + for (int i = 1; i <= DesktopCount; i++) + { + SendMessage(hWndDexpot, DEX_GETDESKTOPTITLE, i, (LPARAM) hWndMessageWindow); + } + } + else if (DesktopNumber > 0 && DesktopNumber <= DesktopCount) + { + SendMessage(hWndDexpot, DEX_GETDESKTOPTITLE, DesktopNumber, (LPARAM) hWndMessageWindow); + } + } +} + +void DexpotDesktopNameMeasure::OnDesktopConfigurationChanged() +{ + InitializeData(); +} + +void DexpotDesktopNameMeasure::OnDesktopCountChanged(int NewCount) +{ + InitializeData(); +} + +void DexpotDesktopNameMeasure::SetDesktopName(UINT Desktop, std::wstring &Name) +{ + if (--Desktop >= DesktopNames.size()) DesktopNames.resize(Desktop + 1); + if (Desktop >= 0) DesktopNames[Desktop] = Name; +} + + +/* + * DexpotDesktopWallpaperMeasure + * + */ +DexpotDesktopWallpaperMeasure::DexpotDesktopWallpaperMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {} + +UINT DexpotDesktopWallpaperMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) +{ + DesktopNumber = _ttoi(ReadConfigString(section, _T("VDDesktop"), _T("0"))); + return DexpotMeasure::Initialize(iniFile, section); +} + +LPCTSTR DexpotDesktopWallpaperMeasure::GetString(UINT flags) +{ + if (DesktopNumber == 0) + { + SystemParametersInfo(SPI_GETDESKWALLPAPER, STRINGBUFFER_SIZE, StringBuffer, 0); + return StringBuffer; + } + else if (DesktopNumber > 0 && (UINT) DesktopNumber <= DesktopWallpapers.size()) + { + return DesktopWallpapers[DesktopNumber - 1].c_str(); + } + + StringBuffer[0] = _T('\0'); + return StringBuffer; +} + +void DexpotDesktopWallpaperMeasure::InitializeData() +{ + if (PluginRegistered) + { + int DesktopCount = (int) SendMessage(hWndDexpot, DEX_GETDESKTOPCOUNT, 0, 0); + DesktopWallpapers.resize(DesktopCount); + if (DesktopNumber == 0) + { + for (int i = 1; i <= DesktopCount; i++) + { + SendMessage(hWndDexpot, DEX_GETDESKTOPWALLPAPER, i, (LPARAM) hWndMessageWindow); + } + } + else if (DesktopNumber > 0 && DesktopNumber <= DesktopCount) + { + SendMessage(hWndDexpot, DEX_GETDESKTOPWALLPAPER, DesktopNumber, (LPARAM) hWndMessageWindow); + } + } +} +void DexpotDesktopWallpaperMeasure::OnSwitched(int FromDesktop, int ToDesktop, WORD Flags, WORD Trigger) +{ + SendMessage(hWndDexpot, DEX_GETDESKTOPWALLPAPER, FromDesktop, (LPARAM) hWndMessageWindow); +} + +void DexpotDesktopWallpaperMeasure::OnDesktopConfigurationChanged() +{ + InitializeData(); +} + +void DexpotDesktopWallpaperMeasure::OnDesktopCountChanged(int NewCount) +{ + InitializeData(); +} + +void DexpotDesktopWallpaperMeasure::SetDesktopWallpaper(UINT Desktop, std::wstring &Wallpaper) +{ + if (--Desktop >= DesktopWallpapers.size()) DesktopWallpapers.resize(Desktop + 1); + if (Desktop >= 0) DesktopWallpapers[Desktop] = Wallpaper; +} + + +/* + * DexpotCommandMeasure + * + */ +DexpotCommandMeasure::DexpotCommandMeasure(HMODULE instance, UINT id) : DexpotMeasure(instance, id) {} + +void DexpotCommandMeasure::ExecuteBang(LPCTSTR args) +{ + if (PluginRegistered) + { + COPYDATASTRUCT cds; + + cds.dwData = DEX_DEXPOTCOMMAND; + cds.lpData = (PVOID) args; + cds.cbData = (DWORD) (_tcslen(args) + 1) * sizeof(TCHAR); + + SendMessage(hWndDexpot, WM_COPYDATA, (WPARAM) hWndMessageWindow, (LPARAM) &cds); + } +} diff --git a/Plugins/PluginVirtualDesktops/DexpotMeasure.h b/Plugins/PluginVirtualDesktops/DexpotMeasure.h index 54a5ca36..c52b265c 100644 --- a/Plugins/PluginVirtualDesktops/DexpotMeasure.h +++ b/Plugins/PluginVirtualDesktops/DexpotMeasure.h @@ -1,210 +1,210 @@ -/* - Copyright (C) 2010-2011 Patrick Dubbert - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma once -#include "VDMeasure.h" - -#include <windows.h> -#include <map> -#include <set> -#include <vector> -#include <string> - -#define STRINGBUFFER_SIZE MAX_PATH - -class DexpotMeasure : public VDMeasure -{ -public: - DexpotMeasure(HMODULE instance, UINT id); - virtual ~DexpotMeasure(void) {}; - - virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); - virtual void Finalize(); - virtual UINT Update(); - virtual LPCTSTR GetString(UINT flags); - virtual void ExecuteBang(LPCTSTR args) {}; - - static DexpotMeasure* CreateMeasure(HMODULE instance, UINT id, LPCTSTR iniFile, LPCTSTR section); - -protected: - virtual void InitializeData() {}; - virtual void OnSwitched(int FromDesktop, int ToDesktop, WORD Flags, WORD Trigger) {}; - virtual void OnDesktopCountChanged(int) {}; - virtual void OnShutdown() {}; - virtual void OnDexpotStarted(); - virtual void OnDesktopConfigurationChanged() {}; - - static void SendBang(std::wstring&); - - static HWND hWndDexpot; - static HWND hWndMessageWindow; - static TCHAR StringBuffer[STRINGBUFFER_SIZE]; - static BOOL PluginRegistered; - static int CurrentDesktop; - -private: - static BOOL FindDexpotWindow(); - static HWND CreateMessageWindow(); - static LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - - static int InstanceCount; - static HWND hWndRainmeterControl; - static std::set<DexpotMeasure*> DexpotMeasures; - static UINT WM_DEXPOTSTARTED; -}; - - -class DexpotDesktopCountMeasure : public DexpotMeasure -{ -public: - DexpotDesktopCountMeasure(HMODULE instance, UINT id); - virtual ~DexpotDesktopCountMeasure(void) {}; - - virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); - virtual UINT Update(); - virtual void InitializeData(); - virtual void OnDesktopCountChanged(int); - -private: - enum DesktopCountType - { - Total, - Columns, - Rows, - }; - - int DesktopCount; - std::wstring OnChange; - DesktopCountType CountType; -}; - - -class DexpotCurrentDesktopMeasure : public DexpotMeasure -{ -public: - DexpotCurrentDesktopMeasure(HMODULE instance, UINT id); - virtual ~DexpotCurrentDesktopMeasure(void) {}; - - virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); - virtual UINT Update(); - virtual void OnSwitched(int, int, WORD, WORD); - -private: - std::wstring OnChange; -}; - - -class DexpotVDMActiveMeasure : public DexpotMeasure -{ -public: - DexpotVDMActiveMeasure(HMODULE instance, UINT id); - virtual ~DexpotVDMActiveMeasure(void) {}; - - virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); - virtual UINT Update(); - virtual void OnShutdown(); - virtual void OnDexpotStarted(); - -private: - std::wstring OnActivate; - std::wstring OnDeactivate; -}; - - -class DexpotSwitchDesktopMeasure : public DexpotMeasure -{ -public: - DexpotSwitchDesktopMeasure(HMODULE instance, UINT id); - virtual ~DexpotSwitchDesktopMeasure(void) {}; - - virtual void ExecuteBang(LPCTSTR args); -}; - - -class DexpotScreenshotMeasure : public DexpotMeasure -{ -public: - DexpotScreenshotMeasure(HMODULE instance, UINT id); - virtual ~DexpotScreenshotMeasure(void) {}; - - virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); - virtual UINT Update(); - virtual LPCTSTR GetString(UINT flags); - virtual void InitializeData(); - virtual void OnSwitched(int, int, WORD, WORD); - -private: - void UpdateScreenshot(); - - std::wstring OutputFile; - int DesktopNumber; - int Width; - int Height; - BOOL RefreshOnUpdate; -}; - - -class DexpotDesktopNameMeasure : public DexpotMeasure -{ -public: - DexpotDesktopNameMeasure(HMODULE instance, UINT id); - virtual ~DexpotDesktopNameMeasure(void) {}; - - virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); - virtual LPCTSTR GetString(UINT flags); - virtual void InitializeData(); - virtual void OnDesktopConfigurationChanged(); - virtual void OnDesktopCountChanged(int NewCount); - - static void SetDesktopName(UINT Desktop, std::wstring &Name); - -private: - int DesktopNumber; - static std::vector<std::wstring> DesktopNames; -}; - - -class DexpotDesktopWallpaperMeasure : public DexpotMeasure -{ -public: - DexpotDesktopWallpaperMeasure(HMODULE instance, UINT id); - virtual ~DexpotDesktopWallpaperMeasure(void) {}; - - virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); - virtual LPCTSTR GetString(UINT flags); - virtual void InitializeData(); - virtual void OnSwitched(int FromDesktop, int ToDesktop, WORD Flags, WORD Trigger); - virtual void OnDesktopConfigurationChanged(); - virtual void OnDesktopCountChanged(int NewCount); - - static void SetDesktopWallpaper(UINT Desktop, std::wstring &Wallpaper); - -private: - int DesktopNumber; - static std::vector<std::wstring> DesktopWallpapers; -}; - - -class DexpotCommandMeasure : public DexpotMeasure -{ -public: - DexpotCommandMeasure(HMODULE instance, UINT id); - virtual ~DexpotCommandMeasure(void) {}; - - virtual void ExecuteBang(LPCTSTR args); -}; +/* + Copyright (C) 2010-2011 Patrick Dubbert + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#pragma once +#include "VDMeasure.h" + +#include <windows.h> +#include <map> +#include <set> +#include <vector> +#include <string> + +#define STRINGBUFFER_SIZE MAX_PATH + +class DexpotMeasure : public VDMeasure +{ +public: + DexpotMeasure(HMODULE instance, UINT id); + virtual ~DexpotMeasure(void) {}; + + virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); + virtual void Finalize(); + virtual UINT Update(); + virtual LPCTSTR GetString(UINT flags); + virtual void ExecuteBang(LPCTSTR args) {}; + + static DexpotMeasure* CreateMeasure(HMODULE instance, UINT id, LPCTSTR iniFile, LPCTSTR section); + +protected: + virtual void InitializeData() {}; + virtual void OnSwitched(int FromDesktop, int ToDesktop, WORD Flags, WORD Trigger) {}; + virtual void OnDesktopCountChanged(int) {}; + virtual void OnShutdown() {}; + virtual void OnDexpotStarted(); + virtual void OnDesktopConfigurationChanged() {}; + + static void SendBang(std::wstring&); + + static HWND hWndDexpot; + static HWND hWndMessageWindow; + static TCHAR StringBuffer[STRINGBUFFER_SIZE]; + static BOOL PluginRegistered; + static int CurrentDesktop; + +private: + static BOOL FindDexpotWindow(); + static HWND CreateMessageWindow(); + static LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + + static int InstanceCount; + static HWND hWndRainmeterControl; + static std::set<DexpotMeasure*> DexpotMeasures; + static UINT WM_DEXPOTSTARTED; +}; + + +class DexpotDesktopCountMeasure : public DexpotMeasure +{ +public: + DexpotDesktopCountMeasure(HMODULE instance, UINT id); + virtual ~DexpotDesktopCountMeasure(void) {}; + + virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); + virtual UINT Update(); + virtual void InitializeData(); + virtual void OnDesktopCountChanged(int); + +private: + enum DesktopCountType + { + Total, + Columns, + Rows, + }; + + int DesktopCount; + std::wstring OnChange; + DesktopCountType CountType; +}; + + +class DexpotCurrentDesktopMeasure : public DexpotMeasure +{ +public: + DexpotCurrentDesktopMeasure(HMODULE instance, UINT id); + virtual ~DexpotCurrentDesktopMeasure(void) {}; + + virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); + virtual UINT Update(); + virtual void OnSwitched(int, int, WORD, WORD); + +private: + std::wstring OnChange; +}; + + +class DexpotVDMActiveMeasure : public DexpotMeasure +{ +public: + DexpotVDMActiveMeasure(HMODULE instance, UINT id); + virtual ~DexpotVDMActiveMeasure(void) {}; + + virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); + virtual UINT Update(); + virtual void OnShutdown(); + virtual void OnDexpotStarted(); + +private: + std::wstring OnActivate; + std::wstring OnDeactivate; +}; + + +class DexpotSwitchDesktopMeasure : public DexpotMeasure +{ +public: + DexpotSwitchDesktopMeasure(HMODULE instance, UINT id); + virtual ~DexpotSwitchDesktopMeasure(void) {}; + + virtual void ExecuteBang(LPCTSTR args); +}; + + +class DexpotScreenshotMeasure : public DexpotMeasure +{ +public: + DexpotScreenshotMeasure(HMODULE instance, UINT id); + virtual ~DexpotScreenshotMeasure(void) {}; + + virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); + virtual UINT Update(); + virtual LPCTSTR GetString(UINT flags); + virtual void InitializeData(); + virtual void OnSwitched(int, int, WORD, WORD); + +private: + void UpdateScreenshot(); + + std::wstring OutputFile; + int DesktopNumber; + int Width; + int Height; + BOOL RefreshOnUpdate; +}; + + +class DexpotDesktopNameMeasure : public DexpotMeasure +{ +public: + DexpotDesktopNameMeasure(HMODULE instance, UINT id); + virtual ~DexpotDesktopNameMeasure(void) {}; + + virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); + virtual LPCTSTR GetString(UINT flags); + virtual void InitializeData(); + virtual void OnDesktopConfigurationChanged(); + virtual void OnDesktopCountChanged(int NewCount); + + static void SetDesktopName(UINT Desktop, std::wstring &Name); + +private: + int DesktopNumber; + static std::vector<std::wstring> DesktopNames; +}; + + +class DexpotDesktopWallpaperMeasure : public DexpotMeasure +{ +public: + DexpotDesktopWallpaperMeasure(HMODULE instance, UINT id); + virtual ~DexpotDesktopWallpaperMeasure(void) {}; + + virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); + virtual LPCTSTR GetString(UINT flags); + virtual void InitializeData(); + virtual void OnSwitched(int FromDesktop, int ToDesktop, WORD Flags, WORD Trigger); + virtual void OnDesktopConfigurationChanged(); + virtual void OnDesktopCountChanged(int NewCount); + + static void SetDesktopWallpaper(UINT Desktop, std::wstring &Wallpaper); + +private: + int DesktopNumber; + static std::vector<std::wstring> DesktopWallpapers; +}; + + +class DexpotCommandMeasure : public DexpotMeasure +{ +public: + DexpotCommandMeasure(HMODULE instance, UINT id); + virtual ~DexpotCommandMeasure(void) {}; + + virtual void ExecuteBang(LPCTSTR args); +}; diff --git a/Plugins/PluginVirtualDesktops/PluginVirtualDesktops.rc b/Plugins/PluginVirtualDesktops/PluginVirtualDesktops.rc index 12fb79f6..2ba73b5d 100644 --- a/Plugins/PluginVirtualDesktops/PluginVirtualDesktops.rc +++ b/Plugins/PluginVirtualDesktops/PluginVirtualDesktops.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.0.0.0" - VALUE "LegalCopyright", " 2010 - Dexpot GbR" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.0.0.0" + VALUE "LegalCopyright", " 2010 - Dexpot GbR" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginVirtualDesktops/PluginVirtualDesktops.vcxproj b/Plugins/PluginVirtualDesktops/PluginVirtualDesktops.vcxproj index b3894aee..43a464e2 100644 --- a/Plugins/PluginVirtualDesktops/PluginVirtualDesktops.vcxproj +++ b/Plugins/PluginVirtualDesktops/PluginVirtualDesktops.vcxproj @@ -1,44 +1,44 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>VirtualDesktops</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClInclude Include="DexpotConstants.h" /> - <ClInclude Include="DexpotMeasure.h" /> - <ClInclude Include="VirtuaWinMeasure.h" /> - <ClInclude Include="VirtuaWinMessages.h" /> - <ClInclude Include="VDMeasure.h" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="DexpotMeasure.cpp" /> - <ClCompile Include="VirtuaWinMeasure.cpp" /> - <ClCompile Include="VirtualDesktops.cpp" /> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="PluginVirtualDesktops.rc" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>VirtualDesktops</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="DexpotConstants.h" /> + <ClInclude Include="DexpotMeasure.h" /> + <ClInclude Include="VirtuaWinMeasure.h" /> + <ClInclude Include="VirtuaWinMessages.h" /> + <ClInclude Include="VDMeasure.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="DexpotMeasure.cpp" /> + <ClCompile Include="VirtuaWinMeasure.cpp" /> + <ClCompile Include="VirtualDesktops.cpp" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="PluginVirtualDesktops.rc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginVirtualDesktops/PluginVirtualDesktops.vcxproj.filters b/Plugins/PluginVirtualDesktops/PluginVirtualDesktops.vcxproj.filters index 873e9548..c949c609 100644 --- a/Plugins/PluginVirtualDesktops/PluginVirtualDesktops.vcxproj.filters +++ b/Plugins/PluginVirtualDesktops/PluginVirtualDesktops.vcxproj.filters @@ -1,38 +1,38 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="Dexpot"> - <UniqueIdentifier>{33f898cd-3c3c-42a0-9b7c-112f37cd558b}</UniqueIdentifier> - </Filter> - <Filter Include="VirtuaWin"> - <UniqueIdentifier>{9d236685-79d3-4b8c-a7d6-8405dd5d260b}</UniqueIdentifier> - </Filter> - </ItemGroup> - <ItemGroup> - <ClInclude Include="DexpotConstants.h"> - <Filter>Dexpot</Filter> - </ClInclude> - <ClInclude Include="DexpotMeasure.h"> - <Filter>Dexpot</Filter> - </ClInclude> - <ClInclude Include="VirtuaWinMeasure.h"> - <Filter>VirtuaWin</Filter> - </ClInclude> - <ClInclude Include="VirtuaWinMessages.h"> - <Filter>VirtuaWin</Filter> - </ClInclude> - <ClInclude Include="VDMeasure.h" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="DexpotMeasure.cpp"> - <Filter>Dexpot</Filter> - </ClCompile> - <ClCompile Include="VirtuaWinMeasure.cpp"> - <Filter>VirtuaWin</Filter> - </ClCompile> - <ClCompile Include="VirtualDesktops.cpp" /> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="PluginVirtualDesktops.rc" /> - </ItemGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Dexpot"> + <UniqueIdentifier>{33f898cd-3c3c-42a0-9b7c-112f37cd558b}</UniqueIdentifier> + </Filter> + <Filter Include="VirtuaWin"> + <UniqueIdentifier>{9d236685-79d3-4b8c-a7d6-8405dd5d260b}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClInclude Include="DexpotConstants.h"> + <Filter>Dexpot</Filter> + </ClInclude> + <ClInclude Include="DexpotMeasure.h"> + <Filter>Dexpot</Filter> + </ClInclude> + <ClInclude Include="VirtuaWinMeasure.h"> + <Filter>VirtuaWin</Filter> + </ClInclude> + <ClInclude Include="VirtuaWinMessages.h"> + <Filter>VirtuaWin</Filter> + </ClInclude> + <ClInclude Include="VDMeasure.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="DexpotMeasure.cpp"> + <Filter>Dexpot</Filter> + </ClCompile> + <ClCompile Include="VirtuaWinMeasure.cpp"> + <Filter>VirtuaWin</Filter> + </ClCompile> + <ClCompile Include="VirtualDesktops.cpp" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="PluginVirtualDesktops.rc" /> + </ItemGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginVirtualDesktops/VDMeasure.h b/Plugins/PluginVirtualDesktops/VDMeasure.h index fdf98684..c213a5f2 100644 --- a/Plugins/PluginVirtualDesktops/VDMeasure.h +++ b/Plugins/PluginVirtualDesktops/VDMeasure.h @@ -1,65 +1,65 @@ -/* - Copyright (C) 2010 Patrick Dubbert - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma once - -#include <windows.h> - -class VDMeasure -{ -public: - VDMeasure(HMODULE instance, UINT id) { hInstance = instance; ID = id; }; - virtual ~VDMeasure(void) {}; - -/* - This function is called when the measure is initialized. - The function must return the maximum value that can be measured. - The return value can also be 0, which means that Rainmeter will - track the maximum value automatically. The parameters for this - function are: - - iniFile The name of the ini-file (usually Rainmeter.ini) - section The name of the section in the ini-file for this measure -*/ - virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section) = 0; - -/* - If the measure needs to free resources before quitting. - The plugin can export Finalize function, which is called - when Rainmeter quits (or refreshes). -*/ - virtual void Finalize() = 0; - -/* - This function is called when new value should be measured. - The function returns the new value. -*/ - virtual UINT Update() = 0; - -/* - This function is called when the value should be - returned as a string. -*/ - virtual LPCTSTR GetString(UINT flags) = 0; - - virtual void ExecuteBang(LPCTSTR args) = 0; - -protected: - static HMODULE hInstance; - UINT ID; -}; +/* + Copyright (C) 2010 Patrick Dubbert + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include <windows.h> + +class VDMeasure +{ +public: + VDMeasure(HMODULE instance, UINT id) { hInstance = instance; ID = id; }; + virtual ~VDMeasure(void) {}; + +/* + This function is called when the measure is initialized. + The function must return the maximum value that can be measured. + The return value can also be 0, which means that Rainmeter will + track the maximum value automatically. The parameters for this + function are: + + iniFile The name of the ini-file (usually Rainmeter.ini) + section The name of the section in the ini-file for this measure +*/ + virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section) = 0; + +/* + If the measure needs to free resources before quitting. + The plugin can export Finalize function, which is called + when Rainmeter quits (or refreshes). +*/ + virtual void Finalize() = 0; + +/* + This function is called when new value should be measured. + The function returns the new value. +*/ + virtual UINT Update() = 0; + +/* + This function is called when the value should be + returned as a string. +*/ + virtual LPCTSTR GetString(UINT flags) = 0; + + virtual void ExecuteBang(LPCTSTR args) = 0; + +protected: + static HMODULE hInstance; + UINT ID; +}; diff --git a/Plugins/PluginVirtualDesktops/VirtuaWinMeasure.cpp b/Plugins/PluginVirtualDesktops/VirtuaWinMeasure.cpp index 41d328a8..01d022b1 100644 --- a/Plugins/PluginVirtualDesktops/VirtuaWinMeasure.cpp +++ b/Plugins/PluginVirtualDesktops/VirtuaWinMeasure.cpp @@ -1,148 +1,148 @@ -/* - Copyright (C) 2010 Patrick Dubbert - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "VirtuaWinMeasure.h" - -#include <tchar.h> - -#include "VirtuaWinMessages.h" -#include "../../Library/Export.h" - -HWND VirtuaWinMeasure::vwHandle = nullptr; -std::map<std::wstring, VirtuaWinMeasure::MeasureType> VirtuaWinMeasure::StringToType; - -VirtuaWinMeasure::VirtuaWinMeasure(HMODULE instance, UINT id) : VDMeasure(instance, id) -{ - if (StringToType.size() == 0) - { - StringToType.insert(std::make_pair(std::wstring(L"VDMActive"), VDMActive)); - StringToType.insert(std::make_pair(std::wstring(L"DesktopCount"), DesktopCountTotal)); - StringToType.insert(std::make_pair(std::wstring(L"CurrentDesktop"), CurrentDesktop)); - StringToType.insert(std::make_pair(std::wstring(L"SwitchDesktop"), SwitchDesktop)); - } -} - -VirtuaWinMeasure::~VirtuaWinMeasure(void) -{ -} - -UINT VirtuaWinMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) -{ - std::wstring TypeString(ReadConfigString(section, _T("VDMeasureType"), _T(""))); - std::map<std::wstring, MeasureType>::iterator i = StringToType.find(TypeString); - if (i != StringToType.end()) - { - Type = i->second; - } - else - { - Type = Unknown; - } - - switch(Type) - { - case VDMActive: - return 1; - - case DesktopCountTotal: - { - LPCTSTR CountType = ReadConfigString(section, _T("VDDesktopCount"), _T("")); - if (_tcsicmp(CountType, _T("X")) == 0) Type = DesktopCountColumns; - else if (_tcsicmp(CountType, _T("Y")) == 0) Type = DesktopCountRows; - if (FindVirtuaWinWindow()) - { - return (UINT) SendMessage(vwHandle, VW_DESKTOP_SIZE, 0, 0); - } - break; - } - } - - return 0; -} - -void VirtuaWinMeasure::Finalize() -{ -} - -UINT VirtuaWinMeasure::Update() -{ - if (!FindVirtuaWinWindow()) - { - return 0; - } - - switch(Type) - { - case VDMActive: - return 1; - - case DesktopCountColumns: - return (UINT) SendMessage(vwHandle, VW_DESKX, 0, 0); - - case DesktopCountRows: - return (UINT) SendMessage(vwHandle, VW_DESKY, 0, 0); - - case DesktopCountTotal: - return (UINT) SendMessage(vwHandle, VW_DESKX, 0, 0) * (UINT) SendMessage(vwHandle, VW_DESKY, 0, 0); - - case CurrentDesktop: - return (UINT) SendMessage(vwHandle, VW_CURDESK, 0, 0); - } - - return 0; -} - -LPCTSTR VirtuaWinMeasure::GetString(UINT flags) -{ - static TCHAR Buffer[MAX_PATH]; - Buffer[0] = _T('\0'); - - switch(Type) - { - case VDMActive: - case DesktopCountColumns: - case DesktopCountRows: - case DesktopCountTotal: - case CurrentDesktop: - swprintf_s(Buffer, MAX_PATH, L"%i", Update()); - break; - } - - return Buffer; -} - -void VirtuaWinMeasure::ExecuteBang(LPCTSTR args) -{ - INT32 Desktop; - - if (!FindVirtuaWinWindow()) return; - - switch(Type) - { - case SwitchDesktop: - Desktop = _wtoi(args); - SendNotifyMessage(vwHandle, VW_CHANGEDESK, Desktop, 0); - } -} - -BOOL VirtuaWinMeasure::FindVirtuaWinWindow() -{ - if (IsWindow(vwHandle)) return TRUE; - vwHandle = FindWindow(_T("VirtuaWinMainClass"), _T("VirtuaWinMainClass")); - return vwHandle != nullptr; -} +/* + Copyright (C) 2010 Patrick Dubbert + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "VirtuaWinMeasure.h" + +#include <tchar.h> + +#include "VirtuaWinMessages.h" +#include "../../Library/Export.h" + +HWND VirtuaWinMeasure::vwHandle = nullptr; +std::map<std::wstring, VirtuaWinMeasure::MeasureType> VirtuaWinMeasure::StringToType; + +VirtuaWinMeasure::VirtuaWinMeasure(HMODULE instance, UINT id) : VDMeasure(instance, id) +{ + if (StringToType.size() == 0) + { + StringToType.insert(std::make_pair(std::wstring(L"VDMActive"), VDMActive)); + StringToType.insert(std::make_pair(std::wstring(L"DesktopCount"), DesktopCountTotal)); + StringToType.insert(std::make_pair(std::wstring(L"CurrentDesktop"), CurrentDesktop)); + StringToType.insert(std::make_pair(std::wstring(L"SwitchDesktop"), SwitchDesktop)); + } +} + +VirtuaWinMeasure::~VirtuaWinMeasure(void) +{ +} + +UINT VirtuaWinMeasure::Initialize(LPCTSTR iniFile, LPCTSTR section) +{ + std::wstring TypeString(ReadConfigString(section, _T("VDMeasureType"), _T(""))); + std::map<std::wstring, MeasureType>::iterator i = StringToType.find(TypeString); + if (i != StringToType.end()) + { + Type = i->second; + } + else + { + Type = Unknown; + } + + switch(Type) + { + case VDMActive: + return 1; + + case DesktopCountTotal: + { + LPCTSTR CountType = ReadConfigString(section, _T("VDDesktopCount"), _T("")); + if (_tcsicmp(CountType, _T("X")) == 0) Type = DesktopCountColumns; + else if (_tcsicmp(CountType, _T("Y")) == 0) Type = DesktopCountRows; + if (FindVirtuaWinWindow()) + { + return (UINT) SendMessage(vwHandle, VW_DESKTOP_SIZE, 0, 0); + } + break; + } + } + + return 0; +} + +void VirtuaWinMeasure::Finalize() +{ +} + +UINT VirtuaWinMeasure::Update() +{ + if (!FindVirtuaWinWindow()) + { + return 0; + } + + switch(Type) + { + case VDMActive: + return 1; + + case DesktopCountColumns: + return (UINT) SendMessage(vwHandle, VW_DESKX, 0, 0); + + case DesktopCountRows: + return (UINT) SendMessage(vwHandle, VW_DESKY, 0, 0); + + case DesktopCountTotal: + return (UINT) SendMessage(vwHandle, VW_DESKX, 0, 0) * (UINT) SendMessage(vwHandle, VW_DESKY, 0, 0); + + case CurrentDesktop: + return (UINT) SendMessage(vwHandle, VW_CURDESK, 0, 0); + } + + return 0; +} + +LPCTSTR VirtuaWinMeasure::GetString(UINT flags) +{ + static TCHAR Buffer[MAX_PATH]; + Buffer[0] = _T('\0'); + + switch(Type) + { + case VDMActive: + case DesktopCountColumns: + case DesktopCountRows: + case DesktopCountTotal: + case CurrentDesktop: + swprintf_s(Buffer, MAX_PATH, L"%i", Update()); + break; + } + + return Buffer; +} + +void VirtuaWinMeasure::ExecuteBang(LPCTSTR args) +{ + INT32 Desktop; + + if (!FindVirtuaWinWindow()) return; + + switch(Type) + { + case SwitchDesktop: + Desktop = _wtoi(args); + SendNotifyMessage(vwHandle, VW_CHANGEDESK, Desktop, 0); + } +} + +BOOL VirtuaWinMeasure::FindVirtuaWinWindow() +{ + if (IsWindow(vwHandle)) return TRUE; + vwHandle = FindWindow(_T("VirtuaWinMainClass"), _T("VirtuaWinMainClass")); + return vwHandle != nullptr; +} diff --git a/Plugins/PluginVirtualDesktops/VirtuaWinMeasure.h b/Plugins/PluginVirtualDesktops/VirtuaWinMeasure.h index 2eb3504c..86b1dc4d 100644 --- a/Plugins/PluginVirtualDesktops/VirtuaWinMeasure.h +++ b/Plugins/PluginVirtualDesktops/VirtuaWinMeasure.h @@ -1,57 +1,57 @@ -/* - Copyright (C) 2010 Patrick Dubbert - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma once -#include "VDMeasure.h" - -#include <windows.h> -#include <map> -#include <string> - -class VirtuaWinMeasure : - public VDMeasure -{ -public: - VirtuaWinMeasure(HMODULE, UINT id); - virtual ~VirtuaWinMeasure(void); - - virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); - virtual void Finalize(); - virtual UINT Update(); - virtual LPCTSTR GetString(UINT flags); - virtual void ExecuteBang(LPCTSTR args); - -private: - enum MeasureType - { - Unknown, - VDMActive, - DesktopCountRows, - DesktopCountColumns, - DesktopCountTotal, - CurrentDesktop, - SwitchDesktop, - }; - - static BOOL FindVirtuaWinWindow(); - - MeasureType Type; - static std::map<std::wstring, MeasureType> StringToType; - static HWND vwHandle; - -}; +/* + Copyright (C) 2010 Patrick Dubbert + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#pragma once +#include "VDMeasure.h" + +#include <windows.h> +#include <map> +#include <string> + +class VirtuaWinMeasure : + public VDMeasure +{ +public: + VirtuaWinMeasure(HMODULE, UINT id); + virtual ~VirtuaWinMeasure(void); + + virtual UINT Initialize(LPCTSTR iniFile, LPCTSTR section); + virtual void Finalize(); + virtual UINT Update(); + virtual LPCTSTR GetString(UINT flags); + virtual void ExecuteBang(LPCTSTR args); + +private: + enum MeasureType + { + Unknown, + VDMActive, + DesktopCountRows, + DesktopCountColumns, + DesktopCountTotal, + CurrentDesktop, + SwitchDesktop, + }; + + static BOOL FindVirtuaWinWindow(); + + MeasureType Type; + static std::map<std::wstring, MeasureType> StringToType; + static HWND vwHandle; + +}; diff --git a/Plugins/PluginVirtualDesktops/VirtualDesktops.cpp b/Plugins/PluginVirtualDesktops/VirtualDesktops.cpp index c2555577..d05d52a6 100644 --- a/Plugins/PluginVirtualDesktops/VirtualDesktops.cpp +++ b/Plugins/PluginVirtualDesktops/VirtualDesktops.cpp @@ -1,162 +1,162 @@ -/* - Copyright (C) 2010-2011 Patrick Dubbert - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/* - - VirtualDesktops Plugin - ---------------------- - - This plugin aims to give Rainmeter skins access to various virtual desktop - managers through a common interface. The following VDMs are supported: - - * Dexpot - * VirtuaWin - - To add support for another virtual desktop manager, - - 1) implement a new class derived from VDMeasure - 2) include its header file below - 3) add a new case for the "VDManager" config string in the Initialize - funtion below - - Different types of measures are identified using the "VDMeasureType" config - string, i.e. - - [VirtualDesktopsMeasure] - Measure=Plugin - Plugin=VirtualDesktops.dll - VDManager=SomeVDM - VDMeasureType=... - - The following basic measure types have to be implemented: - - * VDMActive: returns 1 when the VDM is running, 0 otherwise - - * DesktopCount: returns the number of virtual desktops available; when - "VDDesktopCount=X" or "VDDesktopCount=Y" is given, returns - the number of columns or rows, respectively, in a grid of - desktops - - * CurrentDesktop: returns the number of the currently active desktop - - * SwitchDesktop: when sent a desktop number as a bang, switches to the - corresponding desktop - - You're welcome to add any other measure types that suit the feature set of - the virtual desktop manager in question. Examples can be found in the - existing implementations. - -*/ - -#include "DexpotMeasure.h" -#include "VirtuaWinMeasure.h" - -#include <windows.h> -#include <tchar.h> -#include <map> - -#include "../../Library/Export.h" - -extern "C" -{ - __declspec(dllexport) UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id); - __declspec(dllexport) void Finalize(HMODULE instance, UINT id); - __declspec(dllexport) UINT Update(UINT id); - __declspec(dllexport) LPCTSTR GetString(UINT id, UINT flags); - __declspec(dllexport) void ExecuteBang(LPCTSTR args, UINT id); - __declspec(dllexport) UINT GetPluginVersion(); - __declspec(dllexport) LPCTSTR GetPluginAuthor(); -} - -std::map<UINT, VDMeasure*> Measures; -HMODULE VDMeasure::hInstance; - -UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id) -{ - VDMeasure *Measure = nullptr; - LPCTSTR VDManager = ReadConfigString(section, _T("VDManager"), _T("")); - - if (_tcsicmp(VDManager, _T("Dexpot")) == 0) - { - Measure = DexpotMeasure::CreateMeasure(instance, id, iniFile, section); - } - else if (_tcsicmp(VDManager, _T("VirtuaWin")) == 0) - { - Measure = new VirtuaWinMeasure(instance, id); - } - - if (Measure) - { - Measures.insert(std::make_pair(id, Measure)); - return Measure->Initialize(iniFile, section); - } - - return 0; -} - -UINT Update(UINT id) -{ - std::map<UINT, VDMeasure*>::iterator i = Measures.find(id); - if (i != Measures.end()) - { - return i->second->Update(); - } - - return 0; -} - -LPCTSTR GetString(UINT id, UINT flags) -{ - std::map<UINT, VDMeasure*>::iterator i = Measures.find(id); - if (i != Measures.end()) - { - return i->second->GetString(flags); - } - - return _T(""); -} - -void ExecuteBang(LPCTSTR args, UINT id) -{ - std::map<UINT, VDMeasure*>::iterator i = Measures.find(id); - if (i != Measures.end()) - { - i->second->ExecuteBang(args); - } -} - -void Finalize(HMODULE instance, UINT id) -{ - std::map<UINT, VDMeasure*>::iterator i = Measures.find(id); - if (i != Measures.end()) - { - i->second->Finalize(); - delete i->second; - Measures.erase(i); - } -} - -UINT GetPluginVersion() -{ - return 1001; -} - -LPCTSTR GetPluginAuthor() -{ - return _T("Dexpot GbR (info@dexpot.de)"); -} +/* + Copyright (C) 2010-2011 Patrick Dubbert + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* + + VirtualDesktops Plugin + ---------------------- + + This plugin aims to give Rainmeter skins access to various virtual desktop + managers through a common interface. The following VDMs are supported: + + * Dexpot + * VirtuaWin + + To add support for another virtual desktop manager, + + 1) implement a new class derived from VDMeasure + 2) include its header file below + 3) add a new case for the "VDManager" config string in the Initialize + funtion below + + Different types of measures are identified using the "VDMeasureType" config + string, i.e. + + [VirtualDesktopsMeasure] + Measure=Plugin + Plugin=VirtualDesktops.dll + VDManager=SomeVDM + VDMeasureType=... + + The following basic measure types have to be implemented: + + * VDMActive: returns 1 when the VDM is running, 0 otherwise + + * DesktopCount: returns the number of virtual desktops available; when + "VDDesktopCount=X" or "VDDesktopCount=Y" is given, returns + the number of columns or rows, respectively, in a grid of + desktops + + * CurrentDesktop: returns the number of the currently active desktop + + * SwitchDesktop: when sent a desktop number as a bang, switches to the + corresponding desktop + + You're welcome to add any other measure types that suit the feature set of + the virtual desktop manager in question. Examples can be found in the + existing implementations. + +*/ + +#include "DexpotMeasure.h" +#include "VirtuaWinMeasure.h" + +#include <windows.h> +#include <tchar.h> +#include <map> + +#include "../../Library/Export.h" + +extern "C" +{ + __declspec(dllexport) UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id); + __declspec(dllexport) void Finalize(HMODULE instance, UINT id); + __declspec(dllexport) UINT Update(UINT id); + __declspec(dllexport) LPCTSTR GetString(UINT id, UINT flags); + __declspec(dllexport) void ExecuteBang(LPCTSTR args, UINT id); + __declspec(dllexport) UINT GetPluginVersion(); + __declspec(dllexport) LPCTSTR GetPluginAuthor(); +} + +std::map<UINT, VDMeasure*> Measures; +HMODULE VDMeasure::hInstance; + +UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id) +{ + VDMeasure *Measure = nullptr; + LPCTSTR VDManager = ReadConfigString(section, _T("VDManager"), _T("")); + + if (_tcsicmp(VDManager, _T("Dexpot")) == 0) + { + Measure = DexpotMeasure::CreateMeasure(instance, id, iniFile, section); + } + else if (_tcsicmp(VDManager, _T("VirtuaWin")) == 0) + { + Measure = new VirtuaWinMeasure(instance, id); + } + + if (Measure) + { + Measures.insert(std::make_pair(id, Measure)); + return Measure->Initialize(iniFile, section); + } + + return 0; +} + +UINT Update(UINT id) +{ + std::map<UINT, VDMeasure*>::iterator i = Measures.find(id); + if (i != Measures.end()) + { + return i->second->Update(); + } + + return 0; +} + +LPCTSTR GetString(UINT id, UINT flags) +{ + std::map<UINT, VDMeasure*>::iterator i = Measures.find(id); + if (i != Measures.end()) + { + return i->second->GetString(flags); + } + + return _T(""); +} + +void ExecuteBang(LPCTSTR args, UINT id) +{ + std::map<UINT, VDMeasure*>::iterator i = Measures.find(id); + if (i != Measures.end()) + { + i->second->ExecuteBang(args); + } +} + +void Finalize(HMODULE instance, UINT id) +{ + std::map<UINT, VDMeasure*>::iterator i = Measures.find(id); + if (i != Measures.end()) + { + i->second->Finalize(); + delete i->second; + Measures.erase(i); + } +} + +UINT GetPluginVersion() +{ + return 1001; +} + +LPCTSTR GetPluginAuthor() +{ + return _T("Dexpot GbR (info@dexpot.de)"); +} diff --git a/Plugins/PluginWebParser/PluginWebParser.rc b/Plugins/PluginWebParser/PluginWebParser.rc index 942993a9..463a9f31 100644 --- a/Plugins/PluginWebParser/PluginWebParser.rc +++ b/Plugins/PluginWebParser/PluginWebParser.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,14,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.14.0.0" - VALUE "LegalCopyright", " 2010 - Rainy" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,14,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.14.0.0" + VALUE "LegalCopyright", " 2010 - Rainy" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginWebParser/PluginWebParser.vcxproj b/Plugins/PluginWebParser/PluginWebParser.vcxproj index ba06026d..aaded0f3 100644 --- a/Plugins/PluginWebParser/PluginWebParser.vcxproj +++ b/Plugins/PluginWebParser/PluginWebParser.vcxproj @@ -1,45 +1,45 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{8B820B9F-C154-417C-A090-42198F2AF496}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>WebParser</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <PreprocessorDefinitions>_USRDLL;HAVE_CONFIG_H;SUPPORT_UTF8;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - <AdditionalDependencies>Urlmon.lib;Wininet.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClInclude Include="..\..\Common\StringUtil.h" /> - <ClInclude Include="..\..\Library\pcre-8.10\config.h" /> - <ClInclude Include="..\..\Library\pcre-8.10\pcre.h" /> - <ClInclude Include="..\..\Library\pcre-8.10\pcre_internal.h" /> - <ClInclude Include="..\..\Library\pcre-8.10\ucp.h" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="..\..\Common\StringUtil.cpp" /> - <ClCompile Include="..\..\Library\pcre-8.10\pcre_globals.c" /> - <ClCompile Include="WebParser.cpp" /> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="PluginWebParser.rc" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{8B820B9F-C154-417C-A090-42198F2AF496}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>WebParser</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <PreprocessorDefinitions>_USRDLL;HAVE_CONFIG_H;SUPPORT_UTF8;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <AdditionalDependencies>Urlmon.lib;Wininet.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="..\..\Common\StringUtil.h" /> + <ClInclude Include="..\..\Library\pcre-8.10\config.h" /> + <ClInclude Include="..\..\Library\pcre-8.10\pcre.h" /> + <ClInclude Include="..\..\Library\pcre-8.10\pcre_internal.h" /> + <ClInclude Include="..\..\Library\pcre-8.10\ucp.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\..\Common\StringUtil.cpp" /> + <ClCompile Include="..\..\Library\pcre-8.10\pcre_globals.c" /> + <ClCompile Include="WebParser.cpp" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="PluginWebParser.rc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginWebParser/PluginWebParser.vcxproj.filters b/Plugins/PluginWebParser/PluginWebParser.vcxproj.filters index 5f27bff9..202658ab 100644 --- a/Plugins/PluginWebParser/PluginWebParser.vcxproj.filters +++ b/Plugins/PluginWebParser/PluginWebParser.vcxproj.filters @@ -1,40 +1,40 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="pcre"> - <UniqueIdentifier>{15b74478-8fbf-4a89-b1ed-5488d059708c}</UniqueIdentifier> - </Filter> - <Filter Include="Common"> - <UniqueIdentifier>{a7ff5ecc-efd3-476f-83b8-d5a327f487b5}</UniqueIdentifier> - </Filter> - </ItemGroup> - <ItemGroup> - <ClInclude Include="..\..\Library\pcre-8.10\config.h"> - <Filter>pcre</Filter> - </ClInclude> - <ClInclude Include="..\..\Library\pcre-8.10\pcre.h"> - <Filter>pcre</Filter> - </ClInclude> - <ClInclude Include="..\..\Library\pcre-8.10\pcre_internal.h"> - <Filter>pcre</Filter> - </ClInclude> - <ClInclude Include="..\..\Library\pcre-8.10\ucp.h"> - <Filter>pcre</Filter> - </ClInclude> - <ClInclude Include="..\..\Common\StringUtil.h"> - <Filter>Common</Filter> - </ClInclude> - </ItemGroup> - <ItemGroup> - <ClCompile Include="WebParser.cpp" /> - <ClCompile Include="..\..\Library\pcre-8.10\pcre_globals.c"> - <Filter>pcre</Filter> - </ClCompile> - <ClCompile Include="..\..\Common\StringUtil.cpp"> - <Filter>Common</Filter> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="PluginWebParser.rc" /> - </ItemGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="pcre"> + <UniqueIdentifier>{15b74478-8fbf-4a89-b1ed-5488d059708c}</UniqueIdentifier> + </Filter> + <Filter Include="Common"> + <UniqueIdentifier>{a7ff5ecc-efd3-476f-83b8-d5a327f487b5}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\..\Library\pcre-8.10\config.h"> + <Filter>pcre</Filter> + </ClInclude> + <ClInclude Include="..\..\Library\pcre-8.10\pcre.h"> + <Filter>pcre</Filter> + </ClInclude> + <ClInclude Include="..\..\Library\pcre-8.10\pcre_internal.h"> + <Filter>pcre</Filter> + </ClInclude> + <ClInclude Include="..\..\Library\pcre-8.10\ucp.h"> + <Filter>pcre</Filter> + </ClInclude> + <ClInclude Include="..\..\Common\StringUtil.h"> + <Filter>Common</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="WebParser.cpp" /> + <ClCompile Include="..\..\Library\pcre-8.10\pcre_globals.c"> + <Filter>pcre</Filter> + </ClCompile> + <ClCompile Include="..\..\Common\StringUtil.cpp"> + <Filter>Common</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="PluginWebParser.rc" /> + </ItemGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginWebParser/WebParser.cpp b/Plugins/PluginWebParser/WebParser.cpp index d3f5d321..5b640ed8 100644 --- a/Plugins/PluginWebParser/WebParser.cpp +++ b/Plugins/PluginWebParser/WebParser.cpp @@ -1,1665 +1,1665 @@ -/* - Copyright (C) 2005 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include <windows.h> -#include <string> -#include <unordered_map> -#include <vector> -#include <algorithm> -#include <Wininet.h> -#include <shlwapi.h> -#include <process.h> -#include "../../Library/pcre-8.10/config.h" -#include "../../Library/pcre-8.10/pcre.h" -#include "../../Common/StringUtil.h" -#include "../API/RainmeterAPI.h" - -void ShowError(void* rm, WCHAR* description); - -class ProxyCachePool -{ -public: - ProxyCachePool(LPCWSTR globalProxyName = nullptr) : - m_GlobalProxyName((globalProxyName && *globalProxyName) ? globalProxyName : L"/auto") - { - m_GlobalProxyCache = new ProxyCache(CreateProxy(m_GlobalProxyName.c_str()), true); - - _wcslwr(&m_GlobalProxyName[0]); - m_CacheMap[m_GlobalProxyName] = m_GlobalProxyCache; - //DebugLog(L"* ADD-GLOBAL: key=%s, handle=0x%p, ref=new", m_GlobalProxyName.c_str(), m_GlobalProxyCache->GetCache()); - } - - ~ProxyCachePool() - { - for (auto iter = m_CacheMap.begin(); iter != m_CacheMap.end(); ++iter) - { - ProxyCache* cache = (*iter).second; - //DebugLog(L"* FORCE-REMOVE: key=%s, global=%i, ref=%i", (*iter).first.c_str(), cache->IsGlobal(), cache->GetRef()); - delete cache; - } - } - - HINTERNET GetCache(const std::wstring& proxyName) - { - ProxyCache* cache = nullptr; - - if (proxyName.empty()) - { - // Use global proxy setting - cache = m_GlobalProxyCache; - } - else - { - std::wstring key = proxyName; - _wcslwr(&key[0]); - - auto iter = m_CacheMap.find(key); - if (iter != m_CacheMap.end()) - { - cache = (*iter).second; - } - else // cache not found - { - // Create new proxy - ProxyCache* cache = new ProxyCache(CreateProxy(proxyName.c_str())); - m_CacheMap[key] = cache; - //DebugLog(L"* ADD: key=%s, handle=0x%p, ref=new", key.c_str(), cache->GetCache()); - return cache->GetCache(); - } - } - - // Use proxy cache - cache->AddRef(); - //DebugLog(L"* ADD-REF: key=%s, handle=0x%p, global=%i, ref=%i", - // cache->IsGlobal() ? m_GlobalProxyName.c_str() : proxyName.c_str(), cache->GetCache(), cache->IsGlobal(), cache->GetRef()); - return cache->GetCache(); - } - - void RemoveCache(const std::wstring& proxyName) - { - std::wstring key = proxyName.empty() ? m_GlobalProxyName : proxyName; - - if (!proxyName.empty()) - { - _wcslwr(&key[0]); - } - - auto iter = m_CacheMap.find(key); - if (iter != m_CacheMap.end()) - { - ProxyCache* cache = (*iter).second; - cache->Release(); - //DebugLog(L"* REMOVE: key=%s, global=%i, ref=%i", key.c_str(), cache->IsGlobal(), cache->GetRef()); - - if (cache->IsInvalid()) - { - //DebugLog(L"* EMPTY-ERASE: key=%s", key.c_str()); - m_CacheMap.erase(iter); - delete cache; - } - } - } - -private: - HINTERNET CreateProxy(LPCWSTR proxyName) - { - DWORD proxyType; - LPCWSTR proxyServer; - - if (_wcsicmp(proxyName, L"/auto") == 0) - { - proxyType = INTERNET_OPEN_TYPE_PRECONFIG; - proxyServer = nullptr; - } - else if (_wcsicmp(proxyName, L"/none") == 0) - { - proxyType = INTERNET_OPEN_TYPE_DIRECT; - proxyServer = nullptr; - } - else - { - proxyType = INTERNET_OPEN_TYPE_PROXY; - proxyServer = proxyName; - } - - HINTERNET handle = InternetOpen(L"Rainmeter WebParser plugin", - proxyType, - proxyServer, - nullptr, - 0); - - if (handle) - { - RmLogF(nullptr, LOG_DEBUG, L"WebParser: ProxyServer=\"%s\" (type=%s, handle=0x%p)", - proxyName, - proxyType == INTERNET_OPEN_TYPE_PRECONFIG ? L"PRECONFIG" : proxyType == INTERNET_OPEN_TYPE_DIRECT ? L"DIRECT" : L"PROXY", - handle); - } - else - { - ShowError(nullptr, L"InternetOpen error"); - } - - return handle; - } - - class ProxyCache - { - public: - ProxyCache(HINTERNET handle, bool isGlobal = false) : m_Handle(handle), m_IsGlobal(isGlobal), m_Ref(1) {} - ~ProxyCache() { Dispose(); } - - void AddRef() { if (!IsInvalid()) { ++m_Ref; } } - void Release() { if (m_Ref > 0) { --m_Ref; } if (IsInvalid()) { Dispose(); } } - - bool IsGlobal() { return m_IsGlobal; } - bool IsInvalid() { return (m_Ref <= 0 && !IsGlobal()); } - //int GetRef() { return m_Ref; } - HINTERNET GetCache() { return m_Handle; } - - private: - ProxyCache() {} - ProxyCache(const ProxyCache& cache) {} - - void Dispose() { if (m_Handle) { InternetCloseHandle(m_Handle); m_Handle = nullptr; } } - - HINTERNET m_Handle; - bool m_IsGlobal; - int m_Ref; - }; - - std::unordered_map<std::wstring, ProxyCache*> m_CacheMap; - ProxyCache* m_GlobalProxyCache; - std::wstring m_GlobalProxyName; -}; - -struct ProxySetting -{ - std::wstring server; - HINTERNET handle; - - ProxySetting() : handle() {} -}; - -struct MeasureData -{ - std::wstring url; - std::wstring regExp; - std::wstring resultString; - std::wstring errorString; - std::wstring finishAction; - std::wstring downloadFolder; - std::wstring downloadFile; - std::wstring downloadedFile; - std::wstring debugFileLocation; - void* rm; - void* skin; - ProxySetting proxy; - HANDLE threadHandle; - HANDLE dlThreadHandle; - int codepage; - int stringIndex; - int stringIndex2; - int decodeCharacterReference; - int debug; - UINT updateRate; - UINT updateCounter; - bool download; - bool forceReload; - - MeasureData() : - rm(), - skin(), - threadHandle(), - dlThreadHandle(), - codepage(), - stringIndex(), - stringIndex2(), - decodeCharacterReference(), - debug(), - updateRate(), - updateCounter(), - download(), - forceReload() - { - } -}; - -BYTE* DownloadUrl(HINTERNET handle, std::wstring& url, DWORD* dataSize, bool forceReload); -unsigned __stdcall NetworkThreadProc(void* pParam); -unsigned __stdcall NetworkDownloadThreadProc(void* pParam); -void ParseData(MeasureData* measure, LPCSTR parseData, DWORD dwSize); - -CRITICAL_SECTION g_CriticalSection; -ProxyCachePool* g_ProxyCachePool = nullptr; -UINT g_InstanceCount = 0; - -static std::vector<MeasureData*> g_Measures; -static bool g_Debug = false; - -static std::unordered_map<std::wstring, WCHAR> g_CERs; - -#define OVECCOUNT 300 // should be a multiple of 3 - -std::string ConvertAsciiToUTF8(LPCSTR str, int strLen, int codepage) -{ - std::string szUTF8; - - if (str && *str) - { - std::wstring wide = StringUtil::Widen(str, strLen, codepage); - if (!wide.empty()) - { - szUTF8.swap(StringUtil::NarrowUTF8(wide)); - } - } - return szUTF8; -} - -void DecodeReferences(std::wstring& str, int opt) -{ - // (opt <= 0 || opt > 3) : Do nothing. - // (opt == 1) : Decode both numeric character references and character entity references. - // (opt == 2) : Decode only numeric character references. - // (opt == 3) : Decode only character entity references. - - if (opt >= 1 && opt <= 3) - { - std::wstring::size_type start = 0; - - while ((start = str.find(L'&', start)) != std::wstring::npos) - { - std::wstring::size_type end, pos; - - if ((end = str.find(L';', start)) == std::wstring::npos) break; - pos = start + 1; - - if (pos == end) // &; - skip - { - start = end + 1; - continue; - } - else if ((end - pos) > 10) // name (or number) is too long - { - ++start; - continue; - } - - if (str[pos] == L'#') // Numeric character reference - { - if (opt == 3 || // Decode only character entity references, - ++pos == end) // &#; - skip - { - start = end + 1; - continue; - } - - int base; - if (str[pos] == L'x' || str[pos] == L'X') - { - if (++pos == end) // &#x; or &#X; - skip - { - start = end + 1; - continue; - } - base = 16; - } - else - { - base = 10; - } - - std::wstring num(str, pos, end - pos); - WCHAR* pch = nullptr; - errno = 0; - long ch = wcstol(num.c_str(), &pch, base); - if (pch == nullptr || *pch != L'\0' || errno == ERANGE || ch <= 0 || ch >= 0xFFFE) // invalid character - { - start = pos; - continue; - } - str.replace(start, end - start + 1, 1, (WCHAR)ch); - ++start; - } - else // Character entity reference - { - if (opt == 2) // Decode only numeric character references - skip - { - start = end + 1; - continue; - } - - std::wstring name(str, pos, end - pos); - - std::unordered_map<std::wstring, WCHAR>::const_iterator iter = g_CERs.find(name); - if (iter != g_CERs.end()) - { - str.replace(start, end - start + 1, 1, (*iter).second); - } - ++start; - } - } - } -} - -void FillCharacterEntityReferences() -{ - struct CER - { - WCHAR* name; - WCHAR ch; - }; - - // List from: - // http://www.w3.org/TR/html4/sgml/entities.html - // http://www.w3.org/TR/xhtml1/#C_16 - static CER entities[] = - { - // for markup-significant and internationalization characters - { L"quot", (WCHAR)34 }, - { L"amp", (WCHAR)38 }, - { L"apos", (WCHAR)39 }, - { L"lt", (WCHAR)60 }, - { L"gt", (WCHAR)62 }, - { L"OElig", (WCHAR)338 }, - { L"oelig", (WCHAR)339 }, - { L"Scaron", (WCHAR)352 }, - { L"scaron", (WCHAR)353 }, - { L"Yuml", (WCHAR)376 }, - { L"circ", (WCHAR)710 }, - { L"tilde", (WCHAR)732 }, - { L"ensp", (WCHAR)8194 }, - { L"emsp", (WCHAR)8195 }, - { L"thinsp", (WCHAR)8201 }, - { L"zwnj", (WCHAR)8204 }, - { L"zwj", (WCHAR)8205 }, - { L"lrm", (WCHAR)8206 }, - { L"rlm", (WCHAR)8207 }, - { L"ndash", (WCHAR)8211 }, - { L"mdash", (WCHAR)8212 }, - { L"lsquo", (WCHAR)8216 }, - { L"rsquo", (WCHAR)8217 }, - { L"sbquo", (WCHAR)8218 }, - { L"ldquo", (WCHAR)8220 }, - { L"rdquo", (WCHAR)8221 }, - { L"bdquo", (WCHAR)8222 }, - { L"dagger", (WCHAR)8224 }, - { L"Dagger", (WCHAR)8225 }, - { L"permil", (WCHAR)8240 }, - { L"lsaquo", (WCHAR)8249 }, - { L"rsaquo", (WCHAR)8250 }, - { L"euro", (WCHAR)8364 }, - - // for ISO 8859-1 characters - { L"nbsp", (WCHAR)160 }, - { L"iexcl", (WCHAR)161 }, - { L"cent", (WCHAR)162 }, - { L"pound", (WCHAR)163 }, - { L"curren", (WCHAR)164 }, - { L"yen", (WCHAR)165 }, - { L"brvbar", (WCHAR)166 }, - { L"sect", (WCHAR)167 }, - { L"uml", (WCHAR)168 }, - { L"copy", (WCHAR)169 }, - { L"ordf", (WCHAR)170 }, - { L"laquo", (WCHAR)171 }, - { L"not", (WCHAR)172 }, - { L"shy", (WCHAR)173 }, - { L"reg", (WCHAR)174 }, - { L"macr", (WCHAR)175 }, - { L"deg", (WCHAR)176 }, - { L"plusmn", (WCHAR)177 }, - { L"sup2", (WCHAR)178 }, - { L"sup3", (WCHAR)179 }, - { L"acute", (WCHAR)180 }, - { L"micro", (WCHAR)181 }, - { L"para", (WCHAR)182 }, - { L"middot", (WCHAR)183 }, - { L"cedil", (WCHAR)184 }, - { L"sup1", (WCHAR)185 }, - { L"ordm", (WCHAR)186 }, - { L"raquo", (WCHAR)187 }, - { L"frac14", (WCHAR)188 }, - { L"frac12", (WCHAR)189 }, - { L"frac34", (WCHAR)190 }, - { L"iquest", (WCHAR)191 }, - { L"Agrave", (WCHAR)192 }, - { L"Aacute", (WCHAR)193 }, - { L"Acirc", (WCHAR)194 }, - { L"Atilde", (WCHAR)195 }, - { L"Auml", (WCHAR)196 }, - { L"Aring", (WCHAR)197 }, - { L"AElig", (WCHAR)198 }, - { L"Ccedil", (WCHAR)199 }, - { L"Egrave", (WCHAR)200 }, - { L"Eacute", (WCHAR)201 }, - { L"Ecirc", (WCHAR)202 }, - { L"Euml", (WCHAR)203 }, - { L"Igrave", (WCHAR)204 }, - { L"Iacute", (WCHAR)205 }, - { L"Icirc", (WCHAR)206 }, - { L"Iuml", (WCHAR)207 }, - { L"ETH", (WCHAR)208 }, - { L"Ntilde", (WCHAR)209 }, - { L"Ograve", (WCHAR)210 }, - { L"Oacute", (WCHAR)211 }, - { L"Ocirc", (WCHAR)212 }, - { L"Otilde", (WCHAR)213 }, - { L"Ouml", (WCHAR)214 }, - { L"times", (WCHAR)215 }, - { L"Oslash", (WCHAR)216 }, - { L"Ugrave", (WCHAR)217 }, - { L"Uacute", (WCHAR)218 }, - { L"Ucirc", (WCHAR)219 }, - { L"Uuml", (WCHAR)220 }, - { L"Yacute", (WCHAR)221 }, - { L"THORN", (WCHAR)222 }, - { L"szlig", (WCHAR)223 }, - { L"agrave", (WCHAR)224 }, - { L"aacute", (WCHAR)225 }, - { L"acirc", (WCHAR)226 }, - { L"atilde", (WCHAR)227 }, - { L"auml", (WCHAR)228 }, - { L"aring", (WCHAR)229 }, - { L"aelig", (WCHAR)230 }, - { L"ccedil", (WCHAR)231 }, - { L"egrave", (WCHAR)232 }, - { L"eacute", (WCHAR)233 }, - { L"ecirc", (WCHAR)234 }, - { L"euml", (WCHAR)235 }, - { L"igrave", (WCHAR)236 }, - { L"iacute", (WCHAR)237 }, - { L"icirc", (WCHAR)238 }, - { L"iuml", (WCHAR)239 }, - { L"eth", (WCHAR)240 }, - { L"ntilde", (WCHAR)241 }, - { L"ograve", (WCHAR)242 }, - { L"oacute", (WCHAR)243 }, - { L"ocirc", (WCHAR)244 }, - { L"otilde", (WCHAR)245 }, - { L"ouml", (WCHAR)246 }, - { L"divide", (WCHAR)247 }, - { L"oslash", (WCHAR)248 }, - { L"ugrave", (WCHAR)249 }, - { L"uacute", (WCHAR)250 }, - { L"ucirc", (WCHAR)251 }, - { L"uuml", (WCHAR)252 }, - { L"yacute", (WCHAR)253 }, - { L"thorn", (WCHAR)254 }, - { L"yuml", (WCHAR)255 }, - - // for symbols, mathematical symbols, and Greek letters - { L"fnof", (WCHAR)402 }, - { L"Alpha", (WCHAR)913 }, - { L"Beta", (WCHAR)914 }, - { L"Gamma", (WCHAR)915 }, - { L"Delta", (WCHAR)916 }, - { L"Epsilon", (WCHAR)917 }, - { L"Zeta", (WCHAR)918 }, - { L"Eta", (WCHAR)919 }, - { L"Theta", (WCHAR)920 }, - { L"Iota", (WCHAR)921 }, - { L"Kappa", (WCHAR)922 }, - { L"Lambda", (WCHAR)923 }, - { L"Mu", (WCHAR)924 }, - { L"Nu", (WCHAR)925 }, - { L"Xi", (WCHAR)926 }, - { L"Omicron", (WCHAR)927 }, - { L"Pi", (WCHAR)928 }, - { L"Rho", (WCHAR)929 }, - { L"Sigma", (WCHAR)931 }, - { L"Tau", (WCHAR)932 }, - { L"Upsilon", (WCHAR)933 }, - { L"Phi", (WCHAR)934 }, - { L"Chi", (WCHAR)935 }, - { L"Psi", (WCHAR)936 }, - { L"Omega", (WCHAR)937 }, - { L"alpha", (WCHAR)945 }, - { L"beta", (WCHAR)946 }, - { L"gamma", (WCHAR)947 }, - { L"delta", (WCHAR)948 }, - { L"epsilon", (WCHAR)949 }, - { L"zeta", (WCHAR)950 }, - { L"eta", (WCHAR)951 }, - { L"theta", (WCHAR)952 }, - { L"iota", (WCHAR)953 }, - { L"kappa", (WCHAR)954 }, - { L"lambda", (WCHAR)955 }, - { L"mu", (WCHAR)956 }, - { L"nu", (WCHAR)957 }, - { L"xi", (WCHAR)958 }, - { L"omicron", (WCHAR)959 }, - { L"pi", (WCHAR)960 }, - { L"rho", (WCHAR)961 }, - { L"sigmaf", (WCHAR)962 }, - { L"sigma", (WCHAR)963 }, - { L"tau", (WCHAR)964 }, - { L"upsilon", (WCHAR)965 }, - { L"phi", (WCHAR)966 }, - { L"chi", (WCHAR)967 }, - { L"psi", (WCHAR)968 }, - { L"omega", (WCHAR)969 }, - { L"thetasym", (WCHAR)977 }, - { L"upsih", (WCHAR)978 }, - { L"piv", (WCHAR)982 }, - { L"bull", (WCHAR)8226 }, - { L"hellip", (WCHAR)8230 }, - { L"prime", (WCHAR)8242 }, - { L"Prime", (WCHAR)8243 }, - { L"oline", (WCHAR)8254 }, - { L"frasl", (WCHAR)8260 }, - { L"weierp", (WCHAR)8472 }, - { L"image", (WCHAR)8465 }, - { L"real", (WCHAR)8476 }, - { L"trade", (WCHAR)8482 }, - { L"alefsym", (WCHAR)8501 }, - { L"larr", (WCHAR)8592 }, - { L"uarr", (WCHAR)8593 }, - { L"rarr", (WCHAR)8594 }, - { L"darr", (WCHAR)8595 }, - { L"harr", (WCHAR)8596 }, - { L"crarr", (WCHAR)8629 }, - { L"lArr", (WCHAR)8656 }, - { L"uArr", (WCHAR)8657 }, - { L"rArr", (WCHAR)8658 }, - { L"dArr", (WCHAR)8659 }, - { L"hArr", (WCHAR)8660 }, - { L"forall", (WCHAR)8704 }, - { L"part", (WCHAR)8706 }, - { L"exist", (WCHAR)8707 }, - { L"empty", (WCHAR)8709 }, - { L"nabla", (WCHAR)8711 }, - { L"isin", (WCHAR)8712 }, - { L"notin", (WCHAR)8713 }, - { L"ni", (WCHAR)8715 }, - { L"prod", (WCHAR)8719 }, - { L"sum", (WCHAR)8721 }, - { L"minus", (WCHAR)8722 }, - { L"lowast", (WCHAR)8727 }, - { L"radic", (WCHAR)8730 }, - { L"prop", (WCHAR)8733 }, - { L"infin", (WCHAR)8734 }, - { L"ang", (WCHAR)8736 }, - { L"and", (WCHAR)8743 }, - { L"or", (WCHAR)8744 }, - { L"cap", (WCHAR)8745 }, - { L"cup", (WCHAR)8746 }, - { L"int", (WCHAR)8747 }, - { L"there4", (WCHAR)8756 }, - { L"sim", (WCHAR)8764 }, - { L"cong", (WCHAR)8773 }, - { L"asymp", (WCHAR)8776 }, - { L"ne", (WCHAR)8800 }, - { L"equiv", (WCHAR)8801 }, - { L"le", (WCHAR)8804 }, - { L"ge", (WCHAR)8805 }, - { L"sub", (WCHAR)8834 }, - { L"sup", (WCHAR)8835 }, - { L"nsub", (WCHAR)8836 }, - { L"sube", (WCHAR)8838 }, - { L"supe", (WCHAR)8839 }, - { L"oplus", (WCHAR)8853 }, - { L"otimes", (WCHAR)8855 }, - { L"perp", (WCHAR)8869 }, - { L"sdot", (WCHAR)8901 }, - { L"lceil", (WCHAR)8968 }, - { L"rceil", (WCHAR)8969 }, - { L"lfloor", (WCHAR)8970 }, - { L"rfloor", (WCHAR)8971 }, - { L"lang", (WCHAR)9001 }, - { L"rang", (WCHAR)9002 }, - { L"loz", (WCHAR)9674 }, - { L"spades", (WCHAR)9824 }, - { L"clubs", (WCHAR)9827 }, - { L"hearts", (WCHAR)9829 }, - { L"diams", (WCHAR)9830 } - }; - - const int entityCount = _countof(entities); - g_CERs.rehash(entityCount); - for (int i = 0; i < entityCount; ++i) - { - g_CERs.insert(std::pair<std::wstring, WCHAR>(entities[i].name, entities[i].ch)); - } - - // for DEBUG - //std::map<std::wstring, WCHAR>::const_iterator iter = g_CERs.begin(); - //for ( ; iter != g_CERs.end(); ++iter) - //{ - // WCHAR buffer[64]; - // wsprintf(buffer, L"%s - %c", (*iter).first.c_str(), (*iter).second); - // RmLog(LOG_DEBUG, buffer); - //} -} - -void SetupGlobalProxySetting() -{ - if (!g_ProxyCachePool) - { - WCHAR buffer[MAX_PATH] = {0}; - LPCWSTR file = RmGetSettingsFile(); - - GetPrivateProfileString(L"WebParser.dll", L"ProxyServer", nullptr, buffer, MAX_PATH, file); - g_ProxyCachePool = new ProxyCachePool(buffer); - } -} - -void ClearGlobalProxySetting() -{ - delete g_ProxyCachePool; - g_ProxyCachePool = nullptr; -} - -void SetupProxySetting(ProxySetting& setting, void* rm) -{ - if (g_ProxyCachePool) - { - setting.server = RmReadString(rm, L"ProxyServer", L""); - setting.handle = g_ProxyCachePool->GetCache(setting.server); - } -} - -void ClearProxySetting(ProxySetting& setting) -{ - if (g_ProxyCachePool) - { - g_ProxyCachePool->RemoveCache(setting.server); - } - - setting.handle = nullptr; - setting.server.clear(); -} - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - MeasureData* measure = new MeasureData; - *data = measure; - g_Measures.push_back(measure); - - measure->skin = RmGetSkin(rm); - measure->rm = rm; - - if (g_InstanceCount == 0) - { - InitializeCriticalSection(&g_CriticalSection); - FillCharacterEntityReferences(); - - SetupGlobalProxySetting(); - } - - SetupProxySetting(measure->proxy, rm); // No support for DynamicVariables - - ++g_InstanceCount; -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - MeasureData* measure = (MeasureData*)data; - - EnterCriticalSection(&g_CriticalSection); - - /* Read our own settings from the ini-file */ - - std::wstring url = RmReadString(rm, L"Url", L"", FALSE); - - std::wstring::size_type start = 0; - while ((start = url.find(L"[&", start)) != std::wstring::npos) - { - std::wstring::size_type si = start + 1; - std::wstring::size_type end = url.find(L']', si); - if (end == std::wstring::npos) break; - - std::wstring var = L"["; - var.append(url, si + 1, end - si); - - const WCHAR* result = RmReplaceVariables(rm, var.c_str()); - const size_t resultLength = wcslen(result); - url.replace(start, end - start + 1, result, resultLength); - start += resultLength; - } - - measure->url = url; - - measure->regExp = RmReadString(rm, L"RegExp", L""); - measure->finishAction = RmReadString(rm, L"FinishAction", L"", FALSE); - measure->errorString = RmReadString(rm, L"ErrorString", L""); - - int index = RmReadInt(rm, L"StringIndex", 0); - measure->stringIndex = index < 0 ? 0 : index; - - index = RmReadInt(rm, L"StringIndex2", 0); - measure->stringIndex2 = index < 0 ? 0 : index; - - measure->decodeCharacterReference = RmReadInt(rm, L"DecodeCharacterReference", 0); - measure->updateRate = RmReadInt(rm, L"UpdateRate", 600); - measure->forceReload = 0!=RmReadInt(rm, L"ForceReload", 0); - measure->codepage = RmReadInt(rm, L"CodePage", 0); - - measure->download = 0!=RmReadInt(rm, L"Download", 0); - if (measure->download) - { - measure->downloadFolder = RmPathToAbsolute(rm, L"DownloadFile\\"); - measure->downloadFile = RmReadString(rm, L"DownloadFile", L""); - } - else - { - measure->downloadFile.clear(); - } - - measure->debug = RmReadInt(rm, L"Debug", 0); - if (measure->debug == 2) - { - measure->debugFileLocation = RmReadPath(rm, L"Debug2File", L"WebParserDump.txt"); - RmLog(rm, LOG_DEBUG, measure->debugFileLocation.c_str()); - } - - LeaveCriticalSection(&g_CriticalSection); -} - -PLUGIN_EXPORT double Update(void* data) -{ - MeasureData* measure = (MeasureData*)data; - double value = 0; - - if (measure->download && measure->regExp.empty() && measure->url.find(L'[') == std::wstring::npos) - { - // If RegExp is empty download the file that is pointed by the Url - if (measure->dlThreadHandle == 0) - { - if (measure->updateCounter == 0) - { - // Launch a new thread to fetch the web data - unsigned int id; - HANDLE threadHandle = (HANDLE)_beginthreadex(nullptr, 0, NetworkDownloadThreadProc, measure, 0, &id); - if (threadHandle) - { - measure->dlThreadHandle = threadHandle; - } - } - - measure->updateCounter++; - if (measure->updateCounter >= measure->updateRate) - { - measure->updateCounter = 0; - } - } - - // Else download the file pointed by the result string (this is done later) - } - else - { - // Make sure that the thread is not writing to the result at the same time - EnterCriticalSection(&g_CriticalSection); - - if (!measure->resultString.empty()) - { - value = wcstod(measure->resultString.c_str(), nullptr); - } - - LeaveCriticalSection(&g_CriticalSection); - - if (measure->url.size() > 0 && measure->url.find(L'[') == std::wstring::npos) - { - // This is not a reference; need to update. - if (measure->threadHandle == 0 && measure->dlThreadHandle == 0) - { - if (measure->updateCounter == 0) - { - // Launch a new thread to fetch the web data - unsigned int id; - HANDLE threadHandle = (HANDLE)_beginthreadex(nullptr, 0, NetworkThreadProc, measure, 0, &id); - if (threadHandle) - { - measure->threadHandle = threadHandle; - } - } - - measure->updateCounter++; - if (measure->updateCounter >= measure->updateRate) - { - measure->updateCounter = 0; - } - } - } - } - - return value; -} - -// Fetches the data from the net and parses the page -unsigned __stdcall NetworkThreadProc(void* pParam) -{ - MeasureData* measure = (MeasureData*)pParam; - DWORD dwSize = 0; - - RmLogF(measure->rm, LOG_DEBUG, L"WebParser: Fetching: %s", measure->url.c_str()); - BYTE* data = DownloadUrl(measure->proxy.handle, measure->url, &dwSize, measure->forceReload); - if (!data) - { - ShowError(measure->rm, L"Fetch error"); - } - else - { - if (measure->debug == 2) - { - // Dump to a file - - FILE* file = _wfopen(measure->debugFileLocation.c_str(), L"wb"); - if (file) - { - fwrite(data, sizeof(BYTE), dwSize, file); - fclose(file); - } - else - { - RmLog(measure->rm, LOG_ERROR, L"WebParser: Failed to dump debug data"); - } - } - - ParseData(measure, (LPCSTR)data, dwSize); - - free(data); - } - - EnterCriticalSection(&g_CriticalSection); - CloseHandle(measure->threadHandle); - measure->threadHandle = 0; - LeaveCriticalSection(&g_CriticalSection); - - return 0; // thread completed successfully -} - -void ParseData(MeasureData* measure, LPCSTR parseData, DWORD dwSize) -{ - // Parse the value from the data - pcre* re; - const char* error; - int erroffset; - int ovector[OVECCOUNT]; - int rc; - int flags = PCRE_UTF8; - - if (measure->codepage == 0) - { - flags = 0; - } - - // Compile the regular expression in the first argument - re = pcre_compile( - StringUtil::NarrowUTF8(measure->regExp).c_str(), // the pattern - flags, // default options - &error, // for error message - &erroffset, // for error offset - nullptr); // use default character tables - - if (re != nullptr) - { - // Compilation succeeded: match the subject in the second argument - std::string utf8Data; - - if (measure->codepage == 1200) // 1200 = UTF-16LE - { - // Must convert the data to utf8 - utf8Data = StringUtil::NarrowUTF8((LPCWSTR)parseData, dwSize / 2); - parseData = utf8Data.c_str(); - dwSize = (DWORD)utf8Data.length(); - } - else if (measure->codepage != CP_UTF8 && measure->codepage != 0) // 0 = CP_ACP - { - // Must convert the data to utf8 - utf8Data = ConvertAsciiToUTF8(parseData, dwSize, measure->codepage); - parseData = utf8Data.c_str(); - dwSize = (DWORD)utf8Data.length(); - } - - rc = pcre_exec( - re, // the compiled pattern - nullptr, // no extra data - we didn't study the pattern - parseData, // the subject string - dwSize, // the length of the subject - 0, // start at offset 0 in the subject - 0, // default options - ovector, // output vector for substring information - OVECCOUNT); // number of elements in the output vector - - if (rc >= 0) - { - if (rc == 0) - { - // The output vector wasn't big enough - RmLog(measure->rm, LOG_ERROR, L"WebParser: Too many substrings"); - } - else - { - if (measure->stringIndex < rc) - { - if (measure->debug != 0) - { - for (int i = 0; i < rc; ++i) - { - const char* substring_start = parseData + ovector[2 * i]; - int substring_length = ovector[2 * i + 1] - ovector[2 * i]; - substring_length = min(substring_length, 256); - - const std::wstring value = StringUtil::WidenUTF8(substring_start, substring_length); - RmLogF(measure->rm, LOG_DEBUG, L"WebParser: Index %2d: %s", i, value.c_str()); - } - } - - const char* substring_start = parseData + ovector[2 * measure->stringIndex]; - int substring_length = ovector[2 * measure->stringIndex + 1] - ovector[2 * measure->stringIndex]; - - EnterCriticalSection(&g_CriticalSection); - measure->resultString = StringUtil::WidenUTF8(substring_start, substring_length); - DecodeReferences(measure->resultString, measure->decodeCharacterReference); - LeaveCriticalSection(&g_CriticalSection); - } - else - { - RmLog(measure->rm, LOG_WARNING, L"WebParser: Not enough substrings"); - - // Clear the old result - EnterCriticalSection(&g_CriticalSection); - measure->resultString.clear(); - if (measure->download) - { - if (measure->downloadFile.empty()) // cache mode - { - if (!measure->downloadedFile.empty()) - { - // Delete old downloaded file - DeleteFile(measure->downloadedFile.c_str()); - } - } - measure->downloadedFile.clear(); - } - LeaveCriticalSection(&g_CriticalSection); - } - - // Update the references - std::vector<MeasureData*>::iterator i = g_Measures.begin(); - std::wstring compareStr = L"["; - compareStr += RmGetMeasureName(measure->rm); - compareStr += L']'; - for ( ; i != g_Measures.end(); ++i) - { - if (measure->skin == (*i)->skin && - StringUtil::CaseInsensitiveFind((*i)->url, compareStr) != std::wstring::npos) - { - if ((*i)->stringIndex < rc) - { - const char* substring_start = parseData + ovector[2 * (*i)->stringIndex]; - int substring_length = ovector[2 * (*i)->stringIndex + 1] - ovector[2 * (*i)->stringIndex]; - - if (!(*i)->regExp.empty()) - { - // Change the index and parse the substring - int index = (*i)->stringIndex; - (*i)->stringIndex = (*i)->stringIndex2; - ParseData((*i), substring_start, substring_length); - (*i)->stringIndex = index; - } - else - { - // Set the result - EnterCriticalSection(&g_CriticalSection); - - // Substitude the [measure] with result - std::wstring result = StringUtil::WidenUTF8(substring_start, substring_length); - (*i)->resultString = (*i)->url; - (*i)->resultString.replace( - StringUtil::CaseInsensitiveFind((*i)->resultString, compareStr), - compareStr.size(), result); - DecodeReferences((*i)->resultString, (*i)->decodeCharacterReference); - - // Start download threads for the references - if ((*i)->download) - { - // Start the download thread - unsigned int id; - HANDLE threadHandle = (HANDLE)_beginthreadex(nullptr, 0, NetworkDownloadThreadProc, (*i), 0, &id); - if (threadHandle) - { - (*i)->dlThreadHandle = threadHandle; - } - } - - LeaveCriticalSection(&g_CriticalSection); - } - } - else - { - RmLog((*i)->rm, LOG_WARNING, L"WebParser: Not enough substrings"); - - // Clear the old result - EnterCriticalSection(&g_CriticalSection); - (*i)->resultString.clear(); - if ((*i)->download) - { - if ((*i)->downloadFile.empty()) // cache mode - { - if (!(*i)->downloadedFile.empty()) - { - // Delete old downloaded file - DeleteFile((*i)->downloadedFile.c_str()); - } - } - (*i)->downloadedFile.clear(); - } - LeaveCriticalSection(&g_CriticalSection); - } - } - } - } - } - else - { - // Matching failed: handle error cases - RmLogF(measure->rm, LOG_ERROR, L"WebParser: RegExp matching error (%d)", rc); - - EnterCriticalSection(&g_CriticalSection); - measure->resultString = measure->errorString; - - // Update the references - std::vector<MeasureData*>::iterator i = g_Measures.begin(); - std::wstring compareStr = L"["; - compareStr += RmGetMeasureName(measure->rm); - compareStr += L']'; - for ( ; i != g_Measures.end(); ++i) - { - if ((StringUtil::CaseInsensitiveFind((*i)->url, compareStr) != std::wstring::npos) && - (measure->skin == (*i)->skin)) - { - (*i)->resultString = (*i)->errorString; - } - } - LeaveCriticalSection(&g_CriticalSection); - } - - // Release memory used for the compiled pattern - pcre_free(re); - } - else - { - // Compilation failed. - RmLogF(measure->rm, LOG_ERROR, L"WebParser: RegExp error at offset %d: %S", erroffset, error); - } - - if (measure->download) - { - // Start the download thread - unsigned int id; - HANDLE threadHandle = (HANDLE)_beginthreadex(nullptr, 0, NetworkDownloadThreadProc, measure, 0, &id); - if (threadHandle) - { - measure->dlThreadHandle = threadHandle; - } - } - else - { - if (!measure->finishAction.empty()) - { - RmExecute(measure->skin, measure->finishAction.c_str()); - } - } -} - -// Downloads file from the net -unsigned __stdcall NetworkDownloadThreadProc(void* pParam) -{ - MeasureData* measure = (MeasureData*)pParam; - const bool download = !measure->downloadFile.empty(); - bool ready = false; - - std::wstring url; - - if (measure->regExp.empty() && measure->resultString.empty()) - { - if (!measure->url.empty() && measure->url[0] != L'[') - { - url = measure->url; - } - } - else - { - EnterCriticalSection(&g_CriticalSection); - url = measure->resultString; - LeaveCriticalSection(&g_CriticalSection); - - std::wstring::size_type pos = url.find(L':'); - if (pos == std::wstring::npos && !url.empty()) // No protocol - { - // Add the base url to the string - if (url[0] == L'/') - { - // Absolute path - pos = measure->url.find(L'/', 7); // Assume "http://" (=7) - if (pos != std::wstring::npos) - { - std::wstring path(measure->url.substr(0, pos)); - url = path + url; - } - } - else - { - // Relative path - - pos = measure->url.rfind(L'/'); - if (pos != std::wstring::npos) - { - std::wstring path(measure->url.substr(0, pos + 1)); - url = path + url; - } - } - } - } - - if (!url.empty()) - { - // Create the filename - WCHAR buffer[MAX_PATH] = {0}; - std::wstring fullpath, directory; - - if (download) // download mode - { - PathCanonicalize(buffer, measure->downloadFile.c_str()); - - std::wstring path = buffer; - std::wstring::size_type pos = path.find_first_not_of(L'\\'); - if (pos != std::wstring::npos) - { - path.erase(0, pos); - } - - PathCanonicalize(buffer, measure->downloadFolder.c_str()); - CreateDirectory(buffer, nullptr); // Make sure that the folder exists - - wcscat(buffer, path.c_str()); - - if (buffer[wcslen(buffer)-1] != L'\\') // path is a file - { - fullpath = buffer; - PathRemoveFileSpec(buffer); - } - PathAddBackslash(buffer); - } - else // cache mode - { - GetTempPath(MAX_PATH, buffer); - wcscat(buffer, L"Rainmeter-Cache\\"); // "%TEMP%\Rainmeter-Cache\" - } - CreateDirectory(buffer, nullptr); // Make sure that the folder exists - directory = buffer; - - if (fullpath.empty()) - { - fullpath = directory; - - std::wstring::size_type pos2 = url.find_first_of(L"?#"); - std::wstring::size_type pos1 = url.find_last_of(L'/', pos2); - pos1 = (pos1 != std::wstring::npos) ? pos1 + 1 : 0; - - std::wstring name; - if (pos2 != std::wstring::npos) - { - name.assign(url, pos1, pos2 - pos1); - } - else - { - name.assign(url, pos1, url.length() - pos1); - } - - if (!name.empty()) - { - // Replace reserved characters to "_" - pos1 = 0; - while ((pos1 = name.find_first_of(L"\\/:*?\"<>|", pos1)) != std::wstring::npos) - { - name[pos1] = L'_'; - } - fullpath += name; - } - else - { - fullpath += L"index"; - } - } - - ready = true; - - if (download) // download mode - { - if (!PathFileExists(directory.c_str()) || !PathIsDirectory(directory.c_str())) - { - ready = false; - RmLogF( - measure->rm, LOG_ERROR, - L"WebParser: Directory does not exist: %s", directory.c_str()); - } - else if (PathIsDirectory(fullpath.c_str())) - { - ready = false; - RmLogF( - measure->rm, LOG_ERROR, - L"WebParser: Path is a directory, not a file: %s", fullpath.c_str()); - } - else if (PathFileExists(fullpath.c_str())) - { - DWORD attr = GetFileAttributes(fullpath.c_str()); - if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_READONLY)) - { - ready = false; - RmLogF( - measure->rm, LOG_ERROR, - L"WebParser: File is read-only: %s", fullpath.c_str()); - } - } - } - else // cache mode - { - EnterCriticalSection(&g_CriticalSection); - - if (PathFileExists(fullpath.c_str())) - { - std::wstring::size_type pos = fullpath.find_last_of(L'.'); - - std::wstring path, ext; - if (pos != std::wstring::npos) - { - path.assign(fullpath, 0, pos); - ext.assign(fullpath, pos, fullpath.length() - pos); - } - else - { - path = fullpath; - } - - // Assign a serial number - int i = 1; - do - { - wsprintf(buffer, L"_%i", i++); - - fullpath = path; - fullpath += buffer; - if (!ext.empty()) - { - fullpath += ext; - } - } while (PathFileExists(fullpath.c_str())); - } - - // Create empty file - HANDLE hFile = CreateFile(fullpath.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); - - LeaveCriticalSection(&g_CriticalSection); - } - - if (ready) - { - // Delete IE cache before download if "SyncMode5" is not 3 (every visit to the page) - { - // Check "Temporary Internet Files" sync mode (SyncMode5) - // Values: - // Every visit to the page 3 - // Every time you start Internet Explorer 2 - // Automatically (default) 4 - // Never 0 - // http://support.microsoft.com/kb/263070/en - - HKEY hKey; - LONG ret; - DWORD mode; - - ret = RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", 0, KEY_QUERY_VALUE, &hKey); - if (ret == ERROR_SUCCESS) - { - DWORD size = sizeof(mode); - ret = RegQueryValueEx(hKey, L"SyncMode5", nullptr, nullptr, (LPBYTE)&mode, &size); - RegCloseKey(hKey); - } - - if (ret != ERROR_SUCCESS || mode != 3) - { - std::wstring::size_type pos = url.find_first_of(L'#'); - - if (pos != std::wstring::npos) - { - DeleteUrlCacheEntry(url.substr(0, pos).c_str()); - } - else - { - DeleteUrlCacheEntry(url.c_str()); - } - } - } - - RmLogF( - measure->rm, LOG_DEBUG, - L"WebParser: Downloading url '%s' to: %s", url.c_str(), fullpath.c_str()); - - HRESULT resultCoInitialize = CoInitialize(nullptr); // requires before calling URLDownloadToFile function - - // Download the file - HRESULT result = URLDownloadToFile(nullptr, url.c_str(), fullpath.c_str(), 0, nullptr); - if (result == S_OK) - { - EnterCriticalSection(&g_CriticalSection); - - if (!download) // cache mode - { - if (!measure->downloadedFile.empty()) - { - // Delete old downloaded file - DeleteFile(measure->downloadedFile.c_str()); - } - } - - // Convert LFN to 8.3 filename if the path contains blank character - if (fullpath.find_first_of(L' ') != std::wstring::npos) - { - DWORD size = GetShortPathName(fullpath.c_str(), buffer, MAX_PATH); - if (size > 0 && size <= MAX_PATH) - { - fullpath = buffer; - } - } - measure->downloadedFile = fullpath; - - LeaveCriticalSection(&g_CriticalSection); - - if (!measure->finishAction.empty()) - { - RmExecute(measure->skin, measure->finishAction.c_str()); - } - } - else - { - ready = false; - - if (!download) // cache mode - { - // Delete empty file - DeleteFile(fullpath.c_str()); - } - - RmLogF( - measure->rm, LOG_ERROR, - L"WebParser: Download failed (res=0x%08X, COM=0x%08X): %s", - result, resultCoInitialize, url.c_str()); - } - - if (SUCCEEDED(resultCoInitialize)) - { - CoUninitialize(); - } - } - else - { - RmLogF(measure->rm, LOG_ERROR, L"WebParser: Download failed: %s", url.c_str()); - } - } - else - { - RmLog(measure->rm, LOG_ERROR, L"WebParser: Url is empty"); - } - - if (!ready) // download failed - { - EnterCriticalSection(&g_CriticalSection); - - if (!download) // cache mode - { - if (!measure->downloadedFile.empty()) - { - // Delete old downloaded file - DeleteFile(measure->downloadedFile.c_str()); - } - } - - // Clear old downloaded filename - measure->downloadedFile.clear(); - - LeaveCriticalSection(&g_CriticalSection); - } - - EnterCriticalSection(&g_CriticalSection); - CloseHandle(measure->dlThreadHandle); - measure->dlThreadHandle = 0; - LeaveCriticalSection(&g_CriticalSection); - - return 0; // thread completed successfully -} - -PLUGIN_EXPORT LPCWSTR GetString(void* data) -{ - MeasureData* measure = (MeasureData*)data; - static std::wstring resultString; - - EnterCriticalSection(&g_CriticalSection); - if (measure->download) - { - resultString = measure->downloadedFile; - } - else - { - resultString = measure->resultString; - } - LeaveCriticalSection(&g_CriticalSection); - - return resultString.c_str(); -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - MeasureData* measure = (MeasureData*)data; - - if (measure->threadHandle) - { - // Thread is killed inside critical section so that itself is not inside one when it is terminated - EnterCriticalSection(&g_CriticalSection); - - TerminateThread(measure->threadHandle, 0); - measure->threadHandle = nullptr; - - LeaveCriticalSection(&g_CriticalSection); - } - - if (measure->dlThreadHandle) - { - // Thread is killed inside critical section so that itself is not inside one when it is terminated - EnterCriticalSection(&g_CriticalSection); - - TerminateThread(measure->dlThreadHandle, 0); - measure->dlThreadHandle = nullptr; - - LeaveCriticalSection(&g_CriticalSection); - } - - if (measure->downloadFile.empty()) // cache mode - { - if (!measure->downloadedFile.empty()) - { - // Delete the file - DeleteFile(measure->downloadedFile.c_str()); - } - } - - ClearProxySetting(measure->proxy); - - delete measure; - std::vector<MeasureData*>::iterator iter = std::find(g_Measures.begin(), g_Measures.end(), measure); - g_Measures.erase(iter); - - --g_InstanceCount; - if (g_InstanceCount == 0) - { - // Last one, close all handles - ClearGlobalProxySetting(); - - g_CERs.clear(); - - // Last instance deletes the critical section - DeleteCriticalSection(&g_CriticalSection); - } -} - -/* - Downloads the given url and returns the webpage as dynamically allocated string. - You need to free the returned string after use! -*/ -BYTE* DownloadUrl(HINTERNET handle, std::wstring& url, DWORD* dataSize, bool forceReload) -{ - DWORD flags = INTERNET_FLAG_RESYNCHRONIZE; - if (forceReload) - { - flags = INTERNET_FLAG_RELOAD; - } - - HINTERNET hUrlDump = InternetOpenUrl(handle, url.c_str(), nullptr, 0, flags, 0); - if (!hUrlDump) - { - if (_wcsnicmp(url.c_str(), L"file://", 7) == 0) // file scheme - { - const std::string urlACP = StringUtil::Narrow(url); - hUrlDump = InternetOpenUrlA(handle, urlACP.c_str(), nullptr, 0, flags, 0); - } - - if (!hUrlDump) - { - return nullptr; - } - } - - // Allocate buffer with 3 extra bytes for triple null termination in case the string is - // invalid (e.g. when incorrectly using the UTF-16LE codepage for the data). - const int CHUNK_SIZE = 8192; - DWORD bufferSize = CHUNK_SIZE; - BYTE* buffer = (BYTE*)malloc(bufferSize + 3); - *dataSize = 0; - - // Read the data. - do - { - DWORD readSize; - if (!InternetReadFile(hUrlDump, buffer + *dataSize, bufferSize - *dataSize, &readSize)) - { - free(buffer); - InternetCloseHandle(hUrlDump); - return nullptr; - } - else if (readSize == 0) - { - // All data read. - break; - } - - *dataSize += readSize; - - bufferSize += CHUNK_SIZE; - buffer = (BYTE*)realloc(buffer, bufferSize + 3); - } - while (true); - - InternetCloseHandle(hUrlDump); - - // Triple null terminate the buffer. - buffer[*dataSize] = 0; - buffer[*dataSize + 1] = 0; - buffer[*dataSize + 2] = 0; - - return buffer; -} - -/* - Writes the last error to log. -*/ -void ShowError(void* rm, WCHAR* description) -{ - DWORD dwErr = GetLastError(); - if (dwErr == ERROR_INTERNET_EXTENDED_ERROR) - { - WCHAR szBuffer[1024]; - DWORD dwError, dwLen = 1024; - const WCHAR* error = L"Unknown error"; - if (InternetGetLastResponseInfo(&dwError, szBuffer, &dwLen)) - { - error = szBuffer; - dwErr = dwError; - } - - RmLogF(rm, LOG_ERROR, L"WebParser: (%s) %s (ErrorCode=%i)", description, error, dwErr); - } - else - { - LPVOID lpMsgBuf = nullptr; - - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_HMODULE | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS | - FORMAT_MESSAGE_MAX_WIDTH_MASK, - GetModuleHandle(L"wininet"), - dwErr, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - nullptr - ); - - const WCHAR* error = lpMsgBuf ? (WCHAR*)lpMsgBuf : L"Unknown error"; - RmLogF(rm, LOG_ERROR, L"WebParser: (%s) %s (ErrorCode=%i)", description, error, dwErr); - - if (lpMsgBuf) LocalFree(lpMsgBuf); - } -} - -PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) -{ - MeasureData* measure = (MeasureData*)data; - - // Kill the threads (if any) and reset the update counter - if (_wcsicmp(args, L"UPDATE") == 0) - { - if (measure->threadHandle) - { - // Thread is killed inside critical section so that itself is not inside one when it is terminated - EnterCriticalSection(&g_CriticalSection); - - TerminateThread(measure->threadHandle, 0); - measure->threadHandle = nullptr; - - LeaveCriticalSection(&g_CriticalSection); - } - - if (measure->dlThreadHandle) - { - // Thread is killed inside critical section so that itself is not inside one when it is terminated - EnterCriticalSection(&g_CriticalSection); - - TerminateThread(measure->dlThreadHandle, 0); - measure->dlThreadHandle = nullptr; - - LeaveCriticalSection(&g_CriticalSection); - } - - measure->updateCounter = 0; - } -} +/* + Copyright (C) 2005 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <windows.h> +#include <string> +#include <unordered_map> +#include <vector> +#include <algorithm> +#include <Wininet.h> +#include <shlwapi.h> +#include <process.h> +#include "../../Library/pcre-8.10/config.h" +#include "../../Library/pcre-8.10/pcre.h" +#include "../../Common/StringUtil.h" +#include "../API/RainmeterAPI.h" + +void ShowError(void* rm, WCHAR* description); + +class ProxyCachePool +{ +public: + ProxyCachePool(LPCWSTR globalProxyName = nullptr) : + m_GlobalProxyName((globalProxyName && *globalProxyName) ? globalProxyName : L"/auto") + { + m_GlobalProxyCache = new ProxyCache(CreateProxy(m_GlobalProxyName.c_str()), true); + + _wcslwr(&m_GlobalProxyName[0]); + m_CacheMap[m_GlobalProxyName] = m_GlobalProxyCache; + //DebugLog(L"* ADD-GLOBAL: key=%s, handle=0x%p, ref=new", m_GlobalProxyName.c_str(), m_GlobalProxyCache->GetCache()); + } + + ~ProxyCachePool() + { + for (auto iter = m_CacheMap.begin(); iter != m_CacheMap.end(); ++iter) + { + ProxyCache* cache = (*iter).second; + //DebugLog(L"* FORCE-REMOVE: key=%s, global=%i, ref=%i", (*iter).first.c_str(), cache->IsGlobal(), cache->GetRef()); + delete cache; + } + } + + HINTERNET GetCache(const std::wstring& proxyName) + { + ProxyCache* cache = nullptr; + + if (proxyName.empty()) + { + // Use global proxy setting + cache = m_GlobalProxyCache; + } + else + { + std::wstring key = proxyName; + _wcslwr(&key[0]); + + auto iter = m_CacheMap.find(key); + if (iter != m_CacheMap.end()) + { + cache = (*iter).second; + } + else // cache not found + { + // Create new proxy + ProxyCache* cache = new ProxyCache(CreateProxy(proxyName.c_str())); + m_CacheMap[key] = cache; + //DebugLog(L"* ADD: key=%s, handle=0x%p, ref=new", key.c_str(), cache->GetCache()); + return cache->GetCache(); + } + } + + // Use proxy cache + cache->AddRef(); + //DebugLog(L"* ADD-REF: key=%s, handle=0x%p, global=%i, ref=%i", + // cache->IsGlobal() ? m_GlobalProxyName.c_str() : proxyName.c_str(), cache->GetCache(), cache->IsGlobal(), cache->GetRef()); + return cache->GetCache(); + } + + void RemoveCache(const std::wstring& proxyName) + { + std::wstring key = proxyName.empty() ? m_GlobalProxyName : proxyName; + + if (!proxyName.empty()) + { + _wcslwr(&key[0]); + } + + auto iter = m_CacheMap.find(key); + if (iter != m_CacheMap.end()) + { + ProxyCache* cache = (*iter).second; + cache->Release(); + //DebugLog(L"* REMOVE: key=%s, global=%i, ref=%i", key.c_str(), cache->IsGlobal(), cache->GetRef()); + + if (cache->IsInvalid()) + { + //DebugLog(L"* EMPTY-ERASE: key=%s", key.c_str()); + m_CacheMap.erase(iter); + delete cache; + } + } + } + +private: + HINTERNET CreateProxy(LPCWSTR proxyName) + { + DWORD proxyType; + LPCWSTR proxyServer; + + if (_wcsicmp(proxyName, L"/auto") == 0) + { + proxyType = INTERNET_OPEN_TYPE_PRECONFIG; + proxyServer = nullptr; + } + else if (_wcsicmp(proxyName, L"/none") == 0) + { + proxyType = INTERNET_OPEN_TYPE_DIRECT; + proxyServer = nullptr; + } + else + { + proxyType = INTERNET_OPEN_TYPE_PROXY; + proxyServer = proxyName; + } + + HINTERNET handle = InternetOpen(L"Rainmeter WebParser plugin", + proxyType, + proxyServer, + nullptr, + 0); + + if (handle) + { + RmLogF(nullptr, LOG_DEBUG, L"WebParser: ProxyServer=\"%s\" (type=%s, handle=0x%p)", + proxyName, + proxyType == INTERNET_OPEN_TYPE_PRECONFIG ? L"PRECONFIG" : proxyType == INTERNET_OPEN_TYPE_DIRECT ? L"DIRECT" : L"PROXY", + handle); + } + else + { + ShowError(nullptr, L"InternetOpen error"); + } + + return handle; + } + + class ProxyCache + { + public: + ProxyCache(HINTERNET handle, bool isGlobal = false) : m_Handle(handle), m_IsGlobal(isGlobal), m_Ref(1) {} + ~ProxyCache() { Dispose(); } + + void AddRef() { if (!IsInvalid()) { ++m_Ref; } } + void Release() { if (m_Ref > 0) { --m_Ref; } if (IsInvalid()) { Dispose(); } } + + bool IsGlobal() { return m_IsGlobal; } + bool IsInvalid() { return (m_Ref <= 0 && !IsGlobal()); } + //int GetRef() { return m_Ref; } + HINTERNET GetCache() { return m_Handle; } + + private: + ProxyCache() {} + ProxyCache(const ProxyCache& cache) {} + + void Dispose() { if (m_Handle) { InternetCloseHandle(m_Handle); m_Handle = nullptr; } } + + HINTERNET m_Handle; + bool m_IsGlobal; + int m_Ref; + }; + + std::unordered_map<std::wstring, ProxyCache*> m_CacheMap; + ProxyCache* m_GlobalProxyCache; + std::wstring m_GlobalProxyName; +}; + +struct ProxySetting +{ + std::wstring server; + HINTERNET handle; + + ProxySetting() : handle() {} +}; + +struct MeasureData +{ + std::wstring url; + std::wstring regExp; + std::wstring resultString; + std::wstring errorString; + std::wstring finishAction; + std::wstring downloadFolder; + std::wstring downloadFile; + std::wstring downloadedFile; + std::wstring debugFileLocation; + void* rm; + void* skin; + ProxySetting proxy; + HANDLE threadHandle; + HANDLE dlThreadHandle; + int codepage; + int stringIndex; + int stringIndex2; + int decodeCharacterReference; + int debug; + UINT updateRate; + UINT updateCounter; + bool download; + bool forceReload; + + MeasureData() : + rm(), + skin(), + threadHandle(), + dlThreadHandle(), + codepage(), + stringIndex(), + stringIndex2(), + decodeCharacterReference(), + debug(), + updateRate(), + updateCounter(), + download(), + forceReload() + { + } +}; + +BYTE* DownloadUrl(HINTERNET handle, std::wstring& url, DWORD* dataSize, bool forceReload); +unsigned __stdcall NetworkThreadProc(void* pParam); +unsigned __stdcall NetworkDownloadThreadProc(void* pParam); +void ParseData(MeasureData* measure, LPCSTR parseData, DWORD dwSize); + +CRITICAL_SECTION g_CriticalSection; +ProxyCachePool* g_ProxyCachePool = nullptr; +UINT g_InstanceCount = 0; + +static std::vector<MeasureData*> g_Measures; +static bool g_Debug = false; + +static std::unordered_map<std::wstring, WCHAR> g_CERs; + +#define OVECCOUNT 300 // should be a multiple of 3 + +std::string ConvertAsciiToUTF8(LPCSTR str, int strLen, int codepage) +{ + std::string szUTF8; + + if (str && *str) + { + std::wstring wide = StringUtil::Widen(str, strLen, codepage); + if (!wide.empty()) + { + szUTF8.swap(StringUtil::NarrowUTF8(wide)); + } + } + return szUTF8; +} + +void DecodeReferences(std::wstring& str, int opt) +{ + // (opt <= 0 || opt > 3) : Do nothing. + // (opt == 1) : Decode both numeric character references and character entity references. + // (opt == 2) : Decode only numeric character references. + // (opt == 3) : Decode only character entity references. + + if (opt >= 1 && opt <= 3) + { + std::wstring::size_type start = 0; + + while ((start = str.find(L'&', start)) != std::wstring::npos) + { + std::wstring::size_type end, pos; + + if ((end = str.find(L';', start)) == std::wstring::npos) break; + pos = start + 1; + + if (pos == end) // &; - skip + { + start = end + 1; + continue; + } + else if ((end - pos) > 10) // name (or number) is too long + { + ++start; + continue; + } + + if (str[pos] == L'#') // Numeric character reference + { + if (opt == 3 || // Decode only character entity references, + ++pos == end) // &#; - skip + { + start = end + 1; + continue; + } + + int base; + if (str[pos] == L'x' || str[pos] == L'X') + { + if (++pos == end) // &#x; or &#X; - skip + { + start = end + 1; + continue; + } + base = 16; + } + else + { + base = 10; + } + + std::wstring num(str, pos, end - pos); + WCHAR* pch = nullptr; + errno = 0; + long ch = wcstol(num.c_str(), &pch, base); + if (pch == nullptr || *pch != L'\0' || errno == ERANGE || ch <= 0 || ch >= 0xFFFE) // invalid character + { + start = pos; + continue; + } + str.replace(start, end - start + 1, 1, (WCHAR)ch); + ++start; + } + else // Character entity reference + { + if (opt == 2) // Decode only numeric character references - skip + { + start = end + 1; + continue; + } + + std::wstring name(str, pos, end - pos); + + std::unordered_map<std::wstring, WCHAR>::const_iterator iter = g_CERs.find(name); + if (iter != g_CERs.end()) + { + str.replace(start, end - start + 1, 1, (*iter).second); + } + ++start; + } + } + } +} + +void FillCharacterEntityReferences() +{ + struct CER + { + WCHAR* name; + WCHAR ch; + }; + + // List from: + // http://www.w3.org/TR/html4/sgml/entities.html + // http://www.w3.org/TR/xhtml1/#C_16 + static CER entities[] = + { + // for markup-significant and internationalization characters + { L"quot", (WCHAR)34 }, + { L"amp", (WCHAR)38 }, + { L"apos", (WCHAR)39 }, + { L"lt", (WCHAR)60 }, + { L"gt", (WCHAR)62 }, + { L"OElig", (WCHAR)338 }, + { L"oelig", (WCHAR)339 }, + { L"Scaron", (WCHAR)352 }, + { L"scaron", (WCHAR)353 }, + { L"Yuml", (WCHAR)376 }, + { L"circ", (WCHAR)710 }, + { L"tilde", (WCHAR)732 }, + { L"ensp", (WCHAR)8194 }, + { L"emsp", (WCHAR)8195 }, + { L"thinsp", (WCHAR)8201 }, + { L"zwnj", (WCHAR)8204 }, + { L"zwj", (WCHAR)8205 }, + { L"lrm", (WCHAR)8206 }, + { L"rlm", (WCHAR)8207 }, + { L"ndash", (WCHAR)8211 }, + { L"mdash", (WCHAR)8212 }, + { L"lsquo", (WCHAR)8216 }, + { L"rsquo", (WCHAR)8217 }, + { L"sbquo", (WCHAR)8218 }, + { L"ldquo", (WCHAR)8220 }, + { L"rdquo", (WCHAR)8221 }, + { L"bdquo", (WCHAR)8222 }, + { L"dagger", (WCHAR)8224 }, + { L"Dagger", (WCHAR)8225 }, + { L"permil", (WCHAR)8240 }, + { L"lsaquo", (WCHAR)8249 }, + { L"rsaquo", (WCHAR)8250 }, + { L"euro", (WCHAR)8364 }, + + // for ISO 8859-1 characters + { L"nbsp", (WCHAR)160 }, + { L"iexcl", (WCHAR)161 }, + { L"cent", (WCHAR)162 }, + { L"pound", (WCHAR)163 }, + { L"curren", (WCHAR)164 }, + { L"yen", (WCHAR)165 }, + { L"brvbar", (WCHAR)166 }, + { L"sect", (WCHAR)167 }, + { L"uml", (WCHAR)168 }, + { L"copy", (WCHAR)169 }, + { L"ordf", (WCHAR)170 }, + { L"laquo", (WCHAR)171 }, + { L"not", (WCHAR)172 }, + { L"shy", (WCHAR)173 }, + { L"reg", (WCHAR)174 }, + { L"macr", (WCHAR)175 }, + { L"deg", (WCHAR)176 }, + { L"plusmn", (WCHAR)177 }, + { L"sup2", (WCHAR)178 }, + { L"sup3", (WCHAR)179 }, + { L"acute", (WCHAR)180 }, + { L"micro", (WCHAR)181 }, + { L"para", (WCHAR)182 }, + { L"middot", (WCHAR)183 }, + { L"cedil", (WCHAR)184 }, + { L"sup1", (WCHAR)185 }, + { L"ordm", (WCHAR)186 }, + { L"raquo", (WCHAR)187 }, + { L"frac14", (WCHAR)188 }, + { L"frac12", (WCHAR)189 }, + { L"frac34", (WCHAR)190 }, + { L"iquest", (WCHAR)191 }, + { L"Agrave", (WCHAR)192 }, + { L"Aacute", (WCHAR)193 }, + { L"Acirc", (WCHAR)194 }, + { L"Atilde", (WCHAR)195 }, + { L"Auml", (WCHAR)196 }, + { L"Aring", (WCHAR)197 }, + { L"AElig", (WCHAR)198 }, + { L"Ccedil", (WCHAR)199 }, + { L"Egrave", (WCHAR)200 }, + { L"Eacute", (WCHAR)201 }, + { L"Ecirc", (WCHAR)202 }, + { L"Euml", (WCHAR)203 }, + { L"Igrave", (WCHAR)204 }, + { L"Iacute", (WCHAR)205 }, + { L"Icirc", (WCHAR)206 }, + { L"Iuml", (WCHAR)207 }, + { L"ETH", (WCHAR)208 }, + { L"Ntilde", (WCHAR)209 }, + { L"Ograve", (WCHAR)210 }, + { L"Oacute", (WCHAR)211 }, + { L"Ocirc", (WCHAR)212 }, + { L"Otilde", (WCHAR)213 }, + { L"Ouml", (WCHAR)214 }, + { L"times", (WCHAR)215 }, + { L"Oslash", (WCHAR)216 }, + { L"Ugrave", (WCHAR)217 }, + { L"Uacute", (WCHAR)218 }, + { L"Ucirc", (WCHAR)219 }, + { L"Uuml", (WCHAR)220 }, + { L"Yacute", (WCHAR)221 }, + { L"THORN", (WCHAR)222 }, + { L"szlig", (WCHAR)223 }, + { L"agrave", (WCHAR)224 }, + { L"aacute", (WCHAR)225 }, + { L"acirc", (WCHAR)226 }, + { L"atilde", (WCHAR)227 }, + { L"auml", (WCHAR)228 }, + { L"aring", (WCHAR)229 }, + { L"aelig", (WCHAR)230 }, + { L"ccedil", (WCHAR)231 }, + { L"egrave", (WCHAR)232 }, + { L"eacute", (WCHAR)233 }, + { L"ecirc", (WCHAR)234 }, + { L"euml", (WCHAR)235 }, + { L"igrave", (WCHAR)236 }, + { L"iacute", (WCHAR)237 }, + { L"icirc", (WCHAR)238 }, + { L"iuml", (WCHAR)239 }, + { L"eth", (WCHAR)240 }, + { L"ntilde", (WCHAR)241 }, + { L"ograve", (WCHAR)242 }, + { L"oacute", (WCHAR)243 }, + { L"ocirc", (WCHAR)244 }, + { L"otilde", (WCHAR)245 }, + { L"ouml", (WCHAR)246 }, + { L"divide", (WCHAR)247 }, + { L"oslash", (WCHAR)248 }, + { L"ugrave", (WCHAR)249 }, + { L"uacute", (WCHAR)250 }, + { L"ucirc", (WCHAR)251 }, + { L"uuml", (WCHAR)252 }, + { L"yacute", (WCHAR)253 }, + { L"thorn", (WCHAR)254 }, + { L"yuml", (WCHAR)255 }, + + // for symbols, mathematical symbols, and Greek letters + { L"fnof", (WCHAR)402 }, + { L"Alpha", (WCHAR)913 }, + { L"Beta", (WCHAR)914 }, + { L"Gamma", (WCHAR)915 }, + { L"Delta", (WCHAR)916 }, + { L"Epsilon", (WCHAR)917 }, + { L"Zeta", (WCHAR)918 }, + { L"Eta", (WCHAR)919 }, + { L"Theta", (WCHAR)920 }, + { L"Iota", (WCHAR)921 }, + { L"Kappa", (WCHAR)922 }, + { L"Lambda", (WCHAR)923 }, + { L"Mu", (WCHAR)924 }, + { L"Nu", (WCHAR)925 }, + { L"Xi", (WCHAR)926 }, + { L"Omicron", (WCHAR)927 }, + { L"Pi", (WCHAR)928 }, + { L"Rho", (WCHAR)929 }, + { L"Sigma", (WCHAR)931 }, + { L"Tau", (WCHAR)932 }, + { L"Upsilon", (WCHAR)933 }, + { L"Phi", (WCHAR)934 }, + { L"Chi", (WCHAR)935 }, + { L"Psi", (WCHAR)936 }, + { L"Omega", (WCHAR)937 }, + { L"alpha", (WCHAR)945 }, + { L"beta", (WCHAR)946 }, + { L"gamma", (WCHAR)947 }, + { L"delta", (WCHAR)948 }, + { L"epsilon", (WCHAR)949 }, + { L"zeta", (WCHAR)950 }, + { L"eta", (WCHAR)951 }, + { L"theta", (WCHAR)952 }, + { L"iota", (WCHAR)953 }, + { L"kappa", (WCHAR)954 }, + { L"lambda", (WCHAR)955 }, + { L"mu", (WCHAR)956 }, + { L"nu", (WCHAR)957 }, + { L"xi", (WCHAR)958 }, + { L"omicron", (WCHAR)959 }, + { L"pi", (WCHAR)960 }, + { L"rho", (WCHAR)961 }, + { L"sigmaf", (WCHAR)962 }, + { L"sigma", (WCHAR)963 }, + { L"tau", (WCHAR)964 }, + { L"upsilon", (WCHAR)965 }, + { L"phi", (WCHAR)966 }, + { L"chi", (WCHAR)967 }, + { L"psi", (WCHAR)968 }, + { L"omega", (WCHAR)969 }, + { L"thetasym", (WCHAR)977 }, + { L"upsih", (WCHAR)978 }, + { L"piv", (WCHAR)982 }, + { L"bull", (WCHAR)8226 }, + { L"hellip", (WCHAR)8230 }, + { L"prime", (WCHAR)8242 }, + { L"Prime", (WCHAR)8243 }, + { L"oline", (WCHAR)8254 }, + { L"frasl", (WCHAR)8260 }, + { L"weierp", (WCHAR)8472 }, + { L"image", (WCHAR)8465 }, + { L"real", (WCHAR)8476 }, + { L"trade", (WCHAR)8482 }, + { L"alefsym", (WCHAR)8501 }, + { L"larr", (WCHAR)8592 }, + { L"uarr", (WCHAR)8593 }, + { L"rarr", (WCHAR)8594 }, + { L"darr", (WCHAR)8595 }, + { L"harr", (WCHAR)8596 }, + { L"crarr", (WCHAR)8629 }, + { L"lArr", (WCHAR)8656 }, + { L"uArr", (WCHAR)8657 }, + { L"rArr", (WCHAR)8658 }, + { L"dArr", (WCHAR)8659 }, + { L"hArr", (WCHAR)8660 }, + { L"forall", (WCHAR)8704 }, + { L"part", (WCHAR)8706 }, + { L"exist", (WCHAR)8707 }, + { L"empty", (WCHAR)8709 }, + { L"nabla", (WCHAR)8711 }, + { L"isin", (WCHAR)8712 }, + { L"notin", (WCHAR)8713 }, + { L"ni", (WCHAR)8715 }, + { L"prod", (WCHAR)8719 }, + { L"sum", (WCHAR)8721 }, + { L"minus", (WCHAR)8722 }, + { L"lowast", (WCHAR)8727 }, + { L"radic", (WCHAR)8730 }, + { L"prop", (WCHAR)8733 }, + { L"infin", (WCHAR)8734 }, + { L"ang", (WCHAR)8736 }, + { L"and", (WCHAR)8743 }, + { L"or", (WCHAR)8744 }, + { L"cap", (WCHAR)8745 }, + { L"cup", (WCHAR)8746 }, + { L"int", (WCHAR)8747 }, + { L"there4", (WCHAR)8756 }, + { L"sim", (WCHAR)8764 }, + { L"cong", (WCHAR)8773 }, + { L"asymp", (WCHAR)8776 }, + { L"ne", (WCHAR)8800 }, + { L"equiv", (WCHAR)8801 }, + { L"le", (WCHAR)8804 }, + { L"ge", (WCHAR)8805 }, + { L"sub", (WCHAR)8834 }, + { L"sup", (WCHAR)8835 }, + { L"nsub", (WCHAR)8836 }, + { L"sube", (WCHAR)8838 }, + { L"supe", (WCHAR)8839 }, + { L"oplus", (WCHAR)8853 }, + { L"otimes", (WCHAR)8855 }, + { L"perp", (WCHAR)8869 }, + { L"sdot", (WCHAR)8901 }, + { L"lceil", (WCHAR)8968 }, + { L"rceil", (WCHAR)8969 }, + { L"lfloor", (WCHAR)8970 }, + { L"rfloor", (WCHAR)8971 }, + { L"lang", (WCHAR)9001 }, + { L"rang", (WCHAR)9002 }, + { L"loz", (WCHAR)9674 }, + { L"spades", (WCHAR)9824 }, + { L"clubs", (WCHAR)9827 }, + { L"hearts", (WCHAR)9829 }, + { L"diams", (WCHAR)9830 } + }; + + const int entityCount = _countof(entities); + g_CERs.rehash(entityCount); + for (int i = 0; i < entityCount; ++i) + { + g_CERs.insert(std::pair<std::wstring, WCHAR>(entities[i].name, entities[i].ch)); + } + + // for DEBUG + //std::map<std::wstring, WCHAR>::const_iterator iter = g_CERs.begin(); + //for ( ; iter != g_CERs.end(); ++iter) + //{ + // WCHAR buffer[64]; + // wsprintf(buffer, L"%s - %c", (*iter).first.c_str(), (*iter).second); + // RmLog(LOG_DEBUG, buffer); + //} +} + +void SetupGlobalProxySetting() +{ + if (!g_ProxyCachePool) + { + WCHAR buffer[MAX_PATH] = {0}; + LPCWSTR file = RmGetSettingsFile(); + + GetPrivateProfileString(L"WebParser.dll", L"ProxyServer", nullptr, buffer, MAX_PATH, file); + g_ProxyCachePool = new ProxyCachePool(buffer); + } +} + +void ClearGlobalProxySetting() +{ + delete g_ProxyCachePool; + g_ProxyCachePool = nullptr; +} + +void SetupProxySetting(ProxySetting& setting, void* rm) +{ + if (g_ProxyCachePool) + { + setting.server = RmReadString(rm, L"ProxyServer", L""); + setting.handle = g_ProxyCachePool->GetCache(setting.server); + } +} + +void ClearProxySetting(ProxySetting& setting) +{ + if (g_ProxyCachePool) + { + g_ProxyCachePool->RemoveCache(setting.server); + } + + setting.handle = nullptr; + setting.server.clear(); +} + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + MeasureData* measure = new MeasureData; + *data = measure; + g_Measures.push_back(measure); + + measure->skin = RmGetSkin(rm); + measure->rm = rm; + + if (g_InstanceCount == 0) + { + InitializeCriticalSection(&g_CriticalSection); + FillCharacterEntityReferences(); + + SetupGlobalProxySetting(); + } + + SetupProxySetting(measure->proxy, rm); // No support for DynamicVariables + + ++g_InstanceCount; +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + MeasureData* measure = (MeasureData*)data; + + EnterCriticalSection(&g_CriticalSection); + + /* Read our own settings from the ini-file */ + + std::wstring url = RmReadString(rm, L"Url", L"", FALSE); + + std::wstring::size_type start = 0; + while ((start = url.find(L"[&", start)) != std::wstring::npos) + { + std::wstring::size_type si = start + 1; + std::wstring::size_type end = url.find(L']', si); + if (end == std::wstring::npos) break; + + std::wstring var = L"["; + var.append(url, si + 1, end - si); + + const WCHAR* result = RmReplaceVariables(rm, var.c_str()); + const size_t resultLength = wcslen(result); + url.replace(start, end - start + 1, result, resultLength); + start += resultLength; + } + + measure->url = url; + + measure->regExp = RmReadString(rm, L"RegExp", L""); + measure->finishAction = RmReadString(rm, L"FinishAction", L"", FALSE); + measure->errorString = RmReadString(rm, L"ErrorString", L""); + + int index = RmReadInt(rm, L"StringIndex", 0); + measure->stringIndex = index < 0 ? 0 : index; + + index = RmReadInt(rm, L"StringIndex2", 0); + measure->stringIndex2 = index < 0 ? 0 : index; + + measure->decodeCharacterReference = RmReadInt(rm, L"DecodeCharacterReference", 0); + measure->updateRate = RmReadInt(rm, L"UpdateRate", 600); + measure->forceReload = 0!=RmReadInt(rm, L"ForceReload", 0); + measure->codepage = RmReadInt(rm, L"CodePage", 0); + + measure->download = 0!=RmReadInt(rm, L"Download", 0); + if (measure->download) + { + measure->downloadFolder = RmPathToAbsolute(rm, L"DownloadFile\\"); + measure->downloadFile = RmReadString(rm, L"DownloadFile", L""); + } + else + { + measure->downloadFile.clear(); + } + + measure->debug = RmReadInt(rm, L"Debug", 0); + if (measure->debug == 2) + { + measure->debugFileLocation = RmReadPath(rm, L"Debug2File", L"WebParserDump.txt"); + RmLog(rm, LOG_DEBUG, measure->debugFileLocation.c_str()); + } + + LeaveCriticalSection(&g_CriticalSection); +} + +PLUGIN_EXPORT double Update(void* data) +{ + MeasureData* measure = (MeasureData*)data; + double value = 0; + + if (measure->download && measure->regExp.empty() && measure->url.find(L'[') == std::wstring::npos) + { + // If RegExp is empty download the file that is pointed by the Url + if (measure->dlThreadHandle == 0) + { + if (measure->updateCounter == 0) + { + // Launch a new thread to fetch the web data + unsigned int id; + HANDLE threadHandle = (HANDLE)_beginthreadex(nullptr, 0, NetworkDownloadThreadProc, measure, 0, &id); + if (threadHandle) + { + measure->dlThreadHandle = threadHandle; + } + } + + measure->updateCounter++; + if (measure->updateCounter >= measure->updateRate) + { + measure->updateCounter = 0; + } + } + + // Else download the file pointed by the result string (this is done later) + } + else + { + // Make sure that the thread is not writing to the result at the same time + EnterCriticalSection(&g_CriticalSection); + + if (!measure->resultString.empty()) + { + value = wcstod(measure->resultString.c_str(), nullptr); + } + + LeaveCriticalSection(&g_CriticalSection); + + if (measure->url.size() > 0 && measure->url.find(L'[') == std::wstring::npos) + { + // This is not a reference; need to update. + if (measure->threadHandle == 0 && measure->dlThreadHandle == 0) + { + if (measure->updateCounter == 0) + { + // Launch a new thread to fetch the web data + unsigned int id; + HANDLE threadHandle = (HANDLE)_beginthreadex(nullptr, 0, NetworkThreadProc, measure, 0, &id); + if (threadHandle) + { + measure->threadHandle = threadHandle; + } + } + + measure->updateCounter++; + if (measure->updateCounter >= measure->updateRate) + { + measure->updateCounter = 0; + } + } + } + } + + return value; +} + +// Fetches the data from the net and parses the page +unsigned __stdcall NetworkThreadProc(void* pParam) +{ + MeasureData* measure = (MeasureData*)pParam; + DWORD dwSize = 0; + + RmLogF(measure->rm, LOG_DEBUG, L"WebParser: Fetching: %s", measure->url.c_str()); + BYTE* data = DownloadUrl(measure->proxy.handle, measure->url, &dwSize, measure->forceReload); + if (!data) + { + ShowError(measure->rm, L"Fetch error"); + } + else + { + if (measure->debug == 2) + { + // Dump to a file + + FILE* file = _wfopen(measure->debugFileLocation.c_str(), L"wb"); + if (file) + { + fwrite(data, sizeof(BYTE), dwSize, file); + fclose(file); + } + else + { + RmLog(measure->rm, LOG_ERROR, L"WebParser: Failed to dump debug data"); + } + } + + ParseData(measure, (LPCSTR)data, dwSize); + + free(data); + } + + EnterCriticalSection(&g_CriticalSection); + CloseHandle(measure->threadHandle); + measure->threadHandle = 0; + LeaveCriticalSection(&g_CriticalSection); + + return 0; // thread completed successfully +} + +void ParseData(MeasureData* measure, LPCSTR parseData, DWORD dwSize) +{ + // Parse the value from the data + pcre* re; + const char* error; + int erroffset; + int ovector[OVECCOUNT]; + int rc; + int flags = PCRE_UTF8; + + if (measure->codepage == 0) + { + flags = 0; + } + + // Compile the regular expression in the first argument + re = pcre_compile( + StringUtil::NarrowUTF8(measure->regExp).c_str(), // the pattern + flags, // default options + &error, // for error message + &erroffset, // for error offset + nullptr); // use default character tables + + if (re != nullptr) + { + // Compilation succeeded: match the subject in the second argument + std::string utf8Data; + + if (measure->codepage == 1200) // 1200 = UTF-16LE + { + // Must convert the data to utf8 + utf8Data = StringUtil::NarrowUTF8((LPCWSTR)parseData, dwSize / 2); + parseData = utf8Data.c_str(); + dwSize = (DWORD)utf8Data.length(); + } + else if (measure->codepage != CP_UTF8 && measure->codepage != 0) // 0 = CP_ACP + { + // Must convert the data to utf8 + utf8Data = ConvertAsciiToUTF8(parseData, dwSize, measure->codepage); + parseData = utf8Data.c_str(); + dwSize = (DWORD)utf8Data.length(); + } + + rc = pcre_exec( + re, // the compiled pattern + nullptr, // no extra data - we didn't study the pattern + parseData, // the subject string + dwSize, // the length of the subject + 0, // start at offset 0 in the subject + 0, // default options + ovector, // output vector for substring information + OVECCOUNT); // number of elements in the output vector + + if (rc >= 0) + { + if (rc == 0) + { + // The output vector wasn't big enough + RmLog(measure->rm, LOG_ERROR, L"WebParser: Too many substrings"); + } + else + { + if (measure->stringIndex < rc) + { + if (measure->debug != 0) + { + for (int i = 0; i < rc; ++i) + { + const char* substring_start = parseData + ovector[2 * i]; + int substring_length = ovector[2 * i + 1] - ovector[2 * i]; + substring_length = min(substring_length, 256); + + const std::wstring value = StringUtil::WidenUTF8(substring_start, substring_length); + RmLogF(measure->rm, LOG_DEBUG, L"WebParser: Index %2d: %s", i, value.c_str()); + } + } + + const char* substring_start = parseData + ovector[2 * measure->stringIndex]; + int substring_length = ovector[2 * measure->stringIndex + 1] - ovector[2 * measure->stringIndex]; + + EnterCriticalSection(&g_CriticalSection); + measure->resultString = StringUtil::WidenUTF8(substring_start, substring_length); + DecodeReferences(measure->resultString, measure->decodeCharacterReference); + LeaveCriticalSection(&g_CriticalSection); + } + else + { + RmLog(measure->rm, LOG_WARNING, L"WebParser: Not enough substrings"); + + // Clear the old result + EnterCriticalSection(&g_CriticalSection); + measure->resultString.clear(); + if (measure->download) + { + if (measure->downloadFile.empty()) // cache mode + { + if (!measure->downloadedFile.empty()) + { + // Delete old downloaded file + DeleteFile(measure->downloadedFile.c_str()); + } + } + measure->downloadedFile.clear(); + } + LeaveCriticalSection(&g_CriticalSection); + } + + // Update the references + std::vector<MeasureData*>::iterator i = g_Measures.begin(); + std::wstring compareStr = L"["; + compareStr += RmGetMeasureName(measure->rm); + compareStr += L']'; + for ( ; i != g_Measures.end(); ++i) + { + if (measure->skin == (*i)->skin && + StringUtil::CaseInsensitiveFind((*i)->url, compareStr) != std::wstring::npos) + { + if ((*i)->stringIndex < rc) + { + const char* substring_start = parseData + ovector[2 * (*i)->stringIndex]; + int substring_length = ovector[2 * (*i)->stringIndex + 1] - ovector[2 * (*i)->stringIndex]; + + if (!(*i)->regExp.empty()) + { + // Change the index and parse the substring + int index = (*i)->stringIndex; + (*i)->stringIndex = (*i)->stringIndex2; + ParseData((*i), substring_start, substring_length); + (*i)->stringIndex = index; + } + else + { + // Set the result + EnterCriticalSection(&g_CriticalSection); + + // Substitude the [measure] with result + std::wstring result = StringUtil::WidenUTF8(substring_start, substring_length); + (*i)->resultString = (*i)->url; + (*i)->resultString.replace( + StringUtil::CaseInsensitiveFind((*i)->resultString, compareStr), + compareStr.size(), result); + DecodeReferences((*i)->resultString, (*i)->decodeCharacterReference); + + // Start download threads for the references + if ((*i)->download) + { + // Start the download thread + unsigned int id; + HANDLE threadHandle = (HANDLE)_beginthreadex(nullptr, 0, NetworkDownloadThreadProc, (*i), 0, &id); + if (threadHandle) + { + (*i)->dlThreadHandle = threadHandle; + } + } + + LeaveCriticalSection(&g_CriticalSection); + } + } + else + { + RmLog((*i)->rm, LOG_WARNING, L"WebParser: Not enough substrings"); + + // Clear the old result + EnterCriticalSection(&g_CriticalSection); + (*i)->resultString.clear(); + if ((*i)->download) + { + if ((*i)->downloadFile.empty()) // cache mode + { + if (!(*i)->downloadedFile.empty()) + { + // Delete old downloaded file + DeleteFile((*i)->downloadedFile.c_str()); + } + } + (*i)->downloadedFile.clear(); + } + LeaveCriticalSection(&g_CriticalSection); + } + } + } + } + } + else + { + // Matching failed: handle error cases + RmLogF(measure->rm, LOG_ERROR, L"WebParser: RegExp matching error (%d)", rc); + + EnterCriticalSection(&g_CriticalSection); + measure->resultString = measure->errorString; + + // Update the references + std::vector<MeasureData*>::iterator i = g_Measures.begin(); + std::wstring compareStr = L"["; + compareStr += RmGetMeasureName(measure->rm); + compareStr += L']'; + for ( ; i != g_Measures.end(); ++i) + { + if ((StringUtil::CaseInsensitiveFind((*i)->url, compareStr) != std::wstring::npos) && + (measure->skin == (*i)->skin)) + { + (*i)->resultString = (*i)->errorString; + } + } + LeaveCriticalSection(&g_CriticalSection); + } + + // Release memory used for the compiled pattern + pcre_free(re); + } + else + { + // Compilation failed. + RmLogF(measure->rm, LOG_ERROR, L"WebParser: RegExp error at offset %d: %S", erroffset, error); + } + + if (measure->download) + { + // Start the download thread + unsigned int id; + HANDLE threadHandle = (HANDLE)_beginthreadex(nullptr, 0, NetworkDownloadThreadProc, measure, 0, &id); + if (threadHandle) + { + measure->dlThreadHandle = threadHandle; + } + } + else + { + if (!measure->finishAction.empty()) + { + RmExecute(measure->skin, measure->finishAction.c_str()); + } + } +} + +// Downloads file from the net +unsigned __stdcall NetworkDownloadThreadProc(void* pParam) +{ + MeasureData* measure = (MeasureData*)pParam; + const bool download = !measure->downloadFile.empty(); + bool ready = false; + + std::wstring url; + + if (measure->regExp.empty() && measure->resultString.empty()) + { + if (!measure->url.empty() && measure->url[0] != L'[') + { + url = measure->url; + } + } + else + { + EnterCriticalSection(&g_CriticalSection); + url = measure->resultString; + LeaveCriticalSection(&g_CriticalSection); + + std::wstring::size_type pos = url.find(L':'); + if (pos == std::wstring::npos && !url.empty()) // No protocol + { + // Add the base url to the string + if (url[0] == L'/') + { + // Absolute path + pos = measure->url.find(L'/', 7); // Assume "http://" (=7) + if (pos != std::wstring::npos) + { + std::wstring path(measure->url.substr(0, pos)); + url = path + url; + } + } + else + { + // Relative path + + pos = measure->url.rfind(L'/'); + if (pos != std::wstring::npos) + { + std::wstring path(measure->url.substr(0, pos + 1)); + url = path + url; + } + } + } + } + + if (!url.empty()) + { + // Create the filename + WCHAR buffer[MAX_PATH] = {0}; + std::wstring fullpath, directory; + + if (download) // download mode + { + PathCanonicalize(buffer, measure->downloadFile.c_str()); + + std::wstring path = buffer; + std::wstring::size_type pos = path.find_first_not_of(L'\\'); + if (pos != std::wstring::npos) + { + path.erase(0, pos); + } + + PathCanonicalize(buffer, measure->downloadFolder.c_str()); + CreateDirectory(buffer, nullptr); // Make sure that the folder exists + + wcscat(buffer, path.c_str()); + + if (buffer[wcslen(buffer)-1] != L'\\') // path is a file + { + fullpath = buffer; + PathRemoveFileSpec(buffer); + } + PathAddBackslash(buffer); + } + else // cache mode + { + GetTempPath(MAX_PATH, buffer); + wcscat(buffer, L"Rainmeter-Cache\\"); // "%TEMP%\Rainmeter-Cache\" + } + CreateDirectory(buffer, nullptr); // Make sure that the folder exists + directory = buffer; + + if (fullpath.empty()) + { + fullpath = directory; + + std::wstring::size_type pos2 = url.find_first_of(L"?#"); + std::wstring::size_type pos1 = url.find_last_of(L'/', pos2); + pos1 = (pos1 != std::wstring::npos) ? pos1 + 1 : 0; + + std::wstring name; + if (pos2 != std::wstring::npos) + { + name.assign(url, pos1, pos2 - pos1); + } + else + { + name.assign(url, pos1, url.length() - pos1); + } + + if (!name.empty()) + { + // Replace reserved characters to "_" + pos1 = 0; + while ((pos1 = name.find_first_of(L"\\/:*?\"<>|", pos1)) != std::wstring::npos) + { + name[pos1] = L'_'; + } + fullpath += name; + } + else + { + fullpath += L"index"; + } + } + + ready = true; + + if (download) // download mode + { + if (!PathFileExists(directory.c_str()) || !PathIsDirectory(directory.c_str())) + { + ready = false; + RmLogF( + measure->rm, LOG_ERROR, + L"WebParser: Directory does not exist: %s", directory.c_str()); + } + else if (PathIsDirectory(fullpath.c_str())) + { + ready = false; + RmLogF( + measure->rm, LOG_ERROR, + L"WebParser: Path is a directory, not a file: %s", fullpath.c_str()); + } + else if (PathFileExists(fullpath.c_str())) + { + DWORD attr = GetFileAttributes(fullpath.c_str()); + if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_READONLY)) + { + ready = false; + RmLogF( + measure->rm, LOG_ERROR, + L"WebParser: File is read-only: %s", fullpath.c_str()); + } + } + } + else // cache mode + { + EnterCriticalSection(&g_CriticalSection); + + if (PathFileExists(fullpath.c_str())) + { + std::wstring::size_type pos = fullpath.find_last_of(L'.'); + + std::wstring path, ext; + if (pos != std::wstring::npos) + { + path.assign(fullpath, 0, pos); + ext.assign(fullpath, pos, fullpath.length() - pos); + } + else + { + path = fullpath; + } + + // Assign a serial number + int i = 1; + do + { + wsprintf(buffer, L"_%i", i++); + + fullpath = path; + fullpath += buffer; + if (!ext.empty()) + { + fullpath += ext; + } + } while (PathFileExists(fullpath.c_str())); + } + + // Create empty file + HANDLE hFile = CreateFile(fullpath.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); + + LeaveCriticalSection(&g_CriticalSection); + } + + if (ready) + { + // Delete IE cache before download if "SyncMode5" is not 3 (every visit to the page) + { + // Check "Temporary Internet Files" sync mode (SyncMode5) + // Values: + // Every visit to the page 3 + // Every time you start Internet Explorer 2 + // Automatically (default) 4 + // Never 0 + // http://support.microsoft.com/kb/263070/en + + HKEY hKey; + LONG ret; + DWORD mode; + + ret = RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", 0, KEY_QUERY_VALUE, &hKey); + if (ret == ERROR_SUCCESS) + { + DWORD size = sizeof(mode); + ret = RegQueryValueEx(hKey, L"SyncMode5", nullptr, nullptr, (LPBYTE)&mode, &size); + RegCloseKey(hKey); + } + + if (ret != ERROR_SUCCESS || mode != 3) + { + std::wstring::size_type pos = url.find_first_of(L'#'); + + if (pos != std::wstring::npos) + { + DeleteUrlCacheEntry(url.substr(0, pos).c_str()); + } + else + { + DeleteUrlCacheEntry(url.c_str()); + } + } + } + + RmLogF( + measure->rm, LOG_DEBUG, + L"WebParser: Downloading url '%s' to: %s", url.c_str(), fullpath.c_str()); + + HRESULT resultCoInitialize = CoInitialize(nullptr); // requires before calling URLDownloadToFile function + + // Download the file + HRESULT result = URLDownloadToFile(nullptr, url.c_str(), fullpath.c_str(), 0, nullptr); + if (result == S_OK) + { + EnterCriticalSection(&g_CriticalSection); + + if (!download) // cache mode + { + if (!measure->downloadedFile.empty()) + { + // Delete old downloaded file + DeleteFile(measure->downloadedFile.c_str()); + } + } + + // Convert LFN to 8.3 filename if the path contains blank character + if (fullpath.find_first_of(L' ') != std::wstring::npos) + { + DWORD size = GetShortPathName(fullpath.c_str(), buffer, MAX_PATH); + if (size > 0 && size <= MAX_PATH) + { + fullpath = buffer; + } + } + measure->downloadedFile = fullpath; + + LeaveCriticalSection(&g_CriticalSection); + + if (!measure->finishAction.empty()) + { + RmExecute(measure->skin, measure->finishAction.c_str()); + } + } + else + { + ready = false; + + if (!download) // cache mode + { + // Delete empty file + DeleteFile(fullpath.c_str()); + } + + RmLogF( + measure->rm, LOG_ERROR, + L"WebParser: Download failed (res=0x%08X, COM=0x%08X): %s", + result, resultCoInitialize, url.c_str()); + } + + if (SUCCEEDED(resultCoInitialize)) + { + CoUninitialize(); + } + } + else + { + RmLogF(measure->rm, LOG_ERROR, L"WebParser: Download failed: %s", url.c_str()); + } + } + else + { + RmLog(measure->rm, LOG_ERROR, L"WebParser: Url is empty"); + } + + if (!ready) // download failed + { + EnterCriticalSection(&g_CriticalSection); + + if (!download) // cache mode + { + if (!measure->downloadedFile.empty()) + { + // Delete old downloaded file + DeleteFile(measure->downloadedFile.c_str()); + } + } + + // Clear old downloaded filename + measure->downloadedFile.clear(); + + LeaveCriticalSection(&g_CriticalSection); + } + + EnterCriticalSection(&g_CriticalSection); + CloseHandle(measure->dlThreadHandle); + measure->dlThreadHandle = 0; + LeaveCriticalSection(&g_CriticalSection); + + return 0; // thread completed successfully +} + +PLUGIN_EXPORT LPCWSTR GetString(void* data) +{ + MeasureData* measure = (MeasureData*)data; + static std::wstring resultString; + + EnterCriticalSection(&g_CriticalSection); + if (measure->download) + { + resultString = measure->downloadedFile; + } + else + { + resultString = measure->resultString; + } + LeaveCriticalSection(&g_CriticalSection); + + return resultString.c_str(); +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + MeasureData* measure = (MeasureData*)data; + + if (measure->threadHandle) + { + // Thread is killed inside critical section so that itself is not inside one when it is terminated + EnterCriticalSection(&g_CriticalSection); + + TerminateThread(measure->threadHandle, 0); + measure->threadHandle = nullptr; + + LeaveCriticalSection(&g_CriticalSection); + } + + if (measure->dlThreadHandle) + { + // Thread is killed inside critical section so that itself is not inside one when it is terminated + EnterCriticalSection(&g_CriticalSection); + + TerminateThread(measure->dlThreadHandle, 0); + measure->dlThreadHandle = nullptr; + + LeaveCriticalSection(&g_CriticalSection); + } + + if (measure->downloadFile.empty()) // cache mode + { + if (!measure->downloadedFile.empty()) + { + // Delete the file + DeleteFile(measure->downloadedFile.c_str()); + } + } + + ClearProxySetting(measure->proxy); + + delete measure; + std::vector<MeasureData*>::iterator iter = std::find(g_Measures.begin(), g_Measures.end(), measure); + g_Measures.erase(iter); + + --g_InstanceCount; + if (g_InstanceCount == 0) + { + // Last one, close all handles + ClearGlobalProxySetting(); + + g_CERs.clear(); + + // Last instance deletes the critical section + DeleteCriticalSection(&g_CriticalSection); + } +} + +/* + Downloads the given url and returns the webpage as dynamically allocated string. + You need to free the returned string after use! +*/ +BYTE* DownloadUrl(HINTERNET handle, std::wstring& url, DWORD* dataSize, bool forceReload) +{ + DWORD flags = INTERNET_FLAG_RESYNCHRONIZE; + if (forceReload) + { + flags = INTERNET_FLAG_RELOAD; + } + + HINTERNET hUrlDump = InternetOpenUrl(handle, url.c_str(), nullptr, 0, flags, 0); + if (!hUrlDump) + { + if (_wcsnicmp(url.c_str(), L"file://", 7) == 0) // file scheme + { + const std::string urlACP = StringUtil::Narrow(url); + hUrlDump = InternetOpenUrlA(handle, urlACP.c_str(), nullptr, 0, flags, 0); + } + + if (!hUrlDump) + { + return nullptr; + } + } + + // Allocate buffer with 3 extra bytes for triple null termination in case the string is + // invalid (e.g. when incorrectly using the UTF-16LE codepage for the data). + const int CHUNK_SIZE = 8192; + DWORD bufferSize = CHUNK_SIZE; + BYTE* buffer = (BYTE*)malloc(bufferSize + 3); + *dataSize = 0; + + // Read the data. + do + { + DWORD readSize; + if (!InternetReadFile(hUrlDump, buffer + *dataSize, bufferSize - *dataSize, &readSize)) + { + free(buffer); + InternetCloseHandle(hUrlDump); + return nullptr; + } + else if (readSize == 0) + { + // All data read. + break; + } + + *dataSize += readSize; + + bufferSize += CHUNK_SIZE; + buffer = (BYTE*)realloc(buffer, bufferSize + 3); + } + while (true); + + InternetCloseHandle(hUrlDump); + + // Triple null terminate the buffer. + buffer[*dataSize] = 0; + buffer[*dataSize + 1] = 0; + buffer[*dataSize + 2] = 0; + + return buffer; +} + +/* + Writes the last error to log. +*/ +void ShowError(void* rm, WCHAR* description) +{ + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_INTERNET_EXTENDED_ERROR) + { + WCHAR szBuffer[1024]; + DWORD dwError, dwLen = 1024; + const WCHAR* error = L"Unknown error"; + if (InternetGetLastResponseInfo(&dwError, szBuffer, &dwLen)) + { + error = szBuffer; + dwErr = dwError; + } + + RmLogF(rm, LOG_ERROR, L"WebParser: (%s) %s (ErrorCode=%i)", description, error, dwErr); + } + else + { + LPVOID lpMsgBuf = nullptr; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_HMODULE | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_MAX_WIDTH_MASK, + GetModuleHandle(L"wininet"), + dwErr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + nullptr + ); + + const WCHAR* error = lpMsgBuf ? (WCHAR*)lpMsgBuf : L"Unknown error"; + RmLogF(rm, LOG_ERROR, L"WebParser: (%s) %s (ErrorCode=%i)", description, error, dwErr); + + if (lpMsgBuf) LocalFree(lpMsgBuf); + } +} + +PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) +{ + MeasureData* measure = (MeasureData*)data; + + // Kill the threads (if any) and reset the update counter + if (_wcsicmp(args, L"UPDATE") == 0) + { + if (measure->threadHandle) + { + // Thread is killed inside critical section so that itself is not inside one when it is terminated + EnterCriticalSection(&g_CriticalSection); + + TerminateThread(measure->threadHandle, 0); + measure->threadHandle = nullptr; + + LeaveCriticalSection(&g_CriticalSection); + } + + if (measure->dlThreadHandle) + { + // Thread is killed inside critical section so that itself is not inside one when it is terminated + EnterCriticalSection(&g_CriticalSection); + + TerminateThread(measure->dlThreadHandle, 0); + measure->dlThreadHandle = nullptr; + + LeaveCriticalSection(&g_CriticalSection); + } + + measure->updateCounter = 0; + } +} diff --git a/Plugins/PluginWifiStatus/PluginWifiStatus.rc b/Plugins/PluginWifiStatus/PluginWifiStatus.rc index 31a31ca8..7a021024 100644 --- a/Plugins/PluginWifiStatus/PluginWifiStatus.rc +++ b/Plugins/PluginWifiStatus/PluginWifiStatus.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,9,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.9.0.0" - VALUE "LegalCopyright", " 2010 - nvme" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,9,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.9.0.0" + VALUE "LegalCopyright", " 2010 - nvme" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginWifiStatus/PluginWifiStatus.vcxproj b/Plugins/PluginWifiStatus/PluginWifiStatus.vcxproj index 29266c17..c4c82407 100644 --- a/Plugins/PluginWifiStatus/PluginWifiStatus.vcxproj +++ b/Plugins/PluginWifiStatus/PluginWifiStatus.vcxproj @@ -1,36 +1,36 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{45A34285-56DD-4521-912B-3F884D36FA35}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>WifiStatus</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - <AdditionalDependencies>wlanapi.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ResourceCompile Include="PluginWifiStatus.rc" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="WifiStatus.cpp" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{45A34285-56DD-4521-912B-3F884D36FA35}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>WifiStatus</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <AdditionalDependencies>wlanapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ResourceCompile Include="PluginWifiStatus.rc" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="WifiStatus.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginWifiStatus/WifiStatus.cpp b/Plugins/PluginWifiStatus/WifiStatus.cpp index 68d6c3fb..cd125601 100644 --- a/Plugins/PluginWifiStatus/WifiStatus.cpp +++ b/Plugins/PluginWifiStatus/WifiStatus.cpp @@ -1,496 +1,496 @@ -/* - Copyright (C) 2009 Shaivya Mahajan - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include <windows.h> -#include <string> -#include <wlanapi.h> -#include "../API/RainmeterAPI.h" - -enum MEASURETYPE -{ - UNINITIALIZED, - UNKNOWN, - SSID, - QUALITY, - ENCRYPTION, - AUTH, - LIST, - PHY -}; - -struct MeasureData -{ - MEASURETYPE type; - UINT listStyle; - UINT listMax; - std::wstring statusString; - - MeasureData() : type(UNINITIALIZED), listStyle(), listMax(5) {} -}; - -UINT g_Instances = 0; - -// Globals that store system's wifi interface/adapter structs -// These are initialized in Initialize(), used during each update -HANDLE g_hClient = nullptr; -PWLAN_INTERFACE_INFO g_pInterface = nullptr; -PWLAN_INTERFACE_INFO_LIST g_pIntfList = nullptr; - -// Function that translates DOT11 ENUMs to output strings -LPCWSTR GetDot11Str(int, int); - -std::wstring ConvertToWide(LPCSTR str, int strLen) -{ - std::wstring szWide; - - if (str && *str) - { - int bufLen = MultiByteToWideChar(CP_ACP, 0, str, strLen, nullptr, 0); - if (bufLen > 0) - { - szWide.resize(bufLen); - MultiByteToWideChar(CP_ACP, 0, str, strLen, &szWide[0], bufLen); - } - } - return szWide; -} - -void FinalizeHandle() -{ - g_pInterface = nullptr; - - if (g_pIntfList != nullptr) - { - WlanFreeMemory(g_pIntfList); - g_pIntfList = nullptr; - } - - if (g_hClient != nullptr) - { - WlanCloseHandle(g_hClient, nullptr); - g_hClient = nullptr; - } -} - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - MeasureData* measure = new MeasureData; - *data = measure; - - ++g_Instances; - - if (g_Instances == 1) - { - WCHAR buffer[256]; - - // Create WINLAN API Handle - if (g_hClient == nullptr) - { - DWORD dwNegotiatedVersion = 0; - DWORD dwErr = WlanOpenHandle(WLAN_API_VERSION, nullptr, &dwNegotiatedVersion, &g_hClient); - if (ERROR_SUCCESS != dwErr) - { - FinalizeHandle(); - _snwprintf_s(buffer, _TRUNCATE, L"WifiStatus.dll: Unable to open WLAN API Handle. Error code (%u): %s", dwErr, GetDot11Str((int)dwErr, 5)); - RmLog(LOG_ERROR, buffer); - return; - } - } - - // Query list of WLAN interfaces - if (g_pIntfList == nullptr) - { - DWORD dwErr = WlanEnumInterfaces(g_hClient, nullptr, &g_pIntfList); - if (ERROR_SUCCESS != dwErr) - { - FinalizeHandle(); - _snwprintf_s(buffer, _TRUNCATE, L"WifiStatus.dll: Unable to find any WLAN interfaces/adapters. Error code %u", dwErr); - RmLog(LOG_ERROR, buffer); - return; - } - else if (g_pIntfList->dwNumberOfItems == 0) - { - FinalizeHandle(); - RmLog(LOG_ERROR, L"WifiStatus.dll: No WLAN interfaces/adapters available."); - return; - } - } - } -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - if (g_hClient == nullptr) return; - - MeasureData* measure = (MeasureData*)data; - WCHAR buffer[128]; - bool changed = false; - - int value = 0; - auto logValueError = [&](const WCHAR* option) - { - _snwprintf_s(buffer, _TRUNCATE, L"WifiStatus.dll: %s=%i not valid", option, value); - RmLog(LOG_ERROR, buffer); - }; - - // Select a WLAN interface, default 0. - value = RmReadInt(rm, L"WifiIntfID", 0); - if (value >= (int)g_pIntfList->dwNumberOfItems) - { - logValueError(L"WifiIntfID"); - value = 0; - } - g_pInterface = &g_pIntfList->InterfaceInfo[value]; - - // Select LIST style - value = RmReadInt(rm, L"WifiListStyle", 0); - if (value < 0 || value > 3) - { - logValueError(L"WifiListStyle"); - value = 0; - } - measure->listStyle = value; - - // Set maxmimum number of list items - value = RmReadInt(rm, L"WifiListLimit", 5); - if (value <= 0) - { - logValueError(L"WifiListLimit"); - value = 5; - } - measure->listMax = value; - - // Select type of measure - MEASURETYPE infoType = UNKNOWN; - LPCWSTR type = RmReadString(rm, L"WifiInfoType", L""); - if (_wcsicmp(L"SSID", type) == 0) - { - infoType = SSID; - } - else if (_wcsicmp(L"QUALITY", type) == 0) - { - infoType = QUALITY; - } - else if (_wcsicmp(L"ENCRYPTION", type) == 0) - { - infoType = ENCRYPTION; - } - else if (_wcsicmp(L"AUTH", type) == 0) - { - infoType = AUTH; - } - else if (_wcsicmp(L"LIST", type) == 0) - { - infoType = LIST; - } - else if (_wcsicmp(L"PHY", type) == 0) - { - infoType = PHY; - } - else - { - _snwprintf_s(buffer, _TRUNCATE, L"WifiStatus.dll: WifiInfoType=%s not valid", type); - RmLog(LOG_ERROR, buffer); - } - if (infoType != measure->type) - { - changed = true; - } - measure->type = infoType; - - if (changed) - { - measure->statusString.clear(); - - switch (infoType) - { - case SSID: - case ENCRYPTION: - case AUTH: - *maxValue = 0; - break; - case QUALITY: - *maxValue = 100; - break; - } - } -} - -PLUGIN_EXPORT double Update(void* data) -{ - if (g_pInterface == nullptr) return 0; - - MeasureData* measure = (MeasureData*)data; - double value = 0; - - if (measure->type != UNKNOWN) - { - if (measure->type == LIST) - { - PWLAN_AVAILABLE_NETWORK_LIST pwnl = nullptr; - DWORD dwErr = WlanGetAvailableNetworkList(g_hClient, &g_pInterface->InterfaceGuid, 0, nullptr, &pwnl); - - if (ERROR_SUCCESS != dwErr) - { - measure->statusString = L"Error"; - } - else - { - // Size of network name can be up to 64 chars, set to 80 to add room for delimiters - measure->statusString.clear(); - measure->statusString.reserve(80 * measure->listMax); - - UINT printed = 0; // count of how many networks have been printed already - - // Check all items in WLAN NETWORK LIST - for (size_t i = 0; i < pwnl->dwNumberOfItems ; ++i) - { - if (printed == measure->listMax) break; - - // SSID is in UCHAR, convert to WCHAR - std::wstring ssid = ConvertToWide((LPCSTR)pwnl->Network[i].dot11Ssid.ucSSID, (int)pwnl->Network[i].dot11Ssid.uSSIDLength); - - // Prevent duplicates that result from profiles, check using SSID - if (!ssid.empty() && ssid[0] && wcsstr(measure->statusString.c_str(), ssid.c_str()) == nullptr) - { - ++printed; - measure->statusString += ssid; - if (measure->listStyle > 0) - { - if (measure->listStyle == 1 || measure->listStyle == 3) - { - // ADD PHY type - measure->statusString += L" @"; - measure->statusString += GetDot11Str(pwnl->Network[i].dot11PhyTypes[0], 4); - } - if (measure->listStyle == 2 || measure->listStyle == 3) - { - // ADD cipher and authentication - measure->statusString += L" ("; - measure->statusString += GetDot11Str(pwnl->Network[i].dot11DefaultCipherAlgorithm, 1); - measure->statusString += L':'; - measure->statusString += GetDot11Str(pwnl->Network[i].dot11DefaultAuthAlgorithm, 2); - measure->statusString += L')'; - } - } - measure->statusString += L'\n'; - } - } - - WlanFreeMemory(pwnl); - } - } - else - { - ULONG outsize = 0; - PWLAN_CONNECTION_ATTRIBUTES wlan_cattr = nullptr; - DWORD dwErr = WlanQueryInterface(g_hClient, &g_pInterface->InterfaceGuid, wlan_intf_opcode_current_connection, nullptr, &outsize, (PVOID*)&wlan_cattr, nullptr); - - if (ERROR_SUCCESS != dwErr) - { - switch (measure->type) - { - case SSID: - case PHY: - case ENCRYPTION: - case AUTH: - measure->statusString = L"-1"; - break; - } - } - else - { - switch (measure->type) - { - case QUALITY: - value = (double)wlan_cattr->wlanAssociationAttributes.wlanSignalQuality; - break; - - case SSID: - // Need to convert ucSSID to wchar from uchar - measure->statusString = ConvertToWide((LPCSTR)wlan_cattr->wlanAssociationAttributes.dot11Ssid.ucSSID, (int)wlan_cattr->wlanAssociationAttributes.dot11Ssid.uSSIDLength); - // If not connected yet add current status - measure->statusString += GetDot11Str(wlan_cattr->isState, 3); - break; - - case PHY: - measure->statusString = GetDot11Str(wlan_cattr->wlanAssociationAttributes.dot11PhyType, 4); - break; - - case ENCRYPTION: - measure->statusString = GetDot11Str(wlan_cattr->wlanSecurityAttributes.dot11CipherAlgorithm, 1); - break; - - case AUTH: - measure->statusString = GetDot11Str(wlan_cattr->wlanSecurityAttributes.dot11AuthAlgorithm, 2); - break; - - default: // Invalid type - measure->statusString.clear(); - break; - } - - WlanFreeMemory(wlan_cattr); - } - } - } - - return value; -} - - -PLUGIN_EXPORT LPCWSTR GetString(void* data) -{ - if (g_pInterface == nullptr) return nullptr; - - MeasureData* measure = (MeasureData*)data; - - switch (measure->type) - { - case LIST: - case SSID: - case PHY: - case ENCRYPTION: - case AUTH: - return measure->statusString.c_str(); - - default: - return nullptr; - } -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - MeasureData* measure = (MeasureData*)data; - delete measure; - - if (g_Instances > 0) - { - --g_Instances; - - if (g_Instances == 0) - { - FinalizeHandle(); - } - } -} - -/* - switches from winlanapi.h + SDK - in: -DOT11 ENUM (converted to int) - -type of ENUM (cipher=1, auth=2, status=3, phy=4, otherwise=error strings) - out: String to be returned by measure -*/ -LPCWSTR GetDot11Str(int dot11enum, int type) -{ - if (type == 1) - { - switch (dot11enum) - { - case DOT11_CIPHER_ALGO_NONE: - return L"NONE"; - case DOT11_CIPHER_ALGO_WEP40: - return L"WEP40"; - case DOT11_CIPHER_ALGO_TKIP: - return L"TKIP"; - case DOT11_CIPHER_ALGO_CCMP: - return L"AES"; - case DOT11_CIPHER_ALGO_WEP104: - return L"WEP104"; - case DOT11_CIPHER_ALGO_WPA_USE_GROUP: - return L"WPA-GROUP"; - case DOT11_CIPHER_ALGO_WEP: - return L"WEP"; - default: - return L"???"; - } - } - else if (type == 2) - { - switch (dot11enum) - { - case DOT11_AUTH_ALGO_80211_OPEN: - return L"Open"; - case DOT11_AUTH_ALGO_80211_SHARED_KEY: - return L"Shared"; - case DOT11_AUTH_ALGO_WPA_NONE: - return L"WPA-NONE"; - case DOT11_AUTH_ALGO_WPA: - return L"WPA-Enterprise"; - case DOT11_AUTH_ALGO_WPA_PSK: - return L"WPA-Personal"; - case DOT11_AUTH_ALGO_RSNA: - return L"WPA2-Enterprise"; - case DOT11_AUTH_ALGO_RSNA_PSK: - return L"WPA2-Personal"; - default: - return L"???"; - } - } - else if (type == 3) - { - switch (dot11enum) - { - case wlan_interface_state_connected: - return L""; - case wlan_interface_state_authenticating: - return L"(authorizing...)"; - default: - return L"(connecting...)"; - } - } - else if (type == 4) - { - switch (dot11enum) - { - case dot11_phy_type_unknown: - default: - return L"???"; - case dot11_phy_type_dsss: - return L"DSSS"; - case dot11_phy_type_erp: - return L"802.11g"; - case dot11_phy_type_fhss: - return L"FHSS"; - case dot11_phy_type_hrdsss: - return L"802.11b"; - case dot11_phy_type_irbaseband: - return L"IR-Band"; - case dot11_phy_type_ofdm: - return L"802.11a"; - //Case below appears as dot11_phy_type_ht on MSDN - //However its not supported in winlanapi.h ??? - case 7: - return L"802.11n"; - } - } - else - { - switch (dot11enum) - { - case ERROR_INVALID_PARAMETER: - return L"Invalid parameters"; - case ERROR_NOT_ENOUGH_MEMORY: - return L"Not enough memory"; - case ERROR_REMOTE_SESSION_LIMIT_EXCEEDED: - return L"Too many handles already issued"; - default: - return L"Unknown error code"; - } - } -} +/* + Copyright (C) 2009 Shaivya Mahajan + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <windows.h> +#include <string> +#include <wlanapi.h> +#include "../API/RainmeterAPI.h" + +enum MEASURETYPE +{ + UNINITIALIZED, + UNKNOWN, + SSID, + QUALITY, + ENCRYPTION, + AUTH, + LIST, + PHY +}; + +struct MeasureData +{ + MEASURETYPE type; + UINT listStyle; + UINT listMax; + std::wstring statusString; + + MeasureData() : type(UNINITIALIZED), listStyle(), listMax(5) {} +}; + +UINT g_Instances = 0; + +// Globals that store system's wifi interface/adapter structs +// These are initialized in Initialize(), used during each update +HANDLE g_hClient = nullptr; +PWLAN_INTERFACE_INFO g_pInterface = nullptr; +PWLAN_INTERFACE_INFO_LIST g_pIntfList = nullptr; + +// Function that translates DOT11 ENUMs to output strings +LPCWSTR GetDot11Str(int, int); + +std::wstring ConvertToWide(LPCSTR str, int strLen) +{ + std::wstring szWide; + + if (str && *str) + { + int bufLen = MultiByteToWideChar(CP_ACP, 0, str, strLen, nullptr, 0); + if (bufLen > 0) + { + szWide.resize(bufLen); + MultiByteToWideChar(CP_ACP, 0, str, strLen, &szWide[0], bufLen); + } + } + return szWide; +} + +void FinalizeHandle() +{ + g_pInterface = nullptr; + + if (g_pIntfList != nullptr) + { + WlanFreeMemory(g_pIntfList); + g_pIntfList = nullptr; + } + + if (g_hClient != nullptr) + { + WlanCloseHandle(g_hClient, nullptr); + g_hClient = nullptr; + } +} + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + MeasureData* measure = new MeasureData; + *data = measure; + + ++g_Instances; + + if (g_Instances == 1) + { + WCHAR buffer[256]; + + // Create WINLAN API Handle + if (g_hClient == nullptr) + { + DWORD dwNegotiatedVersion = 0; + DWORD dwErr = WlanOpenHandle(WLAN_API_VERSION, nullptr, &dwNegotiatedVersion, &g_hClient); + if (ERROR_SUCCESS != dwErr) + { + FinalizeHandle(); + _snwprintf_s(buffer, _TRUNCATE, L"WifiStatus.dll: Unable to open WLAN API Handle. Error code (%u): %s", dwErr, GetDot11Str((int)dwErr, 5)); + RmLog(LOG_ERROR, buffer); + return; + } + } + + // Query list of WLAN interfaces + if (g_pIntfList == nullptr) + { + DWORD dwErr = WlanEnumInterfaces(g_hClient, nullptr, &g_pIntfList); + if (ERROR_SUCCESS != dwErr) + { + FinalizeHandle(); + _snwprintf_s(buffer, _TRUNCATE, L"WifiStatus.dll: Unable to find any WLAN interfaces/adapters. Error code %u", dwErr); + RmLog(LOG_ERROR, buffer); + return; + } + else if (g_pIntfList->dwNumberOfItems == 0) + { + FinalizeHandle(); + RmLog(LOG_ERROR, L"WifiStatus.dll: No WLAN interfaces/adapters available."); + return; + } + } + } +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + if (g_hClient == nullptr) return; + + MeasureData* measure = (MeasureData*)data; + WCHAR buffer[128]; + bool changed = false; + + int value = 0; + auto logValueError = [&](const WCHAR* option) + { + _snwprintf_s(buffer, _TRUNCATE, L"WifiStatus.dll: %s=%i not valid", option, value); + RmLog(LOG_ERROR, buffer); + }; + + // Select a WLAN interface, default 0. + value = RmReadInt(rm, L"WifiIntfID", 0); + if (value >= (int)g_pIntfList->dwNumberOfItems) + { + logValueError(L"WifiIntfID"); + value = 0; + } + g_pInterface = &g_pIntfList->InterfaceInfo[value]; + + // Select LIST style + value = RmReadInt(rm, L"WifiListStyle", 0); + if (value < 0 || value > 3) + { + logValueError(L"WifiListStyle"); + value = 0; + } + measure->listStyle = value; + + // Set maxmimum number of list items + value = RmReadInt(rm, L"WifiListLimit", 5); + if (value <= 0) + { + logValueError(L"WifiListLimit"); + value = 5; + } + measure->listMax = value; + + // Select type of measure + MEASURETYPE infoType = UNKNOWN; + LPCWSTR type = RmReadString(rm, L"WifiInfoType", L""); + if (_wcsicmp(L"SSID", type) == 0) + { + infoType = SSID; + } + else if (_wcsicmp(L"QUALITY", type) == 0) + { + infoType = QUALITY; + } + else if (_wcsicmp(L"ENCRYPTION", type) == 0) + { + infoType = ENCRYPTION; + } + else if (_wcsicmp(L"AUTH", type) == 0) + { + infoType = AUTH; + } + else if (_wcsicmp(L"LIST", type) == 0) + { + infoType = LIST; + } + else if (_wcsicmp(L"PHY", type) == 0) + { + infoType = PHY; + } + else + { + _snwprintf_s(buffer, _TRUNCATE, L"WifiStatus.dll: WifiInfoType=%s not valid", type); + RmLog(LOG_ERROR, buffer); + } + if (infoType != measure->type) + { + changed = true; + } + measure->type = infoType; + + if (changed) + { + measure->statusString.clear(); + + switch (infoType) + { + case SSID: + case ENCRYPTION: + case AUTH: + *maxValue = 0; + break; + case QUALITY: + *maxValue = 100; + break; + } + } +} + +PLUGIN_EXPORT double Update(void* data) +{ + if (g_pInterface == nullptr) return 0; + + MeasureData* measure = (MeasureData*)data; + double value = 0; + + if (measure->type != UNKNOWN) + { + if (measure->type == LIST) + { + PWLAN_AVAILABLE_NETWORK_LIST pwnl = nullptr; + DWORD dwErr = WlanGetAvailableNetworkList(g_hClient, &g_pInterface->InterfaceGuid, 0, nullptr, &pwnl); + + if (ERROR_SUCCESS != dwErr) + { + measure->statusString = L"Error"; + } + else + { + // Size of network name can be up to 64 chars, set to 80 to add room for delimiters + measure->statusString.clear(); + measure->statusString.reserve(80 * measure->listMax); + + UINT printed = 0; // count of how many networks have been printed already + + // Check all items in WLAN NETWORK LIST + for (size_t i = 0; i < pwnl->dwNumberOfItems ; ++i) + { + if (printed == measure->listMax) break; + + // SSID is in UCHAR, convert to WCHAR + std::wstring ssid = ConvertToWide((LPCSTR)pwnl->Network[i].dot11Ssid.ucSSID, (int)pwnl->Network[i].dot11Ssid.uSSIDLength); + + // Prevent duplicates that result from profiles, check using SSID + if (!ssid.empty() && ssid[0] && wcsstr(measure->statusString.c_str(), ssid.c_str()) == nullptr) + { + ++printed; + measure->statusString += ssid; + if (measure->listStyle > 0) + { + if (measure->listStyle == 1 || measure->listStyle == 3) + { + // ADD PHY type + measure->statusString += L" @"; + measure->statusString += GetDot11Str(pwnl->Network[i].dot11PhyTypes[0], 4); + } + if (measure->listStyle == 2 || measure->listStyle == 3) + { + // ADD cipher and authentication + measure->statusString += L" ("; + measure->statusString += GetDot11Str(pwnl->Network[i].dot11DefaultCipherAlgorithm, 1); + measure->statusString += L':'; + measure->statusString += GetDot11Str(pwnl->Network[i].dot11DefaultAuthAlgorithm, 2); + measure->statusString += L')'; + } + } + measure->statusString += L'\n'; + } + } + + WlanFreeMemory(pwnl); + } + } + else + { + ULONG outsize = 0; + PWLAN_CONNECTION_ATTRIBUTES wlan_cattr = nullptr; + DWORD dwErr = WlanQueryInterface(g_hClient, &g_pInterface->InterfaceGuid, wlan_intf_opcode_current_connection, nullptr, &outsize, (PVOID*)&wlan_cattr, nullptr); + + if (ERROR_SUCCESS != dwErr) + { + switch (measure->type) + { + case SSID: + case PHY: + case ENCRYPTION: + case AUTH: + measure->statusString = L"-1"; + break; + } + } + else + { + switch (measure->type) + { + case QUALITY: + value = (double)wlan_cattr->wlanAssociationAttributes.wlanSignalQuality; + break; + + case SSID: + // Need to convert ucSSID to wchar from uchar + measure->statusString = ConvertToWide((LPCSTR)wlan_cattr->wlanAssociationAttributes.dot11Ssid.ucSSID, (int)wlan_cattr->wlanAssociationAttributes.dot11Ssid.uSSIDLength); + // If not connected yet add current status + measure->statusString += GetDot11Str(wlan_cattr->isState, 3); + break; + + case PHY: + measure->statusString = GetDot11Str(wlan_cattr->wlanAssociationAttributes.dot11PhyType, 4); + break; + + case ENCRYPTION: + measure->statusString = GetDot11Str(wlan_cattr->wlanSecurityAttributes.dot11CipherAlgorithm, 1); + break; + + case AUTH: + measure->statusString = GetDot11Str(wlan_cattr->wlanSecurityAttributes.dot11AuthAlgorithm, 2); + break; + + default: // Invalid type + measure->statusString.clear(); + break; + } + + WlanFreeMemory(wlan_cattr); + } + } + } + + return value; +} + + +PLUGIN_EXPORT LPCWSTR GetString(void* data) +{ + if (g_pInterface == nullptr) return nullptr; + + MeasureData* measure = (MeasureData*)data; + + switch (measure->type) + { + case LIST: + case SSID: + case PHY: + case ENCRYPTION: + case AUTH: + return measure->statusString.c_str(); + + default: + return nullptr; + } +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + MeasureData* measure = (MeasureData*)data; + delete measure; + + if (g_Instances > 0) + { + --g_Instances; + + if (g_Instances == 0) + { + FinalizeHandle(); + } + } +} + +/* + switches from winlanapi.h + SDK + in: -DOT11 ENUM (converted to int) + -type of ENUM (cipher=1, auth=2, status=3, phy=4, otherwise=error strings) + out: String to be returned by measure +*/ +LPCWSTR GetDot11Str(int dot11enum, int type) +{ + if (type == 1) + { + switch (dot11enum) + { + case DOT11_CIPHER_ALGO_NONE: + return L"NONE"; + case DOT11_CIPHER_ALGO_WEP40: + return L"WEP40"; + case DOT11_CIPHER_ALGO_TKIP: + return L"TKIP"; + case DOT11_CIPHER_ALGO_CCMP: + return L"AES"; + case DOT11_CIPHER_ALGO_WEP104: + return L"WEP104"; + case DOT11_CIPHER_ALGO_WPA_USE_GROUP: + return L"WPA-GROUP"; + case DOT11_CIPHER_ALGO_WEP: + return L"WEP"; + default: + return L"???"; + } + } + else if (type == 2) + { + switch (dot11enum) + { + case DOT11_AUTH_ALGO_80211_OPEN: + return L"Open"; + case DOT11_AUTH_ALGO_80211_SHARED_KEY: + return L"Shared"; + case DOT11_AUTH_ALGO_WPA_NONE: + return L"WPA-NONE"; + case DOT11_AUTH_ALGO_WPA: + return L"WPA-Enterprise"; + case DOT11_AUTH_ALGO_WPA_PSK: + return L"WPA-Personal"; + case DOT11_AUTH_ALGO_RSNA: + return L"WPA2-Enterprise"; + case DOT11_AUTH_ALGO_RSNA_PSK: + return L"WPA2-Personal"; + default: + return L"???"; + } + } + else if (type == 3) + { + switch (dot11enum) + { + case wlan_interface_state_connected: + return L""; + case wlan_interface_state_authenticating: + return L"(authorizing...)"; + default: + return L"(connecting...)"; + } + } + else if (type == 4) + { + switch (dot11enum) + { + case dot11_phy_type_unknown: + default: + return L"???"; + case dot11_phy_type_dsss: + return L"DSSS"; + case dot11_phy_type_erp: + return L"802.11g"; + case dot11_phy_type_fhss: + return L"FHSS"; + case dot11_phy_type_hrdsss: + return L"802.11b"; + case dot11_phy_type_irbaseband: + return L"IR-Band"; + case dot11_phy_type_ofdm: + return L"802.11a"; + //Case below appears as dot11_phy_type_ht on MSDN + //However its not supported in winlanapi.h ??? + case 7: + return L"802.11n"; + } + } + else + { + switch (dot11enum) + { + case ERROR_INVALID_PARAMETER: + return L"Invalid parameters"; + case ERROR_NOT_ENOUGH_MEMORY: + return L"Not enough memory"; + case ERROR_REMOTE_SESSION_LIMIT_EXCEEDED: + return L"Too many handles already issued"; + default: + return L"Unknown error code"; + } + } +} diff --git a/Plugins/PluginWin7Audio/PluginWin7Audio.rc b/Plugins/PluginWin7Audio/PluginWin7Audio.rc index 0268347a..882f8d27 100644 --- a/Plugins/PluginWin7Audio/PluginWin7Audio.rc +++ b/Plugins/PluginWin7Audio/PluginWin7Audio.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,6,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.6.0.0" - VALUE "LegalCopyright", " 2010 - Reiswaffle" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,6,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.6.0.0" + VALUE "LegalCopyright", " 2010 - Reiswaffle" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginWin7Audio/PluginWin7Audio.vcxproj b/Plugins/PluginWin7Audio/PluginWin7Audio.vcxproj index f06044be..b5b83267 100644 --- a/Plugins/PluginWin7Audio/PluginWin7Audio.vcxproj +++ b/Plugins/PluginWin7Audio/PluginWin7Audio.vcxproj @@ -1,38 +1,38 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{6D032D6B-7656-4743-B454-3388E2921EB0}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>Win7AudioPlugin</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ResourceCompile Include="PluginWin7Audio.rc" /> - </ItemGroup> - <ItemGroup> - <ClInclude Include="PolicyConfig.h" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="Win7AudioPlugin.cpp" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{6D032D6B-7656-4743-B454-3388E2921EB0}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>Win7AudioPlugin</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ResourceCompile Include="PluginWin7Audio.rc" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="PolicyConfig.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="Win7AudioPlugin.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginWin7Audio/PolicyConfig.h b/Plugins/PluginWin7Audio/PolicyConfig.h index e4e07fbd..ed9c12d8 100644 --- a/Plugins/PluginWin7Audio/PolicyConfig.h +++ b/Plugins/PluginWin7Audio/PolicyConfig.h @@ -1,92 +1,92 @@ -// ---------------------------------------------------------------------------- -// PolicyConfig.h -// Undocumented COM-interface IPolicyConfig. -// Use for set default audio render endpoint -// @author EreTIk -// ---------------------------------------------------------------------------- - - -#pragma once - -#include <Mmreg.h> - -// ---------------------------------------------------------------------------- -// class CPolicyConfigClient -// {294935CE-F637-4E7C-A41B-AB255460B862} -// -// interface IPolicyConfig -// {568b9108-44bf-40b4-9006-86afe5b5a620} -// -// Query interface: -// CComPtr<IPolicyConfig> PolicyConfig; -// PolicyConfig.CoCreateInstance(__uuidof(CPolicyConfigClient)); -// ---------------------------------------------------------------------------- -class DECLSPEC_UUID("294935CE-F637-4E7C-A41B-AB255460B862") -CPolicyConfigClient; -interface IPolicyConfig : public IUnknown -{ -public: - - virtual HRESULT GetMixFormat( - PCWSTR, - WAVEFORMATEX ** - ); - - virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( - PCWSTR, - INT, - WAVEFORMATEX ** - ); - - virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( - PCWSTR, - WAVEFORMATEX *, - WAVEFORMATEX * - ); - - virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod( - PCWSTR, - INT, - PINT64, - PINT64 - ); - - virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod( - PCWSTR, - PINT64 - ); - - virtual HRESULT STDMETHODCALLTYPE GetShareMode( - PCWSTR, - struct DeviceShareMode * - ); - - virtual HRESULT STDMETHODCALLTYPE SetShareMode( - PCWSTR, - struct DeviceShareMode * - ); - - virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( - PCWSTR, - const PROPERTYKEY &, - PROPVARIANT * - ); - - virtual HRESULT STDMETHODCALLTYPE SetPropertyValue( - PCWSTR, - const PROPERTYKEY &, - PROPVARIANT * - ); - - virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( - __in PCWSTR wszDeviceId, - __in ERole eRole - ); - - virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility( - PCWSTR, - INT - ); -}; -interface DECLSPEC_UUID("568b9108-44bf-40b4-9006-86afe5b5a620") -IPolicyConfig; +// ---------------------------------------------------------------------------- +// PolicyConfig.h +// Undocumented COM-interface IPolicyConfig. +// Use for set default audio render endpoint +// @author EreTIk +// ---------------------------------------------------------------------------- + + +#pragma once + +#include <Mmreg.h> + +// ---------------------------------------------------------------------------- +// class CPolicyConfigClient +// {294935CE-F637-4E7C-A41B-AB255460B862} +// +// interface IPolicyConfig +// {568b9108-44bf-40b4-9006-86afe5b5a620} +// +// Query interface: +// CComPtr<IPolicyConfig> PolicyConfig; +// PolicyConfig.CoCreateInstance(__uuidof(CPolicyConfigClient)); +// ---------------------------------------------------------------------------- +class DECLSPEC_UUID("294935CE-F637-4E7C-A41B-AB255460B862") +CPolicyConfigClient; +interface IPolicyConfig : public IUnknown +{ +public: + + virtual HRESULT GetMixFormat( + PCWSTR, + WAVEFORMATEX ** + ); + + virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( + PCWSTR, + INT, + WAVEFORMATEX ** + ); + + virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( + PCWSTR, + WAVEFORMATEX *, + WAVEFORMATEX * + ); + + virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod( + PCWSTR, + INT, + PINT64, + PINT64 + ); + + virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod( + PCWSTR, + PINT64 + ); + + virtual HRESULT STDMETHODCALLTYPE GetShareMode( + PCWSTR, + struct DeviceShareMode * + ); + + virtual HRESULT STDMETHODCALLTYPE SetShareMode( + PCWSTR, + struct DeviceShareMode * + ); + + virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( + PCWSTR, + const PROPERTYKEY &, + PROPVARIANT * + ); + + virtual HRESULT STDMETHODCALLTYPE SetPropertyValue( + PCWSTR, + const PROPERTYKEY &, + PROPVARIANT * + ); + + virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( + __in PCWSTR wszDeviceId, + __in ERole eRole + ); + + virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility( + PCWSTR, + INT + ); +}; +interface DECLSPEC_UUID("568b9108-44bf-40b4-9006-86afe5b5a620") +IPolicyConfig; diff --git a/Plugins/PluginWin7Audio/Win7AudioPlugin.cpp b/Plugins/PluginWin7Audio/Win7AudioPlugin.cpp index 3ca6ee2b..b5f70dd2 100644 --- a/Plugins/PluginWin7Audio/Win7AudioPlugin.cpp +++ b/Plugins/PluginWin7Audio/Win7AudioPlugin.cpp @@ -1,440 +1,440 @@ -/* - Copyright (C) 2010 Stefan Hiller - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include <windows.h> -#include <string> -#include <vector> -#include <Mmdeviceapi.h> -#include <Endpointvolume.h> -#include <Functiondiscoverykeys_devpkey.h> -#include "PolicyConfig.h" -#include "../API/RainmeterAPI.h" - -#define SAFE_RELEASE(punk) \ - if ((punk) != nullptr) { (punk)->Release(); (punk) = nullptr; } - -static BOOL com_initialized = FALSE; -static BOOL instance_created = FALSE; -static BOOL is_mute = FALSE; -static float master_volume = 0.5f; - -static enum VolumeAction -{ - INIT, - TOGGLE_MUTE, - GET_VOLUME -}; - -const static CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); -const static IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); -const static IID IID_CPolicyConfigClient = __uuidof(CPolicyConfigClient); -const static IID IID_IPolicyConfig = __uuidof(IPolicyConfig); -const static IID IID_IAudioEndpointVolume = __uuidof(IAudioEndpointVolume); - -static IMMDeviceEnumerator *pEnumerator = 0; -static IMMDeviceCollection *pCollection = 0; - -static std::vector<std::wstring> endpointIDs; - -UINT CleanUp() -{ - SAFE_RELEASE(pCollection); - SAFE_RELEASE(pEnumerator); - instance_created = false; - return 0; -} - -bool InitCom() -{ - if (!com_initialized) com_initialized = SUCCEEDED(CoInitialize(0)); - if (!com_initialized) - { - RmLog(LOG_ERROR, L"Win7AudioPlugin.dll: COM initialization failed"); - return false; - } - HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, 0, CLSCTX_ALL, - IID_IMMDeviceEnumerator, (void**)&pEnumerator); - instance_created = (S_OK == hr && pEnumerator); - if (!instance_created) - { - std::wstring dbg_str = L"Win7AudioPlugin.dll: COM creation failed"; - if (hr == REGDB_E_CLASSNOTREG) dbg_str += L" REGDB_E_CLASSNOTREG"; - else if (hr == CLASS_E_NOAGGREGATION) dbg_str += L" CLASS_E_NOAGGREGATION"; - else if (hr == E_NOINTERFACE) dbg_str += L" E_NOINTERFACE"; - else - { - static WCHAR e_code[256]; - wsprintf(e_code, L" %li", (long)hr); - - dbg_str += e_code; - } - RmLog(LOG_ERROR, dbg_str.c_str()); - return CleanUp() != 0; - } - if (S_OK != pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pCollection) || !pCollection) - { - RmLog(LOG_WARNING, L"Win7AudioPlugin.dll: Could not enumerate AudioEndpoints"); - return CleanUp() != 0; - } - return true; -} - -void UnInitCom() -{ - CleanUp(); - if (com_initialized) CoUninitialize(); - com_initialized = FALSE; -} - -HRESULT RegisterDevice(PCWSTR devID) -{ - HRESULT hr = S_FALSE; - - InitCom(); - IPolicyConfig *pPolicyConfig; - - hr = CoCreateInstance(IID_CPolicyConfigClient, nullptr, - CLSCTX_ALL, IID_IPolicyConfig, - (LPVOID *)&pPolicyConfig); - if (hr == S_OK) - { - hr = pPolicyConfig->SetDefaultEndpoint(devID, eConsole); - if (hr == S_OK) - { - hr = pPolicyConfig->SetDefaultEndpoint(devID, eCommunications); - } - SAFE_RELEASE(pPolicyConfig); - } - - UnInitCom(); - return hr; -} - -std::wstring GetDefaultID() -{ - std::wstring id_default; - IMMDevice * pEndpoint = 0; - if (pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pEndpoint) == S_OK) - { - LPWSTR pwszID = 0; - if (pEndpoint->GetId(&pwszID) == S_OK) - { - id_default = pwszID; - } - CoTaskMemFree(pwszID); - } - - SAFE_RELEASE(pEndpoint) - return id_default; -} - -bool GetWin7AudioState(const VolumeAction action) -{ - IMMDevice * pEndpoint = 0; - IAudioEndpointVolume * pEndptVol = 0; - bool success = false; - - if (InitCom()) - { - if (pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pEndpoint) == S_OK) - { - if (pEndpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, 0, (void**)&pEndptVol) == S_OK) - { - if (pEndptVol->GetMute(&is_mute) == S_OK && action == TOGGLE_MUTE) - { - success = pEndptVol->SetMute(is_mute == TRUE ? FALSE : TRUE, 0) == S_OK; - } - // get current volume - float vol = 0.0f; - if (action != TOGGLE_MUTE && pEndptVol->GetMasterVolumeLevelScalar(&vol) == S_OK) - { - master_volume = vol; - } - } - } - } - - SAFE_RELEASE(pEndptVol) - SAFE_RELEASE(pEndpoint) - UnInitCom(); - return success; -} - -UINT GetIndex() -{ - std::wstring id_default; - if (InitCom()) id_default = GetDefaultID(); - UnInitCom(); - - for (UINT i = 0; i < endpointIDs.size(); ++i) - { - if (_wcsicmp(endpointIDs[i].c_str(), id_default.c_str()) == 0) return i + 1; - } - return 0; -} - -bool SetWin7Volume(UINT volume, int offset = 0) -{ - IMMDevice * pEndpoint = 0; - IAudioEndpointVolume * pEndptVol = 0; - bool success = false; - - if (InitCom()) - { - if (pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pEndpoint) == S_OK) - { - if (pEndpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, 0, (void**)&pEndptVol) == S_OK) - { - pEndptVol->SetMute(FALSE, 0); - float vol = 0.0f; - if (offset != 0) // change master volume + offset - { - float off = static_cast<float>(offset) / 100.0f; - vol = master_volume + off; - vol = (vol < 0.0f) ? 0.0f : ((vol > 1.0f) ? 1.0f : vol); - } - else - { - vol = (float)volume / 100.0f; - } - // set to volume - success = pEndptVol->SetMasterVolumeLevelScalar(vol, 0) == S_OK; - if (success) success = pEndptVol->GetMasterVolumeLevelScalar(&vol) == S_OK; - if (success) master_volume = vol; - } - } - } - - SAFE_RELEASE(pEndptVol) - SAFE_RELEASE(pEndpoint) - UnInitCom(); - return success; -} - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - if (!InitCom()) - { - UnInitCom(); - return; - } - - UINT count; - if (!pCollection || (S_OK != pCollection->GetCount(&count))) - { - UnInitCom(); - return; - } - endpointIDs = std::vector<std::wstring>(count); - - for (UINT i = 0; i < count; ++i) - { - IMMDevice *pEndpoint = 0; - - // Get pointer to endpoint number i. - if (pCollection->Item(i, &pEndpoint) == S_OK) - { - // Get the endpoint ID string. - LPWSTR pwszID = 0; - if (pEndpoint->GetId(&pwszID) == S_OK) - { - endpointIDs[i] = pwszID; - } - CoTaskMemFree(pwszID); - } - SAFE_RELEASE(pEndpoint) - } - UnInitCom(); - GetWin7AudioState(INIT); -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - *maxValue = 100; -} - -PLUGIN_EXPORT double Update(void* data) -{ - GetWin7AudioState(GET_VOLUME); - double volume = is_mute == TRUE ? -1.0 : floor(master_volume * 100.0 + 0.5); // rounding up at 0.5 - return volume > 100.0 ? 100.0 : volume; -} - -PLUGIN_EXPORT LPCWSTR GetString(void* data) -{ - static WCHAR result[256]; - wsprintf(result, L"ERROR"); - if (!InitCom() || !pEnumerator) - { - UnInitCom(); - wsprintf(result, L"ERROR - Initializing COM"); - return result; - } - - IMMDevice * pEndpoint = 0; - if (pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pEndpoint) == S_OK) - { - IPropertyStore * pProps = 0; - if (pEndpoint->OpenPropertyStore(STGM_READ, &pProps) == S_OK) - { - PROPVARIANT varName; - PropVariantInit(&varName); - if (pProps->GetValue(PKEY_Device_DeviceDesc, &varName) == S_OK) - { - wcsncpy(result, varName.pwszVal, 255); - PropVariantClear(&varName); - SAFE_RELEASE(pProps) - SAFE_RELEASE(pEndpoint) - UnInitCom(); - return result; - } - else - { - PropVariantClear(&varName); - SAFE_RELEASE(pProps) - SAFE_RELEASE(pEndpoint) - wsprintf(result, L"ERROR - Getting Device Description"); - } - } - else - { - SAFE_RELEASE(pProps) - SAFE_RELEASE(pEndpoint) - wsprintf(result, L"ERROR - Getting Property"); - } - } - else - { - SAFE_RELEASE(pEndpoint) - wsprintf(result, L"ERROR - Getting Default Device"); - } - - UnInitCom(); - return result; -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - UnInitCom(); -} - -PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) -{ - std::wstring wholeBang = args; - - size_t pos = wholeBang.find(' '); - if (pos != -1) - { - std::wstring bang = wholeBang.substr(0, pos); - wholeBang.erase(0, pos + 1); - - if (_wcsicmp(bang.c_str(), L"SetOutputIndex") == 0) - { - // Parse parameters - int index = 0; - if (1 == swscanf_s(wholeBang.c_str(), L"%d", &index)) - { - if (endpointIDs.size() <= 0) - { - RmLog(LOG_WARNING, L"Win7AudioPlugin.dll: No device found"); - return; - } - // set to endpoint [index-1] - if (index <= 0) index = 1; - else if (index > (int)endpointIDs.size()) index = (int)endpointIDs.size(); - RegisterDevice(endpointIDs[index - 1].c_str()); - } - else - { - RmLog(LOG_WARNING, L"Win7AudioPlugin.dll: Incorrect number of arguments for bang"); - } - } - else if (_wcsicmp(bang.c_str(), L"SetVolume") == 0) - { - // Parse parameters - int volume = 0; - if (1 == swscanf_s(wholeBang.c_str(), L"%d", &volume)) - { - if (!SetWin7Volume(volume < 0 ? 0 : (volume > 100 ? 100 : (UINT)volume))) - { - RmLog(LOG_ERROR, L"Win7AudioPlugin.dll: Error setting volume"); - } - } - else - { - RmLog(LOG_WARNING, L"Win7AudioPlugin.dll: Incorrect number of arguments for bang"); - } - } - else if (_wcsicmp(bang.c_str(), L"ChangeVolume") == 0) - { - // Parse parameters - int offset = 0; - if (1 == swscanf_s(wholeBang.c_str(), L"%d", &offset) && offset) - { - if (!SetWin7Volume(0, offset)) - { - RmLog(LOG_ERROR, L"Win7AudioPlugin.dll: Error changing volume"); - } - } - else - { - RmLog(LOG_WARNING, L"Win7AudioPlugin.dll: Incorrect number of arguments for bang"); - } - } - else - { - RmLog(LOG_WARNING, L"Win7AudioPlugin.dll: Unknown bang"); - } - - } - else if (_wcsicmp(wholeBang.c_str(), L"ToggleNext") == 0) - { - //RmLog(LOG_NOTICE, L"Win7AudioPlugin.dll: Next device."); - const UINT i = GetIndex(); - if (i) RegisterDevice(endpointIDs[(i == endpointIDs.size()) ? 0 : i].c_str()); - else RmLog(LOG_ERROR, L"Win7AudioPlugin.dll: Update error"); - } - else if (_wcsicmp(wholeBang.c_str(), L"TogglePrevious") == 0) - { - const UINT i = GetIndex(); - if (i) RegisterDevice(endpointIDs[(i == 1) ? endpointIDs.size() - 1 : i - 2].c_str()); - else RmLog(LOG_ERROR, L"Win7AudioPlugin.dll: Update error"); - } - else if (_wcsicmp(wholeBang.c_str(), L"ToggleMute") == 0) - { - GetWin7AudioState(TOGGLE_MUTE); - } - else if (_wcsicmp(wholeBang.c_str(), L"Mute") == 0) - { - if (!is_mute) - { - GetWin7AudioState(TOGGLE_MUTE); - } - } - else if (_wcsicmp(wholeBang.c_str(), L"Unmute") == 0) - { - if (is_mute) - { - GetWin7AudioState(TOGGLE_MUTE); - } - } - else - { - RmLog(LOG_WARNING, L"Win7AudioPlugin.dll: Unknown bang"); - } +/* + Copyright (C) 2010 Stefan Hiller + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <windows.h> +#include <string> +#include <vector> +#include <Mmdeviceapi.h> +#include <Endpointvolume.h> +#include <Functiondiscoverykeys_devpkey.h> +#include "PolicyConfig.h" +#include "../API/RainmeterAPI.h" + +#define SAFE_RELEASE(punk) \ + if ((punk) != nullptr) { (punk)->Release(); (punk) = nullptr; } + +static BOOL com_initialized = FALSE; +static BOOL instance_created = FALSE; +static BOOL is_mute = FALSE; +static float master_volume = 0.5f; + +static enum VolumeAction +{ + INIT, + TOGGLE_MUTE, + GET_VOLUME +}; + +const static CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); +const static IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); +const static IID IID_CPolicyConfigClient = __uuidof(CPolicyConfigClient); +const static IID IID_IPolicyConfig = __uuidof(IPolicyConfig); +const static IID IID_IAudioEndpointVolume = __uuidof(IAudioEndpointVolume); + +static IMMDeviceEnumerator *pEnumerator = 0; +static IMMDeviceCollection *pCollection = 0; + +static std::vector<std::wstring> endpointIDs; + +UINT CleanUp() +{ + SAFE_RELEASE(pCollection); + SAFE_RELEASE(pEnumerator); + instance_created = false; + return 0; +} + +bool InitCom() +{ + if (!com_initialized) com_initialized = SUCCEEDED(CoInitialize(0)); + if (!com_initialized) + { + RmLog(LOG_ERROR, L"Win7AudioPlugin.dll: COM initialization failed"); + return false; + } + HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, 0, CLSCTX_ALL, + IID_IMMDeviceEnumerator, (void**)&pEnumerator); + instance_created = (S_OK == hr && pEnumerator); + if (!instance_created) + { + std::wstring dbg_str = L"Win7AudioPlugin.dll: COM creation failed"; + if (hr == REGDB_E_CLASSNOTREG) dbg_str += L" REGDB_E_CLASSNOTREG"; + else if (hr == CLASS_E_NOAGGREGATION) dbg_str += L" CLASS_E_NOAGGREGATION"; + else if (hr == E_NOINTERFACE) dbg_str += L" E_NOINTERFACE"; + else + { + static WCHAR e_code[256]; + wsprintf(e_code, L" %li", (long)hr); + + dbg_str += e_code; + } + RmLog(LOG_ERROR, dbg_str.c_str()); + return CleanUp() != 0; + } + if (S_OK != pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pCollection) || !pCollection) + { + RmLog(LOG_WARNING, L"Win7AudioPlugin.dll: Could not enumerate AudioEndpoints"); + return CleanUp() != 0; + } + return true; +} + +void UnInitCom() +{ + CleanUp(); + if (com_initialized) CoUninitialize(); + com_initialized = FALSE; +} + +HRESULT RegisterDevice(PCWSTR devID) +{ + HRESULT hr = S_FALSE; + + InitCom(); + IPolicyConfig *pPolicyConfig; + + hr = CoCreateInstance(IID_CPolicyConfigClient, nullptr, + CLSCTX_ALL, IID_IPolicyConfig, + (LPVOID *)&pPolicyConfig); + if (hr == S_OK) + { + hr = pPolicyConfig->SetDefaultEndpoint(devID, eConsole); + if (hr == S_OK) + { + hr = pPolicyConfig->SetDefaultEndpoint(devID, eCommunications); + } + SAFE_RELEASE(pPolicyConfig); + } + + UnInitCom(); + return hr; +} + +std::wstring GetDefaultID() +{ + std::wstring id_default; + IMMDevice * pEndpoint = 0; + if (pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pEndpoint) == S_OK) + { + LPWSTR pwszID = 0; + if (pEndpoint->GetId(&pwszID) == S_OK) + { + id_default = pwszID; + } + CoTaskMemFree(pwszID); + } + + SAFE_RELEASE(pEndpoint) + return id_default; +} + +bool GetWin7AudioState(const VolumeAction action) +{ + IMMDevice * pEndpoint = 0; + IAudioEndpointVolume * pEndptVol = 0; + bool success = false; + + if (InitCom()) + { + if (pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pEndpoint) == S_OK) + { + if (pEndpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, 0, (void**)&pEndptVol) == S_OK) + { + if (pEndptVol->GetMute(&is_mute) == S_OK && action == TOGGLE_MUTE) + { + success = pEndptVol->SetMute(is_mute == TRUE ? FALSE : TRUE, 0) == S_OK; + } + // get current volume + float vol = 0.0f; + if (action != TOGGLE_MUTE && pEndptVol->GetMasterVolumeLevelScalar(&vol) == S_OK) + { + master_volume = vol; + } + } + } + } + + SAFE_RELEASE(pEndptVol) + SAFE_RELEASE(pEndpoint) + UnInitCom(); + return success; +} + +UINT GetIndex() +{ + std::wstring id_default; + if (InitCom()) id_default = GetDefaultID(); + UnInitCom(); + + for (UINT i = 0; i < endpointIDs.size(); ++i) + { + if (_wcsicmp(endpointIDs[i].c_str(), id_default.c_str()) == 0) return i + 1; + } + return 0; +} + +bool SetWin7Volume(UINT volume, int offset = 0) +{ + IMMDevice * pEndpoint = 0; + IAudioEndpointVolume * pEndptVol = 0; + bool success = false; + + if (InitCom()) + { + if (pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pEndpoint) == S_OK) + { + if (pEndpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, 0, (void**)&pEndptVol) == S_OK) + { + pEndptVol->SetMute(FALSE, 0); + float vol = 0.0f; + if (offset != 0) // change master volume + offset + { + float off = static_cast<float>(offset) / 100.0f; + vol = master_volume + off; + vol = (vol < 0.0f) ? 0.0f : ((vol > 1.0f) ? 1.0f : vol); + } + else + { + vol = (float)volume / 100.0f; + } + // set to volume + success = pEndptVol->SetMasterVolumeLevelScalar(vol, 0) == S_OK; + if (success) success = pEndptVol->GetMasterVolumeLevelScalar(&vol) == S_OK; + if (success) master_volume = vol; + } + } + } + + SAFE_RELEASE(pEndptVol) + SAFE_RELEASE(pEndpoint) + UnInitCom(); + return success; +} + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + if (!InitCom()) + { + UnInitCom(); + return; + } + + UINT count; + if (!pCollection || (S_OK != pCollection->GetCount(&count))) + { + UnInitCom(); + return; + } + endpointIDs = std::vector<std::wstring>(count); + + for (UINT i = 0; i < count; ++i) + { + IMMDevice *pEndpoint = 0; + + // Get pointer to endpoint number i. + if (pCollection->Item(i, &pEndpoint) == S_OK) + { + // Get the endpoint ID string. + LPWSTR pwszID = 0; + if (pEndpoint->GetId(&pwszID) == S_OK) + { + endpointIDs[i] = pwszID; + } + CoTaskMemFree(pwszID); + } + SAFE_RELEASE(pEndpoint) + } + UnInitCom(); + GetWin7AudioState(INIT); +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + *maxValue = 100; +} + +PLUGIN_EXPORT double Update(void* data) +{ + GetWin7AudioState(GET_VOLUME); + double volume = is_mute == TRUE ? -1.0 : floor(master_volume * 100.0 + 0.5); // rounding up at 0.5 + return volume > 100.0 ? 100.0 : volume; +} + +PLUGIN_EXPORT LPCWSTR GetString(void* data) +{ + static WCHAR result[256]; + wsprintf(result, L"ERROR"); + if (!InitCom() || !pEnumerator) + { + UnInitCom(); + wsprintf(result, L"ERROR - Initializing COM"); + return result; + } + + IMMDevice * pEndpoint = 0; + if (pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pEndpoint) == S_OK) + { + IPropertyStore * pProps = 0; + if (pEndpoint->OpenPropertyStore(STGM_READ, &pProps) == S_OK) + { + PROPVARIANT varName; + PropVariantInit(&varName); + if (pProps->GetValue(PKEY_Device_DeviceDesc, &varName) == S_OK) + { + wcsncpy(result, varName.pwszVal, 255); + PropVariantClear(&varName); + SAFE_RELEASE(pProps) + SAFE_RELEASE(pEndpoint) + UnInitCom(); + return result; + } + else + { + PropVariantClear(&varName); + SAFE_RELEASE(pProps) + SAFE_RELEASE(pEndpoint) + wsprintf(result, L"ERROR - Getting Device Description"); + } + } + else + { + SAFE_RELEASE(pProps) + SAFE_RELEASE(pEndpoint) + wsprintf(result, L"ERROR - Getting Property"); + } + } + else + { + SAFE_RELEASE(pEndpoint) + wsprintf(result, L"ERROR - Getting Default Device"); + } + + UnInitCom(); + return result; +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + UnInitCom(); +} + +PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) +{ + std::wstring wholeBang = args; + + size_t pos = wholeBang.find(' '); + if (pos != -1) + { + std::wstring bang = wholeBang.substr(0, pos); + wholeBang.erase(0, pos + 1); + + if (_wcsicmp(bang.c_str(), L"SetOutputIndex") == 0) + { + // Parse parameters + int index = 0; + if (1 == swscanf_s(wholeBang.c_str(), L"%d", &index)) + { + if (endpointIDs.size() <= 0) + { + RmLog(LOG_WARNING, L"Win7AudioPlugin.dll: No device found"); + return; + } + // set to endpoint [index-1] + if (index <= 0) index = 1; + else if (index > (int)endpointIDs.size()) index = (int)endpointIDs.size(); + RegisterDevice(endpointIDs[index - 1].c_str()); + } + else + { + RmLog(LOG_WARNING, L"Win7AudioPlugin.dll: Incorrect number of arguments for bang"); + } + } + else if (_wcsicmp(bang.c_str(), L"SetVolume") == 0) + { + // Parse parameters + int volume = 0; + if (1 == swscanf_s(wholeBang.c_str(), L"%d", &volume)) + { + if (!SetWin7Volume(volume < 0 ? 0 : (volume > 100 ? 100 : (UINT)volume))) + { + RmLog(LOG_ERROR, L"Win7AudioPlugin.dll: Error setting volume"); + } + } + else + { + RmLog(LOG_WARNING, L"Win7AudioPlugin.dll: Incorrect number of arguments for bang"); + } + } + else if (_wcsicmp(bang.c_str(), L"ChangeVolume") == 0) + { + // Parse parameters + int offset = 0; + if (1 == swscanf_s(wholeBang.c_str(), L"%d", &offset) && offset) + { + if (!SetWin7Volume(0, offset)) + { + RmLog(LOG_ERROR, L"Win7AudioPlugin.dll: Error changing volume"); + } + } + else + { + RmLog(LOG_WARNING, L"Win7AudioPlugin.dll: Incorrect number of arguments for bang"); + } + } + else + { + RmLog(LOG_WARNING, L"Win7AudioPlugin.dll: Unknown bang"); + } + + } + else if (_wcsicmp(wholeBang.c_str(), L"ToggleNext") == 0) + { + //RmLog(LOG_NOTICE, L"Win7AudioPlugin.dll: Next device."); + const UINT i = GetIndex(); + if (i) RegisterDevice(endpointIDs[(i == endpointIDs.size()) ? 0 : i].c_str()); + else RmLog(LOG_ERROR, L"Win7AudioPlugin.dll: Update error"); + } + else if (_wcsicmp(wholeBang.c_str(), L"TogglePrevious") == 0) + { + const UINT i = GetIndex(); + if (i) RegisterDevice(endpointIDs[(i == 1) ? endpointIDs.size() - 1 : i - 2].c_str()); + else RmLog(LOG_ERROR, L"Win7AudioPlugin.dll: Update error"); + } + else if (_wcsicmp(wholeBang.c_str(), L"ToggleMute") == 0) + { + GetWin7AudioState(TOGGLE_MUTE); + } + else if (_wcsicmp(wholeBang.c_str(), L"Mute") == 0) + { + if (!is_mute) + { + GetWin7AudioState(TOGGLE_MUTE); + } + } + else if (_wcsicmp(wholeBang.c_str(), L"Unmute") == 0) + { + if (is_mute) + { + GetWin7AudioState(TOGGLE_MUTE); + } + } + else + { + RmLog(LOG_WARNING, L"Win7AudioPlugin.dll: Unknown bang"); + } } \ No newline at end of file diff --git a/Plugins/PluginWindowMessage/PluginWindowMessage.rc b/Plugins/PluginWindowMessage/PluginWindowMessage.rc index ee2ccd61..e2e5c01d 100644 --- a/Plugins/PluginWindowMessage/PluginWindowMessage.rc +++ b/Plugins/PluginWindowMessage/PluginWindowMessage.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,1,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "1.1.0.0" - VALUE "LegalCopyright", " 2010 - Rainy" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,1,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "1.1.0.0" + VALUE "LegalCopyright", " 2010 - Rainy" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginWindowMessage/PluginWindowMessage.vcxproj b/Plugins/PluginWindowMessage/PluginWindowMessage.vcxproj index 167606db..0d9091c7 100644 --- a/Plugins/PluginWindowMessage/PluginWindowMessage.vcxproj +++ b/Plugins/PluginWindowMessage/PluginWindowMessage.vcxproj @@ -1,35 +1,35 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>WindowMessagePlugin</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ResourceCompile Include="PluginWindowMessage.rc" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="WindowMessagePlugin.cpp" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>WindowMessagePlugin</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ResourceCompile Include="PluginWindowMessage.rc" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="WindowMessagePlugin.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginWindowMessage/WindowMessagePlugin.cpp b/Plugins/PluginWindowMessage/WindowMessagePlugin.cpp index 31004380..7bbbefc0 100644 --- a/Plugins/PluginWindowMessage/WindowMessagePlugin.cpp +++ b/Plugins/PluginWindowMessage/WindowMessagePlugin.cpp @@ -1,147 +1,147 @@ -/* - Copyright (C) 2005 Kimmo Pekkola - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include <windows.h> -#include <stdio.h> -#include "../../Common/RawString.h" -#include "../../Library/Export.h" // Rainmeter's exported functions - -struct MeasureData -{ - RawString windowName; - RawString windowClass; - RawString value; - WPARAM wParam; - LPARAM lParam; - DWORD uMsg; - - MeasureData() : wParam(), lParam(), uMsg() {} -}; - -PLUGIN_EXPORT void Initialize(void** data, void* rm) -{ - MeasureData* measure = new MeasureData; - *data = measure; -} - -PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) -{ - MeasureData* measure = (MeasureData*)data; - - measure->windowName = RmReadString(rm, L"WindowName", L""); - measure->windowClass = RmReadString(rm, L"WindowClass", L""); - - DWORD uMsg, wParam, lParam; - LPCWSTR message = RmReadString(rm, L"WindowMessage", L""); - if (3 == swscanf(message, L"%u %u %u", &uMsg, &wParam, &lParam)) - { - measure->uMsg = uMsg; - measure->wParam = wParam; - measure->lParam = lParam; - } -} - -PLUGIN_EXPORT double Update(void* data) -{ - MeasureData* measure = (MeasureData*)data; - - HWND hwnd = FindWindow( - measure->windowClass.empty() ? nullptr : measure->windowClass.c_str(), - measure->windowName.empty() ? nullptr : measure->windowName.c_str()); - - if (hwnd) - { - if (measure->uMsg == 0) - { - // Get window text - WCHAR buffer[256]; - GetWindowText(hwnd, buffer, 256); - measure->value = buffer; - } - else - { - return (double)SendMessage(hwnd, measure->uMsg, measure->wParam, measure->lParam); - } - } - else if (measure->uMsg == 0) - { - measure->value.clear(); - } - - return 0.0; -} - -PLUGIN_EXPORT LPCWSTR GetString(void* data) -{ - MeasureData* measure = (MeasureData*)data; - - if (measure->uMsg == 0) - { - return measure->value.c_str(); - } - - return nullptr; -} - -PLUGIN_EXPORT void Finalize(void* data) -{ - MeasureData* measure = (MeasureData*)data; - delete measure; -} - -PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) -{ - MeasureData* measure = (MeasureData*)data; - - const WCHAR* pos = wcschr(args, L' '); - if (pos) - { - size_t len = pos - args; - if (_wcsnicmp(args, L"SendMessage", len) == 0) - { - ++pos; - - // Parse parameters - DWORD uMsg, wParam, lParam; - if (3 == swscanf(pos, L"%u %u %u", &uMsg, &wParam, &lParam)) - { - - HWND hwnd = FindWindow( - measure->windowClass.empty() ? nullptr : measure->windowClass.c_str(), - measure->windowName.empty() ? nullptr : measure->windowName.c_str()); - - if (hwnd) - { - PostMessage(hwnd, uMsg, wParam, lParam); - } - else - { - RmLog(LOG_ERROR, L"WindowMessagePlugin.dll: Unable to find window"); - } - } - else - { - RmLog(LOG_WARNING, L"WindowMessagePlugin.dll: Incorrect number of arguments for bang"); - } - - return; - } - } - - RmLog(LOG_WARNING, L"WindowMessagePlugin.dll: Unknown bang"); -} +/* + Copyright (C) 2005 Kimmo Pekkola + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <windows.h> +#include <stdio.h> +#include "../../Common/RawString.h" +#include "../../Library/Export.h" // Rainmeter's exported functions + +struct MeasureData +{ + RawString windowName; + RawString windowClass; + RawString value; + WPARAM wParam; + LPARAM lParam; + DWORD uMsg; + + MeasureData() : wParam(), lParam(), uMsg() {} +}; + +PLUGIN_EXPORT void Initialize(void** data, void* rm) +{ + MeasureData* measure = new MeasureData; + *data = measure; +} + +PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue) +{ + MeasureData* measure = (MeasureData*)data; + + measure->windowName = RmReadString(rm, L"WindowName", L""); + measure->windowClass = RmReadString(rm, L"WindowClass", L""); + + DWORD uMsg, wParam, lParam; + LPCWSTR message = RmReadString(rm, L"WindowMessage", L""); + if (3 == swscanf(message, L"%u %u %u", &uMsg, &wParam, &lParam)) + { + measure->uMsg = uMsg; + measure->wParam = wParam; + measure->lParam = lParam; + } +} + +PLUGIN_EXPORT double Update(void* data) +{ + MeasureData* measure = (MeasureData*)data; + + HWND hwnd = FindWindow( + measure->windowClass.empty() ? nullptr : measure->windowClass.c_str(), + measure->windowName.empty() ? nullptr : measure->windowName.c_str()); + + if (hwnd) + { + if (measure->uMsg == 0) + { + // Get window text + WCHAR buffer[256]; + GetWindowText(hwnd, buffer, 256); + measure->value = buffer; + } + else + { + return (double)SendMessage(hwnd, measure->uMsg, measure->wParam, measure->lParam); + } + } + else if (measure->uMsg == 0) + { + measure->value.clear(); + } + + return 0.0; +} + +PLUGIN_EXPORT LPCWSTR GetString(void* data) +{ + MeasureData* measure = (MeasureData*)data; + + if (measure->uMsg == 0) + { + return measure->value.c_str(); + } + + return nullptr; +} + +PLUGIN_EXPORT void Finalize(void* data) +{ + MeasureData* measure = (MeasureData*)data; + delete measure; +} + +PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) +{ + MeasureData* measure = (MeasureData*)data; + + const WCHAR* pos = wcschr(args, L' '); + if (pos) + { + size_t len = pos - args; + if (_wcsnicmp(args, L"SendMessage", len) == 0) + { + ++pos; + + // Parse parameters + DWORD uMsg, wParam, lParam; + if (3 == swscanf(pos, L"%u %u %u", &uMsg, &wParam, &lParam)) + { + + HWND hwnd = FindWindow( + measure->windowClass.empty() ? nullptr : measure->windowClass.c_str(), + measure->windowName.empty() ? nullptr : measure->windowName.c_str()); + + if (hwnd) + { + PostMessage(hwnd, uMsg, wParam, lParam); + } + else + { + RmLog(LOG_ERROR, L"WindowMessagePlugin.dll: Unable to find window"); + } + } + else + { + RmLog(LOG_WARNING, L"WindowMessagePlugin.dll: Incorrect number of arguments for bang"); + } + + return; + } + } + + RmLog(LOG_WARNING, L"WindowMessagePlugin.dll: Unknown bang"); +} diff --git a/Plugins/PluginiTunes/PluginiTunes.rc b/Plugins/PluginiTunes/PluginiTunes.rc index 7c56c2ad..6760e714 100644 --- a/Plugins/PluginiTunes/PluginiTunes.rc +++ b/Plugins/PluginiTunes/PluginiTunes.rc @@ -1,40 +1,40 @@ -#include <VerRsrc.h> -#include "../../Version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,2,0,0 - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT_UNKNOWN -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "0.2.0.0" - VALUE "LegalCopyright", " 2010 - Elestel" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} +#include <VerRsrc.h> +#include "../../Version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,2,0,0 + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT_UNKNOWN +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "0.2.0.0" + VALUE "LegalCopyright", " 2010 - Elestel" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/Plugins/PluginiTunes/PluginiTunes.vcxproj b/Plugins/PluginiTunes/PluginiTunes.vcxproj index 15c1b445..09c9fd8f 100644 --- a/Plugins/PluginiTunes/PluginiTunes.vcxproj +++ b/Plugins/PluginiTunes/PluginiTunes.vcxproj @@ -1,40 +1,40 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{A2DD3CBE-B140-4892-A875-24107FA52518}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <TargetName>iTunesPlugin</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <AdditionalIncludeDirectories>iTunesCOMWindowsSDK;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClInclude Include="iTunesCOMWindowsSDK\iTunesCOMInterface.h" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="iTunesCOMWindowsSDK\iTunesCOMInterface_i.c" /> - <ClCompile Include="iTunesPlugin.cpp" /> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="PluginiTunes.rc" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{A2DD3CBE-B140-4892-A875-24107FA52518}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <TargetName>iTunesPlugin</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\RainmeterPlugin.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <AdditionalIncludeDirectories>iTunesCOMWindowsSDK;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="iTunesCOMWindowsSDK\iTunesCOMInterface.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="iTunesCOMWindowsSDK\iTunesCOMInterface_i.c" /> + <ClCompile Include="iTunesPlugin.cpp" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="PluginiTunes.rc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/Plugins/PluginiTunes/iTunesCOMWindowsSDK/iTunesCOMInterface.h b/Plugins/PluginiTunes/iTunesCOMWindowsSDK/iTunesCOMInterface.h index a07780e1..bce38816 100644 --- a/Plugins/PluginiTunes/iTunesCOMWindowsSDK/iTunesCOMInterface.h +++ b/Plugins/PluginiTunes/iTunesCOMWindowsSDK/iTunesCOMInterface.h @@ -1,14384 +1,14384 @@ - - -/* this ALWAYS GENERATED file contains the definitions for the interfaces */ - - - /* File created by MIDL compiler version 6.00.0366 */ -/* at Wed Jun 25 17:02:20 2008 - */ -/* Compiler settings for iTunesCOMInterface.idl: - Oicf, W1, Zp8, env=Win32 (32b run) - protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: - __declspec(uuid()), __declspec(selectany), __declspec(novtable) - DECLSPEC_UUID(), MIDL_INTERFACE() -*/ -//@@MIDL_FILE_HEADING( ) - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ - - -/* verify that the <rpcndr.h> version is high enough to compile this file*/ -#ifndef __REQUIRED_RPCNDR_H_VERSION__ -#define __REQUIRED_RPCNDR_H_VERSION__ 475 -#endif - -#include "rpc.h" -#include "rpcndr.h" - -#ifndef __RPCNDR_H_VERSION__ -#error this stub requires an updated version of <rpcndr.h> -#endif // __RPCNDR_H_VERSION__ - - -#ifndef __iTunesCOMInterface_h__ -#define __iTunesCOMInterface_h__ - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -#pragma once -#endif - -/* Forward Declarations */ - -#ifndef __IITObject_FWD_DEFINED__ -#define __IITObject_FWD_DEFINED__ -typedef interface IITObject IITObject; -#endif /* __IITObject_FWD_DEFINED__ */ - - -#ifndef __IITSource_FWD_DEFINED__ -#define __IITSource_FWD_DEFINED__ -typedef interface IITSource IITSource; -#endif /* __IITSource_FWD_DEFINED__ */ - - -#ifndef __IITSourceCollection_FWD_DEFINED__ -#define __IITSourceCollection_FWD_DEFINED__ -typedef interface IITSourceCollection IITSourceCollection; -#endif /* __IITSourceCollection_FWD_DEFINED__ */ - - -#ifndef __IITEncoder_FWD_DEFINED__ -#define __IITEncoder_FWD_DEFINED__ -typedef interface IITEncoder IITEncoder; -#endif /* __IITEncoder_FWD_DEFINED__ */ - - -#ifndef __IITEncoderCollection_FWD_DEFINED__ -#define __IITEncoderCollection_FWD_DEFINED__ -typedef interface IITEncoderCollection IITEncoderCollection; -#endif /* __IITEncoderCollection_FWD_DEFINED__ */ - - -#ifndef __IITEQPreset_FWD_DEFINED__ -#define __IITEQPreset_FWD_DEFINED__ -typedef interface IITEQPreset IITEQPreset; -#endif /* __IITEQPreset_FWD_DEFINED__ */ - - -#ifndef __IITEQPresetCollection_FWD_DEFINED__ -#define __IITEQPresetCollection_FWD_DEFINED__ -typedef interface IITEQPresetCollection IITEQPresetCollection; -#endif /* __IITEQPresetCollection_FWD_DEFINED__ */ - - -#ifndef __IITPlaylist_FWD_DEFINED__ -#define __IITPlaylist_FWD_DEFINED__ -typedef interface IITPlaylist IITPlaylist; -#endif /* __IITPlaylist_FWD_DEFINED__ */ - - -#ifndef __IITOperationStatus_FWD_DEFINED__ -#define __IITOperationStatus_FWD_DEFINED__ -typedef interface IITOperationStatus IITOperationStatus; -#endif /* __IITOperationStatus_FWD_DEFINED__ */ - - -#ifndef __IITConvertOperationStatus_FWD_DEFINED__ -#define __IITConvertOperationStatus_FWD_DEFINED__ -typedef interface IITConvertOperationStatus IITConvertOperationStatus; -#endif /* __IITConvertOperationStatus_FWD_DEFINED__ */ - - -#ifndef __IITLibraryPlaylist_FWD_DEFINED__ -#define __IITLibraryPlaylist_FWD_DEFINED__ -typedef interface IITLibraryPlaylist IITLibraryPlaylist; -#endif /* __IITLibraryPlaylist_FWD_DEFINED__ */ - - -#ifndef __IITUserPlaylist_FWD_DEFINED__ -#define __IITUserPlaylist_FWD_DEFINED__ -typedef interface IITUserPlaylist IITUserPlaylist; -#endif /* __IITUserPlaylist_FWD_DEFINED__ */ - - -#ifndef __IITTrack_FWD_DEFINED__ -#define __IITTrack_FWD_DEFINED__ -typedef interface IITTrack IITTrack; -#endif /* __IITTrack_FWD_DEFINED__ */ - - -#ifndef __IITTrackCollection_FWD_DEFINED__ -#define __IITTrackCollection_FWD_DEFINED__ -typedef interface IITTrackCollection IITTrackCollection; -#endif /* __IITTrackCollection_FWD_DEFINED__ */ - - -#ifndef __IITVisual_FWD_DEFINED__ -#define __IITVisual_FWD_DEFINED__ -typedef interface IITVisual IITVisual; -#endif /* __IITVisual_FWD_DEFINED__ */ - - -#ifndef __IITVisualCollection_FWD_DEFINED__ -#define __IITVisualCollection_FWD_DEFINED__ -typedef interface IITVisualCollection IITVisualCollection; -#endif /* __IITVisualCollection_FWD_DEFINED__ */ - - -#ifndef __IITWindow_FWD_DEFINED__ -#define __IITWindow_FWD_DEFINED__ -typedef interface IITWindow IITWindow; -#endif /* __IITWindow_FWD_DEFINED__ */ - - -#ifndef __IITBrowserWindow_FWD_DEFINED__ -#define __IITBrowserWindow_FWD_DEFINED__ -typedef interface IITBrowserWindow IITBrowserWindow; -#endif /* __IITBrowserWindow_FWD_DEFINED__ */ - - -#ifndef __IITWindowCollection_FWD_DEFINED__ -#define __IITWindowCollection_FWD_DEFINED__ -typedef interface IITWindowCollection IITWindowCollection; -#endif /* __IITWindowCollection_FWD_DEFINED__ */ - - -#ifndef __IiTunes_FWD_DEFINED__ -#define __IiTunes_FWD_DEFINED__ -typedef interface IiTunes IiTunes; -#endif /* __IiTunes_FWD_DEFINED__ */ - - -#ifndef ___IiTunesEvents_FWD_DEFINED__ -#define ___IiTunesEvents_FWD_DEFINED__ -typedef interface _IiTunesEvents _IiTunesEvents; -#endif /* ___IiTunesEvents_FWD_DEFINED__ */ - - -#ifndef ___IITConvertOperationStatusEvents_FWD_DEFINED__ -#define ___IITConvertOperationStatusEvents_FWD_DEFINED__ -typedef interface _IITConvertOperationStatusEvents _IITConvertOperationStatusEvents; -#endif /* ___IITConvertOperationStatusEvents_FWD_DEFINED__ */ - - -#ifndef __iTunesApp_FWD_DEFINED__ -#define __iTunesApp_FWD_DEFINED__ - -#ifdef __cplusplus -typedef class iTunesApp iTunesApp; -#else -typedef struct iTunesApp iTunesApp; -#endif /* __cplusplus */ - -#endif /* __iTunesApp_FWD_DEFINED__ */ - - -#ifndef __iTunesConvertOperationStatus_FWD_DEFINED__ -#define __iTunesConvertOperationStatus_FWD_DEFINED__ - -#ifdef __cplusplus -typedef class iTunesConvertOperationStatus iTunesConvertOperationStatus; -#else -typedef struct iTunesConvertOperationStatus iTunesConvertOperationStatus; -#endif /* __cplusplus */ - -#endif /* __iTunesConvertOperationStatus_FWD_DEFINED__ */ - - -#ifndef __IITArtwork_FWD_DEFINED__ -#define __IITArtwork_FWD_DEFINED__ -typedef interface IITArtwork IITArtwork; -#endif /* __IITArtwork_FWD_DEFINED__ */ - - -#ifndef __IITArtworkCollection_FWD_DEFINED__ -#define __IITArtworkCollection_FWD_DEFINED__ -typedef interface IITArtworkCollection IITArtworkCollection; -#endif /* __IITArtworkCollection_FWD_DEFINED__ */ - - -#ifndef __IITURLTrack_FWD_DEFINED__ -#define __IITURLTrack_FWD_DEFINED__ -typedef interface IITURLTrack IITURLTrack; -#endif /* __IITURLTrack_FWD_DEFINED__ */ - - -#ifndef __IITAudioCDPlaylist_FWD_DEFINED__ -#define __IITAudioCDPlaylist_FWD_DEFINED__ -typedef interface IITAudioCDPlaylist IITAudioCDPlaylist; -#endif /* __IITAudioCDPlaylist_FWD_DEFINED__ */ - - -#ifndef __IITPlaylistCollection_FWD_DEFINED__ -#define __IITPlaylistCollection_FWD_DEFINED__ -typedef interface IITPlaylistCollection IITPlaylistCollection; -#endif /* __IITPlaylistCollection_FWD_DEFINED__ */ - - -#ifndef __IITIPodSource_FWD_DEFINED__ -#define __IITIPodSource_FWD_DEFINED__ -typedef interface IITIPodSource IITIPodSource; -#endif /* __IITIPodSource_FWD_DEFINED__ */ - - -#ifndef __IITFileOrCDTrack_FWD_DEFINED__ -#define __IITFileOrCDTrack_FWD_DEFINED__ -typedef interface IITFileOrCDTrack IITFileOrCDTrack; -#endif /* __IITFileOrCDTrack_FWD_DEFINED__ */ - - -#ifndef __IITPlaylistWindow_FWD_DEFINED__ -#define __IITPlaylistWindow_FWD_DEFINED__ -typedef interface IITPlaylistWindow IITPlaylistWindow; -#endif /* __IITPlaylistWindow_FWD_DEFINED__ */ - - -/* header files for imported files */ -#include "oaidl.h" -#include "ocidl.h" -#include "DispEx.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -void * __RPC_USER MIDL_user_allocate(size_t); -void __RPC_USER MIDL_user_free( void * ); - -/* interface __MIDL_itf_iTunesCOMInterface_0000 */ -/* [local] */ - -typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("4B73428D-2F56-4833-8E5D-65590E45FEAD") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0000_0001 - { kITTypeLibrary_MajorVersion = 1, - kITTypeLibrary_MinorVersion = 11 - } ITVersion; - -typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("4C25623B-F990-4ebd-8970-F29A70084B8C") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0000_0002 - { ITUNES_E_USERCANCEL = 0xa0040201, - ITUNES_E_OBJECTDELETED = 0xa0040202, - ITUNES_E_OBJECTLOCKED = 0xa0040203, - ITUNES_E_CONVERSIONINPROGRESS = 0xa0040204, - ITUNES_E_MUSICSTOREDISABLED = 0xa0040205, - ITUNES_E_OBJECTEXISTS = 0xa0040206, - ITUNES_E_PODCASTSDISABLED = 0xa0040207 - } ITErrors; - - - -extern RPC_IF_HANDLE __MIDL_itf_iTunesCOMInterface_0000_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_iTunesCOMInterface_0000_v0_0_s_ifspec; - - -#ifndef __iTunesLib_LIBRARY_DEFINED__ -#define __iTunesLib_LIBRARY_DEFINED__ - -/* library iTunesLib */ -/* [helpstring][uuid][version] */ - - - - - - - - - - - - - - - - - - - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("3D502ACA-B474-4640-A2A4-C149538345EC") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0001 - { ITPlayerStateStopped = 0, - ITPlayerStatePlaying = ITPlayerStateStopped + 1, - ITPlayerStateFastForward = ITPlayerStatePlaying + 1, - ITPlayerStateRewind = ITPlayerStateFastForward + 1 - } ITPlayerState; - -typedef /* [public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("5319FADA-0F39-4015-82A0-48B8B871C63C") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0002 - { ITVisualSizeSmall = 0, - ITVisualSizeMedium = ITVisualSizeSmall + 1, - ITVisualSizeLarge = ITVisualSizeMedium + 1 - } ITVisualSize; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("C8128C8D-EDE0-4f0e-AEB1-08D24A91C551") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0003 - { ITCOMDisabledReasonOther = 0, - ITCOMDisabledReasonDialog = ITCOMDisabledReasonOther + 1, - ITCOMDisabledReasonQuitting = ITCOMDisabledReasonDialog + 1 - } ITCOMDisabledReason; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("6B1BD814-CA6E-4063-9EDA-4128D31068C1") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0004 - { ITPlayButtonStatePlayDisabled = 0, - ITPlayButtonStatePlayEnabled = ITPlayButtonStatePlayDisabled + 1, - ITPlayButtonStatePauseEnabled = ITPlayButtonStatePlayEnabled + 1, - ITPlayButtonStatePauseDisabled = ITPlayButtonStatePauseEnabled + 1, - ITPlayButtonStateStopEnabled = ITPlayButtonStatePauseDisabled + 1, - ITPlayButtonStateStopDisabled = ITPlayButtonStateStopEnabled + 1 - } ITPlayButtonState; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("8AF85488-2154-4e46-B65B-1972A43493EF") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0005 - { ITPlayerButtonPrevious = 0, - ITPlayerButtonPlay = ITPlayerButtonPrevious + 1, - ITPlayerButtonNext = ITPlayerButtonPlay + 1 - } ITPlayerButton; - -typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("2129AB11-F23F-485e-B15A-3F8573294F9A") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0006 - { ITPlayerButtonModifierKeyNone = 0, - ITPlayerButtonModifierKeyShift = 1, - ITPlayerButtonModifierKeyControl = 2, - ITPlayerButtonModifierKeyAlt = 4, - ITPlayerButtonModifierKeyCapsLock = 8 - } ITPlayerButtonModifierKey; - -typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("3194F5F4-8F52-41e6-AB8E-4221CFE29550") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0275_0001 - { ITEventDatabaseChanged = 1, - ITEventPlayerPlay = 2, - ITEventPlayerStop = 3, - ITEventPlayerPlayingTrackChanged = 4, - ITEventUserInterfaceEnabled = 5, - ITEventCOMCallsDisabled = 6, - ITEventCOMCallsEnabled = 7, - ITEventQuitting = 8, - ITEventAboutToPromptUserToQuit = 9, - ITEventSoundVolumeChanged = 10 - } ITEvent; - -typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("2E4D55FA-1CD3-4831-8751-0C11EC4FF6FD") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0276_0001 - { ITConvertOperationStatusChanged = 1, - ITConvertOperationComplete = 2 - } ITConvertOperationStatusEvent; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("269E36A5-1728-46e4-BF04-93032C3DD51C") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0277_0001 - { ITArtworkFormatUnknown = 0, - ITArtworkFormatJPEG = ITArtworkFormatUnknown + 1, - ITArtworkFormatPNG = ITArtworkFormatJPEG + 1, - ITArtworkFormatBMP = ITArtworkFormatPNG + 1 - } ITArtworkFormat; - - - - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("DDE76D6E-5F8C-4bda-AFA6-69E82218CFF3") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0001 - { ITPlaylistKindUnknown = 0, - ITPlaylistKindLibrary = ITPlaylistKindUnknown + 1, - ITPlaylistKindUser = ITPlaylistKindLibrary + 1, - ITPlaylistKindCD = ITPlaylistKindUser + 1, - ITPlaylistKindDevice = ITPlaylistKindCD + 1, - ITPlaylistKindRadioTuner = ITPlaylistKindDevice + 1 - } ITPlaylistKind; - -typedef /* [public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("4E1D67A4-6C7A-4c7d-821C-03AF7EB10C35") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0002 - { ITPlaylistRepeatModeOff = 0, - ITPlaylistRepeatModeOne = ITPlaylistRepeatModeOff + 1, - ITPlaylistRepeatModeAll = ITPlaylistRepeatModeOne + 1 - } ITPlaylistRepeatMode; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("BB8E7701-1E77-4972-B6C4-C70AC216F468") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0003 - { ITPlaylistPrintKindPlaylist = 0, - ITPlaylistPrintKindAlbumlist = ITPlaylistPrintKindPlaylist + 1, - ITPlaylistPrintKindInsert = ITPlaylistPrintKindAlbumlist + 1 - } ITPlaylistPrintKind; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("58765E77-E34A-4d67-AC12-5B5BA33EA08F") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0004 - { ITPlaylistSearchFieldAll = 0, - ITPlaylistSearchFieldVisible = ITPlaylistSearchFieldAll + 1, - ITPlaylistSearchFieldArtists = ITPlaylistSearchFieldVisible + 1, - ITPlaylistSearchFieldAlbums = ITPlaylistSearchFieldArtists + 1, - ITPlaylistSearchFieldComposers = ITPlaylistSearchFieldAlbums + 1, - ITPlaylistSearchFieldSongNames = ITPlaylistSearchFieldComposers + 1 - } ITPlaylistSearchField; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("62BC24E6-5C77-4fb7-AA6C-B7FA40C6095D") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0285_0001 - { ITUserPlaylistSpecialKindNone = 0, - ITUserPlaylistSpecialKindPurchasedMusic = ITUserPlaylistSpecialKindNone + 1, - ITUserPlaylistSpecialKindPartyShuffle = ITUserPlaylistSpecialKindPurchasedMusic + 1, - ITUserPlaylistSpecialKindPodcasts = ITUserPlaylistSpecialKindPartyShuffle + 1, - ITUserPlaylistSpecialKindFolder = ITUserPlaylistSpecialKindPodcasts + 1, - ITUserPlaylistSpecialKindVideos = ITUserPlaylistSpecialKindFolder + 1, - ITUserPlaylistSpecialKindMusic = ITUserPlaylistSpecialKindVideos + 1, - ITUserPlaylistSpecialKindMovies = ITUserPlaylistSpecialKindMusic + 1, - ITUserPlaylistSpecialKindTVShows = ITUserPlaylistSpecialKindMovies + 1, - ITUserPlaylistSpecialKindAudiobooks = ITUserPlaylistSpecialKindTVShows + 1 - } ITUserPlaylistSpecialKind; - - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("5F35912B-E633-4930-9E25-09489BAED75A") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0288_0001 - { ITSourceKindUnknown = 0, - ITSourceKindLibrary = ITSourceKindUnknown + 1, - ITSourceKindIPod = ITSourceKindLibrary + 1, - ITSourceKindAudioCD = ITSourceKindIPod + 1, - ITSourceKindMP3CD = ITSourceKindAudioCD + 1, - ITSourceKindDevice = ITSourceKindMP3CD + 1, - ITSourceKindRadioTuner = ITSourceKindDevice + 1, - ITSourceKindSharedLibrary = ITSourceKindRadioTuner + 1 - } ITSourceKind; - - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("ACA133C5-4697-4d5f-98B1-D9881B85FE98") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0291_0001 - { ITTrackKindUnknown = 0, - ITTrackKindFile = ITTrackKindUnknown + 1, - ITTrackKindCD = ITTrackKindFile + 1, - ITTrackKindURL = ITTrackKindCD + 1, - ITTrackKindDevice = ITTrackKindURL + 1, - ITTrackKindSharedLibrary = ITTrackKindDevice + 1 - } ITTrackKind; - -typedef /* [public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("735ECC17-38CC-4d4d-A838-24AF7DCB440E") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0291_0002 - { ITVideoKindNone = 0, - ITVideoKindMovie = ITVideoKindNone + 1, - ITVideoKindMusicVideo = ITVideoKindMovie + 1, - ITVideoKindTVShow = ITVideoKindMusicVideo + 1 - } ITVideoKind; - -typedef /* [public][public][public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("5C75B72C-D066-4faa-8732-D9ED71A6CBD9") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0291_0003 - { ITRatingKindUser = 0, - ITRatingKindComputed = ITRatingKindUser + 1 - } ITRatingKind; - -typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("C20CE920-EFD9-4c1a-8036-95A895741214") -enum __MIDL___MIDL_itf_iTunesCOMInterface_0297_0001 - { ITWindowKindUnknown = 0, - ITWindowKindBrowser = ITWindowKindUnknown + 1, - ITWindowKindPlaylist = ITWindowKindBrowser + 1, - ITWindowKindEQ = ITWindowKindPlaylist + 1, - ITWindowKindArtwork = ITWindowKindEQ + 1, - ITWindowKindNowPlaying = ITWindowKindArtwork + 1 - } ITWindowKind; - - -EXTERN_C const IID LIBID_iTunesLib; - -#ifndef __IITObject_INTERFACE_DEFINED__ -#define __IITObject_INTERFACE_DEFINED__ - -/* interface IITObject */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITObject; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("9FAB0E27-70D7-4e3a-9965-B0C8B8869BB6") - IITObject : public IDispatch - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetITObjectIDs( - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( - /* [retval][out] */ BSTR *name) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Name( - /* [in] */ BSTR name) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Index( - /* [retval][out] */ long *index) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SourceID( - /* [retval][out] */ long *sourceID) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlaylistID( - /* [retval][out] */ long *playlistID) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackID( - /* [retval][out] */ long *trackID) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackDatabaseID( - /* [retval][out] */ long *databaseID) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITObjectVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITObject * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITObject * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITObject * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITObject * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITObject * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITObject * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITObject * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITObject * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITObject * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITObject * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITObject * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITObject * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITObject * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITObject * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITObject * This, - /* [retval][out] */ long *databaseID); - - END_INTERFACE - } IITObjectVtbl; - - interface IITObject - { - CONST_VTBL struct IITObjectVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITObject_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITObject_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITObject_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITObject_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITObject_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITObject_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITObject_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITObject_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITObject_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITObject_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITObject_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITObject_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITObject_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITObject_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITObject_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITObject_GetITObjectIDs_Proxy( - IITObject * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - -void __RPC_STUB IITObject_GetITObjectIDs_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_Name_Proxy( - IITObject * This, - /* [retval][out] */ BSTR *name); - - -void __RPC_STUB IITObject_get_Name_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITObject_put_Name_Proxy( - IITObject * This, - /* [in] */ BSTR name); - - -void __RPC_STUB IITObject_put_Name_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_Index_Proxy( - IITObject * This, - /* [retval][out] */ long *index); - - -void __RPC_STUB IITObject_get_Index_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_SourceID_Proxy( - IITObject * This, - /* [retval][out] */ long *sourceID); - - -void __RPC_STUB IITObject_get_SourceID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_PlaylistID_Proxy( - IITObject * This, - /* [retval][out] */ long *playlistID); - - -void __RPC_STUB IITObject_get_PlaylistID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_TrackID_Proxy( - IITObject * This, - /* [retval][out] */ long *trackID); - - -void __RPC_STUB IITObject_get_TrackID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_TrackDatabaseID_Proxy( - IITObject * This, - /* [retval][out] */ long *databaseID); - - -void __RPC_STUB IITObject_get_TrackDatabaseID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITObject_INTERFACE_DEFINED__ */ - - -#ifndef __IITSource_INTERFACE_DEFINED__ -#define __IITSource_INTERFACE_DEFINED__ - -/* interface IITSource */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITSource; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("AEC1C4D3-AEF1-4255-B892-3E3D13ADFDF9") - IITSource : public IITObject - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( - /* [retval][out] */ ITSourceKind *kind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Capacity( - /* [retval][out] */ double *capacity) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_FreeSpace( - /* [retval][out] */ double *freespace) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlists( - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITSourceVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITSource * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITSource * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITSource * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITSource * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITSource * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITSource * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITSource * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITSource * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITSource * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITSource * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITSource * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITSource * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITSource * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITSource * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITSource * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITSource * This, - /* [retval][out] */ ITSourceKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Capacity )( - IITSource * This, - /* [retval][out] */ double *capacity); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_FreeSpace )( - IITSource * This, - /* [retval][out] */ double *freespace); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( - IITSource * This, - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); - - END_INTERFACE - } IITSourceVtbl; - - interface IITSource - { - CONST_VTBL struct IITSourceVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITSource_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITSource_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITSource_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITSource_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITSource_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITSource_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITSource_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITSource_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITSource_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITSource_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITSource_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITSource_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITSource_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITSource_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITSource_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITSource_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITSource_get_Capacity(This,capacity) \ - (This)->lpVtbl -> get_Capacity(This,capacity) - -#define IITSource_get_FreeSpace(This,freespace) \ - (This)->lpVtbl -> get_FreeSpace(This,freespace) - -#define IITSource_get_Playlists(This,iPlaylistCollection) \ - (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_Kind_Proxy( - IITSource * This, - /* [retval][out] */ ITSourceKind *kind); - - -void __RPC_STUB IITSource_get_Kind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_Capacity_Proxy( - IITSource * This, - /* [retval][out] */ double *capacity); - - -void __RPC_STUB IITSource_get_Capacity_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_FreeSpace_Proxy( - IITSource * This, - /* [retval][out] */ double *freespace); - - -void __RPC_STUB IITSource_get_FreeSpace_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_Playlists_Proxy( - IITSource * This, - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); - - -void __RPC_STUB IITSource_get_Playlists_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITSource_INTERFACE_DEFINED__ */ - - -#ifndef __IITSourceCollection_INTERFACE_DEFINED__ -#define __IITSourceCollection_INTERFACE_DEFINED__ - -/* interface IITSourceCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITSourceCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("2FF6CE20-FF87-4183-B0B3-F323D047AF41") - IITSourceCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITSource **iSource) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( - /* [in] */ BSTR name, - /* [retval][out] */ IITSource **iSource) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPersistentID( - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITSource **iSource) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITSourceCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITSourceCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITSourceCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITSourceCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITSourceCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITSourceCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITSourceCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITSourceCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITSourceCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITSourceCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITSource **iSource); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( - IITSourceCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITSource **iSource); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITSourceCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPersistentID )( - IITSourceCollection * This, - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITSource **iSource); - - END_INTERFACE - } IITSourceCollectionVtbl; - - interface IITSourceCollection - { - CONST_VTBL struct IITSourceCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITSourceCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITSourceCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITSourceCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITSourceCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITSourceCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITSourceCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITSourceCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITSourceCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITSourceCollection_get_Item(This,index,iSource) \ - (This)->lpVtbl -> get_Item(This,index,iSource) - -#define IITSourceCollection_get_ItemByName(This,name,iSource) \ - (This)->lpVtbl -> get_ItemByName(This,name,iSource) - -#define IITSourceCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#define IITSourceCollection_get_ItemByPersistentID(This,highID,lowID,iSource) \ - (This)->lpVtbl -> get_ItemByPersistentID(This,highID,lowID,iSource) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_Count_Proxy( - IITSourceCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITSourceCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_Item_Proxy( - IITSourceCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITSource **iSource); - - -void __RPC_STUB IITSourceCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_ItemByName_Proxy( - IITSourceCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITSource **iSource); - - -void __RPC_STUB IITSourceCollection_get_ItemByName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get__NewEnum_Proxy( - IITSourceCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITSourceCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_ItemByPersistentID_Proxy( - IITSourceCollection * This, - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITSource **iSource); - - -void __RPC_STUB IITSourceCollection_get_ItemByPersistentID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITSourceCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IITEncoder_INTERFACE_DEFINED__ -#define __IITEncoder_INTERFACE_DEFINED__ - -/* interface IITEncoder */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITEncoder; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("1CF95A1C-55FE-4f45-A2D3-85AC6C504A73") - IITEncoder : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( - /* [retval][out] */ BSTR *name) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Format( - /* [retval][out] */ BSTR *format) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITEncoderVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITEncoder * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITEncoder * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITEncoder * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITEncoder * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITEncoder * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITEncoder * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITEncoder * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITEncoder * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Format )( - IITEncoder * This, - /* [retval][out] */ BSTR *format); - - END_INTERFACE - } IITEncoderVtbl; - - interface IITEncoder - { - CONST_VTBL struct IITEncoderVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITEncoder_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITEncoder_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITEncoder_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITEncoder_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITEncoder_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITEncoder_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITEncoder_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITEncoder_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITEncoder_get_Format(This,format) \ - (This)->lpVtbl -> get_Format(This,format) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoder_get_Name_Proxy( - IITEncoder * This, - /* [retval][out] */ BSTR *name); - - -void __RPC_STUB IITEncoder_get_Name_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoder_get_Format_Proxy( - IITEncoder * This, - /* [retval][out] */ BSTR *format); - - -void __RPC_STUB IITEncoder_get_Format_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITEncoder_INTERFACE_DEFINED__ */ - - -#ifndef __IITEncoderCollection_INTERFACE_DEFINED__ -#define __IITEncoderCollection_INTERFACE_DEFINED__ - -/* interface IITEncoderCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITEncoderCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("8862BCA9-168D-4549-A9D5-ADB35E553BA6") - IITEncoderCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITEncoder **iEncoder) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( - /* [in] */ BSTR name, - /* [retval][out] */ IITEncoder **iEncoder) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITEncoderCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITEncoderCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITEncoderCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITEncoderCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITEncoderCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITEncoderCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITEncoderCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITEncoderCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITEncoderCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITEncoderCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITEncoder **iEncoder); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( - IITEncoderCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITEncoder **iEncoder); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITEncoderCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - END_INTERFACE - } IITEncoderCollectionVtbl; - - interface IITEncoderCollection - { - CONST_VTBL struct IITEncoderCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITEncoderCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITEncoderCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITEncoderCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITEncoderCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITEncoderCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITEncoderCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITEncoderCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITEncoderCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITEncoderCollection_get_Item(This,index,iEncoder) \ - (This)->lpVtbl -> get_Item(This,index,iEncoder) - -#define IITEncoderCollection_get_ItemByName(This,name,iEncoder) \ - (This)->lpVtbl -> get_ItemByName(This,name,iEncoder) - -#define IITEncoderCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get_Count_Proxy( - IITEncoderCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITEncoderCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get_Item_Proxy( - IITEncoderCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITEncoder **iEncoder); - - -void __RPC_STUB IITEncoderCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get_ItemByName_Proxy( - IITEncoderCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITEncoder **iEncoder); - - -void __RPC_STUB IITEncoderCollection_get_ItemByName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get__NewEnum_Proxy( - IITEncoderCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITEncoderCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITEncoderCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IITEQPreset_INTERFACE_DEFINED__ -#define __IITEQPreset_INTERFACE_DEFINED__ - -/* interface IITEQPreset */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITEQPreset; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("5BE75F4F-68FA-4212-ACB7-BE44EA569759") - IITEQPreset : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( - /* [retval][out] */ BSTR *name) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Modifiable( - /* [retval][out] */ VARIANT_BOOL *isModifiable) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Preamp( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Preamp( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band1( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band1( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band2( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band2( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band3( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band3( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band4( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band4( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band5( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band5( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band6( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band6( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band7( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band7( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band8( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band8( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band9( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band9( - /* [in] */ double level) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band10( - /* [retval][out] */ double *level) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band10( - /* [in] */ double level) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( - /* [in] */ VARIANT_BOOL updateAllTracks) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Rename( - /* [in] */ BSTR newName, - /* [in] */ VARIANT_BOOL updateAllTracks) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITEQPresetVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITEQPreset * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITEQPreset * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITEQPreset * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITEQPreset * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITEQPreset * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITEQPreset * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITEQPreset * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITEQPreset * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Modifiable )( - IITEQPreset * This, - /* [retval][out] */ VARIANT_BOOL *isModifiable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Preamp )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Preamp )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band1 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band1 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band2 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band2 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band3 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band3 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band4 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band4 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band5 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band5 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band6 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band6 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band7 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band7 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band8 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band8 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band9 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band9 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band10 )( - IITEQPreset * This, - /* [retval][out] */ double *level); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band10 )( - IITEQPreset * This, - /* [in] */ double level); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITEQPreset * This, - /* [in] */ VARIANT_BOOL updateAllTracks); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Rename )( - IITEQPreset * This, - /* [in] */ BSTR newName, - /* [in] */ VARIANT_BOOL updateAllTracks); - - END_INTERFACE - } IITEQPresetVtbl; - - interface IITEQPreset - { - CONST_VTBL struct IITEQPresetVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITEQPreset_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITEQPreset_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITEQPreset_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITEQPreset_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITEQPreset_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITEQPreset_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITEQPreset_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITEQPreset_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITEQPreset_get_Modifiable(This,isModifiable) \ - (This)->lpVtbl -> get_Modifiable(This,isModifiable) - -#define IITEQPreset_get_Preamp(This,level) \ - (This)->lpVtbl -> get_Preamp(This,level) - -#define IITEQPreset_put_Preamp(This,level) \ - (This)->lpVtbl -> put_Preamp(This,level) - -#define IITEQPreset_get_Band1(This,level) \ - (This)->lpVtbl -> get_Band1(This,level) - -#define IITEQPreset_put_Band1(This,level) \ - (This)->lpVtbl -> put_Band1(This,level) - -#define IITEQPreset_get_Band2(This,level) \ - (This)->lpVtbl -> get_Band2(This,level) - -#define IITEQPreset_put_Band2(This,level) \ - (This)->lpVtbl -> put_Band2(This,level) - -#define IITEQPreset_get_Band3(This,level) \ - (This)->lpVtbl -> get_Band3(This,level) - -#define IITEQPreset_put_Band3(This,level) \ - (This)->lpVtbl -> put_Band3(This,level) - -#define IITEQPreset_get_Band4(This,level) \ - (This)->lpVtbl -> get_Band4(This,level) - -#define IITEQPreset_put_Band4(This,level) \ - (This)->lpVtbl -> put_Band4(This,level) - -#define IITEQPreset_get_Band5(This,level) \ - (This)->lpVtbl -> get_Band5(This,level) - -#define IITEQPreset_put_Band5(This,level) \ - (This)->lpVtbl -> put_Band5(This,level) - -#define IITEQPreset_get_Band6(This,level) \ - (This)->lpVtbl -> get_Band6(This,level) - -#define IITEQPreset_put_Band6(This,level) \ - (This)->lpVtbl -> put_Band6(This,level) - -#define IITEQPreset_get_Band7(This,level) \ - (This)->lpVtbl -> get_Band7(This,level) - -#define IITEQPreset_put_Band7(This,level) \ - (This)->lpVtbl -> put_Band7(This,level) - -#define IITEQPreset_get_Band8(This,level) \ - (This)->lpVtbl -> get_Band8(This,level) - -#define IITEQPreset_put_Band8(This,level) \ - (This)->lpVtbl -> put_Band8(This,level) - -#define IITEQPreset_get_Band9(This,level) \ - (This)->lpVtbl -> get_Band9(This,level) - -#define IITEQPreset_put_Band9(This,level) \ - (This)->lpVtbl -> put_Band9(This,level) - -#define IITEQPreset_get_Band10(This,level) \ - (This)->lpVtbl -> get_Band10(This,level) - -#define IITEQPreset_put_Band10(This,level) \ - (This)->lpVtbl -> put_Band10(This,level) - -#define IITEQPreset_Delete(This,updateAllTracks) \ - (This)->lpVtbl -> Delete(This,updateAllTracks) - -#define IITEQPreset_Rename(This,newName,updateAllTracks) \ - (This)->lpVtbl -> Rename(This,newName,updateAllTracks) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Name_Proxy( - IITEQPreset * This, - /* [retval][out] */ BSTR *name); - - -void __RPC_STUB IITEQPreset_get_Name_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Modifiable_Proxy( - IITEQPreset * This, - /* [retval][out] */ VARIANT_BOOL *isModifiable); - - -void __RPC_STUB IITEQPreset_get_Modifiable_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Preamp_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Preamp_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Preamp_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Preamp_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band1_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band1_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band1_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band1_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band2_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band2_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band2_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band2_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band3_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band3_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band3_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band3_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band4_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band4_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band4_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band4_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band5_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band5_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band5_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band5_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band6_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band6_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band6_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band6_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band7_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band7_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band7_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band7_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band8_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band8_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band8_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band8_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band9_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band9_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band9_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band9_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band10_Proxy( - IITEQPreset * This, - /* [retval][out] */ double *level); - - -void __RPC_STUB IITEQPreset_get_Band10_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band10_Proxy( - IITEQPreset * This, - /* [in] */ double level); - - -void __RPC_STUB IITEQPreset_put_Band10_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITEQPreset_Delete_Proxy( - IITEQPreset * This, - /* [in] */ VARIANT_BOOL updateAllTracks); - - -void __RPC_STUB IITEQPreset_Delete_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITEQPreset_Rename_Proxy( - IITEQPreset * This, - /* [in] */ BSTR newName, - /* [in] */ VARIANT_BOOL updateAllTracks); - - -void __RPC_STUB IITEQPreset_Rename_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITEQPreset_INTERFACE_DEFINED__ */ - - -#ifndef __IITEQPresetCollection_INTERFACE_DEFINED__ -#define __IITEQPresetCollection_INTERFACE_DEFINED__ - -/* interface IITEQPresetCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITEQPresetCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("AEF4D111-3331-48da-B0C2-B468D5D61D08") - IITEQPresetCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITEQPreset **iEQPreset) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( - /* [in] */ BSTR name, - /* [retval][out] */ IITEQPreset **iEQPreset) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITEQPresetCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITEQPresetCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITEQPresetCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITEQPresetCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITEQPresetCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITEQPresetCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITEQPresetCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITEQPresetCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITEQPresetCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITEQPresetCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITEQPreset **iEQPreset); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( - IITEQPresetCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITEQPreset **iEQPreset); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITEQPresetCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - END_INTERFACE - } IITEQPresetCollectionVtbl; - - interface IITEQPresetCollection - { - CONST_VTBL struct IITEQPresetCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITEQPresetCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITEQPresetCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITEQPresetCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITEQPresetCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITEQPresetCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITEQPresetCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITEQPresetCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITEQPresetCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITEQPresetCollection_get_Item(This,index,iEQPreset) \ - (This)->lpVtbl -> get_Item(This,index,iEQPreset) - -#define IITEQPresetCollection_get_ItemByName(This,name,iEQPreset) \ - (This)->lpVtbl -> get_ItemByName(This,name,iEQPreset) - -#define IITEQPresetCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get_Count_Proxy( - IITEQPresetCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITEQPresetCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get_Item_Proxy( - IITEQPresetCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITEQPreset **iEQPreset); - - -void __RPC_STUB IITEQPresetCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get_ItemByName_Proxy( - IITEQPresetCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITEQPreset **iEQPreset); - - -void __RPC_STUB IITEQPresetCollection_get_ItemByName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get__NewEnum_Proxy( - IITEQPresetCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITEQPresetCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITEQPresetCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IITPlaylist_INTERFACE_DEFINED__ -#define __IITPlaylist_INTERFACE_DEFINED__ - -/* interface IITPlaylist */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITPlaylist; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("3D5E072F-2A77-4b17-9E73-E03B77CCCCA9") - IITPlaylist : public IITObject - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayFirstTrack( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Print( - /* [in] */ VARIANT_BOOL showPrintDialog, - /* [in] */ ITPlaylistPrintKind printKind, - /* [in] */ BSTR theme) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Search( - /* [in] */ BSTR searchText, - /* [in] */ ITPlaylistSearchField searchFields, - /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( - /* [retval][out] */ ITPlaylistKind *kind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Source( - /* [retval][out] */ IITSource **iSource) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Duration( - /* [retval][out] */ long *duration) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Shuffle( - /* [retval][out] */ VARIANT_BOOL *isShuffle) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Shuffle( - /* [in] */ VARIANT_BOOL shouldShuffle) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size( - /* [retval][out] */ double *size) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SongRepeat( - /* [retval][out] */ ITPlaylistRepeatMode *repeatMode) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SongRepeat( - /* [in] */ ITPlaylistRepeatMode repeatMode) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Time( - /* [retval][out] */ BSTR *time) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Visible( - /* [retval][out] */ VARIANT_BOOL *isVisible) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Tracks( - /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITPlaylistVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITPlaylist * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITPlaylist * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITPlaylist * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITPlaylist * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITPlaylist * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITPlaylist * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITPlaylist * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITPlaylist * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITPlaylist * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITPlaylist * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITPlaylist * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITPlaylist * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITPlaylist * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITPlaylist * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITPlaylist * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( - IITPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( - IITPlaylist * This, - /* [in] */ VARIANT_BOOL showPrintDialog, - /* [in] */ ITPlaylistPrintKind printKind, - /* [in] */ BSTR theme); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( - IITPlaylist * This, - /* [in] */ BSTR searchText, - /* [in] */ ITPlaylistSearchField searchFields, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITPlaylist * This, - /* [retval][out] */ ITPlaylistKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( - IITPlaylist * This, - /* [retval][out] */ IITSource **iSource); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( - IITPlaylist * This, - /* [retval][out] */ long *duration); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( - IITPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isShuffle); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( - IITPlaylist * This, - /* [in] */ VARIANT_BOOL shouldShuffle); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( - IITPlaylist * This, - /* [retval][out] */ double *size); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( - IITPlaylist * This, - /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( - IITPlaylist * This, - /* [in] */ ITPlaylistRepeatMode repeatMode); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( - IITPlaylist * This, - /* [retval][out] */ BSTR *time); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( - IITPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( - IITPlaylist * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - END_INTERFACE - } IITPlaylistVtbl; - - interface IITPlaylist - { - CONST_VTBL struct IITPlaylistVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITPlaylist_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITPlaylist_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITPlaylist_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITPlaylist_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITPlaylist_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITPlaylist_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITPlaylist_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITPlaylist_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITPlaylist_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITPlaylist_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITPlaylist_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITPlaylist_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITPlaylist_PlayFirstTrack(This) \ - (This)->lpVtbl -> PlayFirstTrack(This) - -#define IITPlaylist_Print(This,showPrintDialog,printKind,theme) \ - (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) - -#define IITPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ - (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) - -#define IITPlaylist_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITPlaylist_get_Source(This,iSource) \ - (This)->lpVtbl -> get_Source(This,iSource) - -#define IITPlaylist_get_Duration(This,duration) \ - (This)->lpVtbl -> get_Duration(This,duration) - -#define IITPlaylist_get_Shuffle(This,isShuffle) \ - (This)->lpVtbl -> get_Shuffle(This,isShuffle) - -#define IITPlaylist_put_Shuffle(This,shouldShuffle) \ - (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) - -#define IITPlaylist_get_Size(This,size) \ - (This)->lpVtbl -> get_Size(This,size) - -#define IITPlaylist_get_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> get_SongRepeat(This,repeatMode) - -#define IITPlaylist_put_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> put_SongRepeat(This,repeatMode) - -#define IITPlaylist_get_Time(This,time) \ - (This)->lpVtbl -> get_Time(This,time) - -#define IITPlaylist_get_Visible(This,isVisible) \ - (This)->lpVtbl -> get_Visible(This,isVisible) - -#define IITPlaylist_get_Tracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_Tracks(This,iTrackCollection) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_Delete_Proxy( - IITPlaylist * This); - - -void __RPC_STUB IITPlaylist_Delete_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_PlayFirstTrack_Proxy( - IITPlaylist * This); - - -void __RPC_STUB IITPlaylist_PlayFirstTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_Print_Proxy( - IITPlaylist * This, - /* [in] */ VARIANT_BOOL showPrintDialog, - /* [in] */ ITPlaylistPrintKind printKind, - /* [in] */ BSTR theme); - - -void __RPC_STUB IITPlaylist_Print_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_Search_Proxy( - IITPlaylist * This, - /* [in] */ BSTR searchText, - /* [in] */ ITPlaylistSearchField searchFields, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - -void __RPC_STUB IITPlaylist_Search_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Kind_Proxy( - IITPlaylist * This, - /* [retval][out] */ ITPlaylistKind *kind); - - -void __RPC_STUB IITPlaylist_get_Kind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Source_Proxy( - IITPlaylist * This, - /* [retval][out] */ IITSource **iSource); - - -void __RPC_STUB IITPlaylist_get_Source_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Duration_Proxy( - IITPlaylist * This, - /* [retval][out] */ long *duration); - - -void __RPC_STUB IITPlaylist_get_Duration_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Shuffle_Proxy( - IITPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isShuffle); - - -void __RPC_STUB IITPlaylist_get_Shuffle_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITPlaylist_put_Shuffle_Proxy( - IITPlaylist * This, - /* [in] */ VARIANT_BOOL shouldShuffle); - - -void __RPC_STUB IITPlaylist_put_Shuffle_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Size_Proxy( - IITPlaylist * This, - /* [retval][out] */ double *size); - - -void __RPC_STUB IITPlaylist_get_Size_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_SongRepeat_Proxy( - IITPlaylist * This, - /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); - - -void __RPC_STUB IITPlaylist_get_SongRepeat_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITPlaylist_put_SongRepeat_Proxy( - IITPlaylist * This, - /* [in] */ ITPlaylistRepeatMode repeatMode); - - -void __RPC_STUB IITPlaylist_put_SongRepeat_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Time_Proxy( - IITPlaylist * This, - /* [retval][out] */ BSTR *time); - - -void __RPC_STUB IITPlaylist_get_Time_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Visible_Proxy( - IITPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - -void __RPC_STUB IITPlaylist_get_Visible_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Tracks_Proxy( - IITPlaylist * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - -void __RPC_STUB IITPlaylist_get_Tracks_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITPlaylist_INTERFACE_DEFINED__ */ - - -#ifndef __IITOperationStatus_INTERFACE_DEFINED__ -#define __IITOperationStatus_INTERFACE_DEFINED__ - -/* interface IITOperationStatus */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITOperationStatus; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("206479C9-FE32-4f9b-A18A-475AC939B479") - IITOperationStatus : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_InProgress( - /* [retval][out] */ VARIANT_BOOL *isInProgress) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Tracks( - /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITOperationStatusVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITOperationStatus * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITOperationStatus * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITOperationStatus * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITOperationStatus * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITOperationStatus * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITOperationStatus * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITOperationStatus * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InProgress )( - IITOperationStatus * This, - /* [retval][out] */ VARIANT_BOOL *isInProgress); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( - IITOperationStatus * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - END_INTERFACE - } IITOperationStatusVtbl; - - interface IITOperationStatus - { - CONST_VTBL struct IITOperationStatusVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITOperationStatus_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITOperationStatus_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITOperationStatus_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITOperationStatus_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITOperationStatus_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITOperationStatus_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITOperationStatus_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITOperationStatus_get_InProgress(This,isInProgress) \ - (This)->lpVtbl -> get_InProgress(This,isInProgress) - -#define IITOperationStatus_get_Tracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_Tracks(This,iTrackCollection) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITOperationStatus_get_InProgress_Proxy( - IITOperationStatus * This, - /* [retval][out] */ VARIANT_BOOL *isInProgress); - - -void __RPC_STUB IITOperationStatus_get_InProgress_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITOperationStatus_get_Tracks_Proxy( - IITOperationStatus * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - -void __RPC_STUB IITOperationStatus_get_Tracks_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITOperationStatus_INTERFACE_DEFINED__ */ - - -#ifndef __IITConvertOperationStatus_INTERFACE_DEFINED__ -#define __IITConvertOperationStatus_INTERFACE_DEFINED__ - -/* interface IITConvertOperationStatus */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITConvertOperationStatus; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("7063AAF6-ABA0-493b-B4FC-920A9F105875") - IITConvertOperationStatus : public IITOperationStatus - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetConversionStatus( - /* [out] */ BSTR *trackName, - /* [out] */ long *progressValue, - /* [out] */ long *maxProgressValue) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE StopConversion( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackName( - /* [retval][out] */ BSTR *trackName) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ProgressValue( - /* [retval][out] */ long *progressValue) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_MaxProgressValue( - /* [retval][out] */ long *maxProgressValue) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITConvertOperationStatusVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITConvertOperationStatus * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITConvertOperationStatus * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITConvertOperationStatus * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITConvertOperationStatus * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITConvertOperationStatus * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITConvertOperationStatus * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITConvertOperationStatus * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InProgress )( - IITConvertOperationStatus * This, - /* [retval][out] */ VARIANT_BOOL *isInProgress); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( - IITConvertOperationStatus * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetConversionStatus )( - IITConvertOperationStatus * This, - /* [out] */ BSTR *trackName, - /* [out] */ long *progressValue, - /* [out] */ long *maxProgressValue); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *StopConversion )( - IITConvertOperationStatus * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackName )( - IITConvertOperationStatus * This, - /* [retval][out] */ BSTR *trackName); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ProgressValue )( - IITConvertOperationStatus * This, - /* [retval][out] */ long *progressValue); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MaxProgressValue )( - IITConvertOperationStatus * This, - /* [retval][out] */ long *maxProgressValue); - - END_INTERFACE - } IITConvertOperationStatusVtbl; - - interface IITConvertOperationStatus - { - CONST_VTBL struct IITConvertOperationStatusVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITConvertOperationStatus_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITConvertOperationStatus_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITConvertOperationStatus_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITConvertOperationStatus_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITConvertOperationStatus_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITConvertOperationStatus_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITConvertOperationStatus_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITConvertOperationStatus_get_InProgress(This,isInProgress) \ - (This)->lpVtbl -> get_InProgress(This,isInProgress) - -#define IITConvertOperationStatus_get_Tracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_Tracks(This,iTrackCollection) - - -#define IITConvertOperationStatus_GetConversionStatus(This,trackName,progressValue,maxProgressValue) \ - (This)->lpVtbl -> GetConversionStatus(This,trackName,progressValue,maxProgressValue) - -#define IITConvertOperationStatus_StopConversion(This) \ - (This)->lpVtbl -> StopConversion(This) - -#define IITConvertOperationStatus_get_TrackName(This,trackName) \ - (This)->lpVtbl -> get_TrackName(This,trackName) - -#define IITConvertOperationStatus_get_ProgressValue(This,progressValue) \ - (This)->lpVtbl -> get_ProgressValue(This,progressValue) - -#define IITConvertOperationStatus_get_MaxProgressValue(This,maxProgressValue) \ - (This)->lpVtbl -> get_MaxProgressValue(This,maxProgressValue) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_GetConversionStatus_Proxy( - IITConvertOperationStatus * This, - /* [out] */ BSTR *trackName, - /* [out] */ long *progressValue, - /* [out] */ long *maxProgressValue); - - -void __RPC_STUB IITConvertOperationStatus_GetConversionStatus_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_StopConversion_Proxy( - IITConvertOperationStatus * This); - - -void __RPC_STUB IITConvertOperationStatus_StopConversion_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_get_TrackName_Proxy( - IITConvertOperationStatus * This, - /* [retval][out] */ BSTR *trackName); - - -void __RPC_STUB IITConvertOperationStatus_get_TrackName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_get_ProgressValue_Proxy( - IITConvertOperationStatus * This, - /* [retval][out] */ long *progressValue); - - -void __RPC_STUB IITConvertOperationStatus_get_ProgressValue_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_get_MaxProgressValue_Proxy( - IITConvertOperationStatus * This, - /* [retval][out] */ long *maxProgressValue); - - -void __RPC_STUB IITConvertOperationStatus_get_MaxProgressValue_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITConvertOperationStatus_INTERFACE_DEFINED__ */ - - -#ifndef __IITLibraryPlaylist_INTERFACE_DEFINED__ -#define __IITLibraryPlaylist_INTERFACE_DEFINED__ - -/* interface IITLibraryPlaylist */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITLibraryPlaylist; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("53AE1704-491C-4289-94A0-958815675A3D") - IITLibraryPlaylist : public IITPlaylist - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFile( - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFiles( - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddURL( - /* [in] */ BSTR url, - /* [retval][out] */ IITURLTrack **iURLTrack) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddTrack( - /* [in] */ VARIANT *iTrackToAdd, - /* [retval][out] */ IITTrack **iAddedTrack) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITLibraryPlaylistVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITLibraryPlaylist * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITLibraryPlaylist * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITLibraryPlaylist * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITLibraryPlaylist * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITLibraryPlaylist * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITLibraryPlaylist * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITLibraryPlaylist * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITLibraryPlaylist * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITLibraryPlaylist * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITLibraryPlaylist * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITLibraryPlaylist * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITLibraryPlaylist * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITLibraryPlaylist * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITLibraryPlaylist * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITLibraryPlaylist * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITLibraryPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( - IITLibraryPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( - IITLibraryPlaylist * This, - /* [in] */ VARIANT_BOOL showPrintDialog, - /* [in] */ ITPlaylistPrintKind printKind, - /* [in] */ BSTR theme); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( - IITLibraryPlaylist * This, - /* [in] */ BSTR searchText, - /* [in] */ ITPlaylistSearchField searchFields, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITLibraryPlaylist * This, - /* [retval][out] */ ITPlaylistKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( - IITLibraryPlaylist * This, - /* [retval][out] */ IITSource **iSource); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( - IITLibraryPlaylist * This, - /* [retval][out] */ long *duration); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( - IITLibraryPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isShuffle); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( - IITLibraryPlaylist * This, - /* [in] */ VARIANT_BOOL shouldShuffle); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( - IITLibraryPlaylist * This, - /* [retval][out] */ double *size); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( - IITLibraryPlaylist * This, - /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( - IITLibraryPlaylist * This, - /* [in] */ ITPlaylistRepeatMode repeatMode); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( - IITLibraryPlaylist * This, - /* [retval][out] */ BSTR *time); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( - IITLibraryPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( - IITLibraryPlaylist * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFile )( - IITLibraryPlaylist * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFiles )( - IITLibraryPlaylist * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddURL )( - IITLibraryPlaylist * This, - /* [in] */ BSTR url, - /* [retval][out] */ IITURLTrack **iURLTrack); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddTrack )( - IITLibraryPlaylist * This, - /* [in] */ VARIANT *iTrackToAdd, - /* [retval][out] */ IITTrack **iAddedTrack); - - END_INTERFACE - } IITLibraryPlaylistVtbl; - - interface IITLibraryPlaylist - { - CONST_VTBL struct IITLibraryPlaylistVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITLibraryPlaylist_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITLibraryPlaylist_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITLibraryPlaylist_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITLibraryPlaylist_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITLibraryPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITLibraryPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITLibraryPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITLibraryPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITLibraryPlaylist_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITLibraryPlaylist_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITLibraryPlaylist_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITLibraryPlaylist_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITLibraryPlaylist_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITLibraryPlaylist_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITLibraryPlaylist_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITLibraryPlaylist_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITLibraryPlaylist_PlayFirstTrack(This) \ - (This)->lpVtbl -> PlayFirstTrack(This) - -#define IITLibraryPlaylist_Print(This,showPrintDialog,printKind,theme) \ - (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) - -#define IITLibraryPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ - (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) - -#define IITLibraryPlaylist_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITLibraryPlaylist_get_Source(This,iSource) \ - (This)->lpVtbl -> get_Source(This,iSource) - -#define IITLibraryPlaylist_get_Duration(This,duration) \ - (This)->lpVtbl -> get_Duration(This,duration) - -#define IITLibraryPlaylist_get_Shuffle(This,isShuffle) \ - (This)->lpVtbl -> get_Shuffle(This,isShuffle) - -#define IITLibraryPlaylist_put_Shuffle(This,shouldShuffle) \ - (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) - -#define IITLibraryPlaylist_get_Size(This,size) \ - (This)->lpVtbl -> get_Size(This,size) - -#define IITLibraryPlaylist_get_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> get_SongRepeat(This,repeatMode) - -#define IITLibraryPlaylist_put_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> put_SongRepeat(This,repeatMode) - -#define IITLibraryPlaylist_get_Time(This,time) \ - (This)->lpVtbl -> get_Time(This,time) - -#define IITLibraryPlaylist_get_Visible(This,isVisible) \ - (This)->lpVtbl -> get_Visible(This,isVisible) - -#define IITLibraryPlaylist_get_Tracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_Tracks(This,iTrackCollection) - - -#define IITLibraryPlaylist_AddFile(This,filePath,iStatus) \ - (This)->lpVtbl -> AddFile(This,filePath,iStatus) - -#define IITLibraryPlaylist_AddFiles(This,filePaths,iStatus) \ - (This)->lpVtbl -> AddFiles(This,filePaths,iStatus) - -#define IITLibraryPlaylist_AddURL(This,url,iURLTrack) \ - (This)->lpVtbl -> AddURL(This,url,iURLTrack) - -#define IITLibraryPlaylist_AddTrack(This,iTrackToAdd,iAddedTrack) \ - (This)->lpVtbl -> AddTrack(This,iTrackToAdd,iAddedTrack) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddFile_Proxy( - IITLibraryPlaylist * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IITLibraryPlaylist_AddFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddFiles_Proxy( - IITLibraryPlaylist * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IITLibraryPlaylist_AddFiles_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddURL_Proxy( - IITLibraryPlaylist * This, - /* [in] */ BSTR url, - /* [retval][out] */ IITURLTrack **iURLTrack); - - -void __RPC_STUB IITLibraryPlaylist_AddURL_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddTrack_Proxy( - IITLibraryPlaylist * This, - /* [in] */ VARIANT *iTrackToAdd, - /* [retval][out] */ IITTrack **iAddedTrack); - - -void __RPC_STUB IITLibraryPlaylist_AddTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITLibraryPlaylist_INTERFACE_DEFINED__ */ - - -#ifndef __IITUserPlaylist_INTERFACE_DEFINED__ -#define __IITUserPlaylist_INTERFACE_DEFINED__ - -/* interface IITUserPlaylist */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITUserPlaylist; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("0A504DED-A0B5-465a-8A94-50E20D7DF692") - IITUserPlaylist : public IITPlaylist - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFile( - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFiles( - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddURL( - /* [in] */ BSTR url, - /* [retval][out] */ IITURLTrack **iURLTrack) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddTrack( - /* [in] */ VARIANT *iTrackToAdd, - /* [retval][out] */ IITTrack **iAddedTrack) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Shared( - /* [retval][out] */ VARIANT_BOOL *isShared) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Shared( - /* [in] */ VARIANT_BOOL shouldBeShared) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Smart( - /* [retval][out] */ VARIANT_BOOL *isSmart) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SpecialKind( - /* [retval][out] */ ITUserPlaylistSpecialKind *specialKind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Parent( - /* [retval][out] */ IITUserPlaylist **iParentPlayList) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePlaylist( - /* [in] */ BSTR playlistName, - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateFolder( - /* [in] */ BSTR folderName, - /* [retval][out] */ IITPlaylist **iFolder) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Parent( - /* [in] */ VARIANT *iParent) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITUserPlaylistVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITUserPlaylist * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITUserPlaylist * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITUserPlaylist * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITUserPlaylist * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITUserPlaylist * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITUserPlaylist * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITUserPlaylist * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITUserPlaylist * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITUserPlaylist * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITUserPlaylist * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITUserPlaylist * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITUserPlaylist * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITUserPlaylist * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITUserPlaylist * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITUserPlaylist * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITUserPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( - IITUserPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( - IITUserPlaylist * This, - /* [in] */ VARIANT_BOOL showPrintDialog, - /* [in] */ ITPlaylistPrintKind printKind, - /* [in] */ BSTR theme); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( - IITUserPlaylist * This, - /* [in] */ BSTR searchText, - /* [in] */ ITPlaylistSearchField searchFields, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITUserPlaylist * This, - /* [retval][out] */ ITPlaylistKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( - IITUserPlaylist * This, - /* [retval][out] */ IITSource **iSource); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( - IITUserPlaylist * This, - /* [retval][out] */ long *duration); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( - IITUserPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isShuffle); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( - IITUserPlaylist * This, - /* [in] */ VARIANT_BOOL shouldShuffle); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( - IITUserPlaylist * This, - /* [retval][out] */ double *size); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( - IITUserPlaylist * This, - /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( - IITUserPlaylist * This, - /* [in] */ ITPlaylistRepeatMode repeatMode); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( - IITUserPlaylist * This, - /* [retval][out] */ BSTR *time); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( - IITUserPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( - IITUserPlaylist * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFile )( - IITUserPlaylist * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFiles )( - IITUserPlaylist * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddURL )( - IITUserPlaylist * This, - /* [in] */ BSTR url, - /* [retval][out] */ IITURLTrack **iURLTrack); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddTrack )( - IITUserPlaylist * This, - /* [in] */ VARIANT *iTrackToAdd, - /* [retval][out] */ IITTrack **iAddedTrack); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shared )( - IITUserPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isShared); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shared )( - IITUserPlaylist * This, - /* [in] */ VARIANT_BOOL shouldBeShared); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Smart )( - IITUserPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isSmart); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SpecialKind )( - IITUserPlaylist * This, - /* [retval][out] */ ITUserPlaylistSpecialKind *specialKind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Parent )( - IITUserPlaylist * This, - /* [retval][out] */ IITUserPlaylist **iParentPlayList); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreatePlaylist )( - IITUserPlaylist * This, - /* [in] */ BSTR playlistName, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateFolder )( - IITUserPlaylist * This, - /* [in] */ BSTR folderName, - /* [retval][out] */ IITPlaylist **iFolder); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Parent )( - IITUserPlaylist * This, - /* [in] */ VARIANT *iParent); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( - IITUserPlaylist * This); - - END_INTERFACE - } IITUserPlaylistVtbl; - - interface IITUserPlaylist - { - CONST_VTBL struct IITUserPlaylistVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITUserPlaylist_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITUserPlaylist_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITUserPlaylist_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITUserPlaylist_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITUserPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITUserPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITUserPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITUserPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITUserPlaylist_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITUserPlaylist_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITUserPlaylist_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITUserPlaylist_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITUserPlaylist_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITUserPlaylist_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITUserPlaylist_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITUserPlaylist_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITUserPlaylist_PlayFirstTrack(This) \ - (This)->lpVtbl -> PlayFirstTrack(This) - -#define IITUserPlaylist_Print(This,showPrintDialog,printKind,theme) \ - (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) - -#define IITUserPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ - (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) - -#define IITUserPlaylist_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITUserPlaylist_get_Source(This,iSource) \ - (This)->lpVtbl -> get_Source(This,iSource) - -#define IITUserPlaylist_get_Duration(This,duration) \ - (This)->lpVtbl -> get_Duration(This,duration) - -#define IITUserPlaylist_get_Shuffle(This,isShuffle) \ - (This)->lpVtbl -> get_Shuffle(This,isShuffle) - -#define IITUserPlaylist_put_Shuffle(This,shouldShuffle) \ - (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) - -#define IITUserPlaylist_get_Size(This,size) \ - (This)->lpVtbl -> get_Size(This,size) - -#define IITUserPlaylist_get_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> get_SongRepeat(This,repeatMode) - -#define IITUserPlaylist_put_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> put_SongRepeat(This,repeatMode) - -#define IITUserPlaylist_get_Time(This,time) \ - (This)->lpVtbl -> get_Time(This,time) - -#define IITUserPlaylist_get_Visible(This,isVisible) \ - (This)->lpVtbl -> get_Visible(This,isVisible) - -#define IITUserPlaylist_get_Tracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_Tracks(This,iTrackCollection) - - -#define IITUserPlaylist_AddFile(This,filePath,iStatus) \ - (This)->lpVtbl -> AddFile(This,filePath,iStatus) - -#define IITUserPlaylist_AddFiles(This,filePaths,iStatus) \ - (This)->lpVtbl -> AddFiles(This,filePaths,iStatus) - -#define IITUserPlaylist_AddURL(This,url,iURLTrack) \ - (This)->lpVtbl -> AddURL(This,url,iURLTrack) - -#define IITUserPlaylist_AddTrack(This,iTrackToAdd,iAddedTrack) \ - (This)->lpVtbl -> AddTrack(This,iTrackToAdd,iAddedTrack) - -#define IITUserPlaylist_get_Shared(This,isShared) \ - (This)->lpVtbl -> get_Shared(This,isShared) - -#define IITUserPlaylist_put_Shared(This,shouldBeShared) \ - (This)->lpVtbl -> put_Shared(This,shouldBeShared) - -#define IITUserPlaylist_get_Smart(This,isSmart) \ - (This)->lpVtbl -> get_Smart(This,isSmart) - -#define IITUserPlaylist_get_SpecialKind(This,specialKind) \ - (This)->lpVtbl -> get_SpecialKind(This,specialKind) - -#define IITUserPlaylist_get_Parent(This,iParentPlayList) \ - (This)->lpVtbl -> get_Parent(This,iParentPlayList) - -#define IITUserPlaylist_CreatePlaylist(This,playlistName,iPlaylist) \ - (This)->lpVtbl -> CreatePlaylist(This,playlistName,iPlaylist) - -#define IITUserPlaylist_CreateFolder(This,folderName,iFolder) \ - (This)->lpVtbl -> CreateFolder(This,folderName,iFolder) - -#define IITUserPlaylist_put_Parent(This,iParent) \ - (This)->lpVtbl -> put_Parent(This,iParent) - -#define IITUserPlaylist_Reveal(This) \ - (This)->lpVtbl -> Reveal(This) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddFile_Proxy( - IITUserPlaylist * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IITUserPlaylist_AddFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddFiles_Proxy( - IITUserPlaylist * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IITUserPlaylist_AddFiles_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddURL_Proxy( - IITUserPlaylist * This, - /* [in] */ BSTR url, - /* [retval][out] */ IITURLTrack **iURLTrack); - - -void __RPC_STUB IITUserPlaylist_AddURL_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddTrack_Proxy( - IITUserPlaylist * This, - /* [in] */ VARIANT *iTrackToAdd, - /* [retval][out] */ IITTrack **iAddedTrack); - - -void __RPC_STUB IITUserPlaylist_AddTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_Shared_Proxy( - IITUserPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isShared); - - -void __RPC_STUB IITUserPlaylist_get_Shared_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_put_Shared_Proxy( - IITUserPlaylist * This, - /* [in] */ VARIANT_BOOL shouldBeShared); - - -void __RPC_STUB IITUserPlaylist_put_Shared_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_Smart_Proxy( - IITUserPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isSmart); - - -void __RPC_STUB IITUserPlaylist_get_Smart_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_SpecialKind_Proxy( - IITUserPlaylist * This, - /* [retval][out] */ ITUserPlaylistSpecialKind *specialKind); - - -void __RPC_STUB IITUserPlaylist_get_SpecialKind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_Parent_Proxy( - IITUserPlaylist * This, - /* [retval][out] */ IITUserPlaylist **iParentPlayList); - - -void __RPC_STUB IITUserPlaylist_get_Parent_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_CreatePlaylist_Proxy( - IITUserPlaylist * This, - /* [in] */ BSTR playlistName, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IITUserPlaylist_CreatePlaylist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_CreateFolder_Proxy( - IITUserPlaylist * This, - /* [in] */ BSTR folderName, - /* [retval][out] */ IITPlaylist **iFolder); - - -void __RPC_STUB IITUserPlaylist_CreateFolder_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_put_Parent_Proxy( - IITUserPlaylist * This, - /* [in] */ VARIANT *iParent); - - -void __RPC_STUB IITUserPlaylist_put_Parent_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_Reveal_Proxy( - IITUserPlaylist * This); - - -void __RPC_STUB IITUserPlaylist_Reveal_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITUserPlaylist_INTERFACE_DEFINED__ */ - - -#ifndef __IITTrack_INTERFACE_DEFINED__ -#define __IITTrack_INTERFACE_DEFINED__ - -/* interface IITTrack */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITTrack; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("4CB0915D-1E54-4727-BAF3-CE6CC9A225A1") - IITTrack : public IITObject - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Play( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddArtworkFromFile( - /* [in] */ BSTR filePath, - /* [retval][out] */ IITArtwork **iArtwork) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( - /* [retval][out] */ ITTrackKind *kind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlist( - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Album( - /* [retval][out] */ BSTR *album) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Album( - /* [in] */ BSTR album) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Artist( - /* [retval][out] */ BSTR *artist) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Artist( - /* [in] */ BSTR artist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BitRate( - /* [retval][out] */ long *bitrate) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BPM( - /* [retval][out] */ long *beatsPerMinute) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_BPM( - /* [in] */ long beatsPerMinute) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Comment( - /* [retval][out] */ BSTR *comment) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Comment( - /* [in] */ BSTR comment) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Compilation( - /* [retval][out] */ VARIANT_BOOL *isCompilation) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Compilation( - /* [in] */ VARIANT_BOOL shouldBeCompilation) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Composer( - /* [retval][out] */ BSTR *composer) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Composer( - /* [in] */ BSTR composer) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DateAdded( - /* [retval][out] */ DATE *dateAdded) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscCount( - /* [retval][out] */ long *discCount) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DiscCount( - /* [in] */ long discCount) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscNumber( - /* [retval][out] */ long *discNumber) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DiscNumber( - /* [in] */ long discNumber) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Duration( - /* [retval][out] */ long *duration) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Enabled( - /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Enabled( - /* [in] */ VARIANT_BOOL shouldBeEnabled) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQ( - /* [retval][out] */ BSTR *eq) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EQ( - /* [in] */ BSTR eq) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Finish( - /* [in] */ long finish) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Finish( - /* [retval][out] */ long *finish) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Genre( - /* [retval][out] */ BSTR *genre) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Genre( - /* [in] */ BSTR genre) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Grouping( - /* [retval][out] */ BSTR *grouping) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Grouping( - /* [in] */ BSTR grouping) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_KindAsString( - /* [retval][out] */ BSTR *kind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ModificationDate( - /* [retval][out] */ DATE *dateModified) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayedCount( - /* [retval][out] */ long *playedCount) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PlayedCount( - /* [in] */ long playedCount) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayedDate( - /* [retval][out] */ DATE *playedDate) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PlayedDate( - /* [in] */ DATE playedDate) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayOrderIndex( - /* [retval][out] */ long *index) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Rating( - /* [retval][out] */ long *rating) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Rating( - /* [in] */ long rating) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SampleRate( - /* [retval][out] */ long *sampleRate) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size( - /* [retval][out] */ long *size) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Start( - /* [retval][out] */ long *start) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Start( - /* [in] */ long start) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Time( - /* [retval][out] */ BSTR *time) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackCount( - /* [retval][out] */ long *trackCount) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_TrackCount( - /* [in] */ long trackCount) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackNumber( - /* [retval][out] */ long *trackNumber) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_TrackNumber( - /* [in] */ long trackNumber) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VolumeAdjustment( - /* [retval][out] */ long *volumeAdjustment) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VolumeAdjustment( - /* [in] */ long volumeAdjustment) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Year( - /* [retval][out] */ long *year) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Year( - /* [in] */ long year) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Artwork( - /* [retval][out] */ IITArtworkCollection **iArtworkCollection) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITTrackVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITTrack * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITTrack * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITTrack * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITTrack * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITTrack * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITTrack * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITTrack * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITTrack * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITTrack * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITTrack * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITTrack * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITTrack * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITTrack * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITTrack * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITTrack * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITTrack * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( - IITTrack * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddArtworkFromFile )( - IITTrack * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITArtwork **iArtwork); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITTrack * This, - /* [retval][out] */ ITTrackKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( - IITTrack * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Album )( - IITTrack * This, - /* [retval][out] */ BSTR *album); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Album )( - IITTrack * This, - /* [in] */ BSTR album); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( - IITTrack * This, - /* [retval][out] */ BSTR *artist); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Artist )( - IITTrack * This, - /* [in] */ BSTR artist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BitRate )( - IITTrack * This, - /* [retval][out] */ long *bitrate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BPM )( - IITTrack * This, - /* [retval][out] */ long *beatsPerMinute); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BPM )( - IITTrack * This, - /* [in] */ long beatsPerMinute); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Comment )( - IITTrack * This, - /* [retval][out] */ BSTR *comment); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Comment )( - IITTrack * This, - /* [in] */ BSTR comment); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( - IITTrack * This, - /* [retval][out] */ VARIANT_BOOL *isCompilation); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Compilation )( - IITTrack * This, - /* [in] */ VARIANT_BOOL shouldBeCompilation); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( - IITTrack * This, - /* [retval][out] */ BSTR *composer); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Composer )( - IITTrack * This, - /* [in] */ BSTR composer); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DateAdded )( - IITTrack * This, - /* [retval][out] */ DATE *dateAdded); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( - IITTrack * This, - /* [retval][out] */ long *discCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscCount )( - IITTrack * This, - /* [in] */ long discCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( - IITTrack * This, - /* [retval][out] */ long *discNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscNumber )( - IITTrack * This, - /* [in] */ long discNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( - IITTrack * This, - /* [retval][out] */ long *duration); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Enabled )( - IITTrack * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Enabled )( - IITTrack * This, - /* [in] */ VARIANT_BOOL shouldBeEnabled); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQ )( - IITTrack * This, - /* [retval][out] */ BSTR *eq); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQ )( - IITTrack * This, - /* [in] */ BSTR eq); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Finish )( - IITTrack * This, - /* [in] */ long finish); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Finish )( - IITTrack * This, - /* [retval][out] */ long *finish); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( - IITTrack * This, - /* [retval][out] */ BSTR *genre); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Genre )( - IITTrack * This, - /* [in] */ BSTR genre); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Grouping )( - IITTrack * This, - /* [retval][out] */ BSTR *grouping); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Grouping )( - IITTrack * This, - /* [in] */ BSTR grouping); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_KindAsString )( - IITTrack * This, - /* [retval][out] */ BSTR *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ModificationDate )( - IITTrack * This, - /* [retval][out] */ DATE *dateModified); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedCount )( - IITTrack * This, - /* [retval][out] */ long *playedCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedCount )( - IITTrack * This, - /* [in] */ long playedCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedDate )( - IITTrack * This, - /* [retval][out] */ DATE *playedDate); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedDate )( - IITTrack * This, - /* [in] */ DATE playedDate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayOrderIndex )( - IITTrack * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Rating )( - IITTrack * This, - /* [retval][out] */ long *rating); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Rating )( - IITTrack * This, - /* [in] */ long rating); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SampleRate )( - IITTrack * This, - /* [retval][out] */ long *sampleRate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( - IITTrack * This, - /* [retval][out] */ long *size); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Start )( - IITTrack * This, - /* [retval][out] */ long *start); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Start )( - IITTrack * This, - /* [in] */ long start); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( - IITTrack * This, - /* [retval][out] */ BSTR *time); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackCount )( - IITTrack * This, - /* [retval][out] */ long *trackCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackCount )( - IITTrack * This, - /* [in] */ long trackCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackNumber )( - IITTrack * This, - /* [retval][out] */ long *trackNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackNumber )( - IITTrack * This, - /* [in] */ long trackNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VolumeAdjustment )( - IITTrack * This, - /* [retval][out] */ long *volumeAdjustment); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VolumeAdjustment )( - IITTrack * This, - /* [in] */ long volumeAdjustment); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( - IITTrack * This, - /* [retval][out] */ long *year); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Year )( - IITTrack * This, - /* [in] */ long year); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artwork )( - IITTrack * This, - /* [retval][out] */ IITArtworkCollection **iArtworkCollection); - - END_INTERFACE - } IITTrackVtbl; - - interface IITTrack - { - CONST_VTBL struct IITTrackVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITTrack_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITTrack_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITTrack_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITTrack_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITTrack_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITTrack_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITTrack_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITTrack_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITTrack_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITTrack_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITTrack_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITTrack_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITTrack_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITTrack_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITTrack_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITTrack_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITTrack_Play(This) \ - (This)->lpVtbl -> Play(This) - -#define IITTrack_AddArtworkFromFile(This,filePath,iArtwork) \ - (This)->lpVtbl -> AddArtworkFromFile(This,filePath,iArtwork) - -#define IITTrack_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITTrack_get_Playlist(This,iPlaylist) \ - (This)->lpVtbl -> get_Playlist(This,iPlaylist) - -#define IITTrack_get_Album(This,album) \ - (This)->lpVtbl -> get_Album(This,album) - -#define IITTrack_put_Album(This,album) \ - (This)->lpVtbl -> put_Album(This,album) - -#define IITTrack_get_Artist(This,artist) \ - (This)->lpVtbl -> get_Artist(This,artist) - -#define IITTrack_put_Artist(This,artist) \ - (This)->lpVtbl -> put_Artist(This,artist) - -#define IITTrack_get_BitRate(This,bitrate) \ - (This)->lpVtbl -> get_BitRate(This,bitrate) - -#define IITTrack_get_BPM(This,beatsPerMinute) \ - (This)->lpVtbl -> get_BPM(This,beatsPerMinute) - -#define IITTrack_put_BPM(This,beatsPerMinute) \ - (This)->lpVtbl -> put_BPM(This,beatsPerMinute) - -#define IITTrack_get_Comment(This,comment) \ - (This)->lpVtbl -> get_Comment(This,comment) - -#define IITTrack_put_Comment(This,comment) \ - (This)->lpVtbl -> put_Comment(This,comment) - -#define IITTrack_get_Compilation(This,isCompilation) \ - (This)->lpVtbl -> get_Compilation(This,isCompilation) - -#define IITTrack_put_Compilation(This,shouldBeCompilation) \ - (This)->lpVtbl -> put_Compilation(This,shouldBeCompilation) - -#define IITTrack_get_Composer(This,composer) \ - (This)->lpVtbl -> get_Composer(This,composer) - -#define IITTrack_put_Composer(This,composer) \ - (This)->lpVtbl -> put_Composer(This,composer) - -#define IITTrack_get_DateAdded(This,dateAdded) \ - (This)->lpVtbl -> get_DateAdded(This,dateAdded) - -#define IITTrack_get_DiscCount(This,discCount) \ - (This)->lpVtbl -> get_DiscCount(This,discCount) - -#define IITTrack_put_DiscCount(This,discCount) \ - (This)->lpVtbl -> put_DiscCount(This,discCount) - -#define IITTrack_get_DiscNumber(This,discNumber) \ - (This)->lpVtbl -> get_DiscNumber(This,discNumber) - -#define IITTrack_put_DiscNumber(This,discNumber) \ - (This)->lpVtbl -> put_DiscNumber(This,discNumber) - -#define IITTrack_get_Duration(This,duration) \ - (This)->lpVtbl -> get_Duration(This,duration) - -#define IITTrack_get_Enabled(This,isEnabled) \ - (This)->lpVtbl -> get_Enabled(This,isEnabled) - -#define IITTrack_put_Enabled(This,shouldBeEnabled) \ - (This)->lpVtbl -> put_Enabled(This,shouldBeEnabled) - -#define IITTrack_get_EQ(This,eq) \ - (This)->lpVtbl -> get_EQ(This,eq) - -#define IITTrack_put_EQ(This,eq) \ - (This)->lpVtbl -> put_EQ(This,eq) - -#define IITTrack_put_Finish(This,finish) \ - (This)->lpVtbl -> put_Finish(This,finish) - -#define IITTrack_get_Finish(This,finish) \ - (This)->lpVtbl -> get_Finish(This,finish) - -#define IITTrack_get_Genre(This,genre) \ - (This)->lpVtbl -> get_Genre(This,genre) - -#define IITTrack_put_Genre(This,genre) \ - (This)->lpVtbl -> put_Genre(This,genre) - -#define IITTrack_get_Grouping(This,grouping) \ - (This)->lpVtbl -> get_Grouping(This,grouping) - -#define IITTrack_put_Grouping(This,grouping) \ - (This)->lpVtbl -> put_Grouping(This,grouping) - -#define IITTrack_get_KindAsString(This,kind) \ - (This)->lpVtbl -> get_KindAsString(This,kind) - -#define IITTrack_get_ModificationDate(This,dateModified) \ - (This)->lpVtbl -> get_ModificationDate(This,dateModified) - -#define IITTrack_get_PlayedCount(This,playedCount) \ - (This)->lpVtbl -> get_PlayedCount(This,playedCount) - -#define IITTrack_put_PlayedCount(This,playedCount) \ - (This)->lpVtbl -> put_PlayedCount(This,playedCount) - -#define IITTrack_get_PlayedDate(This,playedDate) \ - (This)->lpVtbl -> get_PlayedDate(This,playedDate) - -#define IITTrack_put_PlayedDate(This,playedDate) \ - (This)->lpVtbl -> put_PlayedDate(This,playedDate) - -#define IITTrack_get_PlayOrderIndex(This,index) \ - (This)->lpVtbl -> get_PlayOrderIndex(This,index) - -#define IITTrack_get_Rating(This,rating) \ - (This)->lpVtbl -> get_Rating(This,rating) - -#define IITTrack_put_Rating(This,rating) \ - (This)->lpVtbl -> put_Rating(This,rating) - -#define IITTrack_get_SampleRate(This,sampleRate) \ - (This)->lpVtbl -> get_SampleRate(This,sampleRate) - -#define IITTrack_get_Size(This,size) \ - (This)->lpVtbl -> get_Size(This,size) - -#define IITTrack_get_Start(This,start) \ - (This)->lpVtbl -> get_Start(This,start) - -#define IITTrack_put_Start(This,start) \ - (This)->lpVtbl -> put_Start(This,start) - -#define IITTrack_get_Time(This,time) \ - (This)->lpVtbl -> get_Time(This,time) - -#define IITTrack_get_TrackCount(This,trackCount) \ - (This)->lpVtbl -> get_TrackCount(This,trackCount) - -#define IITTrack_put_TrackCount(This,trackCount) \ - (This)->lpVtbl -> put_TrackCount(This,trackCount) - -#define IITTrack_get_TrackNumber(This,trackNumber) \ - (This)->lpVtbl -> get_TrackNumber(This,trackNumber) - -#define IITTrack_put_TrackNumber(This,trackNumber) \ - (This)->lpVtbl -> put_TrackNumber(This,trackNumber) - -#define IITTrack_get_VolumeAdjustment(This,volumeAdjustment) \ - (This)->lpVtbl -> get_VolumeAdjustment(This,volumeAdjustment) - -#define IITTrack_put_VolumeAdjustment(This,volumeAdjustment) \ - (This)->lpVtbl -> put_VolumeAdjustment(This,volumeAdjustment) - -#define IITTrack_get_Year(This,year) \ - (This)->lpVtbl -> get_Year(This,year) - -#define IITTrack_put_Year(This,year) \ - (This)->lpVtbl -> put_Year(This,year) - -#define IITTrack_get_Artwork(This,iArtworkCollection) \ - (This)->lpVtbl -> get_Artwork(This,iArtworkCollection) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITTrack_Delete_Proxy( - IITTrack * This); - - -void __RPC_STUB IITTrack_Delete_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITTrack_Play_Proxy( - IITTrack * This); - - -void __RPC_STUB IITTrack_Play_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITTrack_AddArtworkFromFile_Proxy( - IITTrack * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITArtwork **iArtwork); - - -void __RPC_STUB IITTrack_AddArtworkFromFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Kind_Proxy( - IITTrack * This, - /* [retval][out] */ ITTrackKind *kind); - - -void __RPC_STUB IITTrack_get_Kind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Playlist_Proxy( - IITTrack * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IITTrack_get_Playlist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Album_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *album); - - -void __RPC_STUB IITTrack_get_Album_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Album_Proxy( - IITTrack * This, - /* [in] */ BSTR album); - - -void __RPC_STUB IITTrack_put_Album_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Artist_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *artist); - - -void __RPC_STUB IITTrack_get_Artist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Artist_Proxy( - IITTrack * This, - /* [in] */ BSTR artist); - - -void __RPC_STUB IITTrack_put_Artist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_BitRate_Proxy( - IITTrack * This, - /* [retval][out] */ long *bitrate); - - -void __RPC_STUB IITTrack_get_BitRate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_BPM_Proxy( - IITTrack * This, - /* [retval][out] */ long *beatsPerMinute); - - -void __RPC_STUB IITTrack_get_BPM_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_BPM_Proxy( - IITTrack * This, - /* [in] */ long beatsPerMinute); - - -void __RPC_STUB IITTrack_put_BPM_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Comment_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *comment); - - -void __RPC_STUB IITTrack_get_Comment_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Comment_Proxy( - IITTrack * This, - /* [in] */ BSTR comment); - - -void __RPC_STUB IITTrack_put_Comment_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Compilation_Proxy( - IITTrack * This, - /* [retval][out] */ VARIANT_BOOL *isCompilation); - - -void __RPC_STUB IITTrack_get_Compilation_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Compilation_Proxy( - IITTrack * This, - /* [in] */ VARIANT_BOOL shouldBeCompilation); - - -void __RPC_STUB IITTrack_put_Compilation_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Composer_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *composer); - - -void __RPC_STUB IITTrack_get_Composer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Composer_Proxy( - IITTrack * This, - /* [in] */ BSTR composer); - - -void __RPC_STUB IITTrack_put_Composer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_DateAdded_Proxy( - IITTrack * This, - /* [retval][out] */ DATE *dateAdded); - - -void __RPC_STUB IITTrack_get_DateAdded_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_DiscCount_Proxy( - IITTrack * This, - /* [retval][out] */ long *discCount); - - -void __RPC_STUB IITTrack_get_DiscCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_DiscCount_Proxy( - IITTrack * This, - /* [in] */ long discCount); - - -void __RPC_STUB IITTrack_put_DiscCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_DiscNumber_Proxy( - IITTrack * This, - /* [retval][out] */ long *discNumber); - - -void __RPC_STUB IITTrack_get_DiscNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_DiscNumber_Proxy( - IITTrack * This, - /* [in] */ long discNumber); - - -void __RPC_STUB IITTrack_put_DiscNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Duration_Proxy( - IITTrack * This, - /* [retval][out] */ long *duration); - - -void __RPC_STUB IITTrack_get_Duration_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Enabled_Proxy( - IITTrack * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - -void __RPC_STUB IITTrack_get_Enabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Enabled_Proxy( - IITTrack * This, - /* [in] */ VARIANT_BOOL shouldBeEnabled); - - -void __RPC_STUB IITTrack_put_Enabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_EQ_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *eq); - - -void __RPC_STUB IITTrack_get_EQ_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_EQ_Proxy( - IITTrack * This, - /* [in] */ BSTR eq); - - -void __RPC_STUB IITTrack_put_EQ_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Finish_Proxy( - IITTrack * This, - /* [in] */ long finish); - - -void __RPC_STUB IITTrack_put_Finish_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Finish_Proxy( - IITTrack * This, - /* [retval][out] */ long *finish); - - -void __RPC_STUB IITTrack_get_Finish_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Genre_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *genre); - - -void __RPC_STUB IITTrack_get_Genre_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Genre_Proxy( - IITTrack * This, - /* [in] */ BSTR genre); - - -void __RPC_STUB IITTrack_put_Genre_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Grouping_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *grouping); - - -void __RPC_STUB IITTrack_get_Grouping_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Grouping_Proxy( - IITTrack * This, - /* [in] */ BSTR grouping); - - -void __RPC_STUB IITTrack_put_Grouping_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_KindAsString_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *kind); - - -void __RPC_STUB IITTrack_get_KindAsString_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_ModificationDate_Proxy( - IITTrack * This, - /* [retval][out] */ DATE *dateModified); - - -void __RPC_STUB IITTrack_get_ModificationDate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_PlayedCount_Proxy( - IITTrack * This, - /* [retval][out] */ long *playedCount); - - -void __RPC_STUB IITTrack_get_PlayedCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_PlayedCount_Proxy( - IITTrack * This, - /* [in] */ long playedCount); - - -void __RPC_STUB IITTrack_put_PlayedCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_PlayedDate_Proxy( - IITTrack * This, - /* [retval][out] */ DATE *playedDate); - - -void __RPC_STUB IITTrack_get_PlayedDate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_PlayedDate_Proxy( - IITTrack * This, - /* [in] */ DATE playedDate); - - -void __RPC_STUB IITTrack_put_PlayedDate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_PlayOrderIndex_Proxy( - IITTrack * This, - /* [retval][out] */ long *index); - - -void __RPC_STUB IITTrack_get_PlayOrderIndex_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Rating_Proxy( - IITTrack * This, - /* [retval][out] */ long *rating); - - -void __RPC_STUB IITTrack_get_Rating_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Rating_Proxy( - IITTrack * This, - /* [in] */ long rating); - - -void __RPC_STUB IITTrack_put_Rating_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_SampleRate_Proxy( - IITTrack * This, - /* [retval][out] */ long *sampleRate); - - -void __RPC_STUB IITTrack_get_SampleRate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Size_Proxy( - IITTrack * This, - /* [retval][out] */ long *size); - - -void __RPC_STUB IITTrack_get_Size_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Start_Proxy( - IITTrack * This, - /* [retval][out] */ long *start); - - -void __RPC_STUB IITTrack_get_Start_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Start_Proxy( - IITTrack * This, - /* [in] */ long start); - - -void __RPC_STUB IITTrack_put_Start_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Time_Proxy( - IITTrack * This, - /* [retval][out] */ BSTR *time); - - -void __RPC_STUB IITTrack_get_Time_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_TrackCount_Proxy( - IITTrack * This, - /* [retval][out] */ long *trackCount); - - -void __RPC_STUB IITTrack_get_TrackCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_TrackCount_Proxy( - IITTrack * This, - /* [in] */ long trackCount); - - -void __RPC_STUB IITTrack_put_TrackCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_TrackNumber_Proxy( - IITTrack * This, - /* [retval][out] */ long *trackNumber); - - -void __RPC_STUB IITTrack_get_TrackNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_TrackNumber_Proxy( - IITTrack * This, - /* [in] */ long trackNumber); - - -void __RPC_STUB IITTrack_put_TrackNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_VolumeAdjustment_Proxy( - IITTrack * This, - /* [retval][out] */ long *volumeAdjustment); - - -void __RPC_STUB IITTrack_get_VolumeAdjustment_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_VolumeAdjustment_Proxy( - IITTrack * This, - /* [in] */ long volumeAdjustment); - - -void __RPC_STUB IITTrack_put_VolumeAdjustment_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Year_Proxy( - IITTrack * This, - /* [retval][out] */ long *year); - - -void __RPC_STUB IITTrack_get_Year_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Year_Proxy( - IITTrack * This, - /* [in] */ long year); - - -void __RPC_STUB IITTrack_put_Year_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Artwork_Proxy( - IITTrack * This, - /* [retval][out] */ IITArtworkCollection **iArtworkCollection); - - -void __RPC_STUB IITTrack_get_Artwork_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITTrack_INTERFACE_DEFINED__ */ - - -#ifndef __IITTrackCollection_INTERFACE_DEFINED__ -#define __IITTrackCollection_INTERFACE_DEFINED__ - -/* interface IITTrackCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITTrackCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("755D76F1-6B85-4ce4-8F5F-F88D9743DCD8") - IITTrackCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITTrack **iTrack) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPlayOrder( - /* [in] */ long index, - /* [retval][out] */ IITTrack **iTrack) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( - /* [in] */ BSTR name, - /* [retval][out] */ IITTrack **iTrack) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPersistentID( - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITTrack **iTrack) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITTrackCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITTrackCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITTrackCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITTrackCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITTrackCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITTrackCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITTrackCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITTrackCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITTrackCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITTrackCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITTrack **iTrack); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPlayOrder )( - IITTrackCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITTrack **iTrack); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( - IITTrackCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITTrack **iTrack); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITTrackCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPersistentID )( - IITTrackCollection * This, - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITTrack **iTrack); - - END_INTERFACE - } IITTrackCollectionVtbl; - - interface IITTrackCollection - { - CONST_VTBL struct IITTrackCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITTrackCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITTrackCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITTrackCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITTrackCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITTrackCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITTrackCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITTrackCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITTrackCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITTrackCollection_get_Item(This,index,iTrack) \ - (This)->lpVtbl -> get_Item(This,index,iTrack) - -#define IITTrackCollection_get_ItemByPlayOrder(This,index,iTrack) \ - (This)->lpVtbl -> get_ItemByPlayOrder(This,index,iTrack) - -#define IITTrackCollection_get_ItemByName(This,name,iTrack) \ - (This)->lpVtbl -> get_ItemByName(This,name,iTrack) - -#define IITTrackCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#define IITTrackCollection_get_ItemByPersistentID(This,highID,lowID,iTrack) \ - (This)->lpVtbl -> get_ItemByPersistentID(This,highID,lowID,iTrack) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_Count_Proxy( - IITTrackCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITTrackCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_Item_Proxy( - IITTrackCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITTrack **iTrack); - - -void __RPC_STUB IITTrackCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_ItemByPlayOrder_Proxy( - IITTrackCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITTrack **iTrack); - - -void __RPC_STUB IITTrackCollection_get_ItemByPlayOrder_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_ItemByName_Proxy( - IITTrackCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITTrack **iTrack); - - -void __RPC_STUB IITTrackCollection_get_ItemByName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get__NewEnum_Proxy( - IITTrackCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITTrackCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_ItemByPersistentID_Proxy( - IITTrackCollection * This, - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITTrack **iTrack); - - -void __RPC_STUB IITTrackCollection_get_ItemByPersistentID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITTrackCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IITVisual_INTERFACE_DEFINED__ -#define __IITVisual_INTERFACE_DEFINED__ - -/* interface IITVisual */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITVisual; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("340F3315-ED72-4c09-9ACF-21EB4BDF9931") - IITVisual : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( - /* [retval][out] */ BSTR *name) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITVisualVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITVisual * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITVisual * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITVisual * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITVisual * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITVisual * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITVisual * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITVisual * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITVisual * This, - /* [retval][out] */ BSTR *name); - - END_INTERFACE - } IITVisualVtbl; - - interface IITVisual - { - CONST_VTBL struct IITVisualVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITVisual_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITVisual_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITVisual_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITVisual_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITVisual_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITVisual_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITVisual_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITVisual_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITVisual_get_Name_Proxy( - IITVisual * This, - /* [retval][out] */ BSTR *name); - - -void __RPC_STUB IITVisual_get_Name_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITVisual_INTERFACE_DEFINED__ */ - - -#ifndef __IITVisualCollection_INTERFACE_DEFINED__ -#define __IITVisualCollection_INTERFACE_DEFINED__ - -/* interface IITVisualCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITVisualCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("88A4CCDD-114F-4043-B69B-84D4E6274957") - IITVisualCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITVisual **iVisual) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( - /* [in] */ BSTR name, - /* [retval][out] */ IITVisual **iVisual) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITVisualCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITVisualCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITVisualCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITVisualCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITVisualCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITVisualCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITVisualCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITVisualCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITVisualCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITVisualCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITVisual **iVisual); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( - IITVisualCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITVisual **iVisual); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITVisualCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - END_INTERFACE - } IITVisualCollectionVtbl; - - interface IITVisualCollection - { - CONST_VTBL struct IITVisualCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITVisualCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITVisualCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITVisualCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITVisualCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITVisualCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITVisualCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITVisualCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITVisualCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITVisualCollection_get_Item(This,index,iVisual) \ - (This)->lpVtbl -> get_Item(This,index,iVisual) - -#define IITVisualCollection_get_ItemByName(This,name,iVisual) \ - (This)->lpVtbl -> get_ItemByName(This,name,iVisual) - -#define IITVisualCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get_Count_Proxy( - IITVisualCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITVisualCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get_Item_Proxy( - IITVisualCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITVisual **iVisual); - - -void __RPC_STUB IITVisualCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get_ItemByName_Proxy( - IITVisualCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITVisual **iVisual); - - -void __RPC_STUB IITVisualCollection_get_ItemByName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get__NewEnum_Proxy( - IITVisualCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITVisualCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITVisualCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IITWindow_INTERFACE_DEFINED__ -#define __IITWindow_INTERFACE_DEFINED__ - -/* interface IITWindow */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITWindow; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("370D7BE0-3A89-4a42-B902-C75FC138BE09") - IITWindow : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( - /* [retval][out] */ BSTR *name) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( - /* [retval][out] */ ITWindowKind *kind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Visible( - /* [retval][out] */ VARIANT_BOOL *isVisible) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Visible( - /* [in] */ VARIANT_BOOL shouldBeVisible) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Resizable( - /* [retval][out] */ VARIANT_BOOL *isResizable) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Minimized( - /* [retval][out] */ VARIANT_BOOL *isMinimized) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Minimized( - /* [in] */ VARIANT_BOOL shouldBeMinimized) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Maximizable( - /* [retval][out] */ VARIANT_BOOL *isMaximizable) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Maximized( - /* [retval][out] */ VARIANT_BOOL *isMaximized) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Maximized( - /* [in] */ VARIANT_BOOL shouldBeMaximized) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Zoomable( - /* [retval][out] */ VARIANT_BOOL *isZoomable) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Zoomed( - /* [retval][out] */ VARIANT_BOOL *isZoomed) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Zoomed( - /* [in] */ VARIANT_BOOL shouldBeZoomed) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Top( - /* [retval][out] */ long *top) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Top( - /* [in] */ long top) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Left( - /* [retval][out] */ long *left) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Left( - /* [in] */ long left) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Bottom( - /* [retval][out] */ long *bottom) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Bottom( - /* [in] */ long bottom) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Right( - /* [retval][out] */ long *right) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Right( - /* [in] */ long right) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Width( - /* [retval][out] */ long *width) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Width( - /* [in] */ long width) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Height( - /* [retval][out] */ long *height) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Height( - /* [in] */ long height) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITWindowVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITWindow * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITWindow * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITWindow * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITWindow * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITWindow * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITWindow * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITWindow * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITWindow * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITWindow * This, - /* [retval][out] */ ITWindowKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Visible )( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeVisible); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Resizable )( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isResizable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Minimized )( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMinimized); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Minimized )( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMinimized); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximizable )( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximizable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximized )( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximized); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Maximized )( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMaximized); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomable )( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomed )( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomed); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Zoomed )( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeZoomed); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )( - IITWindow * This, - /* [retval][out] */ long *top); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Top )( - IITWindow * This, - /* [in] */ long top); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )( - IITWindow * This, - /* [retval][out] */ long *left); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Left )( - IITWindow * This, - /* [in] */ long left); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bottom )( - IITWindow * This, - /* [retval][out] */ long *bottom); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bottom )( - IITWindow * This, - /* [in] */ long bottom); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Right )( - IITWindow * This, - /* [retval][out] */ long *right); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Right )( - IITWindow * This, - /* [in] */ long right); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )( - IITWindow * This, - /* [retval][out] */ long *width); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Width )( - IITWindow * This, - /* [in] */ long width); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )( - IITWindow * This, - /* [retval][out] */ long *height); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Height )( - IITWindow * This, - /* [in] */ long height); - - END_INTERFACE - } IITWindowVtbl; - - interface IITWindow - { - CONST_VTBL struct IITWindowVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITWindow_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITWindow_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITWindow_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITWindow_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITWindow_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITWindow_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITWindow_get_Visible(This,isVisible) \ - (This)->lpVtbl -> get_Visible(This,isVisible) - -#define IITWindow_put_Visible(This,shouldBeVisible) \ - (This)->lpVtbl -> put_Visible(This,shouldBeVisible) - -#define IITWindow_get_Resizable(This,isResizable) \ - (This)->lpVtbl -> get_Resizable(This,isResizable) - -#define IITWindow_get_Minimized(This,isMinimized) \ - (This)->lpVtbl -> get_Minimized(This,isMinimized) - -#define IITWindow_put_Minimized(This,shouldBeMinimized) \ - (This)->lpVtbl -> put_Minimized(This,shouldBeMinimized) - -#define IITWindow_get_Maximizable(This,isMaximizable) \ - (This)->lpVtbl -> get_Maximizable(This,isMaximizable) - -#define IITWindow_get_Maximized(This,isMaximized) \ - (This)->lpVtbl -> get_Maximized(This,isMaximized) - -#define IITWindow_put_Maximized(This,shouldBeMaximized) \ - (This)->lpVtbl -> put_Maximized(This,shouldBeMaximized) - -#define IITWindow_get_Zoomable(This,isZoomable) \ - (This)->lpVtbl -> get_Zoomable(This,isZoomable) - -#define IITWindow_get_Zoomed(This,isZoomed) \ - (This)->lpVtbl -> get_Zoomed(This,isZoomed) - -#define IITWindow_put_Zoomed(This,shouldBeZoomed) \ - (This)->lpVtbl -> put_Zoomed(This,shouldBeZoomed) - -#define IITWindow_get_Top(This,top) \ - (This)->lpVtbl -> get_Top(This,top) - -#define IITWindow_put_Top(This,top) \ - (This)->lpVtbl -> put_Top(This,top) - -#define IITWindow_get_Left(This,left) \ - (This)->lpVtbl -> get_Left(This,left) - -#define IITWindow_put_Left(This,left) \ - (This)->lpVtbl -> put_Left(This,left) - -#define IITWindow_get_Bottom(This,bottom) \ - (This)->lpVtbl -> get_Bottom(This,bottom) - -#define IITWindow_put_Bottom(This,bottom) \ - (This)->lpVtbl -> put_Bottom(This,bottom) - -#define IITWindow_get_Right(This,right) \ - (This)->lpVtbl -> get_Right(This,right) - -#define IITWindow_put_Right(This,right) \ - (This)->lpVtbl -> put_Right(This,right) - -#define IITWindow_get_Width(This,width) \ - (This)->lpVtbl -> get_Width(This,width) - -#define IITWindow_put_Width(This,width) \ - (This)->lpVtbl -> put_Width(This,width) - -#define IITWindow_get_Height(This,height) \ - (This)->lpVtbl -> get_Height(This,height) - -#define IITWindow_put_Height(This,height) \ - (This)->lpVtbl -> put_Height(This,height) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Name_Proxy( - IITWindow * This, - /* [retval][out] */ BSTR *name); - - -void __RPC_STUB IITWindow_get_Name_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Kind_Proxy( - IITWindow * This, - /* [retval][out] */ ITWindowKind *kind); - - -void __RPC_STUB IITWindow_get_Kind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Visible_Proxy( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - -void __RPC_STUB IITWindow_get_Visible_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Visible_Proxy( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeVisible); - - -void __RPC_STUB IITWindow_put_Visible_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Resizable_Proxy( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isResizable); - - -void __RPC_STUB IITWindow_get_Resizable_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Minimized_Proxy( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMinimized); - - -void __RPC_STUB IITWindow_get_Minimized_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Minimized_Proxy( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMinimized); - - -void __RPC_STUB IITWindow_put_Minimized_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Maximizable_Proxy( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximizable); - - -void __RPC_STUB IITWindow_get_Maximizable_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Maximized_Proxy( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximized); - - -void __RPC_STUB IITWindow_get_Maximized_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Maximized_Proxy( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMaximized); - - -void __RPC_STUB IITWindow_put_Maximized_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Zoomable_Proxy( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomable); - - -void __RPC_STUB IITWindow_get_Zoomable_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Zoomed_Proxy( - IITWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomed); - - -void __RPC_STUB IITWindow_get_Zoomed_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Zoomed_Proxy( - IITWindow * This, - /* [in] */ VARIANT_BOOL shouldBeZoomed); - - -void __RPC_STUB IITWindow_put_Zoomed_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Top_Proxy( - IITWindow * This, - /* [retval][out] */ long *top); - - -void __RPC_STUB IITWindow_get_Top_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Top_Proxy( - IITWindow * This, - /* [in] */ long top); - - -void __RPC_STUB IITWindow_put_Top_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Left_Proxy( - IITWindow * This, - /* [retval][out] */ long *left); - - -void __RPC_STUB IITWindow_get_Left_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Left_Proxy( - IITWindow * This, - /* [in] */ long left); - - -void __RPC_STUB IITWindow_put_Left_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Bottom_Proxy( - IITWindow * This, - /* [retval][out] */ long *bottom); - - -void __RPC_STUB IITWindow_get_Bottom_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Bottom_Proxy( - IITWindow * This, - /* [in] */ long bottom); - - -void __RPC_STUB IITWindow_put_Bottom_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Right_Proxy( - IITWindow * This, - /* [retval][out] */ long *right); - - -void __RPC_STUB IITWindow_get_Right_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Right_Proxy( - IITWindow * This, - /* [in] */ long right); - - -void __RPC_STUB IITWindow_put_Right_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Width_Proxy( - IITWindow * This, - /* [retval][out] */ long *width); - - -void __RPC_STUB IITWindow_get_Width_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Width_Proxy( - IITWindow * This, - /* [in] */ long width); - - -void __RPC_STUB IITWindow_put_Width_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Height_Proxy( - IITWindow * This, - /* [retval][out] */ long *height); - - -void __RPC_STUB IITWindow_get_Height_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Height_Proxy( - IITWindow * This, - /* [in] */ long height); - - -void __RPC_STUB IITWindow_put_Height_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITWindow_INTERFACE_DEFINED__ */ - - -#ifndef __IITBrowserWindow_INTERFACE_DEFINED__ -#define __IITBrowserWindow_INTERFACE_DEFINED__ - -/* interface IITBrowserWindow */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITBrowserWindow; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("C999F455-C4D5-4aa4-8277-F99753699974") - IITBrowserWindow : public IITWindow - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_MiniPlayer( - /* [retval][out] */ VARIANT_BOOL *isMiniPlayer) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_MiniPlayer( - /* [in] */ VARIANT_BOOL shouldBeMiniPlayer) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedTracks( - /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedPlaylist( - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SelectedPlaylist( - /* [in] */ VARIANT *iPlaylist) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITBrowserWindowVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITBrowserWindow * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITBrowserWindow * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITBrowserWindow * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITBrowserWindow * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITBrowserWindow * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITBrowserWindow * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITBrowserWindow * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITBrowserWindow * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITBrowserWindow * This, - /* [retval][out] */ ITWindowKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Visible )( - IITBrowserWindow * This, - /* [in] */ VARIANT_BOOL shouldBeVisible); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Resizable )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isResizable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Minimized )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMinimized); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Minimized )( - IITBrowserWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMinimized); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximizable )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximizable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximized )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximized); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Maximized )( - IITBrowserWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMaximized); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomable )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomed )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomed); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Zoomed )( - IITBrowserWindow * This, - /* [in] */ VARIANT_BOOL shouldBeZoomed); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )( - IITBrowserWindow * This, - /* [retval][out] */ long *top); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Top )( - IITBrowserWindow * This, - /* [in] */ long top); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )( - IITBrowserWindow * This, - /* [retval][out] */ long *left); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Left )( - IITBrowserWindow * This, - /* [in] */ long left); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bottom )( - IITBrowserWindow * This, - /* [retval][out] */ long *bottom); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bottom )( - IITBrowserWindow * This, - /* [in] */ long bottom); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Right )( - IITBrowserWindow * This, - /* [retval][out] */ long *right); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Right )( - IITBrowserWindow * This, - /* [in] */ long right); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )( - IITBrowserWindow * This, - /* [retval][out] */ long *width); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Width )( - IITBrowserWindow * This, - /* [in] */ long width); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )( - IITBrowserWindow * This, - /* [retval][out] */ long *height); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Height )( - IITBrowserWindow * This, - /* [in] */ long height); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MiniPlayer )( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMiniPlayer); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_MiniPlayer )( - IITBrowserWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMiniPlayer); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedTracks )( - IITBrowserWindow * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedPlaylist )( - IITBrowserWindow * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SelectedPlaylist )( - IITBrowserWindow * This, - /* [in] */ VARIANT *iPlaylist); - - END_INTERFACE - } IITBrowserWindowVtbl; - - interface IITBrowserWindow - { - CONST_VTBL struct IITBrowserWindowVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITBrowserWindow_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITBrowserWindow_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITBrowserWindow_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITBrowserWindow_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITBrowserWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITBrowserWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITBrowserWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITBrowserWindow_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITBrowserWindow_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITBrowserWindow_get_Visible(This,isVisible) \ - (This)->lpVtbl -> get_Visible(This,isVisible) - -#define IITBrowserWindow_put_Visible(This,shouldBeVisible) \ - (This)->lpVtbl -> put_Visible(This,shouldBeVisible) - -#define IITBrowserWindow_get_Resizable(This,isResizable) \ - (This)->lpVtbl -> get_Resizable(This,isResizable) - -#define IITBrowserWindow_get_Minimized(This,isMinimized) \ - (This)->lpVtbl -> get_Minimized(This,isMinimized) - -#define IITBrowserWindow_put_Minimized(This,shouldBeMinimized) \ - (This)->lpVtbl -> put_Minimized(This,shouldBeMinimized) - -#define IITBrowserWindow_get_Maximizable(This,isMaximizable) \ - (This)->lpVtbl -> get_Maximizable(This,isMaximizable) - -#define IITBrowserWindow_get_Maximized(This,isMaximized) \ - (This)->lpVtbl -> get_Maximized(This,isMaximized) - -#define IITBrowserWindow_put_Maximized(This,shouldBeMaximized) \ - (This)->lpVtbl -> put_Maximized(This,shouldBeMaximized) - -#define IITBrowserWindow_get_Zoomable(This,isZoomable) \ - (This)->lpVtbl -> get_Zoomable(This,isZoomable) - -#define IITBrowserWindow_get_Zoomed(This,isZoomed) \ - (This)->lpVtbl -> get_Zoomed(This,isZoomed) - -#define IITBrowserWindow_put_Zoomed(This,shouldBeZoomed) \ - (This)->lpVtbl -> put_Zoomed(This,shouldBeZoomed) - -#define IITBrowserWindow_get_Top(This,top) \ - (This)->lpVtbl -> get_Top(This,top) - -#define IITBrowserWindow_put_Top(This,top) \ - (This)->lpVtbl -> put_Top(This,top) - -#define IITBrowserWindow_get_Left(This,left) \ - (This)->lpVtbl -> get_Left(This,left) - -#define IITBrowserWindow_put_Left(This,left) \ - (This)->lpVtbl -> put_Left(This,left) - -#define IITBrowserWindow_get_Bottom(This,bottom) \ - (This)->lpVtbl -> get_Bottom(This,bottom) - -#define IITBrowserWindow_put_Bottom(This,bottom) \ - (This)->lpVtbl -> put_Bottom(This,bottom) - -#define IITBrowserWindow_get_Right(This,right) \ - (This)->lpVtbl -> get_Right(This,right) - -#define IITBrowserWindow_put_Right(This,right) \ - (This)->lpVtbl -> put_Right(This,right) - -#define IITBrowserWindow_get_Width(This,width) \ - (This)->lpVtbl -> get_Width(This,width) - -#define IITBrowserWindow_put_Width(This,width) \ - (This)->lpVtbl -> put_Width(This,width) - -#define IITBrowserWindow_get_Height(This,height) \ - (This)->lpVtbl -> get_Height(This,height) - -#define IITBrowserWindow_put_Height(This,height) \ - (This)->lpVtbl -> put_Height(This,height) - - -#define IITBrowserWindow_get_MiniPlayer(This,isMiniPlayer) \ - (This)->lpVtbl -> get_MiniPlayer(This,isMiniPlayer) - -#define IITBrowserWindow_put_MiniPlayer(This,shouldBeMiniPlayer) \ - (This)->lpVtbl -> put_MiniPlayer(This,shouldBeMiniPlayer) - -#define IITBrowserWindow_get_SelectedTracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_SelectedTracks(This,iTrackCollection) - -#define IITBrowserWindow_get_SelectedPlaylist(This,iPlaylist) \ - (This)->lpVtbl -> get_SelectedPlaylist(This,iPlaylist) - -#define IITBrowserWindow_put_SelectedPlaylist(This,iPlaylist) \ - (This)->lpVtbl -> put_SelectedPlaylist(This,iPlaylist) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_get_MiniPlayer_Proxy( - IITBrowserWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMiniPlayer); - - -void __RPC_STUB IITBrowserWindow_get_MiniPlayer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_put_MiniPlayer_Proxy( - IITBrowserWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMiniPlayer); - - -void __RPC_STUB IITBrowserWindow_put_MiniPlayer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_get_SelectedTracks_Proxy( - IITBrowserWindow * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - -void __RPC_STUB IITBrowserWindow_get_SelectedTracks_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_get_SelectedPlaylist_Proxy( - IITBrowserWindow * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IITBrowserWindow_get_SelectedPlaylist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_put_SelectedPlaylist_Proxy( - IITBrowserWindow * This, - /* [in] */ VARIANT *iPlaylist); - - -void __RPC_STUB IITBrowserWindow_put_SelectedPlaylist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITBrowserWindow_INTERFACE_DEFINED__ */ - - -#ifndef __IITWindowCollection_INTERFACE_DEFINED__ -#define __IITWindowCollection_INTERFACE_DEFINED__ - -/* interface IITWindowCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITWindowCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("3D8DE381-6C0E-481f-A865-E2385F59FA43") - IITWindowCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITWindow **iWindow) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( - /* [in] */ BSTR name, - /* [retval][out] */ IITWindow **iWindow) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITWindowCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITWindowCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITWindowCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITWindowCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITWindowCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITWindowCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITWindowCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITWindowCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITWindowCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITWindowCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITWindow **iWindow); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( - IITWindowCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITWindow **iWindow); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITWindowCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - END_INTERFACE - } IITWindowCollectionVtbl; - - interface IITWindowCollection - { - CONST_VTBL struct IITWindowCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITWindowCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITWindowCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITWindowCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITWindowCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITWindowCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITWindowCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITWindowCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITWindowCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITWindowCollection_get_Item(This,index,iWindow) \ - (This)->lpVtbl -> get_Item(This,index,iWindow) - -#define IITWindowCollection_get_ItemByName(This,name,iWindow) \ - (This)->lpVtbl -> get_ItemByName(This,name,iWindow) - -#define IITWindowCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get_Count_Proxy( - IITWindowCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITWindowCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get_Item_Proxy( - IITWindowCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITWindow **iWindow); - - -void __RPC_STUB IITWindowCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get_ItemByName_Proxy( - IITWindowCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITWindow **iWindow); - - -void __RPC_STUB IITWindowCollection_get_ItemByName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get__NewEnum_Proxy( - IITWindowCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITWindowCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITWindowCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IiTunes_INTERFACE_DEFINED__ -#define __IiTunes_INTERFACE_DEFINED__ - -/* interface IiTunes */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - - - -EXTERN_C const IID IID_IiTunes; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("9DD6680B-3EDC-40db-A771-E6FE4832E34A") - IiTunes : public IDispatch - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE BackTrack( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE FastForward( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE NextTrack( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Pause( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Play( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayFile( - /* [in] */ BSTR filePath) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayPause( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PreviousTrack( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Resume( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Rewind( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Stop( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFile( - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFiles( - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTrack( - /* [in] */ VARIANT *iTrackToConvert, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTracks( - /* [in] */ VARIANT *iTracksToConvert, - /* [retval][out] */ IITOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CheckVersion( - /* [in] */ long majorVersion, - /* [in] */ long minorVersion, - /* [retval][out] */ VARIANT_BOOL *isCompatible) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetITObjectByID( - /* [in] */ long sourceID, - /* [in] */ long playlistID, - /* [in] */ long trackID, - /* [in] */ long databaseID, - /* [retval][out] */ IITObject **iObject) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePlaylist( - /* [in] */ BSTR playlistName, - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OpenURL( - /* [in] */ BSTR url) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GotoMusicStoreHomePage( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdateIPod( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Authorize( - /* [in] */ long numElems, - /* [size_is][in] */ VARIANT data[ ], - /* [size_is][in] */ BSTR names[ ]) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Quit( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Sources( - /* [retval][out] */ IITSourceCollection **iSourceCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Encoders( - /* [retval][out] */ IITEncoderCollection **iEncoderCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQPresets( - /* [retval][out] */ IITEQPresetCollection **iEQPresetCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Visuals( - /* [retval][out] */ IITVisualCollection **iVisualCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Windows( - /* [retval][out] */ IITWindowCollection **iWindowCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SoundVolume( - /* [retval][out] */ long *volume) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SoundVolume( - /* [in] */ long volume) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Mute( - /* [retval][out] */ VARIANT_BOOL *isMuted) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Mute( - /* [in] */ VARIANT_BOOL shouldMute) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayerState( - /* [retval][out] */ ITPlayerState *playerState) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayerPosition( - /* [retval][out] */ long *playerPos) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PlayerPosition( - /* [in] */ long playerPos) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentEncoder( - /* [retval][out] */ IITEncoder **iEncoder) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentEncoder( - /* [in] */ IITEncoder *iEncoder) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VisualsEnabled( - /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VisualsEnabled( - /* [in] */ VARIANT_BOOL shouldEnable) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_FullScreenVisuals( - /* [retval][out] */ VARIANT_BOOL *isFullScreen) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_FullScreenVisuals( - /* [in] */ VARIANT_BOOL shouldUseFullScreen) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VisualSize( - /* [retval][out] */ ITVisualSize *visualSize) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VisualSize( - /* [in] */ ITVisualSize visualSize) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentVisual( - /* [retval][out] */ IITVisual **iVisual) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentVisual( - /* [in] */ IITVisual *iVisual) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQEnabled( - /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EQEnabled( - /* [in] */ VARIANT_BOOL shouldEnable) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentEQPreset( - /* [retval][out] */ IITEQPreset **iEQPreset) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentEQPreset( - /* [in] */ IITEQPreset *iEQPreset) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentStreamTitle( - /* [retval][out] */ BSTR *streamTitle) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentStreamURL( - /* [retval][out] */ BSTR *streamURL) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BrowserWindow( - /* [retval][out] */ IITBrowserWindow **iBrowserWindow) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQWindow( - /* [retval][out] */ IITWindow **iEQWindow) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LibrarySource( - /* [retval][out] */ IITSource **iLibrarySource) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LibraryPlaylist( - /* [retval][out] */ IITLibraryPlaylist **iLibraryPlaylist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentTrack( - /* [retval][out] */ IITTrack **iTrack) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentPlaylist( - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedTracks( - /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Version( - /* [retval][out] */ BSTR *version) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetOptions( - /* [in] */ long options) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFile2( - /* [in] */ BSTR filePath, - /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFiles2( - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTrack2( - /* [in] */ VARIANT *iTrackToConvert, - /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTracks2( - /* [in] */ VARIANT *iTracksToConvert, - /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AppCommandMessageProcessingEnabled( - /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AppCommandMessageProcessingEnabled( - /* [in] */ VARIANT_BOOL shouldEnable) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ForceToForegroundOnDialog( - /* [retval][out] */ VARIANT_BOOL *forceToForegroundOnDialog) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_ForceToForegroundOnDialog( - /* [in] */ VARIANT_BOOL forceToForegroundOnDialog) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateEQPreset( - /* [in] */ BSTR eqPresetName, - /* [retval][out] */ IITEQPreset **iEQPreset) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePlaylistInSource( - /* [in] */ BSTR playlistName, - /* [in] */ VARIANT *iSource, - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetPlayerButtonsState( - /* [out] */ VARIANT_BOOL *previousEnabled, - /* [out] */ ITPlayButtonState *playPauseStopState, - /* [out] */ VARIANT_BOOL *nextEnabled) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayerButtonClicked( - /* [in] */ ITPlayerButton playerButton, - /* [in] */ long playerButtonModifierKeys) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CanSetShuffle( - /* [in] */ VARIANT *iPlaylist, - /* [retval][out] */ VARIANT_BOOL *canSetShuffle) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CanSetSongRepeat( - /* [in] */ VARIANT *iPlaylist, - /* [retval][out] */ VARIANT_BOOL *canSetSongRepeat) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ConvertOperationStatus( - /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SubscribeToPodcast( - /* [in] */ BSTR url) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdatePodcastFeeds( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateFolder( - /* [in] */ BSTR folderName, - /* [retval][out] */ IITPlaylist **iFolder) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateFolderInSource( - /* [in] */ BSTR folderName, - /* [in] */ VARIANT *iSource, - /* [retval][out] */ IITPlaylist **iFolder) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SoundVolumeControlEnabled( - /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LibraryXMLPath( - /* [retval][out] */ BSTR *filePath) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ITObjectPersistentIDHigh( - /* [in] */ VARIANT *iObject, - /* [retval][out] */ long *highID) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ITObjectPersistentIDLow( - /* [in] */ VARIANT *iObject, - /* [retval][out] */ long *lowID) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetITObjectPersistentIDs( - /* [in] */ VARIANT *iObject, - /* [out] */ long *highID, - /* [out] */ long *lowID) = 0; - - }; - -#else /* C style interface */ - - typedef struct IiTunesVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IiTunes * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IiTunes * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IiTunes * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IiTunes * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IiTunes * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IiTunes * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IiTunes * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *BackTrack )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *FastForward )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *NextTrack )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Pause )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFile )( - IiTunes * This, - /* [in] */ BSTR filePath); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayPause )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PreviousTrack )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Resume )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Rewind )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Stop )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFile )( - IiTunes * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFiles )( - IiTunes * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTrack )( - IiTunes * This, - /* [in] */ VARIANT *iTrackToConvert, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTracks )( - IiTunes * This, - /* [in] */ VARIANT *iTracksToConvert, - /* [retval][out] */ IITOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CheckVersion )( - IiTunes * This, - /* [in] */ long majorVersion, - /* [in] */ long minorVersion, - /* [retval][out] */ VARIANT_BOOL *isCompatible); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectByID )( - IiTunes * This, - /* [in] */ long sourceID, - /* [in] */ long playlistID, - /* [in] */ long trackID, - /* [in] */ long databaseID, - /* [retval][out] */ IITObject **iObject); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreatePlaylist )( - IiTunes * This, - /* [in] */ BSTR playlistName, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *OpenURL )( - IiTunes * This, - /* [in] */ BSTR url); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GotoMusicStoreHomePage )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdateIPod )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Authorize )( - IiTunes * This, - /* [in] */ long numElems, - /* [size_is][in] */ VARIANT data[ ], - /* [size_is][in] */ BSTR names[ ]); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Quit )( - IiTunes * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Sources )( - IiTunes * This, - /* [retval][out] */ IITSourceCollection **iSourceCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Encoders )( - IiTunes * This, - /* [retval][out] */ IITEncoderCollection **iEncoderCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQPresets )( - IiTunes * This, - /* [retval][out] */ IITEQPresetCollection **iEQPresetCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visuals )( - IiTunes * This, - /* [retval][out] */ IITVisualCollection **iVisualCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Windows )( - IiTunes * This, - /* [retval][out] */ IITWindowCollection **iWindowCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SoundVolume )( - IiTunes * This, - /* [retval][out] */ long *volume); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SoundVolume )( - IiTunes * This, - /* [in] */ long volume); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Mute )( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isMuted); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Mute )( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldMute); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayerState )( - IiTunes * This, - /* [retval][out] */ ITPlayerState *playerState); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayerPosition )( - IiTunes * This, - /* [retval][out] */ long *playerPos); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayerPosition )( - IiTunes * This, - /* [in] */ long playerPos); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentEncoder )( - IiTunes * This, - /* [retval][out] */ IITEncoder **iEncoder); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_CurrentEncoder )( - IiTunes * This, - /* [in] */ IITEncoder *iEncoder); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VisualsEnabled )( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VisualsEnabled )( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldEnable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_FullScreenVisuals )( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isFullScreen); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_FullScreenVisuals )( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldUseFullScreen); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VisualSize )( - IiTunes * This, - /* [retval][out] */ ITVisualSize *visualSize); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VisualSize )( - IiTunes * This, - /* [in] */ ITVisualSize visualSize); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentVisual )( - IiTunes * This, - /* [retval][out] */ IITVisual **iVisual); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_CurrentVisual )( - IiTunes * This, - /* [in] */ IITVisual *iVisual); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQEnabled )( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQEnabled )( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldEnable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentEQPreset )( - IiTunes * This, - /* [retval][out] */ IITEQPreset **iEQPreset); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_CurrentEQPreset )( - IiTunes * This, - /* [in] */ IITEQPreset *iEQPreset); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentStreamTitle )( - IiTunes * This, - /* [retval][out] */ BSTR *streamTitle); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentStreamURL )( - IiTunes * This, - /* [retval][out] */ BSTR *streamURL); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BrowserWindow )( - IiTunes * This, - /* [retval][out] */ IITBrowserWindow **iBrowserWindow); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQWindow )( - IiTunes * This, - /* [retval][out] */ IITWindow **iEQWindow); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LibrarySource )( - IiTunes * This, - /* [retval][out] */ IITSource **iLibrarySource); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LibraryPlaylist )( - IiTunes * This, - /* [retval][out] */ IITLibraryPlaylist **iLibraryPlaylist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentTrack )( - IiTunes * This, - /* [retval][out] */ IITTrack **iTrack); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentPlaylist )( - IiTunes * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedTracks )( - IiTunes * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Version )( - IiTunes * This, - /* [retval][out] */ BSTR *version); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetOptions )( - IiTunes * This, - /* [in] */ long options); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFile2 )( - IiTunes * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFiles2 )( - IiTunes * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTrack2 )( - IiTunes * This, - /* [in] */ VARIANT *iTrackToConvert, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTracks2 )( - IiTunes * This, - /* [in] */ VARIANT *iTracksToConvert, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AppCommandMessageProcessingEnabled )( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AppCommandMessageProcessingEnabled )( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldEnable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ForceToForegroundOnDialog )( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *forceToForegroundOnDialog); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ForceToForegroundOnDialog )( - IiTunes * This, - /* [in] */ VARIANT_BOOL forceToForegroundOnDialog); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateEQPreset )( - IiTunes * This, - /* [in] */ BSTR eqPresetName, - /* [retval][out] */ IITEQPreset **iEQPreset); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreatePlaylistInSource )( - IiTunes * This, - /* [in] */ BSTR playlistName, - /* [in] */ VARIANT *iSource, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPlayerButtonsState )( - IiTunes * This, - /* [out] */ VARIANT_BOOL *previousEnabled, - /* [out] */ ITPlayButtonState *playPauseStopState, - /* [out] */ VARIANT_BOOL *nextEnabled); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayerButtonClicked )( - IiTunes * This, - /* [in] */ ITPlayerButton playerButton, - /* [in] */ long playerButtonModifierKeys); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanSetShuffle )( - IiTunes * This, - /* [in] */ VARIANT *iPlaylist, - /* [retval][out] */ VARIANT_BOOL *canSetShuffle); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanSetSongRepeat )( - IiTunes * This, - /* [in] */ VARIANT *iPlaylist, - /* [retval][out] */ VARIANT_BOOL *canSetSongRepeat); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ConvertOperationStatus )( - IiTunes * This, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SubscribeToPodcast )( - IiTunes * This, - /* [in] */ BSTR url); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdatePodcastFeeds )( - IiTunes * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateFolder )( - IiTunes * This, - /* [in] */ BSTR folderName, - /* [retval][out] */ IITPlaylist **iFolder); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateFolderInSource )( - IiTunes * This, - /* [in] */ BSTR folderName, - /* [in] */ VARIANT *iSource, - /* [retval][out] */ IITPlaylist **iFolder); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SoundVolumeControlEnabled )( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LibraryXMLPath )( - IiTunes * This, - /* [retval][out] */ BSTR *filePath); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ITObjectPersistentIDHigh )( - IiTunes * This, - /* [in] */ VARIANT *iObject, - /* [retval][out] */ long *highID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ITObjectPersistentIDLow )( - IiTunes * This, - /* [in] */ VARIANT *iObject, - /* [retval][out] */ long *lowID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectPersistentIDs )( - IiTunes * This, - /* [in] */ VARIANT *iObject, - /* [out] */ long *highID, - /* [out] */ long *lowID); - - END_INTERFACE - } IiTunesVtbl; - - interface IiTunes - { - CONST_VTBL struct IiTunesVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IiTunes_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IiTunes_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IiTunes_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IiTunes_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IiTunes_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IiTunes_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IiTunes_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IiTunes_BackTrack(This) \ - (This)->lpVtbl -> BackTrack(This) - -#define IiTunes_FastForward(This) \ - (This)->lpVtbl -> FastForward(This) - -#define IiTunes_NextTrack(This) \ - (This)->lpVtbl -> NextTrack(This) - -#define IiTunes_Pause(This) \ - (This)->lpVtbl -> Pause(This) - -#define IiTunes_Play(This) \ - (This)->lpVtbl -> Play(This) - -#define IiTunes_PlayFile(This,filePath) \ - (This)->lpVtbl -> PlayFile(This,filePath) - -#define IiTunes_PlayPause(This) \ - (This)->lpVtbl -> PlayPause(This) - -#define IiTunes_PreviousTrack(This) \ - (This)->lpVtbl -> PreviousTrack(This) - -#define IiTunes_Resume(This) \ - (This)->lpVtbl -> Resume(This) - -#define IiTunes_Rewind(This) \ - (This)->lpVtbl -> Rewind(This) - -#define IiTunes_Stop(This) \ - (This)->lpVtbl -> Stop(This) - -#define IiTunes_ConvertFile(This,filePath,iStatus) \ - (This)->lpVtbl -> ConvertFile(This,filePath,iStatus) - -#define IiTunes_ConvertFiles(This,filePaths,iStatus) \ - (This)->lpVtbl -> ConvertFiles(This,filePaths,iStatus) - -#define IiTunes_ConvertTrack(This,iTrackToConvert,iStatus) \ - (This)->lpVtbl -> ConvertTrack(This,iTrackToConvert,iStatus) - -#define IiTunes_ConvertTracks(This,iTracksToConvert,iStatus) \ - (This)->lpVtbl -> ConvertTracks(This,iTracksToConvert,iStatus) - -#define IiTunes_CheckVersion(This,majorVersion,minorVersion,isCompatible) \ - (This)->lpVtbl -> CheckVersion(This,majorVersion,minorVersion,isCompatible) - -#define IiTunes_GetITObjectByID(This,sourceID,playlistID,trackID,databaseID,iObject) \ - (This)->lpVtbl -> GetITObjectByID(This,sourceID,playlistID,trackID,databaseID,iObject) - -#define IiTunes_CreatePlaylist(This,playlistName,iPlaylist) \ - (This)->lpVtbl -> CreatePlaylist(This,playlistName,iPlaylist) - -#define IiTunes_OpenURL(This,url) \ - (This)->lpVtbl -> OpenURL(This,url) - -#define IiTunes_GotoMusicStoreHomePage(This) \ - (This)->lpVtbl -> GotoMusicStoreHomePage(This) - -#define IiTunes_UpdateIPod(This) \ - (This)->lpVtbl -> UpdateIPod(This) - -#define IiTunes_Authorize(This,numElems,data,names) \ - (This)->lpVtbl -> Authorize(This,numElems,data,names) - -#define IiTunes_Quit(This) \ - (This)->lpVtbl -> Quit(This) - -#define IiTunes_get_Sources(This,iSourceCollection) \ - (This)->lpVtbl -> get_Sources(This,iSourceCollection) - -#define IiTunes_get_Encoders(This,iEncoderCollection) \ - (This)->lpVtbl -> get_Encoders(This,iEncoderCollection) - -#define IiTunes_get_EQPresets(This,iEQPresetCollection) \ - (This)->lpVtbl -> get_EQPresets(This,iEQPresetCollection) - -#define IiTunes_get_Visuals(This,iVisualCollection) \ - (This)->lpVtbl -> get_Visuals(This,iVisualCollection) - -#define IiTunes_get_Windows(This,iWindowCollection) \ - (This)->lpVtbl -> get_Windows(This,iWindowCollection) - -#define IiTunes_get_SoundVolume(This,volume) \ - (This)->lpVtbl -> get_SoundVolume(This,volume) - -#define IiTunes_put_SoundVolume(This,volume) \ - (This)->lpVtbl -> put_SoundVolume(This,volume) - -#define IiTunes_get_Mute(This,isMuted) \ - (This)->lpVtbl -> get_Mute(This,isMuted) - -#define IiTunes_put_Mute(This,shouldMute) \ - (This)->lpVtbl -> put_Mute(This,shouldMute) - -#define IiTunes_get_PlayerState(This,playerState) \ - (This)->lpVtbl -> get_PlayerState(This,playerState) - -#define IiTunes_get_PlayerPosition(This,playerPos) \ - (This)->lpVtbl -> get_PlayerPosition(This,playerPos) - -#define IiTunes_put_PlayerPosition(This,playerPos) \ - (This)->lpVtbl -> put_PlayerPosition(This,playerPos) - -#define IiTunes_get_CurrentEncoder(This,iEncoder) \ - (This)->lpVtbl -> get_CurrentEncoder(This,iEncoder) - -#define IiTunes_put_CurrentEncoder(This,iEncoder) \ - (This)->lpVtbl -> put_CurrentEncoder(This,iEncoder) - -#define IiTunes_get_VisualsEnabled(This,isEnabled) \ - (This)->lpVtbl -> get_VisualsEnabled(This,isEnabled) - -#define IiTunes_put_VisualsEnabled(This,shouldEnable) \ - (This)->lpVtbl -> put_VisualsEnabled(This,shouldEnable) - -#define IiTunes_get_FullScreenVisuals(This,isFullScreen) \ - (This)->lpVtbl -> get_FullScreenVisuals(This,isFullScreen) - -#define IiTunes_put_FullScreenVisuals(This,shouldUseFullScreen) \ - (This)->lpVtbl -> put_FullScreenVisuals(This,shouldUseFullScreen) - -#define IiTunes_get_VisualSize(This,visualSize) \ - (This)->lpVtbl -> get_VisualSize(This,visualSize) - -#define IiTunes_put_VisualSize(This,visualSize) \ - (This)->lpVtbl -> put_VisualSize(This,visualSize) - -#define IiTunes_get_CurrentVisual(This,iVisual) \ - (This)->lpVtbl -> get_CurrentVisual(This,iVisual) - -#define IiTunes_put_CurrentVisual(This,iVisual) \ - (This)->lpVtbl -> put_CurrentVisual(This,iVisual) - -#define IiTunes_get_EQEnabled(This,isEnabled) \ - (This)->lpVtbl -> get_EQEnabled(This,isEnabled) - -#define IiTunes_put_EQEnabled(This,shouldEnable) \ - (This)->lpVtbl -> put_EQEnabled(This,shouldEnable) - -#define IiTunes_get_CurrentEQPreset(This,iEQPreset) \ - (This)->lpVtbl -> get_CurrentEQPreset(This,iEQPreset) - -#define IiTunes_put_CurrentEQPreset(This,iEQPreset) \ - (This)->lpVtbl -> put_CurrentEQPreset(This,iEQPreset) - -#define IiTunes_get_CurrentStreamTitle(This,streamTitle) \ - (This)->lpVtbl -> get_CurrentStreamTitle(This,streamTitle) - -#define IiTunes_get_CurrentStreamURL(This,streamURL) \ - (This)->lpVtbl -> get_CurrentStreamURL(This,streamURL) - -#define IiTunes_get_BrowserWindow(This,iBrowserWindow) \ - (This)->lpVtbl -> get_BrowserWindow(This,iBrowserWindow) - -#define IiTunes_get_EQWindow(This,iEQWindow) \ - (This)->lpVtbl -> get_EQWindow(This,iEQWindow) - -#define IiTunes_get_LibrarySource(This,iLibrarySource) \ - (This)->lpVtbl -> get_LibrarySource(This,iLibrarySource) - -#define IiTunes_get_LibraryPlaylist(This,iLibraryPlaylist) \ - (This)->lpVtbl -> get_LibraryPlaylist(This,iLibraryPlaylist) - -#define IiTunes_get_CurrentTrack(This,iTrack) \ - (This)->lpVtbl -> get_CurrentTrack(This,iTrack) - -#define IiTunes_get_CurrentPlaylist(This,iPlaylist) \ - (This)->lpVtbl -> get_CurrentPlaylist(This,iPlaylist) - -#define IiTunes_get_SelectedTracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_SelectedTracks(This,iTrackCollection) - -#define IiTunes_get_Version(This,version) \ - (This)->lpVtbl -> get_Version(This,version) - -#define IiTunes_SetOptions(This,options) \ - (This)->lpVtbl -> SetOptions(This,options) - -#define IiTunes_ConvertFile2(This,filePath,iStatus) \ - (This)->lpVtbl -> ConvertFile2(This,filePath,iStatus) - -#define IiTunes_ConvertFiles2(This,filePaths,iStatus) \ - (This)->lpVtbl -> ConvertFiles2(This,filePaths,iStatus) - -#define IiTunes_ConvertTrack2(This,iTrackToConvert,iStatus) \ - (This)->lpVtbl -> ConvertTrack2(This,iTrackToConvert,iStatus) - -#define IiTunes_ConvertTracks2(This,iTracksToConvert,iStatus) \ - (This)->lpVtbl -> ConvertTracks2(This,iTracksToConvert,iStatus) - -#define IiTunes_get_AppCommandMessageProcessingEnabled(This,isEnabled) \ - (This)->lpVtbl -> get_AppCommandMessageProcessingEnabled(This,isEnabled) - -#define IiTunes_put_AppCommandMessageProcessingEnabled(This,shouldEnable) \ - (This)->lpVtbl -> put_AppCommandMessageProcessingEnabled(This,shouldEnable) - -#define IiTunes_get_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) \ - (This)->lpVtbl -> get_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) - -#define IiTunes_put_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) \ - (This)->lpVtbl -> put_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) - -#define IiTunes_CreateEQPreset(This,eqPresetName,iEQPreset) \ - (This)->lpVtbl -> CreateEQPreset(This,eqPresetName,iEQPreset) - -#define IiTunes_CreatePlaylistInSource(This,playlistName,iSource,iPlaylist) \ - (This)->lpVtbl -> CreatePlaylistInSource(This,playlistName,iSource,iPlaylist) - -#define IiTunes_GetPlayerButtonsState(This,previousEnabled,playPauseStopState,nextEnabled) \ - (This)->lpVtbl -> GetPlayerButtonsState(This,previousEnabled,playPauseStopState,nextEnabled) - -#define IiTunes_PlayerButtonClicked(This,playerButton,playerButtonModifierKeys) \ - (This)->lpVtbl -> PlayerButtonClicked(This,playerButton,playerButtonModifierKeys) - -#define IiTunes_get_CanSetShuffle(This,iPlaylist,canSetShuffle) \ - (This)->lpVtbl -> get_CanSetShuffle(This,iPlaylist,canSetShuffle) - -#define IiTunes_get_CanSetSongRepeat(This,iPlaylist,canSetSongRepeat) \ - (This)->lpVtbl -> get_CanSetSongRepeat(This,iPlaylist,canSetSongRepeat) - -#define IiTunes_get_ConvertOperationStatus(This,iStatus) \ - (This)->lpVtbl -> get_ConvertOperationStatus(This,iStatus) - -#define IiTunes_SubscribeToPodcast(This,url) \ - (This)->lpVtbl -> SubscribeToPodcast(This,url) - -#define IiTunes_UpdatePodcastFeeds(This) \ - (This)->lpVtbl -> UpdatePodcastFeeds(This) - -#define IiTunes_CreateFolder(This,folderName,iFolder) \ - (This)->lpVtbl -> CreateFolder(This,folderName,iFolder) - -#define IiTunes_CreateFolderInSource(This,folderName,iSource,iFolder) \ - (This)->lpVtbl -> CreateFolderInSource(This,folderName,iSource,iFolder) - -#define IiTunes_get_SoundVolumeControlEnabled(This,isEnabled) \ - (This)->lpVtbl -> get_SoundVolumeControlEnabled(This,isEnabled) - -#define IiTunes_get_LibraryXMLPath(This,filePath) \ - (This)->lpVtbl -> get_LibraryXMLPath(This,filePath) - -#define IiTunes_get_ITObjectPersistentIDHigh(This,iObject,highID) \ - (This)->lpVtbl -> get_ITObjectPersistentIDHigh(This,iObject,highID) - -#define IiTunes_get_ITObjectPersistentIDLow(This,iObject,lowID) \ - (This)->lpVtbl -> get_ITObjectPersistentIDLow(This,iObject,lowID) - -#define IiTunes_GetITObjectPersistentIDs(This,iObject,highID,lowID) \ - (This)->lpVtbl -> GetITObjectPersistentIDs(This,iObject,highID,lowID) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_BackTrack_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_BackTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_FastForward_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_FastForward_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_NextTrack_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_NextTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Pause_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_Pause_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Play_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_Play_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PlayFile_Proxy( - IiTunes * This, - /* [in] */ BSTR filePath); - - -void __RPC_STUB IiTunes_PlayFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PlayPause_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_PlayPause_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PreviousTrack_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_PreviousTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Resume_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_Resume_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Rewind_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_Rewind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Stop_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_Stop_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFile_Proxy( - IiTunes * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFiles_Proxy( - IiTunes * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertFiles_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTrack_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iTrackToConvert, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTracks_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iTracksToConvert, - /* [retval][out] */ IITOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertTracks_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CheckVersion_Proxy( - IiTunes * This, - /* [in] */ long majorVersion, - /* [in] */ long minorVersion, - /* [retval][out] */ VARIANT_BOOL *isCompatible); - - -void __RPC_STUB IiTunes_CheckVersion_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GetITObjectByID_Proxy( - IiTunes * This, - /* [in] */ long sourceID, - /* [in] */ long playlistID, - /* [in] */ long trackID, - /* [in] */ long databaseID, - /* [retval][out] */ IITObject **iObject); - - -void __RPC_STUB IiTunes_GetITObjectByID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreatePlaylist_Proxy( - IiTunes * This, - /* [in] */ BSTR playlistName, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IiTunes_CreatePlaylist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_OpenURL_Proxy( - IiTunes * This, - /* [in] */ BSTR url); - - -void __RPC_STUB IiTunes_OpenURL_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GotoMusicStoreHomePage_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_GotoMusicStoreHomePage_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_UpdateIPod_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_UpdateIPod_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Authorize_Proxy( - IiTunes * This, - /* [in] */ long numElems, - /* [size_is][in] */ VARIANT data[ ], - /* [size_is][in] */ BSTR names[ ]); - - -void __RPC_STUB IiTunes_Authorize_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Quit_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_Quit_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Sources_Proxy( - IiTunes * This, - /* [retval][out] */ IITSourceCollection **iSourceCollection); - - -void __RPC_STUB IiTunes_get_Sources_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Encoders_Proxy( - IiTunes * This, - /* [retval][out] */ IITEncoderCollection **iEncoderCollection); - - -void __RPC_STUB IiTunes_get_Encoders_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_EQPresets_Proxy( - IiTunes * This, - /* [retval][out] */ IITEQPresetCollection **iEQPresetCollection); - - -void __RPC_STUB IiTunes_get_EQPresets_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Visuals_Proxy( - IiTunes * This, - /* [retval][out] */ IITVisualCollection **iVisualCollection); - - -void __RPC_STUB IiTunes_get_Visuals_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Windows_Proxy( - IiTunes * This, - /* [retval][out] */ IITWindowCollection **iWindowCollection); - - -void __RPC_STUB IiTunes_get_Windows_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_SoundVolume_Proxy( - IiTunes * This, - /* [retval][out] */ long *volume); - - -void __RPC_STUB IiTunes_get_SoundVolume_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_SoundVolume_Proxy( - IiTunes * This, - /* [in] */ long volume); - - -void __RPC_STUB IiTunes_put_SoundVolume_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Mute_Proxy( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isMuted); - - -void __RPC_STUB IiTunes_get_Mute_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_Mute_Proxy( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldMute); - - -void __RPC_STUB IiTunes_put_Mute_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_PlayerState_Proxy( - IiTunes * This, - /* [retval][out] */ ITPlayerState *playerState); - - -void __RPC_STUB IiTunes_get_PlayerState_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_PlayerPosition_Proxy( - IiTunes * This, - /* [retval][out] */ long *playerPos); - - -void __RPC_STUB IiTunes_get_PlayerPosition_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_PlayerPosition_Proxy( - IiTunes * This, - /* [in] */ long playerPos); - - -void __RPC_STUB IiTunes_put_PlayerPosition_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentEncoder_Proxy( - IiTunes * This, - /* [retval][out] */ IITEncoder **iEncoder); - - -void __RPC_STUB IiTunes_get_CurrentEncoder_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_CurrentEncoder_Proxy( - IiTunes * This, - /* [in] */ IITEncoder *iEncoder); - - -void __RPC_STUB IiTunes_put_CurrentEncoder_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_VisualsEnabled_Proxy( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - -void __RPC_STUB IiTunes_get_VisualsEnabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_VisualsEnabled_Proxy( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldEnable); - - -void __RPC_STUB IiTunes_put_VisualsEnabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_FullScreenVisuals_Proxy( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isFullScreen); - - -void __RPC_STUB IiTunes_get_FullScreenVisuals_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_FullScreenVisuals_Proxy( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldUseFullScreen); - - -void __RPC_STUB IiTunes_put_FullScreenVisuals_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_VisualSize_Proxy( - IiTunes * This, - /* [retval][out] */ ITVisualSize *visualSize); - - -void __RPC_STUB IiTunes_get_VisualSize_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_VisualSize_Proxy( - IiTunes * This, - /* [in] */ ITVisualSize visualSize); - - -void __RPC_STUB IiTunes_put_VisualSize_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentVisual_Proxy( - IiTunes * This, - /* [retval][out] */ IITVisual **iVisual); - - -void __RPC_STUB IiTunes_get_CurrentVisual_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_CurrentVisual_Proxy( - IiTunes * This, - /* [in] */ IITVisual *iVisual); - - -void __RPC_STUB IiTunes_put_CurrentVisual_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_EQEnabled_Proxy( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - -void __RPC_STUB IiTunes_get_EQEnabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_EQEnabled_Proxy( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldEnable); - - -void __RPC_STUB IiTunes_put_EQEnabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentEQPreset_Proxy( - IiTunes * This, - /* [retval][out] */ IITEQPreset **iEQPreset); - - -void __RPC_STUB IiTunes_get_CurrentEQPreset_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_CurrentEQPreset_Proxy( - IiTunes * This, - /* [in] */ IITEQPreset *iEQPreset); - - -void __RPC_STUB IiTunes_put_CurrentEQPreset_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentStreamTitle_Proxy( - IiTunes * This, - /* [retval][out] */ BSTR *streamTitle); - - -void __RPC_STUB IiTunes_get_CurrentStreamTitle_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentStreamURL_Proxy( - IiTunes * This, - /* [retval][out] */ BSTR *streamURL); - - -void __RPC_STUB IiTunes_get_CurrentStreamURL_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_BrowserWindow_Proxy( - IiTunes * This, - /* [retval][out] */ IITBrowserWindow **iBrowserWindow); - - -void __RPC_STUB IiTunes_get_BrowserWindow_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_EQWindow_Proxy( - IiTunes * This, - /* [retval][out] */ IITWindow **iEQWindow); - - -void __RPC_STUB IiTunes_get_EQWindow_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_LibrarySource_Proxy( - IiTunes * This, - /* [retval][out] */ IITSource **iLibrarySource); - - -void __RPC_STUB IiTunes_get_LibrarySource_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_LibraryPlaylist_Proxy( - IiTunes * This, - /* [retval][out] */ IITLibraryPlaylist **iLibraryPlaylist); - - -void __RPC_STUB IiTunes_get_LibraryPlaylist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentTrack_Proxy( - IiTunes * This, - /* [retval][out] */ IITTrack **iTrack); - - -void __RPC_STUB IiTunes_get_CurrentTrack_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentPlaylist_Proxy( - IiTunes * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IiTunes_get_CurrentPlaylist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_SelectedTracks_Proxy( - IiTunes * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - -void __RPC_STUB IiTunes_get_SelectedTracks_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Version_Proxy( - IiTunes * This, - /* [retval][out] */ BSTR *version); - - -void __RPC_STUB IiTunes_get_Version_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_SetOptions_Proxy( - IiTunes * This, - /* [in] */ long options); - - -void __RPC_STUB IiTunes_SetOptions_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFile2_Proxy( - IiTunes * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertFile2_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFiles2_Proxy( - IiTunes * This, - /* [in] */ VARIANT *filePaths, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertFiles2_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTrack2_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iTrackToConvert, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertTrack2_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTracks2_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iTracksToConvert, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_ConvertTracks2_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_AppCommandMessageProcessingEnabled_Proxy( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - -void __RPC_STUB IiTunes_get_AppCommandMessageProcessingEnabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_AppCommandMessageProcessingEnabled_Proxy( - IiTunes * This, - /* [in] */ VARIANT_BOOL shouldEnable); - - -void __RPC_STUB IiTunes_put_AppCommandMessageProcessingEnabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ForceToForegroundOnDialog_Proxy( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *forceToForegroundOnDialog); - - -void __RPC_STUB IiTunes_get_ForceToForegroundOnDialog_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_ForceToForegroundOnDialog_Proxy( - IiTunes * This, - /* [in] */ VARIANT_BOOL forceToForegroundOnDialog); - - -void __RPC_STUB IiTunes_put_ForceToForegroundOnDialog_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreateEQPreset_Proxy( - IiTunes * This, - /* [in] */ BSTR eqPresetName, - /* [retval][out] */ IITEQPreset **iEQPreset); - - -void __RPC_STUB IiTunes_CreateEQPreset_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreatePlaylistInSource_Proxy( - IiTunes * This, - /* [in] */ BSTR playlistName, - /* [in] */ VARIANT *iSource, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IiTunes_CreatePlaylistInSource_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GetPlayerButtonsState_Proxy( - IiTunes * This, - /* [out] */ VARIANT_BOOL *previousEnabled, - /* [out] */ ITPlayButtonState *playPauseStopState, - /* [out] */ VARIANT_BOOL *nextEnabled); - - -void __RPC_STUB IiTunes_GetPlayerButtonsState_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PlayerButtonClicked_Proxy( - IiTunes * This, - /* [in] */ ITPlayerButton playerButton, - /* [in] */ long playerButtonModifierKeys); - - -void __RPC_STUB IiTunes_PlayerButtonClicked_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CanSetShuffle_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iPlaylist, - /* [retval][out] */ VARIANT_BOOL *canSetShuffle); - - -void __RPC_STUB IiTunes_get_CanSetShuffle_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CanSetSongRepeat_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iPlaylist, - /* [retval][out] */ VARIANT_BOOL *canSetSongRepeat); - - -void __RPC_STUB IiTunes_get_CanSetSongRepeat_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ConvertOperationStatus_Proxy( - IiTunes * This, - /* [retval][out] */ IITConvertOperationStatus **iStatus); - - -void __RPC_STUB IiTunes_get_ConvertOperationStatus_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_SubscribeToPodcast_Proxy( - IiTunes * This, - /* [in] */ BSTR url); - - -void __RPC_STUB IiTunes_SubscribeToPodcast_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_UpdatePodcastFeeds_Proxy( - IiTunes * This); - - -void __RPC_STUB IiTunes_UpdatePodcastFeeds_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreateFolder_Proxy( - IiTunes * This, - /* [in] */ BSTR folderName, - /* [retval][out] */ IITPlaylist **iFolder); - - -void __RPC_STUB IiTunes_CreateFolder_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreateFolderInSource_Proxy( - IiTunes * This, - /* [in] */ BSTR folderName, - /* [in] */ VARIANT *iSource, - /* [retval][out] */ IITPlaylist **iFolder); - - -void __RPC_STUB IiTunes_CreateFolderInSource_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_SoundVolumeControlEnabled_Proxy( - IiTunes * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - -void __RPC_STUB IiTunes_get_SoundVolumeControlEnabled_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_LibraryXMLPath_Proxy( - IiTunes * This, - /* [retval][out] */ BSTR *filePath); - - -void __RPC_STUB IiTunes_get_LibraryXMLPath_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ITObjectPersistentIDHigh_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iObject, - /* [retval][out] */ long *highID); - - -void __RPC_STUB IiTunes_get_ITObjectPersistentIDHigh_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ITObjectPersistentIDLow_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iObject, - /* [retval][out] */ long *lowID); - - -void __RPC_STUB IiTunes_get_ITObjectPersistentIDLow_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GetITObjectPersistentIDs_Proxy( - IiTunes * This, - /* [in] */ VARIANT *iObject, - /* [out] */ long *highID, - /* [out] */ long *lowID); - - -void __RPC_STUB IiTunes_GetITObjectPersistentIDs_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IiTunes_INTERFACE_DEFINED__ */ - - -#ifndef ___IiTunesEvents_DISPINTERFACE_DEFINED__ -#define ___IiTunesEvents_DISPINTERFACE_DEFINED__ - -/* dispinterface _IiTunesEvents */ -/* [helpstring][uuid] */ - - -EXTERN_C const IID DIID__IiTunesEvents; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("5846EB78-317E-4b6f-B0C3-11EE8C8FEEF2") - _IiTunesEvents : public IDispatch - { - }; - -#else /* C style interface */ - - typedef struct _IiTunesEventsVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - _IiTunesEvents * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - _IiTunesEvents * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - _IiTunesEvents * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - _IiTunesEvents * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - _IiTunesEvents * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - _IiTunesEvents * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - _IiTunesEvents * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - END_INTERFACE - } _IiTunesEventsVtbl; - - interface _IiTunesEvents - { - CONST_VTBL struct _IiTunesEventsVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define _IiTunesEvents_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define _IiTunesEvents_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define _IiTunesEvents_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define _IiTunesEvents_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define _IiTunesEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define _IiTunesEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define _IiTunesEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - -#endif /* ___IiTunesEvents_DISPINTERFACE_DEFINED__ */ - - -#ifndef ___IITConvertOperationStatusEvents_DISPINTERFACE_DEFINED__ -#define ___IITConvertOperationStatusEvents_DISPINTERFACE_DEFINED__ - -/* dispinterface _IITConvertOperationStatusEvents */ -/* [helpstring][uuid] */ - - -EXTERN_C const IID DIID__IITConvertOperationStatusEvents; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("5C47A705-8E8A-45a1-9EED-71C993F0BF60") - _IITConvertOperationStatusEvents : public IDispatch - { - }; - -#else /* C style interface */ - - typedef struct _IITConvertOperationStatusEventsVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - _IITConvertOperationStatusEvents * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - _IITConvertOperationStatusEvents * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - _IITConvertOperationStatusEvents * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - _IITConvertOperationStatusEvents * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - _IITConvertOperationStatusEvents * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - _IITConvertOperationStatusEvents * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - _IITConvertOperationStatusEvents * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - END_INTERFACE - } _IITConvertOperationStatusEventsVtbl; - - interface _IITConvertOperationStatusEvents - { - CONST_VTBL struct _IITConvertOperationStatusEventsVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define _IITConvertOperationStatusEvents_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define _IITConvertOperationStatusEvents_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define _IITConvertOperationStatusEvents_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define _IITConvertOperationStatusEvents_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define _IITConvertOperationStatusEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define _IITConvertOperationStatusEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define _IITConvertOperationStatusEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - -#endif /* ___IITConvertOperationStatusEvents_DISPINTERFACE_DEFINED__ */ - - -EXTERN_C const CLSID CLSID_iTunesApp; - -#ifdef __cplusplus - -class DECLSPEC_UUID("DC0C2640-1415-4644-875C-6F4D769839BA") -iTunesApp; -#endif - -EXTERN_C const CLSID CLSID_iTunesConvertOperationStatus; - -#ifdef __cplusplus - -class DECLSPEC_UUID("D06596AD-C900-41b2-BC68-1B486450FC56") -iTunesConvertOperationStatus; -#endif - -#ifndef __IITArtwork_INTERFACE_DEFINED__ -#define __IITArtwork_INTERFACE_DEFINED__ - -/* interface IITArtwork */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITArtwork; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("D0A6C1F8-BF3D-4cd8-AC47-FE32BDD17257") - IITArtwork : public IDispatch - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetArtworkFromFile( - /* [in] */ BSTR filePath) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SaveArtworkToFile( - /* [in] */ BSTR filePath) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Format( - /* [retval][out] */ ITArtworkFormat *format) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_IsDownloadedArtwork( - /* [retval][out] */ VARIANT_BOOL *isDownloadedArtwork) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Description( - /* [retval][out] */ BSTR *description) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Description( - /* [in] */ BSTR description) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITArtworkVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITArtwork * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITArtwork * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITArtwork * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITArtwork * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITArtwork * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITArtwork * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITArtwork * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITArtwork * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetArtworkFromFile )( - IITArtwork * This, - /* [in] */ BSTR filePath); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SaveArtworkToFile )( - IITArtwork * This, - /* [in] */ BSTR filePath); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Format )( - IITArtwork * This, - /* [retval][out] */ ITArtworkFormat *format); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsDownloadedArtwork )( - IITArtwork * This, - /* [retval][out] */ VARIANT_BOOL *isDownloadedArtwork); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Description )( - IITArtwork * This, - /* [retval][out] */ BSTR *description); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Description )( - IITArtwork * This, - /* [in] */ BSTR description); - - END_INTERFACE - } IITArtworkVtbl; - - interface IITArtwork - { - CONST_VTBL struct IITArtworkVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITArtwork_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITArtwork_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITArtwork_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITArtwork_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITArtwork_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITArtwork_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITArtwork_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITArtwork_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITArtwork_SetArtworkFromFile(This,filePath) \ - (This)->lpVtbl -> SetArtworkFromFile(This,filePath) - -#define IITArtwork_SaveArtworkToFile(This,filePath) \ - (This)->lpVtbl -> SaveArtworkToFile(This,filePath) - -#define IITArtwork_get_Format(This,format) \ - (This)->lpVtbl -> get_Format(This,format) - -#define IITArtwork_get_IsDownloadedArtwork(This,isDownloadedArtwork) \ - (This)->lpVtbl -> get_IsDownloadedArtwork(This,isDownloadedArtwork) - -#define IITArtwork_get_Description(This,description) \ - (This)->lpVtbl -> get_Description(This,description) - -#define IITArtwork_put_Description(This,description) \ - (This)->lpVtbl -> put_Description(This,description) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITArtwork_Delete_Proxy( - IITArtwork * This); - - -void __RPC_STUB IITArtwork_Delete_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITArtwork_SetArtworkFromFile_Proxy( - IITArtwork * This, - /* [in] */ BSTR filePath); - - -void __RPC_STUB IITArtwork_SetArtworkFromFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITArtwork_SaveArtworkToFile_Proxy( - IITArtwork * This, - /* [in] */ BSTR filePath); - - -void __RPC_STUB IITArtwork_SaveArtworkToFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtwork_get_Format_Proxy( - IITArtwork * This, - /* [retval][out] */ ITArtworkFormat *format); - - -void __RPC_STUB IITArtwork_get_Format_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtwork_get_IsDownloadedArtwork_Proxy( - IITArtwork * This, - /* [retval][out] */ VARIANT_BOOL *isDownloadedArtwork); - - -void __RPC_STUB IITArtwork_get_IsDownloadedArtwork_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtwork_get_Description_Proxy( - IITArtwork * This, - /* [retval][out] */ BSTR *description); - - -void __RPC_STUB IITArtwork_get_Description_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITArtwork_put_Description_Proxy( - IITArtwork * This, - /* [in] */ BSTR description); - - -void __RPC_STUB IITArtwork_put_Description_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITArtwork_INTERFACE_DEFINED__ */ - - -#ifndef __IITArtworkCollection_INTERFACE_DEFINED__ -#define __IITArtworkCollection_INTERFACE_DEFINED__ - -/* interface IITArtworkCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITArtworkCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("BF2742D7-418C-4858-9AF9-2981B062D23E") - IITArtworkCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITArtwork **iArtwork) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITArtworkCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITArtworkCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITArtworkCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITArtworkCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITArtworkCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITArtworkCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITArtworkCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITArtworkCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITArtworkCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITArtworkCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITArtwork **iArtwork); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITArtworkCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - END_INTERFACE - } IITArtworkCollectionVtbl; - - interface IITArtworkCollection - { - CONST_VTBL struct IITArtworkCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITArtworkCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITArtworkCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITArtworkCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITArtworkCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITArtworkCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITArtworkCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITArtworkCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITArtworkCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITArtworkCollection_get_Item(This,index,iArtwork) \ - (This)->lpVtbl -> get_Item(This,index,iArtwork) - -#define IITArtworkCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtworkCollection_get_Count_Proxy( - IITArtworkCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITArtworkCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITArtworkCollection_get_Item_Proxy( - IITArtworkCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITArtwork **iArtwork); - - -void __RPC_STUB IITArtworkCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITArtworkCollection_get__NewEnum_Proxy( - IITArtworkCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITArtworkCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITArtworkCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IITURLTrack_INTERFACE_DEFINED__ -#define __IITURLTrack_INTERFACE_DEFINED__ - -/* interface IITURLTrack */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITURLTrack; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("1116E3B5-29FD-4393-A7BD-454E5E327900") - IITURLTrack : public IITTrack - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_URL( - /* [retval][out] */ BSTR *url) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_URL( - /* [in] */ BSTR url) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Podcast( - /* [retval][out] */ VARIANT_BOOL *isPodcast) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdatePodcastFeed( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE DownloadPodcastEpisode( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Category( - /* [retval][out] */ BSTR *category) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Category( - /* [in] */ BSTR category) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Description( - /* [retval][out] */ BSTR *description) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Description( - /* [in] */ BSTR description) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LongDescription( - /* [retval][out] */ BSTR *longDescription) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_LongDescription( - /* [in] */ BSTR longDescription) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRating( - /* [retval][out] */ long *rating) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AlbumRating( - /* [in] */ long rating) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRatingKind( - /* [retval][out] */ ITRatingKind *ratingKind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RatingKind( - /* [retval][out] */ ITRatingKind *ratingKind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlists( - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITURLTrackVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITURLTrack * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITURLTrack * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITURLTrack * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITURLTrack * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITURLTrack * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITURLTrack * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITURLTrack * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITURLTrack * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITURLTrack * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITURLTrack * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITURLTrack * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITURLTrack * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITURLTrack * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITURLTrack * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITURLTrack * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITURLTrack * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( - IITURLTrack * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddArtworkFromFile )( - IITURLTrack * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITArtwork **iArtwork); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITURLTrack * This, - /* [retval][out] */ ITTrackKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( - IITURLTrack * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Album )( - IITURLTrack * This, - /* [retval][out] */ BSTR *album); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Album )( - IITURLTrack * This, - /* [in] */ BSTR album); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( - IITURLTrack * This, - /* [retval][out] */ BSTR *artist); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Artist )( - IITURLTrack * This, - /* [in] */ BSTR artist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BitRate )( - IITURLTrack * This, - /* [retval][out] */ long *bitrate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BPM )( - IITURLTrack * This, - /* [retval][out] */ long *beatsPerMinute); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BPM )( - IITURLTrack * This, - /* [in] */ long beatsPerMinute); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Comment )( - IITURLTrack * This, - /* [retval][out] */ BSTR *comment); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Comment )( - IITURLTrack * This, - /* [in] */ BSTR comment); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( - IITURLTrack * This, - /* [retval][out] */ VARIANT_BOOL *isCompilation); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Compilation )( - IITURLTrack * This, - /* [in] */ VARIANT_BOOL shouldBeCompilation); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( - IITURLTrack * This, - /* [retval][out] */ BSTR *composer); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Composer )( - IITURLTrack * This, - /* [in] */ BSTR composer); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DateAdded )( - IITURLTrack * This, - /* [retval][out] */ DATE *dateAdded); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( - IITURLTrack * This, - /* [retval][out] */ long *discCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscCount )( - IITURLTrack * This, - /* [in] */ long discCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( - IITURLTrack * This, - /* [retval][out] */ long *discNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscNumber )( - IITURLTrack * This, - /* [in] */ long discNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( - IITURLTrack * This, - /* [retval][out] */ long *duration); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Enabled )( - IITURLTrack * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Enabled )( - IITURLTrack * This, - /* [in] */ VARIANT_BOOL shouldBeEnabled); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQ )( - IITURLTrack * This, - /* [retval][out] */ BSTR *eq); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQ )( - IITURLTrack * This, - /* [in] */ BSTR eq); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Finish )( - IITURLTrack * This, - /* [in] */ long finish); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Finish )( - IITURLTrack * This, - /* [retval][out] */ long *finish); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( - IITURLTrack * This, - /* [retval][out] */ BSTR *genre); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Genre )( - IITURLTrack * This, - /* [in] */ BSTR genre); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Grouping )( - IITURLTrack * This, - /* [retval][out] */ BSTR *grouping); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Grouping )( - IITURLTrack * This, - /* [in] */ BSTR grouping); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_KindAsString )( - IITURLTrack * This, - /* [retval][out] */ BSTR *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ModificationDate )( - IITURLTrack * This, - /* [retval][out] */ DATE *dateModified); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedCount )( - IITURLTrack * This, - /* [retval][out] */ long *playedCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedCount )( - IITURLTrack * This, - /* [in] */ long playedCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedDate )( - IITURLTrack * This, - /* [retval][out] */ DATE *playedDate); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedDate )( - IITURLTrack * This, - /* [in] */ DATE playedDate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayOrderIndex )( - IITURLTrack * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Rating )( - IITURLTrack * This, - /* [retval][out] */ long *rating); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Rating )( - IITURLTrack * This, - /* [in] */ long rating); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SampleRate )( - IITURLTrack * This, - /* [retval][out] */ long *sampleRate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( - IITURLTrack * This, - /* [retval][out] */ long *size); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Start )( - IITURLTrack * This, - /* [retval][out] */ long *start); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Start )( - IITURLTrack * This, - /* [in] */ long start); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( - IITURLTrack * This, - /* [retval][out] */ BSTR *time); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackCount )( - IITURLTrack * This, - /* [retval][out] */ long *trackCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackCount )( - IITURLTrack * This, - /* [in] */ long trackCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackNumber )( - IITURLTrack * This, - /* [retval][out] */ long *trackNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackNumber )( - IITURLTrack * This, - /* [in] */ long trackNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VolumeAdjustment )( - IITURLTrack * This, - /* [retval][out] */ long *volumeAdjustment); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VolumeAdjustment )( - IITURLTrack * This, - /* [in] */ long volumeAdjustment); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( - IITURLTrack * This, - /* [retval][out] */ long *year); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Year )( - IITURLTrack * This, - /* [in] */ long year); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artwork )( - IITURLTrack * This, - /* [retval][out] */ IITArtworkCollection **iArtworkCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_URL )( - IITURLTrack * This, - /* [retval][out] */ BSTR *url); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_URL )( - IITURLTrack * This, - /* [in] */ BSTR url); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Podcast )( - IITURLTrack * This, - /* [retval][out] */ VARIANT_BOOL *isPodcast); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdatePodcastFeed )( - IITURLTrack * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *DownloadPodcastEpisode )( - IITURLTrack * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Category )( - IITURLTrack * This, - /* [retval][out] */ BSTR *category); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Category )( - IITURLTrack * This, - /* [in] */ BSTR category); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Description )( - IITURLTrack * This, - /* [retval][out] */ BSTR *description); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Description )( - IITURLTrack * This, - /* [in] */ BSTR description); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LongDescription )( - IITURLTrack * This, - /* [retval][out] */ BSTR *longDescription); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LongDescription )( - IITURLTrack * This, - /* [in] */ BSTR longDescription); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( - IITURLTrack * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRating )( - IITURLTrack * This, - /* [retval][out] */ long *rating); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AlbumRating )( - IITURLTrack * This, - /* [in] */ long rating); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRatingKind )( - IITURLTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RatingKind )( - IITURLTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( - IITURLTrack * This, - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); - - END_INTERFACE - } IITURLTrackVtbl; - - interface IITURLTrack - { - CONST_VTBL struct IITURLTrackVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITURLTrack_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITURLTrack_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITURLTrack_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITURLTrack_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITURLTrack_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITURLTrack_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITURLTrack_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITURLTrack_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITURLTrack_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITURLTrack_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITURLTrack_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITURLTrack_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITURLTrack_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITURLTrack_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITURLTrack_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITURLTrack_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITURLTrack_Play(This) \ - (This)->lpVtbl -> Play(This) - -#define IITURLTrack_AddArtworkFromFile(This,filePath,iArtwork) \ - (This)->lpVtbl -> AddArtworkFromFile(This,filePath,iArtwork) - -#define IITURLTrack_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITURLTrack_get_Playlist(This,iPlaylist) \ - (This)->lpVtbl -> get_Playlist(This,iPlaylist) - -#define IITURLTrack_get_Album(This,album) \ - (This)->lpVtbl -> get_Album(This,album) - -#define IITURLTrack_put_Album(This,album) \ - (This)->lpVtbl -> put_Album(This,album) - -#define IITURLTrack_get_Artist(This,artist) \ - (This)->lpVtbl -> get_Artist(This,artist) - -#define IITURLTrack_put_Artist(This,artist) \ - (This)->lpVtbl -> put_Artist(This,artist) - -#define IITURLTrack_get_BitRate(This,bitrate) \ - (This)->lpVtbl -> get_BitRate(This,bitrate) - -#define IITURLTrack_get_BPM(This,beatsPerMinute) \ - (This)->lpVtbl -> get_BPM(This,beatsPerMinute) - -#define IITURLTrack_put_BPM(This,beatsPerMinute) \ - (This)->lpVtbl -> put_BPM(This,beatsPerMinute) - -#define IITURLTrack_get_Comment(This,comment) \ - (This)->lpVtbl -> get_Comment(This,comment) - -#define IITURLTrack_put_Comment(This,comment) \ - (This)->lpVtbl -> put_Comment(This,comment) - -#define IITURLTrack_get_Compilation(This,isCompilation) \ - (This)->lpVtbl -> get_Compilation(This,isCompilation) - -#define IITURLTrack_put_Compilation(This,shouldBeCompilation) \ - (This)->lpVtbl -> put_Compilation(This,shouldBeCompilation) - -#define IITURLTrack_get_Composer(This,composer) \ - (This)->lpVtbl -> get_Composer(This,composer) - -#define IITURLTrack_put_Composer(This,composer) \ - (This)->lpVtbl -> put_Composer(This,composer) - -#define IITURLTrack_get_DateAdded(This,dateAdded) \ - (This)->lpVtbl -> get_DateAdded(This,dateAdded) - -#define IITURLTrack_get_DiscCount(This,discCount) \ - (This)->lpVtbl -> get_DiscCount(This,discCount) - -#define IITURLTrack_put_DiscCount(This,discCount) \ - (This)->lpVtbl -> put_DiscCount(This,discCount) - -#define IITURLTrack_get_DiscNumber(This,discNumber) \ - (This)->lpVtbl -> get_DiscNumber(This,discNumber) - -#define IITURLTrack_put_DiscNumber(This,discNumber) \ - (This)->lpVtbl -> put_DiscNumber(This,discNumber) - -#define IITURLTrack_get_Duration(This,duration) \ - (This)->lpVtbl -> get_Duration(This,duration) - -#define IITURLTrack_get_Enabled(This,isEnabled) \ - (This)->lpVtbl -> get_Enabled(This,isEnabled) - -#define IITURLTrack_put_Enabled(This,shouldBeEnabled) \ - (This)->lpVtbl -> put_Enabled(This,shouldBeEnabled) - -#define IITURLTrack_get_EQ(This,eq) \ - (This)->lpVtbl -> get_EQ(This,eq) - -#define IITURLTrack_put_EQ(This,eq) \ - (This)->lpVtbl -> put_EQ(This,eq) - -#define IITURLTrack_put_Finish(This,finish) \ - (This)->lpVtbl -> put_Finish(This,finish) - -#define IITURLTrack_get_Finish(This,finish) \ - (This)->lpVtbl -> get_Finish(This,finish) - -#define IITURLTrack_get_Genre(This,genre) \ - (This)->lpVtbl -> get_Genre(This,genre) - -#define IITURLTrack_put_Genre(This,genre) \ - (This)->lpVtbl -> put_Genre(This,genre) - -#define IITURLTrack_get_Grouping(This,grouping) \ - (This)->lpVtbl -> get_Grouping(This,grouping) - -#define IITURLTrack_put_Grouping(This,grouping) \ - (This)->lpVtbl -> put_Grouping(This,grouping) - -#define IITURLTrack_get_KindAsString(This,kind) \ - (This)->lpVtbl -> get_KindAsString(This,kind) - -#define IITURLTrack_get_ModificationDate(This,dateModified) \ - (This)->lpVtbl -> get_ModificationDate(This,dateModified) - -#define IITURLTrack_get_PlayedCount(This,playedCount) \ - (This)->lpVtbl -> get_PlayedCount(This,playedCount) - -#define IITURLTrack_put_PlayedCount(This,playedCount) \ - (This)->lpVtbl -> put_PlayedCount(This,playedCount) - -#define IITURLTrack_get_PlayedDate(This,playedDate) \ - (This)->lpVtbl -> get_PlayedDate(This,playedDate) - -#define IITURLTrack_put_PlayedDate(This,playedDate) \ - (This)->lpVtbl -> put_PlayedDate(This,playedDate) - -#define IITURLTrack_get_PlayOrderIndex(This,index) \ - (This)->lpVtbl -> get_PlayOrderIndex(This,index) - -#define IITURLTrack_get_Rating(This,rating) \ - (This)->lpVtbl -> get_Rating(This,rating) - -#define IITURLTrack_put_Rating(This,rating) \ - (This)->lpVtbl -> put_Rating(This,rating) - -#define IITURLTrack_get_SampleRate(This,sampleRate) \ - (This)->lpVtbl -> get_SampleRate(This,sampleRate) - -#define IITURLTrack_get_Size(This,size) \ - (This)->lpVtbl -> get_Size(This,size) - -#define IITURLTrack_get_Start(This,start) \ - (This)->lpVtbl -> get_Start(This,start) - -#define IITURLTrack_put_Start(This,start) \ - (This)->lpVtbl -> put_Start(This,start) - -#define IITURLTrack_get_Time(This,time) \ - (This)->lpVtbl -> get_Time(This,time) - -#define IITURLTrack_get_TrackCount(This,trackCount) \ - (This)->lpVtbl -> get_TrackCount(This,trackCount) - -#define IITURLTrack_put_TrackCount(This,trackCount) \ - (This)->lpVtbl -> put_TrackCount(This,trackCount) - -#define IITURLTrack_get_TrackNumber(This,trackNumber) \ - (This)->lpVtbl -> get_TrackNumber(This,trackNumber) - -#define IITURLTrack_put_TrackNumber(This,trackNumber) \ - (This)->lpVtbl -> put_TrackNumber(This,trackNumber) - -#define IITURLTrack_get_VolumeAdjustment(This,volumeAdjustment) \ - (This)->lpVtbl -> get_VolumeAdjustment(This,volumeAdjustment) - -#define IITURLTrack_put_VolumeAdjustment(This,volumeAdjustment) \ - (This)->lpVtbl -> put_VolumeAdjustment(This,volumeAdjustment) - -#define IITURLTrack_get_Year(This,year) \ - (This)->lpVtbl -> get_Year(This,year) - -#define IITURLTrack_put_Year(This,year) \ - (This)->lpVtbl -> put_Year(This,year) - -#define IITURLTrack_get_Artwork(This,iArtworkCollection) \ - (This)->lpVtbl -> get_Artwork(This,iArtworkCollection) - - -#define IITURLTrack_get_URL(This,url) \ - (This)->lpVtbl -> get_URL(This,url) - -#define IITURLTrack_put_URL(This,url) \ - (This)->lpVtbl -> put_URL(This,url) - -#define IITURLTrack_get_Podcast(This,isPodcast) \ - (This)->lpVtbl -> get_Podcast(This,isPodcast) - -#define IITURLTrack_UpdatePodcastFeed(This) \ - (This)->lpVtbl -> UpdatePodcastFeed(This) - -#define IITURLTrack_DownloadPodcastEpisode(This) \ - (This)->lpVtbl -> DownloadPodcastEpisode(This) - -#define IITURLTrack_get_Category(This,category) \ - (This)->lpVtbl -> get_Category(This,category) - -#define IITURLTrack_put_Category(This,category) \ - (This)->lpVtbl -> put_Category(This,category) - -#define IITURLTrack_get_Description(This,description) \ - (This)->lpVtbl -> get_Description(This,description) - -#define IITURLTrack_put_Description(This,description) \ - (This)->lpVtbl -> put_Description(This,description) - -#define IITURLTrack_get_LongDescription(This,longDescription) \ - (This)->lpVtbl -> get_LongDescription(This,longDescription) - -#define IITURLTrack_put_LongDescription(This,longDescription) \ - (This)->lpVtbl -> put_LongDescription(This,longDescription) - -#define IITURLTrack_Reveal(This) \ - (This)->lpVtbl -> Reveal(This) - -#define IITURLTrack_get_AlbumRating(This,rating) \ - (This)->lpVtbl -> get_AlbumRating(This,rating) - -#define IITURLTrack_put_AlbumRating(This,rating) \ - (This)->lpVtbl -> put_AlbumRating(This,rating) - -#define IITURLTrack_get_AlbumRatingKind(This,ratingKind) \ - (This)->lpVtbl -> get_AlbumRatingKind(This,ratingKind) - -#define IITURLTrack_get_RatingKind(This,ratingKind) \ - (This)->lpVtbl -> get_RatingKind(This,ratingKind) - -#define IITURLTrack_get_Playlists(This,iPlaylistCollection) \ - (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_URL_Proxy( - IITURLTrack * This, - /* [retval][out] */ BSTR *url); - - -void __RPC_STUB IITURLTrack_get_URL_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_URL_Proxy( - IITURLTrack * This, - /* [in] */ BSTR url); - - -void __RPC_STUB IITURLTrack_put_URL_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Podcast_Proxy( - IITURLTrack * This, - /* [retval][out] */ VARIANT_BOOL *isPodcast); - - -void __RPC_STUB IITURLTrack_get_Podcast_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITURLTrack_UpdatePodcastFeed_Proxy( - IITURLTrack * This); - - -void __RPC_STUB IITURLTrack_UpdatePodcastFeed_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITURLTrack_DownloadPodcastEpisode_Proxy( - IITURLTrack * This); - - -void __RPC_STUB IITURLTrack_DownloadPodcastEpisode_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Category_Proxy( - IITURLTrack * This, - /* [retval][out] */ BSTR *category); - - -void __RPC_STUB IITURLTrack_get_Category_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_Category_Proxy( - IITURLTrack * This, - /* [in] */ BSTR category); - - -void __RPC_STUB IITURLTrack_put_Category_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Description_Proxy( - IITURLTrack * This, - /* [retval][out] */ BSTR *description); - - -void __RPC_STUB IITURLTrack_get_Description_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_Description_Proxy( - IITURLTrack * This, - /* [in] */ BSTR description); - - -void __RPC_STUB IITURLTrack_put_Description_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_LongDescription_Proxy( - IITURLTrack * This, - /* [retval][out] */ BSTR *longDescription); - - -void __RPC_STUB IITURLTrack_get_LongDescription_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_LongDescription_Proxy( - IITURLTrack * This, - /* [in] */ BSTR longDescription); - - -void __RPC_STUB IITURLTrack_put_LongDescription_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITURLTrack_Reveal_Proxy( - IITURLTrack * This); - - -void __RPC_STUB IITURLTrack_Reveal_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_AlbumRating_Proxy( - IITURLTrack * This, - /* [retval][out] */ long *rating); - - -void __RPC_STUB IITURLTrack_get_AlbumRating_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_AlbumRating_Proxy( - IITURLTrack * This, - /* [in] */ long rating); - - -void __RPC_STUB IITURLTrack_put_AlbumRating_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_AlbumRatingKind_Proxy( - IITURLTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - -void __RPC_STUB IITURLTrack_get_AlbumRatingKind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_RatingKind_Proxy( - IITURLTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - -void __RPC_STUB IITURLTrack_get_RatingKind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Playlists_Proxy( - IITURLTrack * This, - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); - - -void __RPC_STUB IITURLTrack_get_Playlists_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITURLTrack_INTERFACE_DEFINED__ */ - - -#ifndef __IITAudioCDPlaylist_INTERFACE_DEFINED__ -#define __IITAudioCDPlaylist_INTERFACE_DEFINED__ - -/* interface IITAudioCDPlaylist */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITAudioCDPlaylist; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("CF496DF3-0FED-4d7d-9BD8-529B6E8A082E") - IITAudioCDPlaylist : public IITPlaylist - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Artist( - /* [retval][out] */ BSTR *artist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Compilation( - /* [retval][out] */ VARIANT_BOOL *isCompiliation) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Composer( - /* [retval][out] */ BSTR *composer) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscCount( - /* [retval][out] */ long *discCount) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscNumber( - /* [retval][out] */ long *discNumber) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Genre( - /* [retval][out] */ BSTR *genre) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Year( - /* [retval][out] */ long *year) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITAudioCDPlaylistVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITAudioCDPlaylist * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITAudioCDPlaylist * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITAudioCDPlaylist * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITAudioCDPlaylist * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITAudioCDPlaylist * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITAudioCDPlaylist * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITAudioCDPlaylist * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITAudioCDPlaylist * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITAudioCDPlaylist * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITAudioCDPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( - IITAudioCDPlaylist * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( - IITAudioCDPlaylist * This, - /* [in] */ VARIANT_BOOL showPrintDialog, - /* [in] */ ITPlaylistPrintKind printKind, - /* [in] */ BSTR theme); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( - IITAudioCDPlaylist * This, - /* [in] */ BSTR searchText, - /* [in] */ ITPlaylistSearchField searchFields, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITAudioCDPlaylist * This, - /* [retval][out] */ ITPlaylistKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( - IITAudioCDPlaylist * This, - /* [retval][out] */ IITSource **iSource); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *duration); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( - IITAudioCDPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isShuffle); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( - IITAudioCDPlaylist * This, - /* [in] */ VARIANT_BOOL shouldShuffle); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( - IITAudioCDPlaylist * This, - /* [retval][out] */ double *size); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( - IITAudioCDPlaylist * This, - /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( - IITAudioCDPlaylist * This, - /* [in] */ ITPlaylistRepeatMode repeatMode); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *time); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( - IITAudioCDPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( - IITAudioCDPlaylist * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *artist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( - IITAudioCDPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isCompiliation); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *composer); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *discCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *discNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *genre); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *year); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( - IITAudioCDPlaylist * This); - - END_INTERFACE - } IITAudioCDPlaylistVtbl; - - interface IITAudioCDPlaylist - { - CONST_VTBL struct IITAudioCDPlaylistVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITAudioCDPlaylist_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITAudioCDPlaylist_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITAudioCDPlaylist_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITAudioCDPlaylist_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITAudioCDPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITAudioCDPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITAudioCDPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITAudioCDPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITAudioCDPlaylist_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITAudioCDPlaylist_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITAudioCDPlaylist_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITAudioCDPlaylist_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITAudioCDPlaylist_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITAudioCDPlaylist_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITAudioCDPlaylist_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITAudioCDPlaylist_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITAudioCDPlaylist_PlayFirstTrack(This) \ - (This)->lpVtbl -> PlayFirstTrack(This) - -#define IITAudioCDPlaylist_Print(This,showPrintDialog,printKind,theme) \ - (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) - -#define IITAudioCDPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ - (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) - -#define IITAudioCDPlaylist_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITAudioCDPlaylist_get_Source(This,iSource) \ - (This)->lpVtbl -> get_Source(This,iSource) - -#define IITAudioCDPlaylist_get_Duration(This,duration) \ - (This)->lpVtbl -> get_Duration(This,duration) - -#define IITAudioCDPlaylist_get_Shuffle(This,isShuffle) \ - (This)->lpVtbl -> get_Shuffle(This,isShuffle) - -#define IITAudioCDPlaylist_put_Shuffle(This,shouldShuffle) \ - (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) - -#define IITAudioCDPlaylist_get_Size(This,size) \ - (This)->lpVtbl -> get_Size(This,size) - -#define IITAudioCDPlaylist_get_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> get_SongRepeat(This,repeatMode) - -#define IITAudioCDPlaylist_put_SongRepeat(This,repeatMode) \ - (This)->lpVtbl -> put_SongRepeat(This,repeatMode) - -#define IITAudioCDPlaylist_get_Time(This,time) \ - (This)->lpVtbl -> get_Time(This,time) - -#define IITAudioCDPlaylist_get_Visible(This,isVisible) \ - (This)->lpVtbl -> get_Visible(This,isVisible) - -#define IITAudioCDPlaylist_get_Tracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_Tracks(This,iTrackCollection) - - -#define IITAudioCDPlaylist_get_Artist(This,artist) \ - (This)->lpVtbl -> get_Artist(This,artist) - -#define IITAudioCDPlaylist_get_Compilation(This,isCompiliation) \ - (This)->lpVtbl -> get_Compilation(This,isCompiliation) - -#define IITAudioCDPlaylist_get_Composer(This,composer) \ - (This)->lpVtbl -> get_Composer(This,composer) - -#define IITAudioCDPlaylist_get_DiscCount(This,discCount) \ - (This)->lpVtbl -> get_DiscCount(This,discCount) - -#define IITAudioCDPlaylist_get_DiscNumber(This,discNumber) \ - (This)->lpVtbl -> get_DiscNumber(This,discNumber) - -#define IITAudioCDPlaylist_get_Genre(This,genre) \ - (This)->lpVtbl -> get_Genre(This,genre) - -#define IITAudioCDPlaylist_get_Year(This,year) \ - (This)->lpVtbl -> get_Year(This,year) - -#define IITAudioCDPlaylist_Reveal(This) \ - (This)->lpVtbl -> Reveal(This) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Artist_Proxy( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *artist); - - -void __RPC_STUB IITAudioCDPlaylist_get_Artist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Compilation_Proxy( - IITAudioCDPlaylist * This, - /* [retval][out] */ VARIANT_BOOL *isCompiliation); - - -void __RPC_STUB IITAudioCDPlaylist_get_Compilation_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Composer_Proxy( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *composer); - - -void __RPC_STUB IITAudioCDPlaylist_get_Composer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_DiscCount_Proxy( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *discCount); - - -void __RPC_STUB IITAudioCDPlaylist_get_DiscCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_DiscNumber_Proxy( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *discNumber); - - -void __RPC_STUB IITAudioCDPlaylist_get_DiscNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Genre_Proxy( - IITAudioCDPlaylist * This, - /* [retval][out] */ BSTR *genre); - - -void __RPC_STUB IITAudioCDPlaylist_get_Genre_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Year_Proxy( - IITAudioCDPlaylist * This, - /* [retval][out] */ long *year); - - -void __RPC_STUB IITAudioCDPlaylist_get_Year_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_Reveal_Proxy( - IITAudioCDPlaylist * This); - - -void __RPC_STUB IITAudioCDPlaylist_Reveal_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITAudioCDPlaylist_INTERFACE_DEFINED__ */ - - -#ifndef __IITPlaylistCollection_INTERFACE_DEFINED__ -#define __IITPlaylistCollection_INTERFACE_DEFINED__ - -/* interface IITPlaylistCollection */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITPlaylistCollection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("FF194254-909D-4437-9C50-3AAC2AE6305C") - IITPlaylistCollection : public IDispatch - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( - /* [retval][out] */ long *count) = 0; - - virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( - /* [in] */ long index, - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( - /* [in] */ BSTR name, - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( - /* [retval][out] */ IUnknown **iEnumerator) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPersistentID( - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITPlaylistCollectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITPlaylistCollection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITPlaylistCollection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITPlaylistCollection * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITPlaylistCollection * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITPlaylistCollection * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITPlaylistCollection * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITPlaylistCollection * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( - IITPlaylistCollection * This, - /* [retval][out] */ long *count); - - /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( - IITPlaylistCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( - IITPlaylistCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( - IITPlaylistCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPersistentID )( - IITPlaylistCollection * This, - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITPlaylist **iPlaylist); - - END_INTERFACE - } IITPlaylistCollectionVtbl; - - interface IITPlaylistCollection - { - CONST_VTBL struct IITPlaylistCollectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITPlaylistCollection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITPlaylistCollection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITPlaylistCollection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITPlaylistCollection_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITPlaylistCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITPlaylistCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITPlaylistCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITPlaylistCollection_get_Count(This,count) \ - (This)->lpVtbl -> get_Count(This,count) - -#define IITPlaylistCollection_get_Item(This,index,iPlaylist) \ - (This)->lpVtbl -> get_Item(This,index,iPlaylist) - -#define IITPlaylistCollection_get_ItemByName(This,name,iPlaylist) \ - (This)->lpVtbl -> get_ItemByName(This,name,iPlaylist) - -#define IITPlaylistCollection_get__NewEnum(This,iEnumerator) \ - (This)->lpVtbl -> get__NewEnum(This,iEnumerator) - -#define IITPlaylistCollection_get_ItemByPersistentID(This,highID,lowID,iPlaylist) \ - (This)->lpVtbl -> get_ItemByPersistentID(This,highID,lowID,iPlaylist) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_Count_Proxy( - IITPlaylistCollection * This, - /* [retval][out] */ long *count); - - -void __RPC_STUB IITPlaylistCollection_get_Count_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_Item_Proxy( - IITPlaylistCollection * This, - /* [in] */ long index, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IITPlaylistCollection_get_Item_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_ItemByName_Proxy( - IITPlaylistCollection * This, - /* [in] */ BSTR name, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IITPlaylistCollection_get_ItemByName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get__NewEnum_Proxy( - IITPlaylistCollection * This, - /* [retval][out] */ IUnknown **iEnumerator); - - -void __RPC_STUB IITPlaylistCollection_get__NewEnum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_ItemByPersistentID_Proxy( - IITPlaylistCollection * This, - /* [in] */ long highID, - /* [in] */ long lowID, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IITPlaylistCollection_get_ItemByPersistentID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITPlaylistCollection_INTERFACE_DEFINED__ */ - - -#ifndef __IITIPodSource_INTERFACE_DEFINED__ -#define __IITIPodSource_INTERFACE_DEFINED__ - -/* interface IITIPodSource */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITIPodSource; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("CF4D8ACE-1720-4fb9-B0AE-9877249E89B0") - IITIPodSource : public IITSource - { - public: - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdateIPod( void) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE EjectIPod( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SoftwareVersion( - /* [retval][out] */ BSTR *softwareVersion) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITIPodSourceVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITIPodSource * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITIPodSource * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITIPodSource * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITIPodSource * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITIPodSource * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITIPodSource * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITIPodSource * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITIPodSource * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITIPodSource * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITIPodSource * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITIPodSource * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITIPodSource * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITIPodSource * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITIPodSource * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITIPodSource * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITIPodSource * This, - /* [retval][out] */ ITSourceKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Capacity )( - IITIPodSource * This, - /* [retval][out] */ double *capacity); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_FreeSpace )( - IITIPodSource * This, - /* [retval][out] */ double *freespace); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( - IITIPodSource * This, - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdateIPod )( - IITIPodSource * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *EjectIPod )( - IITIPodSource * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SoftwareVersion )( - IITIPodSource * This, - /* [retval][out] */ BSTR *softwareVersion); - - END_INTERFACE - } IITIPodSourceVtbl; - - interface IITIPodSource - { - CONST_VTBL struct IITIPodSourceVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITIPodSource_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITIPodSource_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITIPodSource_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITIPodSource_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITIPodSource_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITIPodSource_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITIPodSource_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITIPodSource_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITIPodSource_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITIPodSource_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITIPodSource_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITIPodSource_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITIPodSource_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITIPodSource_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITIPodSource_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITIPodSource_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITIPodSource_get_Capacity(This,capacity) \ - (This)->lpVtbl -> get_Capacity(This,capacity) - -#define IITIPodSource_get_FreeSpace(This,freespace) \ - (This)->lpVtbl -> get_FreeSpace(This,freespace) - -#define IITIPodSource_get_Playlists(This,iPlaylistCollection) \ - (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) - - -#define IITIPodSource_UpdateIPod(This) \ - (This)->lpVtbl -> UpdateIPod(This) - -#define IITIPodSource_EjectIPod(This) \ - (This)->lpVtbl -> EjectIPod(This) - -#define IITIPodSource_get_SoftwareVersion(This,softwareVersion) \ - (This)->lpVtbl -> get_SoftwareVersion(This,softwareVersion) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITIPodSource_UpdateIPod_Proxy( - IITIPodSource * This); - - -void __RPC_STUB IITIPodSource_UpdateIPod_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITIPodSource_EjectIPod_Proxy( - IITIPodSource * This); - - -void __RPC_STUB IITIPodSource_EjectIPod_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITIPodSource_get_SoftwareVersion_Proxy( - IITIPodSource * This, - /* [retval][out] */ BSTR *softwareVersion); - - -void __RPC_STUB IITIPodSource_get_SoftwareVersion_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITIPodSource_INTERFACE_DEFINED__ */ - - -#ifndef __IITFileOrCDTrack_INTERFACE_DEFINED__ -#define __IITFileOrCDTrack_INTERFACE_DEFINED__ - -/* interface IITFileOrCDTrack */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITFileOrCDTrack; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("00D7FE99-7868-4cc7-AD9E-ACFD70D09566") - IITFileOrCDTrack : public IITTrack - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Location( - /* [retval][out] */ BSTR *location) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdateInfoFromFile( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Podcast( - /* [retval][out] */ VARIANT_BOOL *isPodcast) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdatePodcastFeed( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RememberBookmark( - /* [retval][out] */ VARIANT_BOOL *rememberBookmark) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_RememberBookmark( - /* [in] */ VARIANT_BOOL shouldRememberBookmark) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ExcludeFromShuffle( - /* [retval][out] */ VARIANT_BOOL *excludeFromShuffle) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_ExcludeFromShuffle( - /* [in] */ VARIANT_BOOL shouldExcludeFromShuffle) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Lyrics( - /* [retval][out] */ BSTR *lyrics) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Lyrics( - /* [in] */ BSTR lyrics) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Category( - /* [retval][out] */ BSTR *category) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Category( - /* [in] */ BSTR category) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Description( - /* [retval][out] */ BSTR *description) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Description( - /* [in] */ BSTR description) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LongDescription( - /* [retval][out] */ BSTR *longDescription) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_LongDescription( - /* [in] */ BSTR longDescription) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BookmarkTime( - /* [retval][out] */ long *bookmarkTime) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_BookmarkTime( - /* [in] */ long bookmarkTime) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VideoKind( - /* [retval][out] */ ITVideoKind *videoKind) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VideoKind( - /* [in] */ ITVideoKind videoKind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SkippedCount( - /* [retval][out] */ long *skippedCount) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SkippedCount( - /* [in] */ long skippedCount) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SkippedDate( - /* [retval][out] */ DATE *skippedDate) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SkippedDate( - /* [in] */ DATE skippedDate) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PartOfGaplessAlbum( - /* [retval][out] */ VARIANT_BOOL *partOfGaplessAlbum) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PartOfGaplessAlbum( - /* [in] */ VARIANT_BOOL shouldBePartOfGaplessAlbum) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumArtist( - /* [retval][out] */ BSTR *albumArtist) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AlbumArtist( - /* [in] */ BSTR albumArtist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Show( - /* [retval][out] */ BSTR *showName) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Show( - /* [in] */ BSTR showName) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SeasonNumber( - /* [retval][out] */ long *seasonNumber) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SeasonNumber( - /* [in] */ long seasonNumber) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EpisodeID( - /* [retval][out] */ BSTR *episodeID) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EpisodeID( - /* [in] */ BSTR episodeID) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EpisodeNumber( - /* [retval][out] */ long *episodeNumber) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EpisodeNumber( - /* [in] */ long episodeNumber) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size64High( - /* [retval][out] */ long *sizeHigh) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size64Low( - /* [retval][out] */ long *sizeLow) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Unplayed( - /* [retval][out] */ VARIANT_BOOL *isUnplayed) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Unplayed( - /* [in] */ VARIANT_BOOL shouldBeUnplayed) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortAlbum( - /* [retval][out] */ BSTR *album) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortAlbum( - /* [in] */ BSTR album) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortAlbumArtist( - /* [retval][out] */ BSTR *albumArtist) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortAlbumArtist( - /* [in] */ BSTR albumArtist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortArtist( - /* [retval][out] */ BSTR *artist) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortArtist( - /* [in] */ BSTR artist) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortComposer( - /* [retval][out] */ BSTR *composer) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortComposer( - /* [in] */ BSTR composer) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortName( - /* [retval][out] */ BSTR *name) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortName( - /* [in] */ BSTR name) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortShow( - /* [retval][out] */ BSTR *showName) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortShow( - /* [in] */ BSTR showName) = 0; - - virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRating( - /* [retval][out] */ long *rating) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AlbumRating( - /* [in] */ long rating) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRatingKind( - /* [retval][out] */ ITRatingKind *ratingKind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RatingKind( - /* [retval][out] */ ITRatingKind *ratingKind) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlists( - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITFileOrCDTrackVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITFileOrCDTrack * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITFileOrCDTrack * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITFileOrCDTrack * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITFileOrCDTrack * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITFileOrCDTrack * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITFileOrCDTrack * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITFileOrCDTrack * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( - IITFileOrCDTrack * This, - /* [out] */ long *sourceID, - /* [out] */ long *playlistID, - /* [out] */ long *trackID, - /* [out] */ long *databaseID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( - IITFileOrCDTrack * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *sourceID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *playlistID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *trackID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *databaseID); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( - IITFileOrCDTrack * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( - IITFileOrCDTrack * This); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddArtworkFromFile )( - IITFileOrCDTrack * This, - /* [in] */ BSTR filePath, - /* [retval][out] */ IITArtwork **iArtwork); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITFileOrCDTrack * This, - /* [retval][out] */ ITTrackKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( - IITFileOrCDTrack * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Album )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *album); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Album )( - IITFileOrCDTrack * This, - /* [in] */ BSTR album); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *artist); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Artist )( - IITFileOrCDTrack * This, - /* [in] */ BSTR artist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BitRate )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *bitrate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BPM )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *beatsPerMinute); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BPM )( - IITFileOrCDTrack * This, - /* [in] */ long beatsPerMinute); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Comment )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *comment); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Comment )( - IITFileOrCDTrack * This, - /* [in] */ BSTR comment); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *isCompilation); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Compilation )( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldBeCompilation); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *composer); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Composer )( - IITFileOrCDTrack * This, - /* [in] */ BSTR composer); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DateAdded )( - IITFileOrCDTrack * This, - /* [retval][out] */ DATE *dateAdded); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *discCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscCount )( - IITFileOrCDTrack * This, - /* [in] */ long discCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *discNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscNumber )( - IITFileOrCDTrack * This, - /* [in] */ long discNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *duration); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Enabled )( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *isEnabled); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Enabled )( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldBeEnabled); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQ )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *eq); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQ )( - IITFileOrCDTrack * This, - /* [in] */ BSTR eq); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Finish )( - IITFileOrCDTrack * This, - /* [in] */ long finish); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Finish )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *finish); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *genre); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Genre )( - IITFileOrCDTrack * This, - /* [in] */ BSTR genre); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Grouping )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *grouping); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Grouping )( - IITFileOrCDTrack * This, - /* [in] */ BSTR grouping); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_KindAsString )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ModificationDate )( - IITFileOrCDTrack * This, - /* [retval][out] */ DATE *dateModified); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedCount )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *playedCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedCount )( - IITFileOrCDTrack * This, - /* [in] */ long playedCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedDate )( - IITFileOrCDTrack * This, - /* [retval][out] */ DATE *playedDate); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedDate )( - IITFileOrCDTrack * This, - /* [in] */ DATE playedDate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayOrderIndex )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *index); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Rating )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *rating); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Rating )( - IITFileOrCDTrack * This, - /* [in] */ long rating); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SampleRate )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *sampleRate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *size); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Start )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *start); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Start )( - IITFileOrCDTrack * This, - /* [in] */ long start); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *time); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackCount )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *trackCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackCount )( - IITFileOrCDTrack * This, - /* [in] */ long trackCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackNumber )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *trackNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackNumber )( - IITFileOrCDTrack * This, - /* [in] */ long trackNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VolumeAdjustment )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *volumeAdjustment); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VolumeAdjustment )( - IITFileOrCDTrack * This, - /* [in] */ long volumeAdjustment); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *year); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Year )( - IITFileOrCDTrack * This, - /* [in] */ long year); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artwork )( - IITFileOrCDTrack * This, - /* [retval][out] */ IITArtworkCollection **iArtworkCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Location )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *location); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdateInfoFromFile )( - IITFileOrCDTrack * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Podcast )( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *isPodcast); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdatePodcastFeed )( - IITFileOrCDTrack * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RememberBookmark )( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *rememberBookmark); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_RememberBookmark )( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldRememberBookmark); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ExcludeFromShuffle )( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *excludeFromShuffle); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ExcludeFromShuffle )( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldExcludeFromShuffle); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Lyrics )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *lyrics); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Lyrics )( - IITFileOrCDTrack * This, - /* [in] */ BSTR lyrics); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Category )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *category); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Category )( - IITFileOrCDTrack * This, - /* [in] */ BSTR category); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Description )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *description); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Description )( - IITFileOrCDTrack * This, - /* [in] */ BSTR description); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LongDescription )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *longDescription); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LongDescription )( - IITFileOrCDTrack * This, - /* [in] */ BSTR longDescription); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BookmarkTime )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *bookmarkTime); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BookmarkTime )( - IITFileOrCDTrack * This, - /* [in] */ long bookmarkTime); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VideoKind )( - IITFileOrCDTrack * This, - /* [retval][out] */ ITVideoKind *videoKind); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VideoKind )( - IITFileOrCDTrack * This, - /* [in] */ ITVideoKind videoKind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SkippedCount )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *skippedCount); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SkippedCount )( - IITFileOrCDTrack * This, - /* [in] */ long skippedCount); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SkippedDate )( - IITFileOrCDTrack * This, - /* [retval][out] */ DATE *skippedDate); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SkippedDate )( - IITFileOrCDTrack * This, - /* [in] */ DATE skippedDate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PartOfGaplessAlbum )( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *partOfGaplessAlbum); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PartOfGaplessAlbum )( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldBePartOfGaplessAlbum); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumArtist )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *albumArtist); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AlbumArtist )( - IITFileOrCDTrack * This, - /* [in] */ BSTR albumArtist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Show )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *showName); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Show )( - IITFileOrCDTrack * This, - /* [in] */ BSTR showName); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SeasonNumber )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *seasonNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SeasonNumber )( - IITFileOrCDTrack * This, - /* [in] */ long seasonNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EpisodeID )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *episodeID); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EpisodeID )( - IITFileOrCDTrack * This, - /* [in] */ BSTR episodeID); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EpisodeNumber )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *episodeNumber); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EpisodeNumber )( - IITFileOrCDTrack * This, - /* [in] */ long episodeNumber); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size64High )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *sizeHigh); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size64Low )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *sizeLow); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Unplayed )( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *isUnplayed); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Unplayed )( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldBeUnplayed); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortAlbum )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *album); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortAlbum )( - IITFileOrCDTrack * This, - /* [in] */ BSTR album); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortAlbumArtist )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *albumArtist); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortAlbumArtist )( - IITFileOrCDTrack * This, - /* [in] */ BSTR albumArtist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortArtist )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *artist); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortArtist )( - IITFileOrCDTrack * This, - /* [in] */ BSTR artist); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortComposer )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *composer); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortComposer )( - IITFileOrCDTrack * This, - /* [in] */ BSTR composer); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortName )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortName )( - IITFileOrCDTrack * This, - /* [in] */ BSTR name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortShow )( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *showName); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortShow )( - IITFileOrCDTrack * This, - /* [in] */ BSTR showName); - - /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( - IITFileOrCDTrack * This); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRating )( - IITFileOrCDTrack * This, - /* [retval][out] */ long *rating); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AlbumRating )( - IITFileOrCDTrack * This, - /* [in] */ long rating); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRatingKind )( - IITFileOrCDTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RatingKind )( - IITFileOrCDTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( - IITFileOrCDTrack * This, - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); - - END_INTERFACE - } IITFileOrCDTrackVtbl; - - interface IITFileOrCDTrack - { - CONST_VTBL struct IITFileOrCDTrackVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITFileOrCDTrack_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITFileOrCDTrack_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITFileOrCDTrack_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITFileOrCDTrack_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITFileOrCDTrack_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITFileOrCDTrack_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITFileOrCDTrack_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITFileOrCDTrack_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ - (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) - -#define IITFileOrCDTrack_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITFileOrCDTrack_put_Name(This,name) \ - (This)->lpVtbl -> put_Name(This,name) - -#define IITFileOrCDTrack_get_Index(This,index) \ - (This)->lpVtbl -> get_Index(This,index) - -#define IITFileOrCDTrack_get_SourceID(This,sourceID) \ - (This)->lpVtbl -> get_SourceID(This,sourceID) - -#define IITFileOrCDTrack_get_PlaylistID(This,playlistID) \ - (This)->lpVtbl -> get_PlaylistID(This,playlistID) - -#define IITFileOrCDTrack_get_TrackID(This,trackID) \ - (This)->lpVtbl -> get_TrackID(This,trackID) - -#define IITFileOrCDTrack_get_TrackDatabaseID(This,databaseID) \ - (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) - - -#define IITFileOrCDTrack_Delete(This) \ - (This)->lpVtbl -> Delete(This) - -#define IITFileOrCDTrack_Play(This) \ - (This)->lpVtbl -> Play(This) - -#define IITFileOrCDTrack_AddArtworkFromFile(This,filePath,iArtwork) \ - (This)->lpVtbl -> AddArtworkFromFile(This,filePath,iArtwork) - -#define IITFileOrCDTrack_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITFileOrCDTrack_get_Playlist(This,iPlaylist) \ - (This)->lpVtbl -> get_Playlist(This,iPlaylist) - -#define IITFileOrCDTrack_get_Album(This,album) \ - (This)->lpVtbl -> get_Album(This,album) - -#define IITFileOrCDTrack_put_Album(This,album) \ - (This)->lpVtbl -> put_Album(This,album) - -#define IITFileOrCDTrack_get_Artist(This,artist) \ - (This)->lpVtbl -> get_Artist(This,artist) - -#define IITFileOrCDTrack_put_Artist(This,artist) \ - (This)->lpVtbl -> put_Artist(This,artist) - -#define IITFileOrCDTrack_get_BitRate(This,bitrate) \ - (This)->lpVtbl -> get_BitRate(This,bitrate) - -#define IITFileOrCDTrack_get_BPM(This,beatsPerMinute) \ - (This)->lpVtbl -> get_BPM(This,beatsPerMinute) - -#define IITFileOrCDTrack_put_BPM(This,beatsPerMinute) \ - (This)->lpVtbl -> put_BPM(This,beatsPerMinute) - -#define IITFileOrCDTrack_get_Comment(This,comment) \ - (This)->lpVtbl -> get_Comment(This,comment) - -#define IITFileOrCDTrack_put_Comment(This,comment) \ - (This)->lpVtbl -> put_Comment(This,comment) - -#define IITFileOrCDTrack_get_Compilation(This,isCompilation) \ - (This)->lpVtbl -> get_Compilation(This,isCompilation) - -#define IITFileOrCDTrack_put_Compilation(This,shouldBeCompilation) \ - (This)->lpVtbl -> put_Compilation(This,shouldBeCompilation) - -#define IITFileOrCDTrack_get_Composer(This,composer) \ - (This)->lpVtbl -> get_Composer(This,composer) - -#define IITFileOrCDTrack_put_Composer(This,composer) \ - (This)->lpVtbl -> put_Composer(This,composer) - -#define IITFileOrCDTrack_get_DateAdded(This,dateAdded) \ - (This)->lpVtbl -> get_DateAdded(This,dateAdded) - -#define IITFileOrCDTrack_get_DiscCount(This,discCount) \ - (This)->lpVtbl -> get_DiscCount(This,discCount) - -#define IITFileOrCDTrack_put_DiscCount(This,discCount) \ - (This)->lpVtbl -> put_DiscCount(This,discCount) - -#define IITFileOrCDTrack_get_DiscNumber(This,discNumber) \ - (This)->lpVtbl -> get_DiscNumber(This,discNumber) - -#define IITFileOrCDTrack_put_DiscNumber(This,discNumber) \ - (This)->lpVtbl -> put_DiscNumber(This,discNumber) - -#define IITFileOrCDTrack_get_Duration(This,duration) \ - (This)->lpVtbl -> get_Duration(This,duration) - -#define IITFileOrCDTrack_get_Enabled(This,isEnabled) \ - (This)->lpVtbl -> get_Enabled(This,isEnabled) - -#define IITFileOrCDTrack_put_Enabled(This,shouldBeEnabled) \ - (This)->lpVtbl -> put_Enabled(This,shouldBeEnabled) - -#define IITFileOrCDTrack_get_EQ(This,eq) \ - (This)->lpVtbl -> get_EQ(This,eq) - -#define IITFileOrCDTrack_put_EQ(This,eq) \ - (This)->lpVtbl -> put_EQ(This,eq) - -#define IITFileOrCDTrack_put_Finish(This,finish) \ - (This)->lpVtbl -> put_Finish(This,finish) - -#define IITFileOrCDTrack_get_Finish(This,finish) \ - (This)->lpVtbl -> get_Finish(This,finish) - -#define IITFileOrCDTrack_get_Genre(This,genre) \ - (This)->lpVtbl -> get_Genre(This,genre) - -#define IITFileOrCDTrack_put_Genre(This,genre) \ - (This)->lpVtbl -> put_Genre(This,genre) - -#define IITFileOrCDTrack_get_Grouping(This,grouping) \ - (This)->lpVtbl -> get_Grouping(This,grouping) - -#define IITFileOrCDTrack_put_Grouping(This,grouping) \ - (This)->lpVtbl -> put_Grouping(This,grouping) - -#define IITFileOrCDTrack_get_KindAsString(This,kind) \ - (This)->lpVtbl -> get_KindAsString(This,kind) - -#define IITFileOrCDTrack_get_ModificationDate(This,dateModified) \ - (This)->lpVtbl -> get_ModificationDate(This,dateModified) - -#define IITFileOrCDTrack_get_PlayedCount(This,playedCount) \ - (This)->lpVtbl -> get_PlayedCount(This,playedCount) - -#define IITFileOrCDTrack_put_PlayedCount(This,playedCount) \ - (This)->lpVtbl -> put_PlayedCount(This,playedCount) - -#define IITFileOrCDTrack_get_PlayedDate(This,playedDate) \ - (This)->lpVtbl -> get_PlayedDate(This,playedDate) - -#define IITFileOrCDTrack_put_PlayedDate(This,playedDate) \ - (This)->lpVtbl -> put_PlayedDate(This,playedDate) - -#define IITFileOrCDTrack_get_PlayOrderIndex(This,index) \ - (This)->lpVtbl -> get_PlayOrderIndex(This,index) - -#define IITFileOrCDTrack_get_Rating(This,rating) \ - (This)->lpVtbl -> get_Rating(This,rating) - -#define IITFileOrCDTrack_put_Rating(This,rating) \ - (This)->lpVtbl -> put_Rating(This,rating) - -#define IITFileOrCDTrack_get_SampleRate(This,sampleRate) \ - (This)->lpVtbl -> get_SampleRate(This,sampleRate) - -#define IITFileOrCDTrack_get_Size(This,size) \ - (This)->lpVtbl -> get_Size(This,size) - -#define IITFileOrCDTrack_get_Start(This,start) \ - (This)->lpVtbl -> get_Start(This,start) - -#define IITFileOrCDTrack_put_Start(This,start) \ - (This)->lpVtbl -> put_Start(This,start) - -#define IITFileOrCDTrack_get_Time(This,time) \ - (This)->lpVtbl -> get_Time(This,time) - -#define IITFileOrCDTrack_get_TrackCount(This,trackCount) \ - (This)->lpVtbl -> get_TrackCount(This,trackCount) - -#define IITFileOrCDTrack_put_TrackCount(This,trackCount) \ - (This)->lpVtbl -> put_TrackCount(This,trackCount) - -#define IITFileOrCDTrack_get_TrackNumber(This,trackNumber) \ - (This)->lpVtbl -> get_TrackNumber(This,trackNumber) - -#define IITFileOrCDTrack_put_TrackNumber(This,trackNumber) \ - (This)->lpVtbl -> put_TrackNumber(This,trackNumber) - -#define IITFileOrCDTrack_get_VolumeAdjustment(This,volumeAdjustment) \ - (This)->lpVtbl -> get_VolumeAdjustment(This,volumeAdjustment) - -#define IITFileOrCDTrack_put_VolumeAdjustment(This,volumeAdjustment) \ - (This)->lpVtbl -> put_VolumeAdjustment(This,volumeAdjustment) - -#define IITFileOrCDTrack_get_Year(This,year) \ - (This)->lpVtbl -> get_Year(This,year) - -#define IITFileOrCDTrack_put_Year(This,year) \ - (This)->lpVtbl -> put_Year(This,year) - -#define IITFileOrCDTrack_get_Artwork(This,iArtworkCollection) \ - (This)->lpVtbl -> get_Artwork(This,iArtworkCollection) - - -#define IITFileOrCDTrack_get_Location(This,location) \ - (This)->lpVtbl -> get_Location(This,location) - -#define IITFileOrCDTrack_UpdateInfoFromFile(This) \ - (This)->lpVtbl -> UpdateInfoFromFile(This) - -#define IITFileOrCDTrack_get_Podcast(This,isPodcast) \ - (This)->lpVtbl -> get_Podcast(This,isPodcast) - -#define IITFileOrCDTrack_UpdatePodcastFeed(This) \ - (This)->lpVtbl -> UpdatePodcastFeed(This) - -#define IITFileOrCDTrack_get_RememberBookmark(This,rememberBookmark) \ - (This)->lpVtbl -> get_RememberBookmark(This,rememberBookmark) - -#define IITFileOrCDTrack_put_RememberBookmark(This,shouldRememberBookmark) \ - (This)->lpVtbl -> put_RememberBookmark(This,shouldRememberBookmark) - -#define IITFileOrCDTrack_get_ExcludeFromShuffle(This,excludeFromShuffle) \ - (This)->lpVtbl -> get_ExcludeFromShuffle(This,excludeFromShuffle) - -#define IITFileOrCDTrack_put_ExcludeFromShuffle(This,shouldExcludeFromShuffle) \ - (This)->lpVtbl -> put_ExcludeFromShuffle(This,shouldExcludeFromShuffle) - -#define IITFileOrCDTrack_get_Lyrics(This,lyrics) \ - (This)->lpVtbl -> get_Lyrics(This,lyrics) - -#define IITFileOrCDTrack_put_Lyrics(This,lyrics) \ - (This)->lpVtbl -> put_Lyrics(This,lyrics) - -#define IITFileOrCDTrack_get_Category(This,category) \ - (This)->lpVtbl -> get_Category(This,category) - -#define IITFileOrCDTrack_put_Category(This,category) \ - (This)->lpVtbl -> put_Category(This,category) - -#define IITFileOrCDTrack_get_Description(This,description) \ - (This)->lpVtbl -> get_Description(This,description) - -#define IITFileOrCDTrack_put_Description(This,description) \ - (This)->lpVtbl -> put_Description(This,description) - -#define IITFileOrCDTrack_get_LongDescription(This,longDescription) \ - (This)->lpVtbl -> get_LongDescription(This,longDescription) - -#define IITFileOrCDTrack_put_LongDescription(This,longDescription) \ - (This)->lpVtbl -> put_LongDescription(This,longDescription) - -#define IITFileOrCDTrack_get_BookmarkTime(This,bookmarkTime) \ - (This)->lpVtbl -> get_BookmarkTime(This,bookmarkTime) - -#define IITFileOrCDTrack_put_BookmarkTime(This,bookmarkTime) \ - (This)->lpVtbl -> put_BookmarkTime(This,bookmarkTime) - -#define IITFileOrCDTrack_get_VideoKind(This,videoKind) \ - (This)->lpVtbl -> get_VideoKind(This,videoKind) - -#define IITFileOrCDTrack_put_VideoKind(This,videoKind) \ - (This)->lpVtbl -> put_VideoKind(This,videoKind) - -#define IITFileOrCDTrack_get_SkippedCount(This,skippedCount) \ - (This)->lpVtbl -> get_SkippedCount(This,skippedCount) - -#define IITFileOrCDTrack_put_SkippedCount(This,skippedCount) \ - (This)->lpVtbl -> put_SkippedCount(This,skippedCount) - -#define IITFileOrCDTrack_get_SkippedDate(This,skippedDate) \ - (This)->lpVtbl -> get_SkippedDate(This,skippedDate) - -#define IITFileOrCDTrack_put_SkippedDate(This,skippedDate) \ - (This)->lpVtbl -> put_SkippedDate(This,skippedDate) - -#define IITFileOrCDTrack_get_PartOfGaplessAlbum(This,partOfGaplessAlbum) \ - (This)->lpVtbl -> get_PartOfGaplessAlbum(This,partOfGaplessAlbum) - -#define IITFileOrCDTrack_put_PartOfGaplessAlbum(This,shouldBePartOfGaplessAlbum) \ - (This)->lpVtbl -> put_PartOfGaplessAlbum(This,shouldBePartOfGaplessAlbum) - -#define IITFileOrCDTrack_get_AlbumArtist(This,albumArtist) \ - (This)->lpVtbl -> get_AlbumArtist(This,albumArtist) - -#define IITFileOrCDTrack_put_AlbumArtist(This,albumArtist) \ - (This)->lpVtbl -> put_AlbumArtist(This,albumArtist) - -#define IITFileOrCDTrack_get_Show(This,showName) \ - (This)->lpVtbl -> get_Show(This,showName) - -#define IITFileOrCDTrack_put_Show(This,showName) \ - (This)->lpVtbl -> put_Show(This,showName) - -#define IITFileOrCDTrack_get_SeasonNumber(This,seasonNumber) \ - (This)->lpVtbl -> get_SeasonNumber(This,seasonNumber) - -#define IITFileOrCDTrack_put_SeasonNumber(This,seasonNumber) \ - (This)->lpVtbl -> put_SeasonNumber(This,seasonNumber) - -#define IITFileOrCDTrack_get_EpisodeID(This,episodeID) \ - (This)->lpVtbl -> get_EpisodeID(This,episodeID) - -#define IITFileOrCDTrack_put_EpisodeID(This,episodeID) \ - (This)->lpVtbl -> put_EpisodeID(This,episodeID) - -#define IITFileOrCDTrack_get_EpisodeNumber(This,episodeNumber) \ - (This)->lpVtbl -> get_EpisodeNumber(This,episodeNumber) - -#define IITFileOrCDTrack_put_EpisodeNumber(This,episodeNumber) \ - (This)->lpVtbl -> put_EpisodeNumber(This,episodeNumber) - -#define IITFileOrCDTrack_get_Size64High(This,sizeHigh) \ - (This)->lpVtbl -> get_Size64High(This,sizeHigh) - -#define IITFileOrCDTrack_get_Size64Low(This,sizeLow) \ - (This)->lpVtbl -> get_Size64Low(This,sizeLow) - -#define IITFileOrCDTrack_get_Unplayed(This,isUnplayed) \ - (This)->lpVtbl -> get_Unplayed(This,isUnplayed) - -#define IITFileOrCDTrack_put_Unplayed(This,shouldBeUnplayed) \ - (This)->lpVtbl -> put_Unplayed(This,shouldBeUnplayed) - -#define IITFileOrCDTrack_get_SortAlbum(This,album) \ - (This)->lpVtbl -> get_SortAlbum(This,album) - -#define IITFileOrCDTrack_put_SortAlbum(This,album) \ - (This)->lpVtbl -> put_SortAlbum(This,album) - -#define IITFileOrCDTrack_get_SortAlbumArtist(This,albumArtist) \ - (This)->lpVtbl -> get_SortAlbumArtist(This,albumArtist) - -#define IITFileOrCDTrack_put_SortAlbumArtist(This,albumArtist) \ - (This)->lpVtbl -> put_SortAlbumArtist(This,albumArtist) - -#define IITFileOrCDTrack_get_SortArtist(This,artist) \ - (This)->lpVtbl -> get_SortArtist(This,artist) - -#define IITFileOrCDTrack_put_SortArtist(This,artist) \ - (This)->lpVtbl -> put_SortArtist(This,artist) - -#define IITFileOrCDTrack_get_SortComposer(This,composer) \ - (This)->lpVtbl -> get_SortComposer(This,composer) - -#define IITFileOrCDTrack_put_SortComposer(This,composer) \ - (This)->lpVtbl -> put_SortComposer(This,composer) - -#define IITFileOrCDTrack_get_SortName(This,name) \ - (This)->lpVtbl -> get_SortName(This,name) - -#define IITFileOrCDTrack_put_SortName(This,name) \ - (This)->lpVtbl -> put_SortName(This,name) - -#define IITFileOrCDTrack_get_SortShow(This,showName) \ - (This)->lpVtbl -> get_SortShow(This,showName) - -#define IITFileOrCDTrack_put_SortShow(This,showName) \ - (This)->lpVtbl -> put_SortShow(This,showName) - -#define IITFileOrCDTrack_Reveal(This) \ - (This)->lpVtbl -> Reveal(This) - -#define IITFileOrCDTrack_get_AlbumRating(This,rating) \ - (This)->lpVtbl -> get_AlbumRating(This,rating) - -#define IITFileOrCDTrack_put_AlbumRating(This,rating) \ - (This)->lpVtbl -> put_AlbumRating(This,rating) - -#define IITFileOrCDTrack_get_AlbumRatingKind(This,ratingKind) \ - (This)->lpVtbl -> get_AlbumRatingKind(This,ratingKind) - -#define IITFileOrCDTrack_get_RatingKind(This,ratingKind) \ - (This)->lpVtbl -> get_RatingKind(This,ratingKind) - -#define IITFileOrCDTrack_get_Playlists(This,iPlaylistCollection) \ - (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Location_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *location); - - -void __RPC_STUB IITFileOrCDTrack_get_Location_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_UpdateInfoFromFile_Proxy( - IITFileOrCDTrack * This); - - -void __RPC_STUB IITFileOrCDTrack_UpdateInfoFromFile_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Podcast_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *isPodcast); - - -void __RPC_STUB IITFileOrCDTrack_get_Podcast_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_UpdatePodcastFeed_Proxy( - IITFileOrCDTrack * This); - - -void __RPC_STUB IITFileOrCDTrack_UpdatePodcastFeed_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_RememberBookmark_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *rememberBookmark); - - -void __RPC_STUB IITFileOrCDTrack_get_RememberBookmark_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_RememberBookmark_Proxy( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldRememberBookmark); - - -void __RPC_STUB IITFileOrCDTrack_put_RememberBookmark_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_ExcludeFromShuffle_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *excludeFromShuffle); - - -void __RPC_STUB IITFileOrCDTrack_get_ExcludeFromShuffle_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_ExcludeFromShuffle_Proxy( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldExcludeFromShuffle); - - -void __RPC_STUB IITFileOrCDTrack_put_ExcludeFromShuffle_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Lyrics_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *lyrics); - - -void __RPC_STUB IITFileOrCDTrack_get_Lyrics_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Lyrics_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR lyrics); - - -void __RPC_STUB IITFileOrCDTrack_put_Lyrics_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Category_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *category); - - -void __RPC_STUB IITFileOrCDTrack_get_Category_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Category_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR category); - - -void __RPC_STUB IITFileOrCDTrack_put_Category_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Description_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *description); - - -void __RPC_STUB IITFileOrCDTrack_get_Description_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Description_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR description); - - -void __RPC_STUB IITFileOrCDTrack_put_Description_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_LongDescription_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *longDescription); - - -void __RPC_STUB IITFileOrCDTrack_get_LongDescription_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_LongDescription_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR longDescription); - - -void __RPC_STUB IITFileOrCDTrack_put_LongDescription_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_BookmarkTime_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ long *bookmarkTime); - - -void __RPC_STUB IITFileOrCDTrack_get_BookmarkTime_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_BookmarkTime_Proxy( - IITFileOrCDTrack * This, - /* [in] */ long bookmarkTime); - - -void __RPC_STUB IITFileOrCDTrack_put_BookmarkTime_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_VideoKind_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ ITVideoKind *videoKind); - - -void __RPC_STUB IITFileOrCDTrack_get_VideoKind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_VideoKind_Proxy( - IITFileOrCDTrack * This, - /* [in] */ ITVideoKind videoKind); - - -void __RPC_STUB IITFileOrCDTrack_put_VideoKind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SkippedCount_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ long *skippedCount); - - -void __RPC_STUB IITFileOrCDTrack_get_SkippedCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SkippedCount_Proxy( - IITFileOrCDTrack * This, - /* [in] */ long skippedCount); - - -void __RPC_STUB IITFileOrCDTrack_put_SkippedCount_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SkippedDate_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ DATE *skippedDate); - - -void __RPC_STUB IITFileOrCDTrack_get_SkippedDate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SkippedDate_Proxy( - IITFileOrCDTrack * This, - /* [in] */ DATE skippedDate); - - -void __RPC_STUB IITFileOrCDTrack_put_SkippedDate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_PartOfGaplessAlbum_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *partOfGaplessAlbum); - - -void __RPC_STUB IITFileOrCDTrack_get_PartOfGaplessAlbum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_PartOfGaplessAlbum_Proxy( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldBePartOfGaplessAlbum); - - -void __RPC_STUB IITFileOrCDTrack_put_PartOfGaplessAlbum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_AlbumArtist_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *albumArtist); - - -void __RPC_STUB IITFileOrCDTrack_get_AlbumArtist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_AlbumArtist_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR albumArtist); - - -void __RPC_STUB IITFileOrCDTrack_put_AlbumArtist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Show_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *showName); - - -void __RPC_STUB IITFileOrCDTrack_get_Show_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Show_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR showName); - - -void __RPC_STUB IITFileOrCDTrack_put_Show_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SeasonNumber_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ long *seasonNumber); - - -void __RPC_STUB IITFileOrCDTrack_get_SeasonNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SeasonNumber_Proxy( - IITFileOrCDTrack * This, - /* [in] */ long seasonNumber); - - -void __RPC_STUB IITFileOrCDTrack_put_SeasonNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_EpisodeID_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *episodeID); - - -void __RPC_STUB IITFileOrCDTrack_get_EpisodeID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_EpisodeID_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR episodeID); - - -void __RPC_STUB IITFileOrCDTrack_put_EpisodeID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_EpisodeNumber_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ long *episodeNumber); - - -void __RPC_STUB IITFileOrCDTrack_get_EpisodeNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_EpisodeNumber_Proxy( - IITFileOrCDTrack * This, - /* [in] */ long episodeNumber); - - -void __RPC_STUB IITFileOrCDTrack_put_EpisodeNumber_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Size64High_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ long *sizeHigh); - - -void __RPC_STUB IITFileOrCDTrack_get_Size64High_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Size64Low_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ long *sizeLow); - - -void __RPC_STUB IITFileOrCDTrack_get_Size64Low_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Unplayed_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ VARIANT_BOOL *isUnplayed); - - -void __RPC_STUB IITFileOrCDTrack_get_Unplayed_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Unplayed_Proxy( - IITFileOrCDTrack * This, - /* [in] */ VARIANT_BOOL shouldBeUnplayed); - - -void __RPC_STUB IITFileOrCDTrack_put_Unplayed_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortAlbum_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *album); - - -void __RPC_STUB IITFileOrCDTrack_get_SortAlbum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortAlbum_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR album); - - -void __RPC_STUB IITFileOrCDTrack_put_SortAlbum_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortAlbumArtist_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *albumArtist); - - -void __RPC_STUB IITFileOrCDTrack_get_SortAlbumArtist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortAlbumArtist_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR albumArtist); - - -void __RPC_STUB IITFileOrCDTrack_put_SortAlbumArtist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortArtist_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *artist); - - -void __RPC_STUB IITFileOrCDTrack_get_SortArtist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortArtist_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR artist); - - -void __RPC_STUB IITFileOrCDTrack_put_SortArtist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortComposer_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *composer); - - -void __RPC_STUB IITFileOrCDTrack_get_SortComposer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortComposer_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR composer); - - -void __RPC_STUB IITFileOrCDTrack_put_SortComposer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortName_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *name); - - -void __RPC_STUB IITFileOrCDTrack_get_SortName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortName_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR name); - - -void __RPC_STUB IITFileOrCDTrack_put_SortName_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortShow_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ BSTR *showName); - - -void __RPC_STUB IITFileOrCDTrack_get_SortShow_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortShow_Proxy( - IITFileOrCDTrack * This, - /* [in] */ BSTR showName); - - -void __RPC_STUB IITFileOrCDTrack_put_SortShow_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_Reveal_Proxy( - IITFileOrCDTrack * This); - - -void __RPC_STUB IITFileOrCDTrack_Reveal_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_AlbumRating_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ long *rating); - - -void __RPC_STUB IITFileOrCDTrack_get_AlbumRating_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_AlbumRating_Proxy( - IITFileOrCDTrack * This, - /* [in] */ long rating); - - -void __RPC_STUB IITFileOrCDTrack_put_AlbumRating_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_AlbumRatingKind_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - -void __RPC_STUB IITFileOrCDTrack_get_AlbumRatingKind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_RatingKind_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ ITRatingKind *ratingKind); - - -void __RPC_STUB IITFileOrCDTrack_get_RatingKind_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Playlists_Proxy( - IITFileOrCDTrack * This, - /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); - - -void __RPC_STUB IITFileOrCDTrack_get_Playlists_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITFileOrCDTrack_INTERFACE_DEFINED__ */ - - -#ifndef __IITPlaylistWindow_INTERFACE_DEFINED__ -#define __IITPlaylistWindow_INTERFACE_DEFINED__ - -/* interface IITPlaylistWindow */ -/* [hidden][unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IITPlaylistWindow; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("349CBB45-2E5A-4822-8E4A-A75555A186F7") - IITPlaylistWindow : public IITWindow - { - public: - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedTracks( - /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlist( - /* [retval][out] */ IITPlaylist **iPlaylist) = 0; - - }; - -#else /* C style interface */ - - typedef struct IITPlaylistWindowVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IITPlaylistWindow * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IITPlaylistWindow * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IITPlaylistWindow * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IITPlaylistWindow * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IITPlaylistWindow * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IITPlaylistWindow * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IITPlaylistWindow * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( - IITPlaylistWindow * This, - /* [retval][out] */ BSTR *name); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( - IITPlaylistWindow * This, - /* [retval][out] */ ITWindowKind *kind); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( - IITPlaylistWindow * This, - /* [retval][out] */ VARIANT_BOOL *isVisible); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Visible )( - IITPlaylistWindow * This, - /* [in] */ VARIANT_BOOL shouldBeVisible); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Resizable )( - IITPlaylistWindow * This, - /* [retval][out] */ VARIANT_BOOL *isResizable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Minimized )( - IITPlaylistWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMinimized); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Minimized )( - IITPlaylistWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMinimized); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximizable )( - IITPlaylistWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximizable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximized )( - IITPlaylistWindow * This, - /* [retval][out] */ VARIANT_BOOL *isMaximized); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Maximized )( - IITPlaylistWindow * This, - /* [in] */ VARIANT_BOOL shouldBeMaximized); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomable )( - IITPlaylistWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomable); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomed )( - IITPlaylistWindow * This, - /* [retval][out] */ VARIANT_BOOL *isZoomed); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Zoomed )( - IITPlaylistWindow * This, - /* [in] */ VARIANT_BOOL shouldBeZoomed); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )( - IITPlaylistWindow * This, - /* [retval][out] */ long *top); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Top )( - IITPlaylistWindow * This, - /* [in] */ long top); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )( - IITPlaylistWindow * This, - /* [retval][out] */ long *left); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Left )( - IITPlaylistWindow * This, - /* [in] */ long left); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bottom )( - IITPlaylistWindow * This, - /* [retval][out] */ long *bottom); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bottom )( - IITPlaylistWindow * This, - /* [in] */ long bottom); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Right )( - IITPlaylistWindow * This, - /* [retval][out] */ long *right); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Right )( - IITPlaylistWindow * This, - /* [in] */ long right); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )( - IITPlaylistWindow * This, - /* [retval][out] */ long *width); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Width )( - IITPlaylistWindow * This, - /* [in] */ long width); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )( - IITPlaylistWindow * This, - /* [retval][out] */ long *height); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Height )( - IITPlaylistWindow * This, - /* [in] */ long height); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedTracks )( - IITPlaylistWindow * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( - IITPlaylistWindow * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - END_INTERFACE - } IITPlaylistWindowVtbl; - - interface IITPlaylistWindow - { - CONST_VTBL struct IITPlaylistWindowVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IITPlaylistWindow_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IITPlaylistWindow_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IITPlaylistWindow_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IITPlaylistWindow_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IITPlaylistWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IITPlaylistWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IITPlaylistWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IITPlaylistWindow_get_Name(This,name) \ - (This)->lpVtbl -> get_Name(This,name) - -#define IITPlaylistWindow_get_Kind(This,kind) \ - (This)->lpVtbl -> get_Kind(This,kind) - -#define IITPlaylistWindow_get_Visible(This,isVisible) \ - (This)->lpVtbl -> get_Visible(This,isVisible) - -#define IITPlaylistWindow_put_Visible(This,shouldBeVisible) \ - (This)->lpVtbl -> put_Visible(This,shouldBeVisible) - -#define IITPlaylistWindow_get_Resizable(This,isResizable) \ - (This)->lpVtbl -> get_Resizable(This,isResizable) - -#define IITPlaylistWindow_get_Minimized(This,isMinimized) \ - (This)->lpVtbl -> get_Minimized(This,isMinimized) - -#define IITPlaylistWindow_put_Minimized(This,shouldBeMinimized) \ - (This)->lpVtbl -> put_Minimized(This,shouldBeMinimized) - -#define IITPlaylistWindow_get_Maximizable(This,isMaximizable) \ - (This)->lpVtbl -> get_Maximizable(This,isMaximizable) - -#define IITPlaylistWindow_get_Maximized(This,isMaximized) \ - (This)->lpVtbl -> get_Maximized(This,isMaximized) - -#define IITPlaylistWindow_put_Maximized(This,shouldBeMaximized) \ - (This)->lpVtbl -> put_Maximized(This,shouldBeMaximized) - -#define IITPlaylistWindow_get_Zoomable(This,isZoomable) \ - (This)->lpVtbl -> get_Zoomable(This,isZoomable) - -#define IITPlaylistWindow_get_Zoomed(This,isZoomed) \ - (This)->lpVtbl -> get_Zoomed(This,isZoomed) - -#define IITPlaylistWindow_put_Zoomed(This,shouldBeZoomed) \ - (This)->lpVtbl -> put_Zoomed(This,shouldBeZoomed) - -#define IITPlaylistWindow_get_Top(This,top) \ - (This)->lpVtbl -> get_Top(This,top) - -#define IITPlaylistWindow_put_Top(This,top) \ - (This)->lpVtbl -> put_Top(This,top) - -#define IITPlaylistWindow_get_Left(This,left) \ - (This)->lpVtbl -> get_Left(This,left) - -#define IITPlaylistWindow_put_Left(This,left) \ - (This)->lpVtbl -> put_Left(This,left) - -#define IITPlaylistWindow_get_Bottom(This,bottom) \ - (This)->lpVtbl -> get_Bottom(This,bottom) - -#define IITPlaylistWindow_put_Bottom(This,bottom) \ - (This)->lpVtbl -> put_Bottom(This,bottom) - -#define IITPlaylistWindow_get_Right(This,right) \ - (This)->lpVtbl -> get_Right(This,right) - -#define IITPlaylistWindow_put_Right(This,right) \ - (This)->lpVtbl -> put_Right(This,right) - -#define IITPlaylistWindow_get_Width(This,width) \ - (This)->lpVtbl -> get_Width(This,width) - -#define IITPlaylistWindow_put_Width(This,width) \ - (This)->lpVtbl -> put_Width(This,width) - -#define IITPlaylistWindow_get_Height(This,height) \ - (This)->lpVtbl -> get_Height(This,height) - -#define IITPlaylistWindow_put_Height(This,height) \ - (This)->lpVtbl -> put_Height(This,height) - - -#define IITPlaylistWindow_get_SelectedTracks(This,iTrackCollection) \ - (This)->lpVtbl -> get_SelectedTracks(This,iTrackCollection) - -#define IITPlaylistWindow_get_Playlist(This,iPlaylist) \ - (This)->lpVtbl -> get_Playlist(This,iPlaylist) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistWindow_get_SelectedTracks_Proxy( - IITPlaylistWindow * This, - /* [retval][out] */ IITTrackCollection **iTrackCollection); - - -void __RPC_STUB IITPlaylistWindow_get_SelectedTracks_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistWindow_get_Playlist_Proxy( - IITPlaylistWindow * This, - /* [retval][out] */ IITPlaylist **iPlaylist); - - -void __RPC_STUB IITPlaylistWindow_get_Playlist_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IITPlaylistWindow_INTERFACE_DEFINED__ */ - -#endif /* __iTunesLib_LIBRARY_DEFINED__ */ - -/* Additional Prototypes for ALL interfaces */ - -/* end of Additional Prototypes */ - -#ifdef __cplusplus -} -#endif - -#endif - - + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 6.00.0366 */ +/* at Wed Jun 25 17:02:20 2008 + */ +/* Compiler settings for iTunesCOMInterface.idl: + Oicf, W1, Zp8, env=Win32 (32b run) + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +//@@MIDL_FILE_HEADING( ) + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the <rpcndr.h> version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of <rpcndr.h> +#endif // __RPCNDR_H_VERSION__ + + +#ifndef __iTunesCOMInterface_h__ +#define __iTunesCOMInterface_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __IITObject_FWD_DEFINED__ +#define __IITObject_FWD_DEFINED__ +typedef interface IITObject IITObject; +#endif /* __IITObject_FWD_DEFINED__ */ + + +#ifndef __IITSource_FWD_DEFINED__ +#define __IITSource_FWD_DEFINED__ +typedef interface IITSource IITSource; +#endif /* __IITSource_FWD_DEFINED__ */ + + +#ifndef __IITSourceCollection_FWD_DEFINED__ +#define __IITSourceCollection_FWD_DEFINED__ +typedef interface IITSourceCollection IITSourceCollection; +#endif /* __IITSourceCollection_FWD_DEFINED__ */ + + +#ifndef __IITEncoder_FWD_DEFINED__ +#define __IITEncoder_FWD_DEFINED__ +typedef interface IITEncoder IITEncoder; +#endif /* __IITEncoder_FWD_DEFINED__ */ + + +#ifndef __IITEncoderCollection_FWD_DEFINED__ +#define __IITEncoderCollection_FWD_DEFINED__ +typedef interface IITEncoderCollection IITEncoderCollection; +#endif /* __IITEncoderCollection_FWD_DEFINED__ */ + + +#ifndef __IITEQPreset_FWD_DEFINED__ +#define __IITEQPreset_FWD_DEFINED__ +typedef interface IITEQPreset IITEQPreset; +#endif /* __IITEQPreset_FWD_DEFINED__ */ + + +#ifndef __IITEQPresetCollection_FWD_DEFINED__ +#define __IITEQPresetCollection_FWD_DEFINED__ +typedef interface IITEQPresetCollection IITEQPresetCollection; +#endif /* __IITEQPresetCollection_FWD_DEFINED__ */ + + +#ifndef __IITPlaylist_FWD_DEFINED__ +#define __IITPlaylist_FWD_DEFINED__ +typedef interface IITPlaylist IITPlaylist; +#endif /* __IITPlaylist_FWD_DEFINED__ */ + + +#ifndef __IITOperationStatus_FWD_DEFINED__ +#define __IITOperationStatus_FWD_DEFINED__ +typedef interface IITOperationStatus IITOperationStatus; +#endif /* __IITOperationStatus_FWD_DEFINED__ */ + + +#ifndef __IITConvertOperationStatus_FWD_DEFINED__ +#define __IITConvertOperationStatus_FWD_DEFINED__ +typedef interface IITConvertOperationStatus IITConvertOperationStatus; +#endif /* __IITConvertOperationStatus_FWD_DEFINED__ */ + + +#ifndef __IITLibraryPlaylist_FWD_DEFINED__ +#define __IITLibraryPlaylist_FWD_DEFINED__ +typedef interface IITLibraryPlaylist IITLibraryPlaylist; +#endif /* __IITLibraryPlaylist_FWD_DEFINED__ */ + + +#ifndef __IITUserPlaylist_FWD_DEFINED__ +#define __IITUserPlaylist_FWD_DEFINED__ +typedef interface IITUserPlaylist IITUserPlaylist; +#endif /* __IITUserPlaylist_FWD_DEFINED__ */ + + +#ifndef __IITTrack_FWD_DEFINED__ +#define __IITTrack_FWD_DEFINED__ +typedef interface IITTrack IITTrack; +#endif /* __IITTrack_FWD_DEFINED__ */ + + +#ifndef __IITTrackCollection_FWD_DEFINED__ +#define __IITTrackCollection_FWD_DEFINED__ +typedef interface IITTrackCollection IITTrackCollection; +#endif /* __IITTrackCollection_FWD_DEFINED__ */ + + +#ifndef __IITVisual_FWD_DEFINED__ +#define __IITVisual_FWD_DEFINED__ +typedef interface IITVisual IITVisual; +#endif /* __IITVisual_FWD_DEFINED__ */ + + +#ifndef __IITVisualCollection_FWD_DEFINED__ +#define __IITVisualCollection_FWD_DEFINED__ +typedef interface IITVisualCollection IITVisualCollection; +#endif /* __IITVisualCollection_FWD_DEFINED__ */ + + +#ifndef __IITWindow_FWD_DEFINED__ +#define __IITWindow_FWD_DEFINED__ +typedef interface IITWindow IITWindow; +#endif /* __IITWindow_FWD_DEFINED__ */ + + +#ifndef __IITBrowserWindow_FWD_DEFINED__ +#define __IITBrowserWindow_FWD_DEFINED__ +typedef interface IITBrowserWindow IITBrowserWindow; +#endif /* __IITBrowserWindow_FWD_DEFINED__ */ + + +#ifndef __IITWindowCollection_FWD_DEFINED__ +#define __IITWindowCollection_FWD_DEFINED__ +typedef interface IITWindowCollection IITWindowCollection; +#endif /* __IITWindowCollection_FWD_DEFINED__ */ + + +#ifndef __IiTunes_FWD_DEFINED__ +#define __IiTunes_FWD_DEFINED__ +typedef interface IiTunes IiTunes; +#endif /* __IiTunes_FWD_DEFINED__ */ + + +#ifndef ___IiTunesEvents_FWD_DEFINED__ +#define ___IiTunesEvents_FWD_DEFINED__ +typedef interface _IiTunesEvents _IiTunesEvents; +#endif /* ___IiTunesEvents_FWD_DEFINED__ */ + + +#ifndef ___IITConvertOperationStatusEvents_FWD_DEFINED__ +#define ___IITConvertOperationStatusEvents_FWD_DEFINED__ +typedef interface _IITConvertOperationStatusEvents _IITConvertOperationStatusEvents; +#endif /* ___IITConvertOperationStatusEvents_FWD_DEFINED__ */ + + +#ifndef __iTunesApp_FWD_DEFINED__ +#define __iTunesApp_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class iTunesApp iTunesApp; +#else +typedef struct iTunesApp iTunesApp; +#endif /* __cplusplus */ + +#endif /* __iTunesApp_FWD_DEFINED__ */ + + +#ifndef __iTunesConvertOperationStatus_FWD_DEFINED__ +#define __iTunesConvertOperationStatus_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class iTunesConvertOperationStatus iTunesConvertOperationStatus; +#else +typedef struct iTunesConvertOperationStatus iTunesConvertOperationStatus; +#endif /* __cplusplus */ + +#endif /* __iTunesConvertOperationStatus_FWD_DEFINED__ */ + + +#ifndef __IITArtwork_FWD_DEFINED__ +#define __IITArtwork_FWD_DEFINED__ +typedef interface IITArtwork IITArtwork; +#endif /* __IITArtwork_FWD_DEFINED__ */ + + +#ifndef __IITArtworkCollection_FWD_DEFINED__ +#define __IITArtworkCollection_FWD_DEFINED__ +typedef interface IITArtworkCollection IITArtworkCollection; +#endif /* __IITArtworkCollection_FWD_DEFINED__ */ + + +#ifndef __IITURLTrack_FWD_DEFINED__ +#define __IITURLTrack_FWD_DEFINED__ +typedef interface IITURLTrack IITURLTrack; +#endif /* __IITURLTrack_FWD_DEFINED__ */ + + +#ifndef __IITAudioCDPlaylist_FWD_DEFINED__ +#define __IITAudioCDPlaylist_FWD_DEFINED__ +typedef interface IITAudioCDPlaylist IITAudioCDPlaylist; +#endif /* __IITAudioCDPlaylist_FWD_DEFINED__ */ + + +#ifndef __IITPlaylistCollection_FWD_DEFINED__ +#define __IITPlaylistCollection_FWD_DEFINED__ +typedef interface IITPlaylistCollection IITPlaylistCollection; +#endif /* __IITPlaylistCollection_FWD_DEFINED__ */ + + +#ifndef __IITIPodSource_FWD_DEFINED__ +#define __IITIPodSource_FWD_DEFINED__ +typedef interface IITIPodSource IITIPodSource; +#endif /* __IITIPodSource_FWD_DEFINED__ */ + + +#ifndef __IITFileOrCDTrack_FWD_DEFINED__ +#define __IITFileOrCDTrack_FWD_DEFINED__ +typedef interface IITFileOrCDTrack IITFileOrCDTrack; +#endif /* __IITFileOrCDTrack_FWD_DEFINED__ */ + + +#ifndef __IITPlaylistWindow_FWD_DEFINED__ +#define __IITPlaylistWindow_FWD_DEFINED__ +typedef interface IITPlaylistWindow IITPlaylistWindow; +#endif /* __IITPlaylistWindow_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "oaidl.h" +#include "ocidl.h" +#include "DispEx.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +void * __RPC_USER MIDL_user_allocate(size_t); +void __RPC_USER MIDL_user_free( void * ); + +/* interface __MIDL_itf_iTunesCOMInterface_0000 */ +/* [local] */ + +typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("4B73428D-2F56-4833-8E5D-65590E45FEAD") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0000_0001 + { kITTypeLibrary_MajorVersion = 1, + kITTypeLibrary_MinorVersion = 11 + } ITVersion; + +typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("4C25623B-F990-4ebd-8970-F29A70084B8C") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0000_0002 + { ITUNES_E_USERCANCEL = 0xa0040201, + ITUNES_E_OBJECTDELETED = 0xa0040202, + ITUNES_E_OBJECTLOCKED = 0xa0040203, + ITUNES_E_CONVERSIONINPROGRESS = 0xa0040204, + ITUNES_E_MUSICSTOREDISABLED = 0xa0040205, + ITUNES_E_OBJECTEXISTS = 0xa0040206, + ITUNES_E_PODCASTSDISABLED = 0xa0040207 + } ITErrors; + + + +extern RPC_IF_HANDLE __MIDL_itf_iTunesCOMInterface_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_iTunesCOMInterface_0000_v0_0_s_ifspec; + + +#ifndef __iTunesLib_LIBRARY_DEFINED__ +#define __iTunesLib_LIBRARY_DEFINED__ + +/* library iTunesLib */ +/* [helpstring][uuid][version] */ + + + + + + + + + + + + + + + + + + + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("3D502ACA-B474-4640-A2A4-C149538345EC") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0001 + { ITPlayerStateStopped = 0, + ITPlayerStatePlaying = ITPlayerStateStopped + 1, + ITPlayerStateFastForward = ITPlayerStatePlaying + 1, + ITPlayerStateRewind = ITPlayerStateFastForward + 1 + } ITPlayerState; + +typedef /* [public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("5319FADA-0F39-4015-82A0-48B8B871C63C") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0002 + { ITVisualSizeSmall = 0, + ITVisualSizeMedium = ITVisualSizeSmall + 1, + ITVisualSizeLarge = ITVisualSizeMedium + 1 + } ITVisualSize; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("C8128C8D-EDE0-4f0e-AEB1-08D24A91C551") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0003 + { ITCOMDisabledReasonOther = 0, + ITCOMDisabledReasonDialog = ITCOMDisabledReasonOther + 1, + ITCOMDisabledReasonQuitting = ITCOMDisabledReasonDialog + 1 + } ITCOMDisabledReason; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("6B1BD814-CA6E-4063-9EDA-4128D31068C1") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0004 + { ITPlayButtonStatePlayDisabled = 0, + ITPlayButtonStatePlayEnabled = ITPlayButtonStatePlayDisabled + 1, + ITPlayButtonStatePauseEnabled = ITPlayButtonStatePlayEnabled + 1, + ITPlayButtonStatePauseDisabled = ITPlayButtonStatePauseEnabled + 1, + ITPlayButtonStateStopEnabled = ITPlayButtonStatePauseDisabled + 1, + ITPlayButtonStateStopDisabled = ITPlayButtonStateStopEnabled + 1 + } ITPlayButtonState; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("8AF85488-2154-4e46-B65B-1972A43493EF") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0005 + { ITPlayerButtonPrevious = 0, + ITPlayerButtonPlay = ITPlayerButtonPrevious + 1, + ITPlayerButtonNext = ITPlayerButtonPlay + 1 + } ITPlayerButton; + +typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("2129AB11-F23F-485e-B15A-3F8573294F9A") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0272_0006 + { ITPlayerButtonModifierKeyNone = 0, + ITPlayerButtonModifierKeyShift = 1, + ITPlayerButtonModifierKeyControl = 2, + ITPlayerButtonModifierKeyAlt = 4, + ITPlayerButtonModifierKeyCapsLock = 8 + } ITPlayerButtonModifierKey; + +typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("3194F5F4-8F52-41e6-AB8E-4221CFE29550") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0275_0001 + { ITEventDatabaseChanged = 1, + ITEventPlayerPlay = 2, + ITEventPlayerStop = 3, + ITEventPlayerPlayingTrackChanged = 4, + ITEventUserInterfaceEnabled = 5, + ITEventCOMCallsDisabled = 6, + ITEventCOMCallsEnabled = 7, + ITEventQuitting = 8, + ITEventAboutToPromptUserToQuit = 9, + ITEventSoundVolumeChanged = 10 + } ITEvent; + +typedef /* [public][v1_enum][uuid] */ DECLSPEC_UUID("2E4D55FA-1CD3-4831-8751-0C11EC4FF6FD") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0276_0001 + { ITConvertOperationStatusChanged = 1, + ITConvertOperationComplete = 2 + } ITConvertOperationStatusEvent; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("269E36A5-1728-46e4-BF04-93032C3DD51C") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0277_0001 + { ITArtworkFormatUnknown = 0, + ITArtworkFormatJPEG = ITArtworkFormatUnknown + 1, + ITArtworkFormatPNG = ITArtworkFormatJPEG + 1, + ITArtworkFormatBMP = ITArtworkFormatPNG + 1 + } ITArtworkFormat; + + + + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("DDE76D6E-5F8C-4bda-AFA6-69E82218CFF3") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0001 + { ITPlaylistKindUnknown = 0, + ITPlaylistKindLibrary = ITPlaylistKindUnknown + 1, + ITPlaylistKindUser = ITPlaylistKindLibrary + 1, + ITPlaylistKindCD = ITPlaylistKindUser + 1, + ITPlaylistKindDevice = ITPlaylistKindCD + 1, + ITPlaylistKindRadioTuner = ITPlaylistKindDevice + 1 + } ITPlaylistKind; + +typedef /* [public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("4E1D67A4-6C7A-4c7d-821C-03AF7EB10C35") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0002 + { ITPlaylistRepeatModeOff = 0, + ITPlaylistRepeatModeOne = ITPlaylistRepeatModeOff + 1, + ITPlaylistRepeatModeAll = ITPlaylistRepeatModeOne + 1 + } ITPlaylistRepeatMode; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("BB8E7701-1E77-4972-B6C4-C70AC216F468") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0003 + { ITPlaylistPrintKindPlaylist = 0, + ITPlaylistPrintKindAlbumlist = ITPlaylistPrintKindPlaylist + 1, + ITPlaylistPrintKindInsert = ITPlaylistPrintKindAlbumlist + 1 + } ITPlaylistPrintKind; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("58765E77-E34A-4d67-AC12-5B5BA33EA08F") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0283_0004 + { ITPlaylistSearchFieldAll = 0, + ITPlaylistSearchFieldVisible = ITPlaylistSearchFieldAll + 1, + ITPlaylistSearchFieldArtists = ITPlaylistSearchFieldVisible + 1, + ITPlaylistSearchFieldAlbums = ITPlaylistSearchFieldArtists + 1, + ITPlaylistSearchFieldComposers = ITPlaylistSearchFieldAlbums + 1, + ITPlaylistSearchFieldSongNames = ITPlaylistSearchFieldComposers + 1 + } ITPlaylistSearchField; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("62BC24E6-5C77-4fb7-AA6C-B7FA40C6095D") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0285_0001 + { ITUserPlaylistSpecialKindNone = 0, + ITUserPlaylistSpecialKindPurchasedMusic = ITUserPlaylistSpecialKindNone + 1, + ITUserPlaylistSpecialKindPartyShuffle = ITUserPlaylistSpecialKindPurchasedMusic + 1, + ITUserPlaylistSpecialKindPodcasts = ITUserPlaylistSpecialKindPartyShuffle + 1, + ITUserPlaylistSpecialKindFolder = ITUserPlaylistSpecialKindPodcasts + 1, + ITUserPlaylistSpecialKindVideos = ITUserPlaylistSpecialKindFolder + 1, + ITUserPlaylistSpecialKindMusic = ITUserPlaylistSpecialKindVideos + 1, + ITUserPlaylistSpecialKindMovies = ITUserPlaylistSpecialKindMusic + 1, + ITUserPlaylistSpecialKindTVShows = ITUserPlaylistSpecialKindMovies + 1, + ITUserPlaylistSpecialKindAudiobooks = ITUserPlaylistSpecialKindTVShows + 1 + } ITUserPlaylistSpecialKind; + + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("5F35912B-E633-4930-9E25-09489BAED75A") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0288_0001 + { ITSourceKindUnknown = 0, + ITSourceKindLibrary = ITSourceKindUnknown + 1, + ITSourceKindIPod = ITSourceKindLibrary + 1, + ITSourceKindAudioCD = ITSourceKindIPod + 1, + ITSourceKindMP3CD = ITSourceKindAudioCD + 1, + ITSourceKindDevice = ITSourceKindMP3CD + 1, + ITSourceKindRadioTuner = ITSourceKindDevice + 1, + ITSourceKindSharedLibrary = ITSourceKindRadioTuner + 1 + } ITSourceKind; + + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("ACA133C5-4697-4d5f-98B1-D9881B85FE98") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0291_0001 + { ITTrackKindUnknown = 0, + ITTrackKindFile = ITTrackKindUnknown + 1, + ITTrackKindCD = ITTrackKindFile + 1, + ITTrackKindURL = ITTrackKindCD + 1, + ITTrackKindDevice = ITTrackKindURL + 1, + ITTrackKindSharedLibrary = ITTrackKindDevice + 1 + } ITTrackKind; + +typedef /* [public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("735ECC17-38CC-4d4d-A838-24AF7DCB440E") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0291_0002 + { ITVideoKindNone = 0, + ITVideoKindMovie = ITVideoKindNone + 1, + ITVideoKindMusicVideo = ITVideoKindMovie + 1, + ITVideoKindTVShow = ITVideoKindMusicVideo + 1 + } ITVideoKind; + +typedef /* [public][public][public][public][public][v1_enum][uuid] */ DECLSPEC_UUID("5C75B72C-D066-4faa-8732-D9ED71A6CBD9") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0291_0003 + { ITRatingKindUser = 0, + ITRatingKindComputed = ITRatingKindUser + 1 + } ITRatingKind; + +typedef /* [public][public][v1_enum][uuid] */ DECLSPEC_UUID("C20CE920-EFD9-4c1a-8036-95A895741214") +enum __MIDL___MIDL_itf_iTunesCOMInterface_0297_0001 + { ITWindowKindUnknown = 0, + ITWindowKindBrowser = ITWindowKindUnknown + 1, + ITWindowKindPlaylist = ITWindowKindBrowser + 1, + ITWindowKindEQ = ITWindowKindPlaylist + 1, + ITWindowKindArtwork = ITWindowKindEQ + 1, + ITWindowKindNowPlaying = ITWindowKindArtwork + 1 + } ITWindowKind; + + +EXTERN_C const IID LIBID_iTunesLib; + +#ifndef __IITObject_INTERFACE_DEFINED__ +#define __IITObject_INTERFACE_DEFINED__ + +/* interface IITObject */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITObject; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9FAB0E27-70D7-4e3a-9965-B0C8B8869BB6") + IITObject : public IDispatch + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetITObjectIDs( + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Name( + /* [in] */ BSTR name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Index( + /* [retval][out] */ long *index) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SourceID( + /* [retval][out] */ long *sourceID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlaylistID( + /* [retval][out] */ long *playlistID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackID( + /* [retval][out] */ long *trackID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackDatabaseID( + /* [retval][out] */ long *databaseID) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITObjectVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITObject * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITObject * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITObject * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITObject * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITObject * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITObject * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITObject * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITObject * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITObject * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITObject * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITObject * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITObject * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITObject * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITObject * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITObject * This, + /* [retval][out] */ long *databaseID); + + END_INTERFACE + } IITObjectVtbl; + + interface IITObject + { + CONST_VTBL struct IITObjectVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITObject_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITObject_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITObject_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITObject_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITObject_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITObject_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITObject_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITObject_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITObject_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITObject_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITObject_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITObject_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITObject_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITObject_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITObject_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITObject_GetITObjectIDs_Proxy( + IITObject * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + +void __RPC_STUB IITObject_GetITObjectIDs_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_Name_Proxy( + IITObject * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITObject_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITObject_put_Name_Proxy( + IITObject * This, + /* [in] */ BSTR name); + + +void __RPC_STUB IITObject_put_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_Index_Proxy( + IITObject * This, + /* [retval][out] */ long *index); + + +void __RPC_STUB IITObject_get_Index_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_SourceID_Proxy( + IITObject * This, + /* [retval][out] */ long *sourceID); + + +void __RPC_STUB IITObject_get_SourceID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_PlaylistID_Proxy( + IITObject * This, + /* [retval][out] */ long *playlistID); + + +void __RPC_STUB IITObject_get_PlaylistID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_TrackID_Proxy( + IITObject * This, + /* [retval][out] */ long *trackID); + + +void __RPC_STUB IITObject_get_TrackID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITObject_get_TrackDatabaseID_Proxy( + IITObject * This, + /* [retval][out] */ long *databaseID); + + +void __RPC_STUB IITObject_get_TrackDatabaseID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITObject_INTERFACE_DEFINED__ */ + + +#ifndef __IITSource_INTERFACE_DEFINED__ +#define __IITSource_INTERFACE_DEFINED__ + +/* interface IITSource */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITSource; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("AEC1C4D3-AEF1-4255-B892-3E3D13ADFDF9") + IITSource : public IITObject + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( + /* [retval][out] */ ITSourceKind *kind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Capacity( + /* [retval][out] */ double *capacity) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_FreeSpace( + /* [retval][out] */ double *freespace) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlists( + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITSourceVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITSource * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITSource * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITSource * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITSource * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITSource * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITSource * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITSource * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITSource * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITSource * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITSource * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITSource * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITSource * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITSource * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITSource * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITSource * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITSource * This, + /* [retval][out] */ ITSourceKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Capacity )( + IITSource * This, + /* [retval][out] */ double *capacity); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_FreeSpace )( + IITSource * This, + /* [retval][out] */ double *freespace); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( + IITSource * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + END_INTERFACE + } IITSourceVtbl; + + interface IITSource + { + CONST_VTBL struct IITSourceVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITSource_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITSource_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITSource_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITSource_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITSource_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITSource_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITSource_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITSource_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITSource_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITSource_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITSource_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITSource_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITSource_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITSource_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITSource_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITSource_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITSource_get_Capacity(This,capacity) \ + (This)->lpVtbl -> get_Capacity(This,capacity) + +#define IITSource_get_FreeSpace(This,freespace) \ + (This)->lpVtbl -> get_FreeSpace(This,freespace) + +#define IITSource_get_Playlists(This,iPlaylistCollection) \ + (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_Kind_Proxy( + IITSource * This, + /* [retval][out] */ ITSourceKind *kind); + + +void __RPC_STUB IITSource_get_Kind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_Capacity_Proxy( + IITSource * This, + /* [retval][out] */ double *capacity); + + +void __RPC_STUB IITSource_get_Capacity_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_FreeSpace_Proxy( + IITSource * This, + /* [retval][out] */ double *freespace); + + +void __RPC_STUB IITSource_get_FreeSpace_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSource_get_Playlists_Proxy( + IITSource * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + +void __RPC_STUB IITSource_get_Playlists_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITSource_INTERFACE_DEFINED__ */ + + +#ifndef __IITSourceCollection_INTERFACE_DEFINED__ +#define __IITSourceCollection_INTERFACE_DEFINED__ + +/* interface IITSourceCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITSourceCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2FF6CE20-FF87-4183-B0B3-F323D047AF41") + IITSourceCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITSource **iSource) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITSource **iSource) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPersistentID( + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITSource **iSource) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITSourceCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITSourceCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITSourceCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITSourceCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITSourceCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITSourceCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITSourceCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITSourceCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITSourceCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITSourceCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITSourceCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITSourceCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPersistentID )( + IITSourceCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITSource **iSource); + + END_INTERFACE + } IITSourceCollectionVtbl; + + interface IITSourceCollection + { + CONST_VTBL struct IITSourceCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITSourceCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITSourceCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITSourceCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITSourceCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITSourceCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITSourceCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITSourceCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITSourceCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITSourceCollection_get_Item(This,index,iSource) \ + (This)->lpVtbl -> get_Item(This,index,iSource) + +#define IITSourceCollection_get_ItemByName(This,name,iSource) \ + (This)->lpVtbl -> get_ItemByName(This,name,iSource) + +#define IITSourceCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#define IITSourceCollection_get_ItemByPersistentID(This,highID,lowID,iSource) \ + (This)->lpVtbl -> get_ItemByPersistentID(This,highID,lowID,iSource) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_Count_Proxy( + IITSourceCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITSourceCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_Item_Proxy( + IITSourceCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITSource **iSource); + + +void __RPC_STUB IITSourceCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_ItemByName_Proxy( + IITSourceCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITSource **iSource); + + +void __RPC_STUB IITSourceCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get__NewEnum_Proxy( + IITSourceCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITSourceCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITSourceCollection_get_ItemByPersistentID_Proxy( + IITSourceCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITSource **iSource); + + +void __RPC_STUB IITSourceCollection_get_ItemByPersistentID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITSourceCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITEncoder_INTERFACE_DEFINED__ +#define __IITEncoder_INTERFACE_DEFINED__ + +/* interface IITEncoder */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITEncoder; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("1CF95A1C-55FE-4f45-A2D3-85AC6C504A73") + IITEncoder : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Format( + /* [retval][out] */ BSTR *format) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITEncoderVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITEncoder * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITEncoder * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITEncoder * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITEncoder * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITEncoder * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITEncoder * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITEncoder * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITEncoder * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Format )( + IITEncoder * This, + /* [retval][out] */ BSTR *format); + + END_INTERFACE + } IITEncoderVtbl; + + interface IITEncoder + { + CONST_VTBL struct IITEncoderVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITEncoder_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITEncoder_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITEncoder_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITEncoder_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITEncoder_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITEncoder_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITEncoder_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITEncoder_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITEncoder_get_Format(This,format) \ + (This)->lpVtbl -> get_Format(This,format) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoder_get_Name_Proxy( + IITEncoder * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITEncoder_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoder_get_Format_Proxy( + IITEncoder * This, + /* [retval][out] */ BSTR *format); + + +void __RPC_STUB IITEncoder_get_Format_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITEncoder_INTERFACE_DEFINED__ */ + + +#ifndef __IITEncoderCollection_INTERFACE_DEFINED__ +#define __IITEncoderCollection_INTERFACE_DEFINED__ + +/* interface IITEncoderCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITEncoderCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("8862BCA9-168D-4549-A9D5-ADB35E553BA6") + IITEncoderCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITEncoder **iEncoder) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITEncoder **iEncoder) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITEncoderCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITEncoderCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITEncoderCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITEncoderCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITEncoderCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITEncoderCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITEncoderCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITEncoderCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITEncoderCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITEncoderCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITEncoder **iEncoder); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITEncoderCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITEncoder **iEncoder); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITEncoderCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + END_INTERFACE + } IITEncoderCollectionVtbl; + + interface IITEncoderCollection + { + CONST_VTBL struct IITEncoderCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITEncoderCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITEncoderCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITEncoderCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITEncoderCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITEncoderCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITEncoderCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITEncoderCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITEncoderCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITEncoderCollection_get_Item(This,index,iEncoder) \ + (This)->lpVtbl -> get_Item(This,index,iEncoder) + +#define IITEncoderCollection_get_ItemByName(This,name,iEncoder) \ + (This)->lpVtbl -> get_ItemByName(This,name,iEncoder) + +#define IITEncoderCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get_Count_Proxy( + IITEncoderCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITEncoderCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get_Item_Proxy( + IITEncoderCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITEncoder **iEncoder); + + +void __RPC_STUB IITEncoderCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get_ItemByName_Proxy( + IITEncoderCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITEncoder **iEncoder); + + +void __RPC_STUB IITEncoderCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITEncoderCollection_get__NewEnum_Proxy( + IITEncoderCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITEncoderCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITEncoderCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITEQPreset_INTERFACE_DEFINED__ +#define __IITEQPreset_INTERFACE_DEFINED__ + +/* interface IITEQPreset */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITEQPreset; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5BE75F4F-68FA-4212-ACB7-BE44EA569759") + IITEQPreset : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Modifiable( + /* [retval][out] */ VARIANT_BOOL *isModifiable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Preamp( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Preamp( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band1( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band1( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band2( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band2( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band3( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band3( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band4( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band4( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band5( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band5( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band6( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band6( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band7( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band7( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band8( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band8( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band9( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band9( + /* [in] */ double level) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Band10( + /* [retval][out] */ double *level) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Band10( + /* [in] */ double level) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( + /* [in] */ VARIANT_BOOL updateAllTracks) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Rename( + /* [in] */ BSTR newName, + /* [in] */ VARIANT_BOOL updateAllTracks) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITEQPresetVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITEQPreset * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITEQPreset * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITEQPreset * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITEQPreset * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITEQPreset * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITEQPreset * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITEQPreset * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITEQPreset * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Modifiable )( + IITEQPreset * This, + /* [retval][out] */ VARIANT_BOOL *isModifiable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Preamp )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Preamp )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band1 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band1 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band2 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band2 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band3 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band3 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band4 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band4 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band5 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band5 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band6 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band6 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band7 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band7 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band8 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band8 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band9 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band9 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Band10 )( + IITEQPreset * This, + /* [retval][out] */ double *level); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Band10 )( + IITEQPreset * This, + /* [in] */ double level); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITEQPreset * This, + /* [in] */ VARIANT_BOOL updateAllTracks); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Rename )( + IITEQPreset * This, + /* [in] */ BSTR newName, + /* [in] */ VARIANT_BOOL updateAllTracks); + + END_INTERFACE + } IITEQPresetVtbl; + + interface IITEQPreset + { + CONST_VTBL struct IITEQPresetVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITEQPreset_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITEQPreset_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITEQPreset_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITEQPreset_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITEQPreset_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITEQPreset_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITEQPreset_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITEQPreset_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITEQPreset_get_Modifiable(This,isModifiable) \ + (This)->lpVtbl -> get_Modifiable(This,isModifiable) + +#define IITEQPreset_get_Preamp(This,level) \ + (This)->lpVtbl -> get_Preamp(This,level) + +#define IITEQPreset_put_Preamp(This,level) \ + (This)->lpVtbl -> put_Preamp(This,level) + +#define IITEQPreset_get_Band1(This,level) \ + (This)->lpVtbl -> get_Band1(This,level) + +#define IITEQPreset_put_Band1(This,level) \ + (This)->lpVtbl -> put_Band1(This,level) + +#define IITEQPreset_get_Band2(This,level) \ + (This)->lpVtbl -> get_Band2(This,level) + +#define IITEQPreset_put_Band2(This,level) \ + (This)->lpVtbl -> put_Band2(This,level) + +#define IITEQPreset_get_Band3(This,level) \ + (This)->lpVtbl -> get_Band3(This,level) + +#define IITEQPreset_put_Band3(This,level) \ + (This)->lpVtbl -> put_Band3(This,level) + +#define IITEQPreset_get_Band4(This,level) \ + (This)->lpVtbl -> get_Band4(This,level) + +#define IITEQPreset_put_Band4(This,level) \ + (This)->lpVtbl -> put_Band4(This,level) + +#define IITEQPreset_get_Band5(This,level) \ + (This)->lpVtbl -> get_Band5(This,level) + +#define IITEQPreset_put_Band5(This,level) \ + (This)->lpVtbl -> put_Band5(This,level) + +#define IITEQPreset_get_Band6(This,level) \ + (This)->lpVtbl -> get_Band6(This,level) + +#define IITEQPreset_put_Band6(This,level) \ + (This)->lpVtbl -> put_Band6(This,level) + +#define IITEQPreset_get_Band7(This,level) \ + (This)->lpVtbl -> get_Band7(This,level) + +#define IITEQPreset_put_Band7(This,level) \ + (This)->lpVtbl -> put_Band7(This,level) + +#define IITEQPreset_get_Band8(This,level) \ + (This)->lpVtbl -> get_Band8(This,level) + +#define IITEQPreset_put_Band8(This,level) \ + (This)->lpVtbl -> put_Band8(This,level) + +#define IITEQPreset_get_Band9(This,level) \ + (This)->lpVtbl -> get_Band9(This,level) + +#define IITEQPreset_put_Band9(This,level) \ + (This)->lpVtbl -> put_Band9(This,level) + +#define IITEQPreset_get_Band10(This,level) \ + (This)->lpVtbl -> get_Band10(This,level) + +#define IITEQPreset_put_Band10(This,level) \ + (This)->lpVtbl -> put_Band10(This,level) + +#define IITEQPreset_Delete(This,updateAllTracks) \ + (This)->lpVtbl -> Delete(This,updateAllTracks) + +#define IITEQPreset_Rename(This,newName,updateAllTracks) \ + (This)->lpVtbl -> Rename(This,newName,updateAllTracks) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Name_Proxy( + IITEQPreset * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITEQPreset_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Modifiable_Proxy( + IITEQPreset * This, + /* [retval][out] */ VARIANT_BOOL *isModifiable); + + +void __RPC_STUB IITEQPreset_get_Modifiable_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Preamp_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Preamp_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Preamp_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Preamp_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band1_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band1_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band1_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band1_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band2_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band2_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band3_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band3_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band3_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band3_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band4_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band4_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band4_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band4_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band5_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band5_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band5_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band5_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band6_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band6_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band6_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band6_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band7_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band7_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band7_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band7_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band8_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band8_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band8_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band8_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band9_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band9_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band9_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band9_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPreset_get_Band10_Proxy( + IITEQPreset * This, + /* [retval][out] */ double *level); + + +void __RPC_STUB IITEQPreset_get_Band10_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITEQPreset_put_Band10_Proxy( + IITEQPreset * This, + /* [in] */ double level); + + +void __RPC_STUB IITEQPreset_put_Band10_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITEQPreset_Delete_Proxy( + IITEQPreset * This, + /* [in] */ VARIANT_BOOL updateAllTracks); + + +void __RPC_STUB IITEQPreset_Delete_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITEQPreset_Rename_Proxy( + IITEQPreset * This, + /* [in] */ BSTR newName, + /* [in] */ VARIANT_BOOL updateAllTracks); + + +void __RPC_STUB IITEQPreset_Rename_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITEQPreset_INTERFACE_DEFINED__ */ + + +#ifndef __IITEQPresetCollection_INTERFACE_DEFINED__ +#define __IITEQPresetCollection_INTERFACE_DEFINED__ + +/* interface IITEQPresetCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITEQPresetCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("AEF4D111-3331-48da-B0C2-B468D5D61D08") + IITEQPresetCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITEQPreset **iEQPreset) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITEQPreset **iEQPreset) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITEQPresetCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITEQPresetCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITEQPresetCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITEQPresetCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITEQPresetCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITEQPresetCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITEQPresetCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITEQPresetCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITEQPresetCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITEQPresetCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITEQPreset **iEQPreset); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITEQPresetCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITEQPreset **iEQPreset); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITEQPresetCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + END_INTERFACE + } IITEQPresetCollectionVtbl; + + interface IITEQPresetCollection + { + CONST_VTBL struct IITEQPresetCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITEQPresetCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITEQPresetCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITEQPresetCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITEQPresetCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITEQPresetCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITEQPresetCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITEQPresetCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITEQPresetCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITEQPresetCollection_get_Item(This,index,iEQPreset) \ + (This)->lpVtbl -> get_Item(This,index,iEQPreset) + +#define IITEQPresetCollection_get_ItemByName(This,name,iEQPreset) \ + (This)->lpVtbl -> get_ItemByName(This,name,iEQPreset) + +#define IITEQPresetCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get_Count_Proxy( + IITEQPresetCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITEQPresetCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get_Item_Proxy( + IITEQPresetCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITEQPreset **iEQPreset); + + +void __RPC_STUB IITEQPresetCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get_ItemByName_Proxy( + IITEQPresetCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITEQPreset **iEQPreset); + + +void __RPC_STUB IITEQPresetCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITEQPresetCollection_get__NewEnum_Proxy( + IITEQPresetCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITEQPresetCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITEQPresetCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITPlaylist_INTERFACE_DEFINED__ +#define __IITPlaylist_INTERFACE_DEFINED__ + +/* interface IITPlaylist */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITPlaylist; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3D5E072F-2A77-4b17-9E73-E03B77CCCCA9") + IITPlaylist : public IITObject + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayFirstTrack( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Print( + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Search( + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( + /* [retval][out] */ ITPlaylistKind *kind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Source( + /* [retval][out] */ IITSource **iSource) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Duration( + /* [retval][out] */ long *duration) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Shuffle( + /* [retval][out] */ VARIANT_BOOL *isShuffle) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Shuffle( + /* [in] */ VARIANT_BOOL shouldShuffle) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size( + /* [retval][out] */ double *size) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SongRepeat( + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SongRepeat( + /* [in] */ ITPlaylistRepeatMode repeatMode) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Time( + /* [retval][out] */ BSTR *time) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Visible( + /* [retval][out] */ VARIANT_BOOL *isVisible) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Tracks( + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITPlaylistVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITPlaylist * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITPlaylist * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITPlaylist * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITPlaylist * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITPlaylist * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITPlaylist * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITPlaylist * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITPlaylist * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITPlaylist * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITPlaylist * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITPlaylist * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITPlaylist * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITPlaylist * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITPlaylist * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITPlaylist * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( + IITPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( + IITPlaylist * This, + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( + IITPlaylist * This, + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITPlaylist * This, + /* [retval][out] */ ITPlaylistKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( + IITPlaylist * This, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITPlaylist * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( + IITPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShuffle); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( + IITPlaylist * This, + /* [in] */ VARIANT_BOOL shouldShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITPlaylist * This, + /* [retval][out] */ double *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( + IITPlaylist * This, + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( + IITPlaylist * This, + /* [in] */ ITPlaylistRepeatMode repeatMode); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITPlaylist * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITPlaylist * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + END_INTERFACE + } IITPlaylistVtbl; + + interface IITPlaylist + { + CONST_VTBL struct IITPlaylistVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITPlaylist_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITPlaylist_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITPlaylist_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITPlaylist_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITPlaylist_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITPlaylist_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITPlaylist_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITPlaylist_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITPlaylist_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITPlaylist_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITPlaylist_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITPlaylist_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITPlaylist_PlayFirstTrack(This) \ + (This)->lpVtbl -> PlayFirstTrack(This) + +#define IITPlaylist_Print(This,showPrintDialog,printKind,theme) \ + (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) + +#define IITPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ + (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) + +#define IITPlaylist_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITPlaylist_get_Source(This,iSource) \ + (This)->lpVtbl -> get_Source(This,iSource) + +#define IITPlaylist_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITPlaylist_get_Shuffle(This,isShuffle) \ + (This)->lpVtbl -> get_Shuffle(This,isShuffle) + +#define IITPlaylist_put_Shuffle(This,shouldShuffle) \ + (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) + +#define IITPlaylist_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITPlaylist_get_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> get_SongRepeat(This,repeatMode) + +#define IITPlaylist_put_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> put_SongRepeat(This,repeatMode) + +#define IITPlaylist_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITPlaylist_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITPlaylist_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_Delete_Proxy( + IITPlaylist * This); + + +void __RPC_STUB IITPlaylist_Delete_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_PlayFirstTrack_Proxy( + IITPlaylist * This); + + +void __RPC_STUB IITPlaylist_PlayFirstTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_Print_Proxy( + IITPlaylist * This, + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme); + + +void __RPC_STUB IITPlaylist_Print_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITPlaylist_Search_Proxy( + IITPlaylist * This, + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IITPlaylist_Search_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Kind_Proxy( + IITPlaylist * This, + /* [retval][out] */ ITPlaylistKind *kind); + + +void __RPC_STUB IITPlaylist_get_Kind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Source_Proxy( + IITPlaylist * This, + /* [retval][out] */ IITSource **iSource); + + +void __RPC_STUB IITPlaylist_get_Source_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Duration_Proxy( + IITPlaylist * This, + /* [retval][out] */ long *duration); + + +void __RPC_STUB IITPlaylist_get_Duration_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Shuffle_Proxy( + IITPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShuffle); + + +void __RPC_STUB IITPlaylist_get_Shuffle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITPlaylist_put_Shuffle_Proxy( + IITPlaylist * This, + /* [in] */ VARIANT_BOOL shouldShuffle); + + +void __RPC_STUB IITPlaylist_put_Shuffle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Size_Proxy( + IITPlaylist * This, + /* [retval][out] */ double *size); + + +void __RPC_STUB IITPlaylist_get_Size_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_SongRepeat_Proxy( + IITPlaylist * This, + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); + + +void __RPC_STUB IITPlaylist_get_SongRepeat_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITPlaylist_put_SongRepeat_Proxy( + IITPlaylist * This, + /* [in] */ ITPlaylistRepeatMode repeatMode); + + +void __RPC_STUB IITPlaylist_put_SongRepeat_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Time_Proxy( + IITPlaylist * This, + /* [retval][out] */ BSTR *time); + + +void __RPC_STUB IITPlaylist_get_Time_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Visible_Proxy( + IITPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + +void __RPC_STUB IITPlaylist_get_Visible_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylist_get_Tracks_Proxy( + IITPlaylist * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IITPlaylist_get_Tracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITPlaylist_INTERFACE_DEFINED__ */ + + +#ifndef __IITOperationStatus_INTERFACE_DEFINED__ +#define __IITOperationStatus_INTERFACE_DEFINED__ + +/* interface IITOperationStatus */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITOperationStatus; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("206479C9-FE32-4f9b-A18A-475AC939B479") + IITOperationStatus : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_InProgress( + /* [retval][out] */ VARIANT_BOOL *isInProgress) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Tracks( + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITOperationStatusVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITOperationStatus * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITOperationStatus * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITOperationStatus * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITOperationStatus * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITOperationStatus * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITOperationStatus * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITOperationStatus * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InProgress )( + IITOperationStatus * This, + /* [retval][out] */ VARIANT_BOOL *isInProgress); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITOperationStatus * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + END_INTERFACE + } IITOperationStatusVtbl; + + interface IITOperationStatus + { + CONST_VTBL struct IITOperationStatusVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITOperationStatus_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITOperationStatus_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITOperationStatus_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITOperationStatus_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITOperationStatus_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITOperationStatus_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITOperationStatus_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITOperationStatus_get_InProgress(This,isInProgress) \ + (This)->lpVtbl -> get_InProgress(This,isInProgress) + +#define IITOperationStatus_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITOperationStatus_get_InProgress_Proxy( + IITOperationStatus * This, + /* [retval][out] */ VARIANT_BOOL *isInProgress); + + +void __RPC_STUB IITOperationStatus_get_InProgress_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITOperationStatus_get_Tracks_Proxy( + IITOperationStatus * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IITOperationStatus_get_Tracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITOperationStatus_INTERFACE_DEFINED__ */ + + +#ifndef __IITConvertOperationStatus_INTERFACE_DEFINED__ +#define __IITConvertOperationStatus_INTERFACE_DEFINED__ + +/* interface IITConvertOperationStatus */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITConvertOperationStatus; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7063AAF6-ABA0-493b-B4FC-920A9F105875") + IITConvertOperationStatus : public IITOperationStatus + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetConversionStatus( + /* [out] */ BSTR *trackName, + /* [out] */ long *progressValue, + /* [out] */ long *maxProgressValue) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE StopConversion( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackName( + /* [retval][out] */ BSTR *trackName) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ProgressValue( + /* [retval][out] */ long *progressValue) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_MaxProgressValue( + /* [retval][out] */ long *maxProgressValue) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITConvertOperationStatusVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITConvertOperationStatus * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITConvertOperationStatus * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITConvertOperationStatus * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITConvertOperationStatus * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITConvertOperationStatus * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITConvertOperationStatus * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITConvertOperationStatus * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_InProgress )( + IITConvertOperationStatus * This, + /* [retval][out] */ VARIANT_BOOL *isInProgress); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITConvertOperationStatus * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetConversionStatus )( + IITConvertOperationStatus * This, + /* [out] */ BSTR *trackName, + /* [out] */ long *progressValue, + /* [out] */ long *maxProgressValue); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *StopConversion )( + IITConvertOperationStatus * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackName )( + IITConvertOperationStatus * This, + /* [retval][out] */ BSTR *trackName); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ProgressValue )( + IITConvertOperationStatus * This, + /* [retval][out] */ long *progressValue); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MaxProgressValue )( + IITConvertOperationStatus * This, + /* [retval][out] */ long *maxProgressValue); + + END_INTERFACE + } IITConvertOperationStatusVtbl; + + interface IITConvertOperationStatus + { + CONST_VTBL struct IITConvertOperationStatusVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITConvertOperationStatus_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITConvertOperationStatus_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITConvertOperationStatus_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITConvertOperationStatus_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITConvertOperationStatus_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITConvertOperationStatus_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITConvertOperationStatus_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITConvertOperationStatus_get_InProgress(This,isInProgress) \ + (This)->lpVtbl -> get_InProgress(This,isInProgress) + +#define IITConvertOperationStatus_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + + +#define IITConvertOperationStatus_GetConversionStatus(This,trackName,progressValue,maxProgressValue) \ + (This)->lpVtbl -> GetConversionStatus(This,trackName,progressValue,maxProgressValue) + +#define IITConvertOperationStatus_StopConversion(This) \ + (This)->lpVtbl -> StopConversion(This) + +#define IITConvertOperationStatus_get_TrackName(This,trackName) \ + (This)->lpVtbl -> get_TrackName(This,trackName) + +#define IITConvertOperationStatus_get_ProgressValue(This,progressValue) \ + (This)->lpVtbl -> get_ProgressValue(This,progressValue) + +#define IITConvertOperationStatus_get_MaxProgressValue(This,maxProgressValue) \ + (This)->lpVtbl -> get_MaxProgressValue(This,maxProgressValue) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_GetConversionStatus_Proxy( + IITConvertOperationStatus * This, + /* [out] */ BSTR *trackName, + /* [out] */ long *progressValue, + /* [out] */ long *maxProgressValue); + + +void __RPC_STUB IITConvertOperationStatus_GetConversionStatus_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_StopConversion_Proxy( + IITConvertOperationStatus * This); + + +void __RPC_STUB IITConvertOperationStatus_StopConversion_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_get_TrackName_Proxy( + IITConvertOperationStatus * This, + /* [retval][out] */ BSTR *trackName); + + +void __RPC_STUB IITConvertOperationStatus_get_TrackName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_get_ProgressValue_Proxy( + IITConvertOperationStatus * This, + /* [retval][out] */ long *progressValue); + + +void __RPC_STUB IITConvertOperationStatus_get_ProgressValue_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITConvertOperationStatus_get_MaxProgressValue_Proxy( + IITConvertOperationStatus * This, + /* [retval][out] */ long *maxProgressValue); + + +void __RPC_STUB IITConvertOperationStatus_get_MaxProgressValue_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITConvertOperationStatus_INTERFACE_DEFINED__ */ + + +#ifndef __IITLibraryPlaylist_INTERFACE_DEFINED__ +#define __IITLibraryPlaylist_INTERFACE_DEFINED__ + +/* interface IITLibraryPlaylist */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITLibraryPlaylist; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("53AE1704-491C-4289-94A0-958815675A3D") + IITLibraryPlaylist : public IITPlaylist + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFile( + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFiles( + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddURL( + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddTrack( + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITLibraryPlaylistVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITLibraryPlaylist * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITLibraryPlaylist * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITLibraryPlaylist * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITLibraryPlaylist * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITLibraryPlaylist * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITLibraryPlaylist * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITLibraryPlaylist * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITLibraryPlaylist * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITLibraryPlaylist * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITLibraryPlaylist * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITLibraryPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( + IITLibraryPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( + IITLibraryPlaylist * This, + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( + IITLibraryPlaylist * This, + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITLibraryPlaylist * This, + /* [retval][out] */ ITPlaylistKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( + IITLibraryPlaylist * This, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITLibraryPlaylist * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( + IITLibraryPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShuffle); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( + IITLibraryPlaylist * This, + /* [in] */ VARIANT_BOOL shouldShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITLibraryPlaylist * This, + /* [retval][out] */ double *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( + IITLibraryPlaylist * This, + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( + IITLibraryPlaylist * This, + /* [in] */ ITPlaylistRepeatMode repeatMode); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITLibraryPlaylist * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITLibraryPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITLibraryPlaylist * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFile )( + IITLibraryPlaylist * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFiles )( + IITLibraryPlaylist * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddURL )( + IITLibraryPlaylist * This, + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddTrack )( + IITLibraryPlaylist * This, + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack); + + END_INTERFACE + } IITLibraryPlaylistVtbl; + + interface IITLibraryPlaylist + { + CONST_VTBL struct IITLibraryPlaylistVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITLibraryPlaylist_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITLibraryPlaylist_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITLibraryPlaylist_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITLibraryPlaylist_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITLibraryPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITLibraryPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITLibraryPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITLibraryPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITLibraryPlaylist_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITLibraryPlaylist_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITLibraryPlaylist_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITLibraryPlaylist_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITLibraryPlaylist_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITLibraryPlaylist_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITLibraryPlaylist_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITLibraryPlaylist_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITLibraryPlaylist_PlayFirstTrack(This) \ + (This)->lpVtbl -> PlayFirstTrack(This) + +#define IITLibraryPlaylist_Print(This,showPrintDialog,printKind,theme) \ + (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) + +#define IITLibraryPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ + (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) + +#define IITLibraryPlaylist_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITLibraryPlaylist_get_Source(This,iSource) \ + (This)->lpVtbl -> get_Source(This,iSource) + +#define IITLibraryPlaylist_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITLibraryPlaylist_get_Shuffle(This,isShuffle) \ + (This)->lpVtbl -> get_Shuffle(This,isShuffle) + +#define IITLibraryPlaylist_put_Shuffle(This,shouldShuffle) \ + (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) + +#define IITLibraryPlaylist_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITLibraryPlaylist_get_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> get_SongRepeat(This,repeatMode) + +#define IITLibraryPlaylist_put_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> put_SongRepeat(This,repeatMode) + +#define IITLibraryPlaylist_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITLibraryPlaylist_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITLibraryPlaylist_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + + +#define IITLibraryPlaylist_AddFile(This,filePath,iStatus) \ + (This)->lpVtbl -> AddFile(This,filePath,iStatus) + +#define IITLibraryPlaylist_AddFiles(This,filePaths,iStatus) \ + (This)->lpVtbl -> AddFiles(This,filePaths,iStatus) + +#define IITLibraryPlaylist_AddURL(This,url,iURLTrack) \ + (This)->lpVtbl -> AddURL(This,url,iURLTrack) + +#define IITLibraryPlaylist_AddTrack(This,iTrackToAdd,iAddedTrack) \ + (This)->lpVtbl -> AddTrack(This,iTrackToAdd,iAddedTrack) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddFile_Proxy( + IITLibraryPlaylist * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IITLibraryPlaylist_AddFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddFiles_Proxy( + IITLibraryPlaylist * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IITLibraryPlaylist_AddFiles_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddURL_Proxy( + IITLibraryPlaylist * This, + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack); + + +void __RPC_STUB IITLibraryPlaylist_AddURL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITLibraryPlaylist_AddTrack_Proxy( + IITLibraryPlaylist * This, + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack); + + +void __RPC_STUB IITLibraryPlaylist_AddTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITLibraryPlaylist_INTERFACE_DEFINED__ */ + + +#ifndef __IITUserPlaylist_INTERFACE_DEFINED__ +#define __IITUserPlaylist_INTERFACE_DEFINED__ + +/* interface IITUserPlaylist */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITUserPlaylist; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("0A504DED-A0B5-465a-8A94-50E20D7DF692") + IITUserPlaylist : public IITPlaylist + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFile( + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddFiles( + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddURL( + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddTrack( + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Shared( + /* [retval][out] */ VARIANT_BOOL *isShared) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Shared( + /* [in] */ VARIANT_BOOL shouldBeShared) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Smart( + /* [retval][out] */ VARIANT_BOOL *isSmart) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SpecialKind( + /* [retval][out] */ ITUserPlaylistSpecialKind *specialKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Parent( + /* [retval][out] */ IITUserPlaylist **iParentPlayList) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePlaylist( + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateFolder( + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Parent( + /* [in] */ VARIANT *iParent) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITUserPlaylistVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITUserPlaylist * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITUserPlaylist * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITUserPlaylist * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITUserPlaylist * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITUserPlaylist * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITUserPlaylist * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITUserPlaylist * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITUserPlaylist * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITUserPlaylist * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITUserPlaylist * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITUserPlaylist * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITUserPlaylist * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITUserPlaylist * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITUserPlaylist * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITUserPlaylist * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITUserPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( + IITUserPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( + IITUserPlaylist * This, + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( + IITUserPlaylist * This, + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITUserPlaylist * This, + /* [retval][out] */ ITPlaylistKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( + IITUserPlaylist * This, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITUserPlaylist * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShuffle); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( + IITUserPlaylist * This, + /* [in] */ VARIANT_BOOL shouldShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITUserPlaylist * This, + /* [retval][out] */ double *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( + IITUserPlaylist * This, + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( + IITUserPlaylist * This, + /* [in] */ ITPlaylistRepeatMode repeatMode); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITUserPlaylist * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITUserPlaylist * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFile )( + IITUserPlaylist * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddFiles )( + IITUserPlaylist * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddURL )( + IITUserPlaylist * This, + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddTrack )( + IITUserPlaylist * This, + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shared )( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShared); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shared )( + IITUserPlaylist * This, + /* [in] */ VARIANT_BOOL shouldBeShared); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Smart )( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isSmart); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SpecialKind )( + IITUserPlaylist * This, + /* [retval][out] */ ITUserPlaylistSpecialKind *specialKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Parent )( + IITUserPlaylist * This, + /* [retval][out] */ IITUserPlaylist **iParentPlayList); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreatePlaylist )( + IITUserPlaylist * This, + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateFolder )( + IITUserPlaylist * This, + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Parent )( + IITUserPlaylist * This, + /* [in] */ VARIANT *iParent); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( + IITUserPlaylist * This); + + END_INTERFACE + } IITUserPlaylistVtbl; + + interface IITUserPlaylist + { + CONST_VTBL struct IITUserPlaylistVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITUserPlaylist_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITUserPlaylist_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITUserPlaylist_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITUserPlaylist_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITUserPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITUserPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITUserPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITUserPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITUserPlaylist_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITUserPlaylist_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITUserPlaylist_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITUserPlaylist_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITUserPlaylist_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITUserPlaylist_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITUserPlaylist_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITUserPlaylist_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITUserPlaylist_PlayFirstTrack(This) \ + (This)->lpVtbl -> PlayFirstTrack(This) + +#define IITUserPlaylist_Print(This,showPrintDialog,printKind,theme) \ + (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) + +#define IITUserPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ + (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) + +#define IITUserPlaylist_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITUserPlaylist_get_Source(This,iSource) \ + (This)->lpVtbl -> get_Source(This,iSource) + +#define IITUserPlaylist_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITUserPlaylist_get_Shuffle(This,isShuffle) \ + (This)->lpVtbl -> get_Shuffle(This,isShuffle) + +#define IITUserPlaylist_put_Shuffle(This,shouldShuffle) \ + (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) + +#define IITUserPlaylist_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITUserPlaylist_get_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> get_SongRepeat(This,repeatMode) + +#define IITUserPlaylist_put_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> put_SongRepeat(This,repeatMode) + +#define IITUserPlaylist_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITUserPlaylist_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITUserPlaylist_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + + +#define IITUserPlaylist_AddFile(This,filePath,iStatus) \ + (This)->lpVtbl -> AddFile(This,filePath,iStatus) + +#define IITUserPlaylist_AddFiles(This,filePaths,iStatus) \ + (This)->lpVtbl -> AddFiles(This,filePaths,iStatus) + +#define IITUserPlaylist_AddURL(This,url,iURLTrack) \ + (This)->lpVtbl -> AddURL(This,url,iURLTrack) + +#define IITUserPlaylist_AddTrack(This,iTrackToAdd,iAddedTrack) \ + (This)->lpVtbl -> AddTrack(This,iTrackToAdd,iAddedTrack) + +#define IITUserPlaylist_get_Shared(This,isShared) \ + (This)->lpVtbl -> get_Shared(This,isShared) + +#define IITUserPlaylist_put_Shared(This,shouldBeShared) \ + (This)->lpVtbl -> put_Shared(This,shouldBeShared) + +#define IITUserPlaylist_get_Smart(This,isSmart) \ + (This)->lpVtbl -> get_Smart(This,isSmart) + +#define IITUserPlaylist_get_SpecialKind(This,specialKind) \ + (This)->lpVtbl -> get_SpecialKind(This,specialKind) + +#define IITUserPlaylist_get_Parent(This,iParentPlayList) \ + (This)->lpVtbl -> get_Parent(This,iParentPlayList) + +#define IITUserPlaylist_CreatePlaylist(This,playlistName,iPlaylist) \ + (This)->lpVtbl -> CreatePlaylist(This,playlistName,iPlaylist) + +#define IITUserPlaylist_CreateFolder(This,folderName,iFolder) \ + (This)->lpVtbl -> CreateFolder(This,folderName,iFolder) + +#define IITUserPlaylist_put_Parent(This,iParent) \ + (This)->lpVtbl -> put_Parent(This,iParent) + +#define IITUserPlaylist_Reveal(This) \ + (This)->lpVtbl -> Reveal(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddFile_Proxy( + IITUserPlaylist * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IITUserPlaylist_AddFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddFiles_Proxy( + IITUserPlaylist * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IITUserPlaylist_AddFiles_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddURL_Proxy( + IITUserPlaylist * This, + /* [in] */ BSTR url, + /* [retval][out] */ IITURLTrack **iURLTrack); + + +void __RPC_STUB IITUserPlaylist_AddURL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_AddTrack_Proxy( + IITUserPlaylist * This, + /* [in] */ VARIANT *iTrackToAdd, + /* [retval][out] */ IITTrack **iAddedTrack); + + +void __RPC_STUB IITUserPlaylist_AddTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_Shared_Proxy( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShared); + + +void __RPC_STUB IITUserPlaylist_get_Shared_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_put_Shared_Proxy( + IITUserPlaylist * This, + /* [in] */ VARIANT_BOOL shouldBeShared); + + +void __RPC_STUB IITUserPlaylist_put_Shared_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_Smart_Proxy( + IITUserPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isSmart); + + +void __RPC_STUB IITUserPlaylist_get_Smart_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_SpecialKind_Proxy( + IITUserPlaylist * This, + /* [retval][out] */ ITUserPlaylistSpecialKind *specialKind); + + +void __RPC_STUB IITUserPlaylist_get_SpecialKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_get_Parent_Proxy( + IITUserPlaylist * This, + /* [retval][out] */ IITUserPlaylist **iParentPlayList); + + +void __RPC_STUB IITUserPlaylist_get_Parent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_CreatePlaylist_Proxy( + IITUserPlaylist * This, + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITUserPlaylist_CreatePlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_CreateFolder_Proxy( + IITUserPlaylist * This, + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder); + + +void __RPC_STUB IITUserPlaylist_CreateFolder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_put_Parent_Proxy( + IITUserPlaylist * This, + /* [in] */ VARIANT *iParent); + + +void __RPC_STUB IITUserPlaylist_put_Parent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITUserPlaylist_Reveal_Proxy( + IITUserPlaylist * This); + + +void __RPC_STUB IITUserPlaylist_Reveal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITUserPlaylist_INTERFACE_DEFINED__ */ + + +#ifndef __IITTrack_INTERFACE_DEFINED__ +#define __IITTrack_INTERFACE_DEFINED__ + +/* interface IITTrack */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITTrack; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("4CB0915D-1E54-4727-BAF3-CE6CC9A225A1") + IITTrack : public IITObject + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Play( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AddArtworkFromFile( + /* [in] */ BSTR filePath, + /* [retval][out] */ IITArtwork **iArtwork) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( + /* [retval][out] */ ITTrackKind *kind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlist( + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Album( + /* [retval][out] */ BSTR *album) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Album( + /* [in] */ BSTR album) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Artist( + /* [retval][out] */ BSTR *artist) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Artist( + /* [in] */ BSTR artist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BitRate( + /* [retval][out] */ long *bitrate) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BPM( + /* [retval][out] */ long *beatsPerMinute) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_BPM( + /* [in] */ long beatsPerMinute) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Comment( + /* [retval][out] */ BSTR *comment) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Comment( + /* [in] */ BSTR comment) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Compilation( + /* [retval][out] */ VARIANT_BOOL *isCompilation) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Compilation( + /* [in] */ VARIANT_BOOL shouldBeCompilation) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Composer( + /* [retval][out] */ BSTR *composer) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Composer( + /* [in] */ BSTR composer) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DateAdded( + /* [retval][out] */ DATE *dateAdded) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscCount( + /* [retval][out] */ long *discCount) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DiscCount( + /* [in] */ long discCount) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscNumber( + /* [retval][out] */ long *discNumber) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DiscNumber( + /* [in] */ long discNumber) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Duration( + /* [retval][out] */ long *duration) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Enabled( + /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Enabled( + /* [in] */ VARIANT_BOOL shouldBeEnabled) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQ( + /* [retval][out] */ BSTR *eq) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EQ( + /* [in] */ BSTR eq) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Finish( + /* [in] */ long finish) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Finish( + /* [retval][out] */ long *finish) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Genre( + /* [retval][out] */ BSTR *genre) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Genre( + /* [in] */ BSTR genre) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Grouping( + /* [retval][out] */ BSTR *grouping) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Grouping( + /* [in] */ BSTR grouping) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_KindAsString( + /* [retval][out] */ BSTR *kind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ModificationDate( + /* [retval][out] */ DATE *dateModified) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayedCount( + /* [retval][out] */ long *playedCount) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PlayedCount( + /* [in] */ long playedCount) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayedDate( + /* [retval][out] */ DATE *playedDate) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PlayedDate( + /* [in] */ DATE playedDate) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayOrderIndex( + /* [retval][out] */ long *index) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Rating( + /* [retval][out] */ long *rating) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Rating( + /* [in] */ long rating) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SampleRate( + /* [retval][out] */ long *sampleRate) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size( + /* [retval][out] */ long *size) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Start( + /* [retval][out] */ long *start) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Start( + /* [in] */ long start) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Time( + /* [retval][out] */ BSTR *time) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackCount( + /* [retval][out] */ long *trackCount) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_TrackCount( + /* [in] */ long trackCount) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_TrackNumber( + /* [retval][out] */ long *trackNumber) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_TrackNumber( + /* [in] */ long trackNumber) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VolumeAdjustment( + /* [retval][out] */ long *volumeAdjustment) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VolumeAdjustment( + /* [in] */ long volumeAdjustment) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Year( + /* [retval][out] */ long *year) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Year( + /* [in] */ long year) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Artwork( + /* [retval][out] */ IITArtworkCollection **iArtworkCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITTrackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITTrack * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITTrack * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITTrack * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITTrack * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITTrack * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITTrack * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITTrack * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITTrack * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITTrack * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITTrack * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITTrack * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITTrack * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITTrack * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITTrack * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( + IITTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddArtworkFromFile )( + IITTrack * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITArtwork **iArtwork); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITTrack * This, + /* [retval][out] */ ITTrackKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( + IITTrack * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Album )( + IITTrack * This, + /* [retval][out] */ BSTR *album); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Album )( + IITTrack * This, + /* [in] */ BSTR album); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( + IITTrack * This, + /* [retval][out] */ BSTR *artist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Artist )( + IITTrack * This, + /* [in] */ BSTR artist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BitRate )( + IITTrack * This, + /* [retval][out] */ long *bitrate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BPM )( + IITTrack * This, + /* [retval][out] */ long *beatsPerMinute); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BPM )( + IITTrack * This, + /* [in] */ long beatsPerMinute); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Comment )( + IITTrack * This, + /* [retval][out] */ BSTR *comment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Comment )( + IITTrack * This, + /* [in] */ BSTR comment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( + IITTrack * This, + /* [retval][out] */ VARIANT_BOOL *isCompilation); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Compilation )( + IITTrack * This, + /* [in] */ VARIANT_BOOL shouldBeCompilation); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( + IITTrack * This, + /* [retval][out] */ BSTR *composer); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Composer )( + IITTrack * This, + /* [in] */ BSTR composer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DateAdded )( + IITTrack * This, + /* [retval][out] */ DATE *dateAdded); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( + IITTrack * This, + /* [retval][out] */ long *discCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscCount )( + IITTrack * This, + /* [in] */ long discCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( + IITTrack * This, + /* [retval][out] */ long *discNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscNumber )( + IITTrack * This, + /* [in] */ long discNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITTrack * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Enabled )( + IITTrack * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Enabled )( + IITTrack * This, + /* [in] */ VARIANT_BOOL shouldBeEnabled); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQ )( + IITTrack * This, + /* [retval][out] */ BSTR *eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQ )( + IITTrack * This, + /* [in] */ BSTR eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Finish )( + IITTrack * This, + /* [in] */ long finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Finish )( + IITTrack * This, + /* [retval][out] */ long *finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( + IITTrack * This, + /* [retval][out] */ BSTR *genre); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Genre )( + IITTrack * This, + /* [in] */ BSTR genre); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Grouping )( + IITTrack * This, + /* [retval][out] */ BSTR *grouping); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Grouping )( + IITTrack * This, + /* [in] */ BSTR grouping); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_KindAsString )( + IITTrack * This, + /* [retval][out] */ BSTR *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ModificationDate )( + IITTrack * This, + /* [retval][out] */ DATE *dateModified); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedCount )( + IITTrack * This, + /* [retval][out] */ long *playedCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedCount )( + IITTrack * This, + /* [in] */ long playedCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedDate )( + IITTrack * This, + /* [retval][out] */ DATE *playedDate); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedDate )( + IITTrack * This, + /* [in] */ DATE playedDate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayOrderIndex )( + IITTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Rating )( + IITTrack * This, + /* [retval][out] */ long *rating); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Rating )( + IITTrack * This, + /* [in] */ long rating); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SampleRate )( + IITTrack * This, + /* [retval][out] */ long *sampleRate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITTrack * This, + /* [retval][out] */ long *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Start )( + IITTrack * This, + /* [retval][out] */ long *start); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Start )( + IITTrack * This, + /* [in] */ long start); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITTrack * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackCount )( + IITTrack * This, + /* [retval][out] */ long *trackCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackCount )( + IITTrack * This, + /* [in] */ long trackCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackNumber )( + IITTrack * This, + /* [retval][out] */ long *trackNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackNumber )( + IITTrack * This, + /* [in] */ long trackNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VolumeAdjustment )( + IITTrack * This, + /* [retval][out] */ long *volumeAdjustment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VolumeAdjustment )( + IITTrack * This, + /* [in] */ long volumeAdjustment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( + IITTrack * This, + /* [retval][out] */ long *year); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Year )( + IITTrack * This, + /* [in] */ long year); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artwork )( + IITTrack * This, + /* [retval][out] */ IITArtworkCollection **iArtworkCollection); + + END_INTERFACE + } IITTrackVtbl; + + interface IITTrack + { + CONST_VTBL struct IITTrackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITTrack_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITTrack_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITTrack_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITTrack_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITTrack_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITTrack_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITTrack_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITTrack_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITTrack_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITTrack_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITTrack_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITTrack_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITTrack_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITTrack_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITTrack_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITTrack_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITTrack_Play(This) \ + (This)->lpVtbl -> Play(This) + +#define IITTrack_AddArtworkFromFile(This,filePath,iArtwork) \ + (This)->lpVtbl -> AddArtworkFromFile(This,filePath,iArtwork) + +#define IITTrack_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITTrack_get_Playlist(This,iPlaylist) \ + (This)->lpVtbl -> get_Playlist(This,iPlaylist) + +#define IITTrack_get_Album(This,album) \ + (This)->lpVtbl -> get_Album(This,album) + +#define IITTrack_put_Album(This,album) \ + (This)->lpVtbl -> put_Album(This,album) + +#define IITTrack_get_Artist(This,artist) \ + (This)->lpVtbl -> get_Artist(This,artist) + +#define IITTrack_put_Artist(This,artist) \ + (This)->lpVtbl -> put_Artist(This,artist) + +#define IITTrack_get_BitRate(This,bitrate) \ + (This)->lpVtbl -> get_BitRate(This,bitrate) + +#define IITTrack_get_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> get_BPM(This,beatsPerMinute) + +#define IITTrack_put_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> put_BPM(This,beatsPerMinute) + +#define IITTrack_get_Comment(This,comment) \ + (This)->lpVtbl -> get_Comment(This,comment) + +#define IITTrack_put_Comment(This,comment) \ + (This)->lpVtbl -> put_Comment(This,comment) + +#define IITTrack_get_Compilation(This,isCompilation) \ + (This)->lpVtbl -> get_Compilation(This,isCompilation) + +#define IITTrack_put_Compilation(This,shouldBeCompilation) \ + (This)->lpVtbl -> put_Compilation(This,shouldBeCompilation) + +#define IITTrack_get_Composer(This,composer) \ + (This)->lpVtbl -> get_Composer(This,composer) + +#define IITTrack_put_Composer(This,composer) \ + (This)->lpVtbl -> put_Composer(This,composer) + +#define IITTrack_get_DateAdded(This,dateAdded) \ + (This)->lpVtbl -> get_DateAdded(This,dateAdded) + +#define IITTrack_get_DiscCount(This,discCount) \ + (This)->lpVtbl -> get_DiscCount(This,discCount) + +#define IITTrack_put_DiscCount(This,discCount) \ + (This)->lpVtbl -> put_DiscCount(This,discCount) + +#define IITTrack_get_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> get_DiscNumber(This,discNumber) + +#define IITTrack_put_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> put_DiscNumber(This,discNumber) + +#define IITTrack_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITTrack_get_Enabled(This,isEnabled) \ + (This)->lpVtbl -> get_Enabled(This,isEnabled) + +#define IITTrack_put_Enabled(This,shouldBeEnabled) \ + (This)->lpVtbl -> put_Enabled(This,shouldBeEnabled) + +#define IITTrack_get_EQ(This,eq) \ + (This)->lpVtbl -> get_EQ(This,eq) + +#define IITTrack_put_EQ(This,eq) \ + (This)->lpVtbl -> put_EQ(This,eq) + +#define IITTrack_put_Finish(This,finish) \ + (This)->lpVtbl -> put_Finish(This,finish) + +#define IITTrack_get_Finish(This,finish) \ + (This)->lpVtbl -> get_Finish(This,finish) + +#define IITTrack_get_Genre(This,genre) \ + (This)->lpVtbl -> get_Genre(This,genre) + +#define IITTrack_put_Genre(This,genre) \ + (This)->lpVtbl -> put_Genre(This,genre) + +#define IITTrack_get_Grouping(This,grouping) \ + (This)->lpVtbl -> get_Grouping(This,grouping) + +#define IITTrack_put_Grouping(This,grouping) \ + (This)->lpVtbl -> put_Grouping(This,grouping) + +#define IITTrack_get_KindAsString(This,kind) \ + (This)->lpVtbl -> get_KindAsString(This,kind) + +#define IITTrack_get_ModificationDate(This,dateModified) \ + (This)->lpVtbl -> get_ModificationDate(This,dateModified) + +#define IITTrack_get_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> get_PlayedCount(This,playedCount) + +#define IITTrack_put_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> put_PlayedCount(This,playedCount) + +#define IITTrack_get_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> get_PlayedDate(This,playedDate) + +#define IITTrack_put_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> put_PlayedDate(This,playedDate) + +#define IITTrack_get_PlayOrderIndex(This,index) \ + (This)->lpVtbl -> get_PlayOrderIndex(This,index) + +#define IITTrack_get_Rating(This,rating) \ + (This)->lpVtbl -> get_Rating(This,rating) + +#define IITTrack_put_Rating(This,rating) \ + (This)->lpVtbl -> put_Rating(This,rating) + +#define IITTrack_get_SampleRate(This,sampleRate) \ + (This)->lpVtbl -> get_SampleRate(This,sampleRate) + +#define IITTrack_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITTrack_get_Start(This,start) \ + (This)->lpVtbl -> get_Start(This,start) + +#define IITTrack_put_Start(This,start) \ + (This)->lpVtbl -> put_Start(This,start) + +#define IITTrack_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITTrack_get_TrackCount(This,trackCount) \ + (This)->lpVtbl -> get_TrackCount(This,trackCount) + +#define IITTrack_put_TrackCount(This,trackCount) \ + (This)->lpVtbl -> put_TrackCount(This,trackCount) + +#define IITTrack_get_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> get_TrackNumber(This,trackNumber) + +#define IITTrack_put_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> put_TrackNumber(This,trackNumber) + +#define IITTrack_get_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> get_VolumeAdjustment(This,volumeAdjustment) + +#define IITTrack_put_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> put_VolumeAdjustment(This,volumeAdjustment) + +#define IITTrack_get_Year(This,year) \ + (This)->lpVtbl -> get_Year(This,year) + +#define IITTrack_put_Year(This,year) \ + (This)->lpVtbl -> put_Year(This,year) + +#define IITTrack_get_Artwork(This,iArtworkCollection) \ + (This)->lpVtbl -> get_Artwork(This,iArtworkCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITTrack_Delete_Proxy( + IITTrack * This); + + +void __RPC_STUB IITTrack_Delete_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITTrack_Play_Proxy( + IITTrack * This); + + +void __RPC_STUB IITTrack_Play_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITTrack_AddArtworkFromFile_Proxy( + IITTrack * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITArtwork **iArtwork); + + +void __RPC_STUB IITTrack_AddArtworkFromFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Kind_Proxy( + IITTrack * This, + /* [retval][out] */ ITTrackKind *kind); + + +void __RPC_STUB IITTrack_get_Kind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Playlist_Proxy( + IITTrack * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITTrack_get_Playlist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Album_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *album); + + +void __RPC_STUB IITTrack_get_Album_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Album_Proxy( + IITTrack * This, + /* [in] */ BSTR album); + + +void __RPC_STUB IITTrack_put_Album_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Artist_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *artist); + + +void __RPC_STUB IITTrack_get_Artist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Artist_Proxy( + IITTrack * This, + /* [in] */ BSTR artist); + + +void __RPC_STUB IITTrack_put_Artist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_BitRate_Proxy( + IITTrack * This, + /* [retval][out] */ long *bitrate); + + +void __RPC_STUB IITTrack_get_BitRate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_BPM_Proxy( + IITTrack * This, + /* [retval][out] */ long *beatsPerMinute); + + +void __RPC_STUB IITTrack_get_BPM_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_BPM_Proxy( + IITTrack * This, + /* [in] */ long beatsPerMinute); + + +void __RPC_STUB IITTrack_put_BPM_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Comment_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *comment); + + +void __RPC_STUB IITTrack_get_Comment_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Comment_Proxy( + IITTrack * This, + /* [in] */ BSTR comment); + + +void __RPC_STUB IITTrack_put_Comment_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Compilation_Proxy( + IITTrack * This, + /* [retval][out] */ VARIANT_BOOL *isCompilation); + + +void __RPC_STUB IITTrack_get_Compilation_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Compilation_Proxy( + IITTrack * This, + /* [in] */ VARIANT_BOOL shouldBeCompilation); + + +void __RPC_STUB IITTrack_put_Compilation_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Composer_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *composer); + + +void __RPC_STUB IITTrack_get_Composer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Composer_Proxy( + IITTrack * This, + /* [in] */ BSTR composer); + + +void __RPC_STUB IITTrack_put_Composer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_DateAdded_Proxy( + IITTrack * This, + /* [retval][out] */ DATE *dateAdded); + + +void __RPC_STUB IITTrack_get_DateAdded_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_DiscCount_Proxy( + IITTrack * This, + /* [retval][out] */ long *discCount); + + +void __RPC_STUB IITTrack_get_DiscCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_DiscCount_Proxy( + IITTrack * This, + /* [in] */ long discCount); + + +void __RPC_STUB IITTrack_put_DiscCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_DiscNumber_Proxy( + IITTrack * This, + /* [retval][out] */ long *discNumber); + + +void __RPC_STUB IITTrack_get_DiscNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_DiscNumber_Proxy( + IITTrack * This, + /* [in] */ long discNumber); + + +void __RPC_STUB IITTrack_put_DiscNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Duration_Proxy( + IITTrack * This, + /* [retval][out] */ long *duration); + + +void __RPC_STUB IITTrack_get_Duration_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Enabled_Proxy( + IITTrack * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + +void __RPC_STUB IITTrack_get_Enabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Enabled_Proxy( + IITTrack * This, + /* [in] */ VARIANT_BOOL shouldBeEnabled); + + +void __RPC_STUB IITTrack_put_Enabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_EQ_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *eq); + + +void __RPC_STUB IITTrack_get_EQ_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_EQ_Proxy( + IITTrack * This, + /* [in] */ BSTR eq); + + +void __RPC_STUB IITTrack_put_EQ_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Finish_Proxy( + IITTrack * This, + /* [in] */ long finish); + + +void __RPC_STUB IITTrack_put_Finish_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Finish_Proxy( + IITTrack * This, + /* [retval][out] */ long *finish); + + +void __RPC_STUB IITTrack_get_Finish_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Genre_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *genre); + + +void __RPC_STUB IITTrack_get_Genre_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Genre_Proxy( + IITTrack * This, + /* [in] */ BSTR genre); + + +void __RPC_STUB IITTrack_put_Genre_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Grouping_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *grouping); + + +void __RPC_STUB IITTrack_get_Grouping_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Grouping_Proxy( + IITTrack * This, + /* [in] */ BSTR grouping); + + +void __RPC_STUB IITTrack_put_Grouping_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_KindAsString_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *kind); + + +void __RPC_STUB IITTrack_get_KindAsString_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_ModificationDate_Proxy( + IITTrack * This, + /* [retval][out] */ DATE *dateModified); + + +void __RPC_STUB IITTrack_get_ModificationDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_PlayedCount_Proxy( + IITTrack * This, + /* [retval][out] */ long *playedCount); + + +void __RPC_STUB IITTrack_get_PlayedCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_PlayedCount_Proxy( + IITTrack * This, + /* [in] */ long playedCount); + + +void __RPC_STUB IITTrack_put_PlayedCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_PlayedDate_Proxy( + IITTrack * This, + /* [retval][out] */ DATE *playedDate); + + +void __RPC_STUB IITTrack_get_PlayedDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_PlayedDate_Proxy( + IITTrack * This, + /* [in] */ DATE playedDate); + + +void __RPC_STUB IITTrack_put_PlayedDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_PlayOrderIndex_Proxy( + IITTrack * This, + /* [retval][out] */ long *index); + + +void __RPC_STUB IITTrack_get_PlayOrderIndex_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Rating_Proxy( + IITTrack * This, + /* [retval][out] */ long *rating); + + +void __RPC_STUB IITTrack_get_Rating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Rating_Proxy( + IITTrack * This, + /* [in] */ long rating); + + +void __RPC_STUB IITTrack_put_Rating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_SampleRate_Proxy( + IITTrack * This, + /* [retval][out] */ long *sampleRate); + + +void __RPC_STUB IITTrack_get_SampleRate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Size_Proxy( + IITTrack * This, + /* [retval][out] */ long *size); + + +void __RPC_STUB IITTrack_get_Size_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Start_Proxy( + IITTrack * This, + /* [retval][out] */ long *start); + + +void __RPC_STUB IITTrack_get_Start_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Start_Proxy( + IITTrack * This, + /* [in] */ long start); + + +void __RPC_STUB IITTrack_put_Start_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Time_Proxy( + IITTrack * This, + /* [retval][out] */ BSTR *time); + + +void __RPC_STUB IITTrack_get_Time_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_TrackCount_Proxy( + IITTrack * This, + /* [retval][out] */ long *trackCount); + + +void __RPC_STUB IITTrack_get_TrackCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_TrackCount_Proxy( + IITTrack * This, + /* [in] */ long trackCount); + + +void __RPC_STUB IITTrack_put_TrackCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_TrackNumber_Proxy( + IITTrack * This, + /* [retval][out] */ long *trackNumber); + + +void __RPC_STUB IITTrack_get_TrackNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_TrackNumber_Proxy( + IITTrack * This, + /* [in] */ long trackNumber); + + +void __RPC_STUB IITTrack_put_TrackNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_VolumeAdjustment_Proxy( + IITTrack * This, + /* [retval][out] */ long *volumeAdjustment); + + +void __RPC_STUB IITTrack_get_VolumeAdjustment_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_VolumeAdjustment_Proxy( + IITTrack * This, + /* [in] */ long volumeAdjustment); + + +void __RPC_STUB IITTrack_put_VolumeAdjustment_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Year_Proxy( + IITTrack * This, + /* [retval][out] */ long *year); + + +void __RPC_STUB IITTrack_get_Year_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITTrack_put_Year_Proxy( + IITTrack * This, + /* [in] */ long year); + + +void __RPC_STUB IITTrack_put_Year_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrack_get_Artwork_Proxy( + IITTrack * This, + /* [retval][out] */ IITArtworkCollection **iArtworkCollection); + + +void __RPC_STUB IITTrack_get_Artwork_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITTrack_INTERFACE_DEFINED__ */ + + +#ifndef __IITTrackCollection_INTERFACE_DEFINED__ +#define __IITTrackCollection_INTERFACE_DEFINED__ + +/* interface IITTrackCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITTrackCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("755D76F1-6B85-4ce4-8F5F-F88D9743DCD8") + IITTrackCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPlayOrder( + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITTrack **iTrack) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPersistentID( + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITTrack **iTrack) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITTrackCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITTrackCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITTrackCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITTrackCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITTrackCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITTrackCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITTrackCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITTrackCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITTrackCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITTrackCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPlayOrder )( + IITTrackCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITTrackCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITTrack **iTrack); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITTrackCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPersistentID )( + IITTrackCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITTrack **iTrack); + + END_INTERFACE + } IITTrackCollectionVtbl; + + interface IITTrackCollection + { + CONST_VTBL struct IITTrackCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITTrackCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITTrackCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITTrackCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITTrackCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITTrackCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITTrackCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITTrackCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITTrackCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITTrackCollection_get_Item(This,index,iTrack) \ + (This)->lpVtbl -> get_Item(This,index,iTrack) + +#define IITTrackCollection_get_ItemByPlayOrder(This,index,iTrack) \ + (This)->lpVtbl -> get_ItemByPlayOrder(This,index,iTrack) + +#define IITTrackCollection_get_ItemByName(This,name,iTrack) \ + (This)->lpVtbl -> get_ItemByName(This,name,iTrack) + +#define IITTrackCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#define IITTrackCollection_get_ItemByPersistentID(This,highID,lowID,iTrack) \ + (This)->lpVtbl -> get_ItemByPersistentID(This,highID,lowID,iTrack) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_Count_Proxy( + IITTrackCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITTrackCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_Item_Proxy( + IITTrackCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack); + + +void __RPC_STUB IITTrackCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_ItemByPlayOrder_Proxy( + IITTrackCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITTrack **iTrack); + + +void __RPC_STUB IITTrackCollection_get_ItemByPlayOrder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_ItemByName_Proxy( + IITTrackCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITTrack **iTrack); + + +void __RPC_STUB IITTrackCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get__NewEnum_Proxy( + IITTrackCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITTrackCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITTrackCollection_get_ItemByPersistentID_Proxy( + IITTrackCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITTrack **iTrack); + + +void __RPC_STUB IITTrackCollection_get_ItemByPersistentID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITTrackCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITVisual_INTERFACE_DEFINED__ +#define __IITVisual_INTERFACE_DEFINED__ + +/* interface IITVisual */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITVisual; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("340F3315-ED72-4c09-9ACF-21EB4BDF9931") + IITVisual : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITVisualVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITVisual * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITVisual * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITVisual * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITVisual * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITVisual * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITVisual * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITVisual * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITVisual * This, + /* [retval][out] */ BSTR *name); + + END_INTERFACE + } IITVisualVtbl; + + interface IITVisual + { + CONST_VTBL struct IITVisualVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITVisual_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITVisual_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITVisual_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITVisual_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITVisual_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITVisual_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITVisual_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITVisual_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITVisual_get_Name_Proxy( + IITVisual * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITVisual_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITVisual_INTERFACE_DEFINED__ */ + + +#ifndef __IITVisualCollection_INTERFACE_DEFINED__ +#define __IITVisualCollection_INTERFACE_DEFINED__ + +/* interface IITVisualCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITVisualCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("88A4CCDD-114F-4043-B69B-84D4E6274957") + IITVisualCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITVisual **iVisual) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITVisual **iVisual) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITVisualCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITVisualCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITVisualCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITVisualCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITVisualCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITVisualCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITVisualCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITVisualCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITVisualCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITVisualCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITVisual **iVisual); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITVisualCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITVisual **iVisual); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITVisualCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + END_INTERFACE + } IITVisualCollectionVtbl; + + interface IITVisualCollection + { + CONST_VTBL struct IITVisualCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITVisualCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITVisualCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITVisualCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITVisualCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITVisualCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITVisualCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITVisualCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITVisualCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITVisualCollection_get_Item(This,index,iVisual) \ + (This)->lpVtbl -> get_Item(This,index,iVisual) + +#define IITVisualCollection_get_ItemByName(This,name,iVisual) \ + (This)->lpVtbl -> get_ItemByName(This,name,iVisual) + +#define IITVisualCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get_Count_Proxy( + IITVisualCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITVisualCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get_Item_Proxy( + IITVisualCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITVisual **iVisual); + + +void __RPC_STUB IITVisualCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get_ItemByName_Proxy( + IITVisualCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITVisual **iVisual); + + +void __RPC_STUB IITVisualCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITVisualCollection_get__NewEnum_Proxy( + IITVisualCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITVisualCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITVisualCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITWindow_INTERFACE_DEFINED__ +#define __IITWindow_INTERFACE_DEFINED__ + +/* interface IITWindow */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITWindow; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("370D7BE0-3A89-4a42-B902-C75FC138BE09") + IITWindow : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Kind( + /* [retval][out] */ ITWindowKind *kind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Visible( + /* [retval][out] */ VARIANT_BOOL *isVisible) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Visible( + /* [in] */ VARIANT_BOOL shouldBeVisible) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Resizable( + /* [retval][out] */ VARIANT_BOOL *isResizable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Minimized( + /* [retval][out] */ VARIANT_BOOL *isMinimized) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Minimized( + /* [in] */ VARIANT_BOOL shouldBeMinimized) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Maximizable( + /* [retval][out] */ VARIANT_BOOL *isMaximizable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Maximized( + /* [retval][out] */ VARIANT_BOOL *isMaximized) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Maximized( + /* [in] */ VARIANT_BOOL shouldBeMaximized) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Zoomable( + /* [retval][out] */ VARIANT_BOOL *isZoomable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Zoomed( + /* [retval][out] */ VARIANT_BOOL *isZoomed) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Zoomed( + /* [in] */ VARIANT_BOOL shouldBeZoomed) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Top( + /* [retval][out] */ long *top) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Top( + /* [in] */ long top) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Left( + /* [retval][out] */ long *left) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Left( + /* [in] */ long left) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Bottom( + /* [retval][out] */ long *bottom) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Bottom( + /* [in] */ long bottom) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Right( + /* [retval][out] */ long *right) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Right( + /* [in] */ long right) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Width( + /* [retval][out] */ long *width) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Width( + /* [in] */ long width) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Height( + /* [retval][out] */ long *height) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Height( + /* [in] */ long height) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITWindowVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITWindow * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITWindow * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITWindow * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITWindow * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITWindow * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITWindow * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITWindow * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITWindow * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITWindow * This, + /* [retval][out] */ ITWindowKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Visible )( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Resizable )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isResizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Minimized )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMinimized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Minimized )( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMinimized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximizable )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximized )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Maximized )( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMaximized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomable )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomed )( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomed); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Zoomed )( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeZoomed); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )( + IITWindow * This, + /* [retval][out] */ long *top); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Top )( + IITWindow * This, + /* [in] */ long top); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )( + IITWindow * This, + /* [retval][out] */ long *left); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Left )( + IITWindow * This, + /* [in] */ long left); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bottom )( + IITWindow * This, + /* [retval][out] */ long *bottom); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bottom )( + IITWindow * This, + /* [in] */ long bottom); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Right )( + IITWindow * This, + /* [retval][out] */ long *right); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Right )( + IITWindow * This, + /* [in] */ long right); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )( + IITWindow * This, + /* [retval][out] */ long *width); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Width )( + IITWindow * This, + /* [in] */ long width); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )( + IITWindow * This, + /* [retval][out] */ long *height); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Height )( + IITWindow * This, + /* [in] */ long height); + + END_INTERFACE + } IITWindowVtbl; + + interface IITWindow + { + CONST_VTBL struct IITWindowVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITWindow_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITWindow_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITWindow_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITWindow_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITWindow_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITWindow_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITWindow_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITWindow_put_Visible(This,shouldBeVisible) \ + (This)->lpVtbl -> put_Visible(This,shouldBeVisible) + +#define IITWindow_get_Resizable(This,isResizable) \ + (This)->lpVtbl -> get_Resizable(This,isResizable) + +#define IITWindow_get_Minimized(This,isMinimized) \ + (This)->lpVtbl -> get_Minimized(This,isMinimized) + +#define IITWindow_put_Minimized(This,shouldBeMinimized) \ + (This)->lpVtbl -> put_Minimized(This,shouldBeMinimized) + +#define IITWindow_get_Maximizable(This,isMaximizable) \ + (This)->lpVtbl -> get_Maximizable(This,isMaximizable) + +#define IITWindow_get_Maximized(This,isMaximized) \ + (This)->lpVtbl -> get_Maximized(This,isMaximized) + +#define IITWindow_put_Maximized(This,shouldBeMaximized) \ + (This)->lpVtbl -> put_Maximized(This,shouldBeMaximized) + +#define IITWindow_get_Zoomable(This,isZoomable) \ + (This)->lpVtbl -> get_Zoomable(This,isZoomable) + +#define IITWindow_get_Zoomed(This,isZoomed) \ + (This)->lpVtbl -> get_Zoomed(This,isZoomed) + +#define IITWindow_put_Zoomed(This,shouldBeZoomed) \ + (This)->lpVtbl -> put_Zoomed(This,shouldBeZoomed) + +#define IITWindow_get_Top(This,top) \ + (This)->lpVtbl -> get_Top(This,top) + +#define IITWindow_put_Top(This,top) \ + (This)->lpVtbl -> put_Top(This,top) + +#define IITWindow_get_Left(This,left) \ + (This)->lpVtbl -> get_Left(This,left) + +#define IITWindow_put_Left(This,left) \ + (This)->lpVtbl -> put_Left(This,left) + +#define IITWindow_get_Bottom(This,bottom) \ + (This)->lpVtbl -> get_Bottom(This,bottom) + +#define IITWindow_put_Bottom(This,bottom) \ + (This)->lpVtbl -> put_Bottom(This,bottom) + +#define IITWindow_get_Right(This,right) \ + (This)->lpVtbl -> get_Right(This,right) + +#define IITWindow_put_Right(This,right) \ + (This)->lpVtbl -> put_Right(This,right) + +#define IITWindow_get_Width(This,width) \ + (This)->lpVtbl -> get_Width(This,width) + +#define IITWindow_put_Width(This,width) \ + (This)->lpVtbl -> put_Width(This,width) + +#define IITWindow_get_Height(This,height) \ + (This)->lpVtbl -> get_Height(This,height) + +#define IITWindow_put_Height(This,height) \ + (This)->lpVtbl -> put_Height(This,height) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Name_Proxy( + IITWindow * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITWindow_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Kind_Proxy( + IITWindow * This, + /* [retval][out] */ ITWindowKind *kind); + + +void __RPC_STUB IITWindow_get_Kind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Visible_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + +void __RPC_STUB IITWindow_get_Visible_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Visible_Proxy( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeVisible); + + +void __RPC_STUB IITWindow_put_Visible_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Resizable_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isResizable); + + +void __RPC_STUB IITWindow_get_Resizable_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Minimized_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMinimized); + + +void __RPC_STUB IITWindow_get_Minimized_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Minimized_Proxy( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMinimized); + + +void __RPC_STUB IITWindow_put_Minimized_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Maximizable_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximizable); + + +void __RPC_STUB IITWindow_get_Maximizable_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Maximized_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximized); + + +void __RPC_STUB IITWindow_get_Maximized_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Maximized_Proxy( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMaximized); + + +void __RPC_STUB IITWindow_put_Maximized_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Zoomable_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomable); + + +void __RPC_STUB IITWindow_get_Zoomable_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Zoomed_Proxy( + IITWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomed); + + +void __RPC_STUB IITWindow_get_Zoomed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Zoomed_Proxy( + IITWindow * This, + /* [in] */ VARIANT_BOOL shouldBeZoomed); + + +void __RPC_STUB IITWindow_put_Zoomed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Top_Proxy( + IITWindow * This, + /* [retval][out] */ long *top); + + +void __RPC_STUB IITWindow_get_Top_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Top_Proxy( + IITWindow * This, + /* [in] */ long top); + + +void __RPC_STUB IITWindow_put_Top_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Left_Proxy( + IITWindow * This, + /* [retval][out] */ long *left); + + +void __RPC_STUB IITWindow_get_Left_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Left_Proxy( + IITWindow * This, + /* [in] */ long left); + + +void __RPC_STUB IITWindow_put_Left_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Bottom_Proxy( + IITWindow * This, + /* [retval][out] */ long *bottom); + + +void __RPC_STUB IITWindow_get_Bottom_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Bottom_Proxy( + IITWindow * This, + /* [in] */ long bottom); + + +void __RPC_STUB IITWindow_put_Bottom_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Right_Proxy( + IITWindow * This, + /* [retval][out] */ long *right); + + +void __RPC_STUB IITWindow_get_Right_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Right_Proxy( + IITWindow * This, + /* [in] */ long right); + + +void __RPC_STUB IITWindow_put_Right_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Width_Proxy( + IITWindow * This, + /* [retval][out] */ long *width); + + +void __RPC_STUB IITWindow_get_Width_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Width_Proxy( + IITWindow * This, + /* [in] */ long width); + + +void __RPC_STUB IITWindow_put_Width_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindow_get_Height_Proxy( + IITWindow * This, + /* [retval][out] */ long *height); + + +void __RPC_STUB IITWindow_get_Height_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITWindow_put_Height_Proxy( + IITWindow * This, + /* [in] */ long height); + + +void __RPC_STUB IITWindow_put_Height_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITWindow_INTERFACE_DEFINED__ */ + + +#ifndef __IITBrowserWindow_INTERFACE_DEFINED__ +#define __IITBrowserWindow_INTERFACE_DEFINED__ + +/* interface IITBrowserWindow */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITBrowserWindow; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C999F455-C4D5-4aa4-8277-F99753699974") + IITBrowserWindow : public IITWindow + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_MiniPlayer( + /* [retval][out] */ VARIANT_BOOL *isMiniPlayer) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_MiniPlayer( + /* [in] */ VARIANT_BOOL shouldBeMiniPlayer) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedTracks( + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedPlaylist( + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SelectedPlaylist( + /* [in] */ VARIANT *iPlaylist) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITBrowserWindowVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITBrowserWindow * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITBrowserWindow * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITBrowserWindow * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITBrowserWindow * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITBrowserWindow * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITBrowserWindow * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITBrowserWindow * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITBrowserWindow * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITBrowserWindow * This, + /* [retval][out] */ ITWindowKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Visible )( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Resizable )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isResizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Minimized )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMinimized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Minimized )( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMinimized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximizable )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximized )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Maximized )( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMaximized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomable )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomed )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomed); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Zoomed )( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeZoomed); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )( + IITBrowserWindow * This, + /* [retval][out] */ long *top); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Top )( + IITBrowserWindow * This, + /* [in] */ long top); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )( + IITBrowserWindow * This, + /* [retval][out] */ long *left); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Left )( + IITBrowserWindow * This, + /* [in] */ long left); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bottom )( + IITBrowserWindow * This, + /* [retval][out] */ long *bottom); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bottom )( + IITBrowserWindow * This, + /* [in] */ long bottom); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Right )( + IITBrowserWindow * This, + /* [retval][out] */ long *right); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Right )( + IITBrowserWindow * This, + /* [in] */ long right); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )( + IITBrowserWindow * This, + /* [retval][out] */ long *width); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Width )( + IITBrowserWindow * This, + /* [in] */ long width); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )( + IITBrowserWindow * This, + /* [retval][out] */ long *height); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Height )( + IITBrowserWindow * This, + /* [in] */ long height); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MiniPlayer )( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMiniPlayer); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_MiniPlayer )( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMiniPlayer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedTracks )( + IITBrowserWindow * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedPlaylist )( + IITBrowserWindow * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SelectedPlaylist )( + IITBrowserWindow * This, + /* [in] */ VARIANT *iPlaylist); + + END_INTERFACE + } IITBrowserWindowVtbl; + + interface IITBrowserWindow + { + CONST_VTBL struct IITBrowserWindowVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITBrowserWindow_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITBrowserWindow_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITBrowserWindow_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITBrowserWindow_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITBrowserWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITBrowserWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITBrowserWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITBrowserWindow_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITBrowserWindow_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITBrowserWindow_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITBrowserWindow_put_Visible(This,shouldBeVisible) \ + (This)->lpVtbl -> put_Visible(This,shouldBeVisible) + +#define IITBrowserWindow_get_Resizable(This,isResizable) \ + (This)->lpVtbl -> get_Resizable(This,isResizable) + +#define IITBrowserWindow_get_Minimized(This,isMinimized) \ + (This)->lpVtbl -> get_Minimized(This,isMinimized) + +#define IITBrowserWindow_put_Minimized(This,shouldBeMinimized) \ + (This)->lpVtbl -> put_Minimized(This,shouldBeMinimized) + +#define IITBrowserWindow_get_Maximizable(This,isMaximizable) \ + (This)->lpVtbl -> get_Maximizable(This,isMaximizable) + +#define IITBrowserWindow_get_Maximized(This,isMaximized) \ + (This)->lpVtbl -> get_Maximized(This,isMaximized) + +#define IITBrowserWindow_put_Maximized(This,shouldBeMaximized) \ + (This)->lpVtbl -> put_Maximized(This,shouldBeMaximized) + +#define IITBrowserWindow_get_Zoomable(This,isZoomable) \ + (This)->lpVtbl -> get_Zoomable(This,isZoomable) + +#define IITBrowserWindow_get_Zoomed(This,isZoomed) \ + (This)->lpVtbl -> get_Zoomed(This,isZoomed) + +#define IITBrowserWindow_put_Zoomed(This,shouldBeZoomed) \ + (This)->lpVtbl -> put_Zoomed(This,shouldBeZoomed) + +#define IITBrowserWindow_get_Top(This,top) \ + (This)->lpVtbl -> get_Top(This,top) + +#define IITBrowserWindow_put_Top(This,top) \ + (This)->lpVtbl -> put_Top(This,top) + +#define IITBrowserWindow_get_Left(This,left) \ + (This)->lpVtbl -> get_Left(This,left) + +#define IITBrowserWindow_put_Left(This,left) \ + (This)->lpVtbl -> put_Left(This,left) + +#define IITBrowserWindow_get_Bottom(This,bottom) \ + (This)->lpVtbl -> get_Bottom(This,bottom) + +#define IITBrowserWindow_put_Bottom(This,bottom) \ + (This)->lpVtbl -> put_Bottom(This,bottom) + +#define IITBrowserWindow_get_Right(This,right) \ + (This)->lpVtbl -> get_Right(This,right) + +#define IITBrowserWindow_put_Right(This,right) \ + (This)->lpVtbl -> put_Right(This,right) + +#define IITBrowserWindow_get_Width(This,width) \ + (This)->lpVtbl -> get_Width(This,width) + +#define IITBrowserWindow_put_Width(This,width) \ + (This)->lpVtbl -> put_Width(This,width) + +#define IITBrowserWindow_get_Height(This,height) \ + (This)->lpVtbl -> get_Height(This,height) + +#define IITBrowserWindow_put_Height(This,height) \ + (This)->lpVtbl -> put_Height(This,height) + + +#define IITBrowserWindow_get_MiniPlayer(This,isMiniPlayer) \ + (This)->lpVtbl -> get_MiniPlayer(This,isMiniPlayer) + +#define IITBrowserWindow_put_MiniPlayer(This,shouldBeMiniPlayer) \ + (This)->lpVtbl -> put_MiniPlayer(This,shouldBeMiniPlayer) + +#define IITBrowserWindow_get_SelectedTracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_SelectedTracks(This,iTrackCollection) + +#define IITBrowserWindow_get_SelectedPlaylist(This,iPlaylist) \ + (This)->lpVtbl -> get_SelectedPlaylist(This,iPlaylist) + +#define IITBrowserWindow_put_SelectedPlaylist(This,iPlaylist) \ + (This)->lpVtbl -> put_SelectedPlaylist(This,iPlaylist) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_get_MiniPlayer_Proxy( + IITBrowserWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMiniPlayer); + + +void __RPC_STUB IITBrowserWindow_get_MiniPlayer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_put_MiniPlayer_Proxy( + IITBrowserWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMiniPlayer); + + +void __RPC_STUB IITBrowserWindow_put_MiniPlayer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_get_SelectedTracks_Proxy( + IITBrowserWindow * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IITBrowserWindow_get_SelectedTracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_get_SelectedPlaylist_Proxy( + IITBrowserWindow * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITBrowserWindow_get_SelectedPlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITBrowserWindow_put_SelectedPlaylist_Proxy( + IITBrowserWindow * This, + /* [in] */ VARIANT *iPlaylist); + + +void __RPC_STUB IITBrowserWindow_put_SelectedPlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITBrowserWindow_INTERFACE_DEFINED__ */ + + +#ifndef __IITWindowCollection_INTERFACE_DEFINED__ +#define __IITWindowCollection_INTERFACE_DEFINED__ + +/* interface IITWindowCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITWindowCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3D8DE381-6C0E-481f-A865-E2385F59FA43") + IITWindowCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITWindow **iWindow) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITWindow **iWindow) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITWindowCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITWindowCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITWindowCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITWindowCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITWindowCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITWindowCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITWindowCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITWindowCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITWindowCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITWindowCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITWindow **iWindow); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITWindowCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITWindow **iWindow); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITWindowCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + END_INTERFACE + } IITWindowCollectionVtbl; + + interface IITWindowCollection + { + CONST_VTBL struct IITWindowCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITWindowCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITWindowCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITWindowCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITWindowCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITWindowCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITWindowCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITWindowCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITWindowCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITWindowCollection_get_Item(This,index,iWindow) \ + (This)->lpVtbl -> get_Item(This,index,iWindow) + +#define IITWindowCollection_get_ItemByName(This,name,iWindow) \ + (This)->lpVtbl -> get_ItemByName(This,name,iWindow) + +#define IITWindowCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get_Count_Proxy( + IITWindowCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITWindowCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get_Item_Proxy( + IITWindowCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITWindow **iWindow); + + +void __RPC_STUB IITWindowCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get_ItemByName_Proxy( + IITWindowCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITWindow **iWindow); + + +void __RPC_STUB IITWindowCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITWindowCollection_get__NewEnum_Proxy( + IITWindowCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITWindowCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITWindowCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IiTunes_INTERFACE_DEFINED__ +#define __IiTunes_INTERFACE_DEFINED__ + +/* interface IiTunes */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + + + +EXTERN_C const IID IID_IiTunes; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9DD6680B-3EDC-40db-A771-E6FE4832E34A") + IiTunes : public IDispatch + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE BackTrack( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE FastForward( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE NextTrack( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Pause( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Play( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayFile( + /* [in] */ BSTR filePath) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayPause( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PreviousTrack( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Resume( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Rewind( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Stop( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFile( + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFiles( + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTrack( + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTracks( + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CheckVersion( + /* [in] */ long majorVersion, + /* [in] */ long minorVersion, + /* [retval][out] */ VARIANT_BOOL *isCompatible) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetITObjectByID( + /* [in] */ long sourceID, + /* [in] */ long playlistID, + /* [in] */ long trackID, + /* [in] */ long databaseID, + /* [retval][out] */ IITObject **iObject) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePlaylist( + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OpenURL( + /* [in] */ BSTR url) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GotoMusicStoreHomePage( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdateIPod( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Authorize( + /* [in] */ long numElems, + /* [size_is][in] */ VARIANT data[ ], + /* [size_is][in] */ BSTR names[ ]) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Quit( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Sources( + /* [retval][out] */ IITSourceCollection **iSourceCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Encoders( + /* [retval][out] */ IITEncoderCollection **iEncoderCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQPresets( + /* [retval][out] */ IITEQPresetCollection **iEQPresetCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Visuals( + /* [retval][out] */ IITVisualCollection **iVisualCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Windows( + /* [retval][out] */ IITWindowCollection **iWindowCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SoundVolume( + /* [retval][out] */ long *volume) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SoundVolume( + /* [in] */ long volume) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Mute( + /* [retval][out] */ VARIANT_BOOL *isMuted) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Mute( + /* [in] */ VARIANT_BOOL shouldMute) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayerState( + /* [retval][out] */ ITPlayerState *playerState) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlayerPosition( + /* [retval][out] */ long *playerPos) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PlayerPosition( + /* [in] */ long playerPos) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentEncoder( + /* [retval][out] */ IITEncoder **iEncoder) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentEncoder( + /* [in] */ IITEncoder *iEncoder) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VisualsEnabled( + /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VisualsEnabled( + /* [in] */ VARIANT_BOOL shouldEnable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_FullScreenVisuals( + /* [retval][out] */ VARIANT_BOOL *isFullScreen) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_FullScreenVisuals( + /* [in] */ VARIANT_BOOL shouldUseFullScreen) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VisualSize( + /* [retval][out] */ ITVisualSize *visualSize) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VisualSize( + /* [in] */ ITVisualSize visualSize) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentVisual( + /* [retval][out] */ IITVisual **iVisual) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentVisual( + /* [in] */ IITVisual *iVisual) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQEnabled( + /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EQEnabled( + /* [in] */ VARIANT_BOOL shouldEnable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentEQPreset( + /* [retval][out] */ IITEQPreset **iEQPreset) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentEQPreset( + /* [in] */ IITEQPreset *iEQPreset) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentStreamTitle( + /* [retval][out] */ BSTR *streamTitle) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentStreamURL( + /* [retval][out] */ BSTR *streamURL) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BrowserWindow( + /* [retval][out] */ IITBrowserWindow **iBrowserWindow) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EQWindow( + /* [retval][out] */ IITWindow **iEQWindow) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LibrarySource( + /* [retval][out] */ IITSource **iLibrarySource) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LibraryPlaylist( + /* [retval][out] */ IITLibraryPlaylist **iLibraryPlaylist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentTrack( + /* [retval][out] */ IITTrack **iTrack) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentPlaylist( + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedTracks( + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Version( + /* [retval][out] */ BSTR *version) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetOptions( + /* [in] */ long options) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFile2( + /* [in] */ BSTR filePath, + /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertFiles2( + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTrack2( + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConvertTracks2( + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AppCommandMessageProcessingEnabled( + /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AppCommandMessageProcessingEnabled( + /* [in] */ VARIANT_BOOL shouldEnable) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ForceToForegroundOnDialog( + /* [retval][out] */ VARIANT_BOOL *forceToForegroundOnDialog) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_ForceToForegroundOnDialog( + /* [in] */ VARIANT_BOOL forceToForegroundOnDialog) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateEQPreset( + /* [in] */ BSTR eqPresetName, + /* [retval][out] */ IITEQPreset **iEQPreset) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreatePlaylistInSource( + /* [in] */ BSTR playlistName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetPlayerButtonsState( + /* [out] */ VARIANT_BOOL *previousEnabled, + /* [out] */ ITPlayButtonState *playPauseStopState, + /* [out] */ VARIANT_BOOL *nextEnabled) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE PlayerButtonClicked( + /* [in] */ ITPlayerButton playerButton, + /* [in] */ long playerButtonModifierKeys) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CanSetShuffle( + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetShuffle) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_CanSetSongRepeat( + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetSongRepeat) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ConvertOperationStatus( + /* [retval][out] */ IITConvertOperationStatus **iStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SubscribeToPodcast( + /* [in] */ BSTR url) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdatePodcastFeeds( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateFolder( + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateFolderInSource( + /* [in] */ BSTR folderName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iFolder) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SoundVolumeControlEnabled( + /* [retval][out] */ VARIANT_BOOL *isEnabled) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LibraryXMLPath( + /* [retval][out] */ BSTR *filePath) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ITObjectPersistentIDHigh( + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *highID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ITObjectPersistentIDLow( + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *lowID) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetITObjectPersistentIDs( + /* [in] */ VARIANT *iObject, + /* [out] */ long *highID, + /* [out] */ long *lowID) = 0; + + }; + +#else /* C style interface */ + + typedef struct IiTunesVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IiTunes * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IiTunes * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IiTunes * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IiTunes * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IiTunes * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IiTunes * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IiTunes * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *BackTrack )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *FastForward )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *NextTrack )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Pause )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFile )( + IiTunes * This, + /* [in] */ BSTR filePath); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayPause )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PreviousTrack )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Resume )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Rewind )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Stop )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFile )( + IiTunes * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFiles )( + IiTunes * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTrack )( + IiTunes * This, + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTracks )( + IiTunes * This, + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CheckVersion )( + IiTunes * This, + /* [in] */ long majorVersion, + /* [in] */ long minorVersion, + /* [retval][out] */ VARIANT_BOOL *isCompatible); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectByID )( + IiTunes * This, + /* [in] */ long sourceID, + /* [in] */ long playlistID, + /* [in] */ long trackID, + /* [in] */ long databaseID, + /* [retval][out] */ IITObject **iObject); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreatePlaylist )( + IiTunes * This, + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *OpenURL )( + IiTunes * This, + /* [in] */ BSTR url); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GotoMusicStoreHomePage )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdateIPod )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Authorize )( + IiTunes * This, + /* [in] */ long numElems, + /* [size_is][in] */ VARIANT data[ ], + /* [size_is][in] */ BSTR names[ ]); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Quit )( + IiTunes * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Sources )( + IiTunes * This, + /* [retval][out] */ IITSourceCollection **iSourceCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Encoders )( + IiTunes * This, + /* [retval][out] */ IITEncoderCollection **iEncoderCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQPresets )( + IiTunes * This, + /* [retval][out] */ IITEQPresetCollection **iEQPresetCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visuals )( + IiTunes * This, + /* [retval][out] */ IITVisualCollection **iVisualCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Windows )( + IiTunes * This, + /* [retval][out] */ IITWindowCollection **iWindowCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SoundVolume )( + IiTunes * This, + /* [retval][out] */ long *volume); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SoundVolume )( + IiTunes * This, + /* [in] */ long volume); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Mute )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isMuted); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Mute )( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldMute); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayerState )( + IiTunes * This, + /* [retval][out] */ ITPlayerState *playerState); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayerPosition )( + IiTunes * This, + /* [retval][out] */ long *playerPos); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayerPosition )( + IiTunes * This, + /* [in] */ long playerPos); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentEncoder )( + IiTunes * This, + /* [retval][out] */ IITEncoder **iEncoder); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_CurrentEncoder )( + IiTunes * This, + /* [in] */ IITEncoder *iEncoder); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VisualsEnabled )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VisualsEnabled )( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_FullScreenVisuals )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isFullScreen); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_FullScreenVisuals )( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldUseFullScreen); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VisualSize )( + IiTunes * This, + /* [retval][out] */ ITVisualSize *visualSize); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VisualSize )( + IiTunes * This, + /* [in] */ ITVisualSize visualSize); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentVisual )( + IiTunes * This, + /* [retval][out] */ IITVisual **iVisual); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_CurrentVisual )( + IiTunes * This, + /* [in] */ IITVisual *iVisual); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQEnabled )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQEnabled )( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentEQPreset )( + IiTunes * This, + /* [retval][out] */ IITEQPreset **iEQPreset); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_CurrentEQPreset )( + IiTunes * This, + /* [in] */ IITEQPreset *iEQPreset); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentStreamTitle )( + IiTunes * This, + /* [retval][out] */ BSTR *streamTitle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentStreamURL )( + IiTunes * This, + /* [retval][out] */ BSTR *streamURL); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BrowserWindow )( + IiTunes * This, + /* [retval][out] */ IITBrowserWindow **iBrowserWindow); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQWindow )( + IiTunes * This, + /* [retval][out] */ IITWindow **iEQWindow); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LibrarySource )( + IiTunes * This, + /* [retval][out] */ IITSource **iLibrarySource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LibraryPlaylist )( + IiTunes * This, + /* [retval][out] */ IITLibraryPlaylist **iLibraryPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentTrack )( + IiTunes * This, + /* [retval][out] */ IITTrack **iTrack); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentPlaylist )( + IiTunes * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedTracks )( + IiTunes * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Version )( + IiTunes * This, + /* [retval][out] */ BSTR *version); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetOptions )( + IiTunes * This, + /* [in] */ long options); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFile2 )( + IiTunes * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertFiles2 )( + IiTunes * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTrack2 )( + IiTunes * This, + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConvertTracks2 )( + IiTunes * This, + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AppCommandMessageProcessingEnabled )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AppCommandMessageProcessingEnabled )( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ForceToForegroundOnDialog )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *forceToForegroundOnDialog); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ForceToForegroundOnDialog )( + IiTunes * This, + /* [in] */ VARIANT_BOOL forceToForegroundOnDialog); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateEQPreset )( + IiTunes * This, + /* [in] */ BSTR eqPresetName, + /* [retval][out] */ IITEQPreset **iEQPreset); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreatePlaylistInSource )( + IiTunes * This, + /* [in] */ BSTR playlistName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetPlayerButtonsState )( + IiTunes * This, + /* [out] */ VARIANT_BOOL *previousEnabled, + /* [out] */ ITPlayButtonState *playPauseStopState, + /* [out] */ VARIANT_BOOL *nextEnabled); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayerButtonClicked )( + IiTunes * This, + /* [in] */ ITPlayerButton playerButton, + /* [in] */ long playerButtonModifierKeys); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanSetShuffle )( + IiTunes * This, + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_CanSetSongRepeat )( + IiTunes * This, + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetSongRepeat); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ConvertOperationStatus )( + IiTunes * This, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SubscribeToPodcast )( + IiTunes * This, + /* [in] */ BSTR url); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdatePodcastFeeds )( + IiTunes * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateFolder )( + IiTunes * This, + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateFolderInSource )( + IiTunes * This, + /* [in] */ BSTR folderName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iFolder); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SoundVolumeControlEnabled )( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LibraryXMLPath )( + IiTunes * This, + /* [retval][out] */ BSTR *filePath); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ITObjectPersistentIDHigh )( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *highID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ITObjectPersistentIDLow )( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *lowID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectPersistentIDs )( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [out] */ long *highID, + /* [out] */ long *lowID); + + END_INTERFACE + } IiTunesVtbl; + + interface IiTunes + { + CONST_VTBL struct IiTunesVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IiTunes_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IiTunes_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IiTunes_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IiTunes_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IiTunes_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IiTunes_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IiTunes_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IiTunes_BackTrack(This) \ + (This)->lpVtbl -> BackTrack(This) + +#define IiTunes_FastForward(This) \ + (This)->lpVtbl -> FastForward(This) + +#define IiTunes_NextTrack(This) \ + (This)->lpVtbl -> NextTrack(This) + +#define IiTunes_Pause(This) \ + (This)->lpVtbl -> Pause(This) + +#define IiTunes_Play(This) \ + (This)->lpVtbl -> Play(This) + +#define IiTunes_PlayFile(This,filePath) \ + (This)->lpVtbl -> PlayFile(This,filePath) + +#define IiTunes_PlayPause(This) \ + (This)->lpVtbl -> PlayPause(This) + +#define IiTunes_PreviousTrack(This) \ + (This)->lpVtbl -> PreviousTrack(This) + +#define IiTunes_Resume(This) \ + (This)->lpVtbl -> Resume(This) + +#define IiTunes_Rewind(This) \ + (This)->lpVtbl -> Rewind(This) + +#define IiTunes_Stop(This) \ + (This)->lpVtbl -> Stop(This) + +#define IiTunes_ConvertFile(This,filePath,iStatus) \ + (This)->lpVtbl -> ConvertFile(This,filePath,iStatus) + +#define IiTunes_ConvertFiles(This,filePaths,iStatus) \ + (This)->lpVtbl -> ConvertFiles(This,filePaths,iStatus) + +#define IiTunes_ConvertTrack(This,iTrackToConvert,iStatus) \ + (This)->lpVtbl -> ConvertTrack(This,iTrackToConvert,iStatus) + +#define IiTunes_ConvertTracks(This,iTracksToConvert,iStatus) \ + (This)->lpVtbl -> ConvertTracks(This,iTracksToConvert,iStatus) + +#define IiTunes_CheckVersion(This,majorVersion,minorVersion,isCompatible) \ + (This)->lpVtbl -> CheckVersion(This,majorVersion,minorVersion,isCompatible) + +#define IiTunes_GetITObjectByID(This,sourceID,playlistID,trackID,databaseID,iObject) \ + (This)->lpVtbl -> GetITObjectByID(This,sourceID,playlistID,trackID,databaseID,iObject) + +#define IiTunes_CreatePlaylist(This,playlistName,iPlaylist) \ + (This)->lpVtbl -> CreatePlaylist(This,playlistName,iPlaylist) + +#define IiTunes_OpenURL(This,url) \ + (This)->lpVtbl -> OpenURL(This,url) + +#define IiTunes_GotoMusicStoreHomePage(This) \ + (This)->lpVtbl -> GotoMusicStoreHomePage(This) + +#define IiTunes_UpdateIPod(This) \ + (This)->lpVtbl -> UpdateIPod(This) + +#define IiTunes_Authorize(This,numElems,data,names) \ + (This)->lpVtbl -> Authorize(This,numElems,data,names) + +#define IiTunes_Quit(This) \ + (This)->lpVtbl -> Quit(This) + +#define IiTunes_get_Sources(This,iSourceCollection) \ + (This)->lpVtbl -> get_Sources(This,iSourceCollection) + +#define IiTunes_get_Encoders(This,iEncoderCollection) \ + (This)->lpVtbl -> get_Encoders(This,iEncoderCollection) + +#define IiTunes_get_EQPresets(This,iEQPresetCollection) \ + (This)->lpVtbl -> get_EQPresets(This,iEQPresetCollection) + +#define IiTunes_get_Visuals(This,iVisualCollection) \ + (This)->lpVtbl -> get_Visuals(This,iVisualCollection) + +#define IiTunes_get_Windows(This,iWindowCollection) \ + (This)->lpVtbl -> get_Windows(This,iWindowCollection) + +#define IiTunes_get_SoundVolume(This,volume) \ + (This)->lpVtbl -> get_SoundVolume(This,volume) + +#define IiTunes_put_SoundVolume(This,volume) \ + (This)->lpVtbl -> put_SoundVolume(This,volume) + +#define IiTunes_get_Mute(This,isMuted) \ + (This)->lpVtbl -> get_Mute(This,isMuted) + +#define IiTunes_put_Mute(This,shouldMute) \ + (This)->lpVtbl -> put_Mute(This,shouldMute) + +#define IiTunes_get_PlayerState(This,playerState) \ + (This)->lpVtbl -> get_PlayerState(This,playerState) + +#define IiTunes_get_PlayerPosition(This,playerPos) \ + (This)->lpVtbl -> get_PlayerPosition(This,playerPos) + +#define IiTunes_put_PlayerPosition(This,playerPos) \ + (This)->lpVtbl -> put_PlayerPosition(This,playerPos) + +#define IiTunes_get_CurrentEncoder(This,iEncoder) \ + (This)->lpVtbl -> get_CurrentEncoder(This,iEncoder) + +#define IiTunes_put_CurrentEncoder(This,iEncoder) \ + (This)->lpVtbl -> put_CurrentEncoder(This,iEncoder) + +#define IiTunes_get_VisualsEnabled(This,isEnabled) \ + (This)->lpVtbl -> get_VisualsEnabled(This,isEnabled) + +#define IiTunes_put_VisualsEnabled(This,shouldEnable) \ + (This)->lpVtbl -> put_VisualsEnabled(This,shouldEnable) + +#define IiTunes_get_FullScreenVisuals(This,isFullScreen) \ + (This)->lpVtbl -> get_FullScreenVisuals(This,isFullScreen) + +#define IiTunes_put_FullScreenVisuals(This,shouldUseFullScreen) \ + (This)->lpVtbl -> put_FullScreenVisuals(This,shouldUseFullScreen) + +#define IiTunes_get_VisualSize(This,visualSize) \ + (This)->lpVtbl -> get_VisualSize(This,visualSize) + +#define IiTunes_put_VisualSize(This,visualSize) \ + (This)->lpVtbl -> put_VisualSize(This,visualSize) + +#define IiTunes_get_CurrentVisual(This,iVisual) \ + (This)->lpVtbl -> get_CurrentVisual(This,iVisual) + +#define IiTunes_put_CurrentVisual(This,iVisual) \ + (This)->lpVtbl -> put_CurrentVisual(This,iVisual) + +#define IiTunes_get_EQEnabled(This,isEnabled) \ + (This)->lpVtbl -> get_EQEnabled(This,isEnabled) + +#define IiTunes_put_EQEnabled(This,shouldEnable) \ + (This)->lpVtbl -> put_EQEnabled(This,shouldEnable) + +#define IiTunes_get_CurrentEQPreset(This,iEQPreset) \ + (This)->lpVtbl -> get_CurrentEQPreset(This,iEQPreset) + +#define IiTunes_put_CurrentEQPreset(This,iEQPreset) \ + (This)->lpVtbl -> put_CurrentEQPreset(This,iEQPreset) + +#define IiTunes_get_CurrentStreamTitle(This,streamTitle) \ + (This)->lpVtbl -> get_CurrentStreamTitle(This,streamTitle) + +#define IiTunes_get_CurrentStreamURL(This,streamURL) \ + (This)->lpVtbl -> get_CurrentStreamURL(This,streamURL) + +#define IiTunes_get_BrowserWindow(This,iBrowserWindow) \ + (This)->lpVtbl -> get_BrowserWindow(This,iBrowserWindow) + +#define IiTunes_get_EQWindow(This,iEQWindow) \ + (This)->lpVtbl -> get_EQWindow(This,iEQWindow) + +#define IiTunes_get_LibrarySource(This,iLibrarySource) \ + (This)->lpVtbl -> get_LibrarySource(This,iLibrarySource) + +#define IiTunes_get_LibraryPlaylist(This,iLibraryPlaylist) \ + (This)->lpVtbl -> get_LibraryPlaylist(This,iLibraryPlaylist) + +#define IiTunes_get_CurrentTrack(This,iTrack) \ + (This)->lpVtbl -> get_CurrentTrack(This,iTrack) + +#define IiTunes_get_CurrentPlaylist(This,iPlaylist) \ + (This)->lpVtbl -> get_CurrentPlaylist(This,iPlaylist) + +#define IiTunes_get_SelectedTracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_SelectedTracks(This,iTrackCollection) + +#define IiTunes_get_Version(This,version) \ + (This)->lpVtbl -> get_Version(This,version) + +#define IiTunes_SetOptions(This,options) \ + (This)->lpVtbl -> SetOptions(This,options) + +#define IiTunes_ConvertFile2(This,filePath,iStatus) \ + (This)->lpVtbl -> ConvertFile2(This,filePath,iStatus) + +#define IiTunes_ConvertFiles2(This,filePaths,iStatus) \ + (This)->lpVtbl -> ConvertFiles2(This,filePaths,iStatus) + +#define IiTunes_ConvertTrack2(This,iTrackToConvert,iStatus) \ + (This)->lpVtbl -> ConvertTrack2(This,iTrackToConvert,iStatus) + +#define IiTunes_ConvertTracks2(This,iTracksToConvert,iStatus) \ + (This)->lpVtbl -> ConvertTracks2(This,iTracksToConvert,iStatus) + +#define IiTunes_get_AppCommandMessageProcessingEnabled(This,isEnabled) \ + (This)->lpVtbl -> get_AppCommandMessageProcessingEnabled(This,isEnabled) + +#define IiTunes_put_AppCommandMessageProcessingEnabled(This,shouldEnable) \ + (This)->lpVtbl -> put_AppCommandMessageProcessingEnabled(This,shouldEnable) + +#define IiTunes_get_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) \ + (This)->lpVtbl -> get_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) + +#define IiTunes_put_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) \ + (This)->lpVtbl -> put_ForceToForegroundOnDialog(This,forceToForegroundOnDialog) + +#define IiTunes_CreateEQPreset(This,eqPresetName,iEQPreset) \ + (This)->lpVtbl -> CreateEQPreset(This,eqPresetName,iEQPreset) + +#define IiTunes_CreatePlaylistInSource(This,playlistName,iSource,iPlaylist) \ + (This)->lpVtbl -> CreatePlaylistInSource(This,playlistName,iSource,iPlaylist) + +#define IiTunes_GetPlayerButtonsState(This,previousEnabled,playPauseStopState,nextEnabled) \ + (This)->lpVtbl -> GetPlayerButtonsState(This,previousEnabled,playPauseStopState,nextEnabled) + +#define IiTunes_PlayerButtonClicked(This,playerButton,playerButtonModifierKeys) \ + (This)->lpVtbl -> PlayerButtonClicked(This,playerButton,playerButtonModifierKeys) + +#define IiTunes_get_CanSetShuffle(This,iPlaylist,canSetShuffle) \ + (This)->lpVtbl -> get_CanSetShuffle(This,iPlaylist,canSetShuffle) + +#define IiTunes_get_CanSetSongRepeat(This,iPlaylist,canSetSongRepeat) \ + (This)->lpVtbl -> get_CanSetSongRepeat(This,iPlaylist,canSetSongRepeat) + +#define IiTunes_get_ConvertOperationStatus(This,iStatus) \ + (This)->lpVtbl -> get_ConvertOperationStatus(This,iStatus) + +#define IiTunes_SubscribeToPodcast(This,url) \ + (This)->lpVtbl -> SubscribeToPodcast(This,url) + +#define IiTunes_UpdatePodcastFeeds(This) \ + (This)->lpVtbl -> UpdatePodcastFeeds(This) + +#define IiTunes_CreateFolder(This,folderName,iFolder) \ + (This)->lpVtbl -> CreateFolder(This,folderName,iFolder) + +#define IiTunes_CreateFolderInSource(This,folderName,iSource,iFolder) \ + (This)->lpVtbl -> CreateFolderInSource(This,folderName,iSource,iFolder) + +#define IiTunes_get_SoundVolumeControlEnabled(This,isEnabled) \ + (This)->lpVtbl -> get_SoundVolumeControlEnabled(This,isEnabled) + +#define IiTunes_get_LibraryXMLPath(This,filePath) \ + (This)->lpVtbl -> get_LibraryXMLPath(This,filePath) + +#define IiTunes_get_ITObjectPersistentIDHigh(This,iObject,highID) \ + (This)->lpVtbl -> get_ITObjectPersistentIDHigh(This,iObject,highID) + +#define IiTunes_get_ITObjectPersistentIDLow(This,iObject,lowID) \ + (This)->lpVtbl -> get_ITObjectPersistentIDLow(This,iObject,lowID) + +#define IiTunes_GetITObjectPersistentIDs(This,iObject,highID,lowID) \ + (This)->lpVtbl -> GetITObjectPersistentIDs(This,iObject,highID,lowID) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_BackTrack_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_BackTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_FastForward_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_FastForward_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_NextTrack_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_NextTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Pause_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Pause_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Play_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Play_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PlayFile_Proxy( + IiTunes * This, + /* [in] */ BSTR filePath); + + +void __RPC_STUB IiTunes_PlayFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PlayPause_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_PlayPause_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PreviousTrack_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_PreviousTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Resume_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Resume_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Rewind_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Rewind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Stop_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Stop_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFile_Proxy( + IiTunes * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFiles_Proxy( + IiTunes * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertFiles_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTrack_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTracks_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertTracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CheckVersion_Proxy( + IiTunes * This, + /* [in] */ long majorVersion, + /* [in] */ long minorVersion, + /* [retval][out] */ VARIANT_BOOL *isCompatible); + + +void __RPC_STUB IiTunes_CheckVersion_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GetITObjectByID_Proxy( + IiTunes * This, + /* [in] */ long sourceID, + /* [in] */ long playlistID, + /* [in] */ long trackID, + /* [in] */ long databaseID, + /* [retval][out] */ IITObject **iObject); + + +void __RPC_STUB IiTunes_GetITObjectByID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreatePlaylist_Proxy( + IiTunes * This, + /* [in] */ BSTR playlistName, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IiTunes_CreatePlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_OpenURL_Proxy( + IiTunes * This, + /* [in] */ BSTR url); + + +void __RPC_STUB IiTunes_OpenURL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GotoMusicStoreHomePage_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_GotoMusicStoreHomePage_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_UpdateIPod_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_UpdateIPod_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Authorize_Proxy( + IiTunes * This, + /* [in] */ long numElems, + /* [size_is][in] */ VARIANT data[ ], + /* [size_is][in] */ BSTR names[ ]); + + +void __RPC_STUB IiTunes_Authorize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_Quit_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_Quit_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Sources_Proxy( + IiTunes * This, + /* [retval][out] */ IITSourceCollection **iSourceCollection); + + +void __RPC_STUB IiTunes_get_Sources_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Encoders_Proxy( + IiTunes * This, + /* [retval][out] */ IITEncoderCollection **iEncoderCollection); + + +void __RPC_STUB IiTunes_get_Encoders_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_EQPresets_Proxy( + IiTunes * This, + /* [retval][out] */ IITEQPresetCollection **iEQPresetCollection); + + +void __RPC_STUB IiTunes_get_EQPresets_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Visuals_Proxy( + IiTunes * This, + /* [retval][out] */ IITVisualCollection **iVisualCollection); + + +void __RPC_STUB IiTunes_get_Visuals_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Windows_Proxy( + IiTunes * This, + /* [retval][out] */ IITWindowCollection **iWindowCollection); + + +void __RPC_STUB IiTunes_get_Windows_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_SoundVolume_Proxy( + IiTunes * This, + /* [retval][out] */ long *volume); + + +void __RPC_STUB IiTunes_get_SoundVolume_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_SoundVolume_Proxy( + IiTunes * This, + /* [in] */ long volume); + + +void __RPC_STUB IiTunes_put_SoundVolume_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Mute_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isMuted); + + +void __RPC_STUB IiTunes_get_Mute_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_Mute_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldMute); + + +void __RPC_STUB IiTunes_put_Mute_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_PlayerState_Proxy( + IiTunes * This, + /* [retval][out] */ ITPlayerState *playerState); + + +void __RPC_STUB IiTunes_get_PlayerState_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_PlayerPosition_Proxy( + IiTunes * This, + /* [retval][out] */ long *playerPos); + + +void __RPC_STUB IiTunes_get_PlayerPosition_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_PlayerPosition_Proxy( + IiTunes * This, + /* [in] */ long playerPos); + + +void __RPC_STUB IiTunes_put_PlayerPosition_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentEncoder_Proxy( + IiTunes * This, + /* [retval][out] */ IITEncoder **iEncoder); + + +void __RPC_STUB IiTunes_get_CurrentEncoder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_CurrentEncoder_Proxy( + IiTunes * This, + /* [in] */ IITEncoder *iEncoder); + + +void __RPC_STUB IiTunes_put_CurrentEncoder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_VisualsEnabled_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + +void __RPC_STUB IiTunes_get_VisualsEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_VisualsEnabled_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + +void __RPC_STUB IiTunes_put_VisualsEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_FullScreenVisuals_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isFullScreen); + + +void __RPC_STUB IiTunes_get_FullScreenVisuals_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_FullScreenVisuals_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldUseFullScreen); + + +void __RPC_STUB IiTunes_put_FullScreenVisuals_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_VisualSize_Proxy( + IiTunes * This, + /* [retval][out] */ ITVisualSize *visualSize); + + +void __RPC_STUB IiTunes_get_VisualSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_VisualSize_Proxy( + IiTunes * This, + /* [in] */ ITVisualSize visualSize); + + +void __RPC_STUB IiTunes_put_VisualSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentVisual_Proxy( + IiTunes * This, + /* [retval][out] */ IITVisual **iVisual); + + +void __RPC_STUB IiTunes_get_CurrentVisual_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_CurrentVisual_Proxy( + IiTunes * This, + /* [in] */ IITVisual *iVisual); + + +void __RPC_STUB IiTunes_put_CurrentVisual_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_EQEnabled_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + +void __RPC_STUB IiTunes_get_EQEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_EQEnabled_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + +void __RPC_STUB IiTunes_put_EQEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentEQPreset_Proxy( + IiTunes * This, + /* [retval][out] */ IITEQPreset **iEQPreset); + + +void __RPC_STUB IiTunes_get_CurrentEQPreset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_CurrentEQPreset_Proxy( + IiTunes * This, + /* [in] */ IITEQPreset *iEQPreset); + + +void __RPC_STUB IiTunes_put_CurrentEQPreset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentStreamTitle_Proxy( + IiTunes * This, + /* [retval][out] */ BSTR *streamTitle); + + +void __RPC_STUB IiTunes_get_CurrentStreamTitle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentStreamURL_Proxy( + IiTunes * This, + /* [retval][out] */ BSTR *streamURL); + + +void __RPC_STUB IiTunes_get_CurrentStreamURL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_BrowserWindow_Proxy( + IiTunes * This, + /* [retval][out] */ IITBrowserWindow **iBrowserWindow); + + +void __RPC_STUB IiTunes_get_BrowserWindow_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_EQWindow_Proxy( + IiTunes * This, + /* [retval][out] */ IITWindow **iEQWindow); + + +void __RPC_STUB IiTunes_get_EQWindow_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_LibrarySource_Proxy( + IiTunes * This, + /* [retval][out] */ IITSource **iLibrarySource); + + +void __RPC_STUB IiTunes_get_LibrarySource_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_LibraryPlaylist_Proxy( + IiTunes * This, + /* [retval][out] */ IITLibraryPlaylist **iLibraryPlaylist); + + +void __RPC_STUB IiTunes_get_LibraryPlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentTrack_Proxy( + IiTunes * This, + /* [retval][out] */ IITTrack **iTrack); + + +void __RPC_STUB IiTunes_get_CurrentTrack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CurrentPlaylist_Proxy( + IiTunes * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IiTunes_get_CurrentPlaylist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_SelectedTracks_Proxy( + IiTunes * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IiTunes_get_SelectedTracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_Version_Proxy( + IiTunes * This, + /* [retval][out] */ BSTR *version); + + +void __RPC_STUB IiTunes_get_Version_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_SetOptions_Proxy( + IiTunes * This, + /* [in] */ long options); + + +void __RPC_STUB IiTunes_SetOptions_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFile2_Proxy( + IiTunes * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertFile2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertFiles2_Proxy( + IiTunes * This, + /* [in] */ VARIANT *filePaths, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertFiles2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTrack2_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iTrackToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertTrack2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_ConvertTracks2_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iTracksToConvert, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_ConvertTracks2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_AppCommandMessageProcessingEnabled_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + +void __RPC_STUB IiTunes_get_AppCommandMessageProcessingEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_AppCommandMessageProcessingEnabled_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL shouldEnable); + + +void __RPC_STUB IiTunes_put_AppCommandMessageProcessingEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ForceToForegroundOnDialog_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *forceToForegroundOnDialog); + + +void __RPC_STUB IiTunes_get_ForceToForegroundOnDialog_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IiTunes_put_ForceToForegroundOnDialog_Proxy( + IiTunes * This, + /* [in] */ VARIANT_BOOL forceToForegroundOnDialog); + + +void __RPC_STUB IiTunes_put_ForceToForegroundOnDialog_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreateEQPreset_Proxy( + IiTunes * This, + /* [in] */ BSTR eqPresetName, + /* [retval][out] */ IITEQPreset **iEQPreset); + + +void __RPC_STUB IiTunes_CreateEQPreset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreatePlaylistInSource_Proxy( + IiTunes * This, + /* [in] */ BSTR playlistName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IiTunes_CreatePlaylistInSource_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GetPlayerButtonsState_Proxy( + IiTunes * This, + /* [out] */ VARIANT_BOOL *previousEnabled, + /* [out] */ ITPlayButtonState *playPauseStopState, + /* [out] */ VARIANT_BOOL *nextEnabled); + + +void __RPC_STUB IiTunes_GetPlayerButtonsState_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_PlayerButtonClicked_Proxy( + IiTunes * This, + /* [in] */ ITPlayerButton playerButton, + /* [in] */ long playerButtonModifierKeys); + + +void __RPC_STUB IiTunes_PlayerButtonClicked_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CanSetShuffle_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetShuffle); + + +void __RPC_STUB IiTunes_get_CanSetShuffle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_CanSetSongRepeat_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iPlaylist, + /* [retval][out] */ VARIANT_BOOL *canSetSongRepeat); + + +void __RPC_STUB IiTunes_get_CanSetSongRepeat_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ConvertOperationStatus_Proxy( + IiTunes * This, + /* [retval][out] */ IITConvertOperationStatus **iStatus); + + +void __RPC_STUB IiTunes_get_ConvertOperationStatus_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_SubscribeToPodcast_Proxy( + IiTunes * This, + /* [in] */ BSTR url); + + +void __RPC_STUB IiTunes_SubscribeToPodcast_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_UpdatePodcastFeeds_Proxy( + IiTunes * This); + + +void __RPC_STUB IiTunes_UpdatePodcastFeeds_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreateFolder_Proxy( + IiTunes * This, + /* [in] */ BSTR folderName, + /* [retval][out] */ IITPlaylist **iFolder); + + +void __RPC_STUB IiTunes_CreateFolder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_CreateFolderInSource_Proxy( + IiTunes * This, + /* [in] */ BSTR folderName, + /* [in] */ VARIANT *iSource, + /* [retval][out] */ IITPlaylist **iFolder); + + +void __RPC_STUB IiTunes_CreateFolderInSource_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_SoundVolumeControlEnabled_Proxy( + IiTunes * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + +void __RPC_STUB IiTunes_get_SoundVolumeControlEnabled_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_LibraryXMLPath_Proxy( + IiTunes * This, + /* [retval][out] */ BSTR *filePath); + + +void __RPC_STUB IiTunes_get_LibraryXMLPath_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ITObjectPersistentIDHigh_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *highID); + + +void __RPC_STUB IiTunes_get_ITObjectPersistentIDHigh_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IiTunes_get_ITObjectPersistentIDLow_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [retval][out] */ long *lowID); + + +void __RPC_STUB IiTunes_get_ITObjectPersistentIDLow_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IiTunes_GetITObjectPersistentIDs_Proxy( + IiTunes * This, + /* [in] */ VARIANT *iObject, + /* [out] */ long *highID, + /* [out] */ long *lowID); + + +void __RPC_STUB IiTunes_GetITObjectPersistentIDs_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IiTunes_INTERFACE_DEFINED__ */ + + +#ifndef ___IiTunesEvents_DISPINTERFACE_DEFINED__ +#define ___IiTunesEvents_DISPINTERFACE_DEFINED__ + +/* dispinterface _IiTunesEvents */ +/* [helpstring][uuid] */ + + +EXTERN_C const IID DIID__IiTunesEvents; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5846EB78-317E-4b6f-B0C3-11EE8C8FEEF2") + _IiTunesEvents : public IDispatch + { + }; + +#else /* C style interface */ + + typedef struct _IiTunesEventsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + _IiTunesEvents * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + _IiTunesEvents * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + _IiTunesEvents * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + _IiTunesEvents * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + _IiTunesEvents * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + _IiTunesEvents * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + _IiTunesEvents * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + END_INTERFACE + } _IiTunesEventsVtbl; + + interface _IiTunesEvents + { + CONST_VTBL struct _IiTunesEventsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define _IiTunesEvents_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define _IiTunesEvents_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define _IiTunesEvents_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define _IiTunesEvents_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define _IiTunesEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define _IiTunesEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define _IiTunesEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + +#endif /* ___IiTunesEvents_DISPINTERFACE_DEFINED__ */ + + +#ifndef ___IITConvertOperationStatusEvents_DISPINTERFACE_DEFINED__ +#define ___IITConvertOperationStatusEvents_DISPINTERFACE_DEFINED__ + +/* dispinterface _IITConvertOperationStatusEvents */ +/* [helpstring][uuid] */ + + +EXTERN_C const IID DIID__IITConvertOperationStatusEvents; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5C47A705-8E8A-45a1-9EED-71C993F0BF60") + _IITConvertOperationStatusEvents : public IDispatch + { + }; + +#else /* C style interface */ + + typedef struct _IITConvertOperationStatusEventsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + _IITConvertOperationStatusEvents * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + _IITConvertOperationStatusEvents * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + _IITConvertOperationStatusEvents * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + _IITConvertOperationStatusEvents * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + _IITConvertOperationStatusEvents * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + _IITConvertOperationStatusEvents * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + _IITConvertOperationStatusEvents * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + END_INTERFACE + } _IITConvertOperationStatusEventsVtbl; + + interface _IITConvertOperationStatusEvents + { + CONST_VTBL struct _IITConvertOperationStatusEventsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define _IITConvertOperationStatusEvents_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define _IITConvertOperationStatusEvents_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define _IITConvertOperationStatusEvents_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define _IITConvertOperationStatusEvents_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define _IITConvertOperationStatusEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define _IITConvertOperationStatusEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define _IITConvertOperationStatusEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + +#endif /* ___IITConvertOperationStatusEvents_DISPINTERFACE_DEFINED__ */ + + +EXTERN_C const CLSID CLSID_iTunesApp; + +#ifdef __cplusplus + +class DECLSPEC_UUID("DC0C2640-1415-4644-875C-6F4D769839BA") +iTunesApp; +#endif + +EXTERN_C const CLSID CLSID_iTunesConvertOperationStatus; + +#ifdef __cplusplus + +class DECLSPEC_UUID("D06596AD-C900-41b2-BC68-1B486450FC56") +iTunesConvertOperationStatus; +#endif + +#ifndef __IITArtwork_INTERFACE_DEFINED__ +#define __IITArtwork_INTERFACE_DEFINED__ + +/* interface IITArtwork */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITArtwork; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("D0A6C1F8-BF3D-4cd8-AC47-FE32BDD17257") + IITArtwork : public IDispatch + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Delete( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetArtworkFromFile( + /* [in] */ BSTR filePath) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SaveArtworkToFile( + /* [in] */ BSTR filePath) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Format( + /* [retval][out] */ ITArtworkFormat *format) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_IsDownloadedArtwork( + /* [retval][out] */ VARIANT_BOOL *isDownloadedArtwork) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Description( + /* [retval][out] */ BSTR *description) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Description( + /* [in] */ BSTR description) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITArtworkVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITArtwork * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITArtwork * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITArtwork * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITArtwork * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITArtwork * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITArtwork * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITArtwork * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITArtwork * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SetArtworkFromFile )( + IITArtwork * This, + /* [in] */ BSTR filePath); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SaveArtworkToFile )( + IITArtwork * This, + /* [in] */ BSTR filePath); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Format )( + IITArtwork * This, + /* [retval][out] */ ITArtworkFormat *format); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsDownloadedArtwork )( + IITArtwork * This, + /* [retval][out] */ VARIANT_BOOL *isDownloadedArtwork); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Description )( + IITArtwork * This, + /* [retval][out] */ BSTR *description); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Description )( + IITArtwork * This, + /* [in] */ BSTR description); + + END_INTERFACE + } IITArtworkVtbl; + + interface IITArtwork + { + CONST_VTBL struct IITArtworkVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITArtwork_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITArtwork_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITArtwork_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITArtwork_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITArtwork_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITArtwork_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITArtwork_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITArtwork_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITArtwork_SetArtworkFromFile(This,filePath) \ + (This)->lpVtbl -> SetArtworkFromFile(This,filePath) + +#define IITArtwork_SaveArtworkToFile(This,filePath) \ + (This)->lpVtbl -> SaveArtworkToFile(This,filePath) + +#define IITArtwork_get_Format(This,format) \ + (This)->lpVtbl -> get_Format(This,format) + +#define IITArtwork_get_IsDownloadedArtwork(This,isDownloadedArtwork) \ + (This)->lpVtbl -> get_IsDownloadedArtwork(This,isDownloadedArtwork) + +#define IITArtwork_get_Description(This,description) \ + (This)->lpVtbl -> get_Description(This,description) + +#define IITArtwork_put_Description(This,description) \ + (This)->lpVtbl -> put_Description(This,description) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITArtwork_Delete_Proxy( + IITArtwork * This); + + +void __RPC_STUB IITArtwork_Delete_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITArtwork_SetArtworkFromFile_Proxy( + IITArtwork * This, + /* [in] */ BSTR filePath); + + +void __RPC_STUB IITArtwork_SetArtworkFromFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITArtwork_SaveArtworkToFile_Proxy( + IITArtwork * This, + /* [in] */ BSTR filePath); + + +void __RPC_STUB IITArtwork_SaveArtworkToFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtwork_get_Format_Proxy( + IITArtwork * This, + /* [retval][out] */ ITArtworkFormat *format); + + +void __RPC_STUB IITArtwork_get_Format_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtwork_get_IsDownloadedArtwork_Proxy( + IITArtwork * This, + /* [retval][out] */ VARIANT_BOOL *isDownloadedArtwork); + + +void __RPC_STUB IITArtwork_get_IsDownloadedArtwork_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtwork_get_Description_Proxy( + IITArtwork * This, + /* [retval][out] */ BSTR *description); + + +void __RPC_STUB IITArtwork_get_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITArtwork_put_Description_Proxy( + IITArtwork * This, + /* [in] */ BSTR description); + + +void __RPC_STUB IITArtwork_put_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITArtwork_INTERFACE_DEFINED__ */ + + +#ifndef __IITArtworkCollection_INTERFACE_DEFINED__ +#define __IITArtworkCollection_INTERFACE_DEFINED__ + +/* interface IITArtworkCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITArtworkCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("BF2742D7-418C-4858-9AF9-2981B062D23E") + IITArtworkCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITArtwork **iArtwork) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITArtworkCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITArtworkCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITArtworkCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITArtworkCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITArtworkCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITArtworkCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITArtworkCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITArtworkCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITArtworkCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITArtworkCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITArtwork **iArtwork); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITArtworkCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + END_INTERFACE + } IITArtworkCollectionVtbl; + + interface IITArtworkCollection + { + CONST_VTBL struct IITArtworkCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITArtworkCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITArtworkCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITArtworkCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITArtworkCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITArtworkCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITArtworkCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITArtworkCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITArtworkCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITArtworkCollection_get_Item(This,index,iArtwork) \ + (This)->lpVtbl -> get_Item(This,index,iArtwork) + +#define IITArtworkCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITArtworkCollection_get_Count_Proxy( + IITArtworkCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITArtworkCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITArtworkCollection_get_Item_Proxy( + IITArtworkCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITArtwork **iArtwork); + + +void __RPC_STUB IITArtworkCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITArtworkCollection_get__NewEnum_Proxy( + IITArtworkCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITArtworkCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITArtworkCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITURLTrack_INTERFACE_DEFINED__ +#define __IITURLTrack_INTERFACE_DEFINED__ + +/* interface IITURLTrack */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITURLTrack; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("1116E3B5-29FD-4393-A7BD-454E5E327900") + IITURLTrack : public IITTrack + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_URL( + /* [retval][out] */ BSTR *url) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_URL( + /* [in] */ BSTR url) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Podcast( + /* [retval][out] */ VARIANT_BOOL *isPodcast) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdatePodcastFeed( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE DownloadPodcastEpisode( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Category( + /* [retval][out] */ BSTR *category) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Category( + /* [in] */ BSTR category) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Description( + /* [retval][out] */ BSTR *description) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Description( + /* [in] */ BSTR description) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LongDescription( + /* [retval][out] */ BSTR *longDescription) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_LongDescription( + /* [in] */ BSTR longDescription) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRating( + /* [retval][out] */ long *rating) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AlbumRating( + /* [in] */ long rating) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRatingKind( + /* [retval][out] */ ITRatingKind *ratingKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RatingKind( + /* [retval][out] */ ITRatingKind *ratingKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlists( + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITURLTrackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITURLTrack * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITURLTrack * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITURLTrack * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITURLTrack * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITURLTrack * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITURLTrack * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITURLTrack * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITURLTrack * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITURLTrack * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITURLTrack * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITURLTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITURLTrack * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITURLTrack * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITURLTrack * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITURLTrack * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITURLTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( + IITURLTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddArtworkFromFile )( + IITURLTrack * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITArtwork **iArtwork); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITURLTrack * This, + /* [retval][out] */ ITTrackKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( + IITURLTrack * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Album )( + IITURLTrack * This, + /* [retval][out] */ BSTR *album); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Album )( + IITURLTrack * This, + /* [in] */ BSTR album); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( + IITURLTrack * This, + /* [retval][out] */ BSTR *artist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Artist )( + IITURLTrack * This, + /* [in] */ BSTR artist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BitRate )( + IITURLTrack * This, + /* [retval][out] */ long *bitrate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BPM )( + IITURLTrack * This, + /* [retval][out] */ long *beatsPerMinute); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BPM )( + IITURLTrack * This, + /* [in] */ long beatsPerMinute); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Comment )( + IITURLTrack * This, + /* [retval][out] */ BSTR *comment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Comment )( + IITURLTrack * This, + /* [in] */ BSTR comment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( + IITURLTrack * This, + /* [retval][out] */ VARIANT_BOOL *isCompilation); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Compilation )( + IITURLTrack * This, + /* [in] */ VARIANT_BOOL shouldBeCompilation); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( + IITURLTrack * This, + /* [retval][out] */ BSTR *composer); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Composer )( + IITURLTrack * This, + /* [in] */ BSTR composer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DateAdded )( + IITURLTrack * This, + /* [retval][out] */ DATE *dateAdded); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( + IITURLTrack * This, + /* [retval][out] */ long *discCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscCount )( + IITURLTrack * This, + /* [in] */ long discCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( + IITURLTrack * This, + /* [retval][out] */ long *discNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscNumber )( + IITURLTrack * This, + /* [in] */ long discNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITURLTrack * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Enabled )( + IITURLTrack * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Enabled )( + IITURLTrack * This, + /* [in] */ VARIANT_BOOL shouldBeEnabled); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQ )( + IITURLTrack * This, + /* [retval][out] */ BSTR *eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQ )( + IITURLTrack * This, + /* [in] */ BSTR eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Finish )( + IITURLTrack * This, + /* [in] */ long finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Finish )( + IITURLTrack * This, + /* [retval][out] */ long *finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( + IITURLTrack * This, + /* [retval][out] */ BSTR *genre); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Genre )( + IITURLTrack * This, + /* [in] */ BSTR genre); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Grouping )( + IITURLTrack * This, + /* [retval][out] */ BSTR *grouping); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Grouping )( + IITURLTrack * This, + /* [in] */ BSTR grouping); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_KindAsString )( + IITURLTrack * This, + /* [retval][out] */ BSTR *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ModificationDate )( + IITURLTrack * This, + /* [retval][out] */ DATE *dateModified); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedCount )( + IITURLTrack * This, + /* [retval][out] */ long *playedCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedCount )( + IITURLTrack * This, + /* [in] */ long playedCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedDate )( + IITURLTrack * This, + /* [retval][out] */ DATE *playedDate); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedDate )( + IITURLTrack * This, + /* [in] */ DATE playedDate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayOrderIndex )( + IITURLTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Rating )( + IITURLTrack * This, + /* [retval][out] */ long *rating); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Rating )( + IITURLTrack * This, + /* [in] */ long rating); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SampleRate )( + IITURLTrack * This, + /* [retval][out] */ long *sampleRate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITURLTrack * This, + /* [retval][out] */ long *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Start )( + IITURLTrack * This, + /* [retval][out] */ long *start); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Start )( + IITURLTrack * This, + /* [in] */ long start); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITURLTrack * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackCount )( + IITURLTrack * This, + /* [retval][out] */ long *trackCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackCount )( + IITURLTrack * This, + /* [in] */ long trackCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackNumber )( + IITURLTrack * This, + /* [retval][out] */ long *trackNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackNumber )( + IITURLTrack * This, + /* [in] */ long trackNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VolumeAdjustment )( + IITURLTrack * This, + /* [retval][out] */ long *volumeAdjustment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VolumeAdjustment )( + IITURLTrack * This, + /* [in] */ long volumeAdjustment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( + IITURLTrack * This, + /* [retval][out] */ long *year); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Year )( + IITURLTrack * This, + /* [in] */ long year); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artwork )( + IITURLTrack * This, + /* [retval][out] */ IITArtworkCollection **iArtworkCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_URL )( + IITURLTrack * This, + /* [retval][out] */ BSTR *url); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_URL )( + IITURLTrack * This, + /* [in] */ BSTR url); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Podcast )( + IITURLTrack * This, + /* [retval][out] */ VARIANT_BOOL *isPodcast); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdatePodcastFeed )( + IITURLTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *DownloadPodcastEpisode )( + IITURLTrack * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Category )( + IITURLTrack * This, + /* [retval][out] */ BSTR *category); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Category )( + IITURLTrack * This, + /* [in] */ BSTR category); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Description )( + IITURLTrack * This, + /* [retval][out] */ BSTR *description); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Description )( + IITURLTrack * This, + /* [in] */ BSTR description); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LongDescription )( + IITURLTrack * This, + /* [retval][out] */ BSTR *longDescription); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LongDescription )( + IITURLTrack * This, + /* [in] */ BSTR longDescription); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( + IITURLTrack * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRating )( + IITURLTrack * This, + /* [retval][out] */ long *rating); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AlbumRating )( + IITURLTrack * This, + /* [in] */ long rating); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRatingKind )( + IITURLTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RatingKind )( + IITURLTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( + IITURLTrack * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + END_INTERFACE + } IITURLTrackVtbl; + + interface IITURLTrack + { + CONST_VTBL struct IITURLTrackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITURLTrack_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITURLTrack_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITURLTrack_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITURLTrack_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITURLTrack_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITURLTrack_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITURLTrack_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITURLTrack_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITURLTrack_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITURLTrack_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITURLTrack_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITURLTrack_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITURLTrack_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITURLTrack_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITURLTrack_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITURLTrack_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITURLTrack_Play(This) \ + (This)->lpVtbl -> Play(This) + +#define IITURLTrack_AddArtworkFromFile(This,filePath,iArtwork) \ + (This)->lpVtbl -> AddArtworkFromFile(This,filePath,iArtwork) + +#define IITURLTrack_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITURLTrack_get_Playlist(This,iPlaylist) \ + (This)->lpVtbl -> get_Playlist(This,iPlaylist) + +#define IITURLTrack_get_Album(This,album) \ + (This)->lpVtbl -> get_Album(This,album) + +#define IITURLTrack_put_Album(This,album) \ + (This)->lpVtbl -> put_Album(This,album) + +#define IITURLTrack_get_Artist(This,artist) \ + (This)->lpVtbl -> get_Artist(This,artist) + +#define IITURLTrack_put_Artist(This,artist) \ + (This)->lpVtbl -> put_Artist(This,artist) + +#define IITURLTrack_get_BitRate(This,bitrate) \ + (This)->lpVtbl -> get_BitRate(This,bitrate) + +#define IITURLTrack_get_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> get_BPM(This,beatsPerMinute) + +#define IITURLTrack_put_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> put_BPM(This,beatsPerMinute) + +#define IITURLTrack_get_Comment(This,comment) \ + (This)->lpVtbl -> get_Comment(This,comment) + +#define IITURLTrack_put_Comment(This,comment) \ + (This)->lpVtbl -> put_Comment(This,comment) + +#define IITURLTrack_get_Compilation(This,isCompilation) \ + (This)->lpVtbl -> get_Compilation(This,isCompilation) + +#define IITURLTrack_put_Compilation(This,shouldBeCompilation) \ + (This)->lpVtbl -> put_Compilation(This,shouldBeCompilation) + +#define IITURLTrack_get_Composer(This,composer) \ + (This)->lpVtbl -> get_Composer(This,composer) + +#define IITURLTrack_put_Composer(This,composer) \ + (This)->lpVtbl -> put_Composer(This,composer) + +#define IITURLTrack_get_DateAdded(This,dateAdded) \ + (This)->lpVtbl -> get_DateAdded(This,dateAdded) + +#define IITURLTrack_get_DiscCount(This,discCount) \ + (This)->lpVtbl -> get_DiscCount(This,discCount) + +#define IITURLTrack_put_DiscCount(This,discCount) \ + (This)->lpVtbl -> put_DiscCount(This,discCount) + +#define IITURLTrack_get_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> get_DiscNumber(This,discNumber) + +#define IITURLTrack_put_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> put_DiscNumber(This,discNumber) + +#define IITURLTrack_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITURLTrack_get_Enabled(This,isEnabled) \ + (This)->lpVtbl -> get_Enabled(This,isEnabled) + +#define IITURLTrack_put_Enabled(This,shouldBeEnabled) \ + (This)->lpVtbl -> put_Enabled(This,shouldBeEnabled) + +#define IITURLTrack_get_EQ(This,eq) \ + (This)->lpVtbl -> get_EQ(This,eq) + +#define IITURLTrack_put_EQ(This,eq) \ + (This)->lpVtbl -> put_EQ(This,eq) + +#define IITURLTrack_put_Finish(This,finish) \ + (This)->lpVtbl -> put_Finish(This,finish) + +#define IITURLTrack_get_Finish(This,finish) \ + (This)->lpVtbl -> get_Finish(This,finish) + +#define IITURLTrack_get_Genre(This,genre) \ + (This)->lpVtbl -> get_Genre(This,genre) + +#define IITURLTrack_put_Genre(This,genre) \ + (This)->lpVtbl -> put_Genre(This,genre) + +#define IITURLTrack_get_Grouping(This,grouping) \ + (This)->lpVtbl -> get_Grouping(This,grouping) + +#define IITURLTrack_put_Grouping(This,grouping) \ + (This)->lpVtbl -> put_Grouping(This,grouping) + +#define IITURLTrack_get_KindAsString(This,kind) \ + (This)->lpVtbl -> get_KindAsString(This,kind) + +#define IITURLTrack_get_ModificationDate(This,dateModified) \ + (This)->lpVtbl -> get_ModificationDate(This,dateModified) + +#define IITURLTrack_get_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> get_PlayedCount(This,playedCount) + +#define IITURLTrack_put_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> put_PlayedCount(This,playedCount) + +#define IITURLTrack_get_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> get_PlayedDate(This,playedDate) + +#define IITURLTrack_put_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> put_PlayedDate(This,playedDate) + +#define IITURLTrack_get_PlayOrderIndex(This,index) \ + (This)->lpVtbl -> get_PlayOrderIndex(This,index) + +#define IITURLTrack_get_Rating(This,rating) \ + (This)->lpVtbl -> get_Rating(This,rating) + +#define IITURLTrack_put_Rating(This,rating) \ + (This)->lpVtbl -> put_Rating(This,rating) + +#define IITURLTrack_get_SampleRate(This,sampleRate) \ + (This)->lpVtbl -> get_SampleRate(This,sampleRate) + +#define IITURLTrack_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITURLTrack_get_Start(This,start) \ + (This)->lpVtbl -> get_Start(This,start) + +#define IITURLTrack_put_Start(This,start) \ + (This)->lpVtbl -> put_Start(This,start) + +#define IITURLTrack_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITURLTrack_get_TrackCount(This,trackCount) \ + (This)->lpVtbl -> get_TrackCount(This,trackCount) + +#define IITURLTrack_put_TrackCount(This,trackCount) \ + (This)->lpVtbl -> put_TrackCount(This,trackCount) + +#define IITURLTrack_get_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> get_TrackNumber(This,trackNumber) + +#define IITURLTrack_put_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> put_TrackNumber(This,trackNumber) + +#define IITURLTrack_get_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> get_VolumeAdjustment(This,volumeAdjustment) + +#define IITURLTrack_put_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> put_VolumeAdjustment(This,volumeAdjustment) + +#define IITURLTrack_get_Year(This,year) \ + (This)->lpVtbl -> get_Year(This,year) + +#define IITURLTrack_put_Year(This,year) \ + (This)->lpVtbl -> put_Year(This,year) + +#define IITURLTrack_get_Artwork(This,iArtworkCollection) \ + (This)->lpVtbl -> get_Artwork(This,iArtworkCollection) + + +#define IITURLTrack_get_URL(This,url) \ + (This)->lpVtbl -> get_URL(This,url) + +#define IITURLTrack_put_URL(This,url) \ + (This)->lpVtbl -> put_URL(This,url) + +#define IITURLTrack_get_Podcast(This,isPodcast) \ + (This)->lpVtbl -> get_Podcast(This,isPodcast) + +#define IITURLTrack_UpdatePodcastFeed(This) \ + (This)->lpVtbl -> UpdatePodcastFeed(This) + +#define IITURLTrack_DownloadPodcastEpisode(This) \ + (This)->lpVtbl -> DownloadPodcastEpisode(This) + +#define IITURLTrack_get_Category(This,category) \ + (This)->lpVtbl -> get_Category(This,category) + +#define IITURLTrack_put_Category(This,category) \ + (This)->lpVtbl -> put_Category(This,category) + +#define IITURLTrack_get_Description(This,description) \ + (This)->lpVtbl -> get_Description(This,description) + +#define IITURLTrack_put_Description(This,description) \ + (This)->lpVtbl -> put_Description(This,description) + +#define IITURLTrack_get_LongDescription(This,longDescription) \ + (This)->lpVtbl -> get_LongDescription(This,longDescription) + +#define IITURLTrack_put_LongDescription(This,longDescription) \ + (This)->lpVtbl -> put_LongDescription(This,longDescription) + +#define IITURLTrack_Reveal(This) \ + (This)->lpVtbl -> Reveal(This) + +#define IITURLTrack_get_AlbumRating(This,rating) \ + (This)->lpVtbl -> get_AlbumRating(This,rating) + +#define IITURLTrack_put_AlbumRating(This,rating) \ + (This)->lpVtbl -> put_AlbumRating(This,rating) + +#define IITURLTrack_get_AlbumRatingKind(This,ratingKind) \ + (This)->lpVtbl -> get_AlbumRatingKind(This,ratingKind) + +#define IITURLTrack_get_RatingKind(This,ratingKind) \ + (This)->lpVtbl -> get_RatingKind(This,ratingKind) + +#define IITURLTrack_get_Playlists(This,iPlaylistCollection) \ + (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_URL_Proxy( + IITURLTrack * This, + /* [retval][out] */ BSTR *url); + + +void __RPC_STUB IITURLTrack_get_URL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_URL_Proxy( + IITURLTrack * This, + /* [in] */ BSTR url); + + +void __RPC_STUB IITURLTrack_put_URL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Podcast_Proxy( + IITURLTrack * This, + /* [retval][out] */ VARIANT_BOOL *isPodcast); + + +void __RPC_STUB IITURLTrack_get_Podcast_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITURLTrack_UpdatePodcastFeed_Proxy( + IITURLTrack * This); + + +void __RPC_STUB IITURLTrack_UpdatePodcastFeed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITURLTrack_DownloadPodcastEpisode_Proxy( + IITURLTrack * This); + + +void __RPC_STUB IITURLTrack_DownloadPodcastEpisode_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Category_Proxy( + IITURLTrack * This, + /* [retval][out] */ BSTR *category); + + +void __RPC_STUB IITURLTrack_get_Category_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_Category_Proxy( + IITURLTrack * This, + /* [in] */ BSTR category); + + +void __RPC_STUB IITURLTrack_put_Category_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Description_Proxy( + IITURLTrack * This, + /* [retval][out] */ BSTR *description); + + +void __RPC_STUB IITURLTrack_get_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_Description_Proxy( + IITURLTrack * This, + /* [in] */ BSTR description); + + +void __RPC_STUB IITURLTrack_put_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_LongDescription_Proxy( + IITURLTrack * This, + /* [retval][out] */ BSTR *longDescription); + + +void __RPC_STUB IITURLTrack_get_LongDescription_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_LongDescription_Proxy( + IITURLTrack * This, + /* [in] */ BSTR longDescription); + + +void __RPC_STUB IITURLTrack_put_LongDescription_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITURLTrack_Reveal_Proxy( + IITURLTrack * This); + + +void __RPC_STUB IITURLTrack_Reveal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_AlbumRating_Proxy( + IITURLTrack * This, + /* [retval][out] */ long *rating); + + +void __RPC_STUB IITURLTrack_get_AlbumRating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITURLTrack_put_AlbumRating_Proxy( + IITURLTrack * This, + /* [in] */ long rating); + + +void __RPC_STUB IITURLTrack_put_AlbumRating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_AlbumRatingKind_Proxy( + IITURLTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + +void __RPC_STUB IITURLTrack_get_AlbumRatingKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_RatingKind_Proxy( + IITURLTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + +void __RPC_STUB IITURLTrack_get_RatingKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITURLTrack_get_Playlists_Proxy( + IITURLTrack * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + +void __RPC_STUB IITURLTrack_get_Playlists_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITURLTrack_INTERFACE_DEFINED__ */ + + +#ifndef __IITAudioCDPlaylist_INTERFACE_DEFINED__ +#define __IITAudioCDPlaylist_INTERFACE_DEFINED__ + +/* interface IITAudioCDPlaylist */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITAudioCDPlaylist; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CF496DF3-0FED-4d7d-9BD8-529B6E8A082E") + IITAudioCDPlaylist : public IITPlaylist + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Artist( + /* [retval][out] */ BSTR *artist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Compilation( + /* [retval][out] */ VARIANT_BOOL *isCompiliation) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Composer( + /* [retval][out] */ BSTR *composer) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscCount( + /* [retval][out] */ long *discCount) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DiscNumber( + /* [retval][out] */ long *discNumber) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Genre( + /* [retval][out] */ BSTR *genre) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Year( + /* [retval][out] */ long *year) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITAudioCDPlaylistVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITAudioCDPlaylist * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITAudioCDPlaylist * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITAudioCDPlaylist * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITAudioCDPlaylist * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITAudioCDPlaylist * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITAudioCDPlaylist * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITAudioCDPlaylist * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITAudioCDPlaylist * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITAudioCDPlaylist * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITAudioCDPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *PlayFirstTrack )( + IITAudioCDPlaylist * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Print )( + IITAudioCDPlaylist * This, + /* [in] */ VARIANT_BOOL showPrintDialog, + /* [in] */ ITPlaylistPrintKind printKind, + /* [in] */ BSTR theme); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Search )( + IITAudioCDPlaylist * This, + /* [in] */ BSTR searchText, + /* [in] */ ITPlaylistSearchField searchFields, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITAudioCDPlaylist * This, + /* [retval][out] */ ITPlaylistKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Source )( + IITAudioCDPlaylist * This, + /* [retval][out] */ IITSource **iSource); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Shuffle )( + IITAudioCDPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isShuffle); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Shuffle )( + IITAudioCDPlaylist * This, + /* [in] */ VARIANT_BOOL shouldShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITAudioCDPlaylist * This, + /* [retval][out] */ double *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SongRepeat )( + IITAudioCDPlaylist * This, + /* [retval][out] */ ITPlaylistRepeatMode *repeatMode); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SongRepeat )( + IITAudioCDPlaylist * This, + /* [in] */ ITPlaylistRepeatMode repeatMode); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITAudioCDPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Tracks )( + IITAudioCDPlaylist * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *artist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( + IITAudioCDPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isCompiliation); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *composer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *discCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *discNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *genre); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *year); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( + IITAudioCDPlaylist * This); + + END_INTERFACE + } IITAudioCDPlaylistVtbl; + + interface IITAudioCDPlaylist + { + CONST_VTBL struct IITAudioCDPlaylistVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITAudioCDPlaylist_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITAudioCDPlaylist_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITAudioCDPlaylist_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITAudioCDPlaylist_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITAudioCDPlaylist_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITAudioCDPlaylist_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITAudioCDPlaylist_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITAudioCDPlaylist_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITAudioCDPlaylist_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITAudioCDPlaylist_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITAudioCDPlaylist_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITAudioCDPlaylist_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITAudioCDPlaylist_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITAudioCDPlaylist_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITAudioCDPlaylist_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITAudioCDPlaylist_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITAudioCDPlaylist_PlayFirstTrack(This) \ + (This)->lpVtbl -> PlayFirstTrack(This) + +#define IITAudioCDPlaylist_Print(This,showPrintDialog,printKind,theme) \ + (This)->lpVtbl -> Print(This,showPrintDialog,printKind,theme) + +#define IITAudioCDPlaylist_Search(This,searchText,searchFields,iTrackCollection) \ + (This)->lpVtbl -> Search(This,searchText,searchFields,iTrackCollection) + +#define IITAudioCDPlaylist_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITAudioCDPlaylist_get_Source(This,iSource) \ + (This)->lpVtbl -> get_Source(This,iSource) + +#define IITAudioCDPlaylist_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITAudioCDPlaylist_get_Shuffle(This,isShuffle) \ + (This)->lpVtbl -> get_Shuffle(This,isShuffle) + +#define IITAudioCDPlaylist_put_Shuffle(This,shouldShuffle) \ + (This)->lpVtbl -> put_Shuffle(This,shouldShuffle) + +#define IITAudioCDPlaylist_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITAudioCDPlaylist_get_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> get_SongRepeat(This,repeatMode) + +#define IITAudioCDPlaylist_put_SongRepeat(This,repeatMode) \ + (This)->lpVtbl -> put_SongRepeat(This,repeatMode) + +#define IITAudioCDPlaylist_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITAudioCDPlaylist_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITAudioCDPlaylist_get_Tracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_Tracks(This,iTrackCollection) + + +#define IITAudioCDPlaylist_get_Artist(This,artist) \ + (This)->lpVtbl -> get_Artist(This,artist) + +#define IITAudioCDPlaylist_get_Compilation(This,isCompiliation) \ + (This)->lpVtbl -> get_Compilation(This,isCompiliation) + +#define IITAudioCDPlaylist_get_Composer(This,composer) \ + (This)->lpVtbl -> get_Composer(This,composer) + +#define IITAudioCDPlaylist_get_DiscCount(This,discCount) \ + (This)->lpVtbl -> get_DiscCount(This,discCount) + +#define IITAudioCDPlaylist_get_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> get_DiscNumber(This,discNumber) + +#define IITAudioCDPlaylist_get_Genre(This,genre) \ + (This)->lpVtbl -> get_Genre(This,genre) + +#define IITAudioCDPlaylist_get_Year(This,year) \ + (This)->lpVtbl -> get_Year(This,year) + +#define IITAudioCDPlaylist_Reveal(This) \ + (This)->lpVtbl -> Reveal(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Artist_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *artist); + + +void __RPC_STUB IITAudioCDPlaylist_get_Artist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Compilation_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ VARIANT_BOOL *isCompiliation); + + +void __RPC_STUB IITAudioCDPlaylist_get_Compilation_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Composer_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *composer); + + +void __RPC_STUB IITAudioCDPlaylist_get_Composer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_DiscCount_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *discCount); + + +void __RPC_STUB IITAudioCDPlaylist_get_DiscCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_DiscNumber_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *discNumber); + + +void __RPC_STUB IITAudioCDPlaylist_get_DiscNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Genre_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ BSTR *genre); + + +void __RPC_STUB IITAudioCDPlaylist_get_Genre_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_get_Year_Proxy( + IITAudioCDPlaylist * This, + /* [retval][out] */ long *year); + + +void __RPC_STUB IITAudioCDPlaylist_get_Year_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITAudioCDPlaylist_Reveal_Proxy( + IITAudioCDPlaylist * This); + + +void __RPC_STUB IITAudioCDPlaylist_Reveal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITAudioCDPlaylist_INTERFACE_DEFINED__ */ + + +#ifndef __IITPlaylistCollection_INTERFACE_DEFINED__ +#define __IITPlaylistCollection_INTERFACE_DEFINED__ + +/* interface IITPlaylistCollection */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITPlaylistCollection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("FF194254-909D-4437-9C50-3AAC2AE6305C") + IITPlaylistCollection : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ long *count) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Item( + /* [in] */ long index, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByName( + /* [in] */ BSTR name, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + virtual /* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **iEnumerator) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ItemByPersistentID( + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITPlaylistCollectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITPlaylistCollection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITPlaylistCollection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITPlaylistCollection * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITPlaylistCollection * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITPlaylistCollection * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITPlaylistCollection * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITPlaylistCollection * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IITPlaylistCollection * This, + /* [retval][out] */ long *count); + + /* [helpstring][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Item )( + IITPlaylistCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByName )( + IITPlaylistCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][restricted][id][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IITPlaylistCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ItemByPersistentID )( + IITPlaylistCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITPlaylist **iPlaylist); + + END_INTERFACE + } IITPlaylistCollectionVtbl; + + interface IITPlaylistCollection + { + CONST_VTBL struct IITPlaylistCollectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITPlaylistCollection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITPlaylistCollection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITPlaylistCollection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITPlaylistCollection_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITPlaylistCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITPlaylistCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITPlaylistCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITPlaylistCollection_get_Count(This,count) \ + (This)->lpVtbl -> get_Count(This,count) + +#define IITPlaylistCollection_get_Item(This,index,iPlaylist) \ + (This)->lpVtbl -> get_Item(This,index,iPlaylist) + +#define IITPlaylistCollection_get_ItemByName(This,name,iPlaylist) \ + (This)->lpVtbl -> get_ItemByName(This,name,iPlaylist) + +#define IITPlaylistCollection_get__NewEnum(This,iEnumerator) \ + (This)->lpVtbl -> get__NewEnum(This,iEnumerator) + +#define IITPlaylistCollection_get_ItemByPersistentID(This,highID,lowID,iPlaylist) \ + (This)->lpVtbl -> get_ItemByPersistentID(This,highID,lowID,iPlaylist) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_Count_Proxy( + IITPlaylistCollection * This, + /* [retval][out] */ long *count); + + +void __RPC_STUB IITPlaylistCollection_get_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_Item_Proxy( + IITPlaylistCollection * This, + /* [in] */ long index, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITPlaylistCollection_get_Item_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_ItemByName_Proxy( + IITPlaylistCollection * This, + /* [in] */ BSTR name, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITPlaylistCollection_get_ItemByName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][restricted][id][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get__NewEnum_Proxy( + IITPlaylistCollection * This, + /* [retval][out] */ IUnknown **iEnumerator); + + +void __RPC_STUB IITPlaylistCollection_get__NewEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistCollection_get_ItemByPersistentID_Proxy( + IITPlaylistCollection * This, + /* [in] */ long highID, + /* [in] */ long lowID, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITPlaylistCollection_get_ItemByPersistentID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITPlaylistCollection_INTERFACE_DEFINED__ */ + + +#ifndef __IITIPodSource_INTERFACE_DEFINED__ +#define __IITIPodSource_INTERFACE_DEFINED__ + +/* interface IITIPodSource */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITIPodSource; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CF4D8ACE-1720-4fb9-B0AE-9877249E89B0") + IITIPodSource : public IITSource + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdateIPod( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE EjectIPod( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SoftwareVersion( + /* [retval][out] */ BSTR *softwareVersion) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITIPodSourceVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITIPodSource * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITIPodSource * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITIPodSource * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITIPodSource * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITIPodSource * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITIPodSource * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITIPodSource * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITIPodSource * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITIPodSource * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITIPodSource * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITIPodSource * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITIPodSource * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITIPodSource * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITIPodSource * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITIPodSource * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITIPodSource * This, + /* [retval][out] */ ITSourceKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Capacity )( + IITIPodSource * This, + /* [retval][out] */ double *capacity); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_FreeSpace )( + IITIPodSource * This, + /* [retval][out] */ double *freespace); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( + IITIPodSource * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdateIPod )( + IITIPodSource * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *EjectIPod )( + IITIPodSource * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SoftwareVersion )( + IITIPodSource * This, + /* [retval][out] */ BSTR *softwareVersion); + + END_INTERFACE + } IITIPodSourceVtbl; + + interface IITIPodSource + { + CONST_VTBL struct IITIPodSourceVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITIPodSource_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITIPodSource_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITIPodSource_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITIPodSource_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITIPodSource_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITIPodSource_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITIPodSource_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITIPodSource_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITIPodSource_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITIPodSource_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITIPodSource_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITIPodSource_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITIPodSource_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITIPodSource_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITIPodSource_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITIPodSource_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITIPodSource_get_Capacity(This,capacity) \ + (This)->lpVtbl -> get_Capacity(This,capacity) + +#define IITIPodSource_get_FreeSpace(This,freespace) \ + (This)->lpVtbl -> get_FreeSpace(This,freespace) + +#define IITIPodSource_get_Playlists(This,iPlaylistCollection) \ + (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) + + +#define IITIPodSource_UpdateIPod(This) \ + (This)->lpVtbl -> UpdateIPod(This) + +#define IITIPodSource_EjectIPod(This) \ + (This)->lpVtbl -> EjectIPod(This) + +#define IITIPodSource_get_SoftwareVersion(This,softwareVersion) \ + (This)->lpVtbl -> get_SoftwareVersion(This,softwareVersion) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITIPodSource_UpdateIPod_Proxy( + IITIPodSource * This); + + +void __RPC_STUB IITIPodSource_UpdateIPod_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITIPodSource_EjectIPod_Proxy( + IITIPodSource * This); + + +void __RPC_STUB IITIPodSource_EjectIPod_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITIPodSource_get_SoftwareVersion_Proxy( + IITIPodSource * This, + /* [retval][out] */ BSTR *softwareVersion); + + +void __RPC_STUB IITIPodSource_get_SoftwareVersion_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITIPodSource_INTERFACE_DEFINED__ */ + + +#ifndef __IITFileOrCDTrack_INTERFACE_DEFINED__ +#define __IITFileOrCDTrack_INTERFACE_DEFINED__ + +/* interface IITFileOrCDTrack */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITFileOrCDTrack; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("00D7FE99-7868-4cc7-AD9E-ACFD70D09566") + IITFileOrCDTrack : public IITTrack + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Location( + /* [retval][out] */ BSTR *location) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdateInfoFromFile( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Podcast( + /* [retval][out] */ VARIANT_BOOL *isPodcast) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UpdatePodcastFeed( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RememberBookmark( + /* [retval][out] */ VARIANT_BOOL *rememberBookmark) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_RememberBookmark( + /* [in] */ VARIANT_BOOL shouldRememberBookmark) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ExcludeFromShuffle( + /* [retval][out] */ VARIANT_BOOL *excludeFromShuffle) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_ExcludeFromShuffle( + /* [in] */ VARIANT_BOOL shouldExcludeFromShuffle) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Lyrics( + /* [retval][out] */ BSTR *lyrics) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Lyrics( + /* [in] */ BSTR lyrics) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Category( + /* [retval][out] */ BSTR *category) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Category( + /* [in] */ BSTR category) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Description( + /* [retval][out] */ BSTR *description) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Description( + /* [in] */ BSTR description) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LongDescription( + /* [retval][out] */ BSTR *longDescription) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_LongDescription( + /* [in] */ BSTR longDescription) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BookmarkTime( + /* [retval][out] */ long *bookmarkTime) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_BookmarkTime( + /* [in] */ long bookmarkTime) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_VideoKind( + /* [retval][out] */ ITVideoKind *videoKind) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_VideoKind( + /* [in] */ ITVideoKind videoKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SkippedCount( + /* [retval][out] */ long *skippedCount) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SkippedCount( + /* [in] */ long skippedCount) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SkippedDate( + /* [retval][out] */ DATE *skippedDate) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SkippedDate( + /* [in] */ DATE skippedDate) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PartOfGaplessAlbum( + /* [retval][out] */ VARIANT_BOOL *partOfGaplessAlbum) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_PartOfGaplessAlbum( + /* [in] */ VARIANT_BOOL shouldBePartOfGaplessAlbum) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumArtist( + /* [retval][out] */ BSTR *albumArtist) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AlbumArtist( + /* [in] */ BSTR albumArtist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Show( + /* [retval][out] */ BSTR *showName) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Show( + /* [in] */ BSTR showName) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SeasonNumber( + /* [retval][out] */ long *seasonNumber) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SeasonNumber( + /* [in] */ long seasonNumber) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EpisodeID( + /* [retval][out] */ BSTR *episodeID) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EpisodeID( + /* [in] */ BSTR episodeID) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_EpisodeNumber( + /* [retval][out] */ long *episodeNumber) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_EpisodeNumber( + /* [in] */ long episodeNumber) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size64High( + /* [retval][out] */ long *sizeHigh) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Size64Low( + /* [retval][out] */ long *sizeLow) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Unplayed( + /* [retval][out] */ VARIANT_BOOL *isUnplayed) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Unplayed( + /* [in] */ VARIANT_BOOL shouldBeUnplayed) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortAlbum( + /* [retval][out] */ BSTR *album) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortAlbum( + /* [in] */ BSTR album) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortAlbumArtist( + /* [retval][out] */ BSTR *albumArtist) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortAlbumArtist( + /* [in] */ BSTR albumArtist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortArtist( + /* [retval][out] */ BSTR *artist) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortArtist( + /* [in] */ BSTR artist) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortComposer( + /* [retval][out] */ BSTR *composer) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortComposer( + /* [in] */ BSTR composer) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortName( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortName( + /* [in] */ BSTR name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SortShow( + /* [retval][out] */ BSTR *showName) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_SortShow( + /* [in] */ BSTR showName) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reveal( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRating( + /* [retval][out] */ long *rating) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AlbumRating( + /* [in] */ long rating) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AlbumRatingKind( + /* [retval][out] */ ITRatingKind *ratingKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RatingKind( + /* [retval][out] */ ITRatingKind *ratingKind) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlists( + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITFileOrCDTrackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITFileOrCDTrack * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITFileOrCDTrack * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITFileOrCDTrack * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITFileOrCDTrack * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITFileOrCDTrack * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITFileOrCDTrack * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITFileOrCDTrack * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetITObjectIDs )( + IITFileOrCDTrack * This, + /* [out] */ long *sourceID, + /* [out] */ long *playlistID, + /* [out] */ long *trackID, + /* [out] */ long *databaseID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Name )( + IITFileOrCDTrack * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Index )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SourceID )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sourceID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlaylistID )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *playlistID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackID )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *trackID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackDatabaseID )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *databaseID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Delete )( + IITFileOrCDTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Play )( + IITFileOrCDTrack * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AddArtworkFromFile )( + IITFileOrCDTrack * This, + /* [in] */ BSTR filePath, + /* [retval][out] */ IITArtwork **iArtwork); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITFileOrCDTrack * This, + /* [retval][out] */ ITTrackKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( + IITFileOrCDTrack * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Album )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *album); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Album )( + IITFileOrCDTrack * This, + /* [in] */ BSTR album); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artist )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *artist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Artist )( + IITFileOrCDTrack * This, + /* [in] */ BSTR artist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BitRate )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *bitrate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BPM )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *beatsPerMinute); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BPM )( + IITFileOrCDTrack * This, + /* [in] */ long beatsPerMinute); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Comment )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *comment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Comment )( + IITFileOrCDTrack * This, + /* [in] */ BSTR comment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Compilation )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isCompilation); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Compilation )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBeCompilation); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Composer )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *composer); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Composer )( + IITFileOrCDTrack * This, + /* [in] */ BSTR composer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DateAdded )( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *dateAdded); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscCount )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *discCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscCount )( + IITFileOrCDTrack * This, + /* [in] */ long discCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DiscNumber )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *discNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DiscNumber )( + IITFileOrCDTrack * This, + /* [in] */ long discNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Duration )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *duration); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Enabled )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isEnabled); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Enabled )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBeEnabled); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EQ )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EQ )( + IITFileOrCDTrack * This, + /* [in] */ BSTR eq); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Finish )( + IITFileOrCDTrack * This, + /* [in] */ long finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Finish )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *finish); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Genre )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *genre); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Genre )( + IITFileOrCDTrack * This, + /* [in] */ BSTR genre); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Grouping )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *grouping); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Grouping )( + IITFileOrCDTrack * This, + /* [in] */ BSTR grouping); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_KindAsString )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ModificationDate )( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *dateModified); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedCount )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *playedCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedCount )( + IITFileOrCDTrack * This, + /* [in] */ long playedCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayedDate )( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *playedDate); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PlayedDate )( + IITFileOrCDTrack * This, + /* [in] */ DATE playedDate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlayOrderIndex )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *index); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Rating )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *rating); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Rating )( + IITFileOrCDTrack * This, + /* [in] */ long rating); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SampleRate )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sampleRate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *size); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Start )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *start); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Start )( + IITFileOrCDTrack * This, + /* [in] */ long start); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Time )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *time); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackCount )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *trackCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackCount )( + IITFileOrCDTrack * This, + /* [in] */ long trackCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_TrackNumber )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *trackNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_TrackNumber )( + IITFileOrCDTrack * This, + /* [in] */ long trackNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VolumeAdjustment )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *volumeAdjustment); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VolumeAdjustment )( + IITFileOrCDTrack * This, + /* [in] */ long volumeAdjustment); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Year )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *year); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Year )( + IITFileOrCDTrack * This, + /* [in] */ long year); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Artwork )( + IITFileOrCDTrack * This, + /* [retval][out] */ IITArtworkCollection **iArtworkCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Location )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *location); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdateInfoFromFile )( + IITFileOrCDTrack * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Podcast )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isPodcast); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UpdatePodcastFeed )( + IITFileOrCDTrack * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RememberBookmark )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *rememberBookmark); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_RememberBookmark )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldRememberBookmark); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ExcludeFromShuffle )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *excludeFromShuffle); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ExcludeFromShuffle )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldExcludeFromShuffle); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Lyrics )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *lyrics); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Lyrics )( + IITFileOrCDTrack * This, + /* [in] */ BSTR lyrics); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Category )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *category); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Category )( + IITFileOrCDTrack * This, + /* [in] */ BSTR category); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Description )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *description); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Description )( + IITFileOrCDTrack * This, + /* [in] */ BSTR description); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LongDescription )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *longDescription); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LongDescription )( + IITFileOrCDTrack * This, + /* [in] */ BSTR longDescription); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BookmarkTime )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *bookmarkTime); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BookmarkTime )( + IITFileOrCDTrack * This, + /* [in] */ long bookmarkTime); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_VideoKind )( + IITFileOrCDTrack * This, + /* [retval][out] */ ITVideoKind *videoKind); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_VideoKind )( + IITFileOrCDTrack * This, + /* [in] */ ITVideoKind videoKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SkippedCount )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *skippedCount); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SkippedCount )( + IITFileOrCDTrack * This, + /* [in] */ long skippedCount); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SkippedDate )( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *skippedDate); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SkippedDate )( + IITFileOrCDTrack * This, + /* [in] */ DATE skippedDate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PartOfGaplessAlbum )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *partOfGaplessAlbum); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_PartOfGaplessAlbum )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBePartOfGaplessAlbum); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumArtist )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *albumArtist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AlbumArtist )( + IITFileOrCDTrack * This, + /* [in] */ BSTR albumArtist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Show )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *showName); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Show )( + IITFileOrCDTrack * This, + /* [in] */ BSTR showName); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SeasonNumber )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *seasonNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SeasonNumber )( + IITFileOrCDTrack * This, + /* [in] */ long seasonNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EpisodeID )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *episodeID); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EpisodeID )( + IITFileOrCDTrack * This, + /* [in] */ BSTR episodeID); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_EpisodeNumber )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *episodeNumber); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_EpisodeNumber )( + IITFileOrCDTrack * This, + /* [in] */ long episodeNumber); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size64High )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sizeHigh); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Size64Low )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sizeLow); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Unplayed )( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isUnplayed); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Unplayed )( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBeUnplayed); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortAlbum )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *album); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortAlbum )( + IITFileOrCDTrack * This, + /* [in] */ BSTR album); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortAlbumArtist )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *albumArtist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortAlbumArtist )( + IITFileOrCDTrack * This, + /* [in] */ BSTR albumArtist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortArtist )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *artist); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortArtist )( + IITFileOrCDTrack * This, + /* [in] */ BSTR artist); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortComposer )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *composer); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortComposer )( + IITFileOrCDTrack * This, + /* [in] */ BSTR composer); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortName )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortName )( + IITFileOrCDTrack * This, + /* [in] */ BSTR name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SortShow )( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *showName); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_SortShow )( + IITFileOrCDTrack * This, + /* [in] */ BSTR showName); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reveal )( + IITFileOrCDTrack * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRating )( + IITFileOrCDTrack * This, + /* [retval][out] */ long *rating); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AlbumRating )( + IITFileOrCDTrack * This, + /* [in] */ long rating); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AlbumRatingKind )( + IITFileOrCDTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RatingKind )( + IITFileOrCDTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlists )( + IITFileOrCDTrack * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + END_INTERFACE + } IITFileOrCDTrackVtbl; + + interface IITFileOrCDTrack + { + CONST_VTBL struct IITFileOrCDTrackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITFileOrCDTrack_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITFileOrCDTrack_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITFileOrCDTrack_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITFileOrCDTrack_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITFileOrCDTrack_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITFileOrCDTrack_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITFileOrCDTrack_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITFileOrCDTrack_GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) \ + (This)->lpVtbl -> GetITObjectIDs(This,sourceID,playlistID,trackID,databaseID) + +#define IITFileOrCDTrack_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITFileOrCDTrack_put_Name(This,name) \ + (This)->lpVtbl -> put_Name(This,name) + +#define IITFileOrCDTrack_get_Index(This,index) \ + (This)->lpVtbl -> get_Index(This,index) + +#define IITFileOrCDTrack_get_SourceID(This,sourceID) \ + (This)->lpVtbl -> get_SourceID(This,sourceID) + +#define IITFileOrCDTrack_get_PlaylistID(This,playlistID) \ + (This)->lpVtbl -> get_PlaylistID(This,playlistID) + +#define IITFileOrCDTrack_get_TrackID(This,trackID) \ + (This)->lpVtbl -> get_TrackID(This,trackID) + +#define IITFileOrCDTrack_get_TrackDatabaseID(This,databaseID) \ + (This)->lpVtbl -> get_TrackDatabaseID(This,databaseID) + + +#define IITFileOrCDTrack_Delete(This) \ + (This)->lpVtbl -> Delete(This) + +#define IITFileOrCDTrack_Play(This) \ + (This)->lpVtbl -> Play(This) + +#define IITFileOrCDTrack_AddArtworkFromFile(This,filePath,iArtwork) \ + (This)->lpVtbl -> AddArtworkFromFile(This,filePath,iArtwork) + +#define IITFileOrCDTrack_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITFileOrCDTrack_get_Playlist(This,iPlaylist) \ + (This)->lpVtbl -> get_Playlist(This,iPlaylist) + +#define IITFileOrCDTrack_get_Album(This,album) \ + (This)->lpVtbl -> get_Album(This,album) + +#define IITFileOrCDTrack_put_Album(This,album) \ + (This)->lpVtbl -> put_Album(This,album) + +#define IITFileOrCDTrack_get_Artist(This,artist) \ + (This)->lpVtbl -> get_Artist(This,artist) + +#define IITFileOrCDTrack_put_Artist(This,artist) \ + (This)->lpVtbl -> put_Artist(This,artist) + +#define IITFileOrCDTrack_get_BitRate(This,bitrate) \ + (This)->lpVtbl -> get_BitRate(This,bitrate) + +#define IITFileOrCDTrack_get_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> get_BPM(This,beatsPerMinute) + +#define IITFileOrCDTrack_put_BPM(This,beatsPerMinute) \ + (This)->lpVtbl -> put_BPM(This,beatsPerMinute) + +#define IITFileOrCDTrack_get_Comment(This,comment) \ + (This)->lpVtbl -> get_Comment(This,comment) + +#define IITFileOrCDTrack_put_Comment(This,comment) \ + (This)->lpVtbl -> put_Comment(This,comment) + +#define IITFileOrCDTrack_get_Compilation(This,isCompilation) \ + (This)->lpVtbl -> get_Compilation(This,isCompilation) + +#define IITFileOrCDTrack_put_Compilation(This,shouldBeCompilation) \ + (This)->lpVtbl -> put_Compilation(This,shouldBeCompilation) + +#define IITFileOrCDTrack_get_Composer(This,composer) \ + (This)->lpVtbl -> get_Composer(This,composer) + +#define IITFileOrCDTrack_put_Composer(This,composer) \ + (This)->lpVtbl -> put_Composer(This,composer) + +#define IITFileOrCDTrack_get_DateAdded(This,dateAdded) \ + (This)->lpVtbl -> get_DateAdded(This,dateAdded) + +#define IITFileOrCDTrack_get_DiscCount(This,discCount) \ + (This)->lpVtbl -> get_DiscCount(This,discCount) + +#define IITFileOrCDTrack_put_DiscCount(This,discCount) \ + (This)->lpVtbl -> put_DiscCount(This,discCount) + +#define IITFileOrCDTrack_get_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> get_DiscNumber(This,discNumber) + +#define IITFileOrCDTrack_put_DiscNumber(This,discNumber) \ + (This)->lpVtbl -> put_DiscNumber(This,discNumber) + +#define IITFileOrCDTrack_get_Duration(This,duration) \ + (This)->lpVtbl -> get_Duration(This,duration) + +#define IITFileOrCDTrack_get_Enabled(This,isEnabled) \ + (This)->lpVtbl -> get_Enabled(This,isEnabled) + +#define IITFileOrCDTrack_put_Enabled(This,shouldBeEnabled) \ + (This)->lpVtbl -> put_Enabled(This,shouldBeEnabled) + +#define IITFileOrCDTrack_get_EQ(This,eq) \ + (This)->lpVtbl -> get_EQ(This,eq) + +#define IITFileOrCDTrack_put_EQ(This,eq) \ + (This)->lpVtbl -> put_EQ(This,eq) + +#define IITFileOrCDTrack_put_Finish(This,finish) \ + (This)->lpVtbl -> put_Finish(This,finish) + +#define IITFileOrCDTrack_get_Finish(This,finish) \ + (This)->lpVtbl -> get_Finish(This,finish) + +#define IITFileOrCDTrack_get_Genre(This,genre) \ + (This)->lpVtbl -> get_Genre(This,genre) + +#define IITFileOrCDTrack_put_Genre(This,genre) \ + (This)->lpVtbl -> put_Genre(This,genre) + +#define IITFileOrCDTrack_get_Grouping(This,grouping) \ + (This)->lpVtbl -> get_Grouping(This,grouping) + +#define IITFileOrCDTrack_put_Grouping(This,grouping) \ + (This)->lpVtbl -> put_Grouping(This,grouping) + +#define IITFileOrCDTrack_get_KindAsString(This,kind) \ + (This)->lpVtbl -> get_KindAsString(This,kind) + +#define IITFileOrCDTrack_get_ModificationDate(This,dateModified) \ + (This)->lpVtbl -> get_ModificationDate(This,dateModified) + +#define IITFileOrCDTrack_get_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> get_PlayedCount(This,playedCount) + +#define IITFileOrCDTrack_put_PlayedCount(This,playedCount) \ + (This)->lpVtbl -> put_PlayedCount(This,playedCount) + +#define IITFileOrCDTrack_get_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> get_PlayedDate(This,playedDate) + +#define IITFileOrCDTrack_put_PlayedDate(This,playedDate) \ + (This)->lpVtbl -> put_PlayedDate(This,playedDate) + +#define IITFileOrCDTrack_get_PlayOrderIndex(This,index) \ + (This)->lpVtbl -> get_PlayOrderIndex(This,index) + +#define IITFileOrCDTrack_get_Rating(This,rating) \ + (This)->lpVtbl -> get_Rating(This,rating) + +#define IITFileOrCDTrack_put_Rating(This,rating) \ + (This)->lpVtbl -> put_Rating(This,rating) + +#define IITFileOrCDTrack_get_SampleRate(This,sampleRate) \ + (This)->lpVtbl -> get_SampleRate(This,sampleRate) + +#define IITFileOrCDTrack_get_Size(This,size) \ + (This)->lpVtbl -> get_Size(This,size) + +#define IITFileOrCDTrack_get_Start(This,start) \ + (This)->lpVtbl -> get_Start(This,start) + +#define IITFileOrCDTrack_put_Start(This,start) \ + (This)->lpVtbl -> put_Start(This,start) + +#define IITFileOrCDTrack_get_Time(This,time) \ + (This)->lpVtbl -> get_Time(This,time) + +#define IITFileOrCDTrack_get_TrackCount(This,trackCount) \ + (This)->lpVtbl -> get_TrackCount(This,trackCount) + +#define IITFileOrCDTrack_put_TrackCount(This,trackCount) \ + (This)->lpVtbl -> put_TrackCount(This,trackCount) + +#define IITFileOrCDTrack_get_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> get_TrackNumber(This,trackNumber) + +#define IITFileOrCDTrack_put_TrackNumber(This,trackNumber) \ + (This)->lpVtbl -> put_TrackNumber(This,trackNumber) + +#define IITFileOrCDTrack_get_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> get_VolumeAdjustment(This,volumeAdjustment) + +#define IITFileOrCDTrack_put_VolumeAdjustment(This,volumeAdjustment) \ + (This)->lpVtbl -> put_VolumeAdjustment(This,volumeAdjustment) + +#define IITFileOrCDTrack_get_Year(This,year) \ + (This)->lpVtbl -> get_Year(This,year) + +#define IITFileOrCDTrack_put_Year(This,year) \ + (This)->lpVtbl -> put_Year(This,year) + +#define IITFileOrCDTrack_get_Artwork(This,iArtworkCollection) \ + (This)->lpVtbl -> get_Artwork(This,iArtworkCollection) + + +#define IITFileOrCDTrack_get_Location(This,location) \ + (This)->lpVtbl -> get_Location(This,location) + +#define IITFileOrCDTrack_UpdateInfoFromFile(This) \ + (This)->lpVtbl -> UpdateInfoFromFile(This) + +#define IITFileOrCDTrack_get_Podcast(This,isPodcast) \ + (This)->lpVtbl -> get_Podcast(This,isPodcast) + +#define IITFileOrCDTrack_UpdatePodcastFeed(This) \ + (This)->lpVtbl -> UpdatePodcastFeed(This) + +#define IITFileOrCDTrack_get_RememberBookmark(This,rememberBookmark) \ + (This)->lpVtbl -> get_RememberBookmark(This,rememberBookmark) + +#define IITFileOrCDTrack_put_RememberBookmark(This,shouldRememberBookmark) \ + (This)->lpVtbl -> put_RememberBookmark(This,shouldRememberBookmark) + +#define IITFileOrCDTrack_get_ExcludeFromShuffle(This,excludeFromShuffle) \ + (This)->lpVtbl -> get_ExcludeFromShuffle(This,excludeFromShuffle) + +#define IITFileOrCDTrack_put_ExcludeFromShuffle(This,shouldExcludeFromShuffle) \ + (This)->lpVtbl -> put_ExcludeFromShuffle(This,shouldExcludeFromShuffle) + +#define IITFileOrCDTrack_get_Lyrics(This,lyrics) \ + (This)->lpVtbl -> get_Lyrics(This,lyrics) + +#define IITFileOrCDTrack_put_Lyrics(This,lyrics) \ + (This)->lpVtbl -> put_Lyrics(This,lyrics) + +#define IITFileOrCDTrack_get_Category(This,category) \ + (This)->lpVtbl -> get_Category(This,category) + +#define IITFileOrCDTrack_put_Category(This,category) \ + (This)->lpVtbl -> put_Category(This,category) + +#define IITFileOrCDTrack_get_Description(This,description) \ + (This)->lpVtbl -> get_Description(This,description) + +#define IITFileOrCDTrack_put_Description(This,description) \ + (This)->lpVtbl -> put_Description(This,description) + +#define IITFileOrCDTrack_get_LongDescription(This,longDescription) \ + (This)->lpVtbl -> get_LongDescription(This,longDescription) + +#define IITFileOrCDTrack_put_LongDescription(This,longDescription) \ + (This)->lpVtbl -> put_LongDescription(This,longDescription) + +#define IITFileOrCDTrack_get_BookmarkTime(This,bookmarkTime) \ + (This)->lpVtbl -> get_BookmarkTime(This,bookmarkTime) + +#define IITFileOrCDTrack_put_BookmarkTime(This,bookmarkTime) \ + (This)->lpVtbl -> put_BookmarkTime(This,bookmarkTime) + +#define IITFileOrCDTrack_get_VideoKind(This,videoKind) \ + (This)->lpVtbl -> get_VideoKind(This,videoKind) + +#define IITFileOrCDTrack_put_VideoKind(This,videoKind) \ + (This)->lpVtbl -> put_VideoKind(This,videoKind) + +#define IITFileOrCDTrack_get_SkippedCount(This,skippedCount) \ + (This)->lpVtbl -> get_SkippedCount(This,skippedCount) + +#define IITFileOrCDTrack_put_SkippedCount(This,skippedCount) \ + (This)->lpVtbl -> put_SkippedCount(This,skippedCount) + +#define IITFileOrCDTrack_get_SkippedDate(This,skippedDate) \ + (This)->lpVtbl -> get_SkippedDate(This,skippedDate) + +#define IITFileOrCDTrack_put_SkippedDate(This,skippedDate) \ + (This)->lpVtbl -> put_SkippedDate(This,skippedDate) + +#define IITFileOrCDTrack_get_PartOfGaplessAlbum(This,partOfGaplessAlbum) \ + (This)->lpVtbl -> get_PartOfGaplessAlbum(This,partOfGaplessAlbum) + +#define IITFileOrCDTrack_put_PartOfGaplessAlbum(This,shouldBePartOfGaplessAlbum) \ + (This)->lpVtbl -> put_PartOfGaplessAlbum(This,shouldBePartOfGaplessAlbum) + +#define IITFileOrCDTrack_get_AlbumArtist(This,albumArtist) \ + (This)->lpVtbl -> get_AlbumArtist(This,albumArtist) + +#define IITFileOrCDTrack_put_AlbumArtist(This,albumArtist) \ + (This)->lpVtbl -> put_AlbumArtist(This,albumArtist) + +#define IITFileOrCDTrack_get_Show(This,showName) \ + (This)->lpVtbl -> get_Show(This,showName) + +#define IITFileOrCDTrack_put_Show(This,showName) \ + (This)->lpVtbl -> put_Show(This,showName) + +#define IITFileOrCDTrack_get_SeasonNumber(This,seasonNumber) \ + (This)->lpVtbl -> get_SeasonNumber(This,seasonNumber) + +#define IITFileOrCDTrack_put_SeasonNumber(This,seasonNumber) \ + (This)->lpVtbl -> put_SeasonNumber(This,seasonNumber) + +#define IITFileOrCDTrack_get_EpisodeID(This,episodeID) \ + (This)->lpVtbl -> get_EpisodeID(This,episodeID) + +#define IITFileOrCDTrack_put_EpisodeID(This,episodeID) \ + (This)->lpVtbl -> put_EpisodeID(This,episodeID) + +#define IITFileOrCDTrack_get_EpisodeNumber(This,episodeNumber) \ + (This)->lpVtbl -> get_EpisodeNumber(This,episodeNumber) + +#define IITFileOrCDTrack_put_EpisodeNumber(This,episodeNumber) \ + (This)->lpVtbl -> put_EpisodeNumber(This,episodeNumber) + +#define IITFileOrCDTrack_get_Size64High(This,sizeHigh) \ + (This)->lpVtbl -> get_Size64High(This,sizeHigh) + +#define IITFileOrCDTrack_get_Size64Low(This,sizeLow) \ + (This)->lpVtbl -> get_Size64Low(This,sizeLow) + +#define IITFileOrCDTrack_get_Unplayed(This,isUnplayed) \ + (This)->lpVtbl -> get_Unplayed(This,isUnplayed) + +#define IITFileOrCDTrack_put_Unplayed(This,shouldBeUnplayed) \ + (This)->lpVtbl -> put_Unplayed(This,shouldBeUnplayed) + +#define IITFileOrCDTrack_get_SortAlbum(This,album) \ + (This)->lpVtbl -> get_SortAlbum(This,album) + +#define IITFileOrCDTrack_put_SortAlbum(This,album) \ + (This)->lpVtbl -> put_SortAlbum(This,album) + +#define IITFileOrCDTrack_get_SortAlbumArtist(This,albumArtist) \ + (This)->lpVtbl -> get_SortAlbumArtist(This,albumArtist) + +#define IITFileOrCDTrack_put_SortAlbumArtist(This,albumArtist) \ + (This)->lpVtbl -> put_SortAlbumArtist(This,albumArtist) + +#define IITFileOrCDTrack_get_SortArtist(This,artist) \ + (This)->lpVtbl -> get_SortArtist(This,artist) + +#define IITFileOrCDTrack_put_SortArtist(This,artist) \ + (This)->lpVtbl -> put_SortArtist(This,artist) + +#define IITFileOrCDTrack_get_SortComposer(This,composer) \ + (This)->lpVtbl -> get_SortComposer(This,composer) + +#define IITFileOrCDTrack_put_SortComposer(This,composer) \ + (This)->lpVtbl -> put_SortComposer(This,composer) + +#define IITFileOrCDTrack_get_SortName(This,name) \ + (This)->lpVtbl -> get_SortName(This,name) + +#define IITFileOrCDTrack_put_SortName(This,name) \ + (This)->lpVtbl -> put_SortName(This,name) + +#define IITFileOrCDTrack_get_SortShow(This,showName) \ + (This)->lpVtbl -> get_SortShow(This,showName) + +#define IITFileOrCDTrack_put_SortShow(This,showName) \ + (This)->lpVtbl -> put_SortShow(This,showName) + +#define IITFileOrCDTrack_Reveal(This) \ + (This)->lpVtbl -> Reveal(This) + +#define IITFileOrCDTrack_get_AlbumRating(This,rating) \ + (This)->lpVtbl -> get_AlbumRating(This,rating) + +#define IITFileOrCDTrack_put_AlbumRating(This,rating) \ + (This)->lpVtbl -> put_AlbumRating(This,rating) + +#define IITFileOrCDTrack_get_AlbumRatingKind(This,ratingKind) \ + (This)->lpVtbl -> get_AlbumRatingKind(This,ratingKind) + +#define IITFileOrCDTrack_get_RatingKind(This,ratingKind) \ + (This)->lpVtbl -> get_RatingKind(This,ratingKind) + +#define IITFileOrCDTrack_get_Playlists(This,iPlaylistCollection) \ + (This)->lpVtbl -> get_Playlists(This,iPlaylistCollection) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Location_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *location); + + +void __RPC_STUB IITFileOrCDTrack_get_Location_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_UpdateInfoFromFile_Proxy( + IITFileOrCDTrack * This); + + +void __RPC_STUB IITFileOrCDTrack_UpdateInfoFromFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Podcast_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isPodcast); + + +void __RPC_STUB IITFileOrCDTrack_get_Podcast_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_UpdatePodcastFeed_Proxy( + IITFileOrCDTrack * This); + + +void __RPC_STUB IITFileOrCDTrack_UpdatePodcastFeed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_RememberBookmark_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *rememberBookmark); + + +void __RPC_STUB IITFileOrCDTrack_get_RememberBookmark_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_RememberBookmark_Proxy( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldRememberBookmark); + + +void __RPC_STUB IITFileOrCDTrack_put_RememberBookmark_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_ExcludeFromShuffle_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *excludeFromShuffle); + + +void __RPC_STUB IITFileOrCDTrack_get_ExcludeFromShuffle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_ExcludeFromShuffle_Proxy( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldExcludeFromShuffle); + + +void __RPC_STUB IITFileOrCDTrack_put_ExcludeFromShuffle_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Lyrics_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *lyrics); + + +void __RPC_STUB IITFileOrCDTrack_get_Lyrics_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Lyrics_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR lyrics); + + +void __RPC_STUB IITFileOrCDTrack_put_Lyrics_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Category_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *category); + + +void __RPC_STUB IITFileOrCDTrack_get_Category_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Category_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR category); + + +void __RPC_STUB IITFileOrCDTrack_put_Category_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Description_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *description); + + +void __RPC_STUB IITFileOrCDTrack_get_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Description_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR description); + + +void __RPC_STUB IITFileOrCDTrack_put_Description_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_LongDescription_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *longDescription); + + +void __RPC_STUB IITFileOrCDTrack_get_LongDescription_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_LongDescription_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR longDescription); + + +void __RPC_STUB IITFileOrCDTrack_put_LongDescription_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_BookmarkTime_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *bookmarkTime); + + +void __RPC_STUB IITFileOrCDTrack_get_BookmarkTime_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_BookmarkTime_Proxy( + IITFileOrCDTrack * This, + /* [in] */ long bookmarkTime); + + +void __RPC_STUB IITFileOrCDTrack_put_BookmarkTime_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_VideoKind_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ ITVideoKind *videoKind); + + +void __RPC_STUB IITFileOrCDTrack_get_VideoKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_VideoKind_Proxy( + IITFileOrCDTrack * This, + /* [in] */ ITVideoKind videoKind); + + +void __RPC_STUB IITFileOrCDTrack_put_VideoKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SkippedCount_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *skippedCount); + + +void __RPC_STUB IITFileOrCDTrack_get_SkippedCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SkippedCount_Proxy( + IITFileOrCDTrack * This, + /* [in] */ long skippedCount); + + +void __RPC_STUB IITFileOrCDTrack_put_SkippedCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SkippedDate_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ DATE *skippedDate); + + +void __RPC_STUB IITFileOrCDTrack_get_SkippedDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SkippedDate_Proxy( + IITFileOrCDTrack * This, + /* [in] */ DATE skippedDate); + + +void __RPC_STUB IITFileOrCDTrack_put_SkippedDate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_PartOfGaplessAlbum_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *partOfGaplessAlbum); + + +void __RPC_STUB IITFileOrCDTrack_get_PartOfGaplessAlbum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_PartOfGaplessAlbum_Proxy( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBePartOfGaplessAlbum); + + +void __RPC_STUB IITFileOrCDTrack_put_PartOfGaplessAlbum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_AlbumArtist_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *albumArtist); + + +void __RPC_STUB IITFileOrCDTrack_get_AlbumArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_AlbumArtist_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR albumArtist); + + +void __RPC_STUB IITFileOrCDTrack_put_AlbumArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Show_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *showName); + + +void __RPC_STUB IITFileOrCDTrack_get_Show_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Show_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR showName); + + +void __RPC_STUB IITFileOrCDTrack_put_Show_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SeasonNumber_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *seasonNumber); + + +void __RPC_STUB IITFileOrCDTrack_get_SeasonNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SeasonNumber_Proxy( + IITFileOrCDTrack * This, + /* [in] */ long seasonNumber); + + +void __RPC_STUB IITFileOrCDTrack_put_SeasonNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_EpisodeID_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *episodeID); + + +void __RPC_STUB IITFileOrCDTrack_get_EpisodeID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_EpisodeID_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR episodeID); + + +void __RPC_STUB IITFileOrCDTrack_put_EpisodeID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_EpisodeNumber_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *episodeNumber); + + +void __RPC_STUB IITFileOrCDTrack_get_EpisodeNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_EpisodeNumber_Proxy( + IITFileOrCDTrack * This, + /* [in] */ long episodeNumber); + + +void __RPC_STUB IITFileOrCDTrack_put_EpisodeNumber_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Size64High_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sizeHigh); + + +void __RPC_STUB IITFileOrCDTrack_get_Size64High_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Size64Low_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *sizeLow); + + +void __RPC_STUB IITFileOrCDTrack_get_Size64Low_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Unplayed_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ VARIANT_BOOL *isUnplayed); + + +void __RPC_STUB IITFileOrCDTrack_get_Unplayed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_Unplayed_Proxy( + IITFileOrCDTrack * This, + /* [in] */ VARIANT_BOOL shouldBeUnplayed); + + +void __RPC_STUB IITFileOrCDTrack_put_Unplayed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortAlbum_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *album); + + +void __RPC_STUB IITFileOrCDTrack_get_SortAlbum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortAlbum_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR album); + + +void __RPC_STUB IITFileOrCDTrack_put_SortAlbum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortAlbumArtist_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *albumArtist); + + +void __RPC_STUB IITFileOrCDTrack_get_SortAlbumArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortAlbumArtist_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR albumArtist); + + +void __RPC_STUB IITFileOrCDTrack_put_SortAlbumArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortArtist_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *artist); + + +void __RPC_STUB IITFileOrCDTrack_get_SortArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortArtist_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR artist); + + +void __RPC_STUB IITFileOrCDTrack_put_SortArtist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortComposer_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *composer); + + +void __RPC_STUB IITFileOrCDTrack_get_SortComposer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortComposer_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR composer); + + +void __RPC_STUB IITFileOrCDTrack_put_SortComposer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortName_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IITFileOrCDTrack_get_SortName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortName_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR name); + + +void __RPC_STUB IITFileOrCDTrack_put_SortName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_SortShow_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ BSTR *showName); + + +void __RPC_STUB IITFileOrCDTrack_get_SortShow_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_SortShow_Proxy( + IITFileOrCDTrack * This, + /* [in] */ BSTR showName); + + +void __RPC_STUB IITFileOrCDTrack_put_SortShow_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_Reveal_Proxy( + IITFileOrCDTrack * This); + + +void __RPC_STUB IITFileOrCDTrack_Reveal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_AlbumRating_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ long *rating); + + +void __RPC_STUB IITFileOrCDTrack_get_AlbumRating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_put_AlbumRating_Proxy( + IITFileOrCDTrack * This, + /* [in] */ long rating); + + +void __RPC_STUB IITFileOrCDTrack_put_AlbumRating_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_AlbumRatingKind_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + +void __RPC_STUB IITFileOrCDTrack_get_AlbumRatingKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_RatingKind_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ ITRatingKind *ratingKind); + + +void __RPC_STUB IITFileOrCDTrack_get_RatingKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITFileOrCDTrack_get_Playlists_Proxy( + IITFileOrCDTrack * This, + /* [retval][out] */ IITPlaylistCollection **iPlaylistCollection); + + +void __RPC_STUB IITFileOrCDTrack_get_Playlists_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITFileOrCDTrack_INTERFACE_DEFINED__ */ + + +#ifndef __IITPlaylistWindow_INTERFACE_DEFINED__ +#define __IITPlaylistWindow_INTERFACE_DEFINED__ + +/* interface IITPlaylistWindow */ +/* [hidden][unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IITPlaylistWindow; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("349CBB45-2E5A-4822-8E4A-A75555A186F7") + IITPlaylistWindow : public IITWindow + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_SelectedTracks( + /* [retval][out] */ IITTrackCollection **iTrackCollection) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Playlist( + /* [retval][out] */ IITPlaylist **iPlaylist) = 0; + + }; + +#else /* C style interface */ + + typedef struct IITPlaylistWindowVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IITPlaylistWindow * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IITPlaylistWindow * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IITPlaylistWindow * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IITPlaylistWindow * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IITPlaylistWindow * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IITPlaylistWindow * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IITPlaylistWindow * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IITPlaylistWindow * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Kind )( + IITPlaylistWindow * This, + /* [retval][out] */ ITWindowKind *kind); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Visible )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isVisible); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Visible )( + IITPlaylistWindow * This, + /* [in] */ VARIANT_BOOL shouldBeVisible); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Resizable )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isResizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Minimized )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMinimized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Minimized )( + IITPlaylistWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMinimized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximizable )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximizable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Maximized )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isMaximized); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Maximized )( + IITPlaylistWindow * This, + /* [in] */ VARIANT_BOOL shouldBeMaximized); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomable )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomable); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Zoomed )( + IITPlaylistWindow * This, + /* [retval][out] */ VARIANT_BOOL *isZoomed); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Zoomed )( + IITPlaylistWindow * This, + /* [in] */ VARIANT_BOOL shouldBeZoomed); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Top )( + IITPlaylistWindow * This, + /* [retval][out] */ long *top); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Top )( + IITPlaylistWindow * This, + /* [in] */ long top); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Left )( + IITPlaylistWindow * This, + /* [retval][out] */ long *left); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Left )( + IITPlaylistWindow * This, + /* [in] */ long left); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Bottom )( + IITPlaylistWindow * This, + /* [retval][out] */ long *bottom); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Bottom )( + IITPlaylistWindow * This, + /* [in] */ long bottom); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Right )( + IITPlaylistWindow * This, + /* [retval][out] */ long *right); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Right )( + IITPlaylistWindow * This, + /* [in] */ long right); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Width )( + IITPlaylistWindow * This, + /* [retval][out] */ long *width); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Width )( + IITPlaylistWindow * This, + /* [in] */ long width); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Height )( + IITPlaylistWindow * This, + /* [retval][out] */ long *height); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Height )( + IITPlaylistWindow * This, + /* [in] */ long height); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_SelectedTracks )( + IITPlaylistWindow * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Playlist )( + IITPlaylistWindow * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + END_INTERFACE + } IITPlaylistWindowVtbl; + + interface IITPlaylistWindow + { + CONST_VTBL struct IITPlaylistWindowVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IITPlaylistWindow_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IITPlaylistWindow_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IITPlaylistWindow_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IITPlaylistWindow_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IITPlaylistWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IITPlaylistWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IITPlaylistWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IITPlaylistWindow_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IITPlaylistWindow_get_Kind(This,kind) \ + (This)->lpVtbl -> get_Kind(This,kind) + +#define IITPlaylistWindow_get_Visible(This,isVisible) \ + (This)->lpVtbl -> get_Visible(This,isVisible) + +#define IITPlaylistWindow_put_Visible(This,shouldBeVisible) \ + (This)->lpVtbl -> put_Visible(This,shouldBeVisible) + +#define IITPlaylistWindow_get_Resizable(This,isResizable) \ + (This)->lpVtbl -> get_Resizable(This,isResizable) + +#define IITPlaylistWindow_get_Minimized(This,isMinimized) \ + (This)->lpVtbl -> get_Minimized(This,isMinimized) + +#define IITPlaylistWindow_put_Minimized(This,shouldBeMinimized) \ + (This)->lpVtbl -> put_Minimized(This,shouldBeMinimized) + +#define IITPlaylistWindow_get_Maximizable(This,isMaximizable) \ + (This)->lpVtbl -> get_Maximizable(This,isMaximizable) + +#define IITPlaylistWindow_get_Maximized(This,isMaximized) \ + (This)->lpVtbl -> get_Maximized(This,isMaximized) + +#define IITPlaylistWindow_put_Maximized(This,shouldBeMaximized) \ + (This)->lpVtbl -> put_Maximized(This,shouldBeMaximized) + +#define IITPlaylistWindow_get_Zoomable(This,isZoomable) \ + (This)->lpVtbl -> get_Zoomable(This,isZoomable) + +#define IITPlaylistWindow_get_Zoomed(This,isZoomed) \ + (This)->lpVtbl -> get_Zoomed(This,isZoomed) + +#define IITPlaylistWindow_put_Zoomed(This,shouldBeZoomed) \ + (This)->lpVtbl -> put_Zoomed(This,shouldBeZoomed) + +#define IITPlaylistWindow_get_Top(This,top) \ + (This)->lpVtbl -> get_Top(This,top) + +#define IITPlaylistWindow_put_Top(This,top) \ + (This)->lpVtbl -> put_Top(This,top) + +#define IITPlaylistWindow_get_Left(This,left) \ + (This)->lpVtbl -> get_Left(This,left) + +#define IITPlaylistWindow_put_Left(This,left) \ + (This)->lpVtbl -> put_Left(This,left) + +#define IITPlaylistWindow_get_Bottom(This,bottom) \ + (This)->lpVtbl -> get_Bottom(This,bottom) + +#define IITPlaylistWindow_put_Bottom(This,bottom) \ + (This)->lpVtbl -> put_Bottom(This,bottom) + +#define IITPlaylistWindow_get_Right(This,right) \ + (This)->lpVtbl -> get_Right(This,right) + +#define IITPlaylistWindow_put_Right(This,right) \ + (This)->lpVtbl -> put_Right(This,right) + +#define IITPlaylistWindow_get_Width(This,width) \ + (This)->lpVtbl -> get_Width(This,width) + +#define IITPlaylistWindow_put_Width(This,width) \ + (This)->lpVtbl -> put_Width(This,width) + +#define IITPlaylistWindow_get_Height(This,height) \ + (This)->lpVtbl -> get_Height(This,height) + +#define IITPlaylistWindow_put_Height(This,height) \ + (This)->lpVtbl -> put_Height(This,height) + + +#define IITPlaylistWindow_get_SelectedTracks(This,iTrackCollection) \ + (This)->lpVtbl -> get_SelectedTracks(This,iTrackCollection) + +#define IITPlaylistWindow_get_Playlist(This,iPlaylist) \ + (This)->lpVtbl -> get_Playlist(This,iPlaylist) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistWindow_get_SelectedTracks_Proxy( + IITPlaylistWindow * This, + /* [retval][out] */ IITTrackCollection **iTrackCollection); + + +void __RPC_STUB IITPlaylistWindow_get_SelectedTracks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IITPlaylistWindow_get_Playlist_Proxy( + IITPlaylistWindow * This, + /* [retval][out] */ IITPlaylist **iPlaylist); + + +void __RPC_STUB IITPlaylistWindow_get_Playlist_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IITPlaylistWindow_INTERFACE_DEFINED__ */ + +#endif /* __iTunesLib_LIBRARY_DEFINED__ */ + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/Plugins/PluginiTunes/iTunesCOMWindowsSDK/iTunesCOMInterface_i.c b/Plugins/PluginiTunes/iTunesCOMWindowsSDK/iTunesCOMInterface_i.c deleted file mode 100644 index 9402c13e..00000000 --- a/Plugins/PluginiTunes/iTunesCOMWindowsSDK/iTunesCOMInterface_i.c +++ /dev/null @@ -1,175 +0,0 @@ - - -/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ - -/* link this file in with the server and any clients */ - - - /* File created by MIDL compiler version 6.00.0366 */ -/* at Wed Jun 25 17:02:20 2008 - */ -/* Compiler settings for iTunesCOMInterface.idl: - Oicf, W1, Zp8, env=Win32 (32b run) - protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: - __declspec(uuid()), __declspec(selectany), __declspec(novtable) - DECLSPEC_UUID(), MIDL_INTERFACE() -*/ -//@@MIDL_FILE_HEADING( ) - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ - - -#ifdef __cplusplus -extern "C"{ -#endif - - -#include <rpc.h> -#include <rpcndr.h> - -#ifdef _MIDL_USE_GUIDDEF_ - -#ifndef INITGUID -#define INITGUID -#include <guiddef.h> -#undef INITGUID -#else -#include <guiddef.h> -#endif - -#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ - DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) - -#else // !_MIDL_USE_GUIDDEF_ - -#ifndef __IID_DEFINED__ -#define __IID_DEFINED__ - -typedef struct _IID -{ - unsigned long x; - unsigned short s1; - unsigned short s2; - unsigned char c[8]; -} IID; - -#endif // __IID_DEFINED__ - -#ifndef CLSID_DEFINED -#define CLSID_DEFINED -typedef IID CLSID; -#endif // CLSID_DEFINED - -#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ - const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} - -#endif !_MIDL_USE_GUIDDEF_ - -MIDL_DEFINE_GUID(IID, LIBID_iTunesLib,0x9E93C96F,0xCF0D,0x43f6,0x8B,0xA8,0xB8,0x07,0xA3,0x37,0x07,0x12); - - -MIDL_DEFINE_GUID(IID, IID_IITObject,0x9FAB0E27,0x70D7,0x4e3a,0x99,0x65,0xB0,0xC8,0xB8,0x86,0x9B,0xB6); - - -MIDL_DEFINE_GUID(IID, IID_IITSource,0xAEC1C4D3,0xAEF1,0x4255,0xB8,0x92,0x3E,0x3D,0x13,0xAD,0xFD,0xF9); - - -MIDL_DEFINE_GUID(IID, IID_IITSourceCollection,0x2FF6CE20,0xFF87,0x4183,0xB0,0xB3,0xF3,0x23,0xD0,0x47,0xAF,0x41); - - -MIDL_DEFINE_GUID(IID, IID_IITEncoder,0x1CF95A1C,0x55FE,0x4f45,0xA2,0xD3,0x85,0xAC,0x6C,0x50,0x4A,0x73); - - -MIDL_DEFINE_GUID(IID, IID_IITEncoderCollection,0x8862BCA9,0x168D,0x4549,0xA9,0xD5,0xAD,0xB3,0x5E,0x55,0x3B,0xA6); - - -MIDL_DEFINE_GUID(IID, IID_IITEQPreset,0x5BE75F4F,0x68FA,0x4212,0xAC,0xB7,0xBE,0x44,0xEA,0x56,0x97,0x59); - - -MIDL_DEFINE_GUID(IID, IID_IITEQPresetCollection,0xAEF4D111,0x3331,0x48da,0xB0,0xC2,0xB4,0x68,0xD5,0xD6,0x1D,0x08); - - -MIDL_DEFINE_GUID(IID, IID_IITPlaylist,0x3D5E072F,0x2A77,0x4b17,0x9E,0x73,0xE0,0x3B,0x77,0xCC,0xCC,0xA9); - - -MIDL_DEFINE_GUID(IID, IID_IITOperationStatus,0x206479C9,0xFE32,0x4f9b,0xA1,0x8A,0x47,0x5A,0xC9,0x39,0xB4,0x79); - - -MIDL_DEFINE_GUID(IID, IID_IITConvertOperationStatus,0x7063AAF6,0xABA0,0x493b,0xB4,0xFC,0x92,0x0A,0x9F,0x10,0x58,0x75); - - -MIDL_DEFINE_GUID(IID, IID_IITLibraryPlaylist,0x53AE1704,0x491C,0x4289,0x94,0xA0,0x95,0x88,0x15,0x67,0x5A,0x3D); - - -MIDL_DEFINE_GUID(IID, IID_IITUserPlaylist,0x0A504DED,0xA0B5,0x465a,0x8A,0x94,0x50,0xE2,0x0D,0x7D,0xF6,0x92); - - -MIDL_DEFINE_GUID(IID, IID_IITTrack,0x4CB0915D,0x1E54,0x4727,0xBA,0xF3,0xCE,0x6C,0xC9,0xA2,0x25,0xA1); - - -MIDL_DEFINE_GUID(IID, IID_IITTrackCollection,0x755D76F1,0x6B85,0x4ce4,0x8F,0x5F,0xF8,0x8D,0x97,0x43,0xDC,0xD8); - - -MIDL_DEFINE_GUID(IID, IID_IITVisual,0x340F3315,0xED72,0x4c09,0x9A,0xCF,0x21,0xEB,0x4B,0xDF,0x99,0x31); - - -MIDL_DEFINE_GUID(IID, IID_IITVisualCollection,0x88A4CCDD,0x114F,0x4043,0xB6,0x9B,0x84,0xD4,0xE6,0x27,0x49,0x57); - - -MIDL_DEFINE_GUID(IID, IID_IITWindow,0x370D7BE0,0x3A89,0x4a42,0xB9,0x02,0xC7,0x5F,0xC1,0x38,0xBE,0x09); - - -MIDL_DEFINE_GUID(IID, IID_IITBrowserWindow,0xC999F455,0xC4D5,0x4aa4,0x82,0x77,0xF9,0x97,0x53,0x69,0x99,0x74); - - -MIDL_DEFINE_GUID(IID, IID_IITWindowCollection,0x3D8DE381,0x6C0E,0x481f,0xA8,0x65,0xE2,0x38,0x5F,0x59,0xFA,0x43); - - -MIDL_DEFINE_GUID(IID, IID_IiTunes,0x9DD6680B,0x3EDC,0x40db,0xA7,0x71,0xE6,0xFE,0x48,0x32,0xE3,0x4A); - - -MIDL_DEFINE_GUID(IID, DIID__IiTunesEvents,0x5846EB78,0x317E,0x4b6f,0xB0,0xC3,0x11,0xEE,0x8C,0x8F,0xEE,0xF2); - - -MIDL_DEFINE_GUID(IID, DIID__IITConvertOperationStatusEvents,0x5C47A705,0x8E8A,0x45a1,0x9E,0xED,0x71,0xC9,0x93,0xF0,0xBF,0x60); - - -MIDL_DEFINE_GUID(CLSID, CLSID_iTunesApp,0xDC0C2640,0x1415,0x4644,0x87,0x5C,0x6F,0x4D,0x76,0x98,0x39,0xBA); - - -MIDL_DEFINE_GUID(CLSID, CLSID_iTunesConvertOperationStatus,0xD06596AD,0xC900,0x41b2,0xBC,0x68,0x1B,0x48,0x64,0x50,0xFC,0x56); - - -MIDL_DEFINE_GUID(IID, IID_IITArtwork,0xD0A6C1F8,0xBF3D,0x4cd8,0xAC,0x47,0xFE,0x32,0xBD,0xD1,0x72,0x57); - - -MIDL_DEFINE_GUID(IID, IID_IITArtworkCollection,0xBF2742D7,0x418C,0x4858,0x9A,0xF9,0x29,0x81,0xB0,0x62,0xD2,0x3E); - - -MIDL_DEFINE_GUID(IID, IID_IITURLTrack,0x1116E3B5,0x29FD,0x4393,0xA7,0xBD,0x45,0x4E,0x5E,0x32,0x79,0x00); - - -MIDL_DEFINE_GUID(IID, IID_IITAudioCDPlaylist,0xCF496DF3,0x0FED,0x4d7d,0x9B,0xD8,0x52,0x9B,0x6E,0x8A,0x08,0x2E); - - -MIDL_DEFINE_GUID(IID, IID_IITPlaylistCollection,0xFF194254,0x909D,0x4437,0x9C,0x50,0x3A,0xAC,0x2A,0xE6,0x30,0x5C); - - -MIDL_DEFINE_GUID(IID, IID_IITIPodSource,0xCF4D8ACE,0x1720,0x4fb9,0xB0,0xAE,0x98,0x77,0x24,0x9E,0x89,0xB0); - - -MIDL_DEFINE_GUID(IID, IID_IITFileOrCDTrack,0x00D7FE99,0x7868,0x4cc7,0xAD,0x9E,0xAC,0xFD,0x70,0xD0,0x95,0x66); - - -MIDL_DEFINE_GUID(IID, IID_IITPlaylistWindow,0x349CBB45,0x2E5A,0x4822,0x8E,0x4A,0xA7,0x55,0x55,0xA1,0x86,0xF7); - -#undef MIDL_DEFINE_GUID - -#ifdef __cplusplus -} -#endif - - - diff --git a/Plugins/PluginiTunes/iTunesPlugin.cpp b/Plugins/PluginiTunes/iTunesPlugin.cpp index 3ba46cdb..875c518d 100644 --- a/Plugins/PluginiTunes/iTunesPlugin.cpp +++ b/Plugins/PluginiTunes/iTunesPlugin.cpp @@ -1,980 +1,980 @@ -/* - Copyright (C) 2009 Elestel - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include <windows.h> -#include <comdef.h> -#include "iTunesCOMInterface.h" -#include "../../Library/Export.h" // Rainmeter's exported functions -#include <map> -#include <time.h> - -const int VOLUME_STEP = 5; - -/* The exported functions */ -extern "C" -{ -__declspec( dllexport ) UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id); -__declspec( dllexport ) void Finalize(HMODULE instance, UINT id); -__declspec( dllexport ) LPCTSTR GetString(UINT id, UINT flags); -__declspec( dllexport ) UINT Update(UINT id); -__declspec( dllexport ) UINT GetPluginVersion(); -__declspec( dllexport ) LPCTSTR GetPluginAuthor(); -__declspec( dllexport ) void ExecuteBang(LPCTSTR args, UINT id); -} - -enum COMMAND_TYPE -{ - COMMAND_POWER, - COMMAND_TOGGLEITUNES, - COMMAND_TOGGLEVISUALS, - COMMAND_SOUNDVOLUMEUP, - COMMAND_SOUNDVOLUMEDOWN, -// Player Controls - COMMAND_BACKTRACK, - COMMAND_FASTFORWARD, - COMMAND_NEXTTRACK, - COMMAND_PAUSE, - COMMAND_PLAY, - COMMAND_PLAYFILE, - COMMAND_PLAYPAUSE, - COMMAND_PREVIOUSTRACK, - COMMAND_RESUME, - COMMAND_REWIND, - COMMAND_STOP, - COMMAND_GETPLAYERBUTTONSSTATE, - COMMAND_PLAYERBUTTONCLICKED, -// Conversion Methods - COMMAND_CONVERTFILE, - COMMAND_CONVERTFILES, - COMMAND_TRACK, - COMMAND_TRACKS, - COMMAND_FILE2, - COMMAND_FILES2, - COMMAND_TRACK2, - COMMAND_TRACKS2, -// Miscellaneous Methods - COMMAND_CHECKVERSION, - COMMAND_GETITOBJECTBYID, - COMMAND_CREATEPLAYLIST, - COMMAND_OPENURL, - COMMAND_GOTOMUSICSTOREHOMEPAGE, - COMMAND_UPDATEIPOD, - COMMAND_QUIT, - COMMAND_CREATEEQPRESET, - COMMAND_CREATEPLAYLISTINSOURCE, - COMMAND_SUBSCRIBETOPODCAST, - COMMAND_UPDATEPODCASTFEEDS, - COMMAND_CREATEFOLDER, - COMMAND_CREATEFOLDERINSOURCE, - COMMAND_GETITOBJECTPERSISTENTIDS, -// Collection Properties - //TODO: Sources - //TODO: Encoders - //TODO: EQPresets - //TODO: Visuals - //TODO: Windows -// Sound Properties - COMMAND_GETSOUNDVOLUME, - COMMAND_SETSOUNDVOLUME, - COMMAND_GETMUTE, - COMMAND_SETMUTE, -// Player Properties - COMMAND_GETPLAYERSTATE, - COMMAND_GETPLAYERPOSITIONPERCENT, - COMMAND_GETPLAYERPOSITION, - COMMAND_SETPLAYERPOSITION, -// Encoder Properties - //TODO: CurrentEncoder -// Visual Properties - //TODO: VisualsEnabled - //TODO: FullScreenVisuals - //TODO: VisualSize - //TODO: CurrentVisual -// EQ Properties - COMMAND_GETEQENABLED, - COMMAND_SETEQENABLED, - COMMAND_GETCURRENTEQPRESET, - COMMAND_SETCURRENTEQPRESET, -// Streaming Properties - COMMAND_GETCURRENTSTREAMTITLE, - COMMAND_GETCURRENTSTREAMURL, -// Miscellaneous Properties - //TODO: BrowserWindow - //TODO: EQWindow - //TODO: LibrarySource - //TODO: LibraryPlaylist - // CurrentTrack - COMMAND_GETCURRENTTRACK_ALBUM, - COMMAND_GETCURRENTTRACK_ARTIST, - COMMAND_GETCURRENTTRACK_BITRATE, - COMMAND_GETCURRENTTRACK_BPM, - COMMAND_GETCURRENTTRACK_COMMENT, - COMMAND_GETCURRENTTRACK_COMPOSER, - COMMAND_GETCURRENTTRACK_EQ, - COMMAND_GETCURRENTTRACK_GENRE, - COMMAND_GETCURRENTTRACK_KINDASSTRING, - COMMAND_GETCURRENTTRACK_NAME, - COMMAND_GETCURRENTTRACK_RATING, - COMMAND_GETCURRENTTRACK_SAMPLERATE, - COMMAND_GETCURRENTTRACK_SIZE, - COMMAND_GETCURRENTTRACK_TIME, - COMMAND_GETCURRENTTRACK_TRACKCOUNT, - COMMAND_GETCURRENTTRACK_TRACKNUMBER, - COMMAND_GETCURRENTTRACK_YEAR, - COMMAND_GETCURRENTTRACK_ARTWORK, - //TODO: other CurrentTrack properties - //TODO: CurrentPlaylist - COMMAND_GETVERSION, - //TODO: AppCommandMessageProcessingEnabled - //TODO: ForceToForegroundOnDialog - //TODO: CanSetShuffle - //TODO: CanSetSongRepeat - //TODO: ConvertOperationStatus - //TODO: SoundVolumeControlEnabled - //TODO: LibraryXMLPath - //TODO: ITObjectPersistentIDHigh - //TODO: ITObjectPersistentIDLow - - COMMAND_COUNT -}; - -const static wchar_t* CommandName[COMMAND_COUNT] = -{ - L"Power", // COMMAND_POWER - L"ToggleiTunes", // COMMAND_TOGGLEITUNES - L"ToggleVisuals", // COMMAND_TOGGLEVISUALS - L"SoundVolumeUp", // COMMAND_SOUNDVOLUMEUP - L"SoundVolumeDown", // COMMAND_SOUNDVOLUMEDOWN -// Player Controls - L"BackTrack", // COMMAND_BACKTRACK - L"FastForward", // COMMAND_FASTFORWARD - L"NextTrack", // COMMAND_NEXTTRACK - L"Pause", // COMMAND_PAUSE - L"Play", // COMMAND_PLAY - L"PlayFile", // COMMAND_PLAYFILE - L"PlayPause", // COMMAND_PLAYPAUSE - L"PreviousTrack", // COMMAND_PREVIOUSTRACK - L"Resume", // COMMAND_RESUME - L"Rewind", // COMMAND_REWIND - L"Stop", // COMMAND_STOP - L"GetPlayerButtonsState", // COMMAND_GETPLAYERBUTTONSSTATE - L"PlayerButtonClicked", // COMMAND_PLAYERBUTTONCLICKED -// Conversion Methods - L"ConvertFile", // COMMAND_CONVERTFILE - L"ConvertFiles", // COMMAND_CONVERTFILES - L"ConvertTrack", // COMMAND_TRACK - L"ConvertTracks", // COMMAND_TRACKS - L"ConvertFile2", // COMMAND_FILE2 - L"ConvertFiles2", // COMMAND_FILES2 - L"ConvertTrack2", // COMMAND_TRACK2 - L"ConvertTracks2", // COMMAND_TRACKS2 -// Miscellaneous Methods - L"CheckVersion", // COMMAND_CHECKVERSION - L"GetITObjectByID", // COMMAND_GETITOBJECTBYID - L"CreatePlaylist", // COMMAND_CREATEPLAYLIST - L"OpenURL", // COMMAND_OPENURL - L"GotoMusicStoreHomePage", // COMMAND_GOTOMUSICSTOREHOMEPAGE - L"UpdateIPod", // COMMAND_UPDATEIPOD - L"Quit", // COMMAND_QUIT - L"CreateEQPreset", // COMMAND_CREATEEQPRESET - L"CreatePlaylistInSource", // COMMAND_CREATEPLAYLISTINSOURCE - L"SubscribeToPodcast", // COMMAND_SUBSCRIBETOPODCAST - L"UpdatePodcastFeeds", // COMMAND_UPDATEPODCASTFEEDS - L"CreateFolder", // COMMAND_CREATEFOLDER - L"CreateFolderInSource", // COMMAND_CREATEFOLDERINSOURCE - L"GetITObjectPersistentIDs",// COMMAND_GETITOBJECTPERSISTENTIDS -// Collection Properties - //TODO: Sources - //TODO: Encoders - //TODO: EQPresets - //TODO: Visuals - //TODO: Windows -// Sound Properties - L"GetSoundVolume", // COMMAND_GETSOUNDVOLUME - L"SetSoundVolume", // COMMAND_SETSOUNDVOLUME - L"GetMute", // COMMAND_GETMUTE - L"SetMute", // COMMAND_SETMUTE -// Player Properties - L"GetPlayerState", // COMMAND_GETPLAYERSTATE - L"GetPlayerPositionPercent",// COMMAND_GETPLAYERPOSITIONPERCENT - L"GetPlayerPosition", // COMMAND_GETPLAYERPOSITION - L"SetPlayerPosition", // COMMAND_SETPLAYERPOSITION -// Encoder Properties - //TODO: CurrentEncoder -// Visual Properties - //TODO: VisualsEnabled - //TODO: FullScreenVisuals - //TODO: VisualSize - //TODO: CurrentVisual -// EQ Properties - L"GetEQEnabled", // COMMAND_GETEQENABLED - L"SetEQEnabled", // COMMAND_SETEQENABLED - L"GetCurrentEQPreset", // COMMAND_GETCURRENTEQPRESET - L"SetCurrentEQPreset", // COMMAND_SETCURRENTEQPRESET -// Streaming Properties - L"GetCurrentStreamTitle", // COMMAND_GETCURRENTSTREAMTITLE - L"GetCurrentStreamURL", // COMMAND_GETCURRENTSTREAMURL -// Miscellaneous Properties - //TODO: BrowserWindow - //TODO: EQWindow - //TODO: LibrarySource - //TODO: LibraryPlaylist - // CurrentTrack - L"GetCurrentTrackAlbum", // COMMAND_GETCURRENTTRACK_ALBUM - L"GetCurrentTrackArtist", // COMMAND_GETCURRENTTRACK_ARTIST - L"GetCurrentTrackBitrate", // COMMAND_GETCURRENTTRACK_BITRATE - L"GetCurrentTrackBPM", // COMMAND_GETCURRENTTRACK_BPM - L"GetCurrentTrackComment", // COMMAND_GETCURRENTTRACK_COMMENT - L"GetCurrentTrackComposer", // COMMAND_GETCURRENTTRACK_COMPOSER - L"GetCurrentTrackEQ", // COMMAND_GETCURRENTTRACK_EQ - L"GetCurrentTrackGenre", // COMMAND_GETCURRENTTRACK_GENRE - L"GetCurrentTrackKindAsString", // COMMAND_GETCURRENTTRACK_KINDASSTRING - L"GetCurrentTrackName", // COMMAND_GETCURRENTTRACK_NAME - L"GetCurrentTrackRating", // COMMAND_GETCURRENTTRACK_RATING - L"GetCurrentTrackSampleRate", // COMMAND_GETCURRENTTRACK_SAMPLERATE - L"GetCurrentTrackSize", // COMMAND_GETCURRENTTRACK_SIZE - L"GetCurrentTrackTime", // COMMAND_GETCURRENTTRACK_TIME - L"GetCurrentTrackTrackCount", // COMMAND_GETCURRENTTRACK_TRACKCOUNT - L"GetCurrentTrackTrackNumber", // COMMAND_GETCURRENTTRACK_TRACKNUMBER - L"GetCurrentTrackYear", // COMMAND_GETCURRENTTRACK_YEAR - L"GetCurrentTrackArtwork", // COMMAND_GETCURRENTTRACK_ARTWORK - //TODO: other CurrentTrack properties - // TODO: CurrentPlaylist - L"GetVersion", // COMMAND_GETVERSION - //TODO: AppCommandMessageProcessingEnabled - //TODO: ForceToForegroundOnDialog - //TODO: CanSetShuffle - //TODO: CanSetSongRepeat - //TODO: ConvertOperationStatus - //TODO: SoundVolumeControlEnabled - //TODO: LibraryXMLPath - //TODO: ITObjectPersistentIDHigh - //TODO: ITObjectPersistentIDLow -}; - -_COM_SMARTPTR_TYPEDEF(IiTunes, __uuidof(IiTunes)); -_COM_SMARTPTR_TYPEDEF(IITTrack, __uuidof(IITTrack)); -_COM_SMARTPTR_TYPEDEF(IITArtworkCollection, __uuidof(IITArtworkCollection)); -_COM_SMARTPTR_TYPEDEF(IITArtwork, __uuidof(IITArtwork)); -_COM_SMARTPTR_TYPEDEF(IITBrowserWindow, __uuidof(IITBrowserWindow)); - -static IiTunesPtr iTunes; -static bool CoInitialized = false; -static bool InstanceCreated = false; - -typedef std::map<UINT, COMMAND_TYPE> CCommandIdMap; -static CCommandIdMap CommandIdMap; - -static wchar_t BaseDir[MAX_PATH]; - -static IITTrackPtr CurrentTrack; -static wchar_t CurrentTrackArtworkPath[MAX_PATH]; -static wchar_t DefaultTrackArtworkPath[MAX_PATH]; -static bool updateCurrentTrack() -{ - static clock_t lastClock = 0; - clock_t currentClock = clock(); - if (0 == lastClock || currentClock - lastClock > CLOCKS_PER_SEC) - { - wsprintf(CurrentTrackArtworkPath, L"%s%s", BaseDir, DefaultTrackArtworkPath); - if (CurrentTrack != nullptr) - CurrentTrack.Release(); - if (FAILED(iTunes->get_CurrentTrack(&CurrentTrack)) || !CurrentTrack) - return false; - - lastClock = currentClock; - - IITArtworkCollectionPtr artworkCollection; - if (SUCCEEDED(CurrentTrack->get_Artwork(&artworkCollection))) - { - long count; - artworkCollection->get_Count(&count); - - IITArtworkPtr artwork; - ITArtworkFormat artworkFormat; - if (count > 0 && - SUCCEEDED(artworkCollection->get_Item(1, &artwork)) && - SUCCEEDED(artwork->get_Format(&artworkFormat))) - { - _bstr_t path; - - wsprintf(CurrentTrackArtworkPath, L"%s\\iTunesArtwork", BaseDir); - CreateDirectory(CurrentTrackArtworkPath, nullptr); - - switch (artworkFormat) - { - case ITArtworkFormatJPEG: - wcscat(CurrentTrackArtworkPath, L"\\artwork.jpg"); - break; - case ITArtworkFormatPNG : - wcscat(CurrentTrackArtworkPath, L"\\artwork.png"); - break; - case ITArtworkFormatBMP: - wcscat(CurrentTrackArtworkPath, L"\\artwork.bmp"); - break; - } - path = CurrentTrackArtworkPath; - if (FAILED(artwork->SaveArtworkToFile(path))) - { - wsprintf(CurrentTrackArtworkPath, L"%s%s", BaseDir, DefaultTrackArtworkPath); - } - } - } - } - return (nullptr != CurrentTrack); -} - -static bool iTunesAboutToPromptUserToQuit = false; -// from http://www.codeproject.com/KB/cs/itunestray.aspx?msg=2300786#xx2300786xx -class CiTunesEventHandler : public _IiTunesEvents -{ -private: - long m_dwRefCount; - ITypeInfo* m_pITypeInfo; // Pointer to type information. - -public: - CiTunesEventHandler() - { - m_dwRefCount=0; - ITypeLib* pITypeLib = nullptr ; - HRESULT hr = ::LoadRegTypeLib(LIBID_iTunesLib, 1, 5, 0x00, &pITypeLib) ; - // Get type information for the interface of the object. - hr = pITypeLib->GetTypeInfoOfGuid(DIID__IiTunesEvents, &m_pITypeInfo) ; - pITypeLib->Release() ; - } - ~CiTunesEventHandler() - {} - - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) - { - if ((iid == IID_IDispatch)||(iid == DIID__IiTunesEvents)) { - m_dwRefCount++; - *ppvObject = this;//(_IiTunesEvents *)this; - return S_OK; - } - if (iid == IID_IUnknown) { - m_dwRefCount++; - *ppvObject = this;//(IUnknown *)this; - return S_OK; - } - return E_NOINTERFACE; - } - ULONG STDMETHODCALLTYPE CiTunesEventHandler::AddRef() - { - InterlockedIncrement(&m_dwRefCount); - return m_dwRefCount; - } - ULONG STDMETHODCALLTYPE Release() - { - InterlockedDecrement(&m_dwRefCount); - if (m_dwRefCount == 0) { - delete this; - return 0; - } - return m_dwRefCount; - } - HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *){return E_NOTIMPL;}; - HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT,LCID,ITypeInfo ** ){return E_NOTIMPL;}; - HRESULT STDMETHODCALLTYPE GetIDsOfNames(const IID &,LPOLESTR * ,UINT,LCID,DISPID *){return E_NOTIMPL;}; - HRESULT STDMETHODCALLTYPE Invoke(DISPID dispidMember, REFIID, LCID,WORD, DISPPARAMS* pdispparams, VARIANT*,EXCEPINFO*, UINT*) - { - switch (dispidMember) //look in the documentation for "enum ITEvent" to get the numbers for the functions you want to implement - { - case 9: // AboutToPromptUserToQuitEvent - CurrentTrack.Release(); - iTunes->Quit(); - iTunes.Release(); - InstanceCreated = false; - iTunesAboutToPromptUserToQuit = true; - break; - default: - break; - } - return S_OK; - } -}; - -static CiTunesEventHandler* iTunesEventHandler; -static void initEventHandler() -{ - IConnectionPointContainer* icpc; - iTunes->QueryInterface(IID_IConnectionPointContainer, (void **)&icpc); - IConnectionPoint* icp; - icpc->FindConnectionPoint(DIID__IiTunesEvents, &icp); - icpc->Release(); - DWORD dwAdvise; - iTunesEventHandler = new CiTunesEventHandler(); - icp->Advise(iTunesEventHandler, &dwAdvise); - icp->Release(); -} - -/* -This function is called when the measure is initialized. -The function must return the maximum value that can be measured. -The return value can also be 0, which means that Rainmeter will -track the maximum value automatically. The parameters for this -function are: - -instance The instance of this DLL -iniFile The name of the ini-file (usually Rainmeter.ini) -section The name of the section in the ini-file for this measure -id The identifier for the measure. This is used to identify the measures that use the same plugin. -*/ -UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id) -{ - if (!CoInitialized) - { - ::CoInitialize(nullptr); - wcsncpy(BaseDir, iniFile, MAX_PATH); - BaseDir[MAX_PATH - 1] = 0; - wchar_t* lastBackslash = wcsrchr(BaseDir, L'\\'); - if (lastBackslash) - lastBackslash[1] = 0; - CoInitialized = true; - } - - if (CoInitialized && !InstanceCreated && (FindWindow(L"iTunesApp", L"iTunes") || FindWindow(L"iTunes", L"iTunes"))) - { - if (SUCCEEDED(iTunes.CreateInstance(CLSID_iTunesApp, nullptr, CLSCTX_LOCAL_SERVER))) - { - InstanceCreated = true; - initEventHandler(); - } - else - { - LSLog(LOG_ERROR, nullptr, L"iTunesPlugin.dll: Unable to create instance"); - } - } - - const wchar_t* type = ReadConfigString(section, L"Command", L""); - for (int i = 0; i < COMMAND_COUNT; i++) - { - if (CommandName[i] && type && _wcsicmp(CommandName[i], type) == 0) - { - CommandIdMap[id] = (COMMAND_TYPE)i; - - if (COMMAND_GETCURRENTTRACK_ARTWORK == (COMMAND_TYPE)i) - { - const wchar_t* defaultArtwork = ReadConfigString(section, L"DefaultArtwork", L""); - wcscpy(DefaultTrackArtworkPath, defaultArtwork); - } - } - } - - return 0; -} - -/* -This function is called when new value should be measured. -The function returns the new value. -*/ -UINT Update(UINT id) -{ - if (!CoInitialized || !InstanceCreated) - { - // Check if the iTunes window has appeared - if (FindWindow(L"iTunesApp", L"iTunes") || FindWindow(L"iTunes", L"iTunes")) - { - if (!iTunesAboutToPromptUserToQuit && SUCCEEDED(iTunes.CreateInstance(CLSID_iTunesApp, nullptr, CLSCTX_LOCAL_SERVER))) - { - InstanceCreated = true; - initEventHandler(); - } - else - { - LSLog(LOG_ERROR, nullptr, L"iTunesPlugin.dll: Unable to create instance"); - return 0; - } - } - else - { - iTunesAboutToPromptUserToQuit = false; - return 0; - } - } - - CCommandIdMap::const_iterator it = CommandIdMap.find(id); - COMMAND_TYPE command = (it != CommandIdMap.end()) ? it->second : COMMAND_COUNT; - - switch (command) - { - case COMMAND_GETSOUNDVOLUME: // value: 0 ~ 100 - { - long volume; - iTunes->get_SoundVolume(&volume); - return volume; - } - case COMMAND_GETPLAYERPOSITIONPERCENT: // value: 0 ~ 100 - { - long pos; - iTunes->get_PlayerPosition(&pos); - if (!updateCurrentTrack()) - return 0; - long duration; - CurrentTrack->get_Duration(&duration); - return duration ? pos * 100 / duration : 0; - } - case COMMAND_GETPLAYERPOSITION: // value: seconds - { - long pos; - iTunes->get_PlayerPosition(&pos); - return pos; - } - } - return 0; -} - -/* -This function is called when the value should be -returned as a string. -*/ -#define BUFFER_SIZE 256 -LPCTSTR GetString(UINT id, UINT flags) -{ - //Error Check - static wchar_t buffer[BUFFER_SIZE]; - buffer[0] = 0; - if (!CoInitialized) - { - wsprintf(buffer, L"Fail to initialize"); - return buffer; - } - - CCommandIdMap::const_iterator it = CommandIdMap.find(id); - COMMAND_TYPE command = (it != CommandIdMap.end()) ? it->second : COMMAND_COUNT; - - if (!InstanceCreated) - { - //wsprintf(buffer, L"iTunes is not running"); - if (COMMAND_GETCURRENTTRACK_ARTWORK == command) - wsprintf(buffer, L"%s%s", BaseDir, DefaultTrackArtworkPath); - return buffer; - } - - if (command >= COMMAND_GETCURRENTTRACK_ALBUM && command <= COMMAND_GETCURRENTTRACK_ARTWORK) - { - if (!updateCurrentTrack()) - return buffer; - - BSTR bstrValue; - long longValue; - bool bstrUsed = false; - - switch (command) - { - case COMMAND_GETCURRENTTRACK_ALBUM: - bstrUsed = SUCCEEDED(CurrentTrack->get_Album(&bstrValue)); - break; - case COMMAND_GETCURRENTTRACK_ARTIST: - bstrUsed = SUCCEEDED(CurrentTrack->get_Artist(&bstrValue)); - break; - case COMMAND_GETCURRENTTRACK_BITRATE: - if (SUCCEEDED(CurrentTrack->get_BitRate(&longValue))) - { - wsprintf(buffer, L"%dkbps", longValue); - } - break; - case COMMAND_GETCURRENTTRACK_BPM: - if (SUCCEEDED(CurrentTrack->get_BPM(&longValue))) - { - wsprintf(buffer, L"%dbpm", longValue); - } - break; - case COMMAND_GETCURRENTTRACK_COMMENT: - bstrUsed = SUCCEEDED(CurrentTrack->get_Comment(&bstrValue)); - break; - case COMMAND_GETCURRENTTRACK_COMPOSER: - bstrUsed = SUCCEEDED(CurrentTrack->get_Composer(&bstrValue)); - break; - case COMMAND_GETCURRENTTRACK_EQ: - bstrUsed = SUCCEEDED(CurrentTrack->get_EQ(&bstrValue)); - break; - case COMMAND_GETCURRENTTRACK_GENRE: - bstrUsed = SUCCEEDED(CurrentTrack->get_Genre(&bstrValue)); - break; - case COMMAND_GETCURRENTTRACK_KINDASSTRING: - bstrUsed = SUCCEEDED(CurrentTrack->get_KindAsString(&bstrValue)); - break; - case COMMAND_GETCURRENTTRACK_NAME: - bstrUsed = SUCCEEDED(CurrentTrack->get_Name(&bstrValue)); - break; - case COMMAND_GETCURRENTTRACK_RATING: - if (SUCCEEDED(CurrentTrack->get_Rating(&longValue))) - { - wsprintf(buffer, L"%d/100", longValue); - } - break; - case COMMAND_GETCURRENTTRACK_SAMPLERATE: - if (SUCCEEDED(CurrentTrack->get_SampleRate(&longValue))) - { - wsprintf(buffer, L"%dHz", longValue); - } - break; - case COMMAND_GETCURRENTTRACK_SIZE: - if (SUCCEEDED(CurrentTrack->get_Size(&longValue))) - { - if (longValue < 1024) - wsprintf(buffer, L"%dbytes", longValue); - else if (longValue < 1024 * 1024) - wsprintf(buffer, L"%d.%dKbytes", longValue/1024, (longValue*10/1024)%10); - else - wsprintf(buffer, L"%d.%dMbytes", longValue/1024/1024, (longValue*10/1024/1024)%10); - } - break; - case COMMAND_GETCURRENTTRACK_TIME: - bstrUsed = SUCCEEDED(CurrentTrack->get_Time(&bstrValue)); - break; - case COMMAND_GETCURRENTTRACK_TRACKCOUNT: - if (SUCCEEDED(CurrentTrack->get_TrackCount(&longValue))) - { - wsprintf(buffer, L"%d", longValue); - } - break; - case COMMAND_GETCURRENTTRACK_TRACKNUMBER: - if (SUCCEEDED(CurrentTrack->get_TrackNumber(&longValue))) - { - wsprintf(buffer, L"%d", longValue); - } - break; - case COMMAND_GETCURRENTTRACK_YEAR: - if (SUCCEEDED(CurrentTrack->get_Year(&longValue))) - { - wsprintf(buffer, L"%d", longValue); - } - break; - case COMMAND_GETCURRENTTRACK_ARTWORK: - { - wsprintf(buffer, L"%s", CurrentTrackArtworkPath); - break; - } - } - - if (bstrUsed && bstrValue) - { - wcsncpy(buffer, bstrValue, BUFFER_SIZE - 1); - buffer[BUFFER_SIZE - 1] = 0; - SysFreeString(bstrValue); - } - return buffer; - } - - wsprintf(buffer, L"Type Incorrect"); - return buffer; -} - -void ExecuteBang(LPCTSTR args, UINT id) -{ - if (!CoInitialized) - { - return; - } - - COMMAND_TYPE command; - - if (wcslen(args) == 0) - { - CCommandIdMap::const_iterator it = CommandIdMap.find(id); - command = (it != CommandIdMap.end()) ? it->second : COMMAND_COUNT; - } - else - { - if (_wcsicmp(args, L"Backtrack") == 0) - { - command = COMMAND_BACKTRACK; - } - else if (_wcsicmp(args, L"FastForward") == 0) - { - command = COMMAND_FASTFORWARD; - } - else if (_wcsicmp(args, L"NextTrack") == 0) - { - command = COMMAND_NEXTTRACK; - } - else if (_wcsicmp(args, L"Pause") == 0) - { - command = COMMAND_PAUSE; - } - else if (_wcsicmp(args, L"Play") == 0) - { - command = COMMAND_PLAY; - } - else if (_wcsicmp(args, L"PlayPause") == 0) - { - command = COMMAND_PLAYPAUSE; - } - else if (_wcsicmp(args, L"Power") == 0) - { - command = COMMAND_POWER; - } - else if (_wcsicmp(args, L"PreviousTrack") == 0) - { - command = COMMAND_PREVIOUSTRACK; - } - else if (_wcsicmp(args, L"Resume") == 0) - { - command = COMMAND_RESUME; - } - else if (_wcsicmp(args, L"Rewind") == 0) - { - command = COMMAND_REWIND; - } - else if (_wcsicmp(args, L"Stop") == 0) - { - command = COMMAND_STOP; - } - else if (_wcsicmp(args, L"SoundVolumeUp") == 0) - { - command = COMMAND_SOUNDVOLUMEUP; - } - else if (_wcsicmp(args, L"SoundVolumeDown") == 0) - { - command = COMMAND_SOUNDVOLUMEDOWN; - } - else if (_wcsicmp(args, L"ToggleiTunes") == 0) - { - command = COMMAND_TOGGLEITUNES; - } - else if (_wcsicmp(args, L"ToggleVisuals") == 0) - { - command = COMMAND_TOGGLEVISUALS; - } - else if (_wcsicmp(args, L"UpdateiPod") == 0) - { - command = COMMAND_UPDATEIPOD; - } - else if (_wcsicmp(args, L"UpdatePodcastFeeds") == 0) - { - command = COMMAND_UPDATEPODCASTFEEDS; - } - else if (_wcsicmp(args, L"GotoMusicStoreHomePage") == 0) - { - command = COMMAND_GOTOMUSICSTOREHOMEPAGE; - } - else if (_wcsicmp(args, L"Quit") == 0) - { - command = COMMAND_QUIT; - } - else - { - LSLog(LOG_NOTICE, nullptr, L"iTunesPlugin.dll: Invalid Command"); - return; - } - } - - if (!InstanceCreated) - { - if (COMMAND_POWER == command && CoInitialized && SUCCEEDED(iTunes.CreateInstance(CLSID_iTunesApp, nullptr, CLSCTX_LOCAL_SERVER))) - { - IITBrowserWindowPtr browserWindow; - if (SUCCEEDED(iTunes->get_BrowserWindow(&browserWindow))) - { - browserWindow->put_Minimized(VARIANT_TRUE); - } - InstanceCreated = true; - } - return; - } - - switch (command) - { - case COMMAND_POWER: - { - iTunes->Quit(); - iTunes.Release(); - InstanceCreated = false; - break; - } - case COMMAND_TOGGLEITUNES: - { - IITBrowserWindowPtr browserWindow; - if (FAILED(iTunes->get_BrowserWindow(&browserWindow))) - { - break; - } - VARIANT_BOOL minimized; - if (SUCCEEDED(browserWindow->get_Minimized(&minimized))) - { - browserWindow->put_Minimized((VARIANT_TRUE == minimized) ? VARIANT_FALSE : VARIANT_TRUE); - } - break; - } - case COMMAND_TOGGLEVISUALS: - { - VARIANT_BOOL visualsEnabled; - if (SUCCEEDED(iTunes->get_VisualsEnabled(&visualsEnabled))) - { - iTunes->put_VisualsEnabled((VARIANT_TRUE == visualsEnabled) ? VARIANT_FALSE : VARIANT_TRUE); - } - break; - } - case COMMAND_SOUNDVOLUMEUP: - { - long volume; - iTunes->get_SoundVolume(&volume); - volume += VOLUME_STEP; - (volume > 100) ? volume = 100 : 0; - iTunes->put_SoundVolume(volume); - break; - } - case COMMAND_SOUNDVOLUMEDOWN: - { - long volume; - iTunes->get_SoundVolume(&volume); - volume -= VOLUME_STEP; - (volume < 0) ? volume = 0 : 0; - iTunes->put_SoundVolume(volume); - break; - } - - // Player Controls - case COMMAND_BACKTRACK: - iTunes->BackTrack(); - break; - case COMMAND_FASTFORWARD: - iTunes->FastForward(); - break; - case COMMAND_NEXTTRACK: - iTunes->NextTrack(); - break; - case COMMAND_PAUSE: - iTunes->Pause(); - break; - case COMMAND_PLAY: - iTunes->Pause(); - iTunes->Play(); - break; - case COMMAND_PLAYFILE: - //TODO: - break; - case COMMAND_PLAYPAUSE: - iTunes->PlayPause(); - break; - case COMMAND_PREVIOUSTRACK: - iTunes->PreviousTrack(); - break; - case COMMAND_RESUME: - iTunes->Resume(); - break; - case COMMAND_REWIND: - iTunes->Rewind(); - break; - case COMMAND_STOP: - iTunes->Stop(); - break; - case COMMAND_GETPLAYERBUTTONSSTATE: - //TODO: - break; - case COMMAND_PLAYERBUTTONCLICKED: - //TODO: - break; - - // Conversion Methods - case COMMAND_CONVERTFILE: - //TODO: - break; - case COMMAND_CONVERTFILES: - //TODO: - break; - case COMMAND_TRACK: - //TODO: - break; - case COMMAND_TRACKS: - //TODO: - break; - case COMMAND_FILE2: - //TODO: - break; - case COMMAND_FILES2: - //TODO: - break; - case COMMAND_TRACK2: - //TODO: - break; - case COMMAND_TRACKS2: - //TODO: - break; - - // Miscellaneous Methods - case COMMAND_CHECKVERSION: - //TODO: - break; - case COMMAND_GETITOBJECTBYID: - //TODO: - break; - case COMMAND_CREATEPLAYLIST: - //TODO: - break; - case COMMAND_OPENURL: - //TODO: - break; - case COMMAND_GOTOMUSICSTOREHOMEPAGE: - iTunes->GotoMusicStoreHomePage(); - break; - case COMMAND_UPDATEIPOD: - iTunes->UpdateIPod(); - break; - case COMMAND_QUIT: - iTunes->Quit(); - break; - case COMMAND_CREATEEQPRESET: - //TODO: - break; - case COMMAND_CREATEPLAYLISTINSOURCE: - //TODO: - break; - case COMMAND_SUBSCRIBETOPODCAST: - //TODO: - break; - case COMMAND_UPDATEPODCASTFEEDS: - iTunes->UpdatePodcastFeeds(); - break; - case COMMAND_CREATEFOLDER: - //TODO: - break; - case COMMAND_CREATEFOLDERINSOURCE: - //TODO: - break; - case COMMAND_GETITOBJECTPERSISTENTIDS: - //TODO: - break; - } -} - -/* -If the measure needs to free resources before quitting. -The plugin can export Finalize function, which is called -when Rainmeter quits (or refreshes). -*/ -void Finalize(HMODULE instance, UINT id) -{ - if (InstanceCreated) - { - iTunes.Release(); - InstanceCreated = false; - } -} - -UINT GetPluginVersion() -{ - return 0002; -} - -LPCTSTR GetPluginAuthor() -{ - return L"Elestel"; +/* + Copyright (C) 2009 Elestel + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <windows.h> +#include <comdef.h> +#include "iTunesCOMInterface.h" +#include "../../Library/Export.h" // Rainmeter's exported functions +#include <map> +#include <time.h> + +const int VOLUME_STEP = 5; + +/* The exported functions */ +extern "C" +{ +__declspec( dllexport ) UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id); +__declspec( dllexport ) void Finalize(HMODULE instance, UINT id); +__declspec( dllexport ) LPCTSTR GetString(UINT id, UINT flags); +__declspec( dllexport ) UINT Update(UINT id); +__declspec( dllexport ) UINT GetPluginVersion(); +__declspec( dllexport ) LPCTSTR GetPluginAuthor(); +__declspec( dllexport ) void ExecuteBang(LPCTSTR args, UINT id); +} + +enum COMMAND_TYPE +{ + COMMAND_POWER, + COMMAND_TOGGLEITUNES, + COMMAND_TOGGLEVISUALS, + COMMAND_SOUNDVOLUMEUP, + COMMAND_SOUNDVOLUMEDOWN, +// Player Controls + COMMAND_BACKTRACK, + COMMAND_FASTFORWARD, + COMMAND_NEXTTRACK, + COMMAND_PAUSE, + COMMAND_PLAY, + COMMAND_PLAYFILE, + COMMAND_PLAYPAUSE, + COMMAND_PREVIOUSTRACK, + COMMAND_RESUME, + COMMAND_REWIND, + COMMAND_STOP, + COMMAND_GETPLAYERBUTTONSSTATE, + COMMAND_PLAYERBUTTONCLICKED, +// Conversion Methods + COMMAND_CONVERTFILE, + COMMAND_CONVERTFILES, + COMMAND_TRACK, + COMMAND_TRACKS, + COMMAND_FILE2, + COMMAND_FILES2, + COMMAND_TRACK2, + COMMAND_TRACKS2, +// Miscellaneous Methods + COMMAND_CHECKVERSION, + COMMAND_GETITOBJECTBYID, + COMMAND_CREATEPLAYLIST, + COMMAND_OPENURL, + COMMAND_GOTOMUSICSTOREHOMEPAGE, + COMMAND_UPDATEIPOD, + COMMAND_QUIT, + COMMAND_CREATEEQPRESET, + COMMAND_CREATEPLAYLISTINSOURCE, + COMMAND_SUBSCRIBETOPODCAST, + COMMAND_UPDATEPODCASTFEEDS, + COMMAND_CREATEFOLDER, + COMMAND_CREATEFOLDERINSOURCE, + COMMAND_GETITOBJECTPERSISTENTIDS, +// Collection Properties + //TODO: Sources + //TODO: Encoders + //TODO: EQPresets + //TODO: Visuals + //TODO: Windows +// Sound Properties + COMMAND_GETSOUNDVOLUME, + COMMAND_SETSOUNDVOLUME, + COMMAND_GETMUTE, + COMMAND_SETMUTE, +// Player Properties + COMMAND_GETPLAYERSTATE, + COMMAND_GETPLAYERPOSITIONPERCENT, + COMMAND_GETPLAYERPOSITION, + COMMAND_SETPLAYERPOSITION, +// Encoder Properties + //TODO: CurrentEncoder +// Visual Properties + //TODO: VisualsEnabled + //TODO: FullScreenVisuals + //TODO: VisualSize + //TODO: CurrentVisual +// EQ Properties + COMMAND_GETEQENABLED, + COMMAND_SETEQENABLED, + COMMAND_GETCURRENTEQPRESET, + COMMAND_SETCURRENTEQPRESET, +// Streaming Properties + COMMAND_GETCURRENTSTREAMTITLE, + COMMAND_GETCURRENTSTREAMURL, +// Miscellaneous Properties + //TODO: BrowserWindow + //TODO: EQWindow + //TODO: LibrarySource + //TODO: LibraryPlaylist + // CurrentTrack + COMMAND_GETCURRENTTRACK_ALBUM, + COMMAND_GETCURRENTTRACK_ARTIST, + COMMAND_GETCURRENTTRACK_BITRATE, + COMMAND_GETCURRENTTRACK_BPM, + COMMAND_GETCURRENTTRACK_COMMENT, + COMMAND_GETCURRENTTRACK_COMPOSER, + COMMAND_GETCURRENTTRACK_EQ, + COMMAND_GETCURRENTTRACK_GENRE, + COMMAND_GETCURRENTTRACK_KINDASSTRING, + COMMAND_GETCURRENTTRACK_NAME, + COMMAND_GETCURRENTTRACK_RATING, + COMMAND_GETCURRENTTRACK_SAMPLERATE, + COMMAND_GETCURRENTTRACK_SIZE, + COMMAND_GETCURRENTTRACK_TIME, + COMMAND_GETCURRENTTRACK_TRACKCOUNT, + COMMAND_GETCURRENTTRACK_TRACKNUMBER, + COMMAND_GETCURRENTTRACK_YEAR, + COMMAND_GETCURRENTTRACK_ARTWORK, + //TODO: other CurrentTrack properties + //TODO: CurrentPlaylist + COMMAND_GETVERSION, + //TODO: AppCommandMessageProcessingEnabled + //TODO: ForceToForegroundOnDialog + //TODO: CanSetShuffle + //TODO: CanSetSongRepeat + //TODO: ConvertOperationStatus + //TODO: SoundVolumeControlEnabled + //TODO: LibraryXMLPath + //TODO: ITObjectPersistentIDHigh + //TODO: ITObjectPersistentIDLow + + COMMAND_COUNT +}; + +const static wchar_t* CommandName[COMMAND_COUNT] = +{ + L"Power", // COMMAND_POWER + L"ToggleiTunes", // COMMAND_TOGGLEITUNES + L"ToggleVisuals", // COMMAND_TOGGLEVISUALS + L"SoundVolumeUp", // COMMAND_SOUNDVOLUMEUP + L"SoundVolumeDown", // COMMAND_SOUNDVOLUMEDOWN +// Player Controls + L"BackTrack", // COMMAND_BACKTRACK + L"FastForward", // COMMAND_FASTFORWARD + L"NextTrack", // COMMAND_NEXTTRACK + L"Pause", // COMMAND_PAUSE + L"Play", // COMMAND_PLAY + L"PlayFile", // COMMAND_PLAYFILE + L"PlayPause", // COMMAND_PLAYPAUSE + L"PreviousTrack", // COMMAND_PREVIOUSTRACK + L"Resume", // COMMAND_RESUME + L"Rewind", // COMMAND_REWIND + L"Stop", // COMMAND_STOP + L"GetPlayerButtonsState", // COMMAND_GETPLAYERBUTTONSSTATE + L"PlayerButtonClicked", // COMMAND_PLAYERBUTTONCLICKED +// Conversion Methods + L"ConvertFile", // COMMAND_CONVERTFILE + L"ConvertFiles", // COMMAND_CONVERTFILES + L"ConvertTrack", // COMMAND_TRACK + L"ConvertTracks", // COMMAND_TRACKS + L"ConvertFile2", // COMMAND_FILE2 + L"ConvertFiles2", // COMMAND_FILES2 + L"ConvertTrack2", // COMMAND_TRACK2 + L"ConvertTracks2", // COMMAND_TRACKS2 +// Miscellaneous Methods + L"CheckVersion", // COMMAND_CHECKVERSION + L"GetITObjectByID", // COMMAND_GETITOBJECTBYID + L"CreatePlaylist", // COMMAND_CREATEPLAYLIST + L"OpenURL", // COMMAND_OPENURL + L"GotoMusicStoreHomePage", // COMMAND_GOTOMUSICSTOREHOMEPAGE + L"UpdateIPod", // COMMAND_UPDATEIPOD + L"Quit", // COMMAND_QUIT + L"CreateEQPreset", // COMMAND_CREATEEQPRESET + L"CreatePlaylistInSource", // COMMAND_CREATEPLAYLISTINSOURCE + L"SubscribeToPodcast", // COMMAND_SUBSCRIBETOPODCAST + L"UpdatePodcastFeeds", // COMMAND_UPDATEPODCASTFEEDS + L"CreateFolder", // COMMAND_CREATEFOLDER + L"CreateFolderInSource", // COMMAND_CREATEFOLDERINSOURCE + L"GetITObjectPersistentIDs",// COMMAND_GETITOBJECTPERSISTENTIDS +// Collection Properties + //TODO: Sources + //TODO: Encoders + //TODO: EQPresets + //TODO: Visuals + //TODO: Windows +// Sound Properties + L"GetSoundVolume", // COMMAND_GETSOUNDVOLUME + L"SetSoundVolume", // COMMAND_SETSOUNDVOLUME + L"GetMute", // COMMAND_GETMUTE + L"SetMute", // COMMAND_SETMUTE +// Player Properties + L"GetPlayerState", // COMMAND_GETPLAYERSTATE + L"GetPlayerPositionPercent",// COMMAND_GETPLAYERPOSITIONPERCENT + L"GetPlayerPosition", // COMMAND_GETPLAYERPOSITION + L"SetPlayerPosition", // COMMAND_SETPLAYERPOSITION +// Encoder Properties + //TODO: CurrentEncoder +// Visual Properties + //TODO: VisualsEnabled + //TODO: FullScreenVisuals + //TODO: VisualSize + //TODO: CurrentVisual +// EQ Properties + L"GetEQEnabled", // COMMAND_GETEQENABLED + L"SetEQEnabled", // COMMAND_SETEQENABLED + L"GetCurrentEQPreset", // COMMAND_GETCURRENTEQPRESET + L"SetCurrentEQPreset", // COMMAND_SETCURRENTEQPRESET +// Streaming Properties + L"GetCurrentStreamTitle", // COMMAND_GETCURRENTSTREAMTITLE + L"GetCurrentStreamURL", // COMMAND_GETCURRENTSTREAMURL +// Miscellaneous Properties + //TODO: BrowserWindow + //TODO: EQWindow + //TODO: LibrarySource + //TODO: LibraryPlaylist + // CurrentTrack + L"GetCurrentTrackAlbum", // COMMAND_GETCURRENTTRACK_ALBUM + L"GetCurrentTrackArtist", // COMMAND_GETCURRENTTRACK_ARTIST + L"GetCurrentTrackBitrate", // COMMAND_GETCURRENTTRACK_BITRATE + L"GetCurrentTrackBPM", // COMMAND_GETCURRENTTRACK_BPM + L"GetCurrentTrackComment", // COMMAND_GETCURRENTTRACK_COMMENT + L"GetCurrentTrackComposer", // COMMAND_GETCURRENTTRACK_COMPOSER + L"GetCurrentTrackEQ", // COMMAND_GETCURRENTTRACK_EQ + L"GetCurrentTrackGenre", // COMMAND_GETCURRENTTRACK_GENRE + L"GetCurrentTrackKindAsString", // COMMAND_GETCURRENTTRACK_KINDASSTRING + L"GetCurrentTrackName", // COMMAND_GETCURRENTTRACK_NAME + L"GetCurrentTrackRating", // COMMAND_GETCURRENTTRACK_RATING + L"GetCurrentTrackSampleRate", // COMMAND_GETCURRENTTRACK_SAMPLERATE + L"GetCurrentTrackSize", // COMMAND_GETCURRENTTRACK_SIZE + L"GetCurrentTrackTime", // COMMAND_GETCURRENTTRACK_TIME + L"GetCurrentTrackTrackCount", // COMMAND_GETCURRENTTRACK_TRACKCOUNT + L"GetCurrentTrackTrackNumber", // COMMAND_GETCURRENTTRACK_TRACKNUMBER + L"GetCurrentTrackYear", // COMMAND_GETCURRENTTRACK_YEAR + L"GetCurrentTrackArtwork", // COMMAND_GETCURRENTTRACK_ARTWORK + //TODO: other CurrentTrack properties + // TODO: CurrentPlaylist + L"GetVersion", // COMMAND_GETVERSION + //TODO: AppCommandMessageProcessingEnabled + //TODO: ForceToForegroundOnDialog + //TODO: CanSetShuffle + //TODO: CanSetSongRepeat + //TODO: ConvertOperationStatus + //TODO: SoundVolumeControlEnabled + //TODO: LibraryXMLPath + //TODO: ITObjectPersistentIDHigh + //TODO: ITObjectPersistentIDLow +}; + +_COM_SMARTPTR_TYPEDEF(IiTunes, __uuidof(IiTunes)); +_COM_SMARTPTR_TYPEDEF(IITTrack, __uuidof(IITTrack)); +_COM_SMARTPTR_TYPEDEF(IITArtworkCollection, __uuidof(IITArtworkCollection)); +_COM_SMARTPTR_TYPEDEF(IITArtwork, __uuidof(IITArtwork)); +_COM_SMARTPTR_TYPEDEF(IITBrowserWindow, __uuidof(IITBrowserWindow)); + +static IiTunesPtr iTunes; +static bool CoInitialized = false; +static bool InstanceCreated = false; + +typedef std::map<UINT, COMMAND_TYPE> CCommandIdMap; +static CCommandIdMap CommandIdMap; + +static wchar_t BaseDir[MAX_PATH]; + +static IITTrackPtr CurrentTrack; +static wchar_t CurrentTrackArtworkPath[MAX_PATH]; +static wchar_t DefaultTrackArtworkPath[MAX_PATH]; +static bool updateCurrentTrack() +{ + static clock_t lastClock = 0; + clock_t currentClock = clock(); + if (0 == lastClock || currentClock - lastClock > CLOCKS_PER_SEC) + { + wsprintf(CurrentTrackArtworkPath, L"%s%s", BaseDir, DefaultTrackArtworkPath); + if (CurrentTrack != nullptr) + CurrentTrack.Release(); + if (FAILED(iTunes->get_CurrentTrack(&CurrentTrack)) || !CurrentTrack) + return false; + + lastClock = currentClock; + + IITArtworkCollectionPtr artworkCollection; + if (SUCCEEDED(CurrentTrack->get_Artwork(&artworkCollection))) + { + long count; + artworkCollection->get_Count(&count); + + IITArtworkPtr artwork; + ITArtworkFormat artworkFormat; + if (count > 0 && + SUCCEEDED(artworkCollection->get_Item(1, &artwork)) && + SUCCEEDED(artwork->get_Format(&artworkFormat))) + { + _bstr_t path; + + wsprintf(CurrentTrackArtworkPath, L"%s\\iTunesArtwork", BaseDir); + CreateDirectory(CurrentTrackArtworkPath, nullptr); + + switch (artworkFormat) + { + case ITArtworkFormatJPEG: + wcscat(CurrentTrackArtworkPath, L"\\artwork.jpg"); + break; + case ITArtworkFormatPNG : + wcscat(CurrentTrackArtworkPath, L"\\artwork.png"); + break; + case ITArtworkFormatBMP: + wcscat(CurrentTrackArtworkPath, L"\\artwork.bmp"); + break; + } + path = CurrentTrackArtworkPath; + if (FAILED(artwork->SaveArtworkToFile(path))) + { + wsprintf(CurrentTrackArtworkPath, L"%s%s", BaseDir, DefaultTrackArtworkPath); + } + } + } + } + return (nullptr != CurrentTrack); +} + +static bool iTunesAboutToPromptUserToQuit = false; +// from http://www.codeproject.com/KB/cs/itunestray.aspx?msg=2300786#xx2300786xx +class CiTunesEventHandler : public _IiTunesEvents +{ +private: + long m_dwRefCount; + ITypeInfo* m_pITypeInfo; // Pointer to type information. + +public: + CiTunesEventHandler() + { + m_dwRefCount=0; + ITypeLib* pITypeLib = nullptr ; + HRESULT hr = ::LoadRegTypeLib(LIBID_iTunesLib, 1, 5, 0x00, &pITypeLib) ; + // Get type information for the interface of the object. + hr = pITypeLib->GetTypeInfoOfGuid(DIID__IiTunesEvents, &m_pITypeInfo) ; + pITypeLib->Release() ; + } + ~CiTunesEventHandler() + {} + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) + { + if ((iid == IID_IDispatch)||(iid == DIID__IiTunesEvents)) { + m_dwRefCount++; + *ppvObject = this;//(_IiTunesEvents *)this; + return S_OK; + } + if (iid == IID_IUnknown) { + m_dwRefCount++; + *ppvObject = this;//(IUnknown *)this; + return S_OK; + } + return E_NOINTERFACE; + } + ULONG STDMETHODCALLTYPE CiTunesEventHandler::AddRef() + { + InterlockedIncrement(&m_dwRefCount); + return m_dwRefCount; + } + ULONG STDMETHODCALLTYPE Release() + { + InterlockedDecrement(&m_dwRefCount); + if (m_dwRefCount == 0) { + delete this; + return 0; + } + return m_dwRefCount; + } + HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *){return E_NOTIMPL;}; + HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT,LCID,ITypeInfo ** ){return E_NOTIMPL;}; + HRESULT STDMETHODCALLTYPE GetIDsOfNames(const IID &,LPOLESTR * ,UINT,LCID,DISPID *){return E_NOTIMPL;}; + HRESULT STDMETHODCALLTYPE Invoke(DISPID dispidMember, REFIID, LCID,WORD, DISPPARAMS* pdispparams, VARIANT*,EXCEPINFO*, UINT*) + { + switch (dispidMember) //look in the documentation for "enum ITEvent" to get the numbers for the functions you want to implement + { + case 9: // AboutToPromptUserToQuitEvent + CurrentTrack.Release(); + iTunes->Quit(); + iTunes.Release(); + InstanceCreated = false; + iTunesAboutToPromptUserToQuit = true; + break; + default: + break; + } + return S_OK; + } +}; + +static CiTunesEventHandler* iTunesEventHandler; +static void initEventHandler() +{ + IConnectionPointContainer* icpc; + iTunes->QueryInterface(IID_IConnectionPointContainer, (void **)&icpc); + IConnectionPoint* icp; + icpc->FindConnectionPoint(DIID__IiTunesEvents, &icp); + icpc->Release(); + DWORD dwAdvise; + iTunesEventHandler = new CiTunesEventHandler(); + icp->Advise(iTunesEventHandler, &dwAdvise); + icp->Release(); +} + +/* +This function is called when the measure is initialized. +The function must return the maximum value that can be measured. +The return value can also be 0, which means that Rainmeter will +track the maximum value automatically. The parameters for this +function are: + +instance The instance of this DLL +iniFile The name of the ini-file (usually Rainmeter.ini) +section The name of the section in the ini-file for this measure +id The identifier for the measure. This is used to identify the measures that use the same plugin. +*/ +UINT Initialize(HMODULE instance, LPCTSTR iniFile, LPCTSTR section, UINT id) +{ + if (!CoInitialized) + { + ::CoInitialize(nullptr); + wcsncpy(BaseDir, iniFile, MAX_PATH); + BaseDir[MAX_PATH - 1] = 0; + wchar_t* lastBackslash = wcsrchr(BaseDir, L'\\'); + if (lastBackslash) + lastBackslash[1] = 0; + CoInitialized = true; + } + + if (CoInitialized && !InstanceCreated && (FindWindow(L"iTunesApp", L"iTunes") || FindWindow(L"iTunes", L"iTunes"))) + { + if (SUCCEEDED(iTunes.CreateInstance(CLSID_iTunesApp, nullptr, CLSCTX_LOCAL_SERVER))) + { + InstanceCreated = true; + initEventHandler(); + } + else + { + LSLog(LOG_ERROR, nullptr, L"iTunesPlugin.dll: Unable to create instance"); + } + } + + const wchar_t* type = ReadConfigString(section, L"Command", L""); + for (int i = 0; i < COMMAND_COUNT; i++) + { + if (CommandName[i] && type && _wcsicmp(CommandName[i], type) == 0) + { + CommandIdMap[id] = (COMMAND_TYPE)i; + + if (COMMAND_GETCURRENTTRACK_ARTWORK == (COMMAND_TYPE)i) + { + const wchar_t* defaultArtwork = ReadConfigString(section, L"DefaultArtwork", L""); + wcscpy(DefaultTrackArtworkPath, defaultArtwork); + } + } + } + + return 0; +} + +/* +This function is called when new value should be measured. +The function returns the new value. +*/ +UINT Update(UINT id) +{ + if (!CoInitialized || !InstanceCreated) + { + // Check if the iTunes window has appeared + if (FindWindow(L"iTunesApp", L"iTunes") || FindWindow(L"iTunes", L"iTunes")) + { + if (!iTunesAboutToPromptUserToQuit && SUCCEEDED(iTunes.CreateInstance(CLSID_iTunesApp, nullptr, CLSCTX_LOCAL_SERVER))) + { + InstanceCreated = true; + initEventHandler(); + } + else + { + LSLog(LOG_ERROR, nullptr, L"iTunesPlugin.dll: Unable to create instance"); + return 0; + } + } + else + { + iTunesAboutToPromptUserToQuit = false; + return 0; + } + } + + CCommandIdMap::const_iterator it = CommandIdMap.find(id); + COMMAND_TYPE command = (it != CommandIdMap.end()) ? it->second : COMMAND_COUNT; + + switch (command) + { + case COMMAND_GETSOUNDVOLUME: // value: 0 ~ 100 + { + long volume; + iTunes->get_SoundVolume(&volume); + return volume; + } + case COMMAND_GETPLAYERPOSITIONPERCENT: // value: 0 ~ 100 + { + long pos; + iTunes->get_PlayerPosition(&pos); + if (!updateCurrentTrack()) + return 0; + long duration; + CurrentTrack->get_Duration(&duration); + return duration ? pos * 100 / duration : 0; + } + case COMMAND_GETPLAYERPOSITION: // value: seconds + { + long pos; + iTunes->get_PlayerPosition(&pos); + return pos; + } + } + return 0; +} + +/* +This function is called when the value should be +returned as a string. +*/ +#define BUFFER_SIZE 256 +LPCTSTR GetString(UINT id, UINT flags) +{ + //Error Check + static wchar_t buffer[BUFFER_SIZE]; + buffer[0] = 0; + if (!CoInitialized) + { + wsprintf(buffer, L"Fail to initialize"); + return buffer; + } + + CCommandIdMap::const_iterator it = CommandIdMap.find(id); + COMMAND_TYPE command = (it != CommandIdMap.end()) ? it->second : COMMAND_COUNT; + + if (!InstanceCreated) + { + //wsprintf(buffer, L"iTunes is not running"); + if (COMMAND_GETCURRENTTRACK_ARTWORK == command) + wsprintf(buffer, L"%s%s", BaseDir, DefaultTrackArtworkPath); + return buffer; + } + + if (command >= COMMAND_GETCURRENTTRACK_ALBUM && command <= COMMAND_GETCURRENTTRACK_ARTWORK) + { + if (!updateCurrentTrack()) + return buffer; + + BSTR bstrValue; + long longValue; + bool bstrUsed = false; + + switch (command) + { + case COMMAND_GETCURRENTTRACK_ALBUM: + bstrUsed = SUCCEEDED(CurrentTrack->get_Album(&bstrValue)); + break; + case COMMAND_GETCURRENTTRACK_ARTIST: + bstrUsed = SUCCEEDED(CurrentTrack->get_Artist(&bstrValue)); + break; + case COMMAND_GETCURRENTTRACK_BITRATE: + if (SUCCEEDED(CurrentTrack->get_BitRate(&longValue))) + { + wsprintf(buffer, L"%dkbps", longValue); + } + break; + case COMMAND_GETCURRENTTRACK_BPM: + if (SUCCEEDED(CurrentTrack->get_BPM(&longValue))) + { + wsprintf(buffer, L"%dbpm", longValue); + } + break; + case COMMAND_GETCURRENTTRACK_COMMENT: + bstrUsed = SUCCEEDED(CurrentTrack->get_Comment(&bstrValue)); + break; + case COMMAND_GETCURRENTTRACK_COMPOSER: + bstrUsed = SUCCEEDED(CurrentTrack->get_Composer(&bstrValue)); + break; + case COMMAND_GETCURRENTTRACK_EQ: + bstrUsed = SUCCEEDED(CurrentTrack->get_EQ(&bstrValue)); + break; + case COMMAND_GETCURRENTTRACK_GENRE: + bstrUsed = SUCCEEDED(CurrentTrack->get_Genre(&bstrValue)); + break; + case COMMAND_GETCURRENTTRACK_KINDASSTRING: + bstrUsed = SUCCEEDED(CurrentTrack->get_KindAsString(&bstrValue)); + break; + case COMMAND_GETCURRENTTRACK_NAME: + bstrUsed = SUCCEEDED(CurrentTrack->get_Name(&bstrValue)); + break; + case COMMAND_GETCURRENTTRACK_RATING: + if (SUCCEEDED(CurrentTrack->get_Rating(&longValue))) + { + wsprintf(buffer, L"%d/100", longValue); + } + break; + case COMMAND_GETCURRENTTRACK_SAMPLERATE: + if (SUCCEEDED(CurrentTrack->get_SampleRate(&longValue))) + { + wsprintf(buffer, L"%dHz", longValue); + } + break; + case COMMAND_GETCURRENTTRACK_SIZE: + if (SUCCEEDED(CurrentTrack->get_Size(&longValue))) + { + if (longValue < 1024) + wsprintf(buffer, L"%dbytes", longValue); + else if (longValue < 1024 * 1024) + wsprintf(buffer, L"%d.%dKbytes", longValue/1024, (longValue*10/1024)%10); + else + wsprintf(buffer, L"%d.%dMbytes", longValue/1024/1024, (longValue*10/1024/1024)%10); + } + break; + case COMMAND_GETCURRENTTRACK_TIME: + bstrUsed = SUCCEEDED(CurrentTrack->get_Time(&bstrValue)); + break; + case COMMAND_GETCURRENTTRACK_TRACKCOUNT: + if (SUCCEEDED(CurrentTrack->get_TrackCount(&longValue))) + { + wsprintf(buffer, L"%d", longValue); + } + break; + case COMMAND_GETCURRENTTRACK_TRACKNUMBER: + if (SUCCEEDED(CurrentTrack->get_TrackNumber(&longValue))) + { + wsprintf(buffer, L"%d", longValue); + } + break; + case COMMAND_GETCURRENTTRACK_YEAR: + if (SUCCEEDED(CurrentTrack->get_Year(&longValue))) + { + wsprintf(buffer, L"%d", longValue); + } + break; + case COMMAND_GETCURRENTTRACK_ARTWORK: + { + wsprintf(buffer, L"%s", CurrentTrackArtworkPath); + break; + } + } + + if (bstrUsed && bstrValue) + { + wcsncpy(buffer, bstrValue, BUFFER_SIZE - 1); + buffer[BUFFER_SIZE - 1] = 0; + SysFreeString(bstrValue); + } + return buffer; + } + + wsprintf(buffer, L"Type Incorrect"); + return buffer; +} + +void ExecuteBang(LPCTSTR args, UINT id) +{ + if (!CoInitialized) + { + return; + } + + COMMAND_TYPE command; + + if (wcslen(args) == 0) + { + CCommandIdMap::const_iterator it = CommandIdMap.find(id); + command = (it != CommandIdMap.end()) ? it->second : COMMAND_COUNT; + } + else + { + if (_wcsicmp(args, L"Backtrack") == 0) + { + command = COMMAND_BACKTRACK; + } + else if (_wcsicmp(args, L"FastForward") == 0) + { + command = COMMAND_FASTFORWARD; + } + else if (_wcsicmp(args, L"NextTrack") == 0) + { + command = COMMAND_NEXTTRACK; + } + else if (_wcsicmp(args, L"Pause") == 0) + { + command = COMMAND_PAUSE; + } + else if (_wcsicmp(args, L"Play") == 0) + { + command = COMMAND_PLAY; + } + else if (_wcsicmp(args, L"PlayPause") == 0) + { + command = COMMAND_PLAYPAUSE; + } + else if (_wcsicmp(args, L"Power") == 0) + { + command = COMMAND_POWER; + } + else if (_wcsicmp(args, L"PreviousTrack") == 0) + { + command = COMMAND_PREVIOUSTRACK; + } + else if (_wcsicmp(args, L"Resume") == 0) + { + command = COMMAND_RESUME; + } + else if (_wcsicmp(args, L"Rewind") == 0) + { + command = COMMAND_REWIND; + } + else if (_wcsicmp(args, L"Stop") == 0) + { + command = COMMAND_STOP; + } + else if (_wcsicmp(args, L"SoundVolumeUp") == 0) + { + command = COMMAND_SOUNDVOLUMEUP; + } + else if (_wcsicmp(args, L"SoundVolumeDown") == 0) + { + command = COMMAND_SOUNDVOLUMEDOWN; + } + else if (_wcsicmp(args, L"ToggleiTunes") == 0) + { + command = COMMAND_TOGGLEITUNES; + } + else if (_wcsicmp(args, L"ToggleVisuals") == 0) + { + command = COMMAND_TOGGLEVISUALS; + } + else if (_wcsicmp(args, L"UpdateiPod") == 0) + { + command = COMMAND_UPDATEIPOD; + } + else if (_wcsicmp(args, L"UpdatePodcastFeeds") == 0) + { + command = COMMAND_UPDATEPODCASTFEEDS; + } + else if (_wcsicmp(args, L"GotoMusicStoreHomePage") == 0) + { + command = COMMAND_GOTOMUSICSTOREHOMEPAGE; + } + else if (_wcsicmp(args, L"Quit") == 0) + { + command = COMMAND_QUIT; + } + else + { + LSLog(LOG_NOTICE, nullptr, L"iTunesPlugin.dll: Invalid Command"); + return; + } + } + + if (!InstanceCreated) + { + if (COMMAND_POWER == command && CoInitialized && SUCCEEDED(iTunes.CreateInstance(CLSID_iTunesApp, nullptr, CLSCTX_LOCAL_SERVER))) + { + IITBrowserWindowPtr browserWindow; + if (SUCCEEDED(iTunes->get_BrowserWindow(&browserWindow))) + { + browserWindow->put_Minimized(VARIANT_TRUE); + } + InstanceCreated = true; + } + return; + } + + switch (command) + { + case COMMAND_POWER: + { + iTunes->Quit(); + iTunes.Release(); + InstanceCreated = false; + break; + } + case COMMAND_TOGGLEITUNES: + { + IITBrowserWindowPtr browserWindow; + if (FAILED(iTunes->get_BrowserWindow(&browserWindow))) + { + break; + } + VARIANT_BOOL minimized; + if (SUCCEEDED(browserWindow->get_Minimized(&minimized))) + { + browserWindow->put_Minimized((VARIANT_TRUE == minimized) ? VARIANT_FALSE : VARIANT_TRUE); + } + break; + } + case COMMAND_TOGGLEVISUALS: + { + VARIANT_BOOL visualsEnabled; + if (SUCCEEDED(iTunes->get_VisualsEnabled(&visualsEnabled))) + { + iTunes->put_VisualsEnabled((VARIANT_TRUE == visualsEnabled) ? VARIANT_FALSE : VARIANT_TRUE); + } + break; + } + case COMMAND_SOUNDVOLUMEUP: + { + long volume; + iTunes->get_SoundVolume(&volume); + volume += VOLUME_STEP; + (volume > 100) ? volume = 100 : 0; + iTunes->put_SoundVolume(volume); + break; + } + case COMMAND_SOUNDVOLUMEDOWN: + { + long volume; + iTunes->get_SoundVolume(&volume); + volume -= VOLUME_STEP; + (volume < 0) ? volume = 0 : 0; + iTunes->put_SoundVolume(volume); + break; + } + + // Player Controls + case COMMAND_BACKTRACK: + iTunes->BackTrack(); + break; + case COMMAND_FASTFORWARD: + iTunes->FastForward(); + break; + case COMMAND_NEXTTRACK: + iTunes->NextTrack(); + break; + case COMMAND_PAUSE: + iTunes->Pause(); + break; + case COMMAND_PLAY: + iTunes->Pause(); + iTunes->Play(); + break; + case COMMAND_PLAYFILE: + //TODO: + break; + case COMMAND_PLAYPAUSE: + iTunes->PlayPause(); + break; + case COMMAND_PREVIOUSTRACK: + iTunes->PreviousTrack(); + break; + case COMMAND_RESUME: + iTunes->Resume(); + break; + case COMMAND_REWIND: + iTunes->Rewind(); + break; + case COMMAND_STOP: + iTunes->Stop(); + break; + case COMMAND_GETPLAYERBUTTONSSTATE: + //TODO: + break; + case COMMAND_PLAYERBUTTONCLICKED: + //TODO: + break; + + // Conversion Methods + case COMMAND_CONVERTFILE: + //TODO: + break; + case COMMAND_CONVERTFILES: + //TODO: + break; + case COMMAND_TRACK: + //TODO: + break; + case COMMAND_TRACKS: + //TODO: + break; + case COMMAND_FILE2: + //TODO: + break; + case COMMAND_FILES2: + //TODO: + break; + case COMMAND_TRACK2: + //TODO: + break; + case COMMAND_TRACKS2: + //TODO: + break; + + // Miscellaneous Methods + case COMMAND_CHECKVERSION: + //TODO: + break; + case COMMAND_GETITOBJECTBYID: + //TODO: + break; + case COMMAND_CREATEPLAYLIST: + //TODO: + break; + case COMMAND_OPENURL: + //TODO: + break; + case COMMAND_GOTOMUSICSTOREHOMEPAGE: + iTunes->GotoMusicStoreHomePage(); + break; + case COMMAND_UPDATEIPOD: + iTunes->UpdateIPod(); + break; + case COMMAND_QUIT: + iTunes->Quit(); + break; + case COMMAND_CREATEEQPRESET: + //TODO: + break; + case COMMAND_CREATEPLAYLISTINSOURCE: + //TODO: + break; + case COMMAND_SUBSCRIBETOPODCAST: + //TODO: + break; + case COMMAND_UPDATEPODCASTFEEDS: + iTunes->UpdatePodcastFeeds(); + break; + case COMMAND_CREATEFOLDER: + //TODO: + break; + case COMMAND_CREATEFOLDERINSOURCE: + //TODO: + break; + case COMMAND_GETITOBJECTPERSISTENTIDS: + //TODO: + break; + } +} + +/* +If the measure needs to free resources before quitting. +The plugin can export Finalize function, which is called +when Rainmeter quits (or refreshes). +*/ +void Finalize(HMODULE instance, UINT id) +{ + if (InstanceCreated) + { + iTunes.Release(); + InstanceCreated = false; + } +} + +UINT GetPluginVersion() +{ + return 0002; +} + +LPCTSTR GetPluginAuthor() +{ + return L"Elestel"; } \ No newline at end of file diff --git a/README.md b/README.md index 17131e51..d01edba3 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -*Rainmeter Studio* is an editor for Rainmeter skins. +*Rainmeter Studio* is an editor for Rainmeter skins. diff --git a/RainmeterEditor.exe.config b/RainmeterEditor.exe.config index 57c0f2cb..fcd0c937 100644 --- a/RainmeterEditor.exe.config +++ b/RainmeterEditor.exe.config @@ -1,3 +1,3 @@ -<?xml version="1.0" encoding="utf-8"?> -<configuration> -<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration> +<?xml version="1.0" encoding="utf-8"?> +<configuration> +<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration> diff --git a/RainmeterEditor.vshost.exe.config b/RainmeterEditor.vshost.exe.config index 57c0f2cb..fcd0c937 100644 --- a/RainmeterEditor.vshost.exe.config +++ b/RainmeterEditor.vshost.exe.config @@ -1,3 +1,3 @@ -<?xml version="1.0" encoding="utf-8"?> -<configuration> -<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration> +<?xml version="1.0" encoding="utf-8"?> +<configuration> +<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration> diff --git a/RainmeterEditor/App.xaml b/RainmeterEditor/App.xaml index 9b1bf7d7..adce9422 100644 --- a/RainmeterEditor/App.xaml +++ b/RainmeterEditor/App.xaml @@ -1,13 +1,13 @@ -<Application x:Class="RainmeterEditor.App" - xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - StartupUri="UI/MainWindow.xaml" - Startup="Application_Startup"> - <Application.Resources> - <ResourceDictionary> - <ResourceDictionary.MergedDictionaries> - <ResourceDictionary Source="UI/Styles/Common.xaml" /> - </ResourceDictionary.MergedDictionaries> - </ResourceDictionary> - </Application.Resources> -</Application> +<Application x:Class="RainmeterEditor.App" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + StartupUri="UI/MainWindow.xaml" + Startup="Application_Startup"> + <Application.Resources> + <ResourceDictionary> + <ResourceDictionary.MergedDictionaries> + <ResourceDictionary Source="UI/Styles/Common.xaml" /> + </ResourceDictionary.MergedDictionaries> + </ResourceDictionary> + </Application.Resources> +</Application> diff --git a/RainmeterEditor/App.xaml.cs b/RainmeterEditor/App.xaml.cs index 3a28b755..4f4b4409 100644 --- a/RainmeterEditor/App.xaml.cs +++ b/RainmeterEditor/App.xaml.cs @@ -1,22 +1,22 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Data; -using System.Linq; -using System.Windows; -using RainmeterEditor.Business; -using RainmeterEditor.Documents.Text; - -namespace RainmeterEditor -{ - /// <summary> - /// Interaction logic for App.xaml - /// </summary> - public partial class App : Application - { - private void Application_Startup(object sender, StartupEventArgs e) - { - DocumentManager.Instance.RegisterEditorFactory(new TextEditorFactory()); - } - } -} +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Windows; +using RainmeterEditor.Business; +using RainmeterEditor.Documents.Text; + +namespace RainmeterEditor +{ + /// <summary> + /// Interaction logic for App.xaml + /// </summary> + public partial class App : Application + { + private void Application_Startup(object sender, StartupEventArgs e) + { + DocumentManager.Instance.RegisterEditorFactory(new TextEditorFactory()); + } + } +} diff --git a/RainmeterEditor/Business/DocumentManager.cs b/RainmeterEditor/Business/DocumentManager.cs index 113a82bc..230f99c9 100644 --- a/RainmeterEditor/Business/DocumentManager.cs +++ b/RainmeterEditor/Business/DocumentManager.cs @@ -1,78 +1,78 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using RainmeterEditor.Model; -using RainmeterEditor.Model.Events; - -namespace RainmeterEditor.Business -{ - public class DocumentManager - { - #region Singleton instance - private static DocumentManager _instance = null; - - /// <summary> - /// Gets the instance of DocumentManager - /// </summary> - public static DocumentManager Instance - { - get - { - if (_instance == null) - _instance = new DocumentManager(); - - return _instance; - } - } - - #endregion - - private DocumentManager() - { - } - - List<IDocumentEditorFactory> _factories = new List<IDocumentEditorFactory>(); - List<IDocumentEditor> _editors = new List<IDocumentEditor>(); - - public event EventHandler<DocumentOpenedEventArgs> DocumentOpened; - - /// <summary> - /// Registers a document editor factory - /// </summary> - /// <param name="factory">Document editor factory</param> - public void RegisterEditorFactory(IDocumentEditorFactory factory) - { - _factories.Add(factory); - } - - /// <summary> - /// Creates a new document in the specified path, with the specified format, and opens it - /// </summary> - /// <param name="format"></param> - /// <param name="path"></param> - public void Create(DocumentFormat format, string path) - { - // Create document - var document = format.Factory.CreateDocument(format, path); - - // Create editor - var editor = format.Factory.CreateEditor(document); - _editors.Add(editor); - - // Trigger event - if (DocumentOpened != null) - DocumentOpened(this, new DocumentOpenedEventArgs(editor)); - } - - public IEnumerable<DocumentFormat> DocumentFormats - { - get - { - foreach (var f in _factories) - foreach (var df in f.CreateDocumentFormats) - yield return df; - } - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RainmeterEditor.Model; +using RainmeterEditor.Model.Events; + +namespace RainmeterEditor.Business +{ + public class DocumentManager + { + #region Singleton instance + private static DocumentManager _instance = null; + + /// <summary> + /// Gets the instance of DocumentManager + /// </summary> + public static DocumentManager Instance + { + get + { + if (_instance == null) + _instance = new DocumentManager(); + + return _instance; + } + } + + #endregion + + private DocumentManager() + { + } + + List<IDocumentEditorFactory> _factories = new List<IDocumentEditorFactory>(); + List<IDocumentEditor> _editors = new List<IDocumentEditor>(); + + public event EventHandler<DocumentOpenedEventArgs> DocumentOpened; + + /// <summary> + /// Registers a document editor factory + /// </summary> + /// <param name="factory">Document editor factory</param> + public void RegisterEditorFactory(IDocumentEditorFactory factory) + { + _factories.Add(factory); + } + + /// <summary> + /// Creates a new document in the specified path, with the specified format, and opens it + /// </summary> + /// <param name="format"></param> + /// <param name="path"></param> + public void Create(DocumentFormat format, string path) + { + // Create document + var document = format.Factory.CreateDocument(format, path); + + // Create editor + var editor = format.Factory.CreateEditor(document); + _editors.Add(editor); + + // Trigger event + if (DocumentOpened != null) + DocumentOpened(this, new DocumentOpenedEventArgs(editor)); + } + + public IEnumerable<DocumentFormat> DocumentFormats + { + get + { + foreach (var f in _factories) + foreach (var df in f.CreateDocumentFormats) + yield return df; + } + } + } +} diff --git a/RainmeterEditor/Business/ProjectManager.cs b/RainmeterEditor/Business/ProjectManager.cs index 7781a19d..491ea1e7 100644 --- a/RainmeterEditor/Business/ProjectManager.cs +++ b/RainmeterEditor/Business/ProjectManager.cs @@ -1,16 +1,16 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using RainmeterEditor.Model; - -namespace RainmeterEditor.Business -{ - public class ProjectManager - { - public Project ActiveProject { get; protected set; } - - public void Open() { } - public void Close() { } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RainmeterEditor.Model; + +namespace RainmeterEditor.Business +{ + public class ProjectManager + { + public Project ActiveProject { get; protected set; } + + public void Open() { } + public void Close() { } + } +} diff --git a/RainmeterEditor/Documents/Ini/IniDocument.cs b/RainmeterEditor/Documents/Ini/IniDocument.cs index 1cad4829..e6f47574 100644 --- a/RainmeterEditor/Documents/Ini/IniDocument.cs +++ b/RainmeterEditor/Documents/Ini/IniDocument.cs @@ -1,12 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using RainmeterEditor.Model; - -namespace RainmeterEditor.Documents.Ini -{ - /*public class IniDocument : IDocument - { - }*/ -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RainmeterEditor.Model; + +namespace RainmeterEditor.Documents.Ini +{ + /*public class IniDocument : IDocument + { + }*/ +} diff --git a/RainmeterEditor/Documents/Ini/IniSkinDesigner.cs b/RainmeterEditor/Documents/Ini/IniSkinDesigner.cs index b68504cf..f03ec66d 100644 --- a/RainmeterEditor/Documents/Ini/IniSkinDesigner.cs +++ b/RainmeterEditor/Documents/Ini/IniSkinDesigner.cs @@ -1,31 +1,31 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using RainmeterEditor.Model; - -namespace RainmeterEditor.Documents.Ini -{ - /*public class IniSkinDesigner : IDocumentEditor - { - public override IDocument Document - { - get { throw new NotImplementedException(); } - } - - public override string Title - { - get { throw new NotImplementedException(); } - } - - public override System.Windows.UIElement EditorUI - { - get { throw new NotImplementedException(); } - } - - public override EventHandler SelectionChanged - { - get { throw new NotImplementedException(); } - } - }*/ -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RainmeterEditor.Model; + +namespace RainmeterEditor.Documents.Ini +{ + /*public class IniSkinDesigner : IDocumentEditor + { + public override IDocument Document + { + get { throw new NotImplementedException(); } + } + + public override string Title + { + get { throw new NotImplementedException(); } + } + + public override System.Windows.UIElement EditorUI + { + get { throw new NotImplementedException(); } + } + + public override EventHandler SelectionChanged + { + get { throw new NotImplementedException(); } + } + }*/ +} diff --git a/RainmeterEditor/Documents/Ini/IniSkinDesignerControl.xaml b/RainmeterEditor/Documents/Ini/IniSkinDesignerControl.xaml index 69b23166..6a86740f 100644 --- a/RainmeterEditor/Documents/Ini/IniSkinDesignerControl.xaml +++ b/RainmeterEditor/Documents/Ini/IniSkinDesignerControl.xaml @@ -1,11 +1,11 @@ -<UserControl x:Class="RainmeterEditor.Documents.Ini.IniSkinDesignerControl" - xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - mc:Ignorable="d" - d:DesignHeight="300" d:DesignWidth="300"> - <Grid> - - </Grid> -</UserControl> +<UserControl x:Class="RainmeterEditor.Documents.Ini.IniSkinDesignerControl" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + mc:Ignorable="d" + d:DesignHeight="300" d:DesignWidth="300"> + <Grid> + + </Grid> +</UserControl> diff --git a/RainmeterEditor/Documents/Ini/IniSkinDesignerControl.xaml.cs b/RainmeterEditor/Documents/Ini/IniSkinDesignerControl.xaml.cs index c9998a72..f1ad22c5 100644 --- a/RainmeterEditor/Documents/Ini/IniSkinDesignerControl.xaml.cs +++ b/RainmeterEditor/Documents/Ini/IniSkinDesignerControl.xaml.cs @@ -1,27 +1,27 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; - -namespace RainmeterEditor.Documents.Ini -{ - /// <summary> - /// Interaction logic for IniSkinDesignerControl.xaml - /// </summary> - public partial class IniSkinDesignerControl : UserControl - { - public IniSkinDesignerControl() - { - InitializeComponent(); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace RainmeterEditor.Documents.Ini +{ + /// <summary> + /// Interaction logic for IniSkinDesignerControl.xaml + /// </summary> + public partial class IniSkinDesignerControl : UserControl + { + public IniSkinDesignerControl() + { + InitializeComponent(); + } + } +} diff --git a/RainmeterEditor/Documents/Ini/IniSkinDesignerFactory.cs b/RainmeterEditor/Documents/Ini/IniSkinDesignerFactory.cs index 7a644116..d5ebe6cd 100644 --- a/RainmeterEditor/Documents/Ini/IniSkinDesignerFactory.cs +++ b/RainmeterEditor/Documents/Ini/IniSkinDesignerFactory.cs @@ -1,14 +1,14 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using RainmeterEditor.Model; - -namespace RainmeterEditor.Documents.Ini -{ - /*public class IniSkinDesignerFactory : IDocumentEditorFactory - { - - }*/ -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using RainmeterEditor.Model; + +namespace RainmeterEditor.Documents.Ini +{ + /*public class IniSkinDesignerFactory : IDocumentEditorFactory + { + + }*/ +} diff --git a/RainmeterEditor/Documents/Text/TextDocument.cs b/RainmeterEditor/Documents/Text/TextDocument.cs index f2ab6ba2..a634706c 100644 --- a/RainmeterEditor/Documents/Text/TextDocument.cs +++ b/RainmeterEditor/Documents/Text/TextDocument.cs @@ -1,35 +1,35 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using RainmeterEditor.Model; - -namespace RainmeterEditor.Documents.Text -{ - public class TextDocument : IDocument - { - public string Name - { - get - { - return Path.GetFileName(FilePath); - } - } - - public string FilePath - { - get; set; - } - - public string Text - { - get; set; - } - - public TextDocument() - { - Text = String.Empty; - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using RainmeterEditor.Model; + +namespace RainmeterEditor.Documents.Text +{ + public class TextDocument : IDocument + { + public string Name + { + get + { + return Path.GetFileName(FilePath); + } + } + + public string FilePath + { + get; set; + } + + public string Text + { + get; set; + } + + public TextDocument() + { + Text = String.Empty; + } + } +} diff --git a/RainmeterEditor/Documents/Text/TextEditor.cs b/RainmeterEditor/Documents/Text/TextEditor.cs index 673f514d..1b052d22 100644 --- a/RainmeterEditor/Documents/Text/TextEditor.cs +++ b/RainmeterEditor/Documents/Text/TextEditor.cs @@ -1,27 +1,27 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using RainmeterEditor.Model; - -namespace RainmeterEditor.Documents.Text -{ - public class TextEditor : IDocumentEditor - { - private TextDocument _document; - private TextEditorControl _control; - - public TextEditor(TextDocument document) - { - _document = document; - _control = new TextEditorControl(document); - } - - public override IDocument Document { get { return _document; } } - - public override string Title { get { return _document.Name; } } - - public override System.Windows.UIElement EditorUI { get { return _control; } } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using RainmeterEditor.Model; + +namespace RainmeterEditor.Documents.Text +{ + public class TextEditor : IDocumentEditor + { + private TextDocument _document; + private TextEditorControl _control; + + public TextEditor(TextDocument document) + { + _document = document; + _control = new TextEditorControl(document); + } + + public override IDocument Document { get { return _document; } } + + public override string Title { get { return _document.Name; } } + + public override System.Windows.UIElement EditorUI { get { return _control; } } + } +} diff --git a/RainmeterEditor/Documents/Text/TextEditorControl.xaml b/RainmeterEditor/Documents/Text/TextEditorControl.xaml index 53b9aa76..e8508998 100644 --- a/RainmeterEditor/Documents/Text/TextEditorControl.xaml +++ b/RainmeterEditor/Documents/Text/TextEditorControl.xaml @@ -1,11 +1,11 @@ -<UserControl x:Class="RainmeterEditor.Documents.Text.TextEditorControl" - xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - mc:Ignorable="d" - d:DesignHeight="300" d:DesignWidth="300"> - <Grid> - <TextBox Name="text" AcceptsReturn="True" /> - </Grid> -</UserControl> +<UserControl x:Class="RainmeterEditor.Documents.Text.TextEditorControl" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + mc:Ignorable="d" + d:DesignHeight="300" d:DesignWidth="300"> + <Grid> + <TextBox Name="text" AcceptsReturn="True" /> + </Grid> +</UserControl> diff --git a/RainmeterEditor/Documents/Text/TextEditorControl.xaml.cs b/RainmeterEditor/Documents/Text/TextEditorControl.xaml.cs index 0c625f0b..e2994252 100644 --- a/RainmeterEditor/Documents/Text/TextEditorControl.xaml.cs +++ b/RainmeterEditor/Documents/Text/TextEditorControl.xaml.cs @@ -1,32 +1,32 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; - -namespace RainmeterEditor.Documents.Text -{ - /// <summary> - /// Interaction logic for TextEditorControl.xaml - /// </summary> - public partial class TextEditorControl : UserControl - { - private TextDocument _document; - - public TextEditorControl(TextDocument document) - { - InitializeComponent(); - - _document = document; - text.Text = document.Text; - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace RainmeterEditor.Documents.Text +{ + /// <summary> + /// Interaction logic for TextEditorControl.xaml + /// </summary> + public partial class TextEditorControl : UserControl + { + private TextDocument _document; + + public TextEditorControl(TextDocument document) + { + InitializeComponent(); + + _document = document; + text.Text = document.Text; + } + } +} diff --git a/RainmeterEditor/Documents/Text/TextEditorFactory.cs b/RainmeterEditor/Documents/Text/TextEditorFactory.cs index 80b4115a..544cf7de 100644 --- a/RainmeterEditor/Documents/Text/TextEditorFactory.cs +++ b/RainmeterEditor/Documents/Text/TextEditorFactory.cs @@ -1,59 +1,59 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using RainmeterEditor.Business; -using RainmeterEditor.Model; - -namespace RainmeterEditor.Documents.Text -{ - public class TextEditorFactory : IDocumentEditorFactory - { - private TextStorage _storage = new TextStorage(); - - /// <inheritdoc /> - public string EditorName - { - get { return Resources.Strings.DocumentEditor_Text_Name; } - } - - /// <inheritdoc /> - public IEnumerable<DocumentFormat> CreateDocumentFormats - { - get - { - yield return new DocumentFormat() - { - Name = Resources.Strings.DocumentFormat_TextFile_Name, - Category = Resources.Strings.Category_Utility, - DefaultExtension = ".txt", - Description = Resources.Strings.DocumentFormat_TextFile_Description, - Icon = new System.Windows.Media.Imaging.BitmapImage(new Uri("/Resources/Icons/text_file_32.png", UriKind.RelativeOrAbsolute)), - Factory = this - }; - } - } - - - public IDocumentEditor CreateEditor(IDocument document) - { - TextDocument textDocument = document as TextDocument; - - if (textDocument == null) - throw new ArgumentException("Cannot edit provided document."); - - return new TextEditor(textDocument); - } - - public IDocumentStorage Storage { get { return _storage; } } - - public IDocument CreateDocument(DocumentFormat format, string path) - { - var document = new TextDocument(); - document.FilePath = path; - - return document; - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using RainmeterEditor.Business; +using RainmeterEditor.Model; + +namespace RainmeterEditor.Documents.Text +{ + public class TextEditorFactory : IDocumentEditorFactory + { + private TextStorage _storage = new TextStorage(); + + /// <inheritdoc /> + public string EditorName + { + get { return Resources.Strings.DocumentEditor_Text_Name; } + } + + /// <inheritdoc /> + public IEnumerable<DocumentFormat> CreateDocumentFormats + { + get + { + yield return new DocumentFormat() + { + Name = Resources.Strings.DocumentFormat_TextFile_Name, + Category = Resources.Strings.Category_Utility, + DefaultExtension = ".txt", + Description = Resources.Strings.DocumentFormat_TextFile_Description, + Icon = new System.Windows.Media.Imaging.BitmapImage(new Uri("/Resources/Icons/text_file_32.png", UriKind.RelativeOrAbsolute)), + Factory = this + }; + } + } + + + public IDocumentEditor CreateEditor(IDocument document) + { + TextDocument textDocument = document as TextDocument; + + if (textDocument == null) + throw new ArgumentException("Cannot edit provided document."); + + return new TextEditor(textDocument); + } + + public IDocumentStorage Storage { get { return _storage; } } + + public IDocument CreateDocument(DocumentFormat format, string path) + { + var document = new TextDocument(); + document.FilePath = path; + + return document; + } + } +} diff --git a/RainmeterEditor/Documents/Text/TextStorage.cs b/RainmeterEditor/Documents/Text/TextStorage.cs index 0ac65ca8..a607e13f 100644 --- a/RainmeterEditor/Documents/Text/TextStorage.cs +++ b/RainmeterEditor/Documents/Text/TextStorage.cs @@ -1,64 +1,64 @@ -using System; -using System.IO; -using RainmeterEditor.Model; - -namespace RainmeterEditor.Documents.Text -{ - /// <summary> - /// Storage for text files - /// </summary> - public class TextStorage : IDocumentStorage - { - /// <inheritdoc /> - IDocument IDocumentStorage.Read(string path) - { - TextDocument document = new TextDocument(); - document.FilePath = path; - document.Text = File.ReadAllText(path); - - return document; - } - - /// <inheritdoc /> - public void Write(string path, IDocument document) - { - TextDocument textDocument = document as TextDocument; - - if (textDocument == null) - throw new ArgumentException("Provided document is not supported by this storage."); - - File.WriteAllText(path, textDocument.Text); - } - - /// <inheritdoc /> - public bool CanRead(string path) - { - // Open the file - FileStream file = File.OpenRead(path); - - // Read a small chunk (1kb should be enough) - byte[] buffer = new byte[1024]; - int read = file.Read(buffer, 0, buffer.Length); - - // Close file - file.Close(); - - // Find 4 consecutive zero bytes - int cnt = 0; - for (int i = 0; i < read; i++) - { - // Count zero bytes - if (buffer[i] == 0) - ++cnt; - else cnt = 0; - - // Found > 4? Most likely binary file - if (cnt >= 4) - return false; - } - - // Not found, probably text file - return true; - } - } -} +using System; +using System.IO; +using RainmeterEditor.Model; + +namespace RainmeterEditor.Documents.Text +{ + /// <summary> + /// Storage for text files + /// </summary> + public class TextStorage : IDocumentStorage + { + /// <inheritdoc /> + IDocument IDocumentStorage.Read(string path) + { + TextDocument document = new TextDocument(); + document.FilePath = path; + document.Text = File.ReadAllText(path); + + return document; + } + + /// <inheritdoc /> + public void Write(string path, IDocument document) + { + TextDocument textDocument = document as TextDocument; + + if (textDocument == null) + throw new ArgumentException("Provided document is not supported by this storage."); + + File.WriteAllText(path, textDocument.Text); + } + + /// <inheritdoc /> + public bool CanRead(string path) + { + // Open the file + FileStream file = File.OpenRead(path); + + // Read a small chunk (1kb should be enough) + byte[] buffer = new byte[1024]; + int read = file.Read(buffer, 0, buffer.Length); + + // Close file + file.Close(); + + // Find 4 consecutive zero bytes + int cnt = 0; + for (int i = 0; i < read; i++) + { + // Count zero bytes + if (buffer[i] == 0) + ++cnt; + else cnt = 0; + + // Found > 4? Most likely binary file + if (cnt >= 4) + return false; + } + + // Not found, probably text file + return true; + } + } +} diff --git a/RainmeterEditor/Interop/NativeLibrary.cs b/RainmeterEditor/Interop/NativeLibrary.cs index 0b30ef24..58daf48a 100644 --- a/RainmeterEditor/Interop/NativeLibrary.cs +++ b/RainmeterEditor/Interop/NativeLibrary.cs @@ -1,53 +1,53 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; - -namespace RainmeterEditor.Interop -{ - public class NativeLibrary : IDisposable - { - #region Imports - - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] - private static extern IntPtr LoadLibrary(string libname); - - [DllImport("kernel32.dll", CharSet = CharSet.Ansi)] - private static extern bool FreeLibrary(IntPtr hModule); - - [DllImport("kernel32.dll", CharSet = CharSet.Ansi)] - private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); - - #endregion - - public string DllName { get; private set; } - private IntPtr _handle; - - public NativeLibrary(string dllName) - { - // Set properties - DllName = dllName; - - // Load library - _handle = LoadLibrary(DllName); - if (_handle == IntPtr.Zero) - { - int errorCode = Marshal.GetLastWin32Error(); - throw new BadImageFormatException(string.Format("Failed to load library (ErrorCode: {0})", errorCode)); - } - } - - public void Dispose() - { - if (_handle != IntPtr.Zero) - FreeLibrary(_handle); - } - - public Delegate GetFunctionByName(string name, Type delegateType) - { - IntPtr addr = GetProcAddress(_handle, name); - return Marshal.GetDelegateForFunctionPointer(addr, delegateType); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace RainmeterEditor.Interop +{ + public class NativeLibrary : IDisposable + { + #region Imports + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern IntPtr LoadLibrary(string libname); + + [DllImport("kernel32.dll", CharSet = CharSet.Ansi)] + private static extern bool FreeLibrary(IntPtr hModule); + + [DllImport("kernel32.dll", CharSet = CharSet.Ansi)] + private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); + + #endregion + + public string DllName { get; private set; } + private IntPtr _handle; + + public NativeLibrary(string dllName) + { + // Set properties + DllName = dllName; + + // Load library + _handle = LoadLibrary(DllName); + if (_handle == IntPtr.Zero) + { + int errorCode = Marshal.GetLastWin32Error(); + throw new BadImageFormatException(string.Format("Failed to load library (ErrorCode: {0})", errorCode)); + } + } + + public void Dispose() + { + if (_handle != IntPtr.Zero) + FreeLibrary(_handle); + } + + public Delegate GetFunctionByName(string name, Type delegateType) + { + IntPtr addr = GetProcAddress(_handle, name); + return Marshal.GetDelegateForFunctionPointer(addr, delegateType); + } + } +} diff --git a/RainmeterEditor/LICENSE b/RainmeterEditor/LICENSE index fe5f7ed6..67901943 100644 --- a/RainmeterEditor/LICENSE +++ b/RainmeterEditor/LICENSE @@ -1,20 +1,20 @@ -The MIT License (MIT) - -Copyright (c) 2008 Ricardo Amores Hernández - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +The MIT License (MIT) + +Copyright (c) 2008 Ricardo Amores Hernández + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/RainmeterEditor/Model/DocumentFormat.cs b/RainmeterEditor/Model/DocumentFormat.cs index 33c53728..41acc9a2 100644 --- a/RainmeterEditor/Model/DocumentFormat.cs +++ b/RainmeterEditor/Model/DocumentFormat.cs @@ -1,14 +1,14 @@ -using System.Windows.Media; - -namespace RainmeterEditor.Model -{ - public class DocumentFormat - { - public string Name { get; set; } - public ImageSource Icon { get; set; } - public string Description { get; set; } - public string DefaultExtension { get; set; } - public IDocumentEditorFactory Factory { get; set; } - public string Category { get; set; } - } -} +using System.Windows.Media; + +namespace RainmeterEditor.Model +{ + public class DocumentFormat + { + public string Name { get; set; } + public ImageSource Icon { get; set; } + public string Description { get; set; } + public string DefaultExtension { get; set; } + public IDocumentEditorFactory Factory { get; set; } + public string Category { get; set; } + } +} diff --git a/RainmeterEditor/Model/Events/DocumentOpenedEventArgs.cs b/RainmeterEditor/Model/Events/DocumentOpenedEventArgs.cs index f195ffc4..9c4e0df2 100644 --- a/RainmeterEditor/Model/Events/DocumentOpenedEventArgs.cs +++ b/RainmeterEditor/Model/Events/DocumentOpenedEventArgs.cs @@ -1,17 +1,17 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace RainmeterEditor.Model.Events -{ - public class DocumentOpenedEventArgs : EventArgs - { - public IDocumentEditor Editor { get; private set; } - - public DocumentOpenedEventArgs(IDocumentEditor editor) - { - Editor = editor; - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RainmeterEditor.Model.Events +{ + public class DocumentOpenedEventArgs : EventArgs + { + public IDocumentEditor Editor { get; private set; } + + public DocumentOpenedEventArgs(IDocumentEditor editor) + { + Editor = editor; + } + } +} diff --git a/RainmeterEditor/Model/IDocument.cs b/RainmeterEditor/Model/IDocument.cs index d2fccb6d..48ef5cf8 100644 --- a/RainmeterEditor/Model/IDocument.cs +++ b/RainmeterEditor/Model/IDocument.cs @@ -1,13 +1,13 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace RainmeterEditor.Model -{ - public interface IDocument - { - string Name { get; } - string FilePath { get; } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RainmeterEditor.Model +{ + public interface IDocument + { + string Name { get; } + string FilePath { get; } + } +} diff --git a/RainmeterEditor/Model/IDocumentEditor.cs b/RainmeterEditor/Model/IDocumentEditor.cs index 3844e2dc..b0677422 100644 --- a/RainmeterEditor/Model/IDocumentEditor.cs +++ b/RainmeterEditor/Model/IDocumentEditor.cs @@ -1,136 +1,136 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; - -namespace RainmeterEditor.Model -{ - public abstract class IDocumentEditor : IDisposable - { - #region Dirty flag - - private bool _dirty = false; - - /// <summary> - /// Gets a flag indicating if the active document is dirty (modified and not saved) - /// </summary> - public virtual bool Dirty - { - get - { - return _dirty; - } - protected set - { - _dirty = value; - if (DirtyChanged != null) - DirtyChanged(this, new EventArgs()); - } - } - - /// <summary> - /// Triggered when the dirty flag changes - /// </summary> - public event EventHandler DirtyChanged; - - #endregion - - #region Document - - /// <summary> - /// Gets the opened document - /// </summary> - public abstract IDocument Document { get; } - - /// <summary> - /// Gets the title to be displayed in the title bar - /// </summary> - public abstract string Title { get; } - - /// <summary> - /// Triggered when the title changes - /// </summary> - public event EventHandler TitleChanged; - - #endregion - - #region EditorUI - - /// <summary> - /// Gets the editor UI - /// </summary> - public abstract UIElement EditorUI { get; } - - #endregion - - #region Selection properties - - /// <summary> - /// Gets a value indicating if this editor uses the selection properties window - /// </summary> - public virtual bool UsesSelectionProperties - { - get - { - return false; - } - } - - /// <summary> - /// Gets the name of the selected object - /// </summary> - public virtual string SelectionName - { - get - { - return String.Empty; - } - } - - /// <summary> - /// Gets a list of properties for the currently selected object - /// </summary> - public virtual IEnumerable<string> SelectionProperties - { - get - { - yield break; - } - } - - /// <summary> - /// Triggered when the selected object changes (used to update properties) - /// </summary> - public event EventHandler SelectionChanged; - - #endregion - - #region Toolbox - - /// <summary> - /// Gets a list of items to populate the toolbox - /// </summary> - public virtual IEnumerable<string> ToolboxItems - { - get - { - yield break; - } - } - - public event EventHandler ToolboxChanged; - - #endregion - - #region Dispose - /// <summary> - /// Dispose - /// </summary> - public virtual void Dispose() - { - } - - #endregion - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; + +namespace RainmeterEditor.Model +{ + public abstract class IDocumentEditor : IDisposable + { + #region Dirty flag + + private bool _dirty = false; + + /// <summary> + /// Gets a flag indicating if the active document is dirty (modified and not saved) + /// </summary> + public virtual bool Dirty + { + get + { + return _dirty; + } + protected set + { + _dirty = value; + if (DirtyChanged != null) + DirtyChanged(this, new EventArgs()); + } + } + + /// <summary> + /// Triggered when the dirty flag changes + /// </summary> + public event EventHandler DirtyChanged; + + #endregion + + #region Document + + /// <summary> + /// Gets the opened document + /// </summary> + public abstract IDocument Document { get; } + + /// <summary> + /// Gets the title to be displayed in the title bar + /// </summary> + public abstract string Title { get; } + + /// <summary> + /// Triggered when the title changes + /// </summary> + public event EventHandler TitleChanged; + + #endregion + + #region EditorUI + + /// <summary> + /// Gets the editor UI + /// </summary> + public abstract UIElement EditorUI { get; } + + #endregion + + #region Selection properties + + /// <summary> + /// Gets a value indicating if this editor uses the selection properties window + /// </summary> + public virtual bool UsesSelectionProperties + { + get + { + return false; + } + } + + /// <summary> + /// Gets the name of the selected object + /// </summary> + public virtual string SelectionName + { + get + { + return String.Empty; + } + } + + /// <summary> + /// Gets a list of properties for the currently selected object + /// </summary> + public virtual IEnumerable<string> SelectionProperties + { + get + { + yield break; + } + } + + /// <summary> + /// Triggered when the selected object changes (used to update properties) + /// </summary> + public event EventHandler SelectionChanged; + + #endregion + + #region Toolbox + + /// <summary> + /// Gets a list of items to populate the toolbox + /// </summary> + public virtual IEnumerable<string> ToolboxItems + { + get + { + yield break; + } + } + + public event EventHandler ToolboxChanged; + + #endregion + + #region Dispose + /// <summary> + /// Dispose + /// </summary> + public virtual void Dispose() + { + } + + #endregion + } +} diff --git a/RainmeterEditor/Model/IDocumentEditorFactory.cs b/RainmeterEditor/Model/IDocumentEditorFactory.cs index aa10e374..806e36f8 100644 --- a/RainmeterEditor/Model/IDocumentEditorFactory.cs +++ b/RainmeterEditor/Model/IDocumentEditorFactory.cs @@ -1,39 +1,39 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using RainmeterEditor.Storage; - -namespace RainmeterEditor.Model -{ - public interface IDocumentEditorFactory - { - /// <summary> - /// Name of the editor - /// </summary> - string EditorName { get; } - - /// <summary> - /// Formats that will be used to populate the 'create document' dialog - /// </summary> - IEnumerable<DocumentFormat> CreateDocumentFormats { get; } - - /// <summary> - /// Creates a new editor object - /// </summary> - /// <param name="document">Document to be edited by the editor</param> - /// <returns>A new document editor</returns> - IDocumentEditor CreateEditor(IDocument document); - - /// <summary> - /// Creates a new document - /// </summary> - /// <returns>A new document</returns> - IDocument CreateDocument(DocumentFormat format, string path); - - /// <summary> - /// Gets the storage of this factory - /// </summary> - IDocumentStorage Storage { get; } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RainmeterEditor.Storage; + +namespace RainmeterEditor.Model +{ + public interface IDocumentEditorFactory + { + /// <summary> + /// Name of the editor + /// </summary> + string EditorName { get; } + + /// <summary> + /// Formats that will be used to populate the 'create document' dialog + /// </summary> + IEnumerable<DocumentFormat> CreateDocumentFormats { get; } + + /// <summary> + /// Creates a new editor object + /// </summary> + /// <param name="document">Document to be edited by the editor</param> + /// <returns>A new document editor</returns> + IDocumentEditor CreateEditor(IDocument document); + + /// <summary> + /// Creates a new document + /// </summary> + /// <returns>A new document</returns> + IDocument CreateDocument(DocumentFormat format, string path); + + /// <summary> + /// Gets the storage of this factory + /// </summary> + IDocumentStorage Storage { get; } + } +} diff --git a/RainmeterEditor/Model/IDocumentStorage.cs b/RainmeterEditor/Model/IDocumentStorage.cs index 9ee7edac..061945c8 100644 --- a/RainmeterEditor/Model/IDocumentStorage.cs +++ b/RainmeterEditor/Model/IDocumentStorage.cs @@ -1,26 +1,26 @@ -namespace RainmeterEditor.Model -{ - public interface IDocumentStorage - { - /// <summary> - /// Reads a document from file - /// </summary> - /// <param name="path">Path to file</param> - /// <returns>Read document</returns> - IDocument Read(string path); - - /// <summary> - /// Writes a document to a file - /// </summary> - /// <param name="path">Path to file</param> - /// <param name="document">Document to write</param> - void Write(string path, IDocument document); - - /// <summary> - /// Tests if the file can be read by this storage - /// </summary> - /// <param name="path">Path to file</param> - /// <returns>True if file can be read</returns> - bool CanRead(string path); - } -} +namespace RainmeterEditor.Model +{ + public interface IDocumentStorage + { + /// <summary> + /// Reads a document from file + /// </summary> + /// <param name="path">Path to file</param> + /// <returns>Read document</returns> + IDocument Read(string path); + + /// <summary> + /// Writes a document to a file + /// </summary> + /// <param name="path">Path to file</param> + /// <param name="document">Document to write</param> + void Write(string path, IDocument document); + + /// <summary> + /// Tests if the file can be read by this storage + /// </summary> + /// <param name="path">Path to file</param> + /// <returns>True if file can be read</returns> + bool CanRead(string path); + } +} diff --git a/RainmeterEditor/Model/Project.cs b/RainmeterEditor/Model/Project.cs index d971beae..e697f616 100644 --- a/RainmeterEditor/Model/Project.cs +++ b/RainmeterEditor/Model/Project.cs @@ -1,114 +1,114 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Xml.Serialization; - -namespace RainmeterEditor.Model -{ - public class Project - { - [XmlElement("name")] - public string Name { get; set; } - - [XmlElement("author")] - public string Author { get; set; } - - [XmlIgnore] - public Version Version { get; set; } - - [XmlElement("version")] - public string VersionString - { - get - { - return Version.ToString(); - } - set - { - Version = new Version(value); - } - } - - [XmlElement("autoLoadFile")] - public Reference AutoLoadFile { get; set; } - - [XmlArray("variableFiles")] - public List<Reference> VariableFiles { get; set; } - - [XmlIgnore] - public Version MinimumRainmeter { get; set; } - - [XmlElement("minimumRainmeter")] - public string MinimumRainmeterString - { - get - { - return MinimumRainmeter.ToString(); - } - set - { - MinimumRainmeter = new Version(value); - } - } - - [XmlIgnore] - public Version MinimumWindows { get; set; } - - [XmlElement("minimumWindows")] - public string MinimumWindowsString - { - get - { - return MinimumWindows.ToString(); - } - set - { - MinimumWindows = new Version(value); - } - } - - [XmlElement("root")] - public Tree<Reference> Root { get; set; } - - public Project() - { - Root = new Tree<Reference>(); - VariableFiles = new List<Reference>(); - Version = new Version(); - MinimumRainmeter = new Version("3.1"); - MinimumWindows = new Version("5.1"); - } - - public override bool Equals(object obj) - { - Project other = obj as Project; - - if (other == null) - return false; - - bool res = String.Equals(Author, other.Author); - res &= Reference.Equals(AutoLoadFile, other.AutoLoadFile); - res &= Version.Equals(MinimumRainmeter, other.MinimumRainmeter); - res &= Version.Equals(MinimumWindows, other.MinimumWindows); - res &= String.Equals(Name, other.Name); - res &= Tree<Reference>.Equals(Root, other.Root); - res &= Version.Equals(Version, other.Version); - - return res; - } - - public override int GetHashCode() - { - int hash = (Author == null) ? 0 : Author.GetHashCode(); - hash = hash * 7 + ((AutoLoadFile == null) ? 0 : AutoLoadFile.GetHashCode()); - hash = hash * 7 + ((MinimumRainmeter == null) ? 0 : MinimumRainmeter.GetHashCode()); - hash = hash * 7 + ((MinimumWindows == null) ? 0 : MinimumWindows.GetHashCode()); - hash = hash * 7 + ((Name == null) ? 0 : Name.GetHashCode()); - hash = hash * 7 + ((Root == null) ? 0 : Root.GetHashCode()); - hash = hash * 7 + ((Version == null) ? 0 : Version.GetHashCode()); - - return hash; - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Serialization; + +namespace RainmeterEditor.Model +{ + public class Project + { + [XmlElement("name")] + public string Name { get; set; } + + [XmlElement("author")] + public string Author { get; set; } + + [XmlIgnore] + public Version Version { get; set; } + + [XmlElement("version")] + public string VersionString + { + get + { + return Version.ToString(); + } + set + { + Version = new Version(value); + } + } + + [XmlElement("autoLoadFile")] + public Reference AutoLoadFile { get; set; } + + [XmlArray("variableFiles")] + public List<Reference> VariableFiles { get; set; } + + [XmlIgnore] + public Version MinimumRainmeter { get; set; } + + [XmlElement("minimumRainmeter")] + public string MinimumRainmeterString + { + get + { + return MinimumRainmeter.ToString(); + } + set + { + MinimumRainmeter = new Version(value); + } + } + + [XmlIgnore] + public Version MinimumWindows { get; set; } + + [XmlElement("minimumWindows")] + public string MinimumWindowsString + { + get + { + return MinimumWindows.ToString(); + } + set + { + MinimumWindows = new Version(value); + } + } + + [XmlElement("root")] + public Tree<Reference> Root { get; set; } + + public Project() + { + Root = new Tree<Reference>(); + VariableFiles = new List<Reference>(); + Version = new Version(); + MinimumRainmeter = new Version("3.1"); + MinimumWindows = new Version("5.1"); + } + + public override bool Equals(object obj) + { + Project other = obj as Project; + + if (other == null) + return false; + + bool res = String.Equals(Author, other.Author); + res &= Reference.Equals(AutoLoadFile, other.AutoLoadFile); + res &= Version.Equals(MinimumRainmeter, other.MinimumRainmeter); + res &= Version.Equals(MinimumWindows, other.MinimumWindows); + res &= String.Equals(Name, other.Name); + res &= Tree<Reference>.Equals(Root, other.Root); + res &= Version.Equals(Version, other.Version); + + return res; + } + + public override int GetHashCode() + { + int hash = (Author == null) ? 0 : Author.GetHashCode(); + hash = hash * 7 + ((AutoLoadFile == null) ? 0 : AutoLoadFile.GetHashCode()); + hash = hash * 7 + ((MinimumRainmeter == null) ? 0 : MinimumRainmeter.GetHashCode()); + hash = hash * 7 + ((MinimumWindows == null) ? 0 : MinimumWindows.GetHashCode()); + hash = hash * 7 + ((Name == null) ? 0 : Name.GetHashCode()); + hash = hash * 7 + ((Root == null) ? 0 : Root.GetHashCode()); + hash = hash * 7 + ((Version == null) ? 0 : Version.GetHashCode()); + + return hash; + } + } +} diff --git a/RainmeterEditor/Model/Property.cs b/RainmeterEditor/Model/Property.cs index 2f06d25d..96c320a3 100644 --- a/RainmeterEditor/Model/Property.cs +++ b/RainmeterEditor/Model/Property.cs @@ -1,30 +1,30 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace RainmeterEditor.Model -{ - public class Property - { - public string Name { get; set; } - - private object _value; - public object Value - { - get - { - return _value; - } - set - { - _value = value; - - if (ValueChanged != null) - ValueChanged(this, new EventArgs()); - } - } - - public event EventHandler ValueChanged; - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RainmeterEditor.Model +{ + public class Property + { + public string Name { get; set; } + + private object _value; + public object Value + { + get + { + return _value; + } + set + { + _value = value; + + if (ValueChanged != null) + ValueChanged(this, new EventArgs()); + } + } + + public event EventHandler ValueChanged; + } +} diff --git a/RainmeterEditor/Model/RainmeterConfig.cs b/RainmeterEditor/Model/RainmeterConfig.cs index 86a23a16..e2605a2a 100644 --- a/RainmeterEditor/Model/RainmeterConfig.cs +++ b/RainmeterEditor/Model/RainmeterConfig.cs @@ -1,11 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace RainmeterEditor.Model -{ - public class RainmeterConfig - { - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RainmeterEditor.Model +{ + public class RainmeterConfig + { + } +} diff --git a/RainmeterEditor/Model/Reference.cs b/RainmeterEditor/Model/Reference.cs index da7ade23..75f9ad5b 100644 --- a/RainmeterEditor/Model/Reference.cs +++ b/RainmeterEditor/Model/Reference.cs @@ -1,50 +1,50 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Xml.Serialization; - -namespace RainmeterEditor.Model -{ - /// <summary> - /// Reference to a file or folder - /// </summary> - public class Reference - { - [XmlAttribute("name")] - public string Name { get; set; } - - [XmlAttribute("path")] - public string Path { get; set; } - - public Reference() - { - } - - public Reference(string name, string path = null) - { - Name = name; - Path = path; - } - - public override bool Equals(object obj) - { - var other = obj as Reference; - - // Types are different, so not equal - if (other == null) - return false; - - // Compare using string equals - return String.Equals(Name, other.Name) && String.Equals(Path, other.Path); - } - - public override int GetHashCode() - { - int hash = (Name == null) ? 0 : Name.GetHashCode(); - hash = hash * 7 + ((Path == null) ? 0 : Path.GetHashCode()); - - return hash; - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Serialization; + +namespace RainmeterEditor.Model +{ + /// <summary> + /// Reference to a file or folder + /// </summary> + public class Reference + { + [XmlAttribute("name")] + public string Name { get; set; } + + [XmlAttribute("path")] + public string Path { get; set; } + + public Reference() + { + } + + public Reference(string name, string path = null) + { + Name = name; + Path = path; + } + + public override bool Equals(object obj) + { + var other = obj as Reference; + + // Types are different, so not equal + if (other == null) + return false; + + // Compare using string equals + return String.Equals(Name, other.Name) && String.Equals(Path, other.Path); + } + + public override int GetHashCode() + { + int hash = (Name == null) ? 0 : Name.GetHashCode(); + hash = hash * 7 + ((Path == null) ? 0 : Path.GetHashCode()); + + return hash; + } + } +} diff --git a/RainmeterEditor/Model/Tree.cs b/RainmeterEditor/Model/Tree.cs index 984c6cdc..0c187f4d 100644 --- a/RainmeterEditor/Model/Tree.cs +++ b/RainmeterEditor/Model/Tree.cs @@ -1,153 +1,153 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Xml.Serialization; - -namespace RainmeterEditor.Model -{ - public class Tree<T> - { - [XmlElement("data")] - public T Data { get; set; } - - [XmlArray("children"), XmlArrayItem("child")] - public List<Tree<T>> Children { get; set; } - - public Tree() - { - Children = new List<Tree<T>>(); - Data = default(T); - } - - public Tree(T data) - { - Children = new List<Tree<T>>(); - Data = data; - } - - public int IndexOf(Tree<T> item) - { - return Children.IndexOf(item); - } - - public void Insert(int index, Tree<T> item) - { - Children.Insert(index, item); - } - - public void RemoveAt(int index) - { - Children.RemoveAt(index); - } - - public Tree<T> this[int index] - { - get - { - return Children[index]; - } - set - { - Children[index] = value; - } - } - - public void Add(Tree<T> item) - { - Children.Add(item); - } - - public void Clear() - { - Children.Clear(); - } - - public bool Contains(Tree<T> item) - { - return Children.Contains(item); - } - - public void CopyTo(Tree<T>[] array, int arrayIndex) - { - Children.CopyTo(array, arrayIndex); - } - - public int Count - { - get { return Children.Count; } - } - - public bool IsReadOnly - { - get { return false; } - } - - public bool Remove(Tree<T> item) - { - return Children.Remove(item); - } - - public IEnumerator<Tree<T>> GetEnumerator() - { - return Children.GetEnumerator(); - } - - public int IndexOf(T item) - { - return Children.IndexOf(new Tree<T>(item)); - } - - public void Insert(int index, T item) - { - Children.Insert(index, new Tree<T>(item)); - } - - public void Add(T item) - { - Children.Add(new Tree<T>(item)); - } - - public bool Contains(T item) - { - return Children.Contains(new Tree<T>(item)); - } - - public void CopyTo(T[] array, int arrayIndex) - { - foreach (var node in Children) - array[arrayIndex++] = node.Data; - } - - public bool Remove(T item) - { - return Children.Remove(new Tree<T>(item)); - } - - public override bool Equals(object obj) - { - Tree<T> other = obj as Tree<T>; - - // Types are different, so not equal - if (other == null) - return false; - - // Compare data - if (!object.Equals(Data, other.Data)) - return false; - - // Compare children array - return Children.SequenceEqual(other.Children); - } - - public override int GetHashCode() - { - int hash = ((Data == null) ? 0 : Data.GetHashCode()); - - foreach (var c in Children) - hash = hash * 7 + c.GetHashCode(); - - return hash; - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Serialization; + +namespace RainmeterEditor.Model +{ + public class Tree<T> + { + [XmlElement("data")] + public T Data { get; set; } + + [XmlArray("children"), XmlArrayItem("child")] + public List<Tree<T>> Children { get; set; } + + public Tree() + { + Children = new List<Tree<T>>(); + Data = default(T); + } + + public Tree(T data) + { + Children = new List<Tree<T>>(); + Data = data; + } + + public int IndexOf(Tree<T> item) + { + return Children.IndexOf(item); + } + + public void Insert(int index, Tree<T> item) + { + Children.Insert(index, item); + } + + public void RemoveAt(int index) + { + Children.RemoveAt(index); + } + + public Tree<T> this[int index] + { + get + { + return Children[index]; + } + set + { + Children[index] = value; + } + } + + public void Add(Tree<T> item) + { + Children.Add(item); + } + + public void Clear() + { + Children.Clear(); + } + + public bool Contains(Tree<T> item) + { + return Children.Contains(item); + } + + public void CopyTo(Tree<T>[] array, int arrayIndex) + { + Children.CopyTo(array, arrayIndex); + } + + public int Count + { + get { return Children.Count; } + } + + public bool IsReadOnly + { + get { return false; } + } + + public bool Remove(Tree<T> item) + { + return Children.Remove(item); + } + + public IEnumerator<Tree<T>> GetEnumerator() + { + return Children.GetEnumerator(); + } + + public int IndexOf(T item) + { + return Children.IndexOf(new Tree<T>(item)); + } + + public void Insert(int index, T item) + { + Children.Insert(index, new Tree<T>(item)); + } + + public void Add(T item) + { + Children.Add(new Tree<T>(item)); + } + + public bool Contains(T item) + { + return Children.Contains(new Tree<T>(item)); + } + + public void CopyTo(T[] array, int arrayIndex) + { + foreach (var node in Children) + array[arrayIndex++] = node.Data; + } + + public bool Remove(T item) + { + return Children.Remove(new Tree<T>(item)); + } + + public override bool Equals(object obj) + { + Tree<T> other = obj as Tree<T>; + + // Types are different, so not equal + if (other == null) + return false; + + // Compare data + if (!object.Equals(Data, other.Data)) + return false; + + // Compare children array + return Children.SequenceEqual(other.Children); + } + + public override int GetHashCode() + { + int hash = ((Data == null) ? 0 : Data.GetHashCode()); + + foreach (var c in Children) + hash = hash * 7 + c.GetHashCode(); + + return hash; + } + } +} diff --git a/RainmeterEditor/Properties/AssemblyInfo.cs b/RainmeterEditor/Properties/AssemblyInfo.cs index 111b0a67..f9620b46 100644 --- a/RainmeterEditor/Properties/AssemblyInfo.cs +++ b/RainmeterEditor/Properties/AssemblyInfo.cs @@ -1,55 +1,55 @@ -using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Windows; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("RainmeterEditor")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("RainmeterEditor")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -//In order to begin building localizable applications, set -//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file -//inside a <PropertyGroup>. For example, if you are using US english -//in your source files, set the <UICulture> to en-US. Then uncomment -//the NeutralResourceLanguage attribute below. Update the "en-US" in -//the line below to match the UICulture setting in the project file. - -//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] - - -[assembly: ThemeInfo( - ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located - //(used if a resource is not found in the page, - // or application resource dictionaries) - ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located - //(used if a resource is not found in the page, - // app, or any theme specific resource dictionaries) -)] - - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("RainmeterEditor")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("RainmeterEditor")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file +//inside a <PropertyGroup>. For example, if you are using US english +//in your source files, set the <UICulture> to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/RainmeterEditor/Properties/Resources.Designer.cs b/RainmeterEditor/Properties/Resources.Designer.cs index 76b1fffe..06dc2237 100644 --- a/RainmeterEditor/Properties/Resources.Designer.cs +++ b/RainmeterEditor/Properties/Resources.Designer.cs @@ -1,63 +1,63 @@ -//------------------------------------------------------------------------------ -// <auto-generated> -// This code was generated by a tool. -// Runtime Version:4.0.30319.34014 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// </auto-generated> -//------------------------------------------------------------------------------ - -namespace RainmeterEditor.Properties { - using System; - - - /// <summary> - /// A strongly-typed resource class, for looking up localized strings, etc. - /// </summary> - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// <summary> - /// Returns the cached ResourceManager instance used by this class. - /// </summary> - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RainmeterEditor.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// <summary> - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// </summary> - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.34014 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace RainmeterEditor.Properties { + using System; + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RainmeterEditor.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/RainmeterEditor/Properties/Resources.resx b/RainmeterEditor/Properties/Resources.resx index ffecec85..af7dbebb 100644 --- a/RainmeterEditor/Properties/Resources.resx +++ b/RainmeterEditor/Properties/Resources.resx @@ -1,117 +1,117 @@ -<?xml version="1.0" encoding="utf-8"?> -<root> - <!-- - Microsoft ResX Schema - - Version 2.0 - - The primary goals of this format is to allow a simple XML format - that is mostly human readable. The generation and parsing of the - various data types are done through the TypeConverter classes - associated with the data types. - - Example: - - ... ado.net/XML headers & schema ... - <resheader name="resmimetype">text/microsoft-resx</resheader> - <resheader name="version">2.0</resheader> - <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> - <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> - <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> - <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> - <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> - <value>[base64 mime encoded serialized .NET Framework object]</value> - </data> - <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> - <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> - <comment>This is a comment</comment> - </data> - - There are any number of "resheader" rows that contain simple - name/value pairs. - - Each data row contains a name, and value. The row also contains a - type or mimetype. Type corresponds to a .NET class that support - text/value conversion through the TypeConverter architecture. - Classes that don't support this are serialized and stored with the - mimetype set. - - The mimetype is used for serialized objects, and tells the - ResXResourceReader how to depersist the object. This is currently not - extensible. For a given mimetype the value must be set accordingly: - - Note - application/x-microsoft.net.object.binary.base64 is the format - that the ResXResourceWriter will generate, however the reader can - read any of the formats listed below. - - mimetype: application/x-microsoft.net.object.binary.base64 - value : The object must be serialized with - : System.Serialization.Formatters.Binary.BinaryFormatter - : and then encoded with base64 encoding. - - mimetype: application/x-microsoft.net.object.soap.base64 - value : The object must be serialized with - : System.Runtime.Serialization.Formatters.Soap.SoapFormatter - : and then encoded with base64 encoding. - - mimetype: application/x-microsoft.net.object.bytearray.base64 - value : The object must be serialized into a byte array - : using a System.ComponentModel.TypeConverter - : and then encoded with base64 encoding. - --> - <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> - <xsd:element name="root" msdata:IsDataSet="true"> - <xsd:complexType> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="metadata"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" /> - <xsd:attribute name="type" type="xsd:string" /> - <xsd:attribute name="mimetype" type="xsd:string" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="assembly"> - <xsd:complexType> - <xsd:attribute name="alias" type="xsd:string" /> - <xsd:attribute name="name" type="xsd:string" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="data"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> - <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> - <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> - <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="resheader"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" use="required" /> - </xsd:complexType> - </xsd:element> - </xsd:choice> - </xsd:complexType> - </xsd:element> - </xsd:schema> - <resheader name="resmimetype"> - <value>text/microsoft-resx</value> - </resheader> - <resheader name="version"> - <value>2.0</value> - </resheader> - <resheader name="reader"> - <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </resheader> - <resheader name="writer"> - <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </resheader> +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> </root> \ No newline at end of file diff --git a/RainmeterEditor/Properties/Settings.Designer.cs b/RainmeterEditor/Properties/Settings.Designer.cs index 5c2289cb..cfa37b69 100644 --- a/RainmeterEditor/Properties/Settings.Designer.cs +++ b/RainmeterEditor/Properties/Settings.Designer.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------------------------ -// <auto-generated> -// This code was generated by a tool. -// Runtime Version:4.0.30319.34014 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// </auto-generated> -//------------------------------------------------------------------------------ - -namespace RainmeterEditor.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.34014 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace RainmeterEditor.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/RainmeterEditor/Properties/Settings.settings b/RainmeterEditor/Properties/Settings.settings index 8f2fd95d..033d7a5e 100644 --- a/RainmeterEditor/Properties/Settings.settings +++ b/RainmeterEditor/Properties/Settings.settings @@ -1,7 +1,7 @@ -<?xml version='1.0' encoding='utf-8'?> -<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)"> - <Profiles> - <Profile Name="(Default)" /> - </Profiles> - <Settings /> +<?xml version='1.0' encoding='utf-8'?> +<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)"> + <Profiles> + <Profile Name="(Default)" /> + </Profiles> + <Settings /> </SettingsFile> \ No newline at end of file diff --git a/RainmeterEditor/Rainmeter.cs b/RainmeterEditor/Rainmeter.cs index 6eddbec1..136b55f6 100644 --- a/RainmeterEditor/Rainmeter.cs +++ b/RainmeterEditor/Rainmeter.cs @@ -1,59 +1,59 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using RainmeterEditor.Interop; - -namespace RainmeterEditor -{ - class Rainmeter - { - #region Imports - - [DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr Rainmeter_Initialize(); - - [DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)] - private static extern void Rainmeter_Finalize(IntPtr handle); - - #endregion - - private static Rainmeter _instance = null; - - /// <summary> - /// Gets the single instance of this class - /// </summary> - public static Rainmeter Instance - { - get - { - if (_instance == null) - _instance = new Rainmeter(); - - return _instance; - } - } - - private IntPtr _handle; - - #region Constructor, finalizer - - private Rainmeter() - { - _handle = Rainmeter_Initialize(); - - if (_handle == IntPtr.Zero) - throw new Exception("Failed to initialize native library."); - } - - ~Rainmeter() - { - Rainmeter_Finalize(_handle); - } - - #endregion - - public IntPtr Handle { get { return _handle; } } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using RainmeterEditor.Interop; + +namespace RainmeterEditor +{ + class Rainmeter + { + #region Imports + + [DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr Rainmeter_Initialize(); + + [DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)] + private static extern void Rainmeter_Finalize(IntPtr handle); + + #endregion + + private static Rainmeter _instance = null; + + /// <summary> + /// Gets the single instance of this class + /// </summary> + public static Rainmeter Instance + { + get + { + if (_instance == null) + _instance = new Rainmeter(); + + return _instance; + } + } + + private IntPtr _handle; + + #region Constructor, finalizer + + private Rainmeter() + { + _handle = Rainmeter_Initialize(); + + if (_handle == IntPtr.Zero) + throw new Exception("Failed to initialize native library."); + } + + ~Rainmeter() + { + Rainmeter_Finalize(_handle); + } + + #endregion + + public IntPtr Handle { get { return _handle; } } + } +} diff --git a/RainmeterEditor/RainmeterStudio.csproj b/RainmeterEditor/RainmeterStudio.csproj index eb22ed21..202b305b 100644 --- a/RainmeterEditor/RainmeterStudio.csproj +++ b/RainmeterEditor/RainmeterStudio.csproj @@ -1,214 +1,214 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <ProjectGuid>{438D0136-4A27-4E4D-A617-FFACE4554236}</ProjectGuid> - <OutputType>WinExe</OutputType> - <AppDesignerFolder>Properties</AppDesignerFolder> - <RootNamespace>RainmeterEditor</RootNamespace> - <AssemblyName>RainmeterEditor</AssemblyName> - <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> - <FileAlignment>512</FileAlignment> - <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> - <WarningLevel>4</WarningLevel> - <TargetFrameworkProfile /> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <PlatformTarget>x86</PlatformTarget> - <DebugSymbols>true</DebugSymbols> - <DebugType>full</DebugType> - <Optimize>false</Optimize> - <OutputPath>..\x32-Debug\</OutputPath> - <DefineConstants>DEBUG;TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <PlatformTarget>AnyCPU</PlatformTarget> - <DebugType>pdbonly</DebugType> - <Optimize>true</Optimize> - <OutputPath>bin\Release\</OutputPath> - <DefineConstants>TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <ItemGroup> - <Reference Include="INIFileParser"> - <HintPath>..\packages\ini-parser.2.1.1\lib\INIFileParser.dll</HintPath> - </Reference> - <Reference Include="System" /> - <Reference Include="System.Data" /> - <Reference Include="System.Xaml" /> - <Reference Include="System.Xml" /> - <Reference Include="System.Core" /> - <Reference Include="System.Xml.Linq" /> - <Reference Include="System.Data.DataSetExtensions" /> - <Reference Include="WindowsBase" /> - <Reference Include="PresentationCore" /> - <Reference Include="PresentationFramework" /> - <Reference Include="Xceed.Wpf.AvalonDock"> - <HintPath>..\packages\AvalonDock.2.0.2000\lib\net40\Xceed.Wpf.AvalonDock.dll</HintPath> - </Reference> - <Reference Include="Xceed.Wpf.AvalonDock.Themes.Aero"> - <HintPath>..\packages\AvalonDock.2.0.2000\lib\net40\Xceed.Wpf.AvalonDock.Themes.Aero.dll</HintPath> - </Reference> - <Reference Include="Xceed.Wpf.AvalonDock.Themes.Expression"> - <HintPath>..\packages\AvalonDock.2.0.2000\lib\net40\Xceed.Wpf.AvalonDock.Themes.Expression.dll</HintPath> - </Reference> - <Reference Include="Xceed.Wpf.AvalonDock.Themes.Metro"> - <HintPath>..\packages\AvalonDock.2.0.2000\lib\net40\Xceed.Wpf.AvalonDock.Themes.Metro.dll</HintPath> - </Reference> - <Reference Include="Xceed.Wpf.AvalonDock.Themes.VS2010"> - <HintPath>..\packages\AvalonDock.2.0.2000\lib\net40\Xceed.Wpf.AvalonDock.Themes.VS2010.dll</HintPath> - </Reference> - </ItemGroup> - <ItemGroup> - <ApplicationDefinition Include="App.xaml"> - <Generator>MSBuild:Compile</Generator> - <SubType>Designer</SubType> - </ApplicationDefinition> - <Compile Include="Business\DocumentManager.cs" /> - <Compile Include="Business\ProjectManager.cs" /> - <Compile Include="Documents\Text\TextDocument.cs" /> - <Compile Include="Documents\Text\TextEditorControl.xaml.cs"> - <DependentUpon>TextEditorControl.xaml</DependentUpon> - </Compile> - <Compile Include="Documents\Text\TextStorage.cs" /> - <Compile Include="Model\DocumentFormat.cs" /> - <Compile Include="Model\IDocument.cs" /> - <Compile Include="Model\IDocumentEditor.cs" /> - <Compile Include="Model\IDocumentEditorFactory.cs" /> - <Compile Include="Documents\Ini\IniDocument.cs" /> - <Compile Include="Documents\Ini\IniSkinDesigner.cs" /> - <Compile Include="Documents\Ini\IniSkinDesignerControl.xaml.cs"> - <DependentUpon>IniSkinDesignerControl.xaml</DependentUpon> - </Compile> - <Compile Include="Documents\Ini\IniSkinDesignerFactory.cs" /> - <Compile Include="Documents\Text\TextEditor.cs" /> - <Compile Include="Documents\Text\TextEditorFactory.cs" /> - <Compile Include="Interop\NativeLibrary.cs" /> - <Compile Include="Model\Project.cs" /> - <Compile Include="Model\Property.cs" /> - <Compile Include="Model\RainmeterConfig.cs" /> - <Compile Include="Model\Reference.cs" /> - <Compile Include="Model\Tree.cs" /> - <Compile Include="Rainmeter.cs" /> - <Compile Include="Resources\Strings.Designer.cs"> - <AutoGen>True</AutoGen> - <DesignTime>True</DesignTime> - <DependentUpon>Strings.resx</DependentUpon> - </Compile> - <Compile Include="Model\IDocumentStorage.cs" /> - <Compile Include="Storage\ProjectStorage.cs" /> - <Compile Include="Storage\SkinDirectory.cs" /> - <Compile Include="UI\Command.cs" /> - <Compile Include="UI\Dialogs\CreateDocumentDialog.xaml.cs"> - <DependentUpon>CreateDocumentDialog.xaml</DependentUpon> - </Compile> - <Compile Include="UI\Controller\DocumentController.cs" /> - <Compile Include="Model\Events\DocumentOpenedEventArgs.cs" /> - <Compile Include="UI\SkinsPanel.xaml.cs"> - <DependentUpon>SkinsPanel.xaml</DependentUpon> - </Compile> - <Page Include="Documents\Ini\IniSkinDesignerControl.xaml"> - <SubType>Designer</SubType> - <Generator>MSBuild:Compile</Generator> - </Page> - <Page Include="Documents\Text\TextEditorControl.xaml"> - <SubType>Designer</SubType> - <Generator>MSBuild:Compile</Generator> - </Page> - <Page Include="UI\Dialogs\CreateDocumentDialog.xaml"> - <SubType>Designer</SubType> - <Generator>MSBuild:Compile</Generator> - </Page> - <Page Include="UI\MainWindow.xaml"> - <Generator>MSBuild:Compile</Generator> - <SubType>Designer</SubType> - </Page> - <Compile Include="App.xaml.cs"> - <DependentUpon>App.xaml</DependentUpon> - <SubType>Code</SubType> - </Compile> - <Compile Include="UI\MainWindow.xaml.cs"> - <DependentUpon>MainWindow.xaml</DependentUpon> - <SubType>Code</SubType> - </Compile> - <Page Include="UI\SkinsPanel.xaml"> - <SubType>Designer</SubType> - <Generator>MSBuild:Compile</Generator> - </Page> - <Page Include="UI\Styles\ButtonStyle.xaml"> - <SubType>Designer</SubType> - <Generator>MSBuild:Compile</Generator> - </Page> - <Page Include="UI\Styles\Common.xaml"> - <SubType>Designer</SubType> - <Generator>MSBuild:Compile</Generator> - </Page> - </ItemGroup> - <ItemGroup> - <Compile Include="Properties\AssemblyInfo.cs"> - <SubType>Code</SubType> - </Compile> - <Compile Include="Properties\Resources.Designer.cs"> - <AutoGen>True</AutoGen> - <DesignTime>True</DesignTime> - <DependentUpon>Resources.resx</DependentUpon> - </Compile> - <Compile Include="Properties\Settings.Designer.cs"> - <AutoGen>True</AutoGen> - <DependentUpon>Settings.settings</DependentUpon> - <DesignTimeSharedInput>True</DesignTimeSharedInput> - </Compile> - <EmbeddedResource Include="Properties\Resources.resx"> - <Generator>ResXFileCodeGenerator</Generator> - <LastGenOutput>Resources.Designer.cs</LastGenOutput> - </EmbeddedResource> - <EmbeddedResource Include="Resources\Strings.resx"> - <Generator>ResXFileCodeGenerator</Generator> - <LastGenOutput>Strings.Designer.cs</LastGenOutput> - </EmbeddedResource> - <None Include="app.config" /> - <None Include="LICENSE" /> - <None Include="packages.config" /> - <None Include="Properties\Settings.settings"> - <Generator>SettingsSingleFileGenerator</Generator> - <LastGenOutput>Settings.Designer.cs</LastGenOutput> - </None> - <AppDesigner Include="Properties\" /> - </ItemGroup> - <ItemGroup> - <Resource Include="Resources\Icons\text_file_32.png" /> - </ItemGroup> - <ItemGroup> - <SplashScreen Include="Resources\splash.png" /> - </ItemGroup> - <ItemGroup> - <Resource Include="Resources\Icons\arrow_left_16.png" /> - </ItemGroup> - <ItemGroup> - <Resource Include="Resources\Icons\arrow_right_16.png" /> - </ItemGroup> - <ItemGroup> - <Resource Include="Resources\Icons\arrow_backward_16.png" /> - <Resource Include="Resources\Icons\arrow_forward_16.png" /> - </ItemGroup> - <ItemGroup> - <Resource Include="Resources\Icons\page_white_star_16.png" /> - </ItemGroup> - <ItemGroup> - <Resource Include="Resources\Icons\project_16.png" /> - <Resource Include="Resources\Icons\project_star_16.png" /> - </ItemGroup> - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{438D0136-4A27-4E4D-A617-FFACE4554236}</ProjectGuid> + <OutputType>WinExe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>RainmeterEditor</RootNamespace> + <AssemblyName>RainmeterEditor</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <WarningLevel>4</WarningLevel> + <TargetFrameworkProfile /> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <PlatformTarget>x86</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\x32-Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="INIFileParser"> + <HintPath>..\packages\ini-parser.2.1.1\lib\INIFileParser.dll</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xaml" /> + <Reference Include="System.Xml" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="WindowsBase" /> + <Reference Include="PresentationCore" /> + <Reference Include="PresentationFramework" /> + <Reference Include="Xceed.Wpf.AvalonDock"> + <HintPath>..\packages\AvalonDock.2.0.2000\lib\net40\Xceed.Wpf.AvalonDock.dll</HintPath> + </Reference> + <Reference Include="Xceed.Wpf.AvalonDock.Themes.Aero"> + <HintPath>..\packages\AvalonDock.2.0.2000\lib\net40\Xceed.Wpf.AvalonDock.Themes.Aero.dll</HintPath> + </Reference> + <Reference Include="Xceed.Wpf.AvalonDock.Themes.Expression"> + <HintPath>..\packages\AvalonDock.2.0.2000\lib\net40\Xceed.Wpf.AvalonDock.Themes.Expression.dll</HintPath> + </Reference> + <Reference Include="Xceed.Wpf.AvalonDock.Themes.Metro"> + <HintPath>..\packages\AvalonDock.2.0.2000\lib\net40\Xceed.Wpf.AvalonDock.Themes.Metro.dll</HintPath> + </Reference> + <Reference Include="Xceed.Wpf.AvalonDock.Themes.VS2010"> + <HintPath>..\packages\AvalonDock.2.0.2000\lib\net40\Xceed.Wpf.AvalonDock.Themes.VS2010.dll</HintPath> + </Reference> + </ItemGroup> + <ItemGroup> + <ApplicationDefinition Include="App.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </ApplicationDefinition> + <Compile Include="Business\DocumentManager.cs" /> + <Compile Include="Business\ProjectManager.cs" /> + <Compile Include="Documents\Text\TextDocument.cs" /> + <Compile Include="Documents\Text\TextEditorControl.xaml.cs"> + <DependentUpon>TextEditorControl.xaml</DependentUpon> + </Compile> + <Compile Include="Documents\Text\TextStorage.cs" /> + <Compile Include="Model\DocumentFormat.cs" /> + <Compile Include="Model\IDocument.cs" /> + <Compile Include="Model\IDocumentEditor.cs" /> + <Compile Include="Model\IDocumentEditorFactory.cs" /> + <Compile Include="Documents\Ini\IniDocument.cs" /> + <Compile Include="Documents\Ini\IniSkinDesigner.cs" /> + <Compile Include="Documents\Ini\IniSkinDesignerControl.xaml.cs"> + <DependentUpon>IniSkinDesignerControl.xaml</DependentUpon> + </Compile> + <Compile Include="Documents\Ini\IniSkinDesignerFactory.cs" /> + <Compile Include="Documents\Text\TextEditor.cs" /> + <Compile Include="Documents\Text\TextEditorFactory.cs" /> + <Compile Include="Interop\NativeLibrary.cs" /> + <Compile Include="Model\Project.cs" /> + <Compile Include="Model\Property.cs" /> + <Compile Include="Model\RainmeterConfig.cs" /> + <Compile Include="Model\Reference.cs" /> + <Compile Include="Model\Tree.cs" /> + <Compile Include="Rainmeter.cs" /> + <Compile Include="Resources\Strings.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Strings.resx</DependentUpon> + </Compile> + <Compile Include="Model\IDocumentStorage.cs" /> + <Compile Include="Storage\ProjectStorage.cs" /> + <Compile Include="Storage\SkinDirectory.cs" /> + <Compile Include="UI\Command.cs" /> + <Compile Include="UI\Dialogs\CreateDocumentDialog.xaml.cs"> + <DependentUpon>CreateDocumentDialog.xaml</DependentUpon> + </Compile> + <Compile Include="UI\Controller\DocumentController.cs" /> + <Compile Include="Model\Events\DocumentOpenedEventArgs.cs" /> + <Compile Include="UI\SkinsPanel.xaml.cs"> + <DependentUpon>SkinsPanel.xaml</DependentUpon> + </Compile> + <Page Include="Documents\Ini\IniSkinDesignerControl.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Documents\Text\TextEditorControl.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="UI\Dialogs\CreateDocumentDialog.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="UI\MainWindow.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </Page> + <Compile Include="App.xaml.cs"> + <DependentUpon>App.xaml</DependentUpon> + <SubType>Code</SubType> + </Compile> + <Compile Include="UI\MainWindow.xaml.cs"> + <DependentUpon>MainWindow.xaml</DependentUpon> + <SubType>Code</SubType> + </Compile> + <Page Include="UI\SkinsPanel.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="UI\Styles\ButtonStyle.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="UI\Styles\Common.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + </ItemGroup> + <ItemGroup> + <Compile Include="Properties\AssemblyInfo.cs"> + <SubType>Code</SubType> + </Compile> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="Properties\Settings.Designer.cs"> + <AutoGen>True</AutoGen> + <DependentUpon>Settings.settings</DependentUpon> + <DesignTimeSharedInput>True</DesignTimeSharedInput> + </Compile> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + <EmbeddedResource Include="Resources\Strings.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Strings.Designer.cs</LastGenOutput> + </EmbeddedResource> + <None Include="app.config" /> + <None Include="LICENSE" /> + <None Include="packages.config" /> + <None Include="Properties\Settings.settings"> + <Generator>SettingsSingleFileGenerator</Generator> + <LastGenOutput>Settings.Designer.cs</LastGenOutput> + </None> + <AppDesigner Include="Properties\" /> + </ItemGroup> + <ItemGroup> + <Resource Include="Resources\Icons\text_file_32.png" /> + </ItemGroup> + <ItemGroup> + <SplashScreen Include="Resources\splash.png" /> + </ItemGroup> + <ItemGroup> + <Resource Include="Resources\Icons\arrow_left_16.png" /> + </ItemGroup> + <ItemGroup> + <Resource Include="Resources\Icons\arrow_right_16.png" /> + </ItemGroup> + <ItemGroup> + <Resource Include="Resources\Icons\arrow_backward_16.png" /> + <Resource Include="Resources\Icons\arrow_forward_16.png" /> + </ItemGroup> + <ItemGroup> + <Resource Include="Resources\Icons\page_white_star_16.png" /> + </ItemGroup> + <ItemGroup> + <Resource Include="Resources\Icons\project_16.png" /> + <Resource Include="Resources\Icons\project_star_16.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> </Project> \ No newline at end of file diff --git a/RainmeterEditor/Resources/Strings.Designer.cs b/RainmeterEditor/Resources/Strings.Designer.cs index ea6d64cd..a84078db 100644 --- a/RainmeterEditor/Resources/Strings.Designer.cs +++ b/RainmeterEditor/Resources/Strings.Designer.cs @@ -1,117 +1,117 @@ -//------------------------------------------------------------------------------ -// <auto-generated> -// This code was generated by a tool. -// Runtime Version:4.0.30319.34014 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// </auto-generated> -//------------------------------------------------------------------------------ - -namespace RainmeterEditor.Resources { - using System; - - - /// <summary> - /// A strongly-typed resource class, for looking up localized strings, etc. - /// </summary> - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Strings { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Strings() { - } - - /// <summary> - /// Returns the cached ResourceManager instance used by this class. - /// </summary> - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RainmeterEditor.Resources.Strings", typeof(Strings).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// <summary> - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// </summary> - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// <summary> - /// Looks up a localized string similar to Utility. - /// </summary> - internal static string Category_Utility { - get { - return ResourceManager.GetString("Category_Utility", resourceCulture); - } - } - - /// <summary> - /// Looks up a localized string similar to _File.... - /// </summary> - internal static string DocumentCreateCommand_DisplayText { - get { - return ResourceManager.GetString("DocumentCreateCommand_DisplayText", resourceCulture); - } - } - - /// <summary> - /// Looks up a localized string similar to Creates a new file. - /// </summary> - internal static string DocumentCreateCommand_ToolTip { - get { - return ResourceManager.GetString("DocumentCreateCommand_ToolTip", resourceCulture); - } - } - - /// <summary> - /// Looks up a localized string similar to Text Editor. - /// </summary> - internal static string DocumentEditor_Text_Name { - get { - return ResourceManager.GetString("DocumentEditor_Text_Name", resourceCulture); - } - } - - /// <summary> - /// Looks up a localized string similar to Blank text file. - /// </summary> - internal static string DocumentFormat_TextFile_Description { - get { - return ResourceManager.GetString("DocumentFormat_TextFile_Description", resourceCulture); - } - } - - /// <summary> - /// Looks up a localized string similar to Text file. - /// </summary> - internal static string DocumentFormat_TextFile_Name { - get { - return ResourceManager.GetString("DocumentFormat_TextFile_Name", resourceCulture); - } - } - } -} +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.34014 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace RainmeterEditor.Resources { + using System; + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Strings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Strings() { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RainmeterEditor.Resources.Strings", typeof(Strings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// Looks up a localized string similar to Utility. + /// </summary> + internal static string Category_Utility { + get { + return ResourceManager.GetString("Category_Utility", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to _File.... + /// </summary> + internal static string DocumentCreateCommand_DisplayText { + get { + return ResourceManager.GetString("DocumentCreateCommand_DisplayText", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Creates a new file. + /// </summary> + internal static string DocumentCreateCommand_ToolTip { + get { + return ResourceManager.GetString("DocumentCreateCommand_ToolTip", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Text Editor. + /// </summary> + internal static string DocumentEditor_Text_Name { + get { + return ResourceManager.GetString("DocumentEditor_Text_Name", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Blank text file. + /// </summary> + internal static string DocumentFormat_TextFile_Description { + get { + return ResourceManager.GetString("DocumentFormat_TextFile_Description", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Text file. + /// </summary> + internal static string DocumentFormat_TextFile_Name { + get { + return ResourceManager.GetString("DocumentFormat_TextFile_Name", resourceCulture); + } + } + } +} diff --git a/RainmeterEditor/Resources/Strings.resx b/RainmeterEditor/Resources/Strings.resx index e2d125c1..a26a6958 100644 --- a/RainmeterEditor/Resources/Strings.resx +++ b/RainmeterEditor/Resources/Strings.resx @@ -1,138 +1,138 @@ -<?xml version="1.0" encoding="utf-8"?> -<root> - <!-- - Microsoft ResX Schema - - Version 2.0 - - The primary goals of this format is to allow a simple XML format - that is mostly human readable. The generation and parsing of the - various data types are done through the TypeConverter classes - associated with the data types. - - Example: - - ... ado.net/XML headers & schema ... - <resheader name="resmimetype">text/microsoft-resx</resheader> - <resheader name="version">2.0</resheader> - <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> - <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> - <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> - <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> - <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> - <value>[base64 mime encoded serialized .NET Framework object]</value> - </data> - <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> - <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> - <comment>This is a comment</comment> - </data> - - There are any number of "resheader" rows that contain simple - name/value pairs. - - Each data row contains a name, and value. The row also contains a - type or mimetype. Type corresponds to a .NET class that support - text/value conversion through the TypeConverter architecture. - Classes that don't support this are serialized and stored with the - mimetype set. - - The mimetype is used for serialized objects, and tells the - ResXResourceReader how to depersist the object. This is currently not - extensible. For a given mimetype the value must be set accordingly: - - Note - application/x-microsoft.net.object.binary.base64 is the format - that the ResXResourceWriter will generate, however the reader can - read any of the formats listed below. - - mimetype: application/x-microsoft.net.object.binary.base64 - value : The object must be serialized with - : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter - : and then encoded with base64 encoding. - - mimetype: application/x-microsoft.net.object.soap.base64 - value : The object must be serialized with - : System.Runtime.Serialization.Formatters.Soap.SoapFormatter - : and then encoded with base64 encoding. - - mimetype: application/x-microsoft.net.object.bytearray.base64 - value : The object must be serialized into a byte array - : using a System.ComponentModel.TypeConverter - : and then encoded with base64 encoding. - --> - <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> - <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> - <xsd:element name="root" msdata:IsDataSet="true"> - <xsd:complexType> - <xsd:choice maxOccurs="unbounded"> - <xsd:element name="metadata"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - <xsd:attribute name="name" use="required" type="xsd:string" /> - <xsd:attribute name="type" type="xsd:string" /> - <xsd:attribute name="mimetype" type="xsd:string" /> - <xsd:attribute ref="xml:space" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="assembly"> - <xsd:complexType> - <xsd:attribute name="alias" type="xsd:string" /> - <xsd:attribute name="name" type="xsd:string" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="data"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> - <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> - <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> - <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> - <xsd:attribute ref="xml:space" /> - </xsd:complexType> - </xsd:element> - <xsd:element name="resheader"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> - </xsd:sequence> - <xsd:attribute name="name" type="xsd:string" use="required" /> - </xsd:complexType> - </xsd:element> - </xsd:choice> - </xsd:complexType> - </xsd:element> - </xsd:schema> - <resheader name="resmimetype"> - <value>text/microsoft-resx</value> - </resheader> - <resheader name="version"> - <value>2.0</value> - </resheader> - <resheader name="reader"> - <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </resheader> - <resheader name="writer"> - <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> - </resheader> - <data name="Category_Utility" xml:space="preserve"> - <value>Utility</value> - </data> - <data name="DocumentCreateCommand_DisplayText" xml:space="preserve"> - <value>_File...</value> - </data> - <data name="DocumentCreateCommand_ToolTip" xml:space="preserve"> - <value>Creates a new file</value> - </data> - <data name="DocumentEditor_Text_Name" xml:space="preserve"> - <value>Text Editor</value> - </data> - <data name="DocumentFormat_TextFile_Description" xml:space="preserve"> - <value>Blank text file</value> - </data> - <data name="DocumentFormat_TextFile_Name" xml:space="preserve"> - <value>Text file</value> - </data> +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="Category_Utility" xml:space="preserve"> + <value>Utility</value> + </data> + <data name="DocumentCreateCommand_DisplayText" xml:space="preserve"> + <value>_File...</value> + </data> + <data name="DocumentCreateCommand_ToolTip" xml:space="preserve"> + <value>Creates a new file</value> + </data> + <data name="DocumentEditor_Text_Name" xml:space="preserve"> + <value>Text Editor</value> + </data> + <data name="DocumentFormat_TextFile_Description" xml:space="preserve"> + <value>Blank text file</value> + </data> + <data name="DocumentFormat_TextFile_Name" xml:space="preserve"> + <value>Text file</value> + </data> </root> \ No newline at end of file diff --git a/RainmeterEditor/Storage/ProjectStorage.cs b/RainmeterEditor/Storage/ProjectStorage.cs index 25f61d5d..0fd30d59 100644 --- a/RainmeterEditor/Storage/ProjectStorage.cs +++ b/RainmeterEditor/Storage/ProjectStorage.cs @@ -1,40 +1,40 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Xml.Serialization; -using RainmeterEditor.Model; - -namespace RainmeterEditor.Storage -{ - public class ProjectStorage - { - public Project Load(string path) - { - // Open file - var file = File.OpenText(path); - - // Deserialize file - var serializer = new XmlSerializer(typeof(Project), new XmlRootAttribute("project")); - Project project = serializer.Deserialize(file) as Project; - - // Clean up - file.Close(); - return project; - } - - public void Save(string path, Project project) - { - // Open file - var file = File.OpenWrite(path); - - // Deserialize file - var serializer = new XmlSerializer(typeof(Project), new XmlRootAttribute("project")); - serializer.Serialize(file, project); - - // Clean up - file.Close(); - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml.Serialization; +using RainmeterEditor.Model; + +namespace RainmeterEditor.Storage +{ + public class ProjectStorage + { + public Project Load(string path) + { + // Open file + var file = File.OpenText(path); + + // Deserialize file + var serializer = new XmlSerializer(typeof(Project), new XmlRootAttribute("project")); + Project project = serializer.Deserialize(file) as Project; + + // Clean up + file.Close(); + return project; + } + + public void Save(string path, Project project) + { + // Open file + var file = File.OpenWrite(path); + + // Deserialize file + var serializer = new XmlSerializer(typeof(Project), new XmlRootAttribute("project")); + serializer.Serialize(file, project); + + // Clean up + file.Close(); + } + } +} diff --git a/RainmeterEditor/Storage/SkinDirectory.cs b/RainmeterEditor/Storage/SkinDirectory.cs index a617ab4e..00705ff0 100644 --- a/RainmeterEditor/Storage/SkinDirectory.cs +++ b/RainmeterEditor/Storage/SkinDirectory.cs @@ -1,25 +1,25 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; - -namespace RainmeterEditor.Storage -{ - public static class SkinDirectory - { - private static string _path = null; - - public static string Path - { - get - { - return ""; - } - set - { - - } - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace RainmeterEditor.Storage +{ + public static class SkinDirectory + { + private static string _path = null; + + public static string Path + { + get + { + return ""; + } + set + { + + } + } + } +} diff --git a/RainmeterEditor/UI/Command.cs b/RainmeterEditor/UI/Command.cs index 36645b51..ebcd6643 100644 --- a/RainmeterEditor/UI/Command.cs +++ b/RainmeterEditor/UI/Command.cs @@ -1,88 +1,88 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows.Input; -using System.Windows.Media; - -namespace RainmeterEditor.UI -{ - public class Command : ICommand - { - #region Private members - - private Action<object> _execute; - private Func<object, bool> _canExecute; - private Action _executeNoParam; - private Func<bool> _canExecuteNoParam; - - #endregion - - #region Public properties - - public string Name { get; set; } - public string DisplayText { get; set; } - public string Tooltip { get; set; } - public ImageSource Icon { get; set; } - public KeyGesture Shortcut { get; set; } - - public string ShortcutText - { - get - { - string text = String.Empty; - - if ((Shortcut.Modifiers & ModifierKeys.Windows) != 0) - text += "Win+"; - - if ((Shortcut.Modifiers & ModifierKeys.Control) != 0) - text += "Ctrl+"; - - if ((Shortcut.Modifiers & ModifierKeys.Alt) != 0) - text += "Alt+"; - - if ((Shortcut.Modifiers & ModifierKeys.Shift) != 0) - text += "Shift+"; - - text += Enum.GetName(typeof(Key), Shortcut.Key); - return text; - } - } - - #endregion - - public event EventHandler CanExecuteChanged; - - public Command(string name = null, Action<object> execute = null, Func<object, bool> canExecute = null) - { - Name = name; - _execute = execute; - _canExecute = canExecute; - } - - public Command(string name = null, Action execute = null, Func<bool> canExecute = null) - { - Name = name; - _executeNoParam = execute; - _canExecuteNoParam = canExecute; - } - - public virtual bool CanExecute(object parameter) - { - if (_canExecute != null) - return _canExecute(parameter); - else if (_canExecuteNoParam != null) - return _canExecuteNoParam(); - - return true; - } - - public virtual void Execute(object parameter) - { - if (_execute != null) - _execute(parameter); - else if (_executeNoParam != null) - _executeNoParam(); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Input; +using System.Windows.Media; + +namespace RainmeterEditor.UI +{ + public class Command : ICommand + { + #region Private members + + private Action<object> _execute; + private Func<object, bool> _canExecute; + private Action _executeNoParam; + private Func<bool> _canExecuteNoParam; + + #endregion + + #region Public properties + + public string Name { get; set; } + public string DisplayText { get; set; } + public string Tooltip { get; set; } + public ImageSource Icon { get; set; } + public KeyGesture Shortcut { get; set; } + + public string ShortcutText + { + get + { + string text = String.Empty; + + if ((Shortcut.Modifiers & ModifierKeys.Windows) != 0) + text += "Win+"; + + if ((Shortcut.Modifiers & ModifierKeys.Control) != 0) + text += "Ctrl+"; + + if ((Shortcut.Modifiers & ModifierKeys.Alt) != 0) + text += "Alt+"; + + if ((Shortcut.Modifiers & ModifierKeys.Shift) != 0) + text += "Shift+"; + + text += Enum.GetName(typeof(Key), Shortcut.Key); + return text; + } + } + + #endregion + + public event EventHandler CanExecuteChanged; + + public Command(string name = null, Action<object> execute = null, Func<object, bool> canExecute = null) + { + Name = name; + _execute = execute; + _canExecute = canExecute; + } + + public Command(string name = null, Action execute = null, Func<bool> canExecute = null) + { + Name = name; + _executeNoParam = execute; + _canExecuteNoParam = canExecute; + } + + public virtual bool CanExecute(object parameter) + { + if (_canExecute != null) + return _canExecute(parameter); + else if (_canExecuteNoParam != null) + return _canExecuteNoParam(); + + return true; + } + + public virtual void Execute(object parameter) + { + if (_execute != null) + _execute(parameter); + else if (_executeNoParam != null) + _executeNoParam(); + } + } +} diff --git a/RainmeterEditor/UI/Controller/DocumentController.cs b/RainmeterEditor/UI/Controller/DocumentController.cs index 9489bb29..e5db844b 100644 --- a/RainmeterEditor/UI/Controller/DocumentController.cs +++ b/RainmeterEditor/UI/Controller/DocumentController.cs @@ -1,77 +1,77 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using RainmeterEditor.Business; -using RainmeterEditor.UI.Dialogs; -using RainmeterEditor.Model.Events; -using RainmeterEditor.Model; -using System.Windows; -using System.Windows.Input; -using System.Windows.Media.Imaging; - -namespace RainmeterEditor.UI.Controller -{ - public class DocumentController - { - #region Commands - - public Command DocumentCreateCommand { get; private set; } - - #endregion - - public event EventHandler<DocumentOpenedEventArgs> DocumentOpened - { - add - { - DocumentManager.Instance.DocumentOpened += value; - } - remove - { - DocumentManager.Instance.DocumentOpened -= value; - } - } - public event EventHandler DocumentClosed; - - public Window OwnerWindow { get; set; } - - public DocumentController() - { - DocumentCreateCommand = new Command("DocumentCreateCommand", () => CreateWindow()) - { - DisplayText = Resources.Strings.DocumentCreateCommand_DisplayText, - Tooltip = Resources.Strings.DocumentCreateCommand_ToolTip, - Icon = new BitmapImage(new Uri("/Resources/Icons/page_white_star_16.png", UriKind.RelativeOrAbsolute)), - Shortcut = new KeyGesture(Key.N, ModifierKeys.Control) - }; - } - - public void CreateWindow(DocumentFormat defaultFormat = null, string defaultPath = "") - { - // Show dialog - var dialog = new CreateDocumentDialog() - { - Owner = OwnerWindow, - SelectedFormat = defaultFormat, - SelectedPath = defaultPath - }; - bool? res = dialog.ShowDialog(); - - if (!res.HasValue || !res.Value) - return; - - var format = dialog.SelectedFormat; - var path = dialog.SelectedPath; - - // Call manager - DocumentManager.Instance.Create(format, path); - } - - public void Create(DocumentFormat format, string path) - { - // Call manager - DocumentManager.Instance.Create(format, path); - } - - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RainmeterEditor.Business; +using RainmeterEditor.UI.Dialogs; +using RainmeterEditor.Model.Events; +using RainmeterEditor.Model; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media.Imaging; + +namespace RainmeterEditor.UI.Controller +{ + public class DocumentController + { + #region Commands + + public Command DocumentCreateCommand { get; private set; } + + #endregion + + public event EventHandler<DocumentOpenedEventArgs> DocumentOpened + { + add + { + DocumentManager.Instance.DocumentOpened += value; + } + remove + { + DocumentManager.Instance.DocumentOpened -= value; + } + } + public event EventHandler DocumentClosed; + + public Window OwnerWindow { get; set; } + + public DocumentController() + { + DocumentCreateCommand = new Command("DocumentCreateCommand", () => CreateWindow()) + { + DisplayText = Resources.Strings.DocumentCreateCommand_DisplayText, + Tooltip = Resources.Strings.DocumentCreateCommand_ToolTip, + Icon = new BitmapImage(new Uri("/Resources/Icons/page_white_star_16.png", UriKind.RelativeOrAbsolute)), + Shortcut = new KeyGesture(Key.N, ModifierKeys.Control) + }; + } + + public void CreateWindow(DocumentFormat defaultFormat = null, string defaultPath = "") + { + // Show dialog + var dialog = new CreateDocumentDialog() + { + Owner = OwnerWindow, + SelectedFormat = defaultFormat, + SelectedPath = defaultPath + }; + bool? res = dialog.ShowDialog(); + + if (!res.HasValue || !res.Value) + return; + + var format = dialog.SelectedFormat; + var path = dialog.SelectedPath; + + // Call manager + DocumentManager.Instance.Create(format, path); + } + + public void Create(DocumentFormat format, string path) + { + // Call manager + DocumentManager.Instance.Create(format, path); + } + + } +} diff --git a/RainmeterEditor/UI/Dialogs/CreateDocumentDialog.xaml b/RainmeterEditor/UI/Dialogs/CreateDocumentDialog.xaml index 233bf957..7b416439 100644 --- a/RainmeterEditor/UI/Dialogs/CreateDocumentDialog.xaml +++ b/RainmeterEditor/UI/Dialogs/CreateDocumentDialog.xaml @@ -1,64 +1,64 @@ -<Window x:Class="RainmeterEditor.UI.Dialogs.CreateDocumentDialog" - xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - Title="Create..." Height="250" Width="400" - WindowStartupLocation="CenterOwner" - WindowStyle="ToolWindow" ShowInTaskbar="False"> - - <Grid Background="WhiteSmoke"> - <Grid.RowDefinitions> - <RowDefinition /> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - </Grid.RowDefinitions> - - <ListView Name="listFormats" Grid.Row="0"> - <ListView.ItemTemplate> - <DataTemplate> - <DockPanel> - <Image DockPanel.Dock="Left" Source="{Binding Icon}" - Width="32" Height="32" Margin="2" - Stretch="Uniform" VerticalAlignment="Top" /> - <StackPanel Orientation="Vertical" VerticalAlignment="Center"> - <TextBlock Text="{Binding Name}" FontWeight="Bold" /> - <TextBlock Text="{Binding Description}" /> - </StackPanel> - </DockPanel> - </DataTemplate> - </ListView.ItemTemplate> - <ListView.GroupStyle> - <GroupStyle> - <GroupStyle.HeaderTemplate> - <DataTemplate> - <TextBlock FontWeight="Bold" FontSize="13pt" Text="{Binding Name}" /> - </DataTemplate> - </GroupStyle.HeaderTemplate> - </GroupStyle> - </ListView.GroupStyle> - </ListView> - - <Grid Grid.Row="1"> - <Grid.RowDefinitions> - <RowDefinition /> - <RowDefinition /> - </Grid.RowDefinitions> - <Grid.ColumnDefinitions> - <ColumnDefinition Width="Auto" /> - <ColumnDefinition /> - <ColumnDefinition Width="Auto" /> - </Grid.ColumnDefinitions> - - <TextBlock Grid.Row="0">Path:</TextBlock> - <TextBox Name="textPath" Grid.Row="0" Grid.Column="1"></TextBox> - <Button Grid.Row="0" Grid.Column="2">...</Button> - - </Grid> - - <StackPanel Grid.Row="2" Orientation="Horizontal" - HorizontalAlignment="Right"> - <Button Name="buttonCreate" Click="buttonCreate_Click" IsDefault="True">Create</Button> - <Button Name="buttonCancel" Click="buttonCancel_Click" IsCancel="True">Cancel</Button> - </StackPanel> - - </Grid> -</Window> +<Window x:Class="RainmeterEditor.UI.Dialogs.CreateDocumentDialog" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + Title="Create..." Height="250" Width="400" + WindowStartupLocation="CenterOwner" + WindowStyle="ToolWindow" ShowInTaskbar="False"> + + <Grid Background="WhiteSmoke"> + <Grid.RowDefinitions> + <RowDefinition /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + + <ListView Name="listFormats" Grid.Row="0"> + <ListView.ItemTemplate> + <DataTemplate> + <DockPanel> + <Image DockPanel.Dock="Left" Source="{Binding Icon}" + Width="32" Height="32" Margin="2" + Stretch="Uniform" VerticalAlignment="Top" /> + <StackPanel Orientation="Vertical" VerticalAlignment="Center"> + <TextBlock Text="{Binding Name}" FontWeight="Bold" /> + <TextBlock Text="{Binding Description}" /> + </StackPanel> + </DockPanel> + </DataTemplate> + </ListView.ItemTemplate> + <ListView.GroupStyle> + <GroupStyle> + <GroupStyle.HeaderTemplate> + <DataTemplate> + <TextBlock FontWeight="Bold" FontSize="13pt" Text="{Binding Name}" /> + </DataTemplate> + </GroupStyle.HeaderTemplate> + </GroupStyle> + </ListView.GroupStyle> + </ListView> + + <Grid Grid.Row="1"> + <Grid.RowDefinitions> + <RowDefinition /> + <RowDefinition /> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="Auto" /> + <ColumnDefinition /> + <ColumnDefinition Width="Auto" /> + </Grid.ColumnDefinitions> + + <TextBlock Grid.Row="0">Path:</TextBlock> + <TextBox Name="textPath" Grid.Row="0" Grid.Column="1"></TextBox> + <Button Grid.Row="0" Grid.Column="2">...</Button> + + </Grid> + + <StackPanel Grid.Row="2" Orientation="Horizontal" + HorizontalAlignment="Right"> + <Button Name="buttonCreate" Click="buttonCreate_Click" IsDefault="True">Create</Button> + <Button Name="buttonCancel" Click="buttonCancel_Click" IsCancel="True">Cancel</Button> + </StackPanel> + + </Grid> +</Window> diff --git a/RainmeterEditor/UI/Dialogs/CreateDocumentDialog.xaml.cs b/RainmeterEditor/UI/Dialogs/CreateDocumentDialog.xaml.cs index cea85d0a..6060ed95 100644 --- a/RainmeterEditor/UI/Dialogs/CreateDocumentDialog.xaml.cs +++ b/RainmeterEditor/UI/Dialogs/CreateDocumentDialog.xaml.cs @@ -1,93 +1,93 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; -using RainmeterEditor.Business; -using RainmeterEditor.Model; - -namespace RainmeterEditor.UI.Dialogs -{ - /// <summary> - /// Interaction logic for CreateDocumentDialog.xaml - /// </summary> - public partial class CreateDocumentDialog : Window - { - /// <summary> - /// Gets or sets the currently selected file format - /// </summary> - public DocumentFormat SelectedFormat - { - get - { - return listFormats.SelectedItem as DocumentFormat; - } - set - { - listFormats.SelectedItem = value; - } - } - - /// <summary> - /// Gets or sets the path - /// </summary> - public string SelectedPath - { - get - { - return textPath.Text; - } - set - { - textPath.Text = value; - } - } - - /// <summary> - /// Creates a new instance of CreateDocumentDialog - /// </summary> - public CreateDocumentDialog() - { - InitializeComponent(); - - PopulateFormats(); - Validate(); - } - - private void PopulateFormats() - { - listFormats.ItemsSource = DocumentManager.Instance.DocumentFormats; - CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(listFormats.ItemsSource); - view.GroupDescriptions.Add(new PropertyGroupDescription("Category")); - } - - private void buttonCreate_Click(object sender, RoutedEventArgs e) - { - DialogResult = true; - Close(); - } - - private void buttonCancel_Click(object sender, RoutedEventArgs e) - { - DialogResult = false; - Close(); - } - - private void Validate() - { - bool res = true; - res &= !String.IsNullOrWhiteSpace(textPath.Text); - res &= (listFormats.SelectedItem != null); - - buttonCreate.IsEnabled = res; - } - } -} +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using RainmeterEditor.Business; +using RainmeterEditor.Model; + +namespace RainmeterEditor.UI.Dialogs +{ + /// <summary> + /// Interaction logic for CreateDocumentDialog.xaml + /// </summary> + public partial class CreateDocumentDialog : Window + { + /// <summary> + /// Gets or sets the currently selected file format + /// </summary> + public DocumentFormat SelectedFormat + { + get + { + return listFormats.SelectedItem as DocumentFormat; + } + set + { + listFormats.SelectedItem = value; + } + } + + /// <summary> + /// Gets or sets the path + /// </summary> + public string SelectedPath + { + get + { + return textPath.Text; + } + set + { + textPath.Text = value; + } + } + + /// <summary> + /// Creates a new instance of CreateDocumentDialog + /// </summary> + public CreateDocumentDialog() + { + InitializeComponent(); + + PopulateFormats(); + Validate(); + } + + private void PopulateFormats() + { + listFormats.ItemsSource = DocumentManager.Instance.DocumentFormats; + CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(listFormats.ItemsSource); + view.GroupDescriptions.Add(new PropertyGroupDescription("Category")); + } + + private void buttonCreate_Click(object sender, RoutedEventArgs e) + { + DialogResult = true; + Close(); + } + + private void buttonCancel_Click(object sender, RoutedEventArgs e) + { + DialogResult = false; + Close(); + } + + private void Validate() + { + bool res = true; + res &= !String.IsNullOrWhiteSpace(textPath.Text); + res &= (listFormats.SelectedItem != null); + + buttonCreate.IsEnabled = res; + } + } +} diff --git a/RainmeterEditor/UI/MainWindow.xaml b/RainmeterEditor/UI/MainWindow.xaml index e5601ce8..34e353d1 100644 --- a/RainmeterEditor/UI/MainWindow.xaml +++ b/RainmeterEditor/UI/MainWindow.xaml @@ -1,116 +1,116 @@ -<Window x:Class="RainmeterEditor.UI.MainWindow" - xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:ui="clr-namespace:RainmeterEditor.UI" - xmlns:ad="clr-namespace:Xceed.Wpf.AvalonDock;assembly=Xceed.Wpf.AvalonDock" - xmlns:adlayout="clr-namespace:Xceed.Wpf.AvalonDock.Layout;assembly=Xceed.Wpf.AvalonDock" - Title="Rainmeter Studio" Height="350" Width="525" - ResizeMode="CanResizeWithGrip" > - - <Window.Resources> - - </Window.Resources> - - <Grid> - <Grid.RowDefinitions> - <RowDefinition Height="Auto" /> - <!-- Menu bar --> - <RowDefinition Height="Auto" /> - <!-- Toolbar --> - <RowDefinition /> - <!-- Dock area --> - <RowDefinition Height="Auto" /> - <!-- Status bar --> - </Grid.RowDefinitions> - - <!-- Menu bar --> - <Menu Grid.Row="0" Grid.ColumnSpan="10"> - <MenuItem Header="_File"> - <MenuItem Header="_New"> - <MenuItem DataContext="{Binding DocumentCreateCommand}" - Command="{Binding}" Header="{Binding DisplayText}" ToolTip="{Binding Tooltip}" - InputGestureText="{Binding ShortcutText}"> - <MenuItem.Icon> - <Image Source="{Binding Icon}" /> - </MenuItem.Icon> - </MenuItem> - <MenuItem Header="_Project..." Command="{Binding DocumentCreateCommand}"> - <MenuItem.Icon> - <Image Source="/Resources/Icons/project_star_16.png" /> - </MenuItem.Icon> - </MenuItem> - </MenuItem> - <MenuItem Header="_Open..." /> - <Separator /> - <MenuItem Header="_Close" /> - <MenuItem Header="E_xit" /> - </MenuItem> - <MenuItem Header="_Edit" /> - <MenuItem Header="_Help" /> - </Menu> - - <!-- Toolbar --> - <ToolBarTray Grid.Row="1"> - <ToolBar> - <Button Name="buttonBackward" ToolTip="Navigate backward"> - <Image Width="16" Height="16" Source="/Resources/Icons/arrow_backward_16.png" /> - </Button> - <Button Name="buttonForward" ToolTip="Navigate forward"> - <Image Width="16" Height="16" Source="/Resources/Icons/arrow_forward_16.png" /> - </Button> - <Separator /> - <Button DataContext="{Binding DocumentCreateCommand}" - Command="{Binding}" ToolTip="{Binding Tooltip}"> - <Image Source="{Binding Icon}" /> - </Button> - </ToolBar> - </ToolBarTray> - - <!-- Grid splitter --> - <GridSplitter Grid.Row="2" Grid.Column="1" - HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> - - <!-- Document panel --> - <ad:DockingManager - x:Name="dockingManager" - Grid.Row="2"> - <adlayout:LayoutRoot> - - <adlayout:LayoutRoot.LeftSide> - <adlayout:LayoutAnchorSide> - <adlayout:LayoutAnchorGroup> - <adlayout:LayoutAnchorable Title="Toolbox" /> - </adlayout:LayoutAnchorGroup> - </adlayout:LayoutAnchorSide> - </adlayout:LayoutRoot.LeftSide> - - <adlayout:LayoutPanel Orientation="Horizontal"> - <adlayout:LayoutDocumentPane x:Name="documentPane" /> - - <adlayout:LayoutAnchorablePaneGroup DockWidth="150" Orientation="Vertical"> - <adlayout:LayoutAnchorablePane> - <adlayout:LayoutAnchorable Title="Skins"> - <ui:SkinsPanel /> - </adlayout:LayoutAnchorable> - <adlayout:LayoutAnchorable Title="Outline" /> - </adlayout:LayoutAnchorablePane> - <adlayout:LayoutAnchorablePane> - <adlayout:LayoutAnchorable Title="Properties" /> - </adlayout:LayoutAnchorablePane> - </adlayout:LayoutAnchorablePaneGroup> - </adlayout:LayoutPanel> - </adlayout:LayoutRoot> - </ad:DockingManager> - - <!-- Status bar --> - <StatusBar Grid.Row="3" Grid.ColumnSpan="10"> - - <ProgressBar Name="statusProgress" - Width="64" Height="8" - IsIndeterminate="True" - Visibility="Collapsed" /> - - <TextBlock Name="statusMessage">Ready</TextBlock> - </StatusBar> - </Grid> -</Window> +<Window x:Class="RainmeterEditor.UI.MainWindow" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:ui="clr-namespace:RainmeterEditor.UI" + xmlns:ad="clr-namespace:Xceed.Wpf.AvalonDock;assembly=Xceed.Wpf.AvalonDock" + xmlns:adlayout="clr-namespace:Xceed.Wpf.AvalonDock.Layout;assembly=Xceed.Wpf.AvalonDock" + Title="Rainmeter Studio" Height="350" Width="525" + ResizeMode="CanResizeWithGrip" > + + <Window.Resources> + + </Window.Resources> + + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <!-- Menu bar --> + <RowDefinition Height="Auto" /> + <!-- Toolbar --> + <RowDefinition /> + <!-- Dock area --> + <RowDefinition Height="Auto" /> + <!-- Status bar --> + </Grid.RowDefinitions> + + <!-- Menu bar --> + <Menu Grid.Row="0" Grid.ColumnSpan="10"> + <MenuItem Header="_File"> + <MenuItem Header="_New"> + <MenuItem DataContext="{Binding DocumentCreateCommand}" + Command="{Binding}" Header="{Binding DisplayText}" ToolTip="{Binding Tooltip}" + InputGestureText="{Binding ShortcutText}"> + <MenuItem.Icon> + <Image Source="{Binding Icon}" /> + </MenuItem.Icon> + </MenuItem> + <MenuItem Header="_Project..." Command="{Binding DocumentCreateCommand}"> + <MenuItem.Icon> + <Image Source="/Resources/Icons/project_star_16.png" /> + </MenuItem.Icon> + </MenuItem> + </MenuItem> + <MenuItem Header="_Open..." /> + <Separator /> + <MenuItem Header="_Close" /> + <MenuItem Header="E_xit" /> + </MenuItem> + <MenuItem Header="_Edit" /> + <MenuItem Header="_Help" /> + </Menu> + + <!-- Toolbar --> + <ToolBarTray Grid.Row="1"> + <ToolBar> + <Button Name="buttonBackward" ToolTip="Navigate backward"> + <Image Width="16" Height="16" Source="/Resources/Icons/arrow_backward_16.png" /> + </Button> + <Button Name="buttonForward" ToolTip="Navigate forward"> + <Image Width="16" Height="16" Source="/Resources/Icons/arrow_forward_16.png" /> + </Button> + <Separator /> + <Button DataContext="{Binding DocumentCreateCommand}" + Command="{Binding}" ToolTip="{Binding Tooltip}"> + <Image Source="{Binding Icon}" /> + </Button> + </ToolBar> + </ToolBarTray> + + <!-- Grid splitter --> + <GridSplitter Grid.Row="2" Grid.Column="1" + HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> + + <!-- Document panel --> + <ad:DockingManager + x:Name="dockingManager" + Grid.Row="2"> + <adlayout:LayoutRoot> + + <adlayout:LayoutRoot.LeftSide> + <adlayout:LayoutAnchorSide> + <adlayout:LayoutAnchorGroup> + <adlayout:LayoutAnchorable Title="Toolbox" /> + </adlayout:LayoutAnchorGroup> + </adlayout:LayoutAnchorSide> + </adlayout:LayoutRoot.LeftSide> + + <adlayout:LayoutPanel Orientation="Horizontal"> + <adlayout:LayoutDocumentPane x:Name="documentPane" /> + + <adlayout:LayoutAnchorablePaneGroup DockWidth="150" Orientation="Vertical"> + <adlayout:LayoutAnchorablePane> + <adlayout:LayoutAnchorable Title="Skins"> + <ui:SkinsPanel /> + </adlayout:LayoutAnchorable> + <adlayout:LayoutAnchorable Title="Outline" /> + </adlayout:LayoutAnchorablePane> + <adlayout:LayoutAnchorablePane> + <adlayout:LayoutAnchorable Title="Properties" /> + </adlayout:LayoutAnchorablePane> + </adlayout:LayoutAnchorablePaneGroup> + </adlayout:LayoutPanel> + </adlayout:LayoutRoot> + </ad:DockingManager> + + <!-- Status bar --> + <StatusBar Grid.Row="3" Grid.ColumnSpan="10"> + + <ProgressBar Name="statusProgress" + Width="64" Height="8" + IsIndeterminate="True" + Visibility="Collapsed" /> + + <TextBlock Name="statusMessage">Ready</TextBlock> + </StatusBar> + </Grid> +</Window> diff --git a/RainmeterEditor/UI/MainWindow.xaml.cs b/RainmeterEditor/UI/MainWindow.xaml.cs index 67c34f81..e378257e 100644 --- a/RainmeterEditor/UI/MainWindow.xaml.cs +++ b/RainmeterEditor/UI/MainWindow.xaml.cs @@ -1,75 +1,75 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using RainmeterEditor.Model.Events; -using RainmeterEditor.UI.Controller; -using Xceed.Wpf.AvalonDock.Layout; - -namespace RainmeterEditor.UI -{ - /// <summary> - /// Interaction logic for MainWindow.xaml - /// </summary> - public partial class MainWindow : Window - { - private DocumentController documentController; - - public Command DocumentCreateCommand { get { return documentController.DocumentCreateCommand; } } - - public MainWindow() - { - InitializeComponent(); - - this.DataContext = this; - - documentController = new DocumentController(); - documentController.OwnerWindow = this; - documentController.DocumentOpened += documentController_DocumentOpened; - AddKeyBinding(documentController.DocumentCreateCommand); - } - - private void AddKeyBinding(Command c) - { - if (c.Shortcut != null) - InputBindings.Add(new KeyBinding(c, c.Shortcut)); - } - - void documentController_DocumentOpened(object sender, DocumentOpenedEventArgs e) - { - // Spawn a new window - LayoutDocument document = new LayoutDocument(); - document.Content = e.Editor.EditorUI; - document.Title = e.Editor.Title; - document.Closing += document_Closing; - - documentPane.Children.Add(document); - documentPane.SelectedContentIndex = documentPane.IndexOf(document); - } - - void document_Closing(object sender, System.ComponentModel.CancelEventArgs e) - { - switch (MessageBox.Show("Are you sure?", "", MessageBoxButton.YesNoCancel, MessageBoxImage.Question)) - { - case MessageBoxResult.Yes: - break; - - case MessageBoxResult.No: - break; - - default: - e.Cancel = true; - return; - } - } - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using RainmeterEditor.Model.Events; +using RainmeterEditor.UI.Controller; +using Xceed.Wpf.AvalonDock.Layout; + +namespace RainmeterEditor.UI +{ + /// <summary> + /// Interaction logic for MainWindow.xaml + /// </summary> + public partial class MainWindow : Window + { + private DocumentController documentController; + + public Command DocumentCreateCommand { get { return documentController.DocumentCreateCommand; } } + + public MainWindow() + { + InitializeComponent(); + + this.DataContext = this; + + documentController = new DocumentController(); + documentController.OwnerWindow = this; + documentController.DocumentOpened += documentController_DocumentOpened; + AddKeyBinding(documentController.DocumentCreateCommand); + } + + private void AddKeyBinding(Command c) + { + if (c.Shortcut != null) + InputBindings.Add(new KeyBinding(c, c.Shortcut)); + } + + void documentController_DocumentOpened(object sender, DocumentOpenedEventArgs e) + { + // Spawn a new window + LayoutDocument document = new LayoutDocument(); + document.Content = e.Editor.EditorUI; + document.Title = e.Editor.Title; + document.Closing += document_Closing; + + documentPane.Children.Add(document); + documentPane.SelectedContentIndex = documentPane.IndexOf(document); + } + + void document_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + switch (MessageBox.Show("Are you sure?", "", MessageBoxButton.YesNoCancel, MessageBoxImage.Question)) + { + case MessageBoxResult.Yes: + break; + + case MessageBoxResult.No: + break; + + default: + e.Cancel = true; + return; + } + } + } } \ No newline at end of file diff --git a/RainmeterEditor/UI/SkinsPanel.xaml b/RainmeterEditor/UI/SkinsPanel.xaml index de379aab..5a5746f6 100644 --- a/RainmeterEditor/UI/SkinsPanel.xaml +++ b/RainmeterEditor/UI/SkinsPanel.xaml @@ -1,16 +1,16 @@ -<UserControl x:Class="RainmeterEditor.UI.SkinsPanel" - xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - mc:Ignorable="d" - d:DesignHeight="300" d:DesignWidth="300"> - <Grid> - <TreeView> - <TreeViewItem Header="Sample item"> - <TreeViewItem Header="Sample subitem" /> - </TreeViewItem> - <TreeViewItem Header="Sample item 2" /> - </TreeView> - </Grid> -</UserControl> +<UserControl x:Class="RainmeterEditor.UI.SkinsPanel" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + mc:Ignorable="d" + d:DesignHeight="300" d:DesignWidth="300"> + <Grid> + <TreeView> + <TreeViewItem Header="Sample item"> + <TreeViewItem Header="Sample subitem" /> + </TreeViewItem> + <TreeViewItem Header="Sample item 2" /> + </TreeView> + </Grid> +</UserControl> diff --git a/RainmeterEditor/UI/SkinsPanel.xaml.cs b/RainmeterEditor/UI/SkinsPanel.xaml.cs index 6cc848bd..6d8425ab 100644 --- a/RainmeterEditor/UI/SkinsPanel.xaml.cs +++ b/RainmeterEditor/UI/SkinsPanel.xaml.cs @@ -1,31 +1,31 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using RainmeterEditor.Interop; -using RainmeterEditor.Storage; - -namespace RainmeterEditor.UI -{ - /// <summary> - /// Interaction logic for SkinsPanel.xaml - /// </summary> - public partial class SkinsPanel : UserControl - { - public SkinsPanel() - { - InitializeComponent(); - - //var x = Rainmeter.Instance.Handle; - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using RainmeterEditor.Interop; +using RainmeterEditor.Storage; + +namespace RainmeterEditor.UI +{ + /// <summary> + /// Interaction logic for SkinsPanel.xaml + /// </summary> + public partial class SkinsPanel : UserControl + { + public SkinsPanel() + { + InitializeComponent(); + + //var x = Rainmeter.Instance.Handle; + } + } +} diff --git a/RainmeterEditor/UI/Styles/ButtonStyle.xaml b/RainmeterEditor/UI/Styles/ButtonStyle.xaml index 72b3c419..53f3fd5a 100644 --- a/RainmeterEditor/UI/Styles/ButtonStyle.xaml +++ b/RainmeterEditor/UI/Styles/ButtonStyle.xaml @@ -1,55 +1,55 @@ -<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - <Style TargetType="Button"> - <Setter Property="Margin" Value="1" /> - <Setter Property="Padding" Value="6,1,6,1" /> - <Setter Property="SnapsToDevicePixels" Value="True" /> - <Setter Property="Template"> - <Setter.Value> - <ControlTemplate TargetType="Button"> - <Border Name="_border" - BorderBrush="Gray" - BorderThickness="1" - CornerRadius="2" - Padding="{TemplateBinding Padding}"> - <Border.Background> - <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> - <GradientStop Color="#eeee" Offset="0" /> - <GradientStop Color="#cccc" Offset="1" /> - </LinearGradientBrush> - </Border.Background> - <ContentPresenter Name="_content" /> - </Border> - <ControlTemplate.Triggers> - <Trigger Property="IsMouseOver" Value="True"> - <Setter TargetName="_border" Property="Background" > - <Setter.Value> - <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> - <GradientStop Color="#eeee" Offset="0" /> - <GradientStop Color="#dddd" Offset="1" /> - </LinearGradientBrush> - </Setter.Value> - </Setter> - </Trigger> - - <Trigger Property="IsPressed" Value="True"> - <Setter TargetName="_border" Property="Background" > - <Setter.Value> - <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> - <GradientStop Color="#dddd" Offset="0" /> - <GradientStop Color="#bbbb" Offset="1" /> - </LinearGradientBrush> - </Setter.Value> - </Setter> - </Trigger> - - <Trigger Property="IsEnabled" Value="False"> - <Setter TargetName="_content" Property="Opacity" Value=".5" /> - </Trigger> - - </ControlTemplate.Triggers> - </ControlTemplate> - </Setter.Value> - </Setter> - </Style> +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + <Style TargetType="Button"> + <Setter Property="Margin" Value="1" /> + <Setter Property="Padding" Value="6,1,6,1" /> + <Setter Property="SnapsToDevicePixels" Value="True" /> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="Button"> + <Border Name="_border" + BorderBrush="Gray" + BorderThickness="1" + CornerRadius="2" + Padding="{TemplateBinding Padding}"> + <Border.Background> + <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> + <GradientStop Color="#eeee" Offset="0" /> + <GradientStop Color="#cccc" Offset="1" /> + </LinearGradientBrush> + </Border.Background> + <ContentPresenter Name="_content" /> + </Border> + <ControlTemplate.Triggers> + <Trigger Property="IsMouseOver" Value="True"> + <Setter TargetName="_border" Property="Background" > + <Setter.Value> + <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> + <GradientStop Color="#eeee" Offset="0" /> + <GradientStop Color="#dddd" Offset="1" /> + </LinearGradientBrush> + </Setter.Value> + </Setter> + </Trigger> + + <Trigger Property="IsPressed" Value="True"> + <Setter TargetName="_border" Property="Background" > + <Setter.Value> + <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> + <GradientStop Color="#dddd" Offset="0" /> + <GradientStop Color="#bbbb" Offset="1" /> + </LinearGradientBrush> + </Setter.Value> + </Setter> + </Trigger> + + <Trigger Property="IsEnabled" Value="False"> + <Setter TargetName="_content" Property="Opacity" Value=".5" /> + </Trigger> + + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> </ResourceDictionary> \ No newline at end of file diff --git a/RainmeterEditor/UI/Styles/Common.xaml b/RainmeterEditor/UI/Styles/Common.xaml index bae659cf..57751a24 100644 --- a/RainmeterEditor/UI/Styles/Common.xaml +++ b/RainmeterEditor/UI/Styles/Common.xaml @@ -1,6 +1,6 @@ -<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - <ResourceDictionary.MergedDictionaries> - <ResourceDictionary Source="ButtonStyle.xaml" /> - </ResourceDictionary.MergedDictionaries> +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + <ResourceDictionary.MergedDictionaries> + <ResourceDictionary Source="ButtonStyle.xaml" /> + </ResourceDictionary.MergedDictionaries> </ResourceDictionary> \ No newline at end of file diff --git a/RainmeterEditor/app.config b/RainmeterEditor/app.config index 57c0f2cb..fcd0c937 100644 --- a/RainmeterEditor/app.config +++ b/RainmeterEditor/app.config @@ -1,3 +1,3 @@ -<?xml version="1.0" encoding="utf-8"?> -<configuration> -<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration> +<?xml version="1.0" encoding="utf-8"?> +<configuration> +<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration> diff --git a/RainmeterEditor/packages.config b/RainmeterEditor/packages.config index f523d41a..82c30905 100644 --- a/RainmeterEditor/packages.config +++ b/RainmeterEditor/packages.config @@ -1,5 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?> -<packages> - <package id="AvalonDock" version="2.0.2000" targetFramework="net40" /> - <package id="ini-parser" version="2.1.1" targetFramework="net40" /> +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="AvalonDock" version="2.0.2000" targetFramework="net40" /> + <package id="ini-parser" version="2.1.1" targetFramework="net40" /> </packages> \ No newline at end of file diff --git a/RainmeterStudio.Tests/Properties/AssemblyInfo.cs b/RainmeterStudio.Tests/Properties/AssemblyInfo.cs index 11e77916..bda5a38c 100644 --- a/RainmeterStudio.Tests/Properties/AssemblyInfo.cs +++ b/RainmeterStudio.Tests/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("RainmeterStudio.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("RainmeterStudio.Tests")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("e4fee45f-07d7-4ce8-96f7-b8dc29e62150")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("RainmeterStudio.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("RainmeterStudio.Tests")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("e4fee45f-07d7-4ce8-96f7-b8dc29e62150")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/RainmeterStudio.Tests/RainmeterStudio.Tests.csproj b/RainmeterStudio.Tests/RainmeterStudio.Tests.csproj index 8aafd4ca..f235ff84 100644 --- a/RainmeterStudio.Tests/RainmeterStudio.Tests.csproj +++ b/RainmeterStudio.Tests/RainmeterStudio.Tests.csproj @@ -1,96 +1,96 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <ProjectGuid>{845F4BD4-6822-4D92-9DDB-15FD18A47E5A}</ProjectGuid> - <OutputType>Library</OutputType> - <AppDesignerFolder>Properties</AppDesignerFolder> - <RootNamespace>RainmeterStudio.Tests</RootNamespace> - <AssemblyName>RainmeterStudio.Tests</AssemblyName> - <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> - <FileAlignment>512</FileAlignment> - <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> - <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> - <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> - <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath> - <IsCodedUITest>False</IsCodedUITest> - <TestProjectType>UnitTest</TestProjectType> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <DebugSymbols>true</DebugSymbols> - <DebugType>full</DebugType> - <Optimize>false</Optimize> - <OutputPath>bin\Debug\</OutputPath> - <DefineConstants>DEBUG;TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - <PlatformTarget>x86</PlatformTarget> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <DebugType>pdbonly</DebugType> - <Optimize>true</Optimize> - <OutputPath>bin\Release\</OutputPath> - <DefineConstants>TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <ItemGroup> - <Reference Include="System" /> - <Reference Include="System.Core"> - <RequiredTargetFramework>3.5</RequiredTargetFramework> - </Reference> - </ItemGroup> - <Choose> - <When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'"> - <ItemGroup> - <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /> - </ItemGroup> - </When> - <Otherwise> - <ItemGroup> - <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" /> - </ItemGroup> - </Otherwise> - </Choose> - <ItemGroup> - <Compile Include="Storage\ProjectStorageTest.cs" /> - <Compile Include="Properties\AssemblyInfo.cs" /> - </ItemGroup> - <ItemGroup> - <WCFMetadata Include="Service References\" /> - </ItemGroup> - <ItemGroup> - <ProjectReference Include="..\RainmeterEditor\RainmeterStudio.csproj"> - <Project>{438d0136-4a27-4e4d-a617-fface4554236}</Project> - <Name>RainmeterStudio</Name> - </ProjectReference> - </ItemGroup> - <Choose> - <When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'"> - <ItemGroup> - <Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <Private>False</Private> - </Reference> - <Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <Private>False</Private> - </Reference> - <Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <Private>False</Private> - </Reference> - <Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <Private>False</Private> - </Reference> - </ItemGroup> - </When> - </Choose> - <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" /> - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{845F4BD4-6822-4D92-9DDB-15FD18A47E5A}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>RainmeterStudio.Tests</RootNamespace> + <AssemblyName>RainmeterStudio.Tests</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> + <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> + <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath> + <IsCodedUITest>False</IsCodedUITest> + <TestProjectType>UnitTest</TestProjectType> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <PlatformTarget>x86</PlatformTarget> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + </ItemGroup> + <Choose> + <When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'"> + <ItemGroup> + <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /> + </ItemGroup> + </When> + <Otherwise> + <ItemGroup> + <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" /> + </ItemGroup> + </Otherwise> + </Choose> + <ItemGroup> + <Compile Include="Storage\ProjectStorageTest.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <WCFMetadata Include="Service References\" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\RainmeterEditor\RainmeterStudio.csproj"> + <Project>{438d0136-4a27-4e4d-a617-fface4554236}</Project> + <Name>RainmeterStudio</Name> + </ProjectReference> + </ItemGroup> + <Choose> + <When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'"> + <ItemGroup> + <Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + </ItemGroup> + </When> + </Choose> + <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" /> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> </Project> \ No newline at end of file diff --git a/RainmeterStudio.Tests/Storage/ProjectStorageTest.cs b/RainmeterStudio.Tests/Storage/ProjectStorageTest.cs index c96a6275..adac4e10 100644 --- a/RainmeterStudio.Tests/Storage/ProjectStorageTest.cs +++ b/RainmeterStudio.Tests/Storage/ProjectStorageTest.cs @@ -1,110 +1,110 @@ -using System; -using System.Text; -using System.Collections.Generic; -using System.Linq; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using RainmeterEditor.Storage; -using RainmeterEditor.Model; -using System.IO; - -namespace RainmeterStudio.Tests.Storage -{ - /// <summary> - /// Tests the ProjectStorage class - /// </summary> - [TestClass] - public class ProjectStorageTest - { - private ProjectStorage ProjectStorage = new ProjectStorage(); - - public TestContext TestContext { get; set; } - - [TestInitialize] - public void Initialize() - { - Directory.SetCurrentDirectory(TestContext.DeploymentDirectory); - } - - [TestMethod] - public void ProjectStorageSmokeTest() - { - string filename = TestContext.TestName + ".rsproj"; - - // Create project - Project project = CreateProject(); - - // Save and load - ProjectStorage.Save(filename, project); - Project res = ProjectStorage.Load(filename); - - // Verify results - Assert.IsNotNull(res); - Assert.AreEqual(project, res); - Assert.AreEqual(project.GetHashCode(), res.GetHashCode()); - Assert.AreEqual(project.Author, res.Author); - Assert.AreEqual(project.AutoLoadFile, res.AutoLoadFile); - Assert.AreEqual(project.MinimumRainmeter, res.MinimumRainmeter); - Assert.AreEqual(project.MinimumWindows, res.MinimumWindows); - Assert.AreEqual(project.Name, res.Name); - Assert.AreEqual(project.Root, res.Root); - Assert.IsTrue(project.VariableFiles.SequenceEqual(res.VariableFiles)); - Assert.AreEqual(project.Version, res.Version); - } - - [TestMethod] - public void ProjectStorageEmptyProjectSmokeTest() - { - string filename = TestContext.TestName + ".rsproj"; - - // Create a project - Project project = new Project(); - - // Save and load project - ProjectStorage.Save(filename, project); - Project res = ProjectStorage.Load(filename); - - // Test results - Assert.IsNotNull(res); - Assert.AreEqual(project, res); - Assert.AreEqual(project.GetHashCode(), res.GetHashCode()); - Assert.AreEqual(project.Author, res.Author); - Assert.AreEqual(project.AutoLoadFile, res.AutoLoadFile); - Assert.AreEqual(project.MinimumRainmeter, res.MinimumRainmeter); - Assert.AreEqual(project.MinimumWindows, res.MinimumWindows); - Assert.AreEqual(project.Name, res.Name); - Assert.AreEqual(project.Root, res.Root); - Assert.IsTrue(project.VariableFiles.SequenceEqual(res.VariableFiles)); - Assert.AreEqual(project.Version, res.Version); - } - - private Project CreateProject() - { - // Create some file references - Reference folder1 = new Reference("folder1"); - Reference folder2 = new Reference("folder2"); - Reference file1 = new Reference("file1.txt"); - Reference file2 = new Reference("file2.ini"); - Reference file3 = new Reference("file3.bmp"); - - // Create a project - Project project = new Project(); - project.Author = "Tiberiu Chibici"; - project.MinimumRainmeter = new Version("3.1"); - project.MinimumWindows = new Version("5.1"); - project.Name = "My project"; - project.Version = new Version("1.0.1"); - - project.AutoLoadFile = file2; - project.VariableFiles.Add(file1); - - // Set project references - project.Root.Add(folder1); - project.Root.Add(folder2); - project.Root[0].Add(file1); - project.Root[1].Add(file2); - project.Root.Add(file3); - - return project; - } - } -} +using System; +using System.Text; +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using RainmeterEditor.Storage; +using RainmeterEditor.Model; +using System.IO; + +namespace RainmeterStudio.Tests.Storage +{ + /// <summary> + /// Tests the ProjectStorage class + /// </summary> + [TestClass] + public class ProjectStorageTest + { + private ProjectStorage ProjectStorage = new ProjectStorage(); + + public TestContext TestContext { get; set; } + + [TestInitialize] + public void Initialize() + { + Directory.SetCurrentDirectory(TestContext.DeploymentDirectory); + } + + [TestMethod] + public void ProjectStorageSmokeTest() + { + string filename = TestContext.TestName + ".rsproj"; + + // Create project + Project project = CreateProject(); + + // Save and load + ProjectStorage.Save(filename, project); + Project res = ProjectStorage.Load(filename); + + // Verify results + Assert.IsNotNull(res); + Assert.AreEqual(project, res); + Assert.AreEqual(project.GetHashCode(), res.GetHashCode()); + Assert.AreEqual(project.Author, res.Author); + Assert.AreEqual(project.AutoLoadFile, res.AutoLoadFile); + Assert.AreEqual(project.MinimumRainmeter, res.MinimumRainmeter); + Assert.AreEqual(project.MinimumWindows, res.MinimumWindows); + Assert.AreEqual(project.Name, res.Name); + Assert.AreEqual(project.Root, res.Root); + Assert.IsTrue(project.VariableFiles.SequenceEqual(res.VariableFiles)); + Assert.AreEqual(project.Version, res.Version); + } + + [TestMethod] + public void ProjectStorageEmptyProjectSmokeTest() + { + string filename = TestContext.TestName + ".rsproj"; + + // Create a project + Project project = new Project(); + + // Save and load project + ProjectStorage.Save(filename, project); + Project res = ProjectStorage.Load(filename); + + // Test results + Assert.IsNotNull(res); + Assert.AreEqual(project, res); + Assert.AreEqual(project.GetHashCode(), res.GetHashCode()); + Assert.AreEqual(project.Author, res.Author); + Assert.AreEqual(project.AutoLoadFile, res.AutoLoadFile); + Assert.AreEqual(project.MinimumRainmeter, res.MinimumRainmeter); + Assert.AreEqual(project.MinimumWindows, res.MinimumWindows); + Assert.AreEqual(project.Name, res.Name); + Assert.AreEqual(project.Root, res.Root); + Assert.IsTrue(project.VariableFiles.SequenceEqual(res.VariableFiles)); + Assert.AreEqual(project.Version, res.Version); + } + + private Project CreateProject() + { + // Create some file references + Reference folder1 = new Reference("folder1"); + Reference folder2 = new Reference("folder2"); + Reference file1 = new Reference("file1.txt"); + Reference file2 = new Reference("file2.ini"); + Reference file3 = new Reference("file3.bmp"); + + // Create a project + Project project = new Project(); + project.Author = "Tiberiu Chibici"; + project.MinimumRainmeter = new Version("3.1"); + project.MinimumWindows = new Version("5.1"); + project.Name = "My project"; + project.Version = new Version("1.0.1"); + + project.AutoLoadFile = file2; + project.VariableFiles.Add(file1); + + // Set project references + project.Root.Add(folder1); + project.Root.Add(folder2); + project.Root[0].Add(file1); + project.Root[1].Add(file2); + project.Root.Add(file3); + + return project; + } + } +} diff --git a/RainmeterStudio.sln b/RainmeterStudio.sln index e81ebaa0..ffea0851 100644 --- a/RainmeterStudio.sln +++ b/RainmeterStudio.sln @@ -1,535 +1,535 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.30110.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "Common\Common.vcxproj", "{19312085-AA51-4BD6-BE92-4B6098CCA539}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Installer", "Installer\Installer.vcxproj", "{2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Language", "Language\Language.vcxproj", "{6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Library", "Library\Library.vcxproj", "{BE9D2400-7F1C-49D6-8498-5CE495491AD6}" - ProjectSection(ProjectDependencies) = postProject - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A} = {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A} - {19312085-AA51-4BD6-BE92-4B6098CCA539} = {19312085-AA51-4BD6-BE92-4B6098CCA539} - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6} = {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6} - {6D61FBE9-6913-4885-A95D-1A8C0C223D82} = {6D61FBE9-6913-4885-A95D-1A8C0C223D82} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Library_Lua", "Library\Library_Lua.vcxproj", "{BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Library_PCRE", "Library\Library_PCRE.vcxproj", "{6D61FBE9-6913-4885-A95D-1A8C0C223D82}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SkinInstaller", "SkinInstaller\SkinInstaller.vcxproj", "{6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SkinInstallerLauncher", "SkinInstaller\SkinInstallerLauncher.vcxproj", "{2D8F1DDB-6470-45A1-B95A-3E2960641314}" - ProjectSection(ProjectDependencies) = postProject - {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA} = {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginAdvancedCPU", "Plugins\PluginAdvancedCPU\PluginAdvancedCPU.vcxproj", "{EE8EC522-8430-4B46-86A3-D943D77F9E4B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginCoreTemp", "Plugins\PluginCoreTemp\PluginCoreTemp.vcxproj", "{F32FA418-8DF4-4E94-B92B-EBD502F5DC07}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginFileView", "Plugins\PluginFileView\PluginFileView.vcxproj", "{64FDEE97-6B7E-40E5-A489-ECA322825BC8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginFolderInfo", "Plugins\PluginFolderInfo\PluginFolderInfo.vcxproj", "{A221819D-4263-42AA-B22A-C022924842A7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginInputText", "Plugins\PluginInputText\PluginInputText.csproj", "{2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginiTunes", "Plugins\PluginiTunes\PluginiTunes.vcxproj", "{A2DD3CBE-B140-4892-A875-24107FA52518}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginMediaKey", "Plugins\PluginMediaKey\PluginMediaKey.vcxproj", "{EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginNowPlaying", "Plugins\PluginNowPlaying\PluginNowPlaying.vcxproj", "{C7FECFCD-E6C6-4F95-BB9A-E1762B043969}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginPerfMon", "Plugins\PluginPerfMon\PluginPerfMon.vcxproj", "{5344B52B-BAC3-479C-B41D-D465B8BDA1AD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginPing", "Plugins\PluginPing\PluginPing.vcxproj", "{C862B662-5CC6-4E79-B1B3-905E0B98D627}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginPower", "Plugins\PluginPower\PluginPower.vcxproj", "{C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginProcess", "Plugins\PluginProcess\PluginProcess.vcxproj", "{05203741-CD80-4060-8218-EC5D1120FE3E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginQuote", "Plugins\PluginQuote\PluginQuote.vcxproj", "{C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginRecycleManager", "Plugins\PluginRecycleManager\PluginRecycleManager.vcxproj", "{4F8C4C09-431C-45C4-830B-32006E783C3A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginResMon", "Plugins\PluginResMon\PluginResMon.vcxproj", "{17D3BD92-6F5D-438C-A89B-88F4CE06DB94}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginSpeedFan", "Plugins\PluginSpeedFan\PluginSpeedFan.vcxproj", "{D10AB316-0F7A-4551-BE4F-385E04CCF1E8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginSysInfo", "Plugins\PluginSysInfo\PluginSysInfo.vcxproj", "{6EBCA4DA-8CC7-42FE-8F45-878ABE165078}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginVirtualDesktops", "Plugins\PluginVirtualDesktops\PluginVirtualDesktops.vcxproj", "{4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginWebParser", "Plugins\PluginWebParser\PluginWebParser.vcxproj", "{8B820B9F-C154-417C-A090-42198F2AF496}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginWifiStatus", "Plugins\PluginWifiStatus\PluginWifiStatus.vcxproj", "{45A34285-56DD-4521-912B-3F884D36FA35}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginWin7Audio", "Plugins\PluginWin7Audio\PluginWin7Audio.vcxproj", "{6D032D6B-7656-4743-B454-3388E2921EB0}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginWindowMessage", "Plugins\PluginWindowMessage\PluginWindowMessage.vcxproj", "{B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RainmeterStudio", "RainmeterEditor\RainmeterStudio.csproj", "{438D0136-4A27-4E4D-A617-FFACE4554236}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RainmeterStudio.Tests", "RainmeterStudio.Tests\RainmeterStudio.Tests.csproj", "{845F4BD4-6822-4D92-9DDB-15FD18A47E5A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {19312085-AA51-4BD6-BE92-4B6098CCA539}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {19312085-AA51-4BD6-BE92-4B6098CCA539}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {19312085-AA51-4BD6-BE92-4B6098CCA539}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {19312085-AA51-4BD6-BE92-4B6098CCA539}.Debug|Win32.ActiveCfg = Debug|Win32 - {19312085-AA51-4BD6-BE92-4B6098CCA539}.Debug|Win32.Build.0 = Debug|Win32 - {19312085-AA51-4BD6-BE92-4B6098CCA539}.Debug|x64.ActiveCfg = Debug|x64 - {19312085-AA51-4BD6-BE92-4B6098CCA539}.Debug|x64.Build.0 = Debug|x64 - {19312085-AA51-4BD6-BE92-4B6098CCA539}.Release|Any CPU.ActiveCfg = Release|Win32 - {19312085-AA51-4BD6-BE92-4B6098CCA539}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {19312085-AA51-4BD6-BE92-4B6098CCA539}.Release|Mixed Platforms.Build.0 = Release|Win32 - {19312085-AA51-4BD6-BE92-4B6098CCA539}.Release|Win32.ActiveCfg = Release|Win32 - {19312085-AA51-4BD6-BE92-4B6098CCA539}.Release|Win32.Build.0 = Release|Win32 - {19312085-AA51-4BD6-BE92-4B6098CCA539}.Release|x64.ActiveCfg = Release|x64 - {19312085-AA51-4BD6-BE92-4B6098CCA539}.Release|x64.Build.0 = Release|x64 - {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Debug|Win32.ActiveCfg = Debug|Win32 - {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Debug|x64.ActiveCfg = Debug|Win32 - {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Release|Any CPU.ActiveCfg = Release|Win32 - {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Release|Mixed Platforms.Build.0 = Release|Win32 - {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Release|Win32.ActiveCfg = Release|Win32 - {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Release|x64.ActiveCfg = Release|Win32 - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Debug|Win32.ActiveCfg = Debug|Win32 - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Debug|Win32.Build.0 = Debug|Win32 - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Debug|x64.ActiveCfg = Debug|x64 - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Debug|x64.Build.0 = Debug|x64 - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Release|Any CPU.ActiveCfg = Release|Win32 - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Release|Mixed Platforms.Build.0 = Release|Win32 - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Release|Win32.ActiveCfg = Release|Win32 - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Release|Win32.Build.0 = Release|Win32 - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Release|x64.ActiveCfg = Release|x64 - {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Release|x64.Build.0 = Release|x64 - {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Debug|Win32.ActiveCfg = Debug|Win32 - {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Debug|Win32.Build.0 = Debug|Win32 - {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Debug|x64.ActiveCfg = Debug|x64 - {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Debug|x64.Build.0 = Debug|x64 - {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Release|Any CPU.ActiveCfg = Release|Win32 - {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Release|Mixed Platforms.Build.0 = Release|Win32 - {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Release|Win32.ActiveCfg = Release|Win32 - {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Release|Win32.Build.0 = Release|Win32 - {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Release|x64.ActiveCfg = Release|x64 - {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Release|x64.Build.0 = Release|x64 - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Debug|Win32.ActiveCfg = Debug|Win32 - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Debug|Win32.Build.0 = Debug|Win32 - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Debug|x64.ActiveCfg = Debug|x64 - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Debug|x64.Build.0 = Debug|x64 - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Release|Any CPU.ActiveCfg = Release|Win32 - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Release|Mixed Platforms.Build.0 = Release|Win32 - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Release|Win32.ActiveCfg = Release|Win32 - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Release|Win32.Build.0 = Release|Win32 - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Release|x64.ActiveCfg = Release|x64 - {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Release|x64.Build.0 = Release|x64 - {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Debug|Win32.ActiveCfg = Debug|Win32 - {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Debug|Win32.Build.0 = Debug|Win32 - {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Debug|x64.ActiveCfg = Debug|x64 - {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Debug|x64.Build.0 = Debug|x64 - {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Release|Any CPU.ActiveCfg = Release|Win32 - {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Release|Mixed Platforms.Build.0 = Release|Win32 - {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Release|Win32.ActiveCfg = Release|Win32 - {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Release|Win32.Build.0 = Release|Win32 - {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Release|x64.ActiveCfg = Release|x64 - {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Release|x64.Build.0 = Release|x64 - {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Debug|Win32.ActiveCfg = Debug|Win32 - {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Debug|Win32.Build.0 = Debug|Win32 - {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Debug|x64.ActiveCfg = Debug|x64 - {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Debug|x64.Build.0 = Debug|x64 - {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Release|Any CPU.ActiveCfg = Release|Win32 - {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Release|Mixed Platforms.Build.0 = Release|Win32 - {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Release|Win32.ActiveCfg = Release|Win32 - {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Release|Win32.Build.0 = Release|Win32 - {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Release|x64.ActiveCfg = Release|x64 - {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Release|x64.Build.0 = Release|x64 - {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Debug|Win32.ActiveCfg = Debug|Win32 - {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Debug|Win32.Build.0 = Debug|Win32 - {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Debug|x64.ActiveCfg = Debug|x64 - {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Debug|x64.Build.0 = Debug|x64 - {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Release|Any CPU.ActiveCfg = Release|Win32 - {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Release|Mixed Platforms.Build.0 = Release|Win32 - {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Release|Win32.ActiveCfg = Release|Win32 - {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Release|Win32.Build.0 = Release|Win32 - {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Release|x64.ActiveCfg = Release|x64 - {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Release|x64.Build.0 = Release|x64 - {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Debug|Win32.ActiveCfg = Debug|Win32 - {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Debug|Win32.Build.0 = Debug|Win32 - {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Debug|x64.ActiveCfg = Debug|x64 - {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Debug|x64.Build.0 = Debug|x64 - {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Release|Any CPU.ActiveCfg = Release|Win32 - {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Release|Mixed Platforms.Build.0 = Release|Win32 - {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Release|Win32.ActiveCfg = Release|Win32 - {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Release|Win32.Build.0 = Release|Win32 - {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Release|x64.ActiveCfg = Release|x64 - {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Release|x64.Build.0 = Release|x64 - {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Debug|Win32.ActiveCfg = Debug|Win32 - {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Debug|Win32.Build.0 = Debug|Win32 - {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Debug|x64.ActiveCfg = Debug|x64 - {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Debug|x64.Build.0 = Debug|x64 - {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|Any CPU.ActiveCfg = Release|Win32 - {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|Mixed Platforms.Build.0 = Release|Win32 - {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|Win32.ActiveCfg = Release|Win32 - {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|Win32.Build.0 = Release|Win32 - {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|x64.ActiveCfg = Release|x64 - {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|x64.Build.0 = Release|x64 - {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Debug|Win32.ActiveCfg = Debug|Win32 - {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Debug|Win32.Build.0 = Debug|Win32 - {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Debug|x64.ActiveCfg = Debug|x64 - {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Debug|x64.Build.0 = Debug|x64 - {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Release|Any CPU.ActiveCfg = Release|Win32 - {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Release|Mixed Platforms.Build.0 = Release|Win32 - {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Release|Win32.ActiveCfg = Release|Win32 - {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Release|Win32.Build.0 = Release|Win32 - {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Release|x64.ActiveCfg = Release|x64 - {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Release|x64.Build.0 = Release|x64 - {A221819D-4263-42AA-B22A-C022924842A7}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {A221819D-4263-42AA-B22A-C022924842A7}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {A221819D-4263-42AA-B22A-C022924842A7}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {A221819D-4263-42AA-B22A-C022924842A7}.Debug|Win32.ActiveCfg = Debug|Win32 - {A221819D-4263-42AA-B22A-C022924842A7}.Debug|Win32.Build.0 = Debug|Win32 - {A221819D-4263-42AA-B22A-C022924842A7}.Debug|x64.ActiveCfg = Debug|x64 - {A221819D-4263-42AA-B22A-C022924842A7}.Debug|x64.Build.0 = Debug|x64 - {A221819D-4263-42AA-B22A-C022924842A7}.Release|Any CPU.ActiveCfg = Release|Win32 - {A221819D-4263-42AA-B22A-C022924842A7}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {A221819D-4263-42AA-B22A-C022924842A7}.Release|Mixed Platforms.Build.0 = Release|Win32 - {A221819D-4263-42AA-B22A-C022924842A7}.Release|Win32.ActiveCfg = Release|Win32 - {A221819D-4263-42AA-B22A-C022924842A7}.Release|Win32.Build.0 = Release|Win32 - {A221819D-4263-42AA-B22A-C022924842A7}.Release|x64.ActiveCfg = Release|x64 - {A221819D-4263-42AA-B22A-C022924842A7}.Release|x64.Build.0 = Release|x64 - {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Debug|Any CPU.ActiveCfg = Debug|x86 - {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Debug|Win32.ActiveCfg = Debug|x86 - {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Debug|Win32.Build.0 = Debug|x86 - {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Debug|x64.ActiveCfg = Debug|x64 - {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Debug|x64.Build.0 = Debug|x64 - {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Release|Any CPU.ActiveCfg = Release|x86 - {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Release|Mixed Platforms.Build.0 = Release|x86 - {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Release|Win32.ActiveCfg = Release|x86 - {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Release|Win32.Build.0 = Release|x86 - {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Release|x64.ActiveCfg = Release|x64 - {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Release|x64.Build.0 = Release|x64 - {A2DD3CBE-B140-4892-A875-24107FA52518}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {A2DD3CBE-B140-4892-A875-24107FA52518}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {A2DD3CBE-B140-4892-A875-24107FA52518}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {A2DD3CBE-B140-4892-A875-24107FA52518}.Debug|Win32.ActiveCfg = Debug|Win32 - {A2DD3CBE-B140-4892-A875-24107FA52518}.Debug|Win32.Build.0 = Debug|Win32 - {A2DD3CBE-B140-4892-A875-24107FA52518}.Debug|x64.ActiveCfg = Debug|x64 - {A2DD3CBE-B140-4892-A875-24107FA52518}.Debug|x64.Build.0 = Debug|x64 - {A2DD3CBE-B140-4892-A875-24107FA52518}.Release|Any CPU.ActiveCfg = Release|Win32 - {A2DD3CBE-B140-4892-A875-24107FA52518}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {A2DD3CBE-B140-4892-A875-24107FA52518}.Release|Mixed Platforms.Build.0 = Release|Win32 - {A2DD3CBE-B140-4892-A875-24107FA52518}.Release|Win32.ActiveCfg = Release|Win32 - {A2DD3CBE-B140-4892-A875-24107FA52518}.Release|Win32.Build.0 = Release|Win32 - {A2DD3CBE-B140-4892-A875-24107FA52518}.Release|x64.ActiveCfg = Release|x64 - {A2DD3CBE-B140-4892-A875-24107FA52518}.Release|x64.Build.0 = Release|x64 - {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Debug|Win32.ActiveCfg = Debug|Win32 - {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Debug|Win32.Build.0 = Debug|Win32 - {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Debug|x64.ActiveCfg = Debug|x64 - {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Debug|x64.Build.0 = Debug|x64 - {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release|Any CPU.ActiveCfg = Release|Win32 - {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release|Mixed Platforms.Build.0 = Release|Win32 - {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release|Win32.ActiveCfg = Release|Win32 - {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release|Win32.Build.0 = Release|Win32 - {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release|x64.ActiveCfg = Release|x64 - {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release|x64.Build.0 = Release|x64 - {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|Win32.ActiveCfg = Debug|Win32 - {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|Win32.Build.0 = Debug|Win32 - {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|x64.ActiveCfg = Debug|x64 - {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|x64.Build.0 = Debug|x64 - {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|Any CPU.ActiveCfg = Release|Win32 - {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|Mixed Platforms.Build.0 = Release|Win32 - {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|Win32.ActiveCfg = Release|Win32 - {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|Win32.Build.0 = Release|Win32 - {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|x64.ActiveCfg = Release|x64 - {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|x64.Build.0 = Release|x64 - {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|Win32.ActiveCfg = Debug|Win32 - {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|Win32.Build.0 = Debug|Win32 - {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|x64.ActiveCfg = Debug|x64 - {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|x64.Build.0 = Debug|x64 - {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Release|Any CPU.ActiveCfg = Release|Win32 - {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Release|Mixed Platforms.Build.0 = Release|Win32 - {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Release|Win32.ActiveCfg = Release|Win32 - {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Release|Win32.Build.0 = Release|Win32 - {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Release|x64.ActiveCfg = Release|x64 - {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Release|x64.Build.0 = Release|x64 - {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Debug|Win32.ActiveCfg = Debug|Win32 - {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Debug|Win32.Build.0 = Debug|Win32 - {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Debug|x64.ActiveCfg = Debug|x64 - {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Debug|x64.Build.0 = Debug|x64 - {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Release|Any CPU.ActiveCfg = Release|Win32 - {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Release|Mixed Platforms.Build.0 = Release|Win32 - {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Release|Win32.ActiveCfg = Release|Win32 - {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Release|Win32.Build.0 = Release|Win32 - {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Release|x64.ActiveCfg = Release|x64 - {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Release|x64.Build.0 = Release|x64 - {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Debug|Win32.ActiveCfg = Debug|Win32 - {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Debug|Win32.Build.0 = Debug|Win32 - {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Debug|x64.ActiveCfg = Debug|x64 - {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Debug|x64.Build.0 = Debug|x64 - {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Release|Any CPU.ActiveCfg = Release|Win32 - {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Release|Mixed Platforms.Build.0 = Release|Win32 - {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Release|Win32.ActiveCfg = Release|Win32 - {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Release|Win32.Build.0 = Release|Win32 - {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Release|x64.ActiveCfg = Release|x64 - {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Release|x64.Build.0 = Release|x64 - {05203741-CD80-4060-8218-EC5D1120FE3E}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {05203741-CD80-4060-8218-EC5D1120FE3E}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {05203741-CD80-4060-8218-EC5D1120FE3E}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {05203741-CD80-4060-8218-EC5D1120FE3E}.Debug|Win32.ActiveCfg = Debug|Win32 - {05203741-CD80-4060-8218-EC5D1120FE3E}.Debug|Win32.Build.0 = Debug|Win32 - {05203741-CD80-4060-8218-EC5D1120FE3E}.Debug|x64.ActiveCfg = Debug|x64 - {05203741-CD80-4060-8218-EC5D1120FE3E}.Debug|x64.Build.0 = Debug|x64 - {05203741-CD80-4060-8218-EC5D1120FE3E}.Release|Any CPU.ActiveCfg = Release|Win32 - {05203741-CD80-4060-8218-EC5D1120FE3E}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {05203741-CD80-4060-8218-EC5D1120FE3E}.Release|Mixed Platforms.Build.0 = Release|Win32 - {05203741-CD80-4060-8218-EC5D1120FE3E}.Release|Win32.ActiveCfg = Release|Win32 - {05203741-CD80-4060-8218-EC5D1120FE3E}.Release|Win32.Build.0 = Release|Win32 - {05203741-CD80-4060-8218-EC5D1120FE3E}.Release|x64.ActiveCfg = Release|x64 - {05203741-CD80-4060-8218-EC5D1120FE3E}.Release|x64.Build.0 = Release|x64 - {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Debug|Win32.ActiveCfg = Debug|Win32 - {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Debug|Win32.Build.0 = Debug|Win32 - {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Debug|x64.ActiveCfg = Debug|x64 - {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Debug|x64.Build.0 = Debug|x64 - {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Release|Any CPU.ActiveCfg = Release|Win32 - {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Release|Mixed Platforms.Build.0 = Release|Win32 - {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Release|Win32.ActiveCfg = Release|Win32 - {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Release|Win32.Build.0 = Release|Win32 - {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Release|x64.ActiveCfg = Release|x64 - {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Release|x64.Build.0 = Release|x64 - {4F8C4C09-431C-45C4-830B-32006E783C3A}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {4F8C4C09-431C-45C4-830B-32006E783C3A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {4F8C4C09-431C-45C4-830B-32006E783C3A}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {4F8C4C09-431C-45C4-830B-32006E783C3A}.Debug|Win32.ActiveCfg = Debug|Win32 - {4F8C4C09-431C-45C4-830B-32006E783C3A}.Debug|Win32.Build.0 = Debug|Win32 - {4F8C4C09-431C-45C4-830B-32006E783C3A}.Debug|x64.ActiveCfg = Debug|x64 - {4F8C4C09-431C-45C4-830B-32006E783C3A}.Debug|x64.Build.0 = Debug|x64 - {4F8C4C09-431C-45C4-830B-32006E783C3A}.Release|Any CPU.ActiveCfg = Release|Win32 - {4F8C4C09-431C-45C4-830B-32006E783C3A}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {4F8C4C09-431C-45C4-830B-32006E783C3A}.Release|Mixed Platforms.Build.0 = Release|Win32 - {4F8C4C09-431C-45C4-830B-32006E783C3A}.Release|Win32.ActiveCfg = Release|Win32 - {4F8C4C09-431C-45C4-830B-32006E783C3A}.Release|Win32.Build.0 = Release|Win32 - {4F8C4C09-431C-45C4-830B-32006E783C3A}.Release|x64.ActiveCfg = Release|x64 - {4F8C4C09-431C-45C4-830B-32006E783C3A}.Release|x64.Build.0 = Release|x64 - {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Debug|Win32.ActiveCfg = Debug|Win32 - {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Debug|Win32.Build.0 = Debug|Win32 - {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Debug|x64.ActiveCfg = Debug|x64 - {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Debug|x64.Build.0 = Debug|x64 - {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Release|Any CPU.ActiveCfg = Release|Win32 - {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Release|Mixed Platforms.Build.0 = Release|Win32 - {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Release|Win32.ActiveCfg = Release|Win32 - {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Release|Win32.Build.0 = Release|Win32 - {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Release|x64.ActiveCfg = Release|x64 - {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Release|x64.Build.0 = Release|x64 - {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Debug|Win32.ActiveCfg = Debug|Win32 - {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Debug|Win32.Build.0 = Debug|Win32 - {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Debug|x64.ActiveCfg = Debug|x64 - {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Debug|x64.Build.0 = Debug|x64 - {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Release|Any CPU.ActiveCfg = Release|Win32 - {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Release|Mixed Platforms.Build.0 = Release|Win32 - {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Release|Win32.ActiveCfg = Release|Win32 - {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Release|Win32.Build.0 = Release|Win32 - {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Release|x64.ActiveCfg = Release|x64 - {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Release|x64.Build.0 = Release|x64 - {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Debug|Win32.ActiveCfg = Debug|Win32 - {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Debug|Win32.Build.0 = Debug|Win32 - {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Debug|x64.ActiveCfg = Debug|x64 - {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Debug|x64.Build.0 = Debug|x64 - {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Release|Any CPU.ActiveCfg = Release|Win32 - {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Release|Mixed Platforms.Build.0 = Release|Win32 - {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Release|Win32.ActiveCfg = Release|Win32 - {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Release|Win32.Build.0 = Release|Win32 - {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Release|x64.ActiveCfg = Release|x64 - {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Release|x64.Build.0 = Release|x64 - {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Debug|Win32.ActiveCfg = Debug|Win32 - {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Debug|Win32.Build.0 = Debug|Win32 - {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Debug|x64.ActiveCfg = Debug|x64 - {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Debug|x64.Build.0 = Debug|x64 - {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Release|Any CPU.ActiveCfg = Release|Win32 - {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Release|Mixed Platforms.Build.0 = Release|Win32 - {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Release|Win32.ActiveCfg = Release|Win32 - {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Release|Win32.Build.0 = Release|Win32 - {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Release|x64.ActiveCfg = Release|x64 - {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Release|x64.Build.0 = Release|x64 - {8B820B9F-C154-417C-A090-42198F2AF496}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {8B820B9F-C154-417C-A090-42198F2AF496}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {8B820B9F-C154-417C-A090-42198F2AF496}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {8B820B9F-C154-417C-A090-42198F2AF496}.Debug|Win32.ActiveCfg = Debug|Win32 - {8B820B9F-C154-417C-A090-42198F2AF496}.Debug|Win32.Build.0 = Debug|Win32 - {8B820B9F-C154-417C-A090-42198F2AF496}.Debug|x64.ActiveCfg = Debug|x64 - {8B820B9F-C154-417C-A090-42198F2AF496}.Debug|x64.Build.0 = Debug|x64 - {8B820B9F-C154-417C-A090-42198F2AF496}.Release|Any CPU.ActiveCfg = Release|Win32 - {8B820B9F-C154-417C-A090-42198F2AF496}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {8B820B9F-C154-417C-A090-42198F2AF496}.Release|Mixed Platforms.Build.0 = Release|Win32 - {8B820B9F-C154-417C-A090-42198F2AF496}.Release|Win32.ActiveCfg = Release|Win32 - {8B820B9F-C154-417C-A090-42198F2AF496}.Release|Win32.Build.0 = Release|Win32 - {8B820B9F-C154-417C-A090-42198F2AF496}.Release|x64.ActiveCfg = Release|x64 - {8B820B9F-C154-417C-A090-42198F2AF496}.Release|x64.Build.0 = Release|x64 - {45A34285-56DD-4521-912B-3F884D36FA35}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {45A34285-56DD-4521-912B-3F884D36FA35}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {45A34285-56DD-4521-912B-3F884D36FA35}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {45A34285-56DD-4521-912B-3F884D36FA35}.Debug|Win32.ActiveCfg = Debug|Win32 - {45A34285-56DD-4521-912B-3F884D36FA35}.Debug|Win32.Build.0 = Debug|Win32 - {45A34285-56DD-4521-912B-3F884D36FA35}.Debug|x64.ActiveCfg = Debug|x64 - {45A34285-56DD-4521-912B-3F884D36FA35}.Debug|x64.Build.0 = Debug|x64 - {45A34285-56DD-4521-912B-3F884D36FA35}.Release|Any CPU.ActiveCfg = Release|Win32 - {45A34285-56DD-4521-912B-3F884D36FA35}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {45A34285-56DD-4521-912B-3F884D36FA35}.Release|Mixed Platforms.Build.0 = Release|Win32 - {45A34285-56DD-4521-912B-3F884D36FA35}.Release|Win32.ActiveCfg = Release|Win32 - {45A34285-56DD-4521-912B-3F884D36FA35}.Release|Win32.Build.0 = Release|Win32 - {45A34285-56DD-4521-912B-3F884D36FA35}.Release|x64.ActiveCfg = Release|x64 - {45A34285-56DD-4521-912B-3F884D36FA35}.Release|x64.Build.0 = Release|x64 - {6D032D6B-7656-4743-B454-3388E2921EB0}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {6D032D6B-7656-4743-B454-3388E2921EB0}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {6D032D6B-7656-4743-B454-3388E2921EB0}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {6D032D6B-7656-4743-B454-3388E2921EB0}.Debug|Win32.ActiveCfg = Debug|Win32 - {6D032D6B-7656-4743-B454-3388E2921EB0}.Debug|Win32.Build.0 = Debug|Win32 - {6D032D6B-7656-4743-B454-3388E2921EB0}.Debug|x64.ActiveCfg = Debug|x64 - {6D032D6B-7656-4743-B454-3388E2921EB0}.Debug|x64.Build.0 = Debug|x64 - {6D032D6B-7656-4743-B454-3388E2921EB0}.Release|Any CPU.ActiveCfg = Release|Win32 - {6D032D6B-7656-4743-B454-3388E2921EB0}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {6D032D6B-7656-4743-B454-3388E2921EB0}.Release|Mixed Platforms.Build.0 = Release|Win32 - {6D032D6B-7656-4743-B454-3388E2921EB0}.Release|Win32.ActiveCfg = Release|Win32 - {6D032D6B-7656-4743-B454-3388E2921EB0}.Release|Win32.Build.0 = Release|Win32 - {6D032D6B-7656-4743-B454-3388E2921EB0}.Release|x64.ActiveCfg = Release|x64 - {6D032D6B-7656-4743-B454-3388E2921EB0}.Release|x64.Build.0 = Release|x64 - {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Debug|Win32.ActiveCfg = Debug|Win32 - {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Debug|Win32.Build.0 = Debug|Win32 - {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Debug|x64.ActiveCfg = Debug|x64 - {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Debug|x64.Build.0 = Debug|x64 - {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Release|Any CPU.ActiveCfg = Release|Win32 - {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Release|Mixed Platforms.Build.0 = Release|Win32 - {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Release|Win32.ActiveCfg = Release|Win32 - {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Release|Win32.Build.0 = Release|Win32 - {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Release|x64.ActiveCfg = Release|x64 - {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Release|x64.Build.0 = Release|x64 - {438D0136-4A27-4E4D-A617-FFACE4554236}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {438D0136-4A27-4E4D-A617-FFACE4554236}.Debug|Any CPU.Build.0 = Debug|Any CPU - {438D0136-4A27-4E4D-A617-FFACE4554236}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {438D0136-4A27-4E4D-A617-FFACE4554236}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {438D0136-4A27-4E4D-A617-FFACE4554236}.Debug|Win32.ActiveCfg = Debug|Any CPU - {438D0136-4A27-4E4D-A617-FFACE4554236}.Debug|x64.ActiveCfg = Debug|Any CPU - {438D0136-4A27-4E4D-A617-FFACE4554236}.Release|Any CPU.ActiveCfg = Release|Any CPU - {438D0136-4A27-4E4D-A617-FFACE4554236}.Release|Any CPU.Build.0 = Release|Any CPU - {438D0136-4A27-4E4D-A617-FFACE4554236}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {438D0136-4A27-4E4D-A617-FFACE4554236}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {438D0136-4A27-4E4D-A617-FFACE4554236}.Release|Win32.ActiveCfg = Release|Any CPU - {438D0136-4A27-4E4D-A617-FFACE4554236}.Release|x64.ActiveCfg = Release|Any CPU - {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Debug|Win32.ActiveCfg = Debug|Any CPU - {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Debug|x64.ActiveCfg = Debug|Any CPU - {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Release|Any CPU.Build.0 = Release|Any CPU - {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Release|Win32.ActiveCfg = Release|Any CPU - {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Release|x64.ActiveCfg = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30110.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "Common\Common.vcxproj", "{19312085-AA51-4BD6-BE92-4B6098CCA539}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Installer", "Installer\Installer.vcxproj", "{2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Language", "Language\Language.vcxproj", "{6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Library", "Library\Library.vcxproj", "{BE9D2400-7F1C-49D6-8498-5CE495491AD6}" + ProjectSection(ProjectDependencies) = postProject + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A} = {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A} + {19312085-AA51-4BD6-BE92-4B6098CCA539} = {19312085-AA51-4BD6-BE92-4B6098CCA539} + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6} = {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6} + {6D61FBE9-6913-4885-A95D-1A8C0C223D82} = {6D61FBE9-6913-4885-A95D-1A8C0C223D82} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Library_Lua", "Library\Library_Lua.vcxproj", "{BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Library_PCRE", "Library\Library_PCRE.vcxproj", "{6D61FBE9-6913-4885-A95D-1A8C0C223D82}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SkinInstaller", "SkinInstaller\SkinInstaller.vcxproj", "{6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SkinInstallerLauncher", "SkinInstaller\SkinInstallerLauncher.vcxproj", "{2D8F1DDB-6470-45A1-B95A-3E2960641314}" + ProjectSection(ProjectDependencies) = postProject + {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA} = {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginAdvancedCPU", "Plugins\PluginAdvancedCPU\PluginAdvancedCPU.vcxproj", "{EE8EC522-8430-4B46-86A3-D943D77F9E4B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginCoreTemp", "Plugins\PluginCoreTemp\PluginCoreTemp.vcxproj", "{F32FA418-8DF4-4E94-B92B-EBD502F5DC07}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginFileView", "Plugins\PluginFileView\PluginFileView.vcxproj", "{64FDEE97-6B7E-40E5-A489-ECA322825BC8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginFolderInfo", "Plugins\PluginFolderInfo\PluginFolderInfo.vcxproj", "{A221819D-4263-42AA-B22A-C022924842A7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginInputText", "Plugins\PluginInputText\PluginInputText.csproj", "{2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginiTunes", "Plugins\PluginiTunes\PluginiTunes.vcxproj", "{A2DD3CBE-B140-4892-A875-24107FA52518}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginMediaKey", "Plugins\PluginMediaKey\PluginMediaKey.vcxproj", "{EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginNowPlaying", "Plugins\PluginNowPlaying\PluginNowPlaying.vcxproj", "{C7FECFCD-E6C6-4F95-BB9A-E1762B043969}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginPerfMon", "Plugins\PluginPerfMon\PluginPerfMon.vcxproj", "{5344B52B-BAC3-479C-B41D-D465B8BDA1AD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginPing", "Plugins\PluginPing\PluginPing.vcxproj", "{C862B662-5CC6-4E79-B1B3-905E0B98D627}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginPower", "Plugins\PluginPower\PluginPower.vcxproj", "{C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginProcess", "Plugins\PluginProcess\PluginProcess.vcxproj", "{05203741-CD80-4060-8218-EC5D1120FE3E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginQuote", "Plugins\PluginQuote\PluginQuote.vcxproj", "{C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginRecycleManager", "Plugins\PluginRecycleManager\PluginRecycleManager.vcxproj", "{4F8C4C09-431C-45C4-830B-32006E783C3A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginResMon", "Plugins\PluginResMon\PluginResMon.vcxproj", "{17D3BD92-6F5D-438C-A89B-88F4CE06DB94}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginSpeedFan", "Plugins\PluginSpeedFan\PluginSpeedFan.vcxproj", "{D10AB316-0F7A-4551-BE4F-385E04CCF1E8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginSysInfo", "Plugins\PluginSysInfo\PluginSysInfo.vcxproj", "{6EBCA4DA-8CC7-42FE-8F45-878ABE165078}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginVirtualDesktops", "Plugins\PluginVirtualDesktops\PluginVirtualDesktops.vcxproj", "{4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginWebParser", "Plugins\PluginWebParser\PluginWebParser.vcxproj", "{8B820B9F-C154-417C-A090-42198F2AF496}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginWifiStatus", "Plugins\PluginWifiStatus\PluginWifiStatus.vcxproj", "{45A34285-56DD-4521-912B-3F884D36FA35}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginWin7Audio", "Plugins\PluginWin7Audio\PluginWin7Audio.vcxproj", "{6D032D6B-7656-4743-B454-3388E2921EB0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginWindowMessage", "Plugins\PluginWindowMessage\PluginWindowMessage.vcxproj", "{B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RainmeterStudio", "RainmeterEditor\RainmeterStudio.csproj", "{438D0136-4A27-4E4D-A617-FFACE4554236}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RainmeterStudio.Tests", "RainmeterStudio.Tests\RainmeterStudio.Tests.csproj", "{845F4BD4-6822-4D92-9DDB-15FD18A47E5A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {19312085-AA51-4BD6-BE92-4B6098CCA539}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {19312085-AA51-4BD6-BE92-4B6098CCA539}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {19312085-AA51-4BD6-BE92-4B6098CCA539}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {19312085-AA51-4BD6-BE92-4B6098CCA539}.Debug|Win32.ActiveCfg = Debug|Win32 + {19312085-AA51-4BD6-BE92-4B6098CCA539}.Debug|Win32.Build.0 = Debug|Win32 + {19312085-AA51-4BD6-BE92-4B6098CCA539}.Debug|x64.ActiveCfg = Debug|x64 + {19312085-AA51-4BD6-BE92-4B6098CCA539}.Debug|x64.Build.0 = Debug|x64 + {19312085-AA51-4BD6-BE92-4B6098CCA539}.Release|Any CPU.ActiveCfg = Release|Win32 + {19312085-AA51-4BD6-BE92-4B6098CCA539}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {19312085-AA51-4BD6-BE92-4B6098CCA539}.Release|Mixed Platforms.Build.0 = Release|Win32 + {19312085-AA51-4BD6-BE92-4B6098CCA539}.Release|Win32.ActiveCfg = Release|Win32 + {19312085-AA51-4BD6-BE92-4B6098CCA539}.Release|Win32.Build.0 = Release|Win32 + {19312085-AA51-4BD6-BE92-4B6098CCA539}.Release|x64.ActiveCfg = Release|x64 + {19312085-AA51-4BD6-BE92-4B6098CCA539}.Release|x64.Build.0 = Release|x64 + {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Debug|Win32.ActiveCfg = Debug|Win32 + {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Debug|x64.ActiveCfg = Debug|Win32 + {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Release|Any CPU.ActiveCfg = Release|Win32 + {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Release|Mixed Platforms.Build.0 = Release|Win32 + {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Release|Win32.ActiveCfg = Release|Win32 + {2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}.Release|x64.ActiveCfg = Release|Win32 + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Debug|Win32.ActiveCfg = Debug|Win32 + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Debug|Win32.Build.0 = Debug|Win32 + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Debug|x64.ActiveCfg = Debug|x64 + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Debug|x64.Build.0 = Debug|x64 + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Release|Any CPU.ActiveCfg = Release|Win32 + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Release|Mixed Platforms.Build.0 = Release|Win32 + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Release|Win32.ActiveCfg = Release|Win32 + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Release|Win32.Build.0 = Release|Win32 + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Release|x64.ActiveCfg = Release|x64 + {6BE6F228-B741-4DA9-9FBC-E9F2A7BD483A}.Release|x64.Build.0 = Release|x64 + {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Debug|Win32.ActiveCfg = Debug|Win32 + {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Debug|Win32.Build.0 = Debug|Win32 + {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Debug|x64.ActiveCfg = Debug|x64 + {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Debug|x64.Build.0 = Debug|x64 + {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Release|Any CPU.ActiveCfg = Release|Win32 + {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Release|Mixed Platforms.Build.0 = Release|Win32 + {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Release|Win32.ActiveCfg = Release|Win32 + {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Release|Win32.Build.0 = Release|Win32 + {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Release|x64.ActiveCfg = Release|x64 + {BE9D2400-7F1C-49D6-8498-5CE495491AD6}.Release|x64.Build.0 = Release|x64 + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Debug|Win32.ActiveCfg = Debug|Win32 + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Debug|Win32.Build.0 = Debug|Win32 + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Debug|x64.ActiveCfg = Debug|x64 + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Debug|x64.Build.0 = Debug|x64 + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Release|Any CPU.ActiveCfg = Release|Win32 + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Release|Mixed Platforms.Build.0 = Release|Win32 + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Release|Win32.ActiveCfg = Release|Win32 + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Release|Win32.Build.0 = Release|Win32 + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Release|x64.ActiveCfg = Release|x64 + {BC25C5DC-AEFB-49F9-8188-3C1B8C8929E6}.Release|x64.Build.0 = Release|x64 + {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Debug|Win32.ActiveCfg = Debug|Win32 + {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Debug|Win32.Build.0 = Debug|Win32 + {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Debug|x64.ActiveCfg = Debug|x64 + {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Debug|x64.Build.0 = Debug|x64 + {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Release|Any CPU.ActiveCfg = Release|Win32 + {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Release|Mixed Platforms.Build.0 = Release|Win32 + {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Release|Win32.ActiveCfg = Release|Win32 + {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Release|Win32.Build.0 = Release|Win32 + {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Release|x64.ActiveCfg = Release|x64 + {6D61FBE9-6913-4885-A95D-1A8C0C223D82}.Release|x64.Build.0 = Release|x64 + {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Debug|Win32.ActiveCfg = Debug|Win32 + {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Debug|Win32.Build.0 = Debug|Win32 + {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Debug|x64.ActiveCfg = Debug|x64 + {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Debug|x64.Build.0 = Debug|x64 + {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Release|Any CPU.ActiveCfg = Release|Win32 + {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Release|Mixed Platforms.Build.0 = Release|Win32 + {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Release|Win32.ActiveCfg = Release|Win32 + {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Release|Win32.Build.0 = Release|Win32 + {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Release|x64.ActiveCfg = Release|x64 + {6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}.Release|x64.Build.0 = Release|x64 + {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Debug|Win32.ActiveCfg = Debug|Win32 + {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Debug|Win32.Build.0 = Debug|Win32 + {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Debug|x64.ActiveCfg = Debug|x64 + {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Debug|x64.Build.0 = Debug|x64 + {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Release|Any CPU.ActiveCfg = Release|Win32 + {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Release|Mixed Platforms.Build.0 = Release|Win32 + {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Release|Win32.ActiveCfg = Release|Win32 + {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Release|Win32.Build.0 = Release|Win32 + {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Release|x64.ActiveCfg = Release|x64 + {2D8F1DDB-6470-45A1-B95A-3E2960641314}.Release|x64.Build.0 = Release|x64 + {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Debug|Win32.ActiveCfg = Debug|Win32 + {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Debug|Win32.Build.0 = Debug|Win32 + {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Debug|x64.ActiveCfg = Debug|x64 + {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Debug|x64.Build.0 = Debug|x64 + {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Release|Any CPU.ActiveCfg = Release|Win32 + {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Release|Mixed Platforms.Build.0 = Release|Win32 + {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Release|Win32.ActiveCfg = Release|Win32 + {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Release|Win32.Build.0 = Release|Win32 + {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Release|x64.ActiveCfg = Release|x64 + {EE8EC522-8430-4B46-86A3-D943D77F9E4B}.Release|x64.Build.0 = Release|x64 + {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Debug|Win32.ActiveCfg = Debug|Win32 + {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Debug|Win32.Build.0 = Debug|Win32 + {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Debug|x64.ActiveCfg = Debug|x64 + {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Debug|x64.Build.0 = Debug|x64 + {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|Any CPU.ActiveCfg = Release|Win32 + {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|Mixed Platforms.Build.0 = Release|Win32 + {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|Win32.ActiveCfg = Release|Win32 + {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|Win32.Build.0 = Release|Win32 + {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|x64.ActiveCfg = Release|x64 + {F32FA418-8DF4-4E94-B92B-EBD502F5DC07}.Release|x64.Build.0 = Release|x64 + {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Debug|Win32.ActiveCfg = Debug|Win32 + {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Debug|Win32.Build.0 = Debug|Win32 + {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Debug|x64.ActiveCfg = Debug|x64 + {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Debug|x64.Build.0 = Debug|x64 + {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Release|Any CPU.ActiveCfg = Release|Win32 + {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Release|Mixed Platforms.Build.0 = Release|Win32 + {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Release|Win32.ActiveCfg = Release|Win32 + {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Release|Win32.Build.0 = Release|Win32 + {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Release|x64.ActiveCfg = Release|x64 + {64FDEE97-6B7E-40E5-A489-ECA322825BC8}.Release|x64.Build.0 = Release|x64 + {A221819D-4263-42AA-B22A-C022924842A7}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Debug|Win32.ActiveCfg = Debug|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Debug|Win32.Build.0 = Debug|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Debug|x64.ActiveCfg = Debug|x64 + {A221819D-4263-42AA-B22A-C022924842A7}.Debug|x64.Build.0 = Debug|x64 + {A221819D-4263-42AA-B22A-C022924842A7}.Release|Any CPU.ActiveCfg = Release|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Release|Mixed Platforms.Build.0 = Release|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Release|Win32.ActiveCfg = Release|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Release|Win32.Build.0 = Release|Win32 + {A221819D-4263-42AA-B22A-C022924842A7}.Release|x64.ActiveCfg = Release|x64 + {A221819D-4263-42AA-B22A-C022924842A7}.Release|x64.Build.0 = Release|x64 + {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Debug|Any CPU.ActiveCfg = Debug|x86 + {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Debug|Win32.ActiveCfg = Debug|x86 + {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Debug|Win32.Build.0 = Debug|x86 + {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Debug|x64.ActiveCfg = Debug|x64 + {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Debug|x64.Build.0 = Debug|x64 + {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Release|Any CPU.ActiveCfg = Release|x86 + {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Release|Mixed Platforms.Build.0 = Release|x86 + {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Release|Win32.ActiveCfg = Release|x86 + {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Release|Win32.Build.0 = Release|x86 + {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Release|x64.ActiveCfg = Release|x64 + {2CFEC79A-E39E-4FFD-ABC2-C4A69DD1E44D}.Release|x64.Build.0 = Release|x64 + {A2DD3CBE-B140-4892-A875-24107FA52518}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {A2DD3CBE-B140-4892-A875-24107FA52518}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {A2DD3CBE-B140-4892-A875-24107FA52518}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {A2DD3CBE-B140-4892-A875-24107FA52518}.Debug|Win32.ActiveCfg = Debug|Win32 + {A2DD3CBE-B140-4892-A875-24107FA52518}.Debug|Win32.Build.0 = Debug|Win32 + {A2DD3CBE-B140-4892-A875-24107FA52518}.Debug|x64.ActiveCfg = Debug|x64 + {A2DD3CBE-B140-4892-A875-24107FA52518}.Debug|x64.Build.0 = Debug|x64 + {A2DD3CBE-B140-4892-A875-24107FA52518}.Release|Any CPU.ActiveCfg = Release|Win32 + {A2DD3CBE-B140-4892-A875-24107FA52518}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {A2DD3CBE-B140-4892-A875-24107FA52518}.Release|Mixed Platforms.Build.0 = Release|Win32 + {A2DD3CBE-B140-4892-A875-24107FA52518}.Release|Win32.ActiveCfg = Release|Win32 + {A2DD3CBE-B140-4892-A875-24107FA52518}.Release|Win32.Build.0 = Release|Win32 + {A2DD3CBE-B140-4892-A875-24107FA52518}.Release|x64.ActiveCfg = Release|x64 + {A2DD3CBE-B140-4892-A875-24107FA52518}.Release|x64.Build.0 = Release|x64 + {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Debug|Win32.ActiveCfg = Debug|Win32 + {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Debug|Win32.Build.0 = Debug|Win32 + {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Debug|x64.ActiveCfg = Debug|x64 + {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Debug|x64.Build.0 = Debug|x64 + {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release|Any CPU.ActiveCfg = Release|Win32 + {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release|Mixed Platforms.Build.0 = Release|Win32 + {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release|Win32.ActiveCfg = Release|Win32 + {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release|Win32.Build.0 = Release|Win32 + {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release|x64.ActiveCfg = Release|x64 + {EB48A04A-657E-41B8-B2F5-D47F8C30B2B4}.Release|x64.Build.0 = Release|x64 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|Win32.ActiveCfg = Debug|Win32 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|Win32.Build.0 = Debug|Win32 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|x64.ActiveCfg = Debug|x64 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Debug|x64.Build.0 = Debug|x64 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|Any CPU.ActiveCfg = Release|Win32 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|Mixed Platforms.Build.0 = Release|Win32 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|Win32.ActiveCfg = Release|Win32 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|Win32.Build.0 = Release|Win32 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|x64.ActiveCfg = Release|x64 + {C7FECFCD-E6C6-4F95-BB9A-E1762B043969}.Release|x64.Build.0 = Release|x64 + {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|Win32.ActiveCfg = Debug|Win32 + {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|Win32.Build.0 = Debug|Win32 + {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|x64.ActiveCfg = Debug|x64 + {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Debug|x64.Build.0 = Debug|x64 + {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Release|Any CPU.ActiveCfg = Release|Win32 + {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Release|Mixed Platforms.Build.0 = Release|Win32 + {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Release|Win32.ActiveCfg = Release|Win32 + {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Release|Win32.Build.0 = Release|Win32 + {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Release|x64.ActiveCfg = Release|x64 + {5344B52B-BAC3-479C-B41D-D465B8BDA1AD}.Release|x64.Build.0 = Release|x64 + {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Debug|Win32.ActiveCfg = Debug|Win32 + {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Debug|Win32.Build.0 = Debug|Win32 + {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Debug|x64.ActiveCfg = Debug|x64 + {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Debug|x64.Build.0 = Debug|x64 + {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Release|Any CPU.ActiveCfg = Release|Win32 + {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Release|Mixed Platforms.Build.0 = Release|Win32 + {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Release|Win32.ActiveCfg = Release|Win32 + {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Release|Win32.Build.0 = Release|Win32 + {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Release|x64.ActiveCfg = Release|x64 + {C862B662-5CC6-4E79-B1B3-905E0B98D627}.Release|x64.Build.0 = Release|x64 + {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Debug|Win32.ActiveCfg = Debug|Win32 + {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Debug|Win32.Build.0 = Debug|Win32 + {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Debug|x64.ActiveCfg = Debug|x64 + {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Debug|x64.Build.0 = Debug|x64 + {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Release|Any CPU.ActiveCfg = Release|Win32 + {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Release|Mixed Platforms.Build.0 = Release|Win32 + {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Release|Win32.ActiveCfg = Release|Win32 + {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Release|Win32.Build.0 = Release|Win32 + {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Release|x64.ActiveCfg = Release|x64 + {C30E7EB6-9655-4AF4-98AE-D6E6B14631AF}.Release|x64.Build.0 = Release|x64 + {05203741-CD80-4060-8218-EC5D1120FE3E}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {05203741-CD80-4060-8218-EC5D1120FE3E}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {05203741-CD80-4060-8218-EC5D1120FE3E}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {05203741-CD80-4060-8218-EC5D1120FE3E}.Debug|Win32.ActiveCfg = Debug|Win32 + {05203741-CD80-4060-8218-EC5D1120FE3E}.Debug|Win32.Build.0 = Debug|Win32 + {05203741-CD80-4060-8218-EC5D1120FE3E}.Debug|x64.ActiveCfg = Debug|x64 + {05203741-CD80-4060-8218-EC5D1120FE3E}.Debug|x64.Build.0 = Debug|x64 + {05203741-CD80-4060-8218-EC5D1120FE3E}.Release|Any CPU.ActiveCfg = Release|Win32 + {05203741-CD80-4060-8218-EC5D1120FE3E}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {05203741-CD80-4060-8218-EC5D1120FE3E}.Release|Mixed Platforms.Build.0 = Release|Win32 + {05203741-CD80-4060-8218-EC5D1120FE3E}.Release|Win32.ActiveCfg = Release|Win32 + {05203741-CD80-4060-8218-EC5D1120FE3E}.Release|Win32.Build.0 = Release|Win32 + {05203741-CD80-4060-8218-EC5D1120FE3E}.Release|x64.ActiveCfg = Release|x64 + {05203741-CD80-4060-8218-EC5D1120FE3E}.Release|x64.Build.0 = Release|x64 + {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Debug|Win32.ActiveCfg = Debug|Win32 + {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Debug|Win32.Build.0 = Debug|Win32 + {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Debug|x64.ActiveCfg = Debug|x64 + {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Debug|x64.Build.0 = Debug|x64 + {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Release|Any CPU.ActiveCfg = Release|Win32 + {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Release|Mixed Platforms.Build.0 = Release|Win32 + {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Release|Win32.ActiveCfg = Release|Win32 + {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Release|Win32.Build.0 = Release|Win32 + {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Release|x64.ActiveCfg = Release|x64 + {C029E0CF-F203-41D0-9608-A3EA2CF0ED1F}.Release|x64.Build.0 = Release|x64 + {4F8C4C09-431C-45C4-830B-32006E783C3A}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {4F8C4C09-431C-45C4-830B-32006E783C3A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {4F8C4C09-431C-45C4-830B-32006E783C3A}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {4F8C4C09-431C-45C4-830B-32006E783C3A}.Debug|Win32.ActiveCfg = Debug|Win32 + {4F8C4C09-431C-45C4-830B-32006E783C3A}.Debug|Win32.Build.0 = Debug|Win32 + {4F8C4C09-431C-45C4-830B-32006E783C3A}.Debug|x64.ActiveCfg = Debug|x64 + {4F8C4C09-431C-45C4-830B-32006E783C3A}.Debug|x64.Build.0 = Debug|x64 + {4F8C4C09-431C-45C4-830B-32006E783C3A}.Release|Any CPU.ActiveCfg = Release|Win32 + {4F8C4C09-431C-45C4-830B-32006E783C3A}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {4F8C4C09-431C-45C4-830B-32006E783C3A}.Release|Mixed Platforms.Build.0 = Release|Win32 + {4F8C4C09-431C-45C4-830B-32006E783C3A}.Release|Win32.ActiveCfg = Release|Win32 + {4F8C4C09-431C-45C4-830B-32006E783C3A}.Release|Win32.Build.0 = Release|Win32 + {4F8C4C09-431C-45C4-830B-32006E783C3A}.Release|x64.ActiveCfg = Release|x64 + {4F8C4C09-431C-45C4-830B-32006E783C3A}.Release|x64.Build.0 = Release|x64 + {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Debug|Win32.ActiveCfg = Debug|Win32 + {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Debug|Win32.Build.0 = Debug|Win32 + {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Debug|x64.ActiveCfg = Debug|x64 + {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Debug|x64.Build.0 = Debug|x64 + {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Release|Any CPU.ActiveCfg = Release|Win32 + {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Release|Mixed Platforms.Build.0 = Release|Win32 + {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Release|Win32.ActiveCfg = Release|Win32 + {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Release|Win32.Build.0 = Release|Win32 + {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Release|x64.ActiveCfg = Release|x64 + {17D3BD92-6F5D-438C-A89B-88F4CE06DB94}.Release|x64.Build.0 = Release|x64 + {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Debug|Win32.ActiveCfg = Debug|Win32 + {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Debug|Win32.Build.0 = Debug|Win32 + {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Debug|x64.ActiveCfg = Debug|x64 + {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Debug|x64.Build.0 = Debug|x64 + {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Release|Any CPU.ActiveCfg = Release|Win32 + {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Release|Mixed Platforms.Build.0 = Release|Win32 + {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Release|Win32.ActiveCfg = Release|Win32 + {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Release|Win32.Build.0 = Release|Win32 + {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Release|x64.ActiveCfg = Release|x64 + {D10AB316-0F7A-4551-BE4F-385E04CCF1E8}.Release|x64.Build.0 = Release|x64 + {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Debug|Win32.ActiveCfg = Debug|Win32 + {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Debug|Win32.Build.0 = Debug|Win32 + {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Debug|x64.ActiveCfg = Debug|x64 + {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Debug|x64.Build.0 = Debug|x64 + {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Release|Any CPU.ActiveCfg = Release|Win32 + {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Release|Mixed Platforms.Build.0 = Release|Win32 + {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Release|Win32.ActiveCfg = Release|Win32 + {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Release|Win32.Build.0 = Release|Win32 + {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Release|x64.ActiveCfg = Release|x64 + {6EBCA4DA-8CC7-42FE-8F45-878ABE165078}.Release|x64.Build.0 = Release|x64 + {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Debug|Win32.ActiveCfg = Debug|Win32 + {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Debug|Win32.Build.0 = Debug|Win32 + {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Debug|x64.ActiveCfg = Debug|x64 + {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Debug|x64.Build.0 = Debug|x64 + {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Release|Any CPU.ActiveCfg = Release|Win32 + {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Release|Mixed Platforms.Build.0 = Release|Win32 + {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Release|Win32.ActiveCfg = Release|Win32 + {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Release|Win32.Build.0 = Release|Win32 + {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Release|x64.ActiveCfg = Release|x64 + {4640AB3A-5A8B-2DA0-980C-A70BCAB3A7F1}.Release|x64.Build.0 = Release|x64 + {8B820B9F-C154-417C-A090-42198F2AF496}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {8B820B9F-C154-417C-A090-42198F2AF496}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {8B820B9F-C154-417C-A090-42198F2AF496}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {8B820B9F-C154-417C-A090-42198F2AF496}.Debug|Win32.ActiveCfg = Debug|Win32 + {8B820B9F-C154-417C-A090-42198F2AF496}.Debug|Win32.Build.0 = Debug|Win32 + {8B820B9F-C154-417C-A090-42198F2AF496}.Debug|x64.ActiveCfg = Debug|x64 + {8B820B9F-C154-417C-A090-42198F2AF496}.Debug|x64.Build.0 = Debug|x64 + {8B820B9F-C154-417C-A090-42198F2AF496}.Release|Any CPU.ActiveCfg = Release|Win32 + {8B820B9F-C154-417C-A090-42198F2AF496}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {8B820B9F-C154-417C-A090-42198F2AF496}.Release|Mixed Platforms.Build.0 = Release|Win32 + {8B820B9F-C154-417C-A090-42198F2AF496}.Release|Win32.ActiveCfg = Release|Win32 + {8B820B9F-C154-417C-A090-42198F2AF496}.Release|Win32.Build.0 = Release|Win32 + {8B820B9F-C154-417C-A090-42198F2AF496}.Release|x64.ActiveCfg = Release|x64 + {8B820B9F-C154-417C-A090-42198F2AF496}.Release|x64.Build.0 = Release|x64 + {45A34285-56DD-4521-912B-3F884D36FA35}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {45A34285-56DD-4521-912B-3F884D36FA35}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {45A34285-56DD-4521-912B-3F884D36FA35}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {45A34285-56DD-4521-912B-3F884D36FA35}.Debug|Win32.ActiveCfg = Debug|Win32 + {45A34285-56DD-4521-912B-3F884D36FA35}.Debug|Win32.Build.0 = Debug|Win32 + {45A34285-56DD-4521-912B-3F884D36FA35}.Debug|x64.ActiveCfg = Debug|x64 + {45A34285-56DD-4521-912B-3F884D36FA35}.Debug|x64.Build.0 = Debug|x64 + {45A34285-56DD-4521-912B-3F884D36FA35}.Release|Any CPU.ActiveCfg = Release|Win32 + {45A34285-56DD-4521-912B-3F884D36FA35}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {45A34285-56DD-4521-912B-3F884D36FA35}.Release|Mixed Platforms.Build.0 = Release|Win32 + {45A34285-56DD-4521-912B-3F884D36FA35}.Release|Win32.ActiveCfg = Release|Win32 + {45A34285-56DD-4521-912B-3F884D36FA35}.Release|Win32.Build.0 = Release|Win32 + {45A34285-56DD-4521-912B-3F884D36FA35}.Release|x64.ActiveCfg = Release|x64 + {45A34285-56DD-4521-912B-3F884D36FA35}.Release|x64.Build.0 = Release|x64 + {6D032D6B-7656-4743-B454-3388E2921EB0}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {6D032D6B-7656-4743-B454-3388E2921EB0}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {6D032D6B-7656-4743-B454-3388E2921EB0}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {6D032D6B-7656-4743-B454-3388E2921EB0}.Debug|Win32.ActiveCfg = Debug|Win32 + {6D032D6B-7656-4743-B454-3388E2921EB0}.Debug|Win32.Build.0 = Debug|Win32 + {6D032D6B-7656-4743-B454-3388E2921EB0}.Debug|x64.ActiveCfg = Debug|x64 + {6D032D6B-7656-4743-B454-3388E2921EB0}.Debug|x64.Build.0 = Debug|x64 + {6D032D6B-7656-4743-B454-3388E2921EB0}.Release|Any CPU.ActiveCfg = Release|Win32 + {6D032D6B-7656-4743-B454-3388E2921EB0}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {6D032D6B-7656-4743-B454-3388E2921EB0}.Release|Mixed Platforms.Build.0 = Release|Win32 + {6D032D6B-7656-4743-B454-3388E2921EB0}.Release|Win32.ActiveCfg = Release|Win32 + {6D032D6B-7656-4743-B454-3388E2921EB0}.Release|Win32.Build.0 = Release|Win32 + {6D032D6B-7656-4743-B454-3388E2921EB0}.Release|x64.ActiveCfg = Release|x64 + {6D032D6B-7656-4743-B454-3388E2921EB0}.Release|x64.Build.0 = Release|x64 + {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Debug|Win32.ActiveCfg = Debug|Win32 + {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Debug|Win32.Build.0 = Debug|Win32 + {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Debug|x64.ActiveCfg = Debug|x64 + {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Debug|x64.Build.0 = Debug|x64 + {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Release|Any CPU.ActiveCfg = Release|Win32 + {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Release|Mixed Platforms.Build.0 = Release|Win32 + {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Release|Win32.ActiveCfg = Release|Win32 + {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Release|Win32.Build.0 = Release|Win32 + {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Release|x64.ActiveCfg = Release|x64 + {B9184DBA-C6B7-44FE-8BBD-0852DB22D2E4}.Release|x64.Build.0 = Release|x64 + {438D0136-4A27-4E4D-A617-FFACE4554236}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {438D0136-4A27-4E4D-A617-FFACE4554236}.Debug|Any CPU.Build.0 = Debug|Any CPU + {438D0136-4A27-4E4D-A617-FFACE4554236}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {438D0136-4A27-4E4D-A617-FFACE4554236}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {438D0136-4A27-4E4D-A617-FFACE4554236}.Debug|Win32.ActiveCfg = Debug|Any CPU + {438D0136-4A27-4E4D-A617-FFACE4554236}.Debug|x64.ActiveCfg = Debug|Any CPU + {438D0136-4A27-4E4D-A617-FFACE4554236}.Release|Any CPU.ActiveCfg = Release|Any CPU + {438D0136-4A27-4E4D-A617-FFACE4554236}.Release|Any CPU.Build.0 = Release|Any CPU + {438D0136-4A27-4E4D-A617-FFACE4554236}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {438D0136-4A27-4E4D-A617-FFACE4554236}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {438D0136-4A27-4E4D-A617-FFACE4554236}.Release|Win32.ActiveCfg = Release|Any CPU + {438D0136-4A27-4E4D-A617-FFACE4554236}.Release|x64.ActiveCfg = Release|Any CPU + {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Debug|Win32.ActiveCfg = Debug|Any CPU + {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Debug|x64.ActiveCfg = Debug|Any CPU + {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Release|Any CPU.Build.0 = Release|Any CPU + {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Release|Win32.ActiveCfg = Release|Any CPU + {845F4BD4-6822-4D92-9DDB-15FD18A47E5A}.Release|x64.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/SkinInstaller/DialogInstall.cpp b/SkinInstaller/DialogInstall.cpp index 6f449e57..79edec57 100644 --- a/SkinInstaller/DialogInstall.cpp +++ b/SkinInstaller/DialogInstall.cpp @@ -1,1409 +1,1409 @@ -/* - Copyright (C) 2012 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "SkinInstaller.h" -#include "DialogInstall.h" -#include "resource.h" -#include "../Version.h" - -#define WM_DELAYED_CLOSE WM_APP + 0 - -extern GlobalData g_Data; - -DialogInstall* DialogInstall::c_Dialog = nullptr; - -inline bool IsWin32Build() -{ -#ifdef _WIN64 - return false; -#else - return true; -#endif -} - -/* -** Constructor. -** -*/ -DialogInstall::DialogInstall(HWND wnd, const WCHAR* file) : Dialog(wnd), - m_TabInstall(wnd), - m_HeaderBitmap(), - m_InstallThread(), - m_PackageUnzFile(), - m_PackageFileName(file), - m_PackageFormat(PackageFormat::Old), - m_BackupPackage(false), - m_BackupSkins(true), - m_MergeSkins(false), - m_SystemFonts(false) -{ -} - -/* -** Destructor. -** -*/ -DialogInstall::~DialogInstall() -{ - if (m_PackageUnzFile) - { - unzClose(m_PackageUnzFile); - } -} - -/* -** Creates the dialog. -** -*/ -void DialogInstall::Create(HINSTANCE hInstance, LPWSTR lpCmdLine) -{ - // Prompt to select .rmskin file if needed - WCHAR buffer[MAX_PATH]; - if (!*lpCmdLine) - { - buffer[0] = L'\0'; - - OPENFILENAME ofn = {0}; - ofn.lStructSize = sizeof(OPENFILENAME); - ofn.lpstrFilter = L"Rainmeter skin file (.rmskin)\0*.rmskin;*.zip"; - ofn.nFilterIndex = 1; - ofn.lpstrFile = buffer; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrTitle = L"Select Rainmeter skin file"; - ofn.lpstrDefExt = L"rmskin"; - ofn.Flags = OFN_FILEMUSTEXIST; - - if (!GetOpenFileName(&ofn)) - { - return; - } - - lpCmdLine = buffer; - } - - HANDLE hMutex; - if (IsRunning(L"Rainmeter Skin Installer", &hMutex)) - { - HWND hwnd = FindWindow(L"#32770", L"Rainmeter Skin Installer"); - SetForegroundWindow(hwnd); - } - else - { - DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_INSTALL_DIALOG), nullptr, (DLGPROC)DlgProc, (LPARAM)lpCmdLine); - ReleaseMutex(hMutex); - } -} - -Dialog::Tab& DialogInstall::GetActiveTab() -{ - return m_TabInstall; -} - -INT_PTR CALLBACK DialogInstall::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (!c_Dialog) - { - if (uMsg == WM_INITDIALOG) - { - c_Dialog = new DialogInstall(hWnd, (const WCHAR*)lParam); - return c_Dialog->OnInitDialog(wParam, lParam); - } - } - else - { - switch (uMsg) - { - case WM_COMMAND: - return c_Dialog->OnCommand(wParam, lParam); - - case WM_CLOSE: - if (!c_Dialog->m_InstallThread) - { - EndDialog(hWnd, 0); - } - return TRUE; - - case WM_DESTROY: - delete c_Dialog; - c_Dialog = nullptr; - return FALSE; - } - } - - return FALSE; -} - -INT_PTR DialogInstall::OnInitDialog(WPARAM wParam, LPARAM lParam) -{ - HICON hIcon = (HICON)LoadImage(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDI_SKININSTALLER), IMAGE_ICON, 16, 16, LR_SHARED); - SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); - - if (GetOSPlatform() >= OSPLATFORM_VISTA) - { - SetDialogFont(); - } - - HWND item = GetDlgItem(m_Window, IDC_INSTALL_ADVANCED_BUTTON); - Dialog::SetMenuButton(item); - - if (ReadPackage()) - { - item = GetDlgItem(m_Window, IDC_INSTALL_HEADER_BITMAP); - if (m_HeaderBitmap) - { - SendMessage(item, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)m_HeaderBitmap); - } - else - { - RECT r; - GetClientRect(item, &r); - ShowWindow(item, SW_HIDE); - int yDiff = r.bottom; - - // Move all controls on the main dialog up to "fill" header area. - int controlIds[] = { IDC_INSTALL_TAB, IDC_INSTALL_ADVANCED_BUTTON, IDC_INSTALL_INSTALL_BUTTON, IDCANCEL, 0 }; - for (int i = 0; i < _countof(controlIds); ++i) - { - HWND control = controlIds[i] ? GetDlgItem(m_Window, controlIds[i]) : m_TabInstall.GetWindow(); - GetWindowRect(control, &r); - MapWindowPoints(nullptr, m_Window, (POINT*)&r, sizeof(RECT) / sizeof(POINT)); - MoveWindow(control, r.left, r.top - yDiff, r.right - r.left, r.bottom - r.top, TRUE); - } - - // Remove blank area at the bottom of the dialog and center it. - GetWindowRect(m_Window, &r); - MoveWindow(m_Window, r.left, r.top + (yDiff / 2), r.right - r.left, r.bottom - r.top - yDiff, TRUE); - } - - m_TabInstall.Activate(); - } - else - { - if (m_ErrorMessage.empty()) - { - m_ErrorMessage = L"Invalid package:\n"; - m_ErrorMessage += PathFindFileName(m_PackageFileName.c_str()); - m_ErrorMessage += L"\n\nThe Skin Packager tool must be used to create valid .rmskin packages."; - } - - MessageBox(nullptr, m_ErrorMessage.c_str(), L"Rainmeter Skin Installer", MB_ERROR); - EndDialog(m_Window, 0); - } - - - return TRUE; -} - -INT_PTR DialogInstall::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_INSTALL_ADVANCED_BUTTON: - { - RECT r; - GetWindowRect((HWND)lParam, &r); - HMENU menu = LoadMenu(GetInstanceHandle(), MAKEINTRESOURCE(IDR_INSTALL_MENU)); - HMENU subMenu = GetSubMenu(menu, 0); - - if (m_PackageSkins.empty() || m_MergeSkins || m_BackupPackage) - { - EnableMenuItem(subMenu, IDM_INSTALL_BACKUPSKINS, MF_BYCOMMAND | MF_GRAYED); - } - else - { - CheckMenuItem(subMenu, IDM_INSTALL_BACKUPSKINS, (m_BackupSkins ? MF_CHECKED : MF_UNCHECKED) | MF_BYCOMMAND); - } - - if (m_PackageFonts.empty()) - { - EnableMenuItem(subMenu, IDM_INSTALL_SYSTEMFONTS, MF_BYCOMMAND | MF_GRAYED); - } - else - { - CheckMenuItem(subMenu, IDM_INSTALL_SYSTEMFONTS, (m_SystemFonts ? MF_CHECKED : MF_UNCHECKED) | MF_BYCOMMAND); - } - - const WCHAR* formatName = m_PackageFormat == PackageFormat::New ? L"New format" : L"Old format"; - ModifyMenu(subMenu, IDM_INSTALL_FORMAT, MF_STRING | MF_GRAYED | MF_BYCOMMAND, IDM_INSTALL_FORMAT, formatName); - - TrackPopupMenu( - subMenu, - TPM_RIGHTBUTTON | TPM_LEFTALIGN, - r.left, - --r.bottom, - 0, - m_Window, - nullptr); - - DestroyMenu(menu); - } - break; - - case IDC_INSTALL_INSTALL_BUTTON: - BeginInstall(); - break; - - case IDCANCEL: - if (!m_InstallThread) - { - EndDialog(m_Window, 0); - } - break; - - case IDM_INSTALL_BACKUPSKINS: - m_BackupSkins = !m_BackupSkins; - break; - - case IDM_INSTALL_SYSTEMFONTS: - m_SystemFonts = !m_SystemFonts; - break; - - default: - return FALSE; - } - - return TRUE; -} - -INT_PTR DialogInstall::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->code) - { - case BCN_DROPDOWN: - { - NMHDR* hdr = &((NMBCDROPDOWN*)lParam)->hdr; - - // Unpush the drop-down button part and simulate click - Button_SetDropDownState(hdr->hwndFrom, FALSE); - SendMessage(hdr->hwndFrom, BM_CLICK, 0, 0); - } - break; - - default: - return FALSE; - } - - return TRUE; -} - -bool DialogInstall::ExtractCurrentFile(const std::wstring& fileName) -{ - // Some archives don't explicity list directories, so create them recursively - if (!CreateDirectoryRecursive(fileName)) - { - return false; - } - - if (fileName.back() == L'\\') - { - // Nothing left to do - return true; - } - - if (unzOpenCurrentFile(m_PackageUnzFile) != UNZ_OK) - { - return false; - } - - HANDLE hFile = CreateFile(fileName.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - if (hFile == INVALID_HANDLE_VALUE) - { - return false; - } - - int read; - do - { - BYTE buffer[16384]; - DWORD written; - read = unzReadCurrentFile(m_PackageUnzFile, buffer, 16384); - if (read < 0 || !WriteFile(hFile, (LPCVOID)buffer, read, &written, nullptr) || read != written) - { - read = UNZ_ERRNO; - break; - } - } - while (read != UNZ_EOF); - - CloseHandle(hFile); - - return unzCloseCurrentFile(m_PackageUnzFile) == UNZ_OK && read == UNZ_EOF; -} - -bool DialogInstall::ReadPackage() -{ - const WCHAR* fileName = m_PackageFileName.c_str(); - const WCHAR* fileExtension = PathFindExtension(fileName); - - if (_wcsicmp(fileExtension, L".rmskin") == 0) - { - // Check if the footer is present (for new .rmskin format) - PackageFooter footer = {0}; - - FILE* file = _wfopen(fileName, L"rb"); - __int64 fileSize = 0; - if (file) - { - fseek(file, -(long)sizeof(footer), SEEK_END); - fileSize = _ftelli64(file); - fread(&footer, sizeof(footer), 1, file); - fclose(file); - } - - if (strcmp(footer.key, "RMSKIN") == 0) - { - m_PackageFormat = PackageFormat::New; - if (footer.size != fileSize) - { - return false; - } - - if (footer.flags) - { - m_BackupPackage = !(footer.flags & PackageFlag::Backup); - } - } - } - else if (_wcsicmp(fileExtension, L".zip") != 0) - { - return false; - } - - m_PackageUnzFile = unzOpen(ConvertToAscii(fileName).c_str()); - if (!m_PackageUnzFile) - { - return false; - } - - WCHAR buffer[MAX_PATH]; - - // Get temporary file to extract the options file and header bitmap - GetTempPath(MAX_PATH, buffer); - GetTempFileName(buffer, L"dat", 0, buffer); - std::wstring tempFile = buffer; - const WCHAR* tempFileSz = tempFile.c_str(); - - // Helper to sets buffer with current file name - auto getFileInfo = [&]()->bool - { - char cBuffer[MAX_PATH * 3]; - unz_file_info ufi; - if (unzGetCurrentFileInfo( - m_PackageUnzFile, &ufi, cBuffer, _countof(cBuffer), nullptr, 0, nullptr, 0) == UNZ_OK) - { - const uLong ZIP_UTF8_FLAG = 1 << 11; - const DWORD codePage = (ufi.flag & ZIP_UTF8_FLAG) ? CP_UTF8 : CP_ACP; - MultiByteToWideChar(codePage, 0, cBuffer, strlen(cBuffer) + 1, buffer, MAX_PATH); - while (WCHAR* pos = wcschr(buffer, L'/')) *pos = L'\\'; - return true; - } - - return false; - }; - - // Loop through the contents of the archive until the settings file is found - WCHAR* path; - bool optionsFound = false; - do - { - if (!getFileInfo()) - { - return false; - } - - path = wcsrchr(buffer, L'\\'); - if (!path) - { - path = buffer; - } - else - { - if (m_PackageFormat == PackageFormat::New) - { - // New package files must be in root of archive - continue; - } - - ++path; // Skip slash - } - - if (_wcsicmp(path, m_PackageFormat == PackageFormat::New ? L"RMSKIN.ini" : L"Rainstaller.cfg") == 0) - { - if (ExtractCurrentFile(tempFile)) - { - optionsFound = ReadOptions(tempFileSz); - DeleteFile(tempFileSz); - } - - break; - } - } - while (unzGoToNextFile(m_PackageUnzFile) == UNZ_OK); - - if (!optionsFound) - { - return false; - } - - // Loop through the archive a second time and find included components - unzGoToFirstFile(m_PackageUnzFile); - - m_PackageRoot.assign(buffer, path - buffer); - const WCHAR* root = m_PackageRoot.c_str(); - do - { - if (!getFileInfo()) - { - return false; - } - - if (wcsncmp(buffer, root, m_PackageRoot.length()) != 0) - { - // Ignore everything that isn't in the root directory - continue; - } - - WCHAR* component = buffer + m_PackageRoot.length(); - path = wcschr(component, L'\\'); - if (path) - { - *path = L'\0'; - ++path; - } - else - { - if (_wcsicmp(component, m_PackageFormat == PackageFormat::New ? L"RMSKIN.bmp" : L"Rainstaller.bmp") == 0) - { - if (!ExtractCurrentFile(tempFile)) - { - return false; - } - - m_HeaderBitmap = (HBITMAP)LoadImage(nullptr, tempFileSz, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); - DeleteFile(tempFileSz); - } - - continue; - } - - const WCHAR* pos = wcschr(path, L'\\'); - const WCHAR* extension = PathFindExtension(pos ? pos : path); - if (pos) - { - // Component with subfolders - const std::wstring item(path, pos - path); - const WCHAR* itemSz = item.c_str(); - - if (_wcsicmp(component, L"Skins") == 0 && - !IsIgnoredSkin(itemSz)) - { - m_PackageSkins.insert(item); - } - else if (_wcsicmp(component, m_PackageFormat == PackageFormat::New ? L"Layouts" : L"Themes") == 0 && - _wcsicmp(extension, m_PackageFormat == PackageFormat::New ? L".ini" : L".thm") == 0 && - !IsIgnoredLayout(itemSz)) - { - m_PackageLayouts.insert(item); - } - else if (_wcsicmp(component, L"Addons") == 0 && - m_PackageFormat == PackageFormat::Old && - !IsIgnoredAddon(itemSz)) - { - m_PackageAddons.insert(item); - } - else if (_wcsicmp(component, L"Plugins") == 0 && - _wcsicmp(itemSz, IsWin32Build() ? L"32bit" : L"64bit") == 0 && - _wcsicmp(extension, L".dll") == 0 && - !wcschr(pos + 1, L'\\')) - { - const std::wstring plugin(pos + 1); - if (!IsIgnoredPlugin(plugin.c_str())) - { - m_PackagePlugins.insert(plugin); - } - } - } - else - { - // Component with subfiles - const std::wstring item = path; - const WCHAR* itemSz = item.c_str(); - - if (_wcsicmp(component, L"Fonts") == 0 && - m_PackageFormat == PackageFormat::Old && - _wcsicmp(extension, L".ttf") == 0) - { - m_PackageFonts.insert(item); - } - } - } - while (unzGoToNextFile(m_PackageUnzFile) == UNZ_OK); - - if (m_PackageSkins.empty()) - { - // Fonts can be installed only with skins - m_PackageFonts.clear(); - } - - return !(m_PackageSkins.empty() && m_PackageLayouts.empty() && - m_PackageAddons.empty() && m_PackageFonts.empty() && m_PackagePlugins.empty()); -} - -bool DialogInstall::ReadOptions(const WCHAR* file) -{ - WCHAR buffer[MAX_LINE_LENGTH]; - - const bool newFormat = m_PackageFormat == PackageFormat::New; - const WCHAR* section = newFormat ? L"rmskin" : L"Rainstaller"; - - const HWND window = m_TabInstall.GetWindow(); - - if (GetPrivateProfileString(section, L"Name", L"", buffer, 64, file) == 0) - { - return false; - } - Static_SetText(GetDlgItem(window, IDC_INSTALLTAB_NAME_TEXT), buffer); - - if (!newFormat) - { - // Determine if skins need to backed up based on name - int s; - int scanned = swscanf(buffer, L"Backup-%d.%d.%d-%d.%d.rmskin", &s, &s, &s, &s, &s); - m_BackupPackage = scanned == 5; - } - - GetPrivateProfileString(section, L"Author", L"", buffer, 64, file); - Static_SetText(GetDlgItem(window, IDC_INSTALLTAB_AUTHOR_TEXT), buffer); - - GetPrivateProfileString(section, L"Version", L"", buffer, 64, file); - Static_SetText(GetDlgItem(window, IDC_INSTALLTAB_VERSION_TEXT), buffer); - - m_MergeSkins = GetPrivateProfileInt(section, newFormat ? L"MergeSkins" : L"Merge", 0, file) != 0; - - GetPrivateProfileString(section, newFormat ? L"VariableFiles" : L"KeepVar", L"", buffer, MAX_LINE_LENGTH, file); - m_VariablesFiles = Tokenize(buffer, L"|"); - - if (GetPrivateProfileString(section, newFormat ? L"MinimumRainmeter" : L"MinRainmeterVer", L"", buffer, MAX_LINE_LENGTH, file) > 0) - { - std::wstring rainmeterDll = g_Data.programPath + L"Rainmeter.dll"; - std::wstring rainmeterVersion = GetFileVersionString(rainmeterDll.c_str()); - if (CompareVersions(buffer, rainmeterVersion) == 1) - { - m_ErrorMessage = L"Rainmeter "; - m_ErrorMessage += buffer; - m_ErrorMessage += L" or higher is required to install this package.\n\n" - L"Get the latest version from rainmeter.net and try again."; - return false; - } - } - - if (GetPrivateProfileString(section, newFormat ? L"LoadType" : L"LaunchType", L"", buffer, MAX_LINE_LENGTH, file) > 0) - { - bool loadSkin = _wcsicmp(buffer, newFormat ? L"Skin" : L"Load") == 0; - - GetPrivateProfileString(section, newFormat ? L"Load" : L"LaunchCommand", L"", buffer, MAX_LINE_LENGTH, file); - if (loadSkin) - { - if (newFormat) - { - m_LoadSkins.push_back(buffer); - } - else - { - m_LoadSkins = Tokenize(buffer, L"|"); - } - } - else - { - m_LoadLayout = buffer; - } - } - - if (newFormat) - { - if (GetPrivateProfileString(section, L"MinimumDotNET", L"", buffer, MAX_LINE_LENGTH, file) > 0 && - CompareVersions(buffer, GetDotNetVersionString()) == 1) - { - m_ErrorMessage = L".NET framework "; - m_ErrorMessage += buffer; - m_ErrorMessage += L" or higher is required to install this package."; - return false; - } - - if (GetPrivateProfileString(section, L"MinimumWindows", L"", buffer, MAX_LINE_LENGTH, file) > 0 && - CompareVersions(buffer, GetWindowsVersionString()) == 1) - { - m_ErrorMessage = L"Your version of Windows is not supported by this package.\n\n" - L"Contact the package author for more information."; - return false; - } - } - - return true; -} - -bool DialogInstall::InstallPackage() -{ - if ((!m_MergeSkins && m_BackupSkins) || m_BackupPackage) - { - // Move skins into backup folder - for (auto iter = m_PackageSkins.cbegin(); iter != m_PackageSkins.cend(); ++iter) - { - std::wstring from = g_Data.skinsPath + *iter; - if (_waccess(from.c_str(), 0) == -1) - { - continue; - } - - SHFILEOPSTRUCT fo = - { - nullptr, - FO_DELETE, - nullptr, - nullptr, - FOF_NO_UI | FOF_NOCONFIRMATION | FOF_ALLOWUNDO - }; - - if (m_BackupPackage) - { - // Remove current skin - from += L'\0'; - fo.pFrom = from.c_str(); - SHFileOperation(&fo); - } - else - { - std::wstring to = g_Data.skinsPath + L"@Backup\\"; - CreateDirectory(to.c_str(), nullptr); - - // Delete current backup - to += *iter; - to += L'\0'; - fo.pFrom = to.c_str(); - SHFileOperation(&fo); - - if (!CopyFiles(from, to, true)) - { - m_ErrorMessage = L"Unable to move to:\n"; - m_ErrorMessage += to; - return false; - } - } - } - } - - WCHAR buffer[MAX_PATH]; - - // Helper to sets buffer with current file name - auto getFileInfo = [&]()->bool - { - char cBuffer[MAX_PATH * 3]; - unz_file_info ufi; - if (unzGetCurrentFileInfo( - m_PackageUnzFile, &ufi, cBuffer, _countof(cBuffer), nullptr, 0, nullptr, 0) == UNZ_OK) - { - const uLong ZIP_UTF8_FLAG = 1 << 11; - const DWORD codePage = (ufi.flag & ZIP_UTF8_FLAG) ? CP_UTF8 : CP_ACP; - MultiByteToWideChar(codePage, 0, cBuffer, strlen(cBuffer) + 1, buffer, MAX_PATH); - while (WCHAR* pos = wcschr(buffer, L'/')) *pos = L'\\'; - return true; - } - - return false; - }; - - unzGoToFirstFile(m_PackageUnzFile); - const WCHAR* root = m_PackageRoot.c_str(); - do - { - if (!getFileInfo()) - { - m_ErrorMessage = L"Error retrieving file info."; - return false; - } - - if (wcsncmp(buffer, root, m_PackageRoot.length()) != 0) - { - // Ignore everything that isn't in the root directory - continue; - } - - WCHAR* component = buffer + m_PackageRoot.length(); - WCHAR* path = wcschr(component, L'\\'); - if (path) - { - *path = L'\0'; - ++path; - } - else - { - continue; - } - - bool error = false; - std::wstring targetPath; - - WCHAR* pos = wcschr(path, L'\\'); - WCHAR* extension = PathFindExtension(pos ? pos : path); - if (pos) - { - const std::wstring item(path, pos - path); - - if (_wcsicmp(component, L"Skins") == 0 && - m_PackageSkins.find(item) != m_PackageSkins.end()) - { - targetPath = g_Data.skinsPath; - } - else if (_wcsicmp(component, L"Addons") == 0 && - m_PackageFormat == PackageFormat::Old && - m_PackageAddons.find(item) != m_PackageAddons.end()) - { - targetPath = g_Data.settingsPath; - targetPath += L"Addons\\"; - } - else if (_wcsicmp(component, L"Plugins") == 0 && - _wcsnicmp(path, IsWin32Build() ? L"32bit" : L"64bit", pos - path) == 0 && - _wcsicmp(extension, L".dll") == 0 && - !wcschr(pos + 1, L'\\')) - { - const std::wstring plugin(pos + 1); - if (m_PackagePlugins.find(plugin) != m_PackagePlugins.end()) - { - path = pos + 1; - targetPath = g_Data.settingsPath; - targetPath += L"Plugins\\"; - } - } - - if (!targetPath.empty()) - { - targetPath += path; - error = !ExtractCurrentFile(targetPath); - } - else if (_wcsicmp(component, m_PackageFormat == PackageFormat::New ? L"Layouts" : L"Themes") == 0 && - _wcsicmp(extension, m_PackageFormat == PackageFormat::New ? L".ini" : L".thm") == 0 && - m_PackageLayouts.find(item) != m_PackageLayouts.end()) - { - if (m_PackageFormat == PackageFormat::Old) - { - wcscpy_s(extension, 5, L".ini"); - } - - targetPath = g_Data.settingsPath; - targetPath += L"Layouts\\"; - targetPath += path; - error = !ExtractCurrentFile(targetPath); - if (!error) - { - CleanLayoutFile(targetPath.c_str()); - } - } - } - else - { - if (_wcsicmp(component, L"Fonts") == 0 && - m_PackageFormat == PackageFormat::Old && - _wcsicmp(extension, L".ttf") == 0) - { - for (auto iter = m_PackageSkins.cbegin(); iter != m_PackageSkins.cend(); ++iter) - { - targetPath = g_Data.skinsPath; - targetPath += *iter; - targetPath += L"\\@Resources\\Fonts\\"; - targetPath += path; - error = !ExtractCurrentFile(targetPath); - if (error) - { - break; - } - } - } - } - - if (error) - { - m_ErrorMessage = L"Unable to create file:\n"; - m_ErrorMessage += targetPath; - m_ErrorMessage += L"\n\nSkin Installer will now quit."; - return false; - } - } - while (unzGoToNextFile(m_PackageUnzFile) == UNZ_OK); - - if (!m_MergeSkins && m_BackupSkins) - { - KeepVariables(); - } - - return true; -} - -void DialogInstall::BeginInstall() -{ - HWND item = GetDlgItem(m_Window, IDC_INSTALL_ADVANCED_BUTTON); - EnableWindow(item, FALSE); - - item = GetDlgItem(m_Window, IDC_INSTALL_INSTALL_BUTTON); - EnableWindow(item, FALSE); - - item = GetDlgItem(m_Window, IDCANCEL); - EnableWindow(item, FALSE); - - item = GetDlgItem(m_TabInstall.GetWindow(), IDC_INSTALLTAB_THEME_CHECKBOX); - if (Button_GetCheck(item) == BST_UNCHECKED) - { - m_LoadLayout.clear(); - m_LoadSkins.clear(); - } - EnableWindow(item, FALSE); - - item = GetDlgItem(m_TabInstall.GetWindow(), IDC_INSTALLTAB_COMPONENTS_LIST); - { - // Remove unchecked items from the component sets - LVITEM lvi; - lvi.mask = LVIF_GROUPID | LVIF_PARAM; - lvi.iSubItem = 0; - lvi.iItem = 0; - - int itemCount = ListView_GetItemCount(item); - for (; lvi.iItem < itemCount; ++lvi.iItem) - { - ListView_GetItem(item, &lvi); - - std::set<std::wstring>* component = nullptr; - switch (lvi.iGroupId) - { - case 0: component = &m_PackageSkins; break; - case 1: component = &m_PackageLayouts; break; - case 2: component = &m_PackageAddons; break; - case 3: component = &m_PackagePlugins; break; - } - - BOOL checked = ListView_GetCheckState(item, lvi.iItem); - if (component && !checked) - { - component->erase(*(std::wstring*)lvi.lParam); - } - } - } - EnableWindow(item, FALSE); - - m_InstallThread = (HANDLE)_beginthreadex(nullptr, 0, InstallThread, this, 0, nullptr); - if (!m_InstallThread) - { - MessageBox(m_Window, L"Unable to start install.", L"Rainmeter Skin Installer", MB_ERROR); - EndDialog(m_Window, 0); - } -} - -UINT __stdcall DialogInstall::InstallThread(void* pParam) -{ - DialogInstall* dialog = (DialogInstall*)pParam; - - if (!CloseRainmeterIfActive()) - { - MessageBox(dialog->m_Window, L"Unable to close Rainmeter.", L"Rainmeter Skin Installer", MB_ERROR); - } - else - { - HWND progressText = GetDlgItem(dialog->m_TabInstall.GetWindow(), IDC_INSTALLTAB_INPROGRESS_TEXT); - ShowWindow(progressText, SW_SHOWNORMAL); - - HWND progressBar = GetDlgItem(dialog->m_TabInstall.GetWindow(), IDC_INSTALLTAB_PROGRESS); - ShowWindow(progressBar, SW_SHOWNORMAL); - SendMessage(progressBar, PBM_SETMARQUEE, (WPARAM)TRUE, 0); - - if (!dialog->InstallPackage()) - { - ShowWindow(progressText, SW_HIDE); - ShowWindow(progressBar, SW_HIDE); - - if (dialog->m_ErrorMessage.empty()) - { - dialog->m_ErrorMessage = L"Unknown error."; - } - dialog->m_ErrorMessage += L"\n\nClick OK to close Skin Installer."; - - MessageBox(dialog->m_Window, dialog->m_ErrorMessage.c_str(), L"Rainmeter Skin Installer", MB_ERROR); - - dialog->m_LoadSkins.clear(); - dialog->m_LoadLayout.clear(); - } - - dialog->LaunchRainmeter(); - } - - EndDialog(dialog->GetWindow(), 0); - return 0; -} - -void DialogInstall::KeepVariables() -{ - WCHAR keyname[32767]; // Max size returned by GetPrivateProfileSection - WCHAR buffer[4]; - std::wstring currKey, currValue; - - for (int i = 0, isize = m_VariablesFiles.size(); i < isize; ++i) - { - std::wstring fromPath = g_Data.skinsPath + L"@Backup\\"; - fromPath += m_VariablesFiles[i]; - std::wstring toPath = g_Data.skinsPath + m_VariablesFiles[i]; - - unsigned int count = GetPrivateProfileSection(L"Variables", keyname, 32767, fromPath.c_str()); - - if ((_waccess(fromPath.c_str(), 0) == 0) && (_waccess(toPath.c_str(), 0) == 0) - && (count > 0)) - { - for (unsigned int j = 0; j < count; ++j) - { - if (keyname[j] == L'=') - { - if (GetPrivateProfileString(L"Variables", currKey.c_str(), nullptr, buffer, 4, toPath.c_str()) > 0) - { - while (keyname[++j] != L'\0') currValue += keyname[j]; - WritePrivateProfileString(L"Variables", currKey.c_str(), currValue.c_str(), toPath.c_str()); - currValue.clear(); - } - else - { - while (keyname[j] != L'\0') ++j; - } - currKey.clear(); - } - else - { - currKey += keyname[j]; - } - } - } - } -} - -void DialogInstall::LaunchRainmeter() -{ - // Execute Rainmeter and wait up to a minute for it process all messages - std::wstring rainmeterExe = g_Data.programPath + L"Rainmeter.exe"; - std::wstring args; - if (!m_LoadLayout.empty()) - { - args += L"!LoadLayout \""; - args += m_LoadLayout; - args += L'"'; - } - - SHELLEXECUTEINFO sei = {0}; - sei.cbSize = sizeof(SHELLEXECUTEINFO); - sei.fMask = SEE_MASK_WAITFORINPUTIDLE | SEE_MASK_UNICODE; - sei.lpFile = rainmeterExe.c_str(); - sei.lpParameters = args.c_str(); - sei.lpDirectory = g_Data.programPath.c_str(); - sei.nShow = SW_SHOWNORMAL; - ShellExecuteEx(&sei); - - if (!m_LoadSkins.empty()) - { - std::wstring::size_type pos; - std::wstring bang; - - for (int i = 0, isize = (int)m_LoadSkins.size(); i < isize; ++i) - { - const std::wstring& skinName = m_LoadSkins[i]; - pos = skinName.find_last_of(L"\\"); - if (pos != std::wstring::npos) - { - // Append with [!ActivateConfig "Config" "File.ini"] - bang += L"[!ActivateConfig \""; - bang.append(skinName, 0, pos); - bang += L"\" \"";; - bang.append(skinName, pos + 1, skinName.length() - pos + 1); - bang += L"\"]"; - } - } - - if (!bang.empty()) - { - sei.fMask = SEE_MASK_UNICODE; - sei.lpParameters = (LPCTSTR)bang.c_str(); - ShellExecuteEx(&sei); - } - } -} - -void DialogInstall::CleanLayoutFile(const WCHAR* file) -{ - // Clear the [Rainmeter] section. - WritePrivateProfileSection(L"Rainmeter", L"", file); - - // Remove the UseD2D key from all sections. - WCHAR buffer[4096]; - if (GetPrivateProfileSectionNames(buffer, _countof(buffer), file) > 0) - { - const WCHAR* section = buffer; - size_t sectionLength = 0; - while ((sectionLength = wcslen(section)) > 0) - { - WritePrivateProfileString(section, L"UseD2D", nullptr, file); - section += sectionLength + 1; - } - } -} - -// Helper for the IsIgnore... functions. -bool IsIgnoredName(const WCHAR* name, const WCHAR* names[], int namesCount) -{ - for (int i = 0; i < namesCount; ++i) - { - if (_wcsicmp(name, names[i]) == 0) - { - return true; - } - } - - return false; -} - -bool DialogInstall::IsIgnoredSkin(const WCHAR* name) -{ - static const WCHAR* s_Skins[] = - { - L"Backup", - L"@Backup" - }; - - return IsIgnoredName(name, s_Skins, _countof(s_Skins)); -} - -bool DialogInstall::IsIgnoredLayout(const WCHAR* name) -{ - static const WCHAR* s_Layouts[] = - { - L"Backup", - L"@Backup" - }; - - return IsIgnoredName(name, s_Layouts, _countof(s_Layouts)); -} - -bool DialogInstall::IsIgnoredAddon(const WCHAR* name) -{ - static const WCHAR* s_Addons[] = - { - L"Backup", - L"Rainstaller", - L"RainBackup" - }; - - return IsIgnoredName(name, s_Addons, _countof(s_Addons)); -} - -bool DialogInstall::IsIgnoredPlugin(const WCHAR* name) -{ - static const WCHAR* s_Plugins[] = - { - L"AdvancedCPU.dll", - L"CoreTemp.dll", - L"FileView.dll", - L"FolderInfo.dll", - L"InputText.dll", - L"iTunesPlugin.dll", - L"MediaKey.dll", - L"NowPlaying.dll", - L"PerfMon.dll", - L"PingPlugin.dll", - L"PowerPlugin.dll", - L"Process.dll", - L"QuotePlugin.dll", - L"RecycleManager.dll", - L"ResMon.dll", - L"SpeedFanPlugin.dll", - L"SysInfo.dll", - L"VirtualDesktops.dll", - L"WebParser.dll", - L"WifiStatus.dll", - L"Win7AudioPlugin.dll", - L"WindowMessagePlugin.dll" - }; - - return IsIgnoredName(name, s_Plugins, _countof(s_Plugins)); -} - -/* -** Splits the string from the delimiters and trims whitespace. -*/ -std::vector<std::wstring> DialogInstall::Tokenize(const std::wstring& str, const std::wstring& delimiters) -{ - // Modified from http://www.digitalpeer.com/id/simple - std::vector<std::wstring> tokens; - std::wstring::size_type lastPos = str.find_first_not_of(delimiters, 0); // Skip delimiters at beginning - std::wstring::size_type pos = str.find_first_of(delimiters, lastPos); // Find first "non-delimiter" - - while (std::wstring::npos != pos || std::wstring::npos != lastPos) - { - std::wstring tmpStr = str.substr(lastPos, pos - lastPos); - std::wstring::size_type tmpPos = tmpStr.find_first_not_of(L" \t"); - if (tmpPos != std::wstring::npos) - { - tmpStr.erase(0, tmpPos); - tmpPos = tmpStr.find_last_not_of(L" \t"); - if (tmpPos != std::wstring::npos) - { - tmpStr.resize(tmpPos + 1); - } - tokens.push_back(tmpStr); - } - else - { - tokens.push_back(L""); // Add empty string - } - lastPos = str.find_first_not_of(delimiters, pos); // Skip delimiters. Note the "not_of" - pos = str.find_first_of(delimiters, lastPos); // Find next "non-delimiter" - } - - return tokens; -} - -/* -** Compares two version strings. Returns 0 if equal, 1 if A > B and -1 if A < B. -*/ -int DialogInstall::CompareVersions(const std::wstring& strA, const std::wstring& strB) -{ - if (strA.empty() && strB.empty()) return 0; - if (strA.empty()) return -1; - if (strB.empty()) return 1; - - std::vector<std::wstring> arrayA = Tokenize(strA, L"."); - std::vector<std::wstring> arrayB = Tokenize(strB, L"."); - - size_t len = max(arrayA.size(), arrayB.size()); - for (size_t i = 0; i < len; ++i) - { - int a = 0; - int b = 0; - - if (i < arrayA.size()) - { - a = _wtoi(arrayA[i].c_str()); - } - if (i < arrayB.size()) - { - b = _wtoi(arrayB[i].c_str()); - } - - if (a > b) return 1; - if (a < b) return -1; - } - return 0; -} - -bool DialogInstall::CreateDirectoryRecursive(const std::wstring& path) -{ - // Dirty... - std::wstring& directory = (std::wstring&)path; - const WCHAR* directorySz = directory.c_str(); - - bool failed = true; - std::wstring::size_type pos = std::wstring::npos; - while ((pos = failed ? directory.find_last_of(L'\\', pos) : directory.find_first_of(L'\\', pos)) != std::wstring::npos) - { - // Temporarily terminate string - directory[pos] = L'\0'; - - failed = CreateDirectory(directorySz, nullptr) == 0 && GetLastError() == ERROR_PATH_NOT_FOUND; - - // Restore slash - directory[pos] = L'\\'; - - pos += failed ? -1 : 1; - } - - return !failed; -} - -std::wstring DialogInstall::GetFileVersionString(const WCHAR* fileName) -{ - DWORD bufSize = GetFileVersionInfoSize(fileName, 0); - void* versionInfo = new WCHAR[bufSize]; - void* fileVersion = 0; - UINT valueSize; - std::wstring result; - - if (GetFileVersionInfo(fileName, 0, bufSize, versionInfo)) - { - struct LANGANDCODEPAGE - { - WORD wLanguage; - WORD wCodePage; - } *languageInfo; - - VerQueryValue(versionInfo, L"\\VarFileInfo\\Translation", (LPVOID*)&languageInfo, &valueSize); - WCHAR blockName[64]; - _snwprintf_s(blockName, _TRUNCATE, L"\\StringFileInfo\\%04x%04x\\FileVersion", languageInfo[0].wLanguage, languageInfo[0].wCodePage); - - VerQueryValue(versionInfo, blockName, &fileVersion, &valueSize); - if (valueSize) - { - result = (WCHAR*)fileVersion; - } - } - - delete [] (WCHAR*)versionInfo; - return result; -} - -std::wstring DialogInstall::GetDotNetVersionString() -{ - WCHAR buffer[255]; - HKEY hKey; - LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP", 0L, KEY_READ, &hKey); - std::wstring currVer(L"v0"), prevVer; - int i = 0; - - while (lRet == ERROR_SUCCESS) - { - lRet = RegEnumKey(hKey, i, buffer, 255); - if (buffer[0] == L'v') - { - currVer = buffer; - } - ++i; - } - - RegCloseKey(hKey); - currVer.erase(0, 1); // Get rid of the 'v' - return currVer; -} - -std::wstring DialogInstall::GetWindowsVersionString() -{ - WCHAR buffer[16]; - OSVERSIONINFOEX osvi = {sizeof(OSVERSIONINFOEX)}; - GetVersionEx((OSVERSIONINFO*)&osvi); - _snwprintf_s(buffer, _TRUNCATE, L"%d.%d.%d", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber); - - return buffer; -} - -// ----------------------------------------------------------------------------------------------- -// -// Install tab -// -// ----------------------------------------------------------------------------------------------- - -/* -** Constructor. -** -*/ -DialogInstall::TabInstall::TabInstall(HWND wnd) : Tab(GetInstanceHandle(), wnd, IDD_INSTALL_TAB, DlgProc) -{ -} - -void DialogInstall::TabInstall::Initialize() -{ - HWND item = GetDlgItem(m_Window, IDC_INSTALLTAB_COMPONENTS_LIST); - - DWORD extendedFlags = LVS_EX_CHECKBOXES | LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT; - - if (GetOSPlatform() >= OSPLATFORM_VISTA) - { - extendedFlags |= LVS_EX_DOUBLEBUFFER; - SetWindowTheme(item, L"explorer", nullptr); - } - - ListView_EnableGroupView(item, TRUE); - ListView_SetExtendedListViewStyleEx(item, 0, extendedFlags); - - // Add columns - LVCOLUMN lvc; - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - lvc.fmt = LVCFMT_LEFT; - lvc.iSubItem = 0; - lvc.cx = 180; - lvc.pszText = L"Name"; - ListView_InsertColumn(item, 0, &lvc); - lvc.iSubItem = 1; - lvc.cx = 150; - lvc.pszText = L"Action"; - ListView_InsertColumn(item, 1, &lvc); - - // Add groups and items - LVGROUP lvg; - lvg.cbSize = sizeof(LVGROUP); - lvg.mask = LVGF_HEADER | LVGF_GROUPID | LVGF_STATE; - lvg.state = (GetOSPlatform() >= OSPLATFORM_VISTA) ? LVGS_COLLAPSIBLE : LVGS_NORMAL; - - LVITEM lvi; - lvi.mask = LVIF_TEXT | LVIF_GROUPID | LVIF_PARAM; - lvi.iSubItem = 0; - - auto addComponent = [&](const WCHAR* name, const std::set<std::wstring>& items, const std::wstring& path, int groupId) - { - lvg.iGroupId = groupId; - lvg.pszHeader = (WCHAR*)name; - ListView_InsertGroup(item, groupId, &lvg); - - lvi.iGroupId = groupId; - lvi.iItem = 0; - for (auto iter = items.cbegin(); iter != items.cend(); ++iter) - { - lvi.pszText = (WCHAR*)(*iter).c_str(); - lvi.lParam = (LPARAM)&(*iter); - ListView_InsertItem(item, &lvi); - ListView_SetCheckState(item, lvi.iItem, TRUE); - - std::wstring itemPath = path + *iter; - WCHAR* text = L"Add"; - if (_waccess(itemPath.c_str(), 0) != -1) - { - bool backup = groupId == 0 && c_Dialog->m_BackupSkins && !c_Dialog->m_BackupPackage; - text = backup ? L"Backup and replace" : L"Replace"; - } - ListView_SetItemText(item, lvi.iItem, 1, text); - - ++lvi.iItem; - } - }; - - addComponent(L"Skins", c_Dialog->m_PackageSkins, g_Data.skinsPath, 0); - addComponent(L"Layouts", c_Dialog->m_PackageLayouts, g_Data.settingsPath + L"Layouts\\", 1); - addComponent(L"Addons", c_Dialog->m_PackageAddons, g_Data.settingsPath + L"Addons\\", 2); - addComponent(L"Plugins", c_Dialog->m_PackagePlugins, g_Data.settingsPath + L"Plugins\\", 3); - - item = GetDlgItem(m_Window, IDC_INSTALLTAB_THEME_CHECKBOX); - if (!c_Dialog->m_LoadLayout.empty()) - { - Button_SetCheck(item, BST_CHECKED); - } - else if (!c_Dialog->m_LoadSkins.empty()) - { - SetWindowText(item, L"Load included skins"); - Button_SetCheck(item, BST_CHECKED); - } - else - { - ShowWindow(item, SW_HIDE); - } - - m_Initialized = true; -} - -INT_PTR CALLBACK DialogInstall::TabInstall::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - return FALSE; -} +/* + Copyright (C) 2012 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "SkinInstaller.h" +#include "DialogInstall.h" +#include "resource.h" +#include "../Version.h" + +#define WM_DELAYED_CLOSE WM_APP + 0 + +extern GlobalData g_Data; + +DialogInstall* DialogInstall::c_Dialog = nullptr; + +inline bool IsWin32Build() +{ +#ifdef _WIN64 + return false; +#else + return true; +#endif +} + +/* +** Constructor. +** +*/ +DialogInstall::DialogInstall(HWND wnd, const WCHAR* file) : Dialog(wnd), + m_TabInstall(wnd), + m_HeaderBitmap(), + m_InstallThread(), + m_PackageUnzFile(), + m_PackageFileName(file), + m_PackageFormat(PackageFormat::Old), + m_BackupPackage(false), + m_BackupSkins(true), + m_MergeSkins(false), + m_SystemFonts(false) +{ +} + +/* +** Destructor. +** +*/ +DialogInstall::~DialogInstall() +{ + if (m_PackageUnzFile) + { + unzClose(m_PackageUnzFile); + } +} + +/* +** Creates the dialog. +** +*/ +void DialogInstall::Create(HINSTANCE hInstance, LPWSTR lpCmdLine) +{ + // Prompt to select .rmskin file if needed + WCHAR buffer[MAX_PATH]; + if (!*lpCmdLine) + { + buffer[0] = L'\0'; + + OPENFILENAME ofn = {0}; + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.lpstrFilter = L"Rainmeter skin file (.rmskin)\0*.rmskin;*.zip"; + ofn.nFilterIndex = 1; + ofn.lpstrFile = buffer; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrTitle = L"Select Rainmeter skin file"; + ofn.lpstrDefExt = L"rmskin"; + ofn.Flags = OFN_FILEMUSTEXIST; + + if (!GetOpenFileName(&ofn)) + { + return; + } + + lpCmdLine = buffer; + } + + HANDLE hMutex; + if (IsRunning(L"Rainmeter Skin Installer", &hMutex)) + { + HWND hwnd = FindWindow(L"#32770", L"Rainmeter Skin Installer"); + SetForegroundWindow(hwnd); + } + else + { + DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_INSTALL_DIALOG), nullptr, (DLGPROC)DlgProc, (LPARAM)lpCmdLine); + ReleaseMutex(hMutex); + } +} + +Dialog::Tab& DialogInstall::GetActiveTab() +{ + return m_TabInstall; +} + +INT_PTR CALLBACK DialogInstall::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (!c_Dialog) + { + if (uMsg == WM_INITDIALOG) + { + c_Dialog = new DialogInstall(hWnd, (const WCHAR*)lParam); + return c_Dialog->OnInitDialog(wParam, lParam); + } + } + else + { + switch (uMsg) + { + case WM_COMMAND: + return c_Dialog->OnCommand(wParam, lParam); + + case WM_CLOSE: + if (!c_Dialog->m_InstallThread) + { + EndDialog(hWnd, 0); + } + return TRUE; + + case WM_DESTROY: + delete c_Dialog; + c_Dialog = nullptr; + return FALSE; + } + } + + return FALSE; +} + +INT_PTR DialogInstall::OnInitDialog(WPARAM wParam, LPARAM lParam) +{ + HICON hIcon = (HICON)LoadImage(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDI_SKININSTALLER), IMAGE_ICON, 16, 16, LR_SHARED); + SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); + + if (GetOSPlatform() >= OSPLATFORM_VISTA) + { + SetDialogFont(); + } + + HWND item = GetDlgItem(m_Window, IDC_INSTALL_ADVANCED_BUTTON); + Dialog::SetMenuButton(item); + + if (ReadPackage()) + { + item = GetDlgItem(m_Window, IDC_INSTALL_HEADER_BITMAP); + if (m_HeaderBitmap) + { + SendMessage(item, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)m_HeaderBitmap); + } + else + { + RECT r; + GetClientRect(item, &r); + ShowWindow(item, SW_HIDE); + int yDiff = r.bottom; + + // Move all controls on the main dialog up to "fill" header area. + int controlIds[] = { IDC_INSTALL_TAB, IDC_INSTALL_ADVANCED_BUTTON, IDC_INSTALL_INSTALL_BUTTON, IDCANCEL, 0 }; + for (int i = 0; i < _countof(controlIds); ++i) + { + HWND control = controlIds[i] ? GetDlgItem(m_Window, controlIds[i]) : m_TabInstall.GetWindow(); + GetWindowRect(control, &r); + MapWindowPoints(nullptr, m_Window, (POINT*)&r, sizeof(RECT) / sizeof(POINT)); + MoveWindow(control, r.left, r.top - yDiff, r.right - r.left, r.bottom - r.top, TRUE); + } + + // Remove blank area at the bottom of the dialog and center it. + GetWindowRect(m_Window, &r); + MoveWindow(m_Window, r.left, r.top + (yDiff / 2), r.right - r.left, r.bottom - r.top - yDiff, TRUE); + } + + m_TabInstall.Activate(); + } + else + { + if (m_ErrorMessage.empty()) + { + m_ErrorMessage = L"Invalid package:\n"; + m_ErrorMessage += PathFindFileName(m_PackageFileName.c_str()); + m_ErrorMessage += L"\n\nThe Skin Packager tool must be used to create valid .rmskin packages."; + } + + MessageBox(nullptr, m_ErrorMessage.c_str(), L"Rainmeter Skin Installer", MB_ERROR); + EndDialog(m_Window, 0); + } + + + return TRUE; +} + +INT_PTR DialogInstall::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_INSTALL_ADVANCED_BUTTON: + { + RECT r; + GetWindowRect((HWND)lParam, &r); + HMENU menu = LoadMenu(GetInstanceHandle(), MAKEINTRESOURCE(IDR_INSTALL_MENU)); + HMENU subMenu = GetSubMenu(menu, 0); + + if (m_PackageSkins.empty() || m_MergeSkins || m_BackupPackage) + { + EnableMenuItem(subMenu, IDM_INSTALL_BACKUPSKINS, MF_BYCOMMAND | MF_GRAYED); + } + else + { + CheckMenuItem(subMenu, IDM_INSTALL_BACKUPSKINS, (m_BackupSkins ? MF_CHECKED : MF_UNCHECKED) | MF_BYCOMMAND); + } + + if (m_PackageFonts.empty()) + { + EnableMenuItem(subMenu, IDM_INSTALL_SYSTEMFONTS, MF_BYCOMMAND | MF_GRAYED); + } + else + { + CheckMenuItem(subMenu, IDM_INSTALL_SYSTEMFONTS, (m_SystemFonts ? MF_CHECKED : MF_UNCHECKED) | MF_BYCOMMAND); + } + + const WCHAR* formatName = m_PackageFormat == PackageFormat::New ? L"New format" : L"Old format"; + ModifyMenu(subMenu, IDM_INSTALL_FORMAT, MF_STRING | MF_GRAYED | MF_BYCOMMAND, IDM_INSTALL_FORMAT, formatName); + + TrackPopupMenu( + subMenu, + TPM_RIGHTBUTTON | TPM_LEFTALIGN, + r.left, + --r.bottom, + 0, + m_Window, + nullptr); + + DestroyMenu(menu); + } + break; + + case IDC_INSTALL_INSTALL_BUTTON: + BeginInstall(); + break; + + case IDCANCEL: + if (!m_InstallThread) + { + EndDialog(m_Window, 0); + } + break; + + case IDM_INSTALL_BACKUPSKINS: + m_BackupSkins = !m_BackupSkins; + break; + + case IDM_INSTALL_SYSTEMFONTS: + m_SystemFonts = !m_SystemFonts; + break; + + default: + return FALSE; + } + + return TRUE; +} + +INT_PTR DialogInstall::OnNotify(WPARAM wParam, LPARAM lParam) +{ + LPNMHDR nm = (LPNMHDR)lParam; + switch (nm->code) + { + case BCN_DROPDOWN: + { + NMHDR* hdr = &((NMBCDROPDOWN*)lParam)->hdr; + + // Unpush the drop-down button part and simulate click + Button_SetDropDownState(hdr->hwndFrom, FALSE); + SendMessage(hdr->hwndFrom, BM_CLICK, 0, 0); + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +bool DialogInstall::ExtractCurrentFile(const std::wstring& fileName) +{ + // Some archives don't explicity list directories, so create them recursively + if (!CreateDirectoryRecursive(fileName)) + { + return false; + } + + if (fileName.back() == L'\\') + { + // Nothing left to do + return true; + } + + if (unzOpenCurrentFile(m_PackageUnzFile) != UNZ_OK) + { + return false; + } + + HANDLE hFile = CreateFile(fileName.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + if (hFile == INVALID_HANDLE_VALUE) + { + return false; + } + + int read; + do + { + BYTE buffer[16384]; + DWORD written; + read = unzReadCurrentFile(m_PackageUnzFile, buffer, 16384); + if (read < 0 || !WriteFile(hFile, (LPCVOID)buffer, read, &written, nullptr) || read != written) + { + read = UNZ_ERRNO; + break; + } + } + while (read != UNZ_EOF); + + CloseHandle(hFile); + + return unzCloseCurrentFile(m_PackageUnzFile) == UNZ_OK && read == UNZ_EOF; +} + +bool DialogInstall::ReadPackage() +{ + const WCHAR* fileName = m_PackageFileName.c_str(); + const WCHAR* fileExtension = PathFindExtension(fileName); + + if (_wcsicmp(fileExtension, L".rmskin") == 0) + { + // Check if the footer is present (for new .rmskin format) + PackageFooter footer = {0}; + + FILE* file = _wfopen(fileName, L"rb"); + __int64 fileSize = 0; + if (file) + { + fseek(file, -(long)sizeof(footer), SEEK_END); + fileSize = _ftelli64(file); + fread(&footer, sizeof(footer), 1, file); + fclose(file); + } + + if (strcmp(footer.key, "RMSKIN") == 0) + { + m_PackageFormat = PackageFormat::New; + if (footer.size != fileSize) + { + return false; + } + + if (footer.flags) + { + m_BackupPackage = !(footer.flags & PackageFlag::Backup); + } + } + } + else if (_wcsicmp(fileExtension, L".zip") != 0) + { + return false; + } + + m_PackageUnzFile = unzOpen(ConvertToAscii(fileName).c_str()); + if (!m_PackageUnzFile) + { + return false; + } + + WCHAR buffer[MAX_PATH]; + + // Get temporary file to extract the options file and header bitmap + GetTempPath(MAX_PATH, buffer); + GetTempFileName(buffer, L"dat", 0, buffer); + std::wstring tempFile = buffer; + const WCHAR* tempFileSz = tempFile.c_str(); + + // Helper to sets buffer with current file name + auto getFileInfo = [&]()->bool + { + char cBuffer[MAX_PATH * 3]; + unz_file_info ufi; + if (unzGetCurrentFileInfo( + m_PackageUnzFile, &ufi, cBuffer, _countof(cBuffer), nullptr, 0, nullptr, 0) == UNZ_OK) + { + const uLong ZIP_UTF8_FLAG = 1 << 11; + const DWORD codePage = (ufi.flag & ZIP_UTF8_FLAG) ? CP_UTF8 : CP_ACP; + MultiByteToWideChar(codePage, 0, cBuffer, strlen(cBuffer) + 1, buffer, MAX_PATH); + while (WCHAR* pos = wcschr(buffer, L'/')) *pos = L'\\'; + return true; + } + + return false; + }; + + // Loop through the contents of the archive until the settings file is found + WCHAR* path; + bool optionsFound = false; + do + { + if (!getFileInfo()) + { + return false; + } + + path = wcsrchr(buffer, L'\\'); + if (!path) + { + path = buffer; + } + else + { + if (m_PackageFormat == PackageFormat::New) + { + // New package files must be in root of archive + continue; + } + + ++path; // Skip slash + } + + if (_wcsicmp(path, m_PackageFormat == PackageFormat::New ? L"RMSKIN.ini" : L"Rainstaller.cfg") == 0) + { + if (ExtractCurrentFile(tempFile)) + { + optionsFound = ReadOptions(tempFileSz); + DeleteFile(tempFileSz); + } + + break; + } + } + while (unzGoToNextFile(m_PackageUnzFile) == UNZ_OK); + + if (!optionsFound) + { + return false; + } + + // Loop through the archive a second time and find included components + unzGoToFirstFile(m_PackageUnzFile); + + m_PackageRoot.assign(buffer, path - buffer); + const WCHAR* root = m_PackageRoot.c_str(); + do + { + if (!getFileInfo()) + { + return false; + } + + if (wcsncmp(buffer, root, m_PackageRoot.length()) != 0) + { + // Ignore everything that isn't in the root directory + continue; + } + + WCHAR* component = buffer + m_PackageRoot.length(); + path = wcschr(component, L'\\'); + if (path) + { + *path = L'\0'; + ++path; + } + else + { + if (_wcsicmp(component, m_PackageFormat == PackageFormat::New ? L"RMSKIN.bmp" : L"Rainstaller.bmp") == 0) + { + if (!ExtractCurrentFile(tempFile)) + { + return false; + } + + m_HeaderBitmap = (HBITMAP)LoadImage(nullptr, tempFileSz, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); + DeleteFile(tempFileSz); + } + + continue; + } + + const WCHAR* pos = wcschr(path, L'\\'); + const WCHAR* extension = PathFindExtension(pos ? pos : path); + if (pos) + { + // Component with subfolders + const std::wstring item(path, pos - path); + const WCHAR* itemSz = item.c_str(); + + if (_wcsicmp(component, L"Skins") == 0 && + !IsIgnoredSkin(itemSz)) + { + m_PackageSkins.insert(item); + } + else if (_wcsicmp(component, m_PackageFormat == PackageFormat::New ? L"Layouts" : L"Themes") == 0 && + _wcsicmp(extension, m_PackageFormat == PackageFormat::New ? L".ini" : L".thm") == 0 && + !IsIgnoredLayout(itemSz)) + { + m_PackageLayouts.insert(item); + } + else if (_wcsicmp(component, L"Addons") == 0 && + m_PackageFormat == PackageFormat::Old && + !IsIgnoredAddon(itemSz)) + { + m_PackageAddons.insert(item); + } + else if (_wcsicmp(component, L"Plugins") == 0 && + _wcsicmp(itemSz, IsWin32Build() ? L"32bit" : L"64bit") == 0 && + _wcsicmp(extension, L".dll") == 0 && + !wcschr(pos + 1, L'\\')) + { + const std::wstring plugin(pos + 1); + if (!IsIgnoredPlugin(plugin.c_str())) + { + m_PackagePlugins.insert(plugin); + } + } + } + else + { + // Component with subfiles + const std::wstring item = path; + const WCHAR* itemSz = item.c_str(); + + if (_wcsicmp(component, L"Fonts") == 0 && + m_PackageFormat == PackageFormat::Old && + _wcsicmp(extension, L".ttf") == 0) + { + m_PackageFonts.insert(item); + } + } + } + while (unzGoToNextFile(m_PackageUnzFile) == UNZ_OK); + + if (m_PackageSkins.empty()) + { + // Fonts can be installed only with skins + m_PackageFonts.clear(); + } + + return !(m_PackageSkins.empty() && m_PackageLayouts.empty() && + m_PackageAddons.empty() && m_PackageFonts.empty() && m_PackagePlugins.empty()); +} + +bool DialogInstall::ReadOptions(const WCHAR* file) +{ + WCHAR buffer[MAX_LINE_LENGTH]; + + const bool newFormat = m_PackageFormat == PackageFormat::New; + const WCHAR* section = newFormat ? L"rmskin" : L"Rainstaller"; + + const HWND window = m_TabInstall.GetWindow(); + + if (GetPrivateProfileString(section, L"Name", L"", buffer, 64, file) == 0) + { + return false; + } + Static_SetText(GetDlgItem(window, IDC_INSTALLTAB_NAME_TEXT), buffer); + + if (!newFormat) + { + // Determine if skins need to backed up based on name + int s; + int scanned = swscanf(buffer, L"Backup-%d.%d.%d-%d.%d.rmskin", &s, &s, &s, &s, &s); + m_BackupPackage = scanned == 5; + } + + GetPrivateProfileString(section, L"Author", L"", buffer, 64, file); + Static_SetText(GetDlgItem(window, IDC_INSTALLTAB_AUTHOR_TEXT), buffer); + + GetPrivateProfileString(section, L"Version", L"", buffer, 64, file); + Static_SetText(GetDlgItem(window, IDC_INSTALLTAB_VERSION_TEXT), buffer); + + m_MergeSkins = GetPrivateProfileInt(section, newFormat ? L"MergeSkins" : L"Merge", 0, file) != 0; + + GetPrivateProfileString(section, newFormat ? L"VariableFiles" : L"KeepVar", L"", buffer, MAX_LINE_LENGTH, file); + m_VariablesFiles = Tokenize(buffer, L"|"); + + if (GetPrivateProfileString(section, newFormat ? L"MinimumRainmeter" : L"MinRainmeterVer", L"", buffer, MAX_LINE_LENGTH, file) > 0) + { + std::wstring rainmeterDll = g_Data.programPath + L"Rainmeter.dll"; + std::wstring rainmeterVersion = GetFileVersionString(rainmeterDll.c_str()); + if (CompareVersions(buffer, rainmeterVersion) == 1) + { + m_ErrorMessage = L"Rainmeter "; + m_ErrorMessage += buffer; + m_ErrorMessage += L" or higher is required to install this package.\n\n" + L"Get the latest version from rainmeter.net and try again."; + return false; + } + } + + if (GetPrivateProfileString(section, newFormat ? L"LoadType" : L"LaunchType", L"", buffer, MAX_LINE_LENGTH, file) > 0) + { + bool loadSkin = _wcsicmp(buffer, newFormat ? L"Skin" : L"Load") == 0; + + GetPrivateProfileString(section, newFormat ? L"Load" : L"LaunchCommand", L"", buffer, MAX_LINE_LENGTH, file); + if (loadSkin) + { + if (newFormat) + { + m_LoadSkins.push_back(buffer); + } + else + { + m_LoadSkins = Tokenize(buffer, L"|"); + } + } + else + { + m_LoadLayout = buffer; + } + } + + if (newFormat) + { + if (GetPrivateProfileString(section, L"MinimumDotNET", L"", buffer, MAX_LINE_LENGTH, file) > 0 && + CompareVersions(buffer, GetDotNetVersionString()) == 1) + { + m_ErrorMessage = L".NET framework "; + m_ErrorMessage += buffer; + m_ErrorMessage += L" or higher is required to install this package."; + return false; + } + + if (GetPrivateProfileString(section, L"MinimumWindows", L"", buffer, MAX_LINE_LENGTH, file) > 0 && + CompareVersions(buffer, GetWindowsVersionString()) == 1) + { + m_ErrorMessage = L"Your version of Windows is not supported by this package.\n\n" + L"Contact the package author for more information."; + return false; + } + } + + return true; +} + +bool DialogInstall::InstallPackage() +{ + if ((!m_MergeSkins && m_BackupSkins) || m_BackupPackage) + { + // Move skins into backup folder + for (auto iter = m_PackageSkins.cbegin(); iter != m_PackageSkins.cend(); ++iter) + { + std::wstring from = g_Data.skinsPath + *iter; + if (_waccess(from.c_str(), 0) == -1) + { + continue; + } + + SHFILEOPSTRUCT fo = + { + nullptr, + FO_DELETE, + nullptr, + nullptr, + FOF_NO_UI | FOF_NOCONFIRMATION | FOF_ALLOWUNDO + }; + + if (m_BackupPackage) + { + // Remove current skin + from += L'\0'; + fo.pFrom = from.c_str(); + SHFileOperation(&fo); + } + else + { + std::wstring to = g_Data.skinsPath + L"@Backup\\"; + CreateDirectory(to.c_str(), nullptr); + + // Delete current backup + to += *iter; + to += L'\0'; + fo.pFrom = to.c_str(); + SHFileOperation(&fo); + + if (!CopyFiles(from, to, true)) + { + m_ErrorMessage = L"Unable to move to:\n"; + m_ErrorMessage += to; + return false; + } + } + } + } + + WCHAR buffer[MAX_PATH]; + + // Helper to sets buffer with current file name + auto getFileInfo = [&]()->bool + { + char cBuffer[MAX_PATH * 3]; + unz_file_info ufi; + if (unzGetCurrentFileInfo( + m_PackageUnzFile, &ufi, cBuffer, _countof(cBuffer), nullptr, 0, nullptr, 0) == UNZ_OK) + { + const uLong ZIP_UTF8_FLAG = 1 << 11; + const DWORD codePage = (ufi.flag & ZIP_UTF8_FLAG) ? CP_UTF8 : CP_ACP; + MultiByteToWideChar(codePage, 0, cBuffer, strlen(cBuffer) + 1, buffer, MAX_PATH); + while (WCHAR* pos = wcschr(buffer, L'/')) *pos = L'\\'; + return true; + } + + return false; + }; + + unzGoToFirstFile(m_PackageUnzFile); + const WCHAR* root = m_PackageRoot.c_str(); + do + { + if (!getFileInfo()) + { + m_ErrorMessage = L"Error retrieving file info."; + return false; + } + + if (wcsncmp(buffer, root, m_PackageRoot.length()) != 0) + { + // Ignore everything that isn't in the root directory + continue; + } + + WCHAR* component = buffer + m_PackageRoot.length(); + WCHAR* path = wcschr(component, L'\\'); + if (path) + { + *path = L'\0'; + ++path; + } + else + { + continue; + } + + bool error = false; + std::wstring targetPath; + + WCHAR* pos = wcschr(path, L'\\'); + WCHAR* extension = PathFindExtension(pos ? pos : path); + if (pos) + { + const std::wstring item(path, pos - path); + + if (_wcsicmp(component, L"Skins") == 0 && + m_PackageSkins.find(item) != m_PackageSkins.end()) + { + targetPath = g_Data.skinsPath; + } + else if (_wcsicmp(component, L"Addons") == 0 && + m_PackageFormat == PackageFormat::Old && + m_PackageAddons.find(item) != m_PackageAddons.end()) + { + targetPath = g_Data.settingsPath; + targetPath += L"Addons\\"; + } + else if (_wcsicmp(component, L"Plugins") == 0 && + _wcsnicmp(path, IsWin32Build() ? L"32bit" : L"64bit", pos - path) == 0 && + _wcsicmp(extension, L".dll") == 0 && + !wcschr(pos + 1, L'\\')) + { + const std::wstring plugin(pos + 1); + if (m_PackagePlugins.find(plugin) != m_PackagePlugins.end()) + { + path = pos + 1; + targetPath = g_Data.settingsPath; + targetPath += L"Plugins\\"; + } + } + + if (!targetPath.empty()) + { + targetPath += path; + error = !ExtractCurrentFile(targetPath); + } + else if (_wcsicmp(component, m_PackageFormat == PackageFormat::New ? L"Layouts" : L"Themes") == 0 && + _wcsicmp(extension, m_PackageFormat == PackageFormat::New ? L".ini" : L".thm") == 0 && + m_PackageLayouts.find(item) != m_PackageLayouts.end()) + { + if (m_PackageFormat == PackageFormat::Old) + { + wcscpy_s(extension, 5, L".ini"); + } + + targetPath = g_Data.settingsPath; + targetPath += L"Layouts\\"; + targetPath += path; + error = !ExtractCurrentFile(targetPath); + if (!error) + { + CleanLayoutFile(targetPath.c_str()); + } + } + } + else + { + if (_wcsicmp(component, L"Fonts") == 0 && + m_PackageFormat == PackageFormat::Old && + _wcsicmp(extension, L".ttf") == 0) + { + for (auto iter = m_PackageSkins.cbegin(); iter != m_PackageSkins.cend(); ++iter) + { + targetPath = g_Data.skinsPath; + targetPath += *iter; + targetPath += L"\\@Resources\\Fonts\\"; + targetPath += path; + error = !ExtractCurrentFile(targetPath); + if (error) + { + break; + } + } + } + } + + if (error) + { + m_ErrorMessage = L"Unable to create file:\n"; + m_ErrorMessage += targetPath; + m_ErrorMessage += L"\n\nSkin Installer will now quit."; + return false; + } + } + while (unzGoToNextFile(m_PackageUnzFile) == UNZ_OK); + + if (!m_MergeSkins && m_BackupSkins) + { + KeepVariables(); + } + + return true; +} + +void DialogInstall::BeginInstall() +{ + HWND item = GetDlgItem(m_Window, IDC_INSTALL_ADVANCED_BUTTON); + EnableWindow(item, FALSE); + + item = GetDlgItem(m_Window, IDC_INSTALL_INSTALL_BUTTON); + EnableWindow(item, FALSE); + + item = GetDlgItem(m_Window, IDCANCEL); + EnableWindow(item, FALSE); + + item = GetDlgItem(m_TabInstall.GetWindow(), IDC_INSTALLTAB_THEME_CHECKBOX); + if (Button_GetCheck(item) == BST_UNCHECKED) + { + m_LoadLayout.clear(); + m_LoadSkins.clear(); + } + EnableWindow(item, FALSE); + + item = GetDlgItem(m_TabInstall.GetWindow(), IDC_INSTALLTAB_COMPONENTS_LIST); + { + // Remove unchecked items from the component sets + LVITEM lvi; + lvi.mask = LVIF_GROUPID | LVIF_PARAM; + lvi.iSubItem = 0; + lvi.iItem = 0; + + int itemCount = ListView_GetItemCount(item); + for (; lvi.iItem < itemCount; ++lvi.iItem) + { + ListView_GetItem(item, &lvi); + + std::set<std::wstring>* component = nullptr; + switch (lvi.iGroupId) + { + case 0: component = &m_PackageSkins; break; + case 1: component = &m_PackageLayouts; break; + case 2: component = &m_PackageAddons; break; + case 3: component = &m_PackagePlugins; break; + } + + BOOL checked = ListView_GetCheckState(item, lvi.iItem); + if (component && !checked) + { + component->erase(*(std::wstring*)lvi.lParam); + } + } + } + EnableWindow(item, FALSE); + + m_InstallThread = (HANDLE)_beginthreadex(nullptr, 0, InstallThread, this, 0, nullptr); + if (!m_InstallThread) + { + MessageBox(m_Window, L"Unable to start install.", L"Rainmeter Skin Installer", MB_ERROR); + EndDialog(m_Window, 0); + } +} + +UINT __stdcall DialogInstall::InstallThread(void* pParam) +{ + DialogInstall* dialog = (DialogInstall*)pParam; + + if (!CloseRainmeterIfActive()) + { + MessageBox(dialog->m_Window, L"Unable to close Rainmeter.", L"Rainmeter Skin Installer", MB_ERROR); + } + else + { + HWND progressText = GetDlgItem(dialog->m_TabInstall.GetWindow(), IDC_INSTALLTAB_INPROGRESS_TEXT); + ShowWindow(progressText, SW_SHOWNORMAL); + + HWND progressBar = GetDlgItem(dialog->m_TabInstall.GetWindow(), IDC_INSTALLTAB_PROGRESS); + ShowWindow(progressBar, SW_SHOWNORMAL); + SendMessage(progressBar, PBM_SETMARQUEE, (WPARAM)TRUE, 0); + + if (!dialog->InstallPackage()) + { + ShowWindow(progressText, SW_HIDE); + ShowWindow(progressBar, SW_HIDE); + + if (dialog->m_ErrorMessage.empty()) + { + dialog->m_ErrorMessage = L"Unknown error."; + } + dialog->m_ErrorMessage += L"\n\nClick OK to close Skin Installer."; + + MessageBox(dialog->m_Window, dialog->m_ErrorMessage.c_str(), L"Rainmeter Skin Installer", MB_ERROR); + + dialog->m_LoadSkins.clear(); + dialog->m_LoadLayout.clear(); + } + + dialog->LaunchRainmeter(); + } + + EndDialog(dialog->GetWindow(), 0); + return 0; +} + +void DialogInstall::KeepVariables() +{ + WCHAR keyname[32767]; // Max size returned by GetPrivateProfileSection + WCHAR buffer[4]; + std::wstring currKey, currValue; + + for (int i = 0, isize = m_VariablesFiles.size(); i < isize; ++i) + { + std::wstring fromPath = g_Data.skinsPath + L"@Backup\\"; + fromPath += m_VariablesFiles[i]; + std::wstring toPath = g_Data.skinsPath + m_VariablesFiles[i]; + + unsigned int count = GetPrivateProfileSection(L"Variables", keyname, 32767, fromPath.c_str()); + + if ((_waccess(fromPath.c_str(), 0) == 0) && (_waccess(toPath.c_str(), 0) == 0) + && (count > 0)) + { + for (unsigned int j = 0; j < count; ++j) + { + if (keyname[j] == L'=') + { + if (GetPrivateProfileString(L"Variables", currKey.c_str(), nullptr, buffer, 4, toPath.c_str()) > 0) + { + while (keyname[++j] != L'\0') currValue += keyname[j]; + WritePrivateProfileString(L"Variables", currKey.c_str(), currValue.c_str(), toPath.c_str()); + currValue.clear(); + } + else + { + while (keyname[j] != L'\0') ++j; + } + currKey.clear(); + } + else + { + currKey += keyname[j]; + } + } + } + } +} + +void DialogInstall::LaunchRainmeter() +{ + // Execute Rainmeter and wait up to a minute for it process all messages + std::wstring rainmeterExe = g_Data.programPath + L"Rainmeter.exe"; + std::wstring args; + if (!m_LoadLayout.empty()) + { + args += L"!LoadLayout \""; + args += m_LoadLayout; + args += L'"'; + } + + SHELLEXECUTEINFO sei = {0}; + sei.cbSize = sizeof(SHELLEXECUTEINFO); + sei.fMask = SEE_MASK_WAITFORINPUTIDLE | SEE_MASK_UNICODE; + sei.lpFile = rainmeterExe.c_str(); + sei.lpParameters = args.c_str(); + sei.lpDirectory = g_Data.programPath.c_str(); + sei.nShow = SW_SHOWNORMAL; + ShellExecuteEx(&sei); + + if (!m_LoadSkins.empty()) + { + std::wstring::size_type pos; + std::wstring bang; + + for (int i = 0, isize = (int)m_LoadSkins.size(); i < isize; ++i) + { + const std::wstring& skinName = m_LoadSkins[i]; + pos = skinName.find_last_of(L"\\"); + if (pos != std::wstring::npos) + { + // Append with [!ActivateConfig "Config" "File.ini"] + bang += L"[!ActivateConfig \""; + bang.append(skinName, 0, pos); + bang += L"\" \"";; + bang.append(skinName, pos + 1, skinName.length() - pos + 1); + bang += L"\"]"; + } + } + + if (!bang.empty()) + { + sei.fMask = SEE_MASK_UNICODE; + sei.lpParameters = (LPCTSTR)bang.c_str(); + ShellExecuteEx(&sei); + } + } +} + +void DialogInstall::CleanLayoutFile(const WCHAR* file) +{ + // Clear the [Rainmeter] section. + WritePrivateProfileSection(L"Rainmeter", L"", file); + + // Remove the UseD2D key from all sections. + WCHAR buffer[4096]; + if (GetPrivateProfileSectionNames(buffer, _countof(buffer), file) > 0) + { + const WCHAR* section = buffer; + size_t sectionLength = 0; + while ((sectionLength = wcslen(section)) > 0) + { + WritePrivateProfileString(section, L"UseD2D", nullptr, file); + section += sectionLength + 1; + } + } +} + +// Helper for the IsIgnore... functions. +bool IsIgnoredName(const WCHAR* name, const WCHAR* names[], int namesCount) +{ + for (int i = 0; i < namesCount; ++i) + { + if (_wcsicmp(name, names[i]) == 0) + { + return true; + } + } + + return false; +} + +bool DialogInstall::IsIgnoredSkin(const WCHAR* name) +{ + static const WCHAR* s_Skins[] = + { + L"Backup", + L"@Backup" + }; + + return IsIgnoredName(name, s_Skins, _countof(s_Skins)); +} + +bool DialogInstall::IsIgnoredLayout(const WCHAR* name) +{ + static const WCHAR* s_Layouts[] = + { + L"Backup", + L"@Backup" + }; + + return IsIgnoredName(name, s_Layouts, _countof(s_Layouts)); +} + +bool DialogInstall::IsIgnoredAddon(const WCHAR* name) +{ + static const WCHAR* s_Addons[] = + { + L"Backup", + L"Rainstaller", + L"RainBackup" + }; + + return IsIgnoredName(name, s_Addons, _countof(s_Addons)); +} + +bool DialogInstall::IsIgnoredPlugin(const WCHAR* name) +{ + static const WCHAR* s_Plugins[] = + { + L"AdvancedCPU.dll", + L"CoreTemp.dll", + L"FileView.dll", + L"FolderInfo.dll", + L"InputText.dll", + L"iTunesPlugin.dll", + L"MediaKey.dll", + L"NowPlaying.dll", + L"PerfMon.dll", + L"PingPlugin.dll", + L"PowerPlugin.dll", + L"Process.dll", + L"QuotePlugin.dll", + L"RecycleManager.dll", + L"ResMon.dll", + L"SpeedFanPlugin.dll", + L"SysInfo.dll", + L"VirtualDesktops.dll", + L"WebParser.dll", + L"WifiStatus.dll", + L"Win7AudioPlugin.dll", + L"WindowMessagePlugin.dll" + }; + + return IsIgnoredName(name, s_Plugins, _countof(s_Plugins)); +} + +/* +** Splits the string from the delimiters and trims whitespace. +*/ +std::vector<std::wstring> DialogInstall::Tokenize(const std::wstring& str, const std::wstring& delimiters) +{ + // Modified from http://www.digitalpeer.com/id/simple + std::vector<std::wstring> tokens; + std::wstring::size_type lastPos = str.find_first_not_of(delimiters, 0); // Skip delimiters at beginning + std::wstring::size_type pos = str.find_first_of(delimiters, lastPos); // Find first "non-delimiter" + + while (std::wstring::npos != pos || std::wstring::npos != lastPos) + { + std::wstring tmpStr = str.substr(lastPos, pos - lastPos); + std::wstring::size_type tmpPos = tmpStr.find_first_not_of(L" \t"); + if (tmpPos != std::wstring::npos) + { + tmpStr.erase(0, tmpPos); + tmpPos = tmpStr.find_last_not_of(L" \t"); + if (tmpPos != std::wstring::npos) + { + tmpStr.resize(tmpPos + 1); + } + tokens.push_back(tmpStr); + } + else + { + tokens.push_back(L""); // Add empty string + } + lastPos = str.find_first_not_of(delimiters, pos); // Skip delimiters. Note the "not_of" + pos = str.find_first_of(delimiters, lastPos); // Find next "non-delimiter" + } + + return tokens; +} + +/* +** Compares two version strings. Returns 0 if equal, 1 if A > B and -1 if A < B. +*/ +int DialogInstall::CompareVersions(const std::wstring& strA, const std::wstring& strB) +{ + if (strA.empty() && strB.empty()) return 0; + if (strA.empty()) return -1; + if (strB.empty()) return 1; + + std::vector<std::wstring> arrayA = Tokenize(strA, L"."); + std::vector<std::wstring> arrayB = Tokenize(strB, L"."); + + size_t len = max(arrayA.size(), arrayB.size()); + for (size_t i = 0; i < len; ++i) + { + int a = 0; + int b = 0; + + if (i < arrayA.size()) + { + a = _wtoi(arrayA[i].c_str()); + } + if (i < arrayB.size()) + { + b = _wtoi(arrayB[i].c_str()); + } + + if (a > b) return 1; + if (a < b) return -1; + } + return 0; +} + +bool DialogInstall::CreateDirectoryRecursive(const std::wstring& path) +{ + // Dirty... + std::wstring& directory = (std::wstring&)path; + const WCHAR* directorySz = directory.c_str(); + + bool failed = true; + std::wstring::size_type pos = std::wstring::npos; + while ((pos = failed ? directory.find_last_of(L'\\', pos) : directory.find_first_of(L'\\', pos)) != std::wstring::npos) + { + // Temporarily terminate string + directory[pos] = L'\0'; + + failed = CreateDirectory(directorySz, nullptr) == 0 && GetLastError() == ERROR_PATH_NOT_FOUND; + + // Restore slash + directory[pos] = L'\\'; + + pos += failed ? -1 : 1; + } + + return !failed; +} + +std::wstring DialogInstall::GetFileVersionString(const WCHAR* fileName) +{ + DWORD bufSize = GetFileVersionInfoSize(fileName, 0); + void* versionInfo = new WCHAR[bufSize]; + void* fileVersion = 0; + UINT valueSize; + std::wstring result; + + if (GetFileVersionInfo(fileName, 0, bufSize, versionInfo)) + { + struct LANGANDCODEPAGE + { + WORD wLanguage; + WORD wCodePage; + } *languageInfo; + + VerQueryValue(versionInfo, L"\\VarFileInfo\\Translation", (LPVOID*)&languageInfo, &valueSize); + WCHAR blockName[64]; + _snwprintf_s(blockName, _TRUNCATE, L"\\StringFileInfo\\%04x%04x\\FileVersion", languageInfo[0].wLanguage, languageInfo[0].wCodePage); + + VerQueryValue(versionInfo, blockName, &fileVersion, &valueSize); + if (valueSize) + { + result = (WCHAR*)fileVersion; + } + } + + delete [] (WCHAR*)versionInfo; + return result; +} + +std::wstring DialogInstall::GetDotNetVersionString() +{ + WCHAR buffer[255]; + HKEY hKey; + LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP", 0L, KEY_READ, &hKey); + std::wstring currVer(L"v0"), prevVer; + int i = 0; + + while (lRet == ERROR_SUCCESS) + { + lRet = RegEnumKey(hKey, i, buffer, 255); + if (buffer[0] == L'v') + { + currVer = buffer; + } + ++i; + } + + RegCloseKey(hKey); + currVer.erase(0, 1); // Get rid of the 'v' + return currVer; +} + +std::wstring DialogInstall::GetWindowsVersionString() +{ + WCHAR buffer[16]; + OSVERSIONINFOEX osvi = {sizeof(OSVERSIONINFOEX)}; + GetVersionEx((OSVERSIONINFO*)&osvi); + _snwprintf_s(buffer, _TRUNCATE, L"%d.%d.%d", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber); + + return buffer; +} + +// ----------------------------------------------------------------------------------------------- +// +// Install tab +// +// ----------------------------------------------------------------------------------------------- + +/* +** Constructor. +** +*/ +DialogInstall::TabInstall::TabInstall(HWND wnd) : Tab(GetInstanceHandle(), wnd, IDD_INSTALL_TAB, DlgProc) +{ +} + +void DialogInstall::TabInstall::Initialize() +{ + HWND item = GetDlgItem(m_Window, IDC_INSTALLTAB_COMPONENTS_LIST); + + DWORD extendedFlags = LVS_EX_CHECKBOXES | LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT; + + if (GetOSPlatform() >= OSPLATFORM_VISTA) + { + extendedFlags |= LVS_EX_DOUBLEBUFFER; + SetWindowTheme(item, L"explorer", nullptr); + } + + ListView_EnableGroupView(item, TRUE); + ListView_SetExtendedListViewStyleEx(item, 0, extendedFlags); + + // Add columns + LVCOLUMN lvc; + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.fmt = LVCFMT_LEFT; + lvc.iSubItem = 0; + lvc.cx = 180; + lvc.pszText = L"Name"; + ListView_InsertColumn(item, 0, &lvc); + lvc.iSubItem = 1; + lvc.cx = 150; + lvc.pszText = L"Action"; + ListView_InsertColumn(item, 1, &lvc); + + // Add groups and items + LVGROUP lvg; + lvg.cbSize = sizeof(LVGROUP); + lvg.mask = LVGF_HEADER | LVGF_GROUPID | LVGF_STATE; + lvg.state = (GetOSPlatform() >= OSPLATFORM_VISTA) ? LVGS_COLLAPSIBLE : LVGS_NORMAL; + + LVITEM lvi; + lvi.mask = LVIF_TEXT | LVIF_GROUPID | LVIF_PARAM; + lvi.iSubItem = 0; + + auto addComponent = [&](const WCHAR* name, const std::set<std::wstring>& items, const std::wstring& path, int groupId) + { + lvg.iGroupId = groupId; + lvg.pszHeader = (WCHAR*)name; + ListView_InsertGroup(item, groupId, &lvg); + + lvi.iGroupId = groupId; + lvi.iItem = 0; + for (auto iter = items.cbegin(); iter != items.cend(); ++iter) + { + lvi.pszText = (WCHAR*)(*iter).c_str(); + lvi.lParam = (LPARAM)&(*iter); + ListView_InsertItem(item, &lvi); + ListView_SetCheckState(item, lvi.iItem, TRUE); + + std::wstring itemPath = path + *iter; + WCHAR* text = L"Add"; + if (_waccess(itemPath.c_str(), 0) != -1) + { + bool backup = groupId == 0 && c_Dialog->m_BackupSkins && !c_Dialog->m_BackupPackage; + text = backup ? L"Backup and replace" : L"Replace"; + } + ListView_SetItemText(item, lvi.iItem, 1, text); + + ++lvi.iItem; + } + }; + + addComponent(L"Skins", c_Dialog->m_PackageSkins, g_Data.skinsPath, 0); + addComponent(L"Layouts", c_Dialog->m_PackageLayouts, g_Data.settingsPath + L"Layouts\\", 1); + addComponent(L"Addons", c_Dialog->m_PackageAddons, g_Data.settingsPath + L"Addons\\", 2); + addComponent(L"Plugins", c_Dialog->m_PackagePlugins, g_Data.settingsPath + L"Plugins\\", 3); + + item = GetDlgItem(m_Window, IDC_INSTALLTAB_THEME_CHECKBOX); + if (!c_Dialog->m_LoadLayout.empty()) + { + Button_SetCheck(item, BST_CHECKED); + } + else if (!c_Dialog->m_LoadSkins.empty()) + { + SetWindowText(item, L"Load included skins"); + Button_SetCheck(item, BST_CHECKED); + } + else + { + ShowWindow(item, SW_HIDE); + } + + m_Initialized = true; +} + +INT_PTR CALLBACK DialogInstall::TabInstall::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return FALSE; +} diff --git a/SkinInstaller/DialogInstall.h b/SkinInstaller/DialogInstall.h index 9fbff284..11c0313f 100644 --- a/SkinInstaller/DialogInstall.h +++ b/SkinInstaller/DialogInstall.h @@ -1,132 +1,132 @@ -/* - Copyright (C) 2012 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef SKININSTALLER_DIALOGINSTALL_H_ -#define SKININSTALLER_DIALOGINSTALL_H_ - -#include <string> -#include "unzip.h" -#include "../Library/Dialog.h" - -class DialogInstall : public Dialog -{ -public: - static void Create(HINSTANCE hInstance, LPWSTR lpCmdLine); - - static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - - static DialogInstall* c_Dialog; - -protected: - virtual Tab& GetActiveTab(); - -private: - friend class DialogPackage; - - class TabInstall : public Tab - { - public: - TabInstall(HWND window); - - virtual void Initialize(); - - static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - }; - - enum Timer - { - Thread = 1 - }; - - enum PackageFormat - { - None, - New, - Old - }; - - enum PackageFlag - { - Backup = 0x0001 - }; - - struct PackageFooter - { - __int64 size; - BYTE flags; - char key[7]; - }; - - DialogInstall(HWND wnd, const WCHAR* file); - virtual ~DialogInstall(); - - bool ReadPackage(); - bool ReadOptions(const WCHAR* file); - bool InstallPackage(); - void BeginInstall(); - static UINT __stdcall InstallThread(void* pParam); - bool ExtractCurrentFile(const std::wstring& fileName); - - void LaunchRainmeter(); - void KeepVariables(); - - static void CleanLayoutFile(const WCHAR* file); - - static bool IsIgnoredSkin(const WCHAR* name); - static bool IsIgnoredLayout(const WCHAR* name); - static bool IsIgnoredAddon(const WCHAR* name); - static bool IsIgnoredPlugin(const WCHAR* name); - - static int CompareVersions(const std::wstring& strA, const std::wstring& strB); - static std::vector<std::wstring> Tokenize(const std::wstring& str, const std::wstring& delimiters); - static bool CreateDirectoryRecursive(const std::wstring& path); - static std::wstring GetFileVersionString(const WCHAR* fileName); - static std::wstring GetDotNetVersionString(); - static std::wstring GetWindowsVersionString(); - - TabInstall m_TabInstall; - - HBITMAP m_HeaderBitmap; - - HANDLE m_InstallThread; - - std::wstring m_ErrorMessage; - - unzFile m_PackageUnzFile; - std::wstring m_PackageFileName; - std::wstring m_PackageRoot; - PackageFormat m_PackageFormat; - std::set<std::wstring> m_PackageSkins; - std::set<std::wstring> m_PackageLayouts; - std::set<std::wstring> m_PackageAddons; - std::set<std::wstring> m_PackageFonts; - std::set<std::wstring> m_PackagePlugins; - - bool m_BackupPackage; - bool m_BackupSkins; - bool m_MergeSkins; - bool m_SystemFonts; - std::vector<std::wstring> m_VariablesFiles; - std::vector<std::wstring> m_LoadSkins; - std::wstring m_LoadLayout; -}; - -#endif +/* + Copyright (C) 2012 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef SKININSTALLER_DIALOGINSTALL_H_ +#define SKININSTALLER_DIALOGINSTALL_H_ + +#include <string> +#include "unzip.h" +#include "../Library/Dialog.h" + +class DialogInstall : public Dialog +{ +public: + static void Create(HINSTANCE hInstance, LPWSTR lpCmdLine); + + static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + + static DialogInstall* c_Dialog; + +protected: + virtual Tab& GetActiveTab(); + +private: + friend class DialogPackage; + + class TabInstall : public Tab + { + public: + TabInstall(HWND window); + + virtual void Initialize(); + + static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + }; + + enum Timer + { + Thread = 1 + }; + + enum PackageFormat + { + None, + New, + Old + }; + + enum PackageFlag + { + Backup = 0x0001 + }; + + struct PackageFooter + { + __int64 size; + BYTE flags; + char key[7]; + }; + + DialogInstall(HWND wnd, const WCHAR* file); + virtual ~DialogInstall(); + + bool ReadPackage(); + bool ReadOptions(const WCHAR* file); + bool InstallPackage(); + void BeginInstall(); + static UINT __stdcall InstallThread(void* pParam); + bool ExtractCurrentFile(const std::wstring& fileName); + + void LaunchRainmeter(); + void KeepVariables(); + + static void CleanLayoutFile(const WCHAR* file); + + static bool IsIgnoredSkin(const WCHAR* name); + static bool IsIgnoredLayout(const WCHAR* name); + static bool IsIgnoredAddon(const WCHAR* name); + static bool IsIgnoredPlugin(const WCHAR* name); + + static int CompareVersions(const std::wstring& strA, const std::wstring& strB); + static std::vector<std::wstring> Tokenize(const std::wstring& str, const std::wstring& delimiters); + static bool CreateDirectoryRecursive(const std::wstring& path); + static std::wstring GetFileVersionString(const WCHAR* fileName); + static std::wstring GetDotNetVersionString(); + static std::wstring GetWindowsVersionString(); + + TabInstall m_TabInstall; + + HBITMAP m_HeaderBitmap; + + HANDLE m_InstallThread; + + std::wstring m_ErrorMessage; + + unzFile m_PackageUnzFile; + std::wstring m_PackageFileName; + std::wstring m_PackageRoot; + PackageFormat m_PackageFormat; + std::set<std::wstring> m_PackageSkins; + std::set<std::wstring> m_PackageLayouts; + std::set<std::wstring> m_PackageAddons; + std::set<std::wstring> m_PackageFonts; + std::set<std::wstring> m_PackagePlugins; + + bool m_BackupPackage; + bool m_BackupSkins; + bool m_MergeSkins; + bool m_SystemFonts; + std::vector<std::wstring> m_VariablesFiles; + std::vector<std::wstring> m_LoadSkins; + std::wstring m_LoadLayout; +}; + +#endif diff --git a/SkinInstaller/DialogPackage.cpp b/SkinInstaller/DialogPackage.cpp index 522ccb7c..608aac73 100644 --- a/SkinInstaller/DialogPackage.cpp +++ b/SkinInstaller/DialogPackage.cpp @@ -1,1403 +1,1403 @@ -/* - Copyright (C) 2012 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "../Common/StringUtil.h" -#include "SkinInstaller.h" -#include "DialogPackage.h" -#include "DialogInstall.h" -#include "resource.h" -#include "../Version.h" - -#define WM_DELAYED_CLOSE WM_APP + 0 - -extern GlobalData g_Data; -extern OsNameVersion g_OsNameVersions[]; - -DialogPackage* DialogPackage::c_Dialog = nullptr; - -DialogPackage::DialogPackage(HWND wnd) : Dialog(wnd), - m_TabInfo(wnd), - m_TabOptions(wnd), - m_TabAdvanced(wnd), - m_LoadLayout(false), - m_MergeSkins(false), - m_PackagerThread(), - m_ZipFile(), - m_AllowNonAsciiFilenames(false) -{ -} - -DialogPackage::~DialogPackage() -{ -} - -void DialogPackage::Create(HINSTANCE hInstance, LPWSTR lpCmdLine) -{ - HANDLE hMutex; - if (IsRunning(L"Rainmeter Skin Packager", &hMutex)) - { - HWND hwnd = FindWindow(L"#32770", L"Rainmeter Skin Packager"); - SetForegroundWindow(hwnd); - } - else - { - DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_PACKAGE_DIALOG), nullptr, (DLGPROC)DlgProc, (LPARAM)lpCmdLine); - ReleaseMutex(hMutex); - } -} - -Dialog::Tab& DialogPackage::GetActiveTab() -{ - int sel = TabCtrl_GetCurSel(GetDlgItem(m_Window, IDC_PACKAGE_TAB)); - if (sel == -1) - { - return m_TabInfo; - } - else if (sel == 0) - { - return m_TabOptions; - } - else // if (sel == 1) - { - return m_TabAdvanced; - } -} - -INT_PTR CALLBACK DialogPackage::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (!c_Dialog) - { - if (uMsg == WM_INITDIALOG) - { - c_Dialog = new DialogPackage(hWnd); - return c_Dialog->OnInitDialog(wParam, lParam); - } - } - else - { - switch (uMsg) - { - case WM_COMMAND: - return c_Dialog->OnCommand(wParam, lParam); - - case WM_NOTIFY: - return c_Dialog->OnNotify(wParam, lParam); - - case WM_CLOSE: - { - if (!c_Dialog->m_PackagerThread) - { - EndDialog(hWnd, 0); - } - } - return TRUE; - - case WM_DESTROY: - delete c_Dialog; - c_Dialog = nullptr; - return FALSE; - } - } - - return FALSE; -} - -INT_PTR DialogPackage::OnInitDialog(WPARAM wParam, LPARAM lParam) -{ - HICON hIcon = (HICON)LoadImage(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDI_SKININSTALLER), IMAGE_ICON, 16, 16, LR_SHARED); - SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); - - if (GetOSPlatform() >= OSPLATFORM_VISTA) - { - SetDialogFont(); - } - - m_TabInfo.Activate(); - - return FALSE; -} - -INT_PTR DialogPackage::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_PACKAGE_NEXT_BUTTON: - { - HWND item = GetDlgItem(m_Window, IDC_PACKAGE_TAB); - TCITEM tci = {0}; - tci.mask = TCIF_TEXT; - tci.pszText = L"Options"; - TabCtrl_InsertItem(item, 0, &tci); - tci.pszText = L"Advanced"; - TabCtrl_InsertItem(item, 1, &tci); - - item = GetDlgItem(m_Window, IDC_PACKAGE_NEXT_BUTTON); - ShowWindow(item, SW_HIDE); - - item = GetDlgItem(m_Window, IDC_PACKAGE_CREATEPACKAGE_BUTTON); - ShowWindow(item, SW_SHOWNORMAL); - SendMessage(m_Window, DM_SETDEFID, IDC_PACKAGE_CREATEPACKAGE_BUTTON, 0); - - ShowWindow(m_TabInfo.GetWindow(), SW_HIDE); - - m_TabOptions.Activate(); - } - break; - - case IDC_PACKAGE_CREATEPACKAGE_BUTTON: - { - HWND item = GetDlgItem(m_Window, IDC_PACKAGE_CREATEPACKAGE_BUTTON); - EnableWindow(item, FALSE); - - item = GetDlgItem(m_Window, IDCANCEL); - EnableWindow(item, FALSE); - - m_TabOptions.Activate(); - item = GetDlgItem(m_Window, IDC_PACKAGE_TAB); - TabCtrl_SetCurSel(item, 0); - EnableWindow(item, FALSE); - EnableWindow(m_TabOptions.GetWindow(), FALSE); - EnableWindow(m_TabAdvanced.GetWindow(), FALSE); - - item = GetDlgItem(m_TabOptions.GetWindow(), IDC_INSTALLTAB_CREATING_TEXT); - ShowWindow(item, SW_SHOWNORMAL); - - item = GetDlgItem(m_TabOptions.GetWindow(), IDC_INSTALLTAB_CREATING_BAR); - ShowWindow(item, SW_SHOWNORMAL); - SendMessage(item, PBM_SETMARQUEE, (WPARAM)TRUE, 0); - - m_PackagerThread = (HANDLE)_beginthreadex(nullptr, 0, PackagerThreadProc, this, 0, nullptr); - if (!m_PackagerThread) - { - MessageBox(m_Window, L"Unknown error.", L"Rainmeter Skin Packager", MB_ERROR); - EndDialog(m_Window, 0); - } - } - break; - - case IDCANCEL: - if (!m_PackagerThread) - { - EndDialog(m_Window, 0); - } - break; - - default: - return FALSE; - } - - return TRUE; -} - -INT_PTR DialogPackage::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->idFrom) - { - case IDC_PACKAGE_TAB: - if (nm->code == TCN_SELCHANGE) - { - // Disable all tab windows first - EnableWindow(m_TabInfo.GetWindow(), FALSE); - EnableWindow(m_TabOptions.GetWindow(), FALSE); - EnableWindow(m_TabAdvanced.GetWindow(), FALSE); - - GetActiveTab().Activate(); - } - break; - - default: - return 1; - } - - return 0; -} - -void DialogPackage::SetNextButtonState() -{ - BOOL state = !(m_Name.empty() || m_Author.empty() || m_SkinFolder.second.empty()); - EnableWindow(GetDlgItem(m_Window, IDC_PACKAGE_NEXT_BUTTON), state); -} - -bool DialogPackage::CreatePackage() -{ - // Create options file - WCHAR tempFile[MAX_PATH]; - GetTempPath(MAX_PATH, tempFile); - GetTempFileName(tempFile, L"ini", 0, tempFile); - - WritePrivateProfileString(L"rmskin", L"Name", m_Name.c_str(), tempFile); - WritePrivateProfileString(L"rmskin", L"Author", m_Author.c_str(), tempFile); - WritePrivateProfileString(L"rmskin", L"Version", m_Version.c_str(), tempFile); - - if (!c_Dialog->m_Load.empty()) - { - WritePrivateProfileString(L"rmskin", L"LoadType", c_Dialog->m_LoadLayout ? L"Layout" : L"Skin", tempFile); - WritePrivateProfileString(L"rmskin", L"Load", c_Dialog->m_Load.c_str(), tempFile); - } - - if (!c_Dialog->m_VariableFiles.empty()) - { - WritePrivateProfileString(L"rmskin", L"VariableFiles", m_VariableFiles.c_str(), tempFile); - } - - if (c_Dialog->m_MergeSkins) - { - WritePrivateProfileString(L"rmskin", L"MergeSkins", L"1", tempFile); - } - - WritePrivateProfileString(L"rmskin", L"MinimumRainmeter", m_MinimumRainmeter.c_str(), tempFile); - WritePrivateProfileString(L"rmskin", L"MinimumWindows", m_MinimumWindows.c_str(), tempFile); - - // Only Skin Installer in Rainmeter 3.0.1 support UTF-8 filenames. - m_AllowNonAsciiFilenames = DialogInstall::CompareVersions(m_MinimumRainmeter, L"3.0.1") != -1; - - // Create archive and add options file and header bitmap - m_ZipFile = zipOpen(ConvertToAscii(m_TargetFile.c_str()).c_str(), APPEND_STATUS_CREATE); - - auto cleanup = [&]()->bool - { - zipClose(m_ZipFile, nullptr); - DeleteFile(m_TargetFile.c_str()); - return false; - }; - - if (!m_ZipFile || - (!c_Dialog->m_HeaderFile.empty() && !AddFileToPackage(c_Dialog->m_HeaderFile.c_str(), L"RMSKIN.bmp")) || - !AddFileToPackage(tempFile, L"RMSKIN.ini")) - { - std::wstring error = L"Unable to create package."; - error += L"\n\nClick OK to close Packager."; - MessageBox(m_Window, error.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONERROR); - DeleteFile(tempFile); - return cleanup(); - } - - // Add skin - { - std::wstring zipPrefix = L"Skins\\" + m_SkinFolder.first; - zipPrefix += L'\\'; - if (!AddFolderToPackage(m_SkinFolder.second, L"", zipPrefix.c_str())) - { - return cleanup(); - } - } - - // Add layouts - for (auto iter = m_LayoutFolders.cbegin(); iter != m_LayoutFolders.cend(); ++iter) - { - std::wstring realPath = (*iter).second + L"Rainmeter.ini"; - std::wstring zipPath = L"Layouts\\" + (*iter).first; - zipPath += L"\\Rainmeter.ini"; - if (!AddFileToPackage(realPath.c_str(), zipPath.c_str())) - { - std::wstring error = L"Error adding layout '"; - error += (*iter).first; - error += L"'."; - error += L"\n\nClick OK to close Packager."; - MessageBox(m_Window, error.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONERROR); - return cleanup(); - } - } - - // Add plugins - for (auto iter = m_PluginFolders.cbegin(); iter != m_PluginFolders.cend(); ++iter) - { - // Add 32bit and 64bit versions - for (int i = 0; i < 2; ++i) - { - const std::wstring& realPath = (i == 0) ? (*iter).second.first : (*iter).second.second; - std::wstring zipPath = ((i == 0) ? L"Plugins\\32bit\\" : L"Plugins\\64bit\\") + (*iter).first; - if (!AddFileToPackage(realPath.c_str(), zipPath.c_str())) - { - std::wstring error = L"Error adding plugin '"; - error += (*iter).first; - error += L"'."; - error += L"\n\nClick OK to close Packager."; - MessageBox(m_Window, error.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONERROR); - return cleanup(); - } - } - } - - // Add footer - FILE* file; - if (zipClose(m_ZipFile, nullptr) == ZIP_OK && - (file = _wfopen(m_TargetFile.c_str(), L"r+b")) != nullptr) - { - fseek(file, 0, SEEK_END); - DialogInstall::PackageFooter footer = { _ftelli64(file), 0, "RMSKIN" }; - fwrite(&footer, sizeof(footer), 1, file); - fclose(file); - } - else - { - std::wstring error = L"Unable to create package."; - error += L"\n\nClick OK to close Packager."; - MessageBox(m_Window, error.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONERROR); - return false; - } - - return true; -} - -unsigned __stdcall DialogPackage::PackagerThreadProc(void* pParam) -{ - DialogPackage* dialog = (DialogPackage*)pParam; - - if (dialog->CreatePackage()) - { - // Stop the progress bar - HWND item = GetDlgItem(dialog->m_TabOptions.GetWindow(), IDC_INSTALLTAB_CREATING_BAR); - SendMessage(item, PBM_SETMARQUEE, (WPARAM)FALSE, 0); - - FlashWindow(dialog->m_Window, TRUE); - - std::wstring message = L"The skin package has been successfully created."; - message += L"\n\nClick OK to close Packager."; - MessageBox(c_Dialog->GetWindow(), message.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONINFORMATION); - } - else - { - DeleteFile(dialog->m_TargetFile.c_str()); - } - - EndDialog(dialog->m_Window, 0); - - return 0; -} - -bool DialogPackage::AddFileToPackage(const WCHAR* filePath, const WCHAR* zipPath) -{ - std::string zipPathUTF8 = StringUtil::NarrowUTF8(zipPath); - for (int i = 0, isize = zipPathUTF8.length(); i < isize; ++i) - { - if ((zipPathUTF8[i] & 0x80) != 0) - { - // UTF-8 lead bit is not zero so the string is non-ASCII. - if (!m_AllowNonAsciiFilenames) - { - return false; - } - } - - if (zipPathUTF8[i] == '\\') - { - zipPathUTF8[i] = '/'; - } - } - - const uLong ZIP_UTF8_FLAG = 1 << 11; - zip_fileinfo fi = {0}; - if (zipOpenNewFileInZip4( - m_ZipFile, zipPathUTF8.c_str(), &fi, - nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, Z_DEFAULT_COMPRESSION, - 0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0, 0, ZIP_UTF8_FLAG) != ZIP_OK) - { - return false; - } - - bool result = true; - - if (filePath) - { - HANDLE file = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - if (file == INVALID_HANDLE_VALUE) - { - result = false; - } - else - { - do - { - const DWORD bufferSize = 16 * 1024; - BYTE buffer[bufferSize]; - DWORD readSize; - if (!ReadFile(file, buffer, bufferSize, &readSize, nullptr)) - { - result = false; - } - else if (readSize != 0) - { - result = zipWriteInFileInZip(m_ZipFile, buffer, (UINT)readSize) == ZIP_OK; - } - else - { - // EOF - break; - } - } - while (result); - - CloseHandle(file); - } - } - else - { - // Directory entry, so nothing needs to be written. - } - - return zipCloseFileInZip(m_ZipFile) == ZIP_OK && result; -} - -bool DialogPackage::AddFolderToPackage(const std::wstring& path, std::wstring base, const WCHAR* zipPrefix) -{ - std::wstring currentPath = path + base; - currentPath += L'*'; - - WIN32_FIND_DATA fd; - HANDLE hFind = FindFirstFileEx( - currentPath.c_str(), - FindExInfoStandard, - &fd, - FindExSearchNameMatch, - nullptr, - 0); - - if (hFind == INVALID_HANDLE_VALUE) - { - return false; - } - - currentPath.pop_back(); // Remove * - - bool result = true; - bool filesAdded = false; - std::list<std::wstring> folders; - do - { - if (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) - { - // Ignore hidden files and folders - continue; - } - - if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - if (!(fd.cFileName[0] == L'.' && (!fd.cFileName[1] || fd.cFileName[1] == L'.' && !fd.cFileName[2]))) - { - folders.push_back(fd.cFileName); - } - } - else - { - std::wstring filePath = currentPath + fd.cFileName; - std::wstring zipPath = zipPrefix; - zipPath.append(filePath, path.length(), filePath.length() - path.length()); - - result = AddFileToPackage(filePath.c_str(), zipPath.c_str()); - if (!result) - { - std::wstring error = L"Error adding file:\n"; - error += filePath; - error += L"\n\nClick OK to close Packager."; - MessageBox(m_Window, error.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONERROR); - break; - } - - filesAdded = true; - } - } - while (FindNextFile(hFind, &fd)); - FindClose(hFind); - - if (result) - { - if (!filesAdded && folders.empty()) - { - // Add directory entry if folder is empty. - std::wstring zipPath = zipPrefix; - zipPath.append(currentPath, path.length(), currentPath.length() - path.length()); - AddFileToPackage(nullptr, zipPath.c_str()); - } - - std::list<std::wstring>::const_iterator iter = folders.begin(); - for ( ; iter != folders.end(); ++iter) - { - std::wstring newBase = base + (*iter); - newBase += L'\\'; - result = AddFolderToPackage(path, newBase, zipPrefix); - if (!result) break; - } - } - - return result; -} - -void DialogPackage::ShowHelp() -{ - std::wstring url = L"http://rainmeter.net/cms/UsingApplication-SkinPackager"; - if (revision_beta) - { - url += L"_beta"; - } - - ShellExecute(m_Window, L"open", url.c_str(), nullptr, nullptr, SW_SHOWNORMAL); -} - -std::wstring DialogPackage::SelectFolder(HWND parent, const std::wstring& existingPath) -{ - LPCWSTR dialog = MAKEINTRESOURCE(IDD_PACKAGESELECTFOLDER_DIALOG); - std::wstring folder = existingPath; - if (DialogBoxParam(GetInstanceHandle(), dialog, parent, SelectFolderDlgProc, (LPARAM)&folder) != 1) - { - folder.clear(); - } - return folder; -} - -INT_PTR CALLBACK DialogPackage::SelectFolderDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_INITDIALOG: - { - EnableThemeDialogTexture(hWnd, ETDT_ENABLETAB); - c_Dialog->SetDialogFont(hWnd); - - std::wstring* existingPath = (std::wstring*)lParam; - SetWindowLongPtr(hWnd, GWLP_USERDATA, lParam); - - *existingPath += L'*'; - WIN32_FIND_DATA fd; - HANDLE hFind = FindFirstFileEx(existingPath->c_str(), FindExInfoStandard, &fd, FindExSearchNameMatch, nullptr, 0); - existingPath->pop_back(); - - if (hFind != INVALID_HANDLE_VALUE) - { - const WCHAR* folder = PathFindFileName(existingPath->c_str()); - - HWND item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_EXISTING_RADIO); - std::wstring text = L"Add folder from "; - text.append(folder, wcslen(folder) - 1); - text += L':'; - SetWindowText(item, text.c_str()); - Button_SetCheck(item, BST_CHECKED); - - item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_EXISTING_COMBO); - - do - { - if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && - !(fd.cFileName[0] == L'.' && (!fd.cFileName[1] || fd.cFileName[1] == L'.' && !fd.cFileName[2])) && - wcscmp(fd.cFileName, L"Backup") != 0 && - wcscmp(fd.cFileName, L"@Backup") != 0) - { - ComboBox_InsertString(item, -1, fd.cFileName); - } - } - while (FindNextFile(hFind, &fd)); - - ComboBox_SetCurSel(item, 0); - - FindClose(hFind); - } - } - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_PACKAGESELECTFOLDER_EXISTING_RADIO: - { - HWND item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_EXISTING_COMBO); - EnableWindow(item, TRUE); - int sel = ComboBox_GetCurSel(item); - item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT); - EnableWindow(item, FALSE); - item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_CUSTOMBROWSE_BUTTON); - EnableWindow(item, FALSE); - - item = GetDlgItem(hWnd, IDOK); - EnableWindow(item, sel != -1); - } - break; - - case IDC_PACKAGESELECTFOLDER_CUSTOM_RADIO: - { - HWND item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_EXISTING_COMBO); - EnableWindow(item, FALSE); - item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT); - EnableWindow(item, TRUE); - item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_CUSTOMBROWSE_BUTTON); - EnableWindow(item, TRUE); - - SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT, EN_CHANGE), 0); - } - break; - - case IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT: - if (HIWORD(wParam) == EN_CHANGE) - { - WCHAR buffer[MAX_PATH]; - int len = Edit_GetText((HWND)lParam, buffer, MAX_PATH); - - // Disable Add button if invalid directory - DWORD attributes = GetFileAttributes(buffer); - BOOL state = (attributes != INVALID_FILE_ATTRIBUTES && - attributes & FILE_ATTRIBUTE_DIRECTORY); - EnableWindow(GetDlgItem(hWnd, IDOK), state); - } - break; - - case IDC_PACKAGESELECTFOLDER_CUSTOMBROWSE_BUTTON: - { - WCHAR buffer[MAX_PATH]; - BROWSEINFO bi = {0}; - bi.hwndOwner = hWnd; - bi.ulFlags = BIF_USENEWUI | BIF_NONEWFOLDERBUTTON | BIF_RETURNONLYFSDIRS; - - PIDLIST_ABSOLUTE pidl = SHBrowseForFolder(&bi); - if (pidl && SHGetPathFromIDList(pidl, buffer)) - { - HWND item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT); - SetWindowText(item, buffer); - CoTaskMemFree(pidl); - } - } - break; - - case IDOK: - { - WCHAR buffer[MAX_PATH]; - HWND item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_EXISTING_RADIO); - bool existing = Button_GetCheck(item) == BST_CHECKED; - - item = GetDlgItem(hWnd, existing ? IDC_PACKAGESELECTFOLDER_EXISTING_COMBO : IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT); - GetWindowText(item, buffer, _countof(buffer)); - - std::wstring* result = (std::wstring*)GetWindowLongPtr(hWnd, GWLP_USERDATA); - - if (existing) - { - *result += buffer; - } - else - { - *result = buffer; - } - *result += L'\\'; - - EndDialog(hWnd, 1); - } - } - break; - - case WM_CLOSE: - EndDialog(hWnd, 0); - break; - - default: - return FALSE; - } - - return TRUE; -} - -std::pair<std::wstring, std::wstring> DialogPackage::SelectPlugin(HWND parent) -{ - LPCWSTR dialog = MAKEINTRESOURCE(IDD_PACKAGESELECTPLUGIN_DIALOG); - std::pair<std::wstring, std::wstring> plugins; - if (DialogBoxParam(GetInstanceHandle(), dialog, parent, SelectPluginDlgProc, (LPARAM)&plugins) != 1) - { - plugins.first.clear(); - plugins.second.clear(); - } - return plugins; -} - -INT_PTR CALLBACK DialogPackage::SelectPluginDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_INITDIALOG: - { - EnableThemeDialogTexture(hWnd, ETDT_ENABLETAB); - c_Dialog->SetDialogFont(hWnd); - - auto plugins = (std::pair<std::wstring, std::wstring>*)lParam; - SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)plugins); - } - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_PACKAGESELECTPLUGIN_32BITBROWSE_BUTTON: - case IDC_PACKAGESELECTPLUGIN_64BITBROWSE_BUTTON: - { - WCHAR buffer[MAX_PATH]; - buffer[0] = L'\0'; - - OPENFILENAME ofn = { sizeof(OPENFILENAME) }; - ofn.Flags = OFN_FILEMUSTEXIST; - ofn.lpstrFilter = L"Plugins (.dll)\0*.dll"; - ofn.lpstrTitle = L"Select plugin file"; - ofn.lpstrDefExt = L"dll"; - ofn.nFilterIndex = 0; - ofn.lpstrFile = buffer; - ofn.nMaxFile = _countof(buffer); - ofn.hwndOwner = c_Dialog->GetWindow(); - - if (!GetOpenFileName(&ofn)) - { - break; - } - - bool x32 = LOWORD(wParam) == IDC_PACKAGESELECTPLUGIN_32BITBROWSE_BUTTON; - - LOADED_IMAGE* loadedImage = ImageLoad(ConvertToAscii(buffer).c_str(), nullptr); - if (loadedImage) - { - WORD machine = loadedImage->FileHeader->FileHeader.Machine; - ImageUnload(loadedImage); - - if ((x32 && machine == IMAGE_FILE_MACHINE_I386) || (!x32 && machine == IMAGE_FILE_MACHINE_AMD64)) - { - // Check if same name as other DLL - auto plugins = (std::pair<std::wstring, std::wstring>*)GetWindowLongPtr(hWnd, GWLP_USERDATA); - const WCHAR* otherName = PathFindFileName(x32 ? plugins->second.c_str() : plugins->first.c_str()); - if (*otherName && _wcsicmp(otherName, PathFindFileName(buffer)) != 0) - { - MessageBox(hWnd, L"Plugins must have same name.", L"Rainmeter Skin Packager", MB_OK | MB_TOPMOST); - break; - } - - PathSetDlgItemPath(hWnd, x32 ? IDC_PACKAGESELECTPLUGIN_32BIT_EDIT : IDC_PACKAGESELECTPLUGIN_64BIT_EDIT, buffer); - - (x32 ? plugins->first : plugins->second) = buffer; - - if (!plugins->first.empty() && !plugins->second.empty()) - { - // Enable Add button if both plugins have been selected - EnableWindow(GetDlgItem(hWnd, IDOK), TRUE); - } - break; - } - } - - MessageBox(hWnd, L"Invalid plugin.", L"Rainmeter Skin Packager", MB_OK | MB_TOPMOST); - } - break; - - case IDOK: - EndDialog(hWnd, 1); - break; - } - break; - - case WM_CLOSE: - EndDialog(hWnd, 0); - break; - - default: - return FALSE; - } - - return TRUE; -} - -// ----------------------------------------------------------------------------------------------- -// -// Info tab -// -// ----------------------------------------------------------------------------------------------- - -DialogPackage::TabInfo::TabInfo(HWND wnd) : Tab(GetInstanceHandle(), wnd, IDD_PACKAGEINFO_TAB, DlgProc) -{ -} - -void DialogPackage::TabInfo::Initialize() -{ - m_Initialized = true; - - HWND item = GetDlgItem(m_Window, IDC_INSTALLTAB_NAME_TEXT); - Edit_SetCueBannerText(item, L"..."); - - item = GetDlgItem(m_Window, IDC_INSTALLTAB_AUTHOR_TEXT); - Edit_SetCueBannerText(item, L"..."); - - item = GetDlgItem(m_Window, IDC_INSTALLTAB_VERSION_TEXT); - Edit_SetCueBannerText(item, L"..."); - - item = GetDlgItem(m_Window, IDC_PACKAGEINFO_COMPONENTS_LIST); - - DWORD extendedFlags = LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT; - - if (GetOSPlatform() >= OSPLATFORM_VISTA) - { - extendedFlags |= LVS_EX_DOUBLEBUFFER; - SetWindowTheme(item, L"explorer", nullptr); - } - - ListView_EnableGroupView(item, TRUE); - ListView_SetExtendedListViewStyleEx(item, 0, extendedFlags); - - // Add columns - LVCOLUMN lvc; - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - lvc.fmt = LVCFMT_LEFT; - lvc.iSubItem = 0; - lvc.cx = 252; - lvc.pszText = L"Name"; - ListView_InsertColumn(item, 0, &lvc); - - // Add groups - LVGROUP lvg; - lvg.cbSize = sizeof(LVGROUP); - lvg.mask = LVGF_HEADER | LVGF_GROUPID | LVGF_STATE; - lvg.state = (GetOSPlatform() >= OSPLATFORM_VISTA) ? LVGS_COLLAPSIBLE : LVGS_NORMAL; - lvg.iGroupId = 0; - lvg.pszHeader = L"Skin"; - ListView_InsertGroup(item, -1, &lvg); - lvg.iGroupId = 1; - lvg.pszHeader = L"Layouts"; - ListView_InsertGroup(item, -1, &lvg); - lvg.iGroupId = 2; - lvg.pszHeader = L"Plugins"; - ListView_InsertGroup(item, -1, &lvg); -} - -INT_PTR CALLBACK DialogPackage::TabInfo::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return c_Dialog->m_TabInfo.OnCommand(wParam, lParam); - - case WM_NOTIFY: - return c_Dialog->m_TabInfo.OnNotify(wParam, lParam); - } - - return FALSE; -} - -INT_PTR DialogPackage::TabInfo::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_PACKAGEINFO_ADDSKIN_BUTTON: - { - c_Dialog->m_SkinFolder.second = SelectFolder(m_Window, g_Data.skinsPath); - if (!c_Dialog->m_SkinFolder.second.empty()) - { - c_Dialog->m_SkinFolder.first = PathFindFileName(c_Dialog->m_SkinFolder.second.c_str()); - c_Dialog->m_SkinFolder.first.pop_back(); // Remove slash - - HWND item = GetDlgItem(m_Window, IDC_PACKAGEINFO_COMPONENTS_LIST); - LVITEM lvi; - lvi.mask = LVIF_TEXT | LVIF_GROUPID; - lvi.iItem = 1; - lvi.iSubItem = 0; - lvi.iGroupId = 0; - lvi.pszText = (WCHAR*)c_Dialog->m_SkinFolder.first.c_str(); - ListView_InsertItem(item, &lvi); - - EnableWindow((HWND)lParam, FALSE); - c_Dialog->SetNextButtonState(); - } - } - break; - - case IDC_PACKAGEINFO_ADDTHEME_BUTTON: - { - std::wstring folder = SelectFolder(m_Window, g_Data.settingsPath + L"Layouts\\"); - if (!folder.empty()) - { - std::wstring name = PathFindFileName(folder.c_str()); - name.pop_back(); // Remove slash - - if (c_Dialog->m_LayoutFolders.insert(std::make_pair(name, folder)).second) - { - HWND item = GetDlgItem(m_Window, IDC_PACKAGEINFO_COMPONENTS_LIST); - LVITEM lvi; - lvi.mask = LVIF_TEXT | LVIF_GROUPID; - lvi.iItem = c_Dialog->m_LayoutFolders.size() + 1; - lvi.iSubItem = 0; - lvi.iGroupId = 1; - lvi.pszText = (WCHAR*)name.c_str(); - ListView_InsertItem(item, &lvi); - } - } - } - break; - - case IDC_PACKAGEINFO_ADDPLUGIN_BUTTON: - { - std::pair<std::wstring, std::wstring> plugins = SelectPlugin(m_Window); - std::wstring name = PathFindFileName(plugins.first.c_str()); - if (!name.empty() && c_Dialog->m_PluginFolders.insert(std::make_pair(name, plugins)).second) - { - HWND item = GetDlgItem(m_Window, IDC_PACKAGEINFO_COMPONENTS_LIST); - LVITEM lvi; - lvi.mask = LVIF_TEXT | LVIF_GROUPID; - lvi.iItem = c_Dialog->m_PluginFolders.size() + 1; - lvi.iSubItem = 0; - lvi.iGroupId = 2; - lvi.pszText = (WCHAR*)name.c_str(); - ListView_InsertItem(item, &lvi); - } - } - break; - - case IDC_PACKAGEINFO_REMOVE_BUTTON: - { - HWND item = GetDlgItem(m_Window, IDC_PACKAGEINFO_COMPONENTS_LIST); - int sel = ListView_GetNextItem(item, -1, LVNI_FOCUSED | LVNI_SELECTED); - if (sel != -1) - { - WCHAR buffer[MAX_PATH]; - - // Remove unchecked items from the component sets - LVITEM lvi; - lvi.mask = LVIF_GROUPID | LVIF_TEXT; - lvi.iSubItem = 0; - lvi.iItem = sel; - lvi.pszText = buffer; - lvi.cchTextMax = _countof(buffer); - ListView_GetItem(item, &lvi); - - ListView_DeleteItem(item, sel); - - const std::wstring name = buffer; - switch (lvi.iGroupId) - { - case 0: - { - item = GetDlgItem(m_Window, IDC_PACKAGEINFO_ADDSKIN_BUTTON); - EnableWindow(item, TRUE); - c_Dialog->m_SkinFolder.first.clear(); - c_Dialog->m_SkinFolder.second.clear(); - c_Dialog->SetNextButtonState(); - } - break; - - case 1: - c_Dialog->m_LayoutFolders.erase(c_Dialog->m_LayoutFolders.find(name)); - break; - - case 2: - c_Dialog->m_PluginFolders.erase(c_Dialog->m_PluginFolders.find(name)); - break; - } - } - } - break; - - case IDC_PACKAGEINFO_NAME_EDIT: - case IDC_PACKAGEINFO_AUTHOR_EDIT: - case IDC_PACKAGEINFO_VERSION_EDIT: - if (HIWORD(wParam) == EN_CHANGE) - { - WCHAR buffer[64]; - int len = GetWindowText((HWND)lParam, buffer, _countof(buffer)); - if (LOWORD(wParam) == IDC_PACKAGEINFO_NAME_EDIT) - { - c_Dialog->m_Name.assign(buffer, len); - } - else if (LOWORD(wParam) == IDC_PACKAGEINFO_AUTHOR_EDIT) - { - c_Dialog->m_Author.assign(buffer, len); - } - else // if (LOWORD(wParam) == IDC_PACKAGEINFO_VERSION_EDIT) - { - c_Dialog->m_Version.assign(buffer, len); - } - c_Dialog->SetNextButtonState(); - } - break; - - - default: - return FALSE; - } - - return TRUE; -} - -INT_PTR DialogPackage::TabInfo::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->code) - { - case LVN_ITEMCHANGED: - { - NMLISTVIEW* nmlv = (NMLISTVIEW*)lParam; - if (nm->idFrom == IDC_PACKAGEINFO_COMPONENTS_LIST) - { - BOOL selected = (nmlv->uNewState & LVIS_SELECTED); - - HWND item = GetDlgItem(m_Window, IDC_PACKAGEINFO_REMOVE_BUTTON); - EnableWindow(item, selected); - } - } - break; - - case NM_CLICK: - { - if (nm->idFrom == IDC_PACKAGEINFO_WHATIS_LINK) - { - c_Dialog->ShowHelp(); - } - } - break; - - default: - return FALSE; - } - - return TRUE; -} - -// ----------------------------------------------------------------------------------------------- -// -// Options tab -// -// ----------------------------------------------------------------------------------------------- - -DialogPackage::TabOptions::TabOptions(HWND wnd) : Tab(GetInstanceHandle(), wnd, IDD_PACKAGEOPTIONS_TAB, DlgProc) -{ -} - -void DialogPackage::TabOptions::Initialize() -{ - m_Initialized = true; - - WCHAR buffer[MAX_PATH]; - SHGetFolderPath(nullptr, CSIDL_DESKTOPDIRECTORY, nullptr, SHGFP_TYPE_CURRENT, buffer); - - c_Dialog->m_TargetFile = buffer; - c_Dialog->m_TargetFile += L'\\'; - int pos = (int)c_Dialog->m_TargetFile.length() + 1; - c_Dialog->m_TargetFile += c_Dialog->m_Name; - c_Dialog->m_TargetFile += L'_'; - c_Dialog->m_TargetFile += c_Dialog->m_Version; - - // Escape reserved chars - for (int i = pos, isize = (int)c_Dialog->m_TargetFile.length(); i < isize; ++i) - { - if (wcschr(L"\\/:*?\"<>|", c_Dialog->m_TargetFile[i])) - { - c_Dialog->m_TargetFile[i] = L'_'; - } - } - - c_Dialog->m_TargetFile += L".rmskin"; - - HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_FILE_EDIT); - SetWindowText(item,c_Dialog->m_TargetFile.c_str()); - - item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADTHEME_RADIO); - if (c_Dialog->m_LayoutFolders.empty()) - { - EnableWindow(item, FALSE); - - item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_DONOTHING_RADIO); - Button_SetCheck(item, BST_CHECKED); - } - else - { - c_Dialog->m_LoadLayout = true; - c_Dialog->m_Load = (*c_Dialog->m_LayoutFolders.cbegin()).first; - - Button_SetCheck(item, BST_CHECKED); - - item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADTHEME_COMBO); - ShowWindow(item, SW_SHOWNORMAL); - - for (auto iter = c_Dialog->m_LayoutFolders.cbegin(); iter != c_Dialog->m_LayoutFolders.cend(); ++iter) - { - ComboBox_AddString(item, (*iter).first.c_str()); - } - ComboBox_SetCurSel(item, 0); - } - - item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKIN_EDIT); - Edit_SetCueBannerText(item, L"Select skin"); - - item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_RAINMETERVERSION_EDIT); - _snwprintf_s(buffer, _TRUNCATE, L"%s.%i", APPVERSION, revision_number); - SetWindowText(item, buffer); - c_Dialog->m_MinimumRainmeter = buffer; - - item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_WINDOWSVERSION_COMBO); - ComboBox_AddString(item, L"XP"); - ComboBox_AddString(item, L"Vista"); - ComboBox_AddString(item, L"7"); - ComboBox_SetCurSel(item, 0); - c_Dialog->m_MinimumWindows = g_OsNameVersions[0].version; -} - -INT_PTR CALLBACK DialogPackage::TabOptions::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return c_Dialog->m_TabOptions.OnCommand(wParam, lParam); - } - - return FALSE; -} - -INT_PTR DialogPackage::TabOptions::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_PACKAGEOPTIONS_FILEBROWSE_BUTTON: - { - WCHAR buffer[MAX_PATH]; - HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_FILE_EDIT); - GetWindowText(item, buffer, _countof(buffer)); - - OPENFILENAME ofn = { sizeof(OPENFILENAME) }; - ofn.lpstrFilter = L"Rainmeter skin package (.rmskin)\0*.rmskin"; - ofn.lpstrTitle = L"Select Rainmeter skin package"; - ofn.lpstrDefExt = L"dll"; - ofn.lpstrFile = buffer; - ofn.nMaxFile = _countof(buffer); - ofn.hwndOwner = c_Dialog->GetWindow(); - - if (GetOpenFileName(&ofn)) - { - c_Dialog->m_TargetFile = buffer; - SetWindowText(item, buffer); - } - } - break; - - case IDC_PACKAGEOPTIONS_DONOTHING_RADIO: - { - HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKIN_EDIT); - ShowWindow(item, SW_HIDE); - item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON); - ShowWindow(item, SW_HIDE); - item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADTHEME_COMBO); - ShowWindow(item, SW_HIDE); - - c_Dialog->m_Load.clear(); - } - break; - - case IDC_PACKAGEOPTIONS_LOADSKIN_RADIO: - { - HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKIN_EDIT); - ShowWindow(item, SW_SHOWNORMAL); - - WCHAR buffer[MAX_PATH]; - GetWindowText(item, buffer, _countof(buffer)); - c_Dialog->m_Load = buffer; - c_Dialog->m_LoadLayout = false; - - item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON); - ShowWindow(item, SW_SHOWNORMAL); - item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADTHEME_COMBO); - ShowWindow(item, SW_HIDE); - } - break; - - case IDC_PACKAGEOPTIONS_LOADTHEME_RADIO: - { - HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKIN_EDIT); - ShowWindow(item, SW_HIDE); - item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON); - ShowWindow(item, SW_HIDE); - item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADTHEME_COMBO); - ShowWindow(item, SW_SHOWNORMAL); - - WCHAR buffer[MAX_PATH]; - GetWindowText(item, buffer, _countof(buffer)); - c_Dialog->m_Load = buffer; - c_Dialog->m_LoadLayout = true; - } - break; - - case IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON: - { - WCHAR buffer[MAX_PATH]; - HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKIN_EDIT); - GetWindowText(item, buffer, _countof(buffer)); - - OPENFILENAME ofn = { sizeof(OPENFILENAME) }; - ofn.Flags = OFN_FILEMUSTEXIST; - ofn.FlagsEx = OFN_EX_NOPLACESBAR; - ofn.lpstrFilter = L"Rainmeter skin file (.ini)\0*.ini"; - ofn.lpstrTitle = L"Select Rainmeter skin file"; - ofn.lpstrDefExt = L"ini"; - ofn.lpstrFile = buffer; - ofn.nMaxFile = _countof(buffer); - ofn.lpstrInitialDir = c_Dialog->m_SkinFolder.second.c_str(); - ofn.hwndOwner = c_Dialog->GetWindow(); - - if (GetOpenFileName(&ofn)) - { - // Make sure user didn't browse to some random folder - if (_wcsnicmp(ofn.lpstrInitialDir, buffer, c_Dialog->m_SkinFolder.second.length()) == 0) - { - // Skip everything before actual skin folder - const WCHAR* folderPath = buffer + c_Dialog->m_SkinFolder.second.length() - c_Dialog->m_SkinFolder.first.length() - 1; - SetWindowText(item, folderPath); - c_Dialog->m_Load = folderPath; - } - } - } - break; - - case IDC_PACKAGEOPTIONS_RAINMETERVERSION_EDIT: - if (HIWORD(wParam) == EN_CHANGE) - { - WCHAR buffer[32]; - GetWindowText((HWND)lParam, buffer, _countof(buffer)); - - // Get caret position - DWORD sel = Edit_GetSel((HWND)lParam); - - // Only allow numbers and period - WCHAR* version = buffer; - while (*version) - { - if (iswdigit(*version) || *version == L'.') - { - ++version; - } - else - { - *version = L'\0'; - SetWindowText((HWND)lParam, buffer); - - // Reset caret position - Edit_SetSel((HWND)lParam, LOWORD(sel), HIWORD(sel)); - break; - } - } - - c_Dialog->m_MinimumRainmeter = buffer; - } - break; - - case IDC_PACKAGEOPTIONS_WINDOWSVERSION_COMBO: - if (HIWORD(wParam) == CBN_SELCHANGE) - { - int sel = ComboBox_GetCurSel((HWND)lParam); - c_Dialog->m_MinimumWindows = g_OsNameVersions[sel].version; - } - break; - - default: - return FALSE; - } - - return TRUE; -} - -// ----------------------------------------------------------------------------------------------- -// -// Advanced tab -// -// ----------------------------------------------------------------------------------------------- - -DialogPackage::TabAdvanced::TabAdvanced(HWND wnd) : Tab(GetInstanceHandle(), wnd, IDD_PACKAGEADVANCED_TAB, DlgProc) -{ -} - -void DialogPackage::TabAdvanced::Initialize() -{ - m_Initialized = true; -} - -INT_PTR CALLBACK DialogPackage::TabAdvanced::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - return c_Dialog->m_TabAdvanced.OnCommand(wParam, lParam); - - case WM_NOTIFY: - return c_Dialog->m_TabAdvanced.OnNotify(wParam, lParam); - } - - return FALSE; -} - -INT_PTR DialogPackage::TabAdvanced::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_PACKAGEADVANCED_HEADERROWSE_BUTTON: - { - WCHAR buffer[MAX_PATH]; - HWND item = GetDlgItem(m_Window, IDC_PACKAGEADVANCED_HEADER_EDIT); - GetWindowText(item, buffer, _countof(buffer)); - - OPENFILENAME ofn = { sizeof(OPENFILENAME) }; - ofn.Flags = OFN_FILEMUSTEXIST; - ofn.lpstrFilter = L"Bitmap file (.bmp)\0*.bmp"; - ofn.lpstrTitle = L"Select header image"; - ofn.lpstrDefExt = L"bmp"; - ofn.lpstrFile = buffer; - ofn.nMaxFile = _countof(buffer); - ofn.hwndOwner = c_Dialog->GetWindow(); - - if (GetOpenFileName(&ofn)) - { - c_Dialog->m_HeaderFile = buffer; - SetWindowText(item, buffer); - } - } - break; - - case IDC_PACKAGEADVANCED_VARIABLEFILES_EDIT: - if (HIWORD(wParam) == EN_CHANGE) - { - int length = GetWindowTextLength((HWND)lParam); - c_Dialog->m_VariableFiles.resize(length); - GetWindowText((HWND)lParam, &c_Dialog->m_VariableFiles[0], length + 1); - } - break; - - case IDC_PACKAGEADVANCED_MERGESKINS_CHECK: - c_Dialog->m_MergeSkins = !c_Dialog->m_MergeSkins; - break; - - default: - return FALSE; - } - - return TRUE; -} - -INT_PTR DialogPackage::TabAdvanced::OnNotify(WPARAM wParam, LPARAM lParam) -{ - LPNMHDR nm = (LPNMHDR)lParam; - switch (nm->code) - { - case NM_CLICK: - { - if (nm->idFrom == IDC_PACKAGEADVANCED_HELP_LINK) - { - c_Dialog->ShowHelp(); - } - } - break; - - default: - return FALSE; - } - - return TRUE; +/* + Copyright (C) 2012 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "../Common/StringUtil.h" +#include "SkinInstaller.h" +#include "DialogPackage.h" +#include "DialogInstall.h" +#include "resource.h" +#include "../Version.h" + +#define WM_DELAYED_CLOSE WM_APP + 0 + +extern GlobalData g_Data; +extern OsNameVersion g_OsNameVersions[]; + +DialogPackage* DialogPackage::c_Dialog = nullptr; + +DialogPackage::DialogPackage(HWND wnd) : Dialog(wnd), + m_TabInfo(wnd), + m_TabOptions(wnd), + m_TabAdvanced(wnd), + m_LoadLayout(false), + m_MergeSkins(false), + m_PackagerThread(), + m_ZipFile(), + m_AllowNonAsciiFilenames(false) +{ +} + +DialogPackage::~DialogPackage() +{ +} + +void DialogPackage::Create(HINSTANCE hInstance, LPWSTR lpCmdLine) +{ + HANDLE hMutex; + if (IsRunning(L"Rainmeter Skin Packager", &hMutex)) + { + HWND hwnd = FindWindow(L"#32770", L"Rainmeter Skin Packager"); + SetForegroundWindow(hwnd); + } + else + { + DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_PACKAGE_DIALOG), nullptr, (DLGPROC)DlgProc, (LPARAM)lpCmdLine); + ReleaseMutex(hMutex); + } +} + +Dialog::Tab& DialogPackage::GetActiveTab() +{ + int sel = TabCtrl_GetCurSel(GetDlgItem(m_Window, IDC_PACKAGE_TAB)); + if (sel == -1) + { + return m_TabInfo; + } + else if (sel == 0) + { + return m_TabOptions; + } + else // if (sel == 1) + { + return m_TabAdvanced; + } +} + +INT_PTR CALLBACK DialogPackage::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (!c_Dialog) + { + if (uMsg == WM_INITDIALOG) + { + c_Dialog = new DialogPackage(hWnd); + return c_Dialog->OnInitDialog(wParam, lParam); + } + } + else + { + switch (uMsg) + { + case WM_COMMAND: + return c_Dialog->OnCommand(wParam, lParam); + + case WM_NOTIFY: + return c_Dialog->OnNotify(wParam, lParam); + + case WM_CLOSE: + { + if (!c_Dialog->m_PackagerThread) + { + EndDialog(hWnd, 0); + } + } + return TRUE; + + case WM_DESTROY: + delete c_Dialog; + c_Dialog = nullptr; + return FALSE; + } + } + + return FALSE; +} + +INT_PTR DialogPackage::OnInitDialog(WPARAM wParam, LPARAM lParam) +{ + HICON hIcon = (HICON)LoadImage(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDI_SKININSTALLER), IMAGE_ICON, 16, 16, LR_SHARED); + SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); + + if (GetOSPlatform() >= OSPLATFORM_VISTA) + { + SetDialogFont(); + } + + m_TabInfo.Activate(); + + return FALSE; +} + +INT_PTR DialogPackage::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_PACKAGE_NEXT_BUTTON: + { + HWND item = GetDlgItem(m_Window, IDC_PACKAGE_TAB); + TCITEM tci = {0}; + tci.mask = TCIF_TEXT; + tci.pszText = L"Options"; + TabCtrl_InsertItem(item, 0, &tci); + tci.pszText = L"Advanced"; + TabCtrl_InsertItem(item, 1, &tci); + + item = GetDlgItem(m_Window, IDC_PACKAGE_NEXT_BUTTON); + ShowWindow(item, SW_HIDE); + + item = GetDlgItem(m_Window, IDC_PACKAGE_CREATEPACKAGE_BUTTON); + ShowWindow(item, SW_SHOWNORMAL); + SendMessage(m_Window, DM_SETDEFID, IDC_PACKAGE_CREATEPACKAGE_BUTTON, 0); + + ShowWindow(m_TabInfo.GetWindow(), SW_HIDE); + + m_TabOptions.Activate(); + } + break; + + case IDC_PACKAGE_CREATEPACKAGE_BUTTON: + { + HWND item = GetDlgItem(m_Window, IDC_PACKAGE_CREATEPACKAGE_BUTTON); + EnableWindow(item, FALSE); + + item = GetDlgItem(m_Window, IDCANCEL); + EnableWindow(item, FALSE); + + m_TabOptions.Activate(); + item = GetDlgItem(m_Window, IDC_PACKAGE_TAB); + TabCtrl_SetCurSel(item, 0); + EnableWindow(item, FALSE); + EnableWindow(m_TabOptions.GetWindow(), FALSE); + EnableWindow(m_TabAdvanced.GetWindow(), FALSE); + + item = GetDlgItem(m_TabOptions.GetWindow(), IDC_INSTALLTAB_CREATING_TEXT); + ShowWindow(item, SW_SHOWNORMAL); + + item = GetDlgItem(m_TabOptions.GetWindow(), IDC_INSTALLTAB_CREATING_BAR); + ShowWindow(item, SW_SHOWNORMAL); + SendMessage(item, PBM_SETMARQUEE, (WPARAM)TRUE, 0); + + m_PackagerThread = (HANDLE)_beginthreadex(nullptr, 0, PackagerThreadProc, this, 0, nullptr); + if (!m_PackagerThread) + { + MessageBox(m_Window, L"Unknown error.", L"Rainmeter Skin Packager", MB_ERROR); + EndDialog(m_Window, 0); + } + } + break; + + case IDCANCEL: + if (!m_PackagerThread) + { + EndDialog(m_Window, 0); + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +INT_PTR DialogPackage::OnNotify(WPARAM wParam, LPARAM lParam) +{ + LPNMHDR nm = (LPNMHDR)lParam; + switch (nm->idFrom) + { + case IDC_PACKAGE_TAB: + if (nm->code == TCN_SELCHANGE) + { + // Disable all tab windows first + EnableWindow(m_TabInfo.GetWindow(), FALSE); + EnableWindow(m_TabOptions.GetWindow(), FALSE); + EnableWindow(m_TabAdvanced.GetWindow(), FALSE); + + GetActiveTab().Activate(); + } + break; + + default: + return 1; + } + + return 0; +} + +void DialogPackage::SetNextButtonState() +{ + BOOL state = !(m_Name.empty() || m_Author.empty() || m_SkinFolder.second.empty()); + EnableWindow(GetDlgItem(m_Window, IDC_PACKAGE_NEXT_BUTTON), state); +} + +bool DialogPackage::CreatePackage() +{ + // Create options file + WCHAR tempFile[MAX_PATH]; + GetTempPath(MAX_PATH, tempFile); + GetTempFileName(tempFile, L"ini", 0, tempFile); + + WritePrivateProfileString(L"rmskin", L"Name", m_Name.c_str(), tempFile); + WritePrivateProfileString(L"rmskin", L"Author", m_Author.c_str(), tempFile); + WritePrivateProfileString(L"rmskin", L"Version", m_Version.c_str(), tempFile); + + if (!c_Dialog->m_Load.empty()) + { + WritePrivateProfileString(L"rmskin", L"LoadType", c_Dialog->m_LoadLayout ? L"Layout" : L"Skin", tempFile); + WritePrivateProfileString(L"rmskin", L"Load", c_Dialog->m_Load.c_str(), tempFile); + } + + if (!c_Dialog->m_VariableFiles.empty()) + { + WritePrivateProfileString(L"rmskin", L"VariableFiles", m_VariableFiles.c_str(), tempFile); + } + + if (c_Dialog->m_MergeSkins) + { + WritePrivateProfileString(L"rmskin", L"MergeSkins", L"1", tempFile); + } + + WritePrivateProfileString(L"rmskin", L"MinimumRainmeter", m_MinimumRainmeter.c_str(), tempFile); + WritePrivateProfileString(L"rmskin", L"MinimumWindows", m_MinimumWindows.c_str(), tempFile); + + // Only Skin Installer in Rainmeter 3.0.1 support UTF-8 filenames. + m_AllowNonAsciiFilenames = DialogInstall::CompareVersions(m_MinimumRainmeter, L"3.0.1") != -1; + + // Create archive and add options file and header bitmap + m_ZipFile = zipOpen(ConvertToAscii(m_TargetFile.c_str()).c_str(), APPEND_STATUS_CREATE); + + auto cleanup = [&]()->bool + { + zipClose(m_ZipFile, nullptr); + DeleteFile(m_TargetFile.c_str()); + return false; + }; + + if (!m_ZipFile || + (!c_Dialog->m_HeaderFile.empty() && !AddFileToPackage(c_Dialog->m_HeaderFile.c_str(), L"RMSKIN.bmp")) || + !AddFileToPackage(tempFile, L"RMSKIN.ini")) + { + std::wstring error = L"Unable to create package."; + error += L"\n\nClick OK to close Packager."; + MessageBox(m_Window, error.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONERROR); + DeleteFile(tempFile); + return cleanup(); + } + + // Add skin + { + std::wstring zipPrefix = L"Skins\\" + m_SkinFolder.first; + zipPrefix += L'\\'; + if (!AddFolderToPackage(m_SkinFolder.second, L"", zipPrefix.c_str())) + { + return cleanup(); + } + } + + // Add layouts + for (auto iter = m_LayoutFolders.cbegin(); iter != m_LayoutFolders.cend(); ++iter) + { + std::wstring realPath = (*iter).second + L"Rainmeter.ini"; + std::wstring zipPath = L"Layouts\\" + (*iter).first; + zipPath += L"\\Rainmeter.ini"; + if (!AddFileToPackage(realPath.c_str(), zipPath.c_str())) + { + std::wstring error = L"Error adding layout '"; + error += (*iter).first; + error += L"'."; + error += L"\n\nClick OK to close Packager."; + MessageBox(m_Window, error.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONERROR); + return cleanup(); + } + } + + // Add plugins + for (auto iter = m_PluginFolders.cbegin(); iter != m_PluginFolders.cend(); ++iter) + { + // Add 32bit and 64bit versions + for (int i = 0; i < 2; ++i) + { + const std::wstring& realPath = (i == 0) ? (*iter).second.first : (*iter).second.second; + std::wstring zipPath = ((i == 0) ? L"Plugins\\32bit\\" : L"Plugins\\64bit\\") + (*iter).first; + if (!AddFileToPackage(realPath.c_str(), zipPath.c_str())) + { + std::wstring error = L"Error adding plugin '"; + error += (*iter).first; + error += L"'."; + error += L"\n\nClick OK to close Packager."; + MessageBox(m_Window, error.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONERROR); + return cleanup(); + } + } + } + + // Add footer + FILE* file; + if (zipClose(m_ZipFile, nullptr) == ZIP_OK && + (file = _wfopen(m_TargetFile.c_str(), L"r+b")) != nullptr) + { + fseek(file, 0, SEEK_END); + DialogInstall::PackageFooter footer = { _ftelli64(file), 0, "RMSKIN" }; + fwrite(&footer, sizeof(footer), 1, file); + fclose(file); + } + else + { + std::wstring error = L"Unable to create package."; + error += L"\n\nClick OK to close Packager."; + MessageBox(m_Window, error.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONERROR); + return false; + } + + return true; +} + +unsigned __stdcall DialogPackage::PackagerThreadProc(void* pParam) +{ + DialogPackage* dialog = (DialogPackage*)pParam; + + if (dialog->CreatePackage()) + { + // Stop the progress bar + HWND item = GetDlgItem(dialog->m_TabOptions.GetWindow(), IDC_INSTALLTAB_CREATING_BAR); + SendMessage(item, PBM_SETMARQUEE, (WPARAM)FALSE, 0); + + FlashWindow(dialog->m_Window, TRUE); + + std::wstring message = L"The skin package has been successfully created."; + message += L"\n\nClick OK to close Packager."; + MessageBox(c_Dialog->GetWindow(), message.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONINFORMATION); + } + else + { + DeleteFile(dialog->m_TargetFile.c_str()); + } + + EndDialog(dialog->m_Window, 0); + + return 0; +} + +bool DialogPackage::AddFileToPackage(const WCHAR* filePath, const WCHAR* zipPath) +{ + std::string zipPathUTF8 = StringUtil::NarrowUTF8(zipPath); + for (int i = 0, isize = zipPathUTF8.length(); i < isize; ++i) + { + if ((zipPathUTF8[i] & 0x80) != 0) + { + // UTF-8 lead bit is not zero so the string is non-ASCII. + if (!m_AllowNonAsciiFilenames) + { + return false; + } + } + + if (zipPathUTF8[i] == '\\') + { + zipPathUTF8[i] = '/'; + } + } + + const uLong ZIP_UTF8_FLAG = 1 << 11; + zip_fileinfo fi = {0}; + if (zipOpenNewFileInZip4( + m_ZipFile, zipPathUTF8.c_str(), &fi, + nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, Z_DEFAULT_COMPRESSION, + 0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0, 0, ZIP_UTF8_FLAG) != ZIP_OK) + { + return false; + } + + bool result = true; + + if (filePath) + { + HANDLE file = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + if (file == INVALID_HANDLE_VALUE) + { + result = false; + } + else + { + do + { + const DWORD bufferSize = 16 * 1024; + BYTE buffer[bufferSize]; + DWORD readSize; + if (!ReadFile(file, buffer, bufferSize, &readSize, nullptr)) + { + result = false; + } + else if (readSize != 0) + { + result = zipWriteInFileInZip(m_ZipFile, buffer, (UINT)readSize) == ZIP_OK; + } + else + { + // EOF + break; + } + } + while (result); + + CloseHandle(file); + } + } + else + { + // Directory entry, so nothing needs to be written. + } + + return zipCloseFileInZip(m_ZipFile) == ZIP_OK && result; +} + +bool DialogPackage::AddFolderToPackage(const std::wstring& path, std::wstring base, const WCHAR* zipPrefix) +{ + std::wstring currentPath = path + base; + currentPath += L'*'; + + WIN32_FIND_DATA fd; + HANDLE hFind = FindFirstFileEx( + currentPath.c_str(), + FindExInfoStandard, + &fd, + FindExSearchNameMatch, + nullptr, + 0); + + if (hFind == INVALID_HANDLE_VALUE) + { + return false; + } + + currentPath.pop_back(); // Remove * + + bool result = true; + bool filesAdded = false; + std::list<std::wstring> folders; + do + { + if (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) + { + // Ignore hidden files and folders + continue; + } + + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (!(fd.cFileName[0] == L'.' && (!fd.cFileName[1] || fd.cFileName[1] == L'.' && !fd.cFileName[2]))) + { + folders.push_back(fd.cFileName); + } + } + else + { + std::wstring filePath = currentPath + fd.cFileName; + std::wstring zipPath = zipPrefix; + zipPath.append(filePath, path.length(), filePath.length() - path.length()); + + result = AddFileToPackage(filePath.c_str(), zipPath.c_str()); + if (!result) + { + std::wstring error = L"Error adding file:\n"; + error += filePath; + error += L"\n\nClick OK to close Packager."; + MessageBox(m_Window, error.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONERROR); + break; + } + + filesAdded = true; + } + } + while (FindNextFile(hFind, &fd)); + FindClose(hFind); + + if (result) + { + if (!filesAdded && folders.empty()) + { + // Add directory entry if folder is empty. + std::wstring zipPath = zipPrefix; + zipPath.append(currentPath, path.length(), currentPath.length() - path.length()); + AddFileToPackage(nullptr, zipPath.c_str()); + } + + std::list<std::wstring>::const_iterator iter = folders.begin(); + for ( ; iter != folders.end(); ++iter) + { + std::wstring newBase = base + (*iter); + newBase += L'\\'; + result = AddFolderToPackage(path, newBase, zipPrefix); + if (!result) break; + } + } + + return result; +} + +void DialogPackage::ShowHelp() +{ + std::wstring url = L"http://rainmeter.net/cms/UsingApplication-SkinPackager"; + if (revision_beta) + { + url += L"_beta"; + } + + ShellExecute(m_Window, L"open", url.c_str(), nullptr, nullptr, SW_SHOWNORMAL); +} + +std::wstring DialogPackage::SelectFolder(HWND parent, const std::wstring& existingPath) +{ + LPCWSTR dialog = MAKEINTRESOURCE(IDD_PACKAGESELECTFOLDER_DIALOG); + std::wstring folder = existingPath; + if (DialogBoxParam(GetInstanceHandle(), dialog, parent, SelectFolderDlgProc, (LPARAM)&folder) != 1) + { + folder.clear(); + } + return folder; +} + +INT_PTR CALLBACK DialogPackage::SelectFolderDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_INITDIALOG: + { + EnableThemeDialogTexture(hWnd, ETDT_ENABLETAB); + c_Dialog->SetDialogFont(hWnd); + + std::wstring* existingPath = (std::wstring*)lParam; + SetWindowLongPtr(hWnd, GWLP_USERDATA, lParam); + + *existingPath += L'*'; + WIN32_FIND_DATA fd; + HANDLE hFind = FindFirstFileEx(existingPath->c_str(), FindExInfoStandard, &fd, FindExSearchNameMatch, nullptr, 0); + existingPath->pop_back(); + + if (hFind != INVALID_HANDLE_VALUE) + { + const WCHAR* folder = PathFindFileName(existingPath->c_str()); + + HWND item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_EXISTING_RADIO); + std::wstring text = L"Add folder from "; + text.append(folder, wcslen(folder) - 1); + text += L':'; + SetWindowText(item, text.c_str()); + Button_SetCheck(item, BST_CHECKED); + + item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_EXISTING_COMBO); + + do + { + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && + !(fd.cFileName[0] == L'.' && (!fd.cFileName[1] || fd.cFileName[1] == L'.' && !fd.cFileName[2])) && + wcscmp(fd.cFileName, L"Backup") != 0 && + wcscmp(fd.cFileName, L"@Backup") != 0) + { + ComboBox_InsertString(item, -1, fd.cFileName); + } + } + while (FindNextFile(hFind, &fd)); + + ComboBox_SetCurSel(item, 0); + + FindClose(hFind); + } + } + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_PACKAGESELECTFOLDER_EXISTING_RADIO: + { + HWND item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_EXISTING_COMBO); + EnableWindow(item, TRUE); + int sel = ComboBox_GetCurSel(item); + item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT); + EnableWindow(item, FALSE); + item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_CUSTOMBROWSE_BUTTON); + EnableWindow(item, FALSE); + + item = GetDlgItem(hWnd, IDOK); + EnableWindow(item, sel != -1); + } + break; + + case IDC_PACKAGESELECTFOLDER_CUSTOM_RADIO: + { + HWND item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_EXISTING_COMBO); + EnableWindow(item, FALSE); + item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT); + EnableWindow(item, TRUE); + item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_CUSTOMBROWSE_BUTTON); + EnableWindow(item, TRUE); + + SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT, EN_CHANGE), 0); + } + break; + + case IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT: + if (HIWORD(wParam) == EN_CHANGE) + { + WCHAR buffer[MAX_PATH]; + int len = Edit_GetText((HWND)lParam, buffer, MAX_PATH); + + // Disable Add button if invalid directory + DWORD attributes = GetFileAttributes(buffer); + BOOL state = (attributes != INVALID_FILE_ATTRIBUTES && + attributes & FILE_ATTRIBUTE_DIRECTORY); + EnableWindow(GetDlgItem(hWnd, IDOK), state); + } + break; + + case IDC_PACKAGESELECTFOLDER_CUSTOMBROWSE_BUTTON: + { + WCHAR buffer[MAX_PATH]; + BROWSEINFO bi = {0}; + bi.hwndOwner = hWnd; + bi.ulFlags = BIF_USENEWUI | BIF_NONEWFOLDERBUTTON | BIF_RETURNONLYFSDIRS; + + PIDLIST_ABSOLUTE pidl = SHBrowseForFolder(&bi); + if (pidl && SHGetPathFromIDList(pidl, buffer)) + { + HWND item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT); + SetWindowText(item, buffer); + CoTaskMemFree(pidl); + } + } + break; + + case IDOK: + { + WCHAR buffer[MAX_PATH]; + HWND item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_EXISTING_RADIO); + bool existing = Button_GetCheck(item) == BST_CHECKED; + + item = GetDlgItem(hWnd, existing ? IDC_PACKAGESELECTFOLDER_EXISTING_COMBO : IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT); + GetWindowText(item, buffer, _countof(buffer)); + + std::wstring* result = (std::wstring*)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + if (existing) + { + *result += buffer; + } + else + { + *result = buffer; + } + *result += L'\\'; + + EndDialog(hWnd, 1); + } + } + break; + + case WM_CLOSE: + EndDialog(hWnd, 0); + break; + + default: + return FALSE; + } + + return TRUE; +} + +std::pair<std::wstring, std::wstring> DialogPackage::SelectPlugin(HWND parent) +{ + LPCWSTR dialog = MAKEINTRESOURCE(IDD_PACKAGESELECTPLUGIN_DIALOG); + std::pair<std::wstring, std::wstring> plugins; + if (DialogBoxParam(GetInstanceHandle(), dialog, parent, SelectPluginDlgProc, (LPARAM)&plugins) != 1) + { + plugins.first.clear(); + plugins.second.clear(); + } + return plugins; +} + +INT_PTR CALLBACK DialogPackage::SelectPluginDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_INITDIALOG: + { + EnableThemeDialogTexture(hWnd, ETDT_ENABLETAB); + c_Dialog->SetDialogFont(hWnd); + + auto plugins = (std::pair<std::wstring, std::wstring>*)lParam; + SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)plugins); + } + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_PACKAGESELECTPLUGIN_32BITBROWSE_BUTTON: + case IDC_PACKAGESELECTPLUGIN_64BITBROWSE_BUTTON: + { + WCHAR buffer[MAX_PATH]; + buffer[0] = L'\0'; + + OPENFILENAME ofn = { sizeof(OPENFILENAME) }; + ofn.Flags = OFN_FILEMUSTEXIST; + ofn.lpstrFilter = L"Plugins (.dll)\0*.dll"; + ofn.lpstrTitle = L"Select plugin file"; + ofn.lpstrDefExt = L"dll"; + ofn.nFilterIndex = 0; + ofn.lpstrFile = buffer; + ofn.nMaxFile = _countof(buffer); + ofn.hwndOwner = c_Dialog->GetWindow(); + + if (!GetOpenFileName(&ofn)) + { + break; + } + + bool x32 = LOWORD(wParam) == IDC_PACKAGESELECTPLUGIN_32BITBROWSE_BUTTON; + + LOADED_IMAGE* loadedImage = ImageLoad(ConvertToAscii(buffer).c_str(), nullptr); + if (loadedImage) + { + WORD machine = loadedImage->FileHeader->FileHeader.Machine; + ImageUnload(loadedImage); + + if ((x32 && machine == IMAGE_FILE_MACHINE_I386) || (!x32 && machine == IMAGE_FILE_MACHINE_AMD64)) + { + // Check if same name as other DLL + auto plugins = (std::pair<std::wstring, std::wstring>*)GetWindowLongPtr(hWnd, GWLP_USERDATA); + const WCHAR* otherName = PathFindFileName(x32 ? plugins->second.c_str() : plugins->first.c_str()); + if (*otherName && _wcsicmp(otherName, PathFindFileName(buffer)) != 0) + { + MessageBox(hWnd, L"Plugins must have same name.", L"Rainmeter Skin Packager", MB_OK | MB_TOPMOST); + break; + } + + PathSetDlgItemPath(hWnd, x32 ? IDC_PACKAGESELECTPLUGIN_32BIT_EDIT : IDC_PACKAGESELECTPLUGIN_64BIT_EDIT, buffer); + + (x32 ? plugins->first : plugins->second) = buffer; + + if (!plugins->first.empty() && !plugins->second.empty()) + { + // Enable Add button if both plugins have been selected + EnableWindow(GetDlgItem(hWnd, IDOK), TRUE); + } + break; + } + } + + MessageBox(hWnd, L"Invalid plugin.", L"Rainmeter Skin Packager", MB_OK | MB_TOPMOST); + } + break; + + case IDOK: + EndDialog(hWnd, 1); + break; + } + break; + + case WM_CLOSE: + EndDialog(hWnd, 0); + break; + + default: + return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------------------------------- +// +// Info tab +// +// ----------------------------------------------------------------------------------------------- + +DialogPackage::TabInfo::TabInfo(HWND wnd) : Tab(GetInstanceHandle(), wnd, IDD_PACKAGEINFO_TAB, DlgProc) +{ +} + +void DialogPackage::TabInfo::Initialize() +{ + m_Initialized = true; + + HWND item = GetDlgItem(m_Window, IDC_INSTALLTAB_NAME_TEXT); + Edit_SetCueBannerText(item, L"..."); + + item = GetDlgItem(m_Window, IDC_INSTALLTAB_AUTHOR_TEXT); + Edit_SetCueBannerText(item, L"..."); + + item = GetDlgItem(m_Window, IDC_INSTALLTAB_VERSION_TEXT); + Edit_SetCueBannerText(item, L"..."); + + item = GetDlgItem(m_Window, IDC_PACKAGEINFO_COMPONENTS_LIST); + + DWORD extendedFlags = LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT; + + if (GetOSPlatform() >= OSPLATFORM_VISTA) + { + extendedFlags |= LVS_EX_DOUBLEBUFFER; + SetWindowTheme(item, L"explorer", nullptr); + } + + ListView_EnableGroupView(item, TRUE); + ListView_SetExtendedListViewStyleEx(item, 0, extendedFlags); + + // Add columns + LVCOLUMN lvc; + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.fmt = LVCFMT_LEFT; + lvc.iSubItem = 0; + lvc.cx = 252; + lvc.pszText = L"Name"; + ListView_InsertColumn(item, 0, &lvc); + + // Add groups + LVGROUP lvg; + lvg.cbSize = sizeof(LVGROUP); + lvg.mask = LVGF_HEADER | LVGF_GROUPID | LVGF_STATE; + lvg.state = (GetOSPlatform() >= OSPLATFORM_VISTA) ? LVGS_COLLAPSIBLE : LVGS_NORMAL; + lvg.iGroupId = 0; + lvg.pszHeader = L"Skin"; + ListView_InsertGroup(item, -1, &lvg); + lvg.iGroupId = 1; + lvg.pszHeader = L"Layouts"; + ListView_InsertGroup(item, -1, &lvg); + lvg.iGroupId = 2; + lvg.pszHeader = L"Plugins"; + ListView_InsertGroup(item, -1, &lvg); +} + +INT_PTR CALLBACK DialogPackage::TabInfo::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + return c_Dialog->m_TabInfo.OnCommand(wParam, lParam); + + case WM_NOTIFY: + return c_Dialog->m_TabInfo.OnNotify(wParam, lParam); + } + + return FALSE; +} + +INT_PTR DialogPackage::TabInfo::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_PACKAGEINFO_ADDSKIN_BUTTON: + { + c_Dialog->m_SkinFolder.second = SelectFolder(m_Window, g_Data.skinsPath); + if (!c_Dialog->m_SkinFolder.second.empty()) + { + c_Dialog->m_SkinFolder.first = PathFindFileName(c_Dialog->m_SkinFolder.second.c_str()); + c_Dialog->m_SkinFolder.first.pop_back(); // Remove slash + + HWND item = GetDlgItem(m_Window, IDC_PACKAGEINFO_COMPONENTS_LIST); + LVITEM lvi; + lvi.mask = LVIF_TEXT | LVIF_GROUPID; + lvi.iItem = 1; + lvi.iSubItem = 0; + lvi.iGroupId = 0; + lvi.pszText = (WCHAR*)c_Dialog->m_SkinFolder.first.c_str(); + ListView_InsertItem(item, &lvi); + + EnableWindow((HWND)lParam, FALSE); + c_Dialog->SetNextButtonState(); + } + } + break; + + case IDC_PACKAGEINFO_ADDTHEME_BUTTON: + { + std::wstring folder = SelectFolder(m_Window, g_Data.settingsPath + L"Layouts\\"); + if (!folder.empty()) + { + std::wstring name = PathFindFileName(folder.c_str()); + name.pop_back(); // Remove slash + + if (c_Dialog->m_LayoutFolders.insert(std::make_pair(name, folder)).second) + { + HWND item = GetDlgItem(m_Window, IDC_PACKAGEINFO_COMPONENTS_LIST); + LVITEM lvi; + lvi.mask = LVIF_TEXT | LVIF_GROUPID; + lvi.iItem = c_Dialog->m_LayoutFolders.size() + 1; + lvi.iSubItem = 0; + lvi.iGroupId = 1; + lvi.pszText = (WCHAR*)name.c_str(); + ListView_InsertItem(item, &lvi); + } + } + } + break; + + case IDC_PACKAGEINFO_ADDPLUGIN_BUTTON: + { + std::pair<std::wstring, std::wstring> plugins = SelectPlugin(m_Window); + std::wstring name = PathFindFileName(plugins.first.c_str()); + if (!name.empty() && c_Dialog->m_PluginFolders.insert(std::make_pair(name, plugins)).second) + { + HWND item = GetDlgItem(m_Window, IDC_PACKAGEINFO_COMPONENTS_LIST); + LVITEM lvi; + lvi.mask = LVIF_TEXT | LVIF_GROUPID; + lvi.iItem = c_Dialog->m_PluginFolders.size() + 1; + lvi.iSubItem = 0; + lvi.iGroupId = 2; + lvi.pszText = (WCHAR*)name.c_str(); + ListView_InsertItem(item, &lvi); + } + } + break; + + case IDC_PACKAGEINFO_REMOVE_BUTTON: + { + HWND item = GetDlgItem(m_Window, IDC_PACKAGEINFO_COMPONENTS_LIST); + int sel = ListView_GetNextItem(item, -1, LVNI_FOCUSED | LVNI_SELECTED); + if (sel != -1) + { + WCHAR buffer[MAX_PATH]; + + // Remove unchecked items from the component sets + LVITEM lvi; + lvi.mask = LVIF_GROUPID | LVIF_TEXT; + lvi.iSubItem = 0; + lvi.iItem = sel; + lvi.pszText = buffer; + lvi.cchTextMax = _countof(buffer); + ListView_GetItem(item, &lvi); + + ListView_DeleteItem(item, sel); + + const std::wstring name = buffer; + switch (lvi.iGroupId) + { + case 0: + { + item = GetDlgItem(m_Window, IDC_PACKAGEINFO_ADDSKIN_BUTTON); + EnableWindow(item, TRUE); + c_Dialog->m_SkinFolder.first.clear(); + c_Dialog->m_SkinFolder.second.clear(); + c_Dialog->SetNextButtonState(); + } + break; + + case 1: + c_Dialog->m_LayoutFolders.erase(c_Dialog->m_LayoutFolders.find(name)); + break; + + case 2: + c_Dialog->m_PluginFolders.erase(c_Dialog->m_PluginFolders.find(name)); + break; + } + } + } + break; + + case IDC_PACKAGEINFO_NAME_EDIT: + case IDC_PACKAGEINFO_AUTHOR_EDIT: + case IDC_PACKAGEINFO_VERSION_EDIT: + if (HIWORD(wParam) == EN_CHANGE) + { + WCHAR buffer[64]; + int len = GetWindowText((HWND)lParam, buffer, _countof(buffer)); + if (LOWORD(wParam) == IDC_PACKAGEINFO_NAME_EDIT) + { + c_Dialog->m_Name.assign(buffer, len); + } + else if (LOWORD(wParam) == IDC_PACKAGEINFO_AUTHOR_EDIT) + { + c_Dialog->m_Author.assign(buffer, len); + } + else // if (LOWORD(wParam) == IDC_PACKAGEINFO_VERSION_EDIT) + { + c_Dialog->m_Version.assign(buffer, len); + } + c_Dialog->SetNextButtonState(); + } + break; + + + default: + return FALSE; + } + + return TRUE; +} + +INT_PTR DialogPackage::TabInfo::OnNotify(WPARAM wParam, LPARAM lParam) +{ + LPNMHDR nm = (LPNMHDR)lParam; + switch (nm->code) + { + case LVN_ITEMCHANGED: + { + NMLISTVIEW* nmlv = (NMLISTVIEW*)lParam; + if (nm->idFrom == IDC_PACKAGEINFO_COMPONENTS_LIST) + { + BOOL selected = (nmlv->uNewState & LVIS_SELECTED); + + HWND item = GetDlgItem(m_Window, IDC_PACKAGEINFO_REMOVE_BUTTON); + EnableWindow(item, selected); + } + } + break; + + case NM_CLICK: + { + if (nm->idFrom == IDC_PACKAGEINFO_WHATIS_LINK) + { + c_Dialog->ShowHelp(); + } + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------------------------------- +// +// Options tab +// +// ----------------------------------------------------------------------------------------------- + +DialogPackage::TabOptions::TabOptions(HWND wnd) : Tab(GetInstanceHandle(), wnd, IDD_PACKAGEOPTIONS_TAB, DlgProc) +{ +} + +void DialogPackage::TabOptions::Initialize() +{ + m_Initialized = true; + + WCHAR buffer[MAX_PATH]; + SHGetFolderPath(nullptr, CSIDL_DESKTOPDIRECTORY, nullptr, SHGFP_TYPE_CURRENT, buffer); + + c_Dialog->m_TargetFile = buffer; + c_Dialog->m_TargetFile += L'\\'; + int pos = (int)c_Dialog->m_TargetFile.length() + 1; + c_Dialog->m_TargetFile += c_Dialog->m_Name; + c_Dialog->m_TargetFile += L'_'; + c_Dialog->m_TargetFile += c_Dialog->m_Version; + + // Escape reserved chars + for (int i = pos, isize = (int)c_Dialog->m_TargetFile.length(); i < isize; ++i) + { + if (wcschr(L"\\/:*?\"<>|", c_Dialog->m_TargetFile[i])) + { + c_Dialog->m_TargetFile[i] = L'_'; + } + } + + c_Dialog->m_TargetFile += L".rmskin"; + + HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_FILE_EDIT); + SetWindowText(item,c_Dialog->m_TargetFile.c_str()); + + item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADTHEME_RADIO); + if (c_Dialog->m_LayoutFolders.empty()) + { + EnableWindow(item, FALSE); + + item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_DONOTHING_RADIO); + Button_SetCheck(item, BST_CHECKED); + } + else + { + c_Dialog->m_LoadLayout = true; + c_Dialog->m_Load = (*c_Dialog->m_LayoutFolders.cbegin()).first; + + Button_SetCheck(item, BST_CHECKED); + + item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADTHEME_COMBO); + ShowWindow(item, SW_SHOWNORMAL); + + for (auto iter = c_Dialog->m_LayoutFolders.cbegin(); iter != c_Dialog->m_LayoutFolders.cend(); ++iter) + { + ComboBox_AddString(item, (*iter).first.c_str()); + } + ComboBox_SetCurSel(item, 0); + } + + item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKIN_EDIT); + Edit_SetCueBannerText(item, L"Select skin"); + + item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_RAINMETERVERSION_EDIT); + _snwprintf_s(buffer, _TRUNCATE, L"%s.%i", APPVERSION, revision_number); + SetWindowText(item, buffer); + c_Dialog->m_MinimumRainmeter = buffer; + + item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_WINDOWSVERSION_COMBO); + ComboBox_AddString(item, L"XP"); + ComboBox_AddString(item, L"Vista"); + ComboBox_AddString(item, L"7"); + ComboBox_SetCurSel(item, 0); + c_Dialog->m_MinimumWindows = g_OsNameVersions[0].version; +} + +INT_PTR CALLBACK DialogPackage::TabOptions::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + return c_Dialog->m_TabOptions.OnCommand(wParam, lParam); + } + + return FALSE; +} + +INT_PTR DialogPackage::TabOptions::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_PACKAGEOPTIONS_FILEBROWSE_BUTTON: + { + WCHAR buffer[MAX_PATH]; + HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_FILE_EDIT); + GetWindowText(item, buffer, _countof(buffer)); + + OPENFILENAME ofn = { sizeof(OPENFILENAME) }; + ofn.lpstrFilter = L"Rainmeter skin package (.rmskin)\0*.rmskin"; + ofn.lpstrTitle = L"Select Rainmeter skin package"; + ofn.lpstrDefExt = L"dll"; + ofn.lpstrFile = buffer; + ofn.nMaxFile = _countof(buffer); + ofn.hwndOwner = c_Dialog->GetWindow(); + + if (GetOpenFileName(&ofn)) + { + c_Dialog->m_TargetFile = buffer; + SetWindowText(item, buffer); + } + } + break; + + case IDC_PACKAGEOPTIONS_DONOTHING_RADIO: + { + HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKIN_EDIT); + ShowWindow(item, SW_HIDE); + item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON); + ShowWindow(item, SW_HIDE); + item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADTHEME_COMBO); + ShowWindow(item, SW_HIDE); + + c_Dialog->m_Load.clear(); + } + break; + + case IDC_PACKAGEOPTIONS_LOADSKIN_RADIO: + { + HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKIN_EDIT); + ShowWindow(item, SW_SHOWNORMAL); + + WCHAR buffer[MAX_PATH]; + GetWindowText(item, buffer, _countof(buffer)); + c_Dialog->m_Load = buffer; + c_Dialog->m_LoadLayout = false; + + item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON); + ShowWindow(item, SW_SHOWNORMAL); + item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADTHEME_COMBO); + ShowWindow(item, SW_HIDE); + } + break; + + case IDC_PACKAGEOPTIONS_LOADTHEME_RADIO: + { + HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKIN_EDIT); + ShowWindow(item, SW_HIDE); + item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON); + ShowWindow(item, SW_HIDE); + item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADTHEME_COMBO); + ShowWindow(item, SW_SHOWNORMAL); + + WCHAR buffer[MAX_PATH]; + GetWindowText(item, buffer, _countof(buffer)); + c_Dialog->m_Load = buffer; + c_Dialog->m_LoadLayout = true; + } + break; + + case IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON: + { + WCHAR buffer[MAX_PATH]; + HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKIN_EDIT); + GetWindowText(item, buffer, _countof(buffer)); + + OPENFILENAME ofn = { sizeof(OPENFILENAME) }; + ofn.Flags = OFN_FILEMUSTEXIST; + ofn.FlagsEx = OFN_EX_NOPLACESBAR; + ofn.lpstrFilter = L"Rainmeter skin file (.ini)\0*.ini"; + ofn.lpstrTitle = L"Select Rainmeter skin file"; + ofn.lpstrDefExt = L"ini"; + ofn.lpstrFile = buffer; + ofn.nMaxFile = _countof(buffer); + ofn.lpstrInitialDir = c_Dialog->m_SkinFolder.second.c_str(); + ofn.hwndOwner = c_Dialog->GetWindow(); + + if (GetOpenFileName(&ofn)) + { + // Make sure user didn't browse to some random folder + if (_wcsnicmp(ofn.lpstrInitialDir, buffer, c_Dialog->m_SkinFolder.second.length()) == 0) + { + // Skip everything before actual skin folder + const WCHAR* folderPath = buffer + c_Dialog->m_SkinFolder.second.length() - c_Dialog->m_SkinFolder.first.length() - 1; + SetWindowText(item, folderPath); + c_Dialog->m_Load = folderPath; + } + } + } + break; + + case IDC_PACKAGEOPTIONS_RAINMETERVERSION_EDIT: + if (HIWORD(wParam) == EN_CHANGE) + { + WCHAR buffer[32]; + GetWindowText((HWND)lParam, buffer, _countof(buffer)); + + // Get caret position + DWORD sel = Edit_GetSel((HWND)lParam); + + // Only allow numbers and period + WCHAR* version = buffer; + while (*version) + { + if (iswdigit(*version) || *version == L'.') + { + ++version; + } + else + { + *version = L'\0'; + SetWindowText((HWND)lParam, buffer); + + // Reset caret position + Edit_SetSel((HWND)lParam, LOWORD(sel), HIWORD(sel)); + break; + } + } + + c_Dialog->m_MinimumRainmeter = buffer; + } + break; + + case IDC_PACKAGEOPTIONS_WINDOWSVERSION_COMBO: + if (HIWORD(wParam) == CBN_SELCHANGE) + { + int sel = ComboBox_GetCurSel((HWND)lParam); + c_Dialog->m_MinimumWindows = g_OsNameVersions[sel].version; + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------------------------------- +// +// Advanced tab +// +// ----------------------------------------------------------------------------------------------- + +DialogPackage::TabAdvanced::TabAdvanced(HWND wnd) : Tab(GetInstanceHandle(), wnd, IDD_PACKAGEADVANCED_TAB, DlgProc) +{ +} + +void DialogPackage::TabAdvanced::Initialize() +{ + m_Initialized = true; +} + +INT_PTR CALLBACK DialogPackage::TabAdvanced::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + return c_Dialog->m_TabAdvanced.OnCommand(wParam, lParam); + + case WM_NOTIFY: + return c_Dialog->m_TabAdvanced.OnNotify(wParam, lParam); + } + + return FALSE; +} + +INT_PTR DialogPackage::TabAdvanced::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_PACKAGEADVANCED_HEADERROWSE_BUTTON: + { + WCHAR buffer[MAX_PATH]; + HWND item = GetDlgItem(m_Window, IDC_PACKAGEADVANCED_HEADER_EDIT); + GetWindowText(item, buffer, _countof(buffer)); + + OPENFILENAME ofn = { sizeof(OPENFILENAME) }; + ofn.Flags = OFN_FILEMUSTEXIST; + ofn.lpstrFilter = L"Bitmap file (.bmp)\0*.bmp"; + ofn.lpstrTitle = L"Select header image"; + ofn.lpstrDefExt = L"bmp"; + ofn.lpstrFile = buffer; + ofn.nMaxFile = _countof(buffer); + ofn.hwndOwner = c_Dialog->GetWindow(); + + if (GetOpenFileName(&ofn)) + { + c_Dialog->m_HeaderFile = buffer; + SetWindowText(item, buffer); + } + } + break; + + case IDC_PACKAGEADVANCED_VARIABLEFILES_EDIT: + if (HIWORD(wParam) == EN_CHANGE) + { + int length = GetWindowTextLength((HWND)lParam); + c_Dialog->m_VariableFiles.resize(length); + GetWindowText((HWND)lParam, &c_Dialog->m_VariableFiles[0], length + 1); + } + break; + + case IDC_PACKAGEADVANCED_MERGESKINS_CHECK: + c_Dialog->m_MergeSkins = !c_Dialog->m_MergeSkins; + break; + + default: + return FALSE; + } + + return TRUE; +} + +INT_PTR DialogPackage::TabAdvanced::OnNotify(WPARAM wParam, LPARAM lParam) +{ + LPNMHDR nm = (LPNMHDR)lParam; + switch (nm->code) + { + case NM_CLICK: + { + if (nm->idFrom == IDC_PACKAGEADVANCED_HELP_LINK) + { + c_Dialog->ShowHelp(); + } + } + break; + + default: + return FALSE; + } + + return TRUE; } \ No newline at end of file diff --git a/SkinInstaller/DialogPackage.h b/SkinInstaller/DialogPackage.h index 41f891b3..af20713c 100644 --- a/SkinInstaller/DialogPackage.h +++ b/SkinInstaller/DialogPackage.h @@ -1,127 +1,127 @@ -/* - Copyright (C) 2012 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef SKININSTALLER_DIALOGPACKAGE_H_ -#define SKININSTALLER_DIALOGPACKAGE_H_ - -#include <string> -#include "zip.h" -#include "../Library/Dialog.h" - -class DialogPackage : public Dialog -{ -public: - static void Create(HINSTANCE hInstance, LPWSTR lpCmdLine); - - static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - - static DialogPackage* c_Dialog; - -protected: - virtual Tab& GetActiveTab(); - -private: - class TabInfo : public Tab - { - public: - TabInfo(HWND window); - - virtual void Initialize(); - - static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - }; - - class TabOptions : public Tab - { - public: - TabOptions(HWND window); - - virtual void Initialize(); - - static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - }; - - class TabAdvanced : public Tab - { - public: - TabAdvanced(HWND window); - - virtual void Initialize(); - - static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); - INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); - }; - - DialogPackage(HWND wnd); - virtual ~DialogPackage(); - - void SetNextButtonState(); - - bool CreatePackage(); - static unsigned __stdcall PackagerThreadProc(void* pParam); - - bool AddFileToPackage(const WCHAR* realPath, const WCHAR* zipPath); - bool AddFolderToPackage(const std::wstring& path, std::wstring base, const WCHAR* zipPrefix); - - void ShowHelp(); - - static std::wstring SelectFolder(HWND parent, const std::wstring& existingPath); - static INT_PTR CALLBACK SelectFolderDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - - static std::pair<std::wstring, std::wstring> SelectPlugin(HWND parent); - static INT_PTR CALLBACK SelectPluginDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - - TabInfo m_TabInfo; - TabOptions m_TabOptions; - TabAdvanced m_TabAdvanced; - - std::wstring m_BackupTime; - - // Info tab - std::wstring m_Name; - std::wstring m_Author; - std::wstring m_Version; - std::pair<std::wstring, std::wstring> m_SkinFolder; - std::map<std::wstring, std::wstring> m_LayoutFolders; - std::map<std::wstring, std::pair<std::wstring, std::wstring>> m_PluginFolders; - - // Options tab - std::wstring m_TargetFile; - std::wstring m_MinimumRainmeter; - std::wstring m_MinimumWindows; - bool m_LoadLayout; - std::wstring m_Load; - - // Advanced tab - std::wstring m_HeaderFile; - std::wstring m_VariableFiles; - bool m_MergeSkins; - - HANDLE m_PackagerThread; - zipFile m_ZipFile; - bool m_AllowNonAsciiFilenames; -}; - -#endif +/* + Copyright (C) 2012 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef SKININSTALLER_DIALOGPACKAGE_H_ +#define SKININSTALLER_DIALOGPACKAGE_H_ + +#include <string> +#include "zip.h" +#include "../Library/Dialog.h" + +class DialogPackage : public Dialog +{ +public: + static void Create(HINSTANCE hInstance, LPWSTR lpCmdLine); + + static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + + static DialogPackage* c_Dialog; + +protected: + virtual Tab& GetActiveTab(); + +private: + class TabInfo : public Tab + { + public: + TabInfo(HWND window); + + virtual void Initialize(); + + static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + }; + + class TabOptions : public Tab + { + public: + TabOptions(HWND window); + + virtual void Initialize(); + + static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + }; + + class TabAdvanced : public Tab + { + public: + TabAdvanced(HWND window); + + virtual void Initialize(); + + static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + }; + + DialogPackage(HWND wnd); + virtual ~DialogPackage(); + + void SetNextButtonState(); + + bool CreatePackage(); + static unsigned __stdcall PackagerThreadProc(void* pParam); + + bool AddFileToPackage(const WCHAR* realPath, const WCHAR* zipPath); + bool AddFolderToPackage(const std::wstring& path, std::wstring base, const WCHAR* zipPrefix); + + void ShowHelp(); + + static std::wstring SelectFolder(HWND parent, const std::wstring& existingPath); + static INT_PTR CALLBACK SelectFolderDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + static std::pair<std::wstring, std::wstring> SelectPlugin(HWND parent); + static INT_PTR CALLBACK SelectPluginDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + TabInfo m_TabInfo; + TabOptions m_TabOptions; + TabAdvanced m_TabAdvanced; + + std::wstring m_BackupTime; + + // Info tab + std::wstring m_Name; + std::wstring m_Author; + std::wstring m_Version; + std::pair<std::wstring, std::wstring> m_SkinFolder; + std::map<std::wstring, std::wstring> m_LayoutFolders; + std::map<std::wstring, std::pair<std::wstring, std::wstring>> m_PluginFolders; + + // Options tab + std::wstring m_TargetFile; + std::wstring m_MinimumRainmeter; + std::wstring m_MinimumWindows; + bool m_LoadLayout; + std::wstring m_Load; + + // Advanced tab + std::wstring m_HeaderFile; + std::wstring m_VariableFiles; + bool m_MergeSkins; + + HANDLE m_PackagerThread; + zipFile m_ZipFile; + bool m_AllowNonAsciiFilenames; +}; + +#endif diff --git a/SkinInstaller/SkinInstaller.cpp b/SkinInstaller/SkinInstaller.cpp index 29b19d27..e9613ebc 100644 --- a/SkinInstaller/SkinInstaller.cpp +++ b/SkinInstaller/SkinInstaller.cpp @@ -1,336 +1,336 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" -#include "DialogPackage.h" -#include "DialogInstall.h" -#include "resource.h" -#include "SkinInstaller.h" - -EXTERN_C IMAGE_DOS_HEADER __ImageBase; - -GlobalData g_Data; - -OsNameVersion g_OsNameVersions[] = -{ - { L"XP", L"5.1" }, - { L"Vista", L"6.0" }, - { L"7", L"6.1" }, -// { L"8", L"6.2" } -}; - -/* -** Entry point -** -*/ -int SkinInstallerMain(LPWSTR lpCmdLine) -{ - // Avoid loading a dll from current directory - SetDllDirectory(L""); - - CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); - InitCommonControls(); - - if (lpCmdLine[0] == L'"') - { - // Strip quotes - ++lpCmdLine; - WCHAR* pos = wcsrchr(lpCmdLine, L'"'); - if (pos) - { - *pos = L'\0'; - } - } - - WCHAR buffer[MAX_PATH]; - GetModuleFileName(GetInstanceHandle(), buffer, MAX_PATH); - - // Remove the module's name from the path - WCHAR* pos = wcsrchr(buffer, L'\\'); - if (pos) - { - *(pos + 1) = L'\0'; - } - - g_Data.programPath = g_Data.settingsPath = buffer; - wcscat(buffer, L"Rainmeter.ini"); - - // Find the settings file and read skins path off it - if (_waccess(buffer, 0) == 0) - { - g_Data.iniFile = buffer; - if (GetPrivateProfileString(L"Rainmeter", L"SkinPath", L"", buffer, MAX_LINE_LENGTH, buffer) > 0) - { - g_Data.skinsPath = buffer; - if (g_Data.skinsPath.back() != L'\\' && g_Data.skinsPath.back() != L'/') - { - g_Data.skinsPath += L'\\'; - } - } - else - { - g_Data.skinsPath = g_Data.programPath; - g_Data.skinsPath += L"Skins\\"; - } - } - else - { - HRESULT hr = SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, buffer); - wcscat(buffer, L"\\Rainmeter\\"); - g_Data.settingsPath = buffer; - wcscat(buffer, L"Rainmeter.ini"); - g_Data.iniFile = buffer; - if (SUCCEEDED(hr) && _waccess(buffer, 0) == 0) - { - if (GetPrivateProfileString(L"Rainmeter", L"SkinPath", L"", buffer, MAX_LINE_LENGTH, buffer) > 0) - { - g_Data.skinsPath = buffer; - if (g_Data.skinsPath.back() != L'\\' && g_Data.skinsPath.back() != L'/') - { - g_Data.skinsPath += L'\\'; - } - } - else - { - std::wstring error = L"SkinPath not found.\nMake sure that Rainmeter has been run at least once."; - MessageBox(nullptr, error.c_str(), L"Rainmeter Skin Installer", MB_ERROR); - return 1; - } - } - else - { - std::wstring error = L"Rainmeter.ini not found.\nMake sure that Rainmeter has been run at least once."; - MessageBox(nullptr, error.c_str(), L"Rainmeter Skin Installer", MB_ERROR); - return 1; - } - } - - std::wstring layoutsPath = g_Data.settingsPath + L"Layouts\\"; - if (_waccess(layoutsPath.c_str(), 0) == -1) - { - // Migrate Themes into Layouts for backwards compatibility and rename - // Rainmeter.thm to Rainmeter.ini and RainThemes.bmp to Wallpaper.bmp. - std::wstring themesPath = g_Data.settingsPath + L"Themes"; - if (_waccess(themesPath.c_str(), 0) != -1) - { - // Migrate Themes into Layouts for backwards compatibility and rename - // Rainmeter.thm to Rainmeter.ini and RainThemes.bmp to Wallpaper.bmp. - MoveFile(themesPath.c_str(), layoutsPath.c_str()); - - layoutsPath += L'*'; // For FindFirstFile. - WIN32_FIND_DATA fd; - HANDLE hFind = FindFirstFile(layoutsPath.c_str(), &fd); - layoutsPath.pop_back(); // Remove '*'. - - if (hFind != INVALID_HANDLE_VALUE) - { - do - { - if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && - wcscmp(L".", fd.cFileName) != 0 && - wcscmp(L"..", fd.cFileName) != 0) - { - std::wstring layoutFolder = layoutsPath + fd.cFileName; - layoutFolder += L'\\'; - - std::wstring file = layoutFolder + L"Rainmeter.thm"; - if (_waccess(file.c_str(), 0) != -1) - { - std::wstring newFile = layoutFolder + L"Rainmeter.ini"; - MoveFile(file.c_str(), newFile.c_str()); - } - - file = layoutFolder + L"RainThemes.bmp"; - if (_waccess(file.c_str(), 0) != -1) - { - std::wstring newFile = layoutFolder + L"Wallpaper.bmp"; - MoveFile(file.c_str(), newFile.c_str()); - } - } - } - while (FindNextFile(hFind, &fd)); - - FindClose(hFind); - } - } - } - - if (_wcsnicmp(lpCmdLine, L"/LoadTheme ", 11) == 0) - { - // For backwards compatibility. - std::wstring args = L"!LoadLayout \""; - args += &lpCmdLine[11]; // Skip "/LoadTheme ". - args += L'"'; - - std::wstring file = g_Data.programPath + L"Rainmeter.exe"; - SHELLEXECUTEINFO sei = {0}; - sei.cbSize = sizeof(SHELLEXECUTEINFO); - sei.fMask = SEE_MASK_UNICODE; - sei.lpFile = file.c_str(); - sei.lpParameters = args.c_str(); - sei.lpDirectory = g_Data.programPath.c_str(); - sei.nShow = SW_SHOWNORMAL; - ShellExecuteEx(&sei); - - return 0; - } - else if (wcscmp(lpCmdLine, L"/Packager") == 0) - { - DialogPackage::Create(GetInstanceHandle(), lpCmdLine); - } - else - { - DialogInstall::Create(GetInstanceHandle(), lpCmdLine); - } - - return 0; -} - -bool CloseRainmeterIfActive() -{ - // Close Rainmeter.exe - HWND hwnd = FindWindow(L"DummyRainWClass", L"Rainmeter control window"); - if (hwnd) - { - DWORD pID, exitCode; - GetWindowThreadProcessId(hwnd, &pID); - HANDLE hProcess = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, FALSE, pID); - PostMessage(hwnd, WM_DESTROY, 0, 0); - - // Wait up to 5 seconds for Rainmeter to close - WaitForSingleObject(hProcess, 5000); - GetExitCodeProcess(hProcess, &exitCode); - CloseHandle(hProcess); - - if (exitCode == STILL_ACTIVE) - { - return false; - } - } - - return true; -} - -HINSTANCE GetInstanceHandle() -{ - return (HINSTANCE)&__ImageBase; -} - -// ----------------------------------------------------------------------------------------------- -// Stolen functions from Rainmeter Litestep.cpp, System.cpp, and Application.cpp -// ----------------------------------------------------------------------------------------------- - -bool IsRunning(const WCHAR* name, HANDLE* hMutex) -{ - // Create mutex - HANDLE hMutexTmp = CreateMutex(nullptr, FALSE, name); - if (GetLastError() == ERROR_ALREADY_EXISTS) - { - *hMutex = nullptr; - return true; - } - else - { - *hMutex = hMutexTmp; - return false; - } -} - -bool CopyFiles(const std::wstring& strFrom, const std::wstring& strTo, bool bMove) -{ - std::wstring tmpFrom(strFrom), tmpTo(strTo); - - // The strings must end with double nul - tmpFrom.append(1, L'\0'); - tmpTo.append(1, L'\0'); - - SHFILEOPSTRUCT fo = - { - nullptr, - bMove ? FO_MOVE : FO_COPY, - tmpFrom.c_str(), - tmpTo.c_str(), - FOF_NO_UI | FOF_NOCONFIRMATION | FOF_ALLOWUNDO - }; - - return SHFileOperation(&fo) == 0; -} - -OSPLATFORM GetOSPlatform() -{ - OSVERSIONINFOEX osvi = {sizeof(OSVERSIONINFOEX)}; - if (GetVersionEx((OSVERSIONINFO*)&osvi)) - { - if (osvi.dwMajorVersion == 5) - { - // Not checking for osvi.dwMinorVersion >= 1 because Rainmeter won't run on pre-XP - return OSPLATFORM_XP; - } - else if (osvi.dwMajorVersion == 6) - { - if (osvi.dwMinorVersion == 0) - { - return OSPLATFORM_VISTA; // Vista, Server 2008 - } - else - { - return OSPLATFORM_7; // 7, Server 2008R2 - } - } - else // newer OS - { - return OSPLATFORM_7; - } - } - - return OSPLATFORM_UNKNOWN; -} - -std::string ConvertToAscii(LPCTSTR str) -{ - std::string szAscii; - - if (str && *str) - { - int strLen = (int)wcslen(str); - int bufLen = WideCharToMultiByte(CP_ACP, 0, str, strLen, nullptr, 0, nullptr, nullptr); - if (bufLen > 0) - { - szAscii.resize(bufLen); - WideCharToMultiByte(CP_ACP, 0, str, strLen, &szAscii[0], bufLen, nullptr, nullptr); - } - } - return szAscii; -} - -std::wstring ConvertToWide(LPCSTR str) -{ - std::wstring szWide; - - if (str && *str) - { - int strLen = (int)strlen(str); - int bufLen = MultiByteToWideChar(CP_ACP, 0, str, strLen, nullptr, 0); - if (bufLen > 0) - { - szWide.resize(bufLen); - MultiByteToWideChar(CP_ACP, 0, str, strLen, &szWide[0], bufLen); - } - } - return szWide; +/* + Copyright (C) 2011 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" +#include "DialogPackage.h" +#include "DialogInstall.h" +#include "resource.h" +#include "SkinInstaller.h" + +EXTERN_C IMAGE_DOS_HEADER __ImageBase; + +GlobalData g_Data; + +OsNameVersion g_OsNameVersions[] = +{ + { L"XP", L"5.1" }, + { L"Vista", L"6.0" }, + { L"7", L"6.1" }, +// { L"8", L"6.2" } +}; + +/* +** Entry point +** +*/ +int SkinInstallerMain(LPWSTR lpCmdLine) +{ + // Avoid loading a dll from current directory + SetDllDirectory(L""); + + CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + InitCommonControls(); + + if (lpCmdLine[0] == L'"') + { + // Strip quotes + ++lpCmdLine; + WCHAR* pos = wcsrchr(lpCmdLine, L'"'); + if (pos) + { + *pos = L'\0'; + } + } + + WCHAR buffer[MAX_PATH]; + GetModuleFileName(GetInstanceHandle(), buffer, MAX_PATH); + + // Remove the module's name from the path + WCHAR* pos = wcsrchr(buffer, L'\\'); + if (pos) + { + *(pos + 1) = L'\0'; + } + + g_Data.programPath = g_Data.settingsPath = buffer; + wcscat(buffer, L"Rainmeter.ini"); + + // Find the settings file and read skins path off it + if (_waccess(buffer, 0) == 0) + { + g_Data.iniFile = buffer; + if (GetPrivateProfileString(L"Rainmeter", L"SkinPath", L"", buffer, MAX_LINE_LENGTH, buffer) > 0) + { + g_Data.skinsPath = buffer; + if (g_Data.skinsPath.back() != L'\\' && g_Data.skinsPath.back() != L'/') + { + g_Data.skinsPath += L'\\'; + } + } + else + { + g_Data.skinsPath = g_Data.programPath; + g_Data.skinsPath += L"Skins\\"; + } + } + else + { + HRESULT hr = SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, buffer); + wcscat(buffer, L"\\Rainmeter\\"); + g_Data.settingsPath = buffer; + wcscat(buffer, L"Rainmeter.ini"); + g_Data.iniFile = buffer; + if (SUCCEEDED(hr) && _waccess(buffer, 0) == 0) + { + if (GetPrivateProfileString(L"Rainmeter", L"SkinPath", L"", buffer, MAX_LINE_LENGTH, buffer) > 0) + { + g_Data.skinsPath = buffer; + if (g_Data.skinsPath.back() != L'\\' && g_Data.skinsPath.back() != L'/') + { + g_Data.skinsPath += L'\\'; + } + } + else + { + std::wstring error = L"SkinPath not found.\nMake sure that Rainmeter has been run at least once."; + MessageBox(nullptr, error.c_str(), L"Rainmeter Skin Installer", MB_ERROR); + return 1; + } + } + else + { + std::wstring error = L"Rainmeter.ini not found.\nMake sure that Rainmeter has been run at least once."; + MessageBox(nullptr, error.c_str(), L"Rainmeter Skin Installer", MB_ERROR); + return 1; + } + } + + std::wstring layoutsPath = g_Data.settingsPath + L"Layouts\\"; + if (_waccess(layoutsPath.c_str(), 0) == -1) + { + // Migrate Themes into Layouts for backwards compatibility and rename + // Rainmeter.thm to Rainmeter.ini and RainThemes.bmp to Wallpaper.bmp. + std::wstring themesPath = g_Data.settingsPath + L"Themes"; + if (_waccess(themesPath.c_str(), 0) != -1) + { + // Migrate Themes into Layouts for backwards compatibility and rename + // Rainmeter.thm to Rainmeter.ini and RainThemes.bmp to Wallpaper.bmp. + MoveFile(themesPath.c_str(), layoutsPath.c_str()); + + layoutsPath += L'*'; // For FindFirstFile. + WIN32_FIND_DATA fd; + HANDLE hFind = FindFirstFile(layoutsPath.c_str(), &fd); + layoutsPath.pop_back(); // Remove '*'. + + if (hFind != INVALID_HANDLE_VALUE) + { + do + { + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && + wcscmp(L".", fd.cFileName) != 0 && + wcscmp(L"..", fd.cFileName) != 0) + { + std::wstring layoutFolder = layoutsPath + fd.cFileName; + layoutFolder += L'\\'; + + std::wstring file = layoutFolder + L"Rainmeter.thm"; + if (_waccess(file.c_str(), 0) != -1) + { + std::wstring newFile = layoutFolder + L"Rainmeter.ini"; + MoveFile(file.c_str(), newFile.c_str()); + } + + file = layoutFolder + L"RainThemes.bmp"; + if (_waccess(file.c_str(), 0) != -1) + { + std::wstring newFile = layoutFolder + L"Wallpaper.bmp"; + MoveFile(file.c_str(), newFile.c_str()); + } + } + } + while (FindNextFile(hFind, &fd)); + + FindClose(hFind); + } + } + } + + if (_wcsnicmp(lpCmdLine, L"/LoadTheme ", 11) == 0) + { + // For backwards compatibility. + std::wstring args = L"!LoadLayout \""; + args += &lpCmdLine[11]; // Skip "/LoadTheme ". + args += L'"'; + + std::wstring file = g_Data.programPath + L"Rainmeter.exe"; + SHELLEXECUTEINFO sei = {0}; + sei.cbSize = sizeof(SHELLEXECUTEINFO); + sei.fMask = SEE_MASK_UNICODE; + sei.lpFile = file.c_str(); + sei.lpParameters = args.c_str(); + sei.lpDirectory = g_Data.programPath.c_str(); + sei.nShow = SW_SHOWNORMAL; + ShellExecuteEx(&sei); + + return 0; + } + else if (wcscmp(lpCmdLine, L"/Packager") == 0) + { + DialogPackage::Create(GetInstanceHandle(), lpCmdLine); + } + else + { + DialogInstall::Create(GetInstanceHandle(), lpCmdLine); + } + + return 0; +} + +bool CloseRainmeterIfActive() +{ + // Close Rainmeter.exe + HWND hwnd = FindWindow(L"DummyRainWClass", L"Rainmeter control window"); + if (hwnd) + { + DWORD pID, exitCode; + GetWindowThreadProcessId(hwnd, &pID); + HANDLE hProcess = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, FALSE, pID); + PostMessage(hwnd, WM_DESTROY, 0, 0); + + // Wait up to 5 seconds for Rainmeter to close + WaitForSingleObject(hProcess, 5000); + GetExitCodeProcess(hProcess, &exitCode); + CloseHandle(hProcess); + + if (exitCode == STILL_ACTIVE) + { + return false; + } + } + + return true; +} + +HINSTANCE GetInstanceHandle() +{ + return (HINSTANCE)&__ImageBase; +} + +// ----------------------------------------------------------------------------------------------- +// Stolen functions from Rainmeter Litestep.cpp, System.cpp, and Application.cpp +// ----------------------------------------------------------------------------------------------- + +bool IsRunning(const WCHAR* name, HANDLE* hMutex) +{ + // Create mutex + HANDLE hMutexTmp = CreateMutex(nullptr, FALSE, name); + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + *hMutex = nullptr; + return true; + } + else + { + *hMutex = hMutexTmp; + return false; + } +} + +bool CopyFiles(const std::wstring& strFrom, const std::wstring& strTo, bool bMove) +{ + std::wstring tmpFrom(strFrom), tmpTo(strTo); + + // The strings must end with double nul + tmpFrom.append(1, L'\0'); + tmpTo.append(1, L'\0'); + + SHFILEOPSTRUCT fo = + { + nullptr, + bMove ? FO_MOVE : FO_COPY, + tmpFrom.c_str(), + tmpTo.c_str(), + FOF_NO_UI | FOF_NOCONFIRMATION | FOF_ALLOWUNDO + }; + + return SHFileOperation(&fo) == 0; +} + +OSPLATFORM GetOSPlatform() +{ + OSVERSIONINFOEX osvi = {sizeof(OSVERSIONINFOEX)}; + if (GetVersionEx((OSVERSIONINFO*)&osvi)) + { + if (osvi.dwMajorVersion == 5) + { + // Not checking for osvi.dwMinorVersion >= 1 because Rainmeter won't run on pre-XP + return OSPLATFORM_XP; + } + else if (osvi.dwMajorVersion == 6) + { + if (osvi.dwMinorVersion == 0) + { + return OSPLATFORM_VISTA; // Vista, Server 2008 + } + else + { + return OSPLATFORM_7; // 7, Server 2008R2 + } + } + else // newer OS + { + return OSPLATFORM_7; + } + } + + return OSPLATFORM_UNKNOWN; +} + +std::string ConvertToAscii(LPCTSTR str) +{ + std::string szAscii; + + if (str && *str) + { + int strLen = (int)wcslen(str); + int bufLen = WideCharToMultiByte(CP_ACP, 0, str, strLen, nullptr, 0, nullptr, nullptr); + if (bufLen > 0) + { + szAscii.resize(bufLen); + WideCharToMultiByte(CP_ACP, 0, str, strLen, &szAscii[0], bufLen, nullptr, nullptr); + } + } + return szAscii; +} + +std::wstring ConvertToWide(LPCSTR str) +{ + std::wstring szWide; + + if (str && *str) + { + int strLen = (int)strlen(str); + int bufLen = MultiByteToWideChar(CP_ACP, 0, str, strLen, nullptr, 0); + if (bufLen > 0) + { + szWide.resize(bufLen); + MultiByteToWideChar(CP_ACP, 0, str, strLen, &szWide[0], bufLen); + } + } + return szWide; } \ No newline at end of file diff --git a/SkinInstaller/SkinInstaller.def b/SkinInstaller/SkinInstaller.def index 1bbfc2fc..99c9fe34 100644 --- a/SkinInstaller/SkinInstaller.def +++ b/SkinInstaller/SkinInstaller.def @@ -1,4 +1,4 @@ -LIBRARY -EXPORTS - ; Private - SkinInstallerMain @1 NONAME +LIBRARY +EXPORTS + ; Private + SkinInstallerMain @1 NONAME diff --git a/SkinInstaller/SkinInstaller.h b/SkinInstaller/SkinInstaller.h index 47d3aef0..069c5cb3 100644 --- a/SkinInstaller/SkinInstaller.h +++ b/SkinInstaller/SkinInstaller.h @@ -1,61 +1,61 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef SKININSTALLER_UTIL_H_ -#define SKININSTALLER_UTIL_H_ - -#include <string> -#include "zip.h" -#include "unzip.h" - -#define MAX_LINE_LENGTH 4096 -#define MB_ERROR MB_OK | MB_TOPMOST | MB_ICONERROR - -struct GlobalData -{ - std::wstring programPath; - std::wstring settingsPath; - std::wstring skinsPath; - std::wstring iniFile; -}; - -struct OsNameVersion -{ - const WCHAR* name; - const WCHAR* version; -}; - -enum OSPLATFORM -{ - OSPLATFORM_UNKNOWN = 0, - OSPLATFORM_XP, - OSPLATFORM_VISTA, - OSPLATFORM_7 -}; - -HINSTANCE GetInstanceHandle(); - -bool CloseRainmeterIfActive(); -OSPLATFORM GetOSPlatform(); - -bool IsRunning(const WCHAR* name, HANDLE* hMutex); -bool CopyFiles(const std::wstring& strFrom, const std::wstring& strTo, bool bMove = false); -std::string ConvertToAscii(LPCTSTR str); -std::wstring ConvertToWide(LPCSTR str); - -#endif +/* + Copyright (C) 2011 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef SKININSTALLER_UTIL_H_ +#define SKININSTALLER_UTIL_H_ + +#include <string> +#include "zip.h" +#include "unzip.h" + +#define MAX_LINE_LENGTH 4096 +#define MB_ERROR MB_OK | MB_TOPMOST | MB_ICONERROR + +struct GlobalData +{ + std::wstring programPath; + std::wstring settingsPath; + std::wstring skinsPath; + std::wstring iniFile; +}; + +struct OsNameVersion +{ + const WCHAR* name; + const WCHAR* version; +}; + +enum OSPLATFORM +{ + OSPLATFORM_UNKNOWN = 0, + OSPLATFORM_XP, + OSPLATFORM_VISTA, + OSPLATFORM_7 +}; + +HINSTANCE GetInstanceHandle(); + +bool CloseRainmeterIfActive(); +OSPLATFORM GetOSPlatform(); + +bool IsRunning(const WCHAR* name, HANDLE* hMutex); +bool CopyFiles(const std::wstring& strFrom, const std::wstring& strTo, bool bMove = false); +std::string ConvertToAscii(LPCTSTR str); +std::wstring ConvertToWide(LPCSTR str); + +#endif diff --git a/SkinInstaller/SkinInstaller.rc b/SkinInstaller/SkinInstaller.rc index a1b6494d..4d95a2bf 100644 --- a/SkinInstaller/SkinInstaller.rc +++ b/SkinInstaller/SkinInstaller.rc @@ -1,199 +1,199 @@ -#include <Windows.h> -#include "resource.h" -#include "../Version.h" - -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION FILEVER - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileDescription", "Rainmeter Skin Installer" - VALUE "FileVersion", STRFILEVER - VALUE "LegalCopyright", " 2013 - All authors" - VALUE "OriginalFilename", "SkinInstaller.dll" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDR_INSTALL_MENU MENU -{ - POPUP " " - { - MENUITEM "Backup skins", IDM_INSTALL_BACKUPSKINS - MENUITEM "Install fonts to system", IDM_INSTALL_SYSTEMFONTS, GRAYED - MENUITEM SEPARATOR - MENUITEM " ", IDM_INSTALL_FORMAT, GRAYED - } -} - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_PACKAGE_DIALOG DIALOGEX 0, 0, 300, 280 -STYLE DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Rainmeter Skin Packager" -FONT 8, "MS Shell Dlg 2" -{ - CONTROL "", IDC_PACKAGE_TAB, "SysTabControl32", TCS_TABS | TCS_FIXEDWIDTH, 6, 6, 288, 251 - DEFPUSHBUTTON "Next", IDC_PACKAGE_NEXT_BUTTON, 188, 261, 50, 14, WS_DISABLED - PUSHBUTTON "Create package", IDC_PACKAGE_CREATEPACKAGE_BUTTON, 158, 261, 80, 14, NOT WS_VISIBLE - PUSHBUTTON "Cancel", IDCANCEL, 243, 261, 50, 14 -} - -IDD_PACKAGEINFO_TAB DIALOGEX 15, 15, 270, 235 -STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS -FONT 8, "MS Shell Dlg 2" -{ - LTEXT "Enter the information and select the components to use for the .rmskin package.", IDC_STATIC, 0, 0, 264, 19 - - GROUPBOX "Information", IDC_STATIC, 0, 35, 270, 70 - LTEXT "Name:", IDC_STATIC, 6, 51, 35, 9 - EDITTEXT IDC_PACKAGEINFO_NAME_EDIT, 56, 48, 208, 14 - LTEXT "Author:", IDC_STATIC, 6, 69, 35, 9 - EDITTEXT IDC_PACKAGEINFO_AUTHOR_EDIT, 56, 66, 208, 14 - LTEXT "Version:", IDC_STATIC, 6, 87, 35, 9 - EDITTEXT IDC_PACKAGEINFO_VERSION_EDIT, 56, 83, 140, 14 - - GROUPBOX "Components", IDC_STATIC, 0, 110, 270, 108 - CONTROL "", IDC_PACKAGEINFO_COMPONENTS_LIST, "SysListView32", LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, 6, 125, 182, 86 - PUSHBUTTON "Add skin...", IDC_PACKAGEINFO_ADDSKIN_BUTTON, 194, 125, 70, 14 - PUSHBUTTON "Add layout...", IDC_PACKAGEINFO_ADDTHEME_BUTTON, 194, 144, 70, 14 - PUSHBUTTON "Add plugin...", IDC_PACKAGEINFO_ADDPLUGIN_BUTTON, 194, 162, 70, 14 - PUSHBUTTON "Remove", IDC_PACKAGEINFO_REMOVE_BUTTON, 194, 197, 70, 14, WS_DISABLED - CONTROL "<A>What is a .rmskin package?</A>", IDC_PACKAGEINFO_WHATIS_LINK, "SysLink", 0x0, 0, 225, 264, 9 -} - -IDD_PACKAGEOPTIONS_TAB DIALOGEX 15, 30, 270, 220 -STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS -FONT 8, "MS Shell Dlg 2" -{ - LTEXT "Save package to:", IDC_STATIC, 0, 0, 264, 9 - EDITTEXT IDC_PACKAGEOPTIONS_FILE_EDIT, 0, 17, 240, 14, ES_READONLY | ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP - PUSHBUTTON "...", IDC_PACKAGEOPTIONS_FILEBROWSE_BUTTON, 245, 17, 25, 14, WS_TABSTOP - - - GROUPBOX "After installation", IDC_STATIC, 0, 101, 270, 58 - AUTORADIOBUTTON "Do nothing", IDC_PACKAGEOPTIONS_DONOTHING_RADIO, 6, 116, 85, 9, WS_TABSTOP - AUTORADIOBUTTON "Load skin", IDC_PACKAGEOPTIONS_LOADSKIN_RADIO, 6, 129, 85, 9, WS_TABSTOP - EDITTEXT IDC_PACKAGEOPTIONS_LOADSKIN_EDIT, 96, 126, 138, 14, ES_READONLY | ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | NOT WS_VISIBLE - PUSHBUTTON "...", IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON, 239, 126, 25, 14, WS_TABSTOP | NOT WS_VISIBLE - AUTORADIOBUTTON "Load layout", IDC_PACKAGEOPTIONS_LOADTHEME_RADIO, 6, 142, 85, 9, WS_TABSTOP - COMBOBOX IDC_PACKAGEOPTIONS_LOADTHEME_COMBO, 96, 139, 168, 14, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP | NOT WS_VISIBLE - - GROUPBOX "Minimum requirements", IDC_STATIC, 0, 164, 270, 53 - LTEXT "Rainmeter version:", IDC_STATIC, 6, 180, 85, 9 - EDITTEXT IDC_PACKAGEOPTIONS_RAINMETERVERSION_EDIT, 96, 177, 80, 14 - LTEXT "Windows version:", IDC_STATIC, 6, 198, 85, 9 - COMBOBOX IDC_PACKAGEOPTIONS_WINDOWSVERSION_COMBO, 96, 195, 80, 14, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - LTEXT "Creating...", IDC_INSTALLTAB_CREATING_TEXT, 0, 0, 270, 100, NOT WS_VISIBLE - CONTROL "", IDC_INSTALLTAB_CREATING_BAR, "msctls_progress32", PBS_MARQUEE | NOT WS_VISIBLE | WS_BORDER, 0, 15, 270, 11 -} - -IDD_PACKAGEADVANCED_TAB DIALOGEX 15, 30, 270, 220 -STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS -FONT 8, "MS Shell Dlg 2" -{ - LTEXT "Header image:", IDC_STATIC, 0, 3, 85, 9 - EDITTEXT IDC_PACKAGEADVANCED_HEADER_EDIT, 90, 0, 150, 14, ES_READONLY | ES_AUTOHSCROLL | WS_TABSTOP - PUSHBUTTON "...", IDC_PACKAGEADVANCED_HEADERROWSE_BUTTON, 245, 0, 25, 14, WS_TABSTOP - LTEXT "Variables files:", IDC_STATIC, 0, 24, 85, 9 - EDITTEXT IDC_PACKAGEADVANCED_VARIABLEFILES_EDIT, 90, 21, 180, 14, ES_AUTOHSCROLL | WS_TABSTOP - AUTOCHECKBOX "Merge skins", IDC_PACKAGEADVANCED_MERGESKINS_CHECK, 0, 42, 85, 9, WS_TABSTOP - CONTROL "<A>Help</A>", IDC_PACKAGEADVANCED_HELP_LINK, "SysLink", 0x0, 0, 210, 264, 9 -} - -IDD_PACKAGESELECTFOLDER_DIALOG DIALOGEX 0, 0, 200, 100 -STYLE DS_CENTER | WS_POPUP | WS_TILEDWINDOW -EXSTYLE WS_EX_TOOLWINDOW -CAPTION "Add" -FONT 8, "MS Shell Dlg 2" -{ - AUTORADIOBUTTON "", IDC_PACKAGESELECTFOLDER_EXISTING_RADIO, 6, 6, 220, 9, WS_TABSTOP | BST_CHECKED - COMBOBOX IDC_PACKAGESELECTFOLDER_EXISTING_COMBO, 16, 19, 177, 14, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - AUTORADIOBUTTON "Add custom folder:", IDC_PACKAGESELECTFOLDER_CUSTOM_RADIO, 6, 40, 220, 9, WS_TABSTOP - EDITTEXT IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT, 16, 53, 149, 14, WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL | WS_DISABLED - PUSHBUTTON "...", IDC_PACKAGESELECTFOLDER_CUSTOMBROWSE_BUTTON, 170, 53, 25, 14, WS_TABSTOP | WS_DISABLED - DEFPUSHBUTTON "Add", IDOK, 146, 82, 50, 14 -} - -IDD_PACKAGESELECTPLUGIN_DIALOG DIALOGEX 0, 0, 200, 100 -STYLE DS_CENTER | WS_POPUP | WS_TILEDWINDOW -EXSTYLE WS_EX_TOOLWINDOW -CAPTION "Add" -FONT 8, "MS Shell Dlg 2" -{ - LTEXT "32-bit DLL:", IDC_STATIC, 6, 6, 220, 9 - EDITTEXT IDC_PACKAGESELECTPLUGIN_32BIT_EDIT, 16, 19, 149, 14, ES_READONLY | WS_BORDER - PUSHBUTTON "...", IDC_PACKAGESELECTPLUGIN_32BITBROWSE_BUTTON, 170, 19, 25, 14, WS_TABSTOP - LTEXT "64-bit DLL:", IDC_STATIC, 6, 40, 220, 9 - EDITTEXT IDC_PACKAGESELECTPLUGIN_64BIT_EDIT, 16, 53, 149, 14, ES_READONLY | WS_BORDER - PUSHBUTTON "...", IDC_PACKAGESELECTPLUGIN_64BITBROWSE_BUTTON, 170, 53, 25, 14, WS_TABSTOP - DEFPUSHBUTTON "Add", IDOK, 146, 82, 50, 14, WS_DISABLED -} - -IDD_INSTALL_DIALOG DIALOGEX 0, 0, 266, 250 -STYLE DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Rainmeter Skin Installer" -FONT 8, "MS Shell Dlg 2" -{ - CONTROL 0, IDC_INSTALL_HEADER_BITMAP, STATIC, SS_BITMAP | WS_CHILD | WS_VISIBLE, 0, 0, 266, 37 - CONTROL "", IDC_INSTALL_TAB, "SysTabControl32", TCS_TABS | TCS_FIXEDWIDTH, 6, 42, 254, 185 - PUSHBUTTON "Advanced", IDC_INSTALL_ADVANCED_BUTTON, 6, 231, 70, 14 - DEFPUSHBUTTON "Install", IDC_INSTALL_INSTALL_BUTTON, 155, 231, 50, 14 - PUSHBUTTON "Cancel", IDCANCEL, 210, 231, 50, 14 -} - -IDD_INSTALL_TAB DIALOGEX 15, 51, 236, 168 -STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS -FONT 8, "MS Shell Dlg 2" -{ - LTEXT "Name:", IDC_STATIC, 0, 0, 35, 9 - LTEXT "", IDC_INSTALLTAB_NAME_TEXT, 50, 0, 200, 9, SS_NOPREFIX - LTEXT "Author:", IDC_STATIC, 0, 13, 35, 9 - LTEXT "", IDC_INSTALLTAB_AUTHOR_TEXT, 50, 13, 200, 9, SS_NOPREFIX - LTEXT "Version:", IDC_STATIC, 0, 26, 35, 9 - LTEXT "", IDC_INSTALLTAB_VERSION_TEXT, 50, 26, 200, 9, SS_NOPREFIX - LTEXT "Included components:", IDC_STATIC, 0, 45, 80, 9 - CONTROL "", IDC_INSTALLTAB_COMPONENTS_LIST, "SysListView32", LVS_REPORT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, 0, 60, 234, 86 - AUTOCHECKBOX "Apply included layout", IDC_INSTALLTAB_THEME_CHECKBOX, 4, 155, 220, 9 - LTEXT "Installing...", IDC_INSTALLTAB_INPROGRESS_TEXT, 0, 0, 236, 60, NOT WS_VISIBLE - CONTROL "", IDC_INSTALLTAB_PROGRESS, "msctls_progress32", PBS_MARQUEE | NOT WS_VISIBLE | WS_BORDER, 0, 15, 236, 11 -} +#include <Windows.h> +#include "resource.h" +#include "../Version.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION FILEVER + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileDescription", "Rainmeter Skin Installer" + VALUE "FileVersion", STRFILEVER + VALUE "LegalCopyright", " 2013 - All authors" + VALUE "OriginalFilename", "SkinInstaller.dll" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_INSTALL_MENU MENU +{ + POPUP " " + { + MENUITEM "Backup skins", IDM_INSTALL_BACKUPSKINS + MENUITEM "Install fonts to system", IDM_INSTALL_SYSTEMFONTS, GRAYED + MENUITEM SEPARATOR + MENUITEM " ", IDM_INSTALL_FORMAT, GRAYED + } +} + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_PACKAGE_DIALOG DIALOGEX 0, 0, 300, 280 +STYLE DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Rainmeter Skin Packager" +FONT 8, "MS Shell Dlg 2" +{ + CONTROL "", IDC_PACKAGE_TAB, "SysTabControl32", TCS_TABS | TCS_FIXEDWIDTH, 6, 6, 288, 251 + DEFPUSHBUTTON "Next", IDC_PACKAGE_NEXT_BUTTON, 188, 261, 50, 14, WS_DISABLED + PUSHBUTTON "Create package", IDC_PACKAGE_CREATEPACKAGE_BUTTON, 158, 261, 80, 14, NOT WS_VISIBLE + PUSHBUTTON "Cancel", IDCANCEL, 243, 261, 50, 14 +} + +IDD_PACKAGEINFO_TAB DIALOGEX 15, 15, 270, 235 +STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg 2" +{ + LTEXT "Enter the information and select the components to use for the .rmskin package.", IDC_STATIC, 0, 0, 264, 19 + + GROUPBOX "Information", IDC_STATIC, 0, 35, 270, 70 + LTEXT "Name:", IDC_STATIC, 6, 51, 35, 9 + EDITTEXT IDC_PACKAGEINFO_NAME_EDIT, 56, 48, 208, 14 + LTEXT "Author:", IDC_STATIC, 6, 69, 35, 9 + EDITTEXT IDC_PACKAGEINFO_AUTHOR_EDIT, 56, 66, 208, 14 + LTEXT "Version:", IDC_STATIC, 6, 87, 35, 9 + EDITTEXT IDC_PACKAGEINFO_VERSION_EDIT, 56, 83, 140, 14 + + GROUPBOX "Components", IDC_STATIC, 0, 110, 270, 108 + CONTROL "", IDC_PACKAGEINFO_COMPONENTS_LIST, "SysListView32", LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, 6, 125, 182, 86 + PUSHBUTTON "Add skin...", IDC_PACKAGEINFO_ADDSKIN_BUTTON, 194, 125, 70, 14 + PUSHBUTTON "Add layout...", IDC_PACKAGEINFO_ADDTHEME_BUTTON, 194, 144, 70, 14 + PUSHBUTTON "Add plugin...", IDC_PACKAGEINFO_ADDPLUGIN_BUTTON, 194, 162, 70, 14 + PUSHBUTTON "Remove", IDC_PACKAGEINFO_REMOVE_BUTTON, 194, 197, 70, 14, WS_DISABLED + CONTROL "<A>What is a .rmskin package?</A>", IDC_PACKAGEINFO_WHATIS_LINK, "SysLink", 0x0, 0, 225, 264, 9 +} + +IDD_PACKAGEOPTIONS_TAB DIALOGEX 15, 30, 270, 220 +STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg 2" +{ + LTEXT "Save package to:", IDC_STATIC, 0, 0, 264, 9 + EDITTEXT IDC_PACKAGEOPTIONS_FILE_EDIT, 0, 17, 240, 14, ES_READONLY | ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP + PUSHBUTTON "...", IDC_PACKAGEOPTIONS_FILEBROWSE_BUTTON, 245, 17, 25, 14, WS_TABSTOP + + + GROUPBOX "After installation", IDC_STATIC, 0, 101, 270, 58 + AUTORADIOBUTTON "Do nothing", IDC_PACKAGEOPTIONS_DONOTHING_RADIO, 6, 116, 85, 9, WS_TABSTOP + AUTORADIOBUTTON "Load skin", IDC_PACKAGEOPTIONS_LOADSKIN_RADIO, 6, 129, 85, 9, WS_TABSTOP + EDITTEXT IDC_PACKAGEOPTIONS_LOADSKIN_EDIT, 96, 126, 138, 14, ES_READONLY | ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | NOT WS_VISIBLE + PUSHBUTTON "...", IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON, 239, 126, 25, 14, WS_TABSTOP | NOT WS_VISIBLE + AUTORADIOBUTTON "Load layout", IDC_PACKAGEOPTIONS_LOADTHEME_RADIO, 6, 142, 85, 9, WS_TABSTOP + COMBOBOX IDC_PACKAGEOPTIONS_LOADTHEME_COMBO, 96, 139, 168, 14, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP | NOT WS_VISIBLE + + GROUPBOX "Minimum requirements", IDC_STATIC, 0, 164, 270, 53 + LTEXT "Rainmeter version:", IDC_STATIC, 6, 180, 85, 9 + EDITTEXT IDC_PACKAGEOPTIONS_RAINMETERVERSION_EDIT, 96, 177, 80, 14 + LTEXT "Windows version:", IDC_STATIC, 6, 198, 85, 9 + COMBOBOX IDC_PACKAGEOPTIONS_WINDOWSVERSION_COMBO, 96, 195, 80, 14, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + LTEXT "Creating...", IDC_INSTALLTAB_CREATING_TEXT, 0, 0, 270, 100, NOT WS_VISIBLE + CONTROL "", IDC_INSTALLTAB_CREATING_BAR, "msctls_progress32", PBS_MARQUEE | NOT WS_VISIBLE | WS_BORDER, 0, 15, 270, 11 +} + +IDD_PACKAGEADVANCED_TAB DIALOGEX 15, 30, 270, 220 +STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg 2" +{ + LTEXT "Header image:", IDC_STATIC, 0, 3, 85, 9 + EDITTEXT IDC_PACKAGEADVANCED_HEADER_EDIT, 90, 0, 150, 14, ES_READONLY | ES_AUTOHSCROLL | WS_TABSTOP + PUSHBUTTON "...", IDC_PACKAGEADVANCED_HEADERROWSE_BUTTON, 245, 0, 25, 14, WS_TABSTOP + LTEXT "Variables files:", IDC_STATIC, 0, 24, 85, 9 + EDITTEXT IDC_PACKAGEADVANCED_VARIABLEFILES_EDIT, 90, 21, 180, 14, ES_AUTOHSCROLL | WS_TABSTOP + AUTOCHECKBOX "Merge skins", IDC_PACKAGEADVANCED_MERGESKINS_CHECK, 0, 42, 85, 9, WS_TABSTOP + CONTROL "<A>Help</A>", IDC_PACKAGEADVANCED_HELP_LINK, "SysLink", 0x0, 0, 210, 264, 9 +} + +IDD_PACKAGESELECTFOLDER_DIALOG DIALOGEX 0, 0, 200, 100 +STYLE DS_CENTER | WS_POPUP | WS_TILEDWINDOW +EXSTYLE WS_EX_TOOLWINDOW +CAPTION "Add" +FONT 8, "MS Shell Dlg 2" +{ + AUTORADIOBUTTON "", IDC_PACKAGESELECTFOLDER_EXISTING_RADIO, 6, 6, 220, 9, WS_TABSTOP | BST_CHECKED + COMBOBOX IDC_PACKAGESELECTFOLDER_EXISTING_COMBO, 16, 19, 177, 14, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + AUTORADIOBUTTON "Add custom folder:", IDC_PACKAGESELECTFOLDER_CUSTOM_RADIO, 6, 40, 220, 9, WS_TABSTOP + EDITTEXT IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT, 16, 53, 149, 14, WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL | WS_DISABLED + PUSHBUTTON "...", IDC_PACKAGESELECTFOLDER_CUSTOMBROWSE_BUTTON, 170, 53, 25, 14, WS_TABSTOP | WS_DISABLED + DEFPUSHBUTTON "Add", IDOK, 146, 82, 50, 14 +} + +IDD_PACKAGESELECTPLUGIN_DIALOG DIALOGEX 0, 0, 200, 100 +STYLE DS_CENTER | WS_POPUP | WS_TILEDWINDOW +EXSTYLE WS_EX_TOOLWINDOW +CAPTION "Add" +FONT 8, "MS Shell Dlg 2" +{ + LTEXT "32-bit DLL:", IDC_STATIC, 6, 6, 220, 9 + EDITTEXT IDC_PACKAGESELECTPLUGIN_32BIT_EDIT, 16, 19, 149, 14, ES_READONLY | WS_BORDER + PUSHBUTTON "...", IDC_PACKAGESELECTPLUGIN_32BITBROWSE_BUTTON, 170, 19, 25, 14, WS_TABSTOP + LTEXT "64-bit DLL:", IDC_STATIC, 6, 40, 220, 9 + EDITTEXT IDC_PACKAGESELECTPLUGIN_64BIT_EDIT, 16, 53, 149, 14, ES_READONLY | WS_BORDER + PUSHBUTTON "...", IDC_PACKAGESELECTPLUGIN_64BITBROWSE_BUTTON, 170, 53, 25, 14, WS_TABSTOP + DEFPUSHBUTTON "Add", IDOK, 146, 82, 50, 14, WS_DISABLED +} + +IDD_INSTALL_DIALOG DIALOGEX 0, 0, 266, 250 +STYLE DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Rainmeter Skin Installer" +FONT 8, "MS Shell Dlg 2" +{ + CONTROL 0, IDC_INSTALL_HEADER_BITMAP, STATIC, SS_BITMAP | WS_CHILD | WS_VISIBLE, 0, 0, 266, 37 + CONTROL "", IDC_INSTALL_TAB, "SysTabControl32", TCS_TABS | TCS_FIXEDWIDTH, 6, 42, 254, 185 + PUSHBUTTON "Advanced", IDC_INSTALL_ADVANCED_BUTTON, 6, 231, 70, 14 + DEFPUSHBUTTON "Install", IDC_INSTALL_INSTALL_BUTTON, 155, 231, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 210, 231, 50, 14 +} + +IDD_INSTALL_TAB DIALOGEX 15, 51, 236, 168 +STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg 2" +{ + LTEXT "Name:", IDC_STATIC, 0, 0, 35, 9 + LTEXT "", IDC_INSTALLTAB_NAME_TEXT, 50, 0, 200, 9, SS_NOPREFIX + LTEXT "Author:", IDC_STATIC, 0, 13, 35, 9 + LTEXT "", IDC_INSTALLTAB_AUTHOR_TEXT, 50, 13, 200, 9, SS_NOPREFIX + LTEXT "Version:", IDC_STATIC, 0, 26, 35, 9 + LTEXT "", IDC_INSTALLTAB_VERSION_TEXT, 50, 26, 200, 9, SS_NOPREFIX + LTEXT "Included components:", IDC_STATIC, 0, 45, 80, 9 + CONTROL "", IDC_INSTALLTAB_COMPONENTS_LIST, "SysListView32", LVS_REPORT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, 0, 60, 234, 86 + AUTOCHECKBOX "Apply included layout", IDC_INSTALLTAB_THEME_CHECKBOX, 4, 155, 220, 9 + LTEXT "Installing...", IDC_INSTALLTAB_INPROGRESS_TEXT, 0, 0, 236, 60, NOT WS_VISIBLE + CONTROL "", IDC_INSTALLTAB_PROGRESS, "msctls_progress32", PBS_MARQUEE | NOT WS_VISIBLE | WS_BORDER, 0, 15, 236, 11 +} diff --git a/SkinInstaller/SkinInstaller.vcxproj b/SkinInstaller/SkinInstaller.vcxproj index 5c013b6d..84a10696 100644 --- a/SkinInstaller/SkinInstaller.vcxproj +++ b/SkinInstaller/SkinInstaller.vcxproj @@ -1,110 +1,110 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}</ProjectGuid> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - <Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" /> - </ImportGroup> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <MASM> - <PreprocessorDefinitions>NOOLDPENTIUMCODE</PreprocessorDefinitions> - </MASM> - <ClCompile> - <PreprocessorDefinitions>ZLIB_WINAPI;NOCRYPT;NOUNCRYPT;NO_GZIP;ASMV;ASMINF;NOOLDPENTIUMCODE;HAVE_CONFIG_H;SUPPORT_UTF8;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <DisableSpecificWarnings>4244;4267;4482;4530;4996</DisableSpecificWarnings> - <AdditionalIncludeDirectories>./zlib;./zlib/minizip</AdditionalIncludeDirectories> - <ExceptionHandling>false</ExceptionHandling> - </ClCompile> - <Link> - <SubSystem>Windows</SubSystem> - <AdditionalDependencies>Imagehlp.lib;Wininet.lib;Comctl32.lib;Version.lib;UxTheme.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies> - <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions> - <ModuleDefinitionFile>SkinInstaller.def</ModuleDefinitionFile> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClCompile Include="..\Common\StringUtil.cpp" /> - <ClCompile Include="..\Library\Dialog.cpp" /> - <ClCompile Include="DialogInstall.cpp" /> - <ClCompile Include="DialogPackage.cpp" /> - <ClCompile Include="StdAfx.cpp" /> - <ClCompile Include="SkinInstaller.cpp" /> - <ClCompile Include="zlib\adler32.c" /> - <ClCompile Include="zlib\crc32.c" /> - <ClCompile Include="zlib\deflate.c" /> - <ClCompile Include="zlib\infback.c" /> - <ClCompile Include="zlib\inffas8664.c"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="zlib\inffast.c"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="zlib\inflate.c" /> - <ClCompile Include="zlib\inftrees.c" /> - <ClCompile Include="zlib\minizip\ioapi.c" /> - <ClCompile Include="zlib\minizip\iowin32.c" /> - <ClCompile Include="zlib\minizip\unzip.c" /> - <ClCompile Include="zlib\minizip\zip.c" /> - <ClCompile Include="zlib\trees.c" /> - <ClCompile Include="zlib\zutil.c" /> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="SkinInstaller.rc"> - </ResourceCompile> - </ItemGroup> - <ItemGroup> - <ClInclude Include="..\Library\Dialog.h" /> - <ClInclude Include="DialogInstall.h" /> - <ClInclude Include="DialogPackage.h" /> - <ClInclude Include="resource.h" /> - <ClInclude Include="StdAfx.h" /> - <ClInclude Include="SkinInstaller.h" /> - <ClInclude Include="zlib\crc32.h" /> - <ClInclude Include="zlib\deflate.h" /> - <ClInclude Include="zlib\inffast.h" /> - <ClInclude Include="zlib\inflate.h" /> - <ClInclude Include="zlib\inftrees.h" /> - <ClInclude Include="zlib\minizip\ioapi.h" /> - <ClInclude Include="zlib\minizip\iowin32.h" /> - <ClInclude Include="zlib\minizip\unzip.h" /> - <ClInclude Include="zlib\minizip\zip.h" /> - <ClInclude Include="zlib\zconf.h" /> - <ClInclude Include="zlib\zlib.h" /> - <ClInclude Include="zlib\zutil.h" /> - </ItemGroup> - <ItemGroup> - <MASM Include="zlib\match686.asm"> - <ExcludedFromBuild Condition="'$(Platform)'=='x64'">true</ExcludedFromBuild> - </MASM> - <MASM Include="zlib\gvmat64.asm"> - <ExcludedFromBuild Condition="'$(Platform)'=='Win32'">true</ExcludedFromBuild> - </MASM> - <MASM Include="zlib\inffas32.asm"> - <ExcludedFromBuild Condition="'$(Platform)'=='x64'">true</ExcludedFromBuild> - </MASM> - <MASM Include="zlib\inffasx64.asm"> - <ExcludedFromBuild Condition="'$(Platform)'=='Win32'">true</ExcludedFromBuild> - </MASM> - </ItemGroup> - <ItemGroup> - <None Include="SkinInstaller.def" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - <Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" /> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{6F5D4C4A-C8C3-41DA-BF44-6D42B76464DA}</ProjectGuid> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + <Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" /> + </ImportGroup> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <MASM> + <PreprocessorDefinitions>NOOLDPENTIUMCODE</PreprocessorDefinitions> + </MASM> + <ClCompile> + <PreprocessorDefinitions>ZLIB_WINAPI;NOCRYPT;NOUNCRYPT;NO_GZIP;ASMV;ASMINF;NOOLDPENTIUMCODE;HAVE_CONFIG_H;SUPPORT_UTF8;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <DisableSpecificWarnings>4244;4267;4482;4530;4996</DisableSpecificWarnings> + <AdditionalIncludeDirectories>./zlib;./zlib/minizip</AdditionalIncludeDirectories> + <ExceptionHandling>false</ExceptionHandling> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <AdditionalDependencies>Imagehlp.lib;Wininet.lib;Comctl32.lib;Version.lib;UxTheme.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions> + <ModuleDefinitionFile>SkinInstaller.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="..\Common\StringUtil.cpp" /> + <ClCompile Include="..\Library\Dialog.cpp" /> + <ClCompile Include="DialogInstall.cpp" /> + <ClCompile Include="DialogPackage.cpp" /> + <ClCompile Include="StdAfx.cpp" /> + <ClCompile Include="SkinInstaller.cpp" /> + <ClCompile Include="zlib\adler32.c" /> + <ClCompile Include="zlib\crc32.c" /> + <ClCompile Include="zlib\deflate.c" /> + <ClCompile Include="zlib\infback.c" /> + <ClCompile Include="zlib\inffas8664.c"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="zlib\inffast.c"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="zlib\inflate.c" /> + <ClCompile Include="zlib\inftrees.c" /> + <ClCompile Include="zlib\minizip\ioapi.c" /> + <ClCompile Include="zlib\minizip\iowin32.c" /> + <ClCompile Include="zlib\minizip\unzip.c" /> + <ClCompile Include="zlib\minizip\zip.c" /> + <ClCompile Include="zlib\trees.c" /> + <ClCompile Include="zlib\zutil.c" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="SkinInstaller.rc"> + </ResourceCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\Library\Dialog.h" /> + <ClInclude Include="DialogInstall.h" /> + <ClInclude Include="DialogPackage.h" /> + <ClInclude Include="resource.h" /> + <ClInclude Include="StdAfx.h" /> + <ClInclude Include="SkinInstaller.h" /> + <ClInclude Include="zlib\crc32.h" /> + <ClInclude Include="zlib\deflate.h" /> + <ClInclude Include="zlib\inffast.h" /> + <ClInclude Include="zlib\inflate.h" /> + <ClInclude Include="zlib\inftrees.h" /> + <ClInclude Include="zlib\minizip\ioapi.h" /> + <ClInclude Include="zlib\minizip\iowin32.h" /> + <ClInclude Include="zlib\minizip\unzip.h" /> + <ClInclude Include="zlib\minizip\zip.h" /> + <ClInclude Include="zlib\zconf.h" /> + <ClInclude Include="zlib\zlib.h" /> + <ClInclude Include="zlib\zutil.h" /> + </ItemGroup> + <ItemGroup> + <MASM Include="zlib\match686.asm"> + <ExcludedFromBuild Condition="'$(Platform)'=='x64'">true</ExcludedFromBuild> + </MASM> + <MASM Include="zlib\gvmat64.asm"> + <ExcludedFromBuild Condition="'$(Platform)'=='Win32'">true</ExcludedFromBuild> + </MASM> + <MASM Include="zlib\inffas32.asm"> + <ExcludedFromBuild Condition="'$(Platform)'=='x64'">true</ExcludedFromBuild> + </MASM> + <MASM Include="zlib\inffasx64.asm"> + <ExcludedFromBuild Condition="'$(Platform)'=='Win32'">true</ExcludedFromBuild> + </MASM> + </ItemGroup> + <ItemGroup> + <None Include="SkinInstaller.def" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + <Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" /> + </ImportGroup> </Project> \ No newline at end of file diff --git a/SkinInstaller/SkinInstaller.vcxproj.filters b/SkinInstaller/SkinInstaller.vcxproj.filters index 8101ca94..bdf54441 100644 --- a/SkinInstaller/SkinInstaller.vcxproj.filters +++ b/SkinInstaller/SkinInstaller.vcxproj.filters @@ -1,168 +1,168 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="Source Files"> - <UniqueIdentifier>{3f37d5c4-4ae6-401f-9453-10dfc5fdb7f7}</UniqueIdentifier> - <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions> - </Filter> - <Filter Include="Header Files"> - <UniqueIdentifier>{17b931a7-44f0-4e35-a315-8735fefc7099}</UniqueIdentifier> - <Extensions>h;hpp;hxx;hm;inl</Extensions> - </Filter> - <Filter Include="Resource Files"> - <UniqueIdentifier>{91b7f443-69f2-4af0-8898-79c86916bbc5}</UniqueIdentifier> - <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions> - </Filter> - <Filter Include="zlib"> - <UniqueIdentifier>{42a27d72-d4b7-4a2f-9f0b-5d552623914c}</UniqueIdentifier> - </Filter> - <Filter Include="zlib\minizip"> - <UniqueIdentifier>{b726e25d-2977-424a-b45b-8ee60ce6bd49}</UniqueIdentifier> - </Filter> - <Filter Include="Common"> - <UniqueIdentifier>{b69ece81-b900-41d8-9ccd-61476261c411}</UniqueIdentifier> - </Filter> - </ItemGroup> - <ItemGroup> - <ClCompile Include="StdAfx.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="zlib\adler32.c"> - <Filter>zlib</Filter> - </ClCompile> - <ClCompile Include="zlib\crc32.c"> - <Filter>zlib</Filter> - </ClCompile> - <ClCompile Include="zlib\deflate.c"> - <Filter>zlib</Filter> - </ClCompile> - <ClCompile Include="zlib\infback.c"> - <Filter>zlib</Filter> - </ClCompile> - <ClCompile Include="zlib\inflate.c"> - <Filter>zlib</Filter> - </ClCompile> - <ClCompile Include="zlib\inftrees.c"> - <Filter>zlib</Filter> - </ClCompile> - <ClCompile Include="zlib\trees.c"> - <Filter>zlib</Filter> - </ClCompile> - <ClCompile Include="zlib\zutil.c"> - <Filter>zlib</Filter> - </ClCompile> - <ClCompile Include="zlib\inffast.c"> - <Filter>zlib</Filter> - </ClCompile> - <ClCompile Include="zlib\inffas8664.c"> - <Filter>zlib</Filter> - </ClCompile> - <ClCompile Include="zlib\minizip\zip.c"> - <Filter>zlib\minizip</Filter> - </ClCompile> - <ClCompile Include="zlib\minizip\ioapi.c"> - <Filter>zlib\minizip</Filter> - </ClCompile> - <ClCompile Include="zlib\minizip\iowin32.c"> - <Filter>zlib\minizip</Filter> - </ClCompile> - <ClCompile Include="zlib\minizip\unzip.c"> - <Filter>zlib\minizip</Filter> - </ClCompile> - <ClCompile Include="..\Library\Dialog.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="DialogInstall.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="DialogPackage.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\Common\StringUtil.cpp"> - <Filter>Common</Filter> - </ClCompile> - <ClCompile Include="SkinInstaller.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ClInclude Include="resource.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="StdAfx.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="zlib\zutil.h"> - <Filter>zlib</Filter> - </ClInclude> - <ClInclude Include="zlib\crc32.h"> - <Filter>zlib</Filter> - </ClInclude> - <ClInclude Include="zlib\deflate.h"> - <Filter>zlib</Filter> - </ClInclude> - <ClInclude Include="zlib\inffast.h"> - <Filter>zlib</Filter> - </ClInclude> - <ClInclude Include="zlib\inflate.h"> - <Filter>zlib</Filter> - </ClInclude> - <ClInclude Include="zlib\inftrees.h"> - <Filter>zlib</Filter> - </ClInclude> - <ClInclude Include="zlib\zconf.h"> - <Filter>zlib</Filter> - </ClInclude> - <ClInclude Include="zlib\zlib.h"> - <Filter>zlib</Filter> - </ClInclude> - <ClInclude Include="zlib\minizip\zip.h"> - <Filter>zlib\minizip</Filter> - </ClInclude> - <ClInclude Include="zlib\minizip\ioapi.h"> - <Filter>zlib\minizip</Filter> - </ClInclude> - <ClInclude Include="zlib\minizip\iowin32.h"> - <Filter>zlib\minizip</Filter> - </ClInclude> - <ClInclude Include="zlib\minizip\unzip.h"> - <Filter>zlib\minizip</Filter> - </ClInclude> - <ClInclude Include="..\Library\Dialog.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="DialogInstall.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="DialogPackage.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="SkinInstaller.h"> - <Filter>Header Files</Filter> - </ClInclude> - </ItemGroup> - <ItemGroup> - <None Include="SkinInstaller.def"> - <Filter>Source Files</Filter> - </None> - </ItemGroup> - <ItemGroup> - <MASM Include="zlib\gvmat64.asm"> - <Filter>zlib</Filter> - </MASM> - <MASM Include="zlib\inffasx64.asm"> - <Filter>zlib</Filter> - </MASM> - <MASM Include="zlib\inffas32.asm"> - <Filter>zlib</Filter> - </MASM> - <MASM Include="zlib\match686.asm"> - <Filter>zlib</Filter> - </MASM> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="SkinInstaller.rc"> - <Filter>Resource Files</Filter> - </ResourceCompile> - </ItemGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{3f37d5c4-4ae6-401f-9453-10dfc5fdb7f7}</UniqueIdentifier> + <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{17b931a7-44f0-4e35-a315-8735fefc7099}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{91b7f443-69f2-4af0-8898-79c86916bbc5}</UniqueIdentifier> + <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions> + </Filter> + <Filter Include="zlib"> + <UniqueIdentifier>{42a27d72-d4b7-4a2f-9f0b-5d552623914c}</UniqueIdentifier> + </Filter> + <Filter Include="zlib\minizip"> + <UniqueIdentifier>{b726e25d-2977-424a-b45b-8ee60ce6bd49}</UniqueIdentifier> + </Filter> + <Filter Include="Common"> + <UniqueIdentifier>{b69ece81-b900-41d8-9ccd-61476261c411}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="StdAfx.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="zlib\adler32.c"> + <Filter>zlib</Filter> + </ClCompile> + <ClCompile Include="zlib\crc32.c"> + <Filter>zlib</Filter> + </ClCompile> + <ClCompile Include="zlib\deflate.c"> + <Filter>zlib</Filter> + </ClCompile> + <ClCompile Include="zlib\infback.c"> + <Filter>zlib</Filter> + </ClCompile> + <ClCompile Include="zlib\inflate.c"> + <Filter>zlib</Filter> + </ClCompile> + <ClCompile Include="zlib\inftrees.c"> + <Filter>zlib</Filter> + </ClCompile> + <ClCompile Include="zlib\trees.c"> + <Filter>zlib</Filter> + </ClCompile> + <ClCompile Include="zlib\zutil.c"> + <Filter>zlib</Filter> + </ClCompile> + <ClCompile Include="zlib\inffast.c"> + <Filter>zlib</Filter> + </ClCompile> + <ClCompile Include="zlib\inffas8664.c"> + <Filter>zlib</Filter> + </ClCompile> + <ClCompile Include="zlib\minizip\zip.c"> + <Filter>zlib\minizip</Filter> + </ClCompile> + <ClCompile Include="zlib\minizip\ioapi.c"> + <Filter>zlib\minizip</Filter> + </ClCompile> + <ClCompile Include="zlib\minizip\iowin32.c"> + <Filter>zlib\minizip</Filter> + </ClCompile> + <ClCompile Include="zlib\minizip\unzip.c"> + <Filter>zlib\minizip</Filter> + </ClCompile> + <ClCompile Include="..\Library\Dialog.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="DialogInstall.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="DialogPackage.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\Common\StringUtil.cpp"> + <Filter>Common</Filter> + </ClCompile> + <ClCompile Include="SkinInstaller.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="resource.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="StdAfx.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="zlib\zutil.h"> + <Filter>zlib</Filter> + </ClInclude> + <ClInclude Include="zlib\crc32.h"> + <Filter>zlib</Filter> + </ClInclude> + <ClInclude Include="zlib\deflate.h"> + <Filter>zlib</Filter> + </ClInclude> + <ClInclude Include="zlib\inffast.h"> + <Filter>zlib</Filter> + </ClInclude> + <ClInclude Include="zlib\inflate.h"> + <Filter>zlib</Filter> + </ClInclude> + <ClInclude Include="zlib\inftrees.h"> + <Filter>zlib</Filter> + </ClInclude> + <ClInclude Include="zlib\zconf.h"> + <Filter>zlib</Filter> + </ClInclude> + <ClInclude Include="zlib\zlib.h"> + <Filter>zlib</Filter> + </ClInclude> + <ClInclude Include="zlib\minizip\zip.h"> + <Filter>zlib\minizip</Filter> + </ClInclude> + <ClInclude Include="zlib\minizip\ioapi.h"> + <Filter>zlib\minizip</Filter> + </ClInclude> + <ClInclude Include="zlib\minizip\iowin32.h"> + <Filter>zlib\minizip</Filter> + </ClInclude> + <ClInclude Include="zlib\minizip\unzip.h"> + <Filter>zlib\minizip</Filter> + </ClInclude> + <ClInclude Include="..\Library\Dialog.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="DialogInstall.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="DialogPackage.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="SkinInstaller.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <None Include="SkinInstaller.def"> + <Filter>Source Files</Filter> + </None> + </ItemGroup> + <ItemGroup> + <MASM Include="zlib\gvmat64.asm"> + <Filter>zlib</Filter> + </MASM> + <MASM Include="zlib\inffasx64.asm"> + <Filter>zlib</Filter> + </MASM> + <MASM Include="zlib\inffas32.asm"> + <Filter>zlib</Filter> + </MASM> + <MASM Include="zlib\match686.asm"> + <Filter>zlib</Filter> + </MASM> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="SkinInstaller.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> </Project> \ No newline at end of file diff --git a/SkinInstaller/SkinInstallerLauncher.cpp b/SkinInstaller/SkinInstallerLauncher.cpp index 9508fce9..7bf4e076 100644 --- a/SkinInstaller/SkinInstallerLauncher.cpp +++ b/SkinInstaller/SkinInstallerLauncher.cpp @@ -1,129 +1,129 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include <Windows.h> -#include <Shlwapi.h> - -EXTERN_C IMAGE_DOS_HEADER __ImageBase; - -typedef int (*SkinInstallerMainFunc)(LPWSTR cmdLine); - -WCHAR* GetCommandLineArguments() -{ - WCHAR* args = GetCommandLine(); - - // Skip past (quoted) application path in cmdLine. - if (*args == L'"') - { - ++args; // Skip leading quote. - while (*args && *args != L'"') - { - ++args; - } - ++args; // Skip trailing quote. - } - else - { - while (*args && *args != L' ') - { - ++args; - } - } - - // Skip leading whitespace (similar to CRT implementation). - while (*args && *args <= L' ') - { - ++args; - } - - return args; -} - -/* -** Attempts to load SkinInstaller.dll. If it fails, retries after loading our own copies of the -** CRT DLLs in the Runtime directory. -*/ -HINSTANCE LoadSkinInstallerLibrary() -{ - HINSTANCE rmDll = LoadLibrary(L"SkinInstaller.dll"); - if (!rmDll) - { - WCHAR path[MAX_PATH]; - if (GetModuleFileName(nullptr, path, MAX_PATH) > 0) - { - PathRemoveFileSpec(path); - PathAppend(path, L"Runtime"); - SetDllDirectory(path); - PathAppend(path, L"msvcp120.dll"); - - // Loading msvcpNNN.dll will load msvcrNNN.dll as well. - HINSTANCE msvcrDll = LoadLibrary(path); - SetDllDirectory(L""); - - if (msvcrDll) - { - rmDll = LoadLibrary(L"SkinInstaller.dll"); - FreeLibrary(msvcrDll); - } - } - } - - return rmDll; -} - -/* -** Entry point. In Release builds, the entry point is Main() since the CRT is not used. -** -*/ -int APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) -{ - // Prevent system error message boxes. - UINT oldMode = SetErrorMode(0); - SetErrorMode(oldMode | SEM_FAILCRITICALERRORS); - - WCHAR* args = GetCommandLineArguments(); - - HINSTANCE skinInstallerDll = LoadSkinInstallerLibrary(); - if (skinInstallerDll) - { - auto skinInstallerMain = - (SkinInstallerMainFunc)GetProcAddress(skinInstallerDll, MAKEINTRESOURCEA(1)); - if (skinInstallerMain) - { - return skinInstallerMain(args); - } - } - - WCHAR message[128]; - wsprintf( - message, - L"SkinInstaller.dll load error %ld.", - GetLastError()); - MessageBox(nullptr, message, L"Skin Installer", MB_OK | MB_ICONERROR); - - return 1; -} - -#ifndef _DEBUG -EXTERN_C int WINAPI Main() -{ - int result = wWinMain(nullptr, nullptr, nullptr, 0); - ExitProcess(result); - return 0; // Never reached. -} -#endif +/* + Copyright (C) 2011 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <Windows.h> +#include <Shlwapi.h> + +EXTERN_C IMAGE_DOS_HEADER __ImageBase; + +typedef int (*SkinInstallerMainFunc)(LPWSTR cmdLine); + +WCHAR* GetCommandLineArguments() +{ + WCHAR* args = GetCommandLine(); + + // Skip past (quoted) application path in cmdLine. + if (*args == L'"') + { + ++args; // Skip leading quote. + while (*args && *args != L'"') + { + ++args; + } + ++args; // Skip trailing quote. + } + else + { + while (*args && *args != L' ') + { + ++args; + } + } + + // Skip leading whitespace (similar to CRT implementation). + while (*args && *args <= L' ') + { + ++args; + } + + return args; +} + +/* +** Attempts to load SkinInstaller.dll. If it fails, retries after loading our own copies of the +** CRT DLLs in the Runtime directory. +*/ +HINSTANCE LoadSkinInstallerLibrary() +{ + HINSTANCE rmDll = LoadLibrary(L"SkinInstaller.dll"); + if (!rmDll) + { + WCHAR path[MAX_PATH]; + if (GetModuleFileName(nullptr, path, MAX_PATH) > 0) + { + PathRemoveFileSpec(path); + PathAppend(path, L"Runtime"); + SetDllDirectory(path); + PathAppend(path, L"msvcp120.dll"); + + // Loading msvcpNNN.dll will load msvcrNNN.dll as well. + HINSTANCE msvcrDll = LoadLibrary(path); + SetDllDirectory(L""); + + if (msvcrDll) + { + rmDll = LoadLibrary(L"SkinInstaller.dll"); + FreeLibrary(msvcrDll); + } + } + } + + return rmDll; +} + +/* +** Entry point. In Release builds, the entry point is Main() since the CRT is not used. +** +*/ +int APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) +{ + // Prevent system error message boxes. + UINT oldMode = SetErrorMode(0); + SetErrorMode(oldMode | SEM_FAILCRITICALERRORS); + + WCHAR* args = GetCommandLineArguments(); + + HINSTANCE skinInstallerDll = LoadSkinInstallerLibrary(); + if (skinInstallerDll) + { + auto skinInstallerMain = + (SkinInstallerMainFunc)GetProcAddress(skinInstallerDll, MAKEINTRESOURCEA(1)); + if (skinInstallerMain) + { + return skinInstallerMain(args); + } + } + + WCHAR message[128]; + wsprintf( + message, + L"SkinInstaller.dll load error %ld.", + GetLastError()); + MessageBox(nullptr, message, L"Skin Installer", MB_OK | MB_ICONERROR); + + return 1; +} + +#ifndef _DEBUG +EXTERN_C int WINAPI Main() +{ + int result = wWinMain(nullptr, nullptr, nullptr, 0); + ExitProcess(result); + return 0; // Never reached. +} +#endif diff --git a/SkinInstaller/SkinInstallerLauncher.rc b/SkinInstaller/SkinInstallerLauncher.rc index efcdbb2e..d390551b 100644 --- a/SkinInstaller/SkinInstallerLauncher.rc +++ b/SkinInstaller/SkinInstallerLauncher.rc @@ -1,55 +1,55 @@ -#include <Windows.h> -#include "resource.h" -#include "../Version.h" - -LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT -#pragma code_page(1252) - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION FILEVER - PRODUCTVERSION PRODUCTVER - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileDescription", "Rainmeter Skin Installer" - VALUE "FileVersion", STRFILEVER - VALUE "LegalCopyright", " 2013 - All authors" - VALUE "OriginalFilename", "SkinInstaller.exe" - VALUE "ProductName", "Rainmeter" -#ifdef _WIN64 - VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" -#else - VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" -#endif //_WIN64 - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_SKININSTALLER ICON DISCARDABLE "res/Rainstaller.ico" +#include <Windows.h> +#include "resource.h" +#include "../Version.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION FILEVER + PRODUCTVERSION PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileDescription", "Rainmeter Skin Installer" + VALUE "FileVersion", STRFILEVER + VALUE "LegalCopyright", " 2013 - All authors" + VALUE "OriginalFilename", "SkinInstaller.exe" + VALUE "ProductName", "Rainmeter" +#ifdef _WIN64 + VALUE "ProductVersion", STRPRODUCTVER " (64-bit)" +#else + VALUE "ProductVersion", STRPRODUCTVER " (32-bit)" +#endif //_WIN64 + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_SKININSTALLER ICON DISCARDABLE "res/Rainstaller.ico" diff --git a/SkinInstaller/SkinInstallerLauncher.vcxproj b/SkinInstaller/SkinInstallerLauncher.vcxproj index 9aec9efa..430e1652 100644 --- a/SkinInstaller/SkinInstallerLauncher.vcxproj +++ b/SkinInstaller/SkinInstallerLauncher.vcxproj @@ -1,50 +1,50 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> - <PropertyGroup Label="Globals"> - <ProjectGuid>{2D8F1DDB-6470-45A1-B95A-3E2960641314}</ProjectGuid> - <ConfigurationType>Application</ConfigurationType> - <TargetName>SkinInstaller</TargetName> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <ItemDefinitionGroup> - <ClCompile> - <DisableSpecificWarnings>4018;4090;4114;4267;4351;4786;4800;4996</DisableSpecificWarnings> - </ClCompile> - <Link> - <SubSystem>Windows</SubSystem> - <EntryPointSymbol>wWinMainCRTStartup</EntryPointSymbol> - <AdditionalDependencies>Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - <Manifest> - <AdditionalManifestFiles>..\Application\Application.manifest</AdditionalManifestFiles> - </Manifest> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'"> - <ClCompile> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - <BufferSecurityCheck>false</BufferSecurityCheck> - </ClCompile> - <Link> - <EntryPointSymbol>Main</EntryPointSymbol> - <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClCompile Include="SkinInstallerLauncher.cpp" /> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="SkinInstallerLauncher.rc" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>{2D8F1DDB-6470-45A1-B95A-3E2960641314}</ProjectGuid> + <ConfigurationType>Application</ConfigurationType> + <TargetName>SkinInstaller</TargetName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup> + <ClCompile> + <DisableSpecificWarnings>4018;4090;4114;4267;4351;4786;4800;4996</DisableSpecificWarnings> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <EntryPointSymbol>wWinMainCRTStartup</EntryPointSymbol> + <AdditionalDependencies>Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + <Manifest> + <AdditionalManifestFiles>..\Application\Application.manifest</AdditionalManifestFiles> + </Manifest> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'"> + <ClCompile> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <BufferSecurityCheck>false</BufferSecurityCheck> + </ClCompile> + <Link> + <EntryPointSymbol>Main</EntryPointSymbol> + <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="SkinInstallerLauncher.cpp" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="SkinInstallerLauncher.rc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> </Project> \ No newline at end of file diff --git a/SkinInstaller/SkinInstallerLauncher.vcxproj.filters b/SkinInstaller/SkinInstallerLauncher.vcxproj.filters index a5dc8c34..b3706a27 100644 --- a/SkinInstaller/SkinInstallerLauncher.vcxproj.filters +++ b/SkinInstaller/SkinInstallerLauncher.vcxproj.filters @@ -1,27 +1,27 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="Source Files"> - <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> - </Filter> - <Filter Include="Header Files"> - <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> - <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> - </Filter> - <Filter Include="Resource Files"> - <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> - <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> - </Filter> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="SkinInstallerLauncher.rc"> - <Filter>Resource Files</Filter> - </ResourceCompile> - </ItemGroup> - <ItemGroup> - <ClCompile Include="SkinInstallerLauncher.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - </ItemGroup> +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="SkinInstallerLauncher.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> + <ItemGroup> + <ClCompile Include="SkinInstallerLauncher.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> </Project> \ No newline at end of file diff --git a/SkinInstaller/StdAfx.cpp b/SkinInstaller/StdAfx.cpp index a7369e66..6ecb6b07 100644 --- a/SkinInstaller/StdAfx.cpp +++ b/SkinInstaller/StdAfx.cpp @@ -1,19 +1,19 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "StdAfx.h" +/* + Copyright (C) 2011 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "StdAfx.h" diff --git a/SkinInstaller/StdAfx.h b/SkinInstaller/StdAfx.h index 774226f4..78c224a8 100644 --- a/SkinInstaller/StdAfx.h +++ b/SkinInstaller/StdAfx.h @@ -1,49 +1,49 @@ -/* - Copyright (C) 2011 Birunthan Mohanathas - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __STDAFX_H__ -#define __STDAFX_H__ - -// WINAPI -#include <Windows.h> -#include <Windowsx.h> -#include <Commdlg.h> -#include <Imagehlp.h> -#include <Lmcons.h> -#include <Shlobj.h> -#include <Shlwapi.h> -#include <Shellapi.h> -#include <Uxtheme.h> -#include <Wininet.h> - -// STL -#include <string> -#include <vector> -#include <list> -#include <set> -#include <map> -#include <vector> -#include <ctime> -#include <cstdlib> -#include <cerrno> -#include <cctype> - -// RUNTIME -#include <process.h> - -#endif +/* + Copyright (C) 2011 Birunthan Mohanathas + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __STDAFX_H__ +#define __STDAFX_H__ + +// WINAPI +#include <Windows.h> +#include <Windowsx.h> +#include <Commdlg.h> +#include <Imagehlp.h> +#include <Lmcons.h> +#include <Shlobj.h> +#include <Shlwapi.h> +#include <Shellapi.h> +#include <Uxtheme.h> +#include <Wininet.h> + +// STL +#include <string> +#include <vector> +#include <list> +#include <set> +#include <map> +#include <vector> +#include <ctime> +#include <cstdlib> +#include <cerrno> +#include <cctype> + +// RUNTIME +#include <process.h> + +#endif diff --git a/SkinInstaller/resource.h b/SkinInstaller/resource.h index 0db54782..ad6f4a7f 100644 --- a/SkinInstaller/resource.h +++ b/SkinInstaller/resource.h @@ -1,73 +1,73 @@ -#define IDC_STATIC -1 -#define IDI_SKININSTALLER 100 -#define IDB_INSTALLHEADER 101 -#define IDD_INSTALL_DIALOG 102 -#define IDD_INSTALL_TAB 103 -#define IDR_INSTALL_MENU 104 -#define IDD_PACKAGE_DIALOG 105 -#define IDD_PACKAGEINFO_TAB 106 -#define IDD_PACKAGEOPTIONS_TAB 107 -#define IDD_PACKAGEADVANCED_TAB 108 -#define IDD_PACKAGESELECTFOLDER_DIALOG 109 -#define IDD_PACKAGESELECTPLUGIN_DIALOG 110 - -#define IDC_INSTALL_TAB 1000 -#define IDC_INSTALL_HEADER_BITMAP 1001 -#define IDC_INSTALL_ADVANCED_BUTTON 1002 -#define IDC_INSTALL_INSTALL_BUTTON 1003 - -#define IDC_INSTALLTAB_NAME_TEXT 1000 -#define IDC_INSTALLTAB_AUTHOR_TEXT 1001 -#define IDC_INSTALLTAB_VERSION_TEXT 1002 -#define IDC_INSTALLTAB_COMPONENTS_LIST 1003 -#define IDC_INSTALLTAB_THEME_CHECKBOX 1004 -#define IDC_INSTALLTAB_INPROGRESS_TEXT 1005 -#define IDC_INSTALLTAB_PROGRESS 1006 - -#define IDC_PACKAGE_TAB 1000 -#define IDC_PACKAGE_NEXT_BUTTON 1001 -#define IDC_PACKAGE_CREATEPACKAGE_BUTTON 1002 - -#define IDC_PACKAGEINFO_NAME_EDIT 1000 -#define IDC_PACKAGEINFO_AUTHOR_EDIT 1001 -#define IDC_PACKAGEINFO_VERSION_EDIT 1002 -#define IDC_PACKAGEINFO_COMPONENTS_LIST 1003 -#define IDC_PACKAGEINFO_ADDSKIN_BUTTON 1004 -#define IDC_PACKAGEINFO_ADDTHEME_BUTTON 1005 -#define IDC_PACKAGEINFO_ADDPLUGIN_BUTTON 1006 -#define IDC_PACKAGEINFO_REMOVE_BUTTON 1007 -#define IDC_PACKAGEINFO_WHATIS_LINK 1008 - -#define IDC_PACKAGEOPTIONS_FILE_EDIT 1000 -#define IDC_PACKAGEOPTIONS_FILEBROWSE_BUTTON 1001 -#define IDC_PACKAGEOPTIONS_DONOTHING_RADIO 1002 -#define IDC_PACKAGEOPTIONS_LOADSKIN_RADIO 1003 -#define IDC_PACKAGEOPTIONS_LOADSKIN_EDIT 1004 -#define IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON 1005 -#define IDC_PACKAGEOPTIONS_LOADTHEME_RADIO 1006 -#define IDC_PACKAGEOPTIONS_LOADTHEME_COMBO 1007 -#define IDC_PACKAGEOPTIONS_RAINMETERVERSION_EDIT 1008 -#define IDC_PACKAGEOPTIONS_WINDOWSVERSION_COMBO 1009 -#define IDC_INSTALLTAB_CREATING_TEXT 1010 -#define IDC_INSTALLTAB_CREATING_BAR 1011 - -#define IDC_PACKAGEADVANCED_HEADER_EDIT 1000 -#define IDC_PACKAGEADVANCED_HEADERROWSE_BUTTON 1001 -#define IDC_PACKAGEADVANCED_VARIABLEFILES_EDIT 1002 -#define IDC_PACKAGEADVANCED_MERGESKINS_CHECK 1003 -#define IDC_PACKAGEADVANCED_HELP_LINK 1004 - -#define IDC_PACKAGESELECTFOLDER_EXISTING_RADIO 1000 -#define IDC_PACKAGESELECTFOLDER_EXISTING_COMBO 1001 -#define IDC_PACKAGESELECTFOLDER_CUSTOM_RADIO 1002 -#define IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT 1003 -#define IDC_PACKAGESELECTFOLDER_CUSTOMBROWSE_BUTTON 1004 - -#define IDC_PACKAGESELECTPLUGIN_32BIT_EDIT 1000 -#define IDC_PACKAGESELECTPLUGIN_32BITBROWSE_BUTTON 1001 -#define IDC_PACKAGESELECTPLUGIN_64BIT_EDIT 1002 -#define IDC_PACKAGESELECTPLUGIN_64BITBROWSE_BUTTON 1003 - -#define IDM_INSTALL_BACKUPSKINS 4200 -#define IDM_INSTALL_SYSTEMFONTS 4201 -#define IDM_INSTALL_FORMAT 4202 +#define IDC_STATIC -1 +#define IDI_SKININSTALLER 100 +#define IDB_INSTALLHEADER 101 +#define IDD_INSTALL_DIALOG 102 +#define IDD_INSTALL_TAB 103 +#define IDR_INSTALL_MENU 104 +#define IDD_PACKAGE_DIALOG 105 +#define IDD_PACKAGEINFO_TAB 106 +#define IDD_PACKAGEOPTIONS_TAB 107 +#define IDD_PACKAGEADVANCED_TAB 108 +#define IDD_PACKAGESELECTFOLDER_DIALOG 109 +#define IDD_PACKAGESELECTPLUGIN_DIALOG 110 + +#define IDC_INSTALL_TAB 1000 +#define IDC_INSTALL_HEADER_BITMAP 1001 +#define IDC_INSTALL_ADVANCED_BUTTON 1002 +#define IDC_INSTALL_INSTALL_BUTTON 1003 + +#define IDC_INSTALLTAB_NAME_TEXT 1000 +#define IDC_INSTALLTAB_AUTHOR_TEXT 1001 +#define IDC_INSTALLTAB_VERSION_TEXT 1002 +#define IDC_INSTALLTAB_COMPONENTS_LIST 1003 +#define IDC_INSTALLTAB_THEME_CHECKBOX 1004 +#define IDC_INSTALLTAB_INPROGRESS_TEXT 1005 +#define IDC_INSTALLTAB_PROGRESS 1006 + +#define IDC_PACKAGE_TAB 1000 +#define IDC_PACKAGE_NEXT_BUTTON 1001 +#define IDC_PACKAGE_CREATEPACKAGE_BUTTON 1002 + +#define IDC_PACKAGEINFO_NAME_EDIT 1000 +#define IDC_PACKAGEINFO_AUTHOR_EDIT 1001 +#define IDC_PACKAGEINFO_VERSION_EDIT 1002 +#define IDC_PACKAGEINFO_COMPONENTS_LIST 1003 +#define IDC_PACKAGEINFO_ADDSKIN_BUTTON 1004 +#define IDC_PACKAGEINFO_ADDTHEME_BUTTON 1005 +#define IDC_PACKAGEINFO_ADDPLUGIN_BUTTON 1006 +#define IDC_PACKAGEINFO_REMOVE_BUTTON 1007 +#define IDC_PACKAGEINFO_WHATIS_LINK 1008 + +#define IDC_PACKAGEOPTIONS_FILE_EDIT 1000 +#define IDC_PACKAGEOPTIONS_FILEBROWSE_BUTTON 1001 +#define IDC_PACKAGEOPTIONS_DONOTHING_RADIO 1002 +#define IDC_PACKAGEOPTIONS_LOADSKIN_RADIO 1003 +#define IDC_PACKAGEOPTIONS_LOADSKIN_EDIT 1004 +#define IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON 1005 +#define IDC_PACKAGEOPTIONS_LOADTHEME_RADIO 1006 +#define IDC_PACKAGEOPTIONS_LOADTHEME_COMBO 1007 +#define IDC_PACKAGEOPTIONS_RAINMETERVERSION_EDIT 1008 +#define IDC_PACKAGEOPTIONS_WINDOWSVERSION_COMBO 1009 +#define IDC_INSTALLTAB_CREATING_TEXT 1010 +#define IDC_INSTALLTAB_CREATING_BAR 1011 + +#define IDC_PACKAGEADVANCED_HEADER_EDIT 1000 +#define IDC_PACKAGEADVANCED_HEADERROWSE_BUTTON 1001 +#define IDC_PACKAGEADVANCED_VARIABLEFILES_EDIT 1002 +#define IDC_PACKAGEADVANCED_MERGESKINS_CHECK 1003 +#define IDC_PACKAGEADVANCED_HELP_LINK 1004 + +#define IDC_PACKAGESELECTFOLDER_EXISTING_RADIO 1000 +#define IDC_PACKAGESELECTFOLDER_EXISTING_COMBO 1001 +#define IDC_PACKAGESELECTFOLDER_CUSTOM_RADIO 1002 +#define IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT 1003 +#define IDC_PACKAGESELECTFOLDER_CUSTOMBROWSE_BUTTON 1004 + +#define IDC_PACKAGESELECTPLUGIN_32BIT_EDIT 1000 +#define IDC_PACKAGESELECTPLUGIN_32BITBROWSE_BUTTON 1001 +#define IDC_PACKAGESELECTPLUGIN_64BIT_EDIT 1002 +#define IDC_PACKAGESELECTPLUGIN_64BITBROWSE_BUTTON 1003 + +#define IDM_INSTALL_BACKUPSKINS 4200 +#define IDM_INSTALL_SYSTEMFONTS 4201 +#define IDM_INSTALL_FORMAT 4202 diff --git a/SkinInstaller/zlib/gvmat64.asm b/SkinInstaller/zlib/gvmat64.asm index 9879c28b..c1817f1b 100644 --- a/SkinInstaller/zlib/gvmat64.asm +++ b/SkinInstaller/zlib/gvmat64.asm @@ -1,553 +1,553 @@ -;uInt longest_match_x64( -; deflate_state *s, -; IPos cur_match); /* current match */ - -; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86_64 -; (AMD64 on Athlon 64, Opteron, Phenom -; and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7) -; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant. -; -; File written by Gilles Vollant, by converting to assembly the longest_match -; from Jean-loup Gailly in deflate.c of zLib and infoZip zip. -; -; and by taking inspiration on asm686 with masm, optimised assembly code -; from Brian Raiter, written 1998 -; -; 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. -; -; -; -; http://www.zlib.net -; http://www.winimage.com/zLibDll -; http://www.muppetlabs.com/~breadbox/software/assembly.html -; -; to compile this file for infozip Zip, I use option: -; ml64.exe /Flgvmat64 /c /Zi /DINFOZIP gvmat64.asm -; -; to compile this file for zLib, I use option: -; ml64.exe /Flgvmat64 /c /Zi gvmat64.asm -; Be carrefull to adapt zlib1222add below to your version of zLib -; (if you use a version of zLib before 1.0.4 or after 1.2.2.2, change -; value of zlib1222add later) -; -; This file compile with Microsoft Macro Assembler (x64) for AMD64 -; -; ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK -; -; (you can get Windows WDK with ml64 for AMD64 from -; http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price) -; - - -;uInt longest_match(s, cur_match) -; deflate_state *s; -; IPos cur_match; /* current match */ -.code -longest_match PROC - - -;LocalVarsSize equ 88 - LocalVarsSize equ 72 - -; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12 -; free register : r14,r15 -; register can be saved : rsp - - chainlenwmask equ rsp + 8 - LocalVarsSize ; high word: current chain len - ; low word: s->wmask -;window equ rsp + xx - LocalVarsSize ; local copy of s->window ; stored in r10 -;windowbestlen equ rsp + xx - LocalVarsSize ; s->window + bestlen , use r10+r11 -;scanstart equ rsp + xx - LocalVarsSize ; first two bytes of string ; stored in r12w -;scanend equ rsp + xx - LocalVarsSize ; last two bytes of string use ebx -;scanalign equ rsp + xx - LocalVarsSize ; dword-misalignment of string r13 -;bestlen equ rsp + xx - LocalVarsSize ; size of best match so far -> r11d -;scan equ rsp + xx - LocalVarsSize ; ptr to string wanting match -> r9 -IFDEF INFOZIP -ELSE - nicematch equ (rsp + 16 - LocalVarsSize) ; a good enough match size -ENDIF - -save_rdi equ rsp + 24 - LocalVarsSize -save_rsi equ rsp + 32 - LocalVarsSize -save_rbx equ rsp + 40 - LocalVarsSize -save_rbp equ rsp + 48 - LocalVarsSize -save_r12 equ rsp + 56 - LocalVarsSize -save_r13 equ rsp + 64 - LocalVarsSize -;save_r14 equ rsp + 72 - LocalVarsSize -;save_r15 equ rsp + 80 - LocalVarsSize - - -; summary of register usage -; scanend ebx -; scanendw bx -; chainlenwmask edx -; curmatch rsi -; curmatchd esi -; windowbestlen r8 -; scanalign r9 -; scanalignd r9d -; window r10 -; bestlen r11 -; bestlend r11d -; scanstart r12d -; scanstartw r12w -; scan r13 -; nicematch r14d -; limit r15 -; limitd r15d -; prev rcx - -; all the +4 offsets are due to the addition of pending_buf_size (in zlib -; in the deflate_state structure since the asm code was first written -; (if you compile with zlib 1.0.4 or older, remove the +4). -; Note : these value are good with a 8 bytes boundary pack structure - - - MAX_MATCH equ 258 - MIN_MATCH equ 3 - MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) - - -;;; Offsets for fields in the deflate_state structure. These numbers -;;; are calculated from the definition of deflate_state, with the -;;; assumption that the compiler will dword-align the fields. (Thus, -;;; changing the definition of deflate_state could easily cause this -;;; program to crash horribly, without so much as a warning at -;;; compile time. Sigh.) - -; all the +zlib1222add offsets are due to the addition of fields -; in zlib in the deflate_state structure since the asm code was first written -; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). -; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). -; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). - - -IFDEF INFOZIP - -_DATA SEGMENT -COMM window_size:DWORD -; WMask ; 7fff -COMM window:BYTE:010040H -COMM prev:WORD:08000H -; MatchLen : unused -; PrevMatch : unused -COMM strstart:DWORD -COMM match_start:DWORD -; Lookahead : ignore -COMM prev_length:DWORD ; PrevLen -COMM max_chain_length:DWORD -COMM good_match:DWORD -COMM nice_match:DWORD -prev_ad equ OFFSET prev -window_ad equ OFFSET window -nicematch equ nice_match -_DATA ENDS -WMask equ 07fffh - -ELSE - - IFNDEF zlib1222add - zlib1222add equ 8 - ENDIF -dsWSize equ 56+zlib1222add+(zlib1222add/2) -dsWMask equ 64+zlib1222add+(zlib1222add/2) -dsWindow equ 72+zlib1222add -dsPrev equ 88+zlib1222add -dsMatchLen equ 128+zlib1222add -dsPrevMatch equ 132+zlib1222add -dsStrStart equ 140+zlib1222add -dsMatchStart equ 144+zlib1222add -dsLookahead equ 148+zlib1222add -dsPrevLen equ 152+zlib1222add -dsMaxChainLen equ 156+zlib1222add -dsGoodMatch equ 172+zlib1222add -dsNiceMatch equ 176+zlib1222add - -window_size equ [ rcx + dsWSize] -WMask equ [ rcx + dsWMask] -window_ad equ [ rcx + dsWindow] -prev_ad equ [ rcx + dsPrev] -strstart equ [ rcx + dsStrStart] -match_start equ [ rcx + dsMatchStart] -Lookahead equ [ rcx + dsLookahead] ; 0ffffffffh on infozip -prev_length equ [ rcx + dsPrevLen] -max_chain_length equ [ rcx + dsMaxChainLen] -good_match equ [ rcx + dsGoodMatch] -nice_match equ [ rcx + dsNiceMatch] -ENDIF - -; parameter 1 in r8(deflate state s), param 2 in rdx (cur match) - -; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and -; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp -; -; All registers must be preserved across the call, except for -; rax, rcx, rdx, r8, r9, r10, and r11, which are scratch. - - - -;;; Save registers that the compiler may be using, and adjust esp to -;;; make room for our stack frame. - - -;;; Retrieve the function arguments. r8d will hold cur_match -;;; throughout the entire function. edx will hold the pointer to the -;;; deflate_state structure during the function's setup (before -;;; entering the main loop. - -; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match) - -; this clear high 32 bits of r8, which can be garbage in both r8 and rdx - - mov [save_rdi],rdi - mov [save_rsi],rsi - mov [save_rbx],rbx - mov [save_rbp],rbp -IFDEF INFOZIP - mov r8d,ecx -ELSE - mov r8d,edx -ENDIF - mov [save_r12],r12 - mov [save_r13],r13 -; mov [save_r14],r14 -; mov [save_r15],r15 - - -;;; uInt wmask = s->w_mask; -;;; unsigned chain_length = s->max_chain_length; -;;; if (s->prev_length >= s->good_match) { -;;; chain_length >>= 2; -;;; } - - mov edi, prev_length - mov esi, good_match - mov eax, WMask - mov ebx, max_chain_length - cmp edi, esi - jl LastMatchGood - shr ebx, 2 -LastMatchGood: - -;;; chainlen is decremented once beforehand so that the function can -;;; use the sign flag instead of the zero flag for the exit test. -;;; It is then shifted into the high word, to make room for the wmask -;;; value, which it will always accompany. - - dec ebx - shl ebx, 16 - or ebx, eax - -;;; on zlib only -;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - -IFDEF INFOZIP - mov [chainlenwmask], ebx -; on infozip nice_match = [nice_match] -ELSE - mov eax, nice_match - mov [chainlenwmask], ebx - mov r10d, Lookahead - cmp r10d, eax - cmovnl r10d, eax - mov [nicematch],r10d -ENDIF - -;;; register Bytef *scan = s->window + s->strstart; - mov r10, window_ad - mov ebp, strstart - lea r13, [r10 + rbp] - -;;; Determine how many bytes the scan ptr is off from being -;;; dword-aligned. - - mov r9,r13 - neg r13 - and r13,3 - -;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? -;;; s->strstart - (IPos)MAX_DIST(s) : NIL; -IFDEF INFOZIP - mov eax,07efah ; MAX_DIST = (WSIZE-MIN_LOOKAHEAD) (0x8000-(3+8+1)) -ELSE - mov eax, window_size - sub eax, MIN_LOOKAHEAD -ENDIF - xor edi,edi - sub ebp, eax - - mov r11d, prev_length - - cmovng ebp,edi - -;;; int best_len = s->prev_length; - - -;;; Store the sum of s->window + best_len in esi locally, and in esi. - - lea rsi,[r10+r11] - -;;; register ush scan_start = *(ushf*)scan; -;;; register ush scan_end = *(ushf*)(scan+best_len-1); -;;; Posf *prev = s->prev; - - movzx r12d,word ptr [r9] - movzx ebx, word ptr [r9 + r11 - 1] - - mov rdi, prev_ad - -;;; Jump into the main loop. - - mov edx, [chainlenwmask] - - cmp bx,word ptr [rsi + r8 - 1] - jz LookupLoopIsZero - -LookupLoop1: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - jbe LeaveNow - sub edx, 00010000h - js LeaveNow - -LoopEntry1: - cmp bx,word ptr [rsi + r8 - 1] - jz LookupLoopIsZero - -LookupLoop2: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - jbe LeaveNow - sub edx, 00010000h - js LeaveNow - -LoopEntry2: - cmp bx,word ptr [rsi + r8 - 1] - jz LookupLoopIsZero - -LookupLoop4: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - jbe LeaveNow - sub edx, 00010000h - js LeaveNow - -LoopEntry4: - - cmp bx,word ptr [rsi + r8 - 1] - jnz LookupLoop1 - jmp LookupLoopIsZero - - -;;; do { -;;; match = s->window + cur_match; -;;; if (*(ushf*)(match+best_len-1) != scan_end || -;;; *(ushf*)match != scan_start) continue; -;;; [...] -;;; } while ((cur_match = prev[cur_match & wmask]) > limit -;;; && --chain_length != 0); -;;; -;;; Here is the inner loop of the function. The function will spend the -;;; majority of its time in this loop, and majority of that time will -;;; be spent in the first ten instructions. -;;; -;;; Within this loop: -;;; ebx = scanend -;;; r8d = curmatch -;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) -;;; esi = windowbestlen - i.e., (window + bestlen) -;;; edi = prev -;;; ebp = limit - -LookupLoop: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - jbe LeaveNow - sub edx, 00010000h - js LeaveNow - -LoopEntry: - - cmp bx,word ptr [rsi + r8 - 1] - jnz LookupLoop1 -LookupLoopIsZero: - cmp r12w, word ptr [r10 + r8] - jnz LookupLoop1 - - -;;; Store the current value of chainlen. - mov [chainlenwmask], edx - -;;; Point edi to the string under scrutiny, and esi to the string we -;;; are hoping to match it up with. In actuality, esi and edi are -;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is -;;; initialized to -(MAX_MATCH_8 - scanalign). - - lea rsi,[r8+r10] - mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8) - lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8] - lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8] - - prefetcht1 [rsi+rdx] - prefetcht1 [rdi+rdx] - - -;;; Test the strings for equality, 8 bytes at a time. At the end, -;;; adjust rdx so that it is offset to the exact byte that mismatched. -;;; -;;; We already know at this point that the first three bytes of the -;;; strings match each other, and they can be safely passed over before -;;; starting the compare loop. So what this code does is skip over 0-3 -;;; bytes, as much as necessary in order to dword-align the edi -;;; pointer. (rsi will still be misaligned three times out of four.) -;;; -;;; It should be confessed that this loop usually does not represent -;;; much of the total running time. Replacing it with a more -;;; straightforward "rep cmpsb" would not drastically degrade -;;; performance. - - -LoopCmps: - mov rax, [rsi + rdx] - xor rax, [rdi + rdx] - jnz LeaveLoopCmps - - mov rax, [rsi + rdx + 8] - xor rax, [rdi + rdx + 8] - jnz LeaveLoopCmps8 - - - mov rax, [rsi + rdx + 8+8] - xor rax, [rdi + rdx + 8+8] - jnz LeaveLoopCmps16 - - add rdx,8+8+8 - - jnz short LoopCmps - jmp short LenMaximum -LeaveLoopCmps16: add rdx,8 -LeaveLoopCmps8: add rdx,8 -LeaveLoopCmps: - - test eax, 0000FFFFh - jnz LenLower - - test eax,0ffffffffh - - jnz LenLower32 - - add rdx,4 - shr rax,32 - or ax,ax - jnz LenLower - -LenLower32: - shr eax,16 - add rdx,2 -LenLower: sub al, 1 - adc rdx, 0 -;;; Calculate the length of the match. If it is longer than MAX_MATCH, -;;; then automatically accept it as the best possible match and leave. - - lea rax, [rdi + rdx] - sub rax, r9 - cmp eax, MAX_MATCH - jge LenMaximum - -;;; If the length of the match is not longer than the best match we -;;; have so far, then forget it and return to the lookup loop. -;/////////////////////////////////// - - cmp eax, r11d - jg LongerMatch - - lea rsi,[r10+r11] - - mov rdi, prev_ad - mov edx, [chainlenwmask] - jmp LookupLoop - -;;; s->match_start = cur_match; -;;; best_len = len; -;;; if (len >= nice_match) break; -;;; scan_end = *(ushf*)(scan+best_len-1); - -LongerMatch: - mov r11d, eax - mov match_start, r8d - cmp eax, [nicematch] - jge LeaveNow - - lea rsi,[r10+rax] - - movzx ebx, word ptr [r9 + rax - 1] - mov rdi, prev_ad - mov edx, [chainlenwmask] - jmp LookupLoop - -;;; Accept the current string, with the maximum possible length. - -LenMaximum: - mov r11d,MAX_MATCH - mov match_start, r8d - -;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; -;;; return s->lookahead; - -LeaveNow: -IFDEF INFOZIP - mov eax,r11d -ELSE - mov eax, Lookahead - cmp r11d, eax - cmovng eax, r11d -ENDIF - -;;; Restore the stack and return from whence we came. - - - mov rsi,[save_rsi] - mov rdi,[save_rdi] - mov rbx,[save_rbx] - mov rbp,[save_rbp] - mov r12,[save_r12] - mov r13,[save_r13] -; mov r14,[save_r14] -; mov r15,[save_r15] - - - ret 0 -; please don't remove this string ! -; Your can freely use gvmat64 in any free or commercial app -; but it is far better don't remove the string in the binary! - db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0 -longest_match ENDP - -match_init PROC - ret 0 -match_init ENDP - - -END +;uInt longest_match_x64( +; deflate_state *s, +; IPos cur_match); /* current match */ + +; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86_64 +; (AMD64 on Athlon 64, Opteron, Phenom +; and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7) +; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant. +; +; File written by Gilles Vollant, by converting to assembly the longest_match +; from Jean-loup Gailly in deflate.c of zLib and infoZip zip. +; +; and by taking inspiration on asm686 with masm, optimised assembly code +; from Brian Raiter, written 1998 +; +; 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. +; +; +; +; http://www.zlib.net +; http://www.winimage.com/zLibDll +; http://www.muppetlabs.com/~breadbox/software/assembly.html +; +; to compile this file for infozip Zip, I use option: +; ml64.exe /Flgvmat64 /c /Zi /DINFOZIP gvmat64.asm +; +; to compile this file for zLib, I use option: +; ml64.exe /Flgvmat64 /c /Zi gvmat64.asm +; Be carrefull to adapt zlib1222add below to your version of zLib +; (if you use a version of zLib before 1.0.4 or after 1.2.2.2, change +; value of zlib1222add later) +; +; This file compile with Microsoft Macro Assembler (x64) for AMD64 +; +; ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK +; +; (you can get Windows WDK with ml64 for AMD64 from +; http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price) +; + + +;uInt longest_match(s, cur_match) +; deflate_state *s; +; IPos cur_match; /* current match */ +.code +longest_match PROC + + +;LocalVarsSize equ 88 + LocalVarsSize equ 72 + +; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12 +; free register : r14,r15 +; register can be saved : rsp + + chainlenwmask equ rsp + 8 - LocalVarsSize ; high word: current chain len + ; low word: s->wmask +;window equ rsp + xx - LocalVarsSize ; local copy of s->window ; stored in r10 +;windowbestlen equ rsp + xx - LocalVarsSize ; s->window + bestlen , use r10+r11 +;scanstart equ rsp + xx - LocalVarsSize ; first two bytes of string ; stored in r12w +;scanend equ rsp + xx - LocalVarsSize ; last two bytes of string use ebx +;scanalign equ rsp + xx - LocalVarsSize ; dword-misalignment of string r13 +;bestlen equ rsp + xx - LocalVarsSize ; size of best match so far -> r11d +;scan equ rsp + xx - LocalVarsSize ; ptr to string wanting match -> r9 +IFDEF INFOZIP +ELSE + nicematch equ (rsp + 16 - LocalVarsSize) ; a good enough match size +ENDIF + +save_rdi equ rsp + 24 - LocalVarsSize +save_rsi equ rsp + 32 - LocalVarsSize +save_rbx equ rsp + 40 - LocalVarsSize +save_rbp equ rsp + 48 - LocalVarsSize +save_r12 equ rsp + 56 - LocalVarsSize +save_r13 equ rsp + 64 - LocalVarsSize +;save_r14 equ rsp + 72 - LocalVarsSize +;save_r15 equ rsp + 80 - LocalVarsSize + + +; summary of register usage +; scanend ebx +; scanendw bx +; chainlenwmask edx +; curmatch rsi +; curmatchd esi +; windowbestlen r8 +; scanalign r9 +; scanalignd r9d +; window r10 +; bestlen r11 +; bestlend r11d +; scanstart r12d +; scanstartw r12w +; scan r13 +; nicematch r14d +; limit r15 +; limitd r15d +; prev rcx + +; all the +4 offsets are due to the addition of pending_buf_size (in zlib +; in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, remove the +4). +; Note : these value are good with a 8 bytes boundary pack structure + + + MAX_MATCH equ 258 + MIN_MATCH equ 3 + MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) + + +;;; Offsets for fields in the deflate_state structure. These numbers +;;; are calculated from the definition of deflate_state, with the +;;; assumption that the compiler will dword-align the fields. (Thus, +;;; changing the definition of deflate_state could easily cause this +;;; program to crash horribly, without so much as a warning at +;;; compile time. Sigh.) + +; all the +zlib1222add offsets are due to the addition of fields +; in zlib in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). +; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). +; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). + + +IFDEF INFOZIP + +_DATA SEGMENT +COMM window_size:DWORD +; WMask ; 7fff +COMM window:BYTE:010040H +COMM prev:WORD:08000H +; MatchLen : unused +; PrevMatch : unused +COMM strstart:DWORD +COMM match_start:DWORD +; Lookahead : ignore +COMM prev_length:DWORD ; PrevLen +COMM max_chain_length:DWORD +COMM good_match:DWORD +COMM nice_match:DWORD +prev_ad equ OFFSET prev +window_ad equ OFFSET window +nicematch equ nice_match +_DATA ENDS +WMask equ 07fffh + +ELSE + + IFNDEF zlib1222add + zlib1222add equ 8 + ENDIF +dsWSize equ 56+zlib1222add+(zlib1222add/2) +dsWMask equ 64+zlib1222add+(zlib1222add/2) +dsWindow equ 72+zlib1222add +dsPrev equ 88+zlib1222add +dsMatchLen equ 128+zlib1222add +dsPrevMatch equ 132+zlib1222add +dsStrStart equ 140+zlib1222add +dsMatchStart equ 144+zlib1222add +dsLookahead equ 148+zlib1222add +dsPrevLen equ 152+zlib1222add +dsMaxChainLen equ 156+zlib1222add +dsGoodMatch equ 172+zlib1222add +dsNiceMatch equ 176+zlib1222add + +window_size equ [ rcx + dsWSize] +WMask equ [ rcx + dsWMask] +window_ad equ [ rcx + dsWindow] +prev_ad equ [ rcx + dsPrev] +strstart equ [ rcx + dsStrStart] +match_start equ [ rcx + dsMatchStart] +Lookahead equ [ rcx + dsLookahead] ; 0ffffffffh on infozip +prev_length equ [ rcx + dsPrevLen] +max_chain_length equ [ rcx + dsMaxChainLen] +good_match equ [ rcx + dsGoodMatch] +nice_match equ [ rcx + dsNiceMatch] +ENDIF + +; parameter 1 in r8(deflate state s), param 2 in rdx (cur match) + +; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and +; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp +; +; All registers must be preserved across the call, except for +; rax, rcx, rdx, r8, r9, r10, and r11, which are scratch. + + + +;;; Save registers that the compiler may be using, and adjust esp to +;;; make room for our stack frame. + + +;;; Retrieve the function arguments. r8d will hold cur_match +;;; throughout the entire function. edx will hold the pointer to the +;;; deflate_state structure during the function's setup (before +;;; entering the main loop. + +; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match) + +; this clear high 32 bits of r8, which can be garbage in both r8 and rdx + + mov [save_rdi],rdi + mov [save_rsi],rsi + mov [save_rbx],rbx + mov [save_rbp],rbp +IFDEF INFOZIP + mov r8d,ecx +ELSE + mov r8d,edx +ENDIF + mov [save_r12],r12 + mov [save_r13],r13 +; mov [save_r14],r14 +; mov [save_r15],r15 + + +;;; uInt wmask = s->w_mask; +;;; unsigned chain_length = s->max_chain_length; +;;; if (s->prev_length >= s->good_match) { +;;; chain_length >>= 2; +;;; } + + mov edi, prev_length + mov esi, good_match + mov eax, WMask + mov ebx, max_chain_length + cmp edi, esi + jl LastMatchGood + shr ebx, 2 +LastMatchGood: + +;;; chainlen is decremented once beforehand so that the function can +;;; use the sign flag instead of the zero flag for the exit test. +;;; It is then shifted into the high word, to make room for the wmask +;;; value, which it will always accompany. + + dec ebx + shl ebx, 16 + or ebx, eax + +;;; on zlib only +;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + +IFDEF INFOZIP + mov [chainlenwmask], ebx +; on infozip nice_match = [nice_match] +ELSE + mov eax, nice_match + mov [chainlenwmask], ebx + mov r10d, Lookahead + cmp r10d, eax + cmovnl r10d, eax + mov [nicematch],r10d +ENDIF + +;;; register Bytef *scan = s->window + s->strstart; + mov r10, window_ad + mov ebp, strstart + lea r13, [r10 + rbp] + +;;; Determine how many bytes the scan ptr is off from being +;;; dword-aligned. + + mov r9,r13 + neg r13 + and r13,3 + +;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? +;;; s->strstart - (IPos)MAX_DIST(s) : NIL; +IFDEF INFOZIP + mov eax,07efah ; MAX_DIST = (WSIZE-MIN_LOOKAHEAD) (0x8000-(3+8+1)) +ELSE + mov eax, window_size + sub eax, MIN_LOOKAHEAD +ENDIF + xor edi,edi + sub ebp, eax + + mov r11d, prev_length + + cmovng ebp,edi + +;;; int best_len = s->prev_length; + + +;;; Store the sum of s->window + best_len in esi locally, and in esi. + + lea rsi,[r10+r11] + +;;; register ush scan_start = *(ushf*)scan; +;;; register ush scan_end = *(ushf*)(scan+best_len-1); +;;; Posf *prev = s->prev; + + movzx r12d,word ptr [r9] + movzx ebx, word ptr [r9 + r11 - 1] + + mov rdi, prev_ad + +;;; Jump into the main loop. + + mov edx, [chainlenwmask] + + cmp bx,word ptr [rsi + r8 - 1] + jz LookupLoopIsZero + +LookupLoop1: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry1: + cmp bx,word ptr [rsi + r8 - 1] + jz LookupLoopIsZero + +LookupLoop2: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry2: + cmp bx,word ptr [rsi + r8 - 1] + jz LookupLoopIsZero + +LookupLoop4: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry4: + + cmp bx,word ptr [rsi + r8 - 1] + jnz LookupLoop1 + jmp LookupLoopIsZero + + +;;; do { +;;; match = s->window + cur_match; +;;; if (*(ushf*)(match+best_len-1) != scan_end || +;;; *(ushf*)match != scan_start) continue; +;;; [...] +;;; } while ((cur_match = prev[cur_match & wmask]) > limit +;;; && --chain_length != 0); +;;; +;;; Here is the inner loop of the function. The function will spend the +;;; majority of its time in this loop, and majority of that time will +;;; be spent in the first ten instructions. +;;; +;;; Within this loop: +;;; ebx = scanend +;;; r8d = curmatch +;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) +;;; esi = windowbestlen - i.e., (window + bestlen) +;;; edi = prev +;;; ebp = limit + +LookupLoop: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry: + + cmp bx,word ptr [rsi + r8 - 1] + jnz LookupLoop1 +LookupLoopIsZero: + cmp r12w, word ptr [r10 + r8] + jnz LookupLoop1 + + +;;; Store the current value of chainlen. + mov [chainlenwmask], edx + +;;; Point edi to the string under scrutiny, and esi to the string we +;;; are hoping to match it up with. In actuality, esi and edi are +;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is +;;; initialized to -(MAX_MATCH_8 - scanalign). + + lea rsi,[r8+r10] + mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8) + lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8] + lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8] + + prefetcht1 [rsi+rdx] + prefetcht1 [rdi+rdx] + + +;;; Test the strings for equality, 8 bytes at a time. At the end, +;;; adjust rdx so that it is offset to the exact byte that mismatched. +;;; +;;; We already know at this point that the first three bytes of the +;;; strings match each other, and they can be safely passed over before +;;; starting the compare loop. So what this code does is skip over 0-3 +;;; bytes, as much as necessary in order to dword-align the edi +;;; pointer. (rsi will still be misaligned three times out of four.) +;;; +;;; It should be confessed that this loop usually does not represent +;;; much of the total running time. Replacing it with a more +;;; straightforward "rep cmpsb" would not drastically degrade +;;; performance. + + +LoopCmps: + mov rax, [rsi + rdx] + xor rax, [rdi + rdx] + jnz LeaveLoopCmps + + mov rax, [rsi + rdx + 8] + xor rax, [rdi + rdx + 8] + jnz LeaveLoopCmps8 + + + mov rax, [rsi + rdx + 8+8] + xor rax, [rdi + rdx + 8+8] + jnz LeaveLoopCmps16 + + add rdx,8+8+8 + + jnz short LoopCmps + jmp short LenMaximum +LeaveLoopCmps16: add rdx,8 +LeaveLoopCmps8: add rdx,8 +LeaveLoopCmps: + + test eax, 0000FFFFh + jnz LenLower + + test eax,0ffffffffh + + jnz LenLower32 + + add rdx,4 + shr rax,32 + or ax,ax + jnz LenLower + +LenLower32: + shr eax,16 + add rdx,2 +LenLower: sub al, 1 + adc rdx, 0 +;;; Calculate the length of the match. If it is longer than MAX_MATCH, +;;; then automatically accept it as the best possible match and leave. + + lea rax, [rdi + rdx] + sub rax, r9 + cmp eax, MAX_MATCH + jge LenMaximum + +;;; If the length of the match is not longer than the best match we +;;; have so far, then forget it and return to the lookup loop. +;/////////////////////////////////// + + cmp eax, r11d + jg LongerMatch + + lea rsi,[r10+r11] + + mov rdi, prev_ad + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; s->match_start = cur_match; +;;; best_len = len; +;;; if (len >= nice_match) break; +;;; scan_end = *(ushf*)(scan+best_len-1); + +LongerMatch: + mov r11d, eax + mov match_start, r8d + cmp eax, [nicematch] + jge LeaveNow + + lea rsi,[r10+rax] + + movzx ebx, word ptr [r9 + rax - 1] + mov rdi, prev_ad + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; Accept the current string, with the maximum possible length. + +LenMaximum: + mov r11d,MAX_MATCH + mov match_start, r8d + +;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; +;;; return s->lookahead; + +LeaveNow: +IFDEF INFOZIP + mov eax,r11d +ELSE + mov eax, Lookahead + cmp r11d, eax + cmovng eax, r11d +ENDIF + +;;; Restore the stack and return from whence we came. + + + mov rsi,[save_rsi] + mov rdi,[save_rdi] + mov rbx,[save_rbx] + mov rbp,[save_rbp] + mov r12,[save_r12] + mov r13,[save_r13] +; mov r14,[save_r14] +; mov r15,[save_r15] + + + ret 0 +; please don't remove this string ! +; Your can freely use gvmat64 in any free or commercial app +; but it is far better don't remove the string in the binary! + db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0 +longest_match ENDP + +match_init PROC + ret 0 +match_init ENDP + + +END diff --git a/SkinInstaller/zlib/inffas32.asm b/SkinInstaller/zlib/inffas32.asm index 03d20f83..cb37a81e 100644 --- a/SkinInstaller/zlib/inffas32.asm +++ b/SkinInstaller/zlib/inffas32.asm @@ -1,1080 +1,1080 @@ -;/* inffas32.asm is a hand tuned assembler version of inffast.c -- fast decoding -; * -; * inffas32.asm is derivated from inffas86.c, with translation of assembly code -; * -; * Copyright (C) 1995-2003 Mark Adler -; * For conditions of distribution and use, see copyright notice in zlib.h -; * -; * Copyright (C) 2003 Chris Anderson <christop@charm.net> -; * Please use the copyright conditions above. -; * -; * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from -; * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at -; * the moment. I have successfully compiled and tested this code with gcc2.96, -; * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S -; * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX -; * enabled. I will attempt to merge the MMX code into this version. Newer -; * versions of this and inffast.S can be found at -; * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ -; * -; * 2005 : modification by Gilles Vollant -; */ -; For Visual C++ 4.x and higher and ML 6.x and higher -; ml.exe is in directory \MASM611C of Win95 DDK -; ml.exe is also distributed in http://www.masm32.com/masmdl.htm -; and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/ -; -; -; compile with command line option -; ml /coff /Zi /c /Flinffas32.lst inffas32.asm - -; if you define NO_GZIP (see inflate.h), compile with -; ml /coff /Zi /c /Flinffas32.lst /DNO_GUNZIP inffas32.asm - - -; zlib122sup is 0 fort zlib 1.2.2.1 and lower -; zlib122sup is 8 fort zlib 1.2.2.2 and more (with addition of dmax and head -; in inflate_state in inflate.h) -zlib1222sup equ 8 - - -IFDEF GUNZIP - INFLATE_MODE_TYPE equ 11 - INFLATE_MODE_BAD equ 26 -ELSE - IFNDEF NO_GUNZIP - INFLATE_MODE_TYPE equ 11 - INFLATE_MODE_BAD equ 26 - ELSE - INFLATE_MODE_TYPE equ 3 - INFLATE_MODE_BAD equ 17 - ENDIF -ENDIF - - -; 75 "inffast.S" -;FILE "inffast.S" - -;;;GLOBAL _inflate_fast - -;;;SECTION .text - - - - .586p - .mmx - - name inflate_fast_x86 - .MODEL FLAT - -_DATA segment -inflate_fast_use_mmx: - dd 1 - - -_TEXT segment - - - -ALIGN 4 - db 'Fast decoding Code from Chris Anderson' - db 0 - -ALIGN 4 -invalid_literal_length_code_msg: - db 'invalid literal/length code' - db 0 - -ALIGN 4 -invalid_distance_code_msg: - db 'invalid distance code' - db 0 - -ALIGN 4 -invalid_distance_too_far_msg: - db 'invalid distance too far back' - db 0 - - -ALIGN 4 -inflate_fast_mask: -dd 0 -dd 1 -dd 3 -dd 7 -dd 15 -dd 31 -dd 63 -dd 127 -dd 255 -dd 511 -dd 1023 -dd 2047 -dd 4095 -dd 8191 -dd 16383 -dd 32767 -dd 65535 -dd 131071 -dd 262143 -dd 524287 -dd 1048575 -dd 2097151 -dd 4194303 -dd 8388607 -dd 16777215 -dd 33554431 -dd 67108863 -dd 134217727 -dd 268435455 -dd 536870911 -dd 1073741823 -dd 2147483647 -dd 4294967295 - - -mode_state equ 0 ;/* state->mode */ -wsize_state equ (32+zlib1222sup) ;/* state->wsize */ -write_state equ (36+4+zlib1222sup) ;/* state->write */ -window_state equ (40+4+zlib1222sup) ;/* state->window */ -hold_state equ (44+4+zlib1222sup) ;/* state->hold */ -bits_state equ (48+4+zlib1222sup) ;/* state->bits */ -lencode_state equ (64+4+zlib1222sup) ;/* state->lencode */ -distcode_state equ (68+4+zlib1222sup) ;/* state->distcode */ -lenbits_state equ (72+4+zlib1222sup) ;/* state->lenbits */ -distbits_state equ (76+4+zlib1222sup) ;/* state->distbits */ - - -;;SECTION .text -; 205 "inffast.S" -;GLOBAL inflate_fast_use_mmx - -;SECTION .data - - -; GLOBAL inflate_fast_use_mmx:object -;.size inflate_fast_use_mmx, 4 -; 226 "inffast.S" -;SECTION .text - -ALIGN 4 -_inflate_fast proc near -.FPO (16, 4, 0, 0, 1, 0) - push edi - push esi - push ebp - push ebx - pushfd - sub esp,64 - cld - - - - - mov esi, [esp+88] - mov edi, [esi+28] - - - - - - - - mov edx, [esi+4] - mov eax, [esi+0] - - add edx,eax - sub edx,11 - - mov [esp+44],eax - mov [esp+20],edx - - mov ebp, [esp+92] - mov ecx, [esi+16] - mov ebx, [esi+12] - - sub ebp,ecx - neg ebp - add ebp,ebx - - sub ecx,257 - add ecx,ebx - - mov [esp+60],ebx - mov [esp+40],ebp - mov [esp+16],ecx -; 285 "inffast.S" - mov eax, [edi+lencode_state] - mov ecx, [edi+distcode_state] - - mov [esp+8],eax - mov [esp+12],ecx - - mov eax,1 - mov ecx, [edi+lenbits_state] - shl eax,cl - dec eax - mov [esp+0],eax - - mov eax,1 - mov ecx, [edi+distbits_state] - shl eax,cl - dec eax - mov [esp+4],eax - - mov eax, [edi+wsize_state] - mov ecx, [edi+write_state] - mov edx, [edi+window_state] - - mov [esp+52],eax - mov [esp+48],ecx - mov [esp+56],edx - - mov ebp, [edi+hold_state] - mov ebx, [edi+bits_state] -; 321 "inffast.S" - mov esi, [esp+44] - mov ecx, [esp+20] - cmp ecx,esi - ja L_align_long - - add ecx,11 - sub ecx,esi - mov eax,12 - sub eax,ecx - lea edi, [esp+28] - rep movsb - mov ecx,eax - xor eax,eax - rep stosb - lea esi, [esp+28] - mov [esp+20],esi - jmp L_is_aligned - - -L_align_long: - test esi,3 - jz L_is_aligned - xor eax,eax - mov al, [esi] - inc esi - mov ecx,ebx - add ebx,8 - shl eax,cl - or ebp,eax - jmp L_align_long - -L_is_aligned: - mov edi, [esp+60] -; 366 "inffast.S" -L_check_mmx: - cmp dword ptr [inflate_fast_use_mmx],2 - je L_init_mmx - ja L_do_loop - - push eax - push ebx - push ecx - push edx - pushfd - mov eax, [esp] - xor dword ptr [esp],0200000h - - - - - popfd - pushfd - pop edx - xor edx,eax - jz L_dont_use_mmx - xor eax,eax - cpuid - cmp ebx,0756e6547h - jne L_dont_use_mmx - cmp ecx,06c65746eh - jne L_dont_use_mmx - cmp edx,049656e69h - jne L_dont_use_mmx - mov eax,1 - cpuid - shr eax,8 - and eax,15 - cmp eax,6 - jne L_dont_use_mmx - test edx,0800000h - jnz L_use_mmx - jmp L_dont_use_mmx -L_use_mmx: - mov dword ptr [inflate_fast_use_mmx],2 - jmp L_check_mmx_pop -L_dont_use_mmx: - mov dword ptr [inflate_fast_use_mmx],3 -L_check_mmx_pop: - pop edx - pop ecx - pop ebx - pop eax - jmp L_check_mmx -; 426 "inffast.S" -ALIGN 4 -L_do_loop: -; 437 "inffast.S" - cmp bl,15 - ja L_get_length_code - - xor eax,eax - lodsw - mov cl,bl - add bl,16 - shl eax,cl - or ebp,eax - -L_get_length_code: - mov edx, [esp+0] - mov ecx, [esp+8] - and edx,ebp - mov eax, [ecx+edx*4] - -L_dolen: - - - - - - - mov cl,ah - sub bl,ah - shr ebp,cl - - - - - - - test al,al - jnz L_test_for_length_base - - shr eax,16 - stosb - -L_while_test: - - - cmp [esp+16],edi - jbe L_break_loop - - cmp [esp+20],esi - ja L_do_loop - jmp L_break_loop - -L_test_for_length_base: -; 502 "inffast.S" - mov edx,eax - shr edx,16 - mov cl,al - - test al,16 - jz L_test_for_second_level_length - and cl,15 - jz L_save_len - cmp bl,cl - jae L_add_bits_to_len - - mov ch,cl - xor eax,eax - lodsw - mov cl,bl - add bl,16 - shl eax,cl - or ebp,eax - mov cl,ch - -L_add_bits_to_len: - mov eax,1 - shl eax,cl - dec eax - sub bl,cl - and eax,ebp - shr ebp,cl - add edx,eax - -L_save_len: - mov [esp+24],edx - - -L_decode_distance: -; 549 "inffast.S" - cmp bl,15 - ja L_get_distance_code - - xor eax,eax - lodsw - mov cl,bl - add bl,16 - shl eax,cl - or ebp,eax - -L_get_distance_code: - mov edx, [esp+4] - mov ecx, [esp+12] - and edx,ebp - mov eax, [ecx+edx*4] - - -L_dodist: - mov edx,eax - shr edx,16 - mov cl,ah - sub bl,ah - shr ebp,cl -; 584 "inffast.S" - mov cl,al - - test al,16 - jz L_test_for_second_level_dist - and cl,15 - jz L_check_dist_one - cmp bl,cl - jae L_add_bits_to_dist - - mov ch,cl - xor eax,eax - lodsw - mov cl,bl - add bl,16 - shl eax,cl - or ebp,eax - mov cl,ch - -L_add_bits_to_dist: - mov eax,1 - shl eax,cl - dec eax - sub bl,cl - and eax,ebp - shr ebp,cl - add edx,eax - jmp L_check_window - -L_check_window: -; 625 "inffast.S" - mov [esp+44],esi - mov eax,edi - sub eax, [esp+40] - - cmp eax,edx - jb L_clip_window - - mov ecx, [esp+24] - mov esi,edi - sub esi,edx - - sub ecx,3 - mov al, [esi] - mov [edi],al - mov al, [esi+1] - mov dl, [esi+2] - add esi,3 - mov [edi+1],al - mov [edi+2],dl - add edi,3 - rep movsb - - mov esi, [esp+44] - jmp L_while_test - -ALIGN 4 -L_check_dist_one: - cmp edx,1 - jne L_check_window - cmp [esp+40],edi - je L_check_window - - dec edi - mov ecx, [esp+24] - mov al, [edi] - sub ecx,3 - - mov [edi+1],al - mov [edi+2],al - mov [edi+3],al - add edi,4 - rep stosb - - jmp L_while_test - -ALIGN 4 -L_test_for_second_level_length: - - - - - test al,64 - jnz L_test_for_end_of_block - - mov eax,1 - shl eax,cl - dec eax - and eax,ebp - add eax,edx - mov edx, [esp+8] - mov eax, [edx+eax*4] - jmp L_dolen - -ALIGN 4 -L_test_for_second_level_dist: - - - - - test al,64 - jnz L_invalid_distance_code - - mov eax,1 - shl eax,cl - dec eax - and eax,ebp - add eax,edx - mov edx, [esp+12] - mov eax, [edx+eax*4] - jmp L_dodist - -ALIGN 4 -L_clip_window: -; 721 "inffast.S" - mov ecx,eax - mov eax, [esp+52] - neg ecx - mov esi, [esp+56] - - cmp eax,edx - jb L_invalid_distance_too_far - - add ecx,edx - cmp dword ptr [esp+48],0 - jne L_wrap_around_window - - sub eax,ecx - add esi,eax -; 749 "inffast.S" - mov eax, [esp+24] - cmp eax,ecx - jbe L_do_copy1 - - sub eax,ecx - rep movsb - mov esi,edi - sub esi,edx - jmp L_do_copy1 - - cmp eax,ecx - jbe L_do_copy1 - - sub eax,ecx - rep movsb - mov esi,edi - sub esi,edx - jmp L_do_copy1 - -L_wrap_around_window: -; 793 "inffast.S" - mov eax, [esp+48] - cmp ecx,eax - jbe L_contiguous_in_window - - add esi, [esp+52] - add esi,eax - sub esi,ecx - sub ecx,eax - - - mov eax, [esp+24] - cmp eax,ecx - jbe L_do_copy1 - - sub eax,ecx - rep movsb - mov esi, [esp+56] - mov ecx, [esp+48] - cmp eax,ecx - jbe L_do_copy1 - - sub eax,ecx - rep movsb - mov esi,edi - sub esi,edx - jmp L_do_copy1 - -L_contiguous_in_window: -; 836 "inffast.S" - add esi,eax - sub esi,ecx - - - mov eax, [esp+24] - cmp eax,ecx - jbe L_do_copy1 - - sub eax,ecx - rep movsb - mov esi,edi - sub esi,edx - -L_do_copy1: -; 862 "inffast.S" - mov ecx,eax - rep movsb - - mov esi, [esp+44] - jmp L_while_test -; 878 "inffast.S" -ALIGN 4 -L_init_mmx: - emms - - - - - - movd mm0,ebp - mov ebp,ebx -; 896 "inffast.S" - movd mm4,dword ptr [esp+0] - movq mm3,mm4 - movd mm5,dword ptr [esp+4] - movq mm2,mm5 - pxor mm1,mm1 - mov ebx, [esp+8] - jmp L_do_loop_mmx - -ALIGN 4 -L_do_loop_mmx: - psrlq mm0,mm1 - - cmp ebp,32 - ja L_get_length_code_mmx - - movd mm6,ebp - movd mm7,dword ptr [esi] - add esi,4 - psllq mm7,mm6 - add ebp,32 - por mm0,mm7 - -L_get_length_code_mmx: - pand mm4,mm0 - movd eax,mm4 - movq mm4,mm3 - mov eax, [ebx+eax*4] - -L_dolen_mmx: - movzx ecx,ah - movd mm1,ecx - sub ebp,ecx - - test al,al - jnz L_test_for_length_base_mmx - - shr eax,16 - stosb - -L_while_test_mmx: - - - cmp [esp+16],edi - jbe L_break_loop - - cmp [esp+20],esi - ja L_do_loop_mmx - jmp L_break_loop - -L_test_for_length_base_mmx: - - mov edx,eax - shr edx,16 - - test al,16 - jz L_test_for_second_level_length_mmx - and eax,15 - jz L_decode_distance_mmx - - psrlq mm0,mm1 - movd mm1,eax - movd ecx,mm0 - sub ebp,eax - and ecx, [inflate_fast_mask+eax*4] - add edx,ecx - -L_decode_distance_mmx: - psrlq mm0,mm1 - - cmp ebp,32 - ja L_get_dist_code_mmx - - movd mm6,ebp - movd mm7,dword ptr [esi] - add esi,4 - psllq mm7,mm6 - add ebp,32 - por mm0,mm7 - -L_get_dist_code_mmx: - mov ebx, [esp+12] - pand mm5,mm0 - movd eax,mm5 - movq mm5,mm2 - mov eax, [ebx+eax*4] - -L_dodist_mmx: - - movzx ecx,ah - mov ebx,eax - shr ebx,16 - sub ebp,ecx - movd mm1,ecx - - test al,16 - jz L_test_for_second_level_dist_mmx - and eax,15 - jz L_check_dist_one_mmx - -L_add_bits_to_dist_mmx: - psrlq mm0,mm1 - movd mm1,eax - movd ecx,mm0 - sub ebp,eax - and ecx, [inflate_fast_mask+eax*4] - add ebx,ecx - -L_check_window_mmx: - mov [esp+44],esi - mov eax,edi - sub eax, [esp+40] - - cmp eax,ebx - jb L_clip_window_mmx - - mov ecx,edx - mov esi,edi - sub esi,ebx - - sub ecx,3 - mov al, [esi] - mov [edi],al - mov al, [esi+1] - mov dl, [esi+2] - add esi,3 - mov [edi+1],al - mov [edi+2],dl - add edi,3 - rep movsb - - mov esi, [esp+44] - mov ebx, [esp+8] - jmp L_while_test_mmx - -ALIGN 4 -L_check_dist_one_mmx: - cmp ebx,1 - jne L_check_window_mmx - cmp [esp+40],edi - je L_check_window_mmx - - dec edi - mov ecx,edx - mov al, [edi] - sub ecx,3 - - mov [edi+1],al - mov [edi+2],al - mov [edi+3],al - add edi,4 - rep stosb - - mov ebx, [esp+8] - jmp L_while_test_mmx - -ALIGN 4 -L_test_for_second_level_length_mmx: - test al,64 - jnz L_test_for_end_of_block - - and eax,15 - psrlq mm0,mm1 - movd ecx,mm0 - and ecx, [inflate_fast_mask+eax*4] - add ecx,edx - mov eax, [ebx+ecx*4] - jmp L_dolen_mmx - -ALIGN 4 -L_test_for_second_level_dist_mmx: - test al,64 - jnz L_invalid_distance_code - - and eax,15 - psrlq mm0,mm1 - movd ecx,mm0 - and ecx, [inflate_fast_mask+eax*4] - mov eax, [esp+12] - add ecx,ebx - mov eax, [eax+ecx*4] - jmp L_dodist_mmx - -ALIGN 4 -L_clip_window_mmx: - - mov ecx,eax - mov eax, [esp+52] - neg ecx - mov esi, [esp+56] - - cmp eax,ebx - jb L_invalid_distance_too_far - - add ecx,ebx - cmp dword ptr [esp+48],0 - jne L_wrap_around_window_mmx - - sub eax,ecx - add esi,eax - - cmp edx,ecx - jbe L_do_copy1_mmx - - sub edx,ecx - rep movsb - mov esi,edi - sub esi,ebx - jmp L_do_copy1_mmx - - cmp edx,ecx - jbe L_do_copy1_mmx - - sub edx,ecx - rep movsb - mov esi,edi - sub esi,ebx - jmp L_do_copy1_mmx - -L_wrap_around_window_mmx: - - mov eax, [esp+48] - cmp ecx,eax - jbe L_contiguous_in_window_mmx - - add esi, [esp+52] - add esi,eax - sub esi,ecx - sub ecx,eax - - - cmp edx,ecx - jbe L_do_copy1_mmx - - sub edx,ecx - rep movsb - mov esi, [esp+56] - mov ecx, [esp+48] - cmp edx,ecx - jbe L_do_copy1_mmx - - sub edx,ecx - rep movsb - mov esi,edi - sub esi,ebx - jmp L_do_copy1_mmx - -L_contiguous_in_window_mmx: - - add esi,eax - sub esi,ecx - - - cmp edx,ecx - jbe L_do_copy1_mmx - - sub edx,ecx - rep movsb - mov esi,edi - sub esi,ebx - -L_do_copy1_mmx: - - - mov ecx,edx - rep movsb - - mov esi, [esp+44] - mov ebx, [esp+8] - jmp L_while_test_mmx -; 1174 "inffast.S" -L_invalid_distance_code: - - - - - - mov ecx, invalid_distance_code_msg - mov edx,INFLATE_MODE_BAD - jmp L_update_stream_state - -L_test_for_end_of_block: - - - - - - test al,32 - jz L_invalid_literal_length_code - - mov ecx,0 - mov edx,INFLATE_MODE_TYPE - jmp L_update_stream_state - -L_invalid_literal_length_code: - - - - - - mov ecx, invalid_literal_length_code_msg - mov edx,INFLATE_MODE_BAD - jmp L_update_stream_state - -L_invalid_distance_too_far: - - - - mov esi, [esp+44] - mov ecx, invalid_distance_too_far_msg - mov edx,INFLATE_MODE_BAD - jmp L_update_stream_state - -L_update_stream_state: - - mov eax, [esp+88] - test ecx,ecx - jz L_skip_msg - mov [eax+24],ecx -L_skip_msg: - mov eax, [eax+28] - mov [eax+mode_state],edx - jmp L_break_loop - -ALIGN 4 -L_break_loop: -; 1243 "inffast.S" - cmp dword ptr [inflate_fast_use_mmx],2 - jne L_update_next_in - - - - mov ebx,ebp - -L_update_next_in: -; 1266 "inffast.S" - mov eax, [esp+88] - mov ecx,ebx - mov edx, [eax+28] - shr ecx,3 - sub esi,ecx - shl ecx,3 - sub ebx,ecx - mov [eax+12],edi - mov [edx+bits_state],ebx - mov ecx,ebx - - lea ebx, [esp+28] - cmp [esp+20],ebx - jne L_buf_not_used - - sub esi,ebx - mov ebx, [eax+0] - mov [esp+20],ebx - add esi,ebx - mov ebx, [eax+4] - sub ebx,11 - add [esp+20],ebx - -L_buf_not_used: - mov [eax+0],esi - - mov ebx,1 - shl ebx,cl - dec ebx - - - - - - cmp dword ptr [inflate_fast_use_mmx],2 - jne L_update_hold - - - - psrlq mm0,mm1 - movd ebp,mm0 - - emms - -L_update_hold: - - - - and ebp,ebx - mov [edx+hold_state],ebp - - - - - mov ebx, [esp+20] - cmp ebx,esi - jbe L_last_is_smaller - - sub ebx,esi - add ebx,11 - mov [eax+4],ebx - jmp L_fixup_out -L_last_is_smaller: - sub esi,ebx - neg esi - add esi,11 - mov [eax+4],esi - - - - -L_fixup_out: - - mov ebx, [esp+16] - cmp ebx,edi - jbe L_end_is_smaller - - sub ebx,edi - add ebx,257 - mov [eax+16],ebx - jmp L_done -L_end_is_smaller: - sub edi,ebx - neg edi - add edi,257 - mov [eax+16],edi - - - - - -L_done: - add esp,64 - popfd - pop ebx - pop ebp - pop esi - pop edi - ret -_inflate_fast endp - -_TEXT ends -end +;/* inffas32.asm is a hand tuned assembler version of inffast.c -- fast decoding +; * +; * inffas32.asm is derivated from inffas86.c, with translation of assembly code +; * +; * Copyright (C) 1995-2003 Mark Adler +; * For conditions of distribution and use, see copyright notice in zlib.h +; * +; * Copyright (C) 2003 Chris Anderson <christop@charm.net> +; * Please use the copyright conditions above. +; * +; * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from +; * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at +; * the moment. I have successfully compiled and tested this code with gcc2.96, +; * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S +; * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX +; * enabled. I will attempt to merge the MMX code into this version. Newer +; * versions of this and inffast.S can be found at +; * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ +; * +; * 2005 : modification by Gilles Vollant +; */ +; For Visual C++ 4.x and higher and ML 6.x and higher +; ml.exe is in directory \MASM611C of Win95 DDK +; ml.exe is also distributed in http://www.masm32.com/masmdl.htm +; and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/ +; +; +; compile with command line option +; ml /coff /Zi /c /Flinffas32.lst inffas32.asm + +; if you define NO_GZIP (see inflate.h), compile with +; ml /coff /Zi /c /Flinffas32.lst /DNO_GUNZIP inffas32.asm + + +; zlib122sup is 0 fort zlib 1.2.2.1 and lower +; zlib122sup is 8 fort zlib 1.2.2.2 and more (with addition of dmax and head +; in inflate_state in inflate.h) +zlib1222sup equ 8 + + +IFDEF GUNZIP + INFLATE_MODE_TYPE equ 11 + INFLATE_MODE_BAD equ 26 +ELSE + IFNDEF NO_GUNZIP + INFLATE_MODE_TYPE equ 11 + INFLATE_MODE_BAD equ 26 + ELSE + INFLATE_MODE_TYPE equ 3 + INFLATE_MODE_BAD equ 17 + ENDIF +ENDIF + + +; 75 "inffast.S" +;FILE "inffast.S" + +;;;GLOBAL _inflate_fast + +;;;SECTION .text + + + + .586p + .mmx + + name inflate_fast_x86 + .MODEL FLAT + +_DATA segment +inflate_fast_use_mmx: + dd 1 + + +_TEXT segment + + + +ALIGN 4 + db 'Fast decoding Code from Chris Anderson' + db 0 + +ALIGN 4 +invalid_literal_length_code_msg: + db 'invalid literal/length code' + db 0 + +ALIGN 4 +invalid_distance_code_msg: + db 'invalid distance code' + db 0 + +ALIGN 4 +invalid_distance_too_far_msg: + db 'invalid distance too far back' + db 0 + + +ALIGN 4 +inflate_fast_mask: +dd 0 +dd 1 +dd 3 +dd 7 +dd 15 +dd 31 +dd 63 +dd 127 +dd 255 +dd 511 +dd 1023 +dd 2047 +dd 4095 +dd 8191 +dd 16383 +dd 32767 +dd 65535 +dd 131071 +dd 262143 +dd 524287 +dd 1048575 +dd 2097151 +dd 4194303 +dd 8388607 +dd 16777215 +dd 33554431 +dd 67108863 +dd 134217727 +dd 268435455 +dd 536870911 +dd 1073741823 +dd 2147483647 +dd 4294967295 + + +mode_state equ 0 ;/* state->mode */ +wsize_state equ (32+zlib1222sup) ;/* state->wsize */ +write_state equ (36+4+zlib1222sup) ;/* state->write */ +window_state equ (40+4+zlib1222sup) ;/* state->window */ +hold_state equ (44+4+zlib1222sup) ;/* state->hold */ +bits_state equ (48+4+zlib1222sup) ;/* state->bits */ +lencode_state equ (64+4+zlib1222sup) ;/* state->lencode */ +distcode_state equ (68+4+zlib1222sup) ;/* state->distcode */ +lenbits_state equ (72+4+zlib1222sup) ;/* state->lenbits */ +distbits_state equ (76+4+zlib1222sup) ;/* state->distbits */ + + +;;SECTION .text +; 205 "inffast.S" +;GLOBAL inflate_fast_use_mmx + +;SECTION .data + + +; GLOBAL inflate_fast_use_mmx:object +;.size inflate_fast_use_mmx, 4 +; 226 "inffast.S" +;SECTION .text + +ALIGN 4 +_inflate_fast proc near +.FPO (16, 4, 0, 0, 1, 0) + push edi + push esi + push ebp + push ebx + pushfd + sub esp,64 + cld + + + + + mov esi, [esp+88] + mov edi, [esi+28] + + + + + + + + mov edx, [esi+4] + mov eax, [esi+0] + + add edx,eax + sub edx,11 + + mov [esp+44],eax + mov [esp+20],edx + + mov ebp, [esp+92] + mov ecx, [esi+16] + mov ebx, [esi+12] + + sub ebp,ecx + neg ebp + add ebp,ebx + + sub ecx,257 + add ecx,ebx + + mov [esp+60],ebx + mov [esp+40],ebp + mov [esp+16],ecx +; 285 "inffast.S" + mov eax, [edi+lencode_state] + mov ecx, [edi+distcode_state] + + mov [esp+8],eax + mov [esp+12],ecx + + mov eax,1 + mov ecx, [edi+lenbits_state] + shl eax,cl + dec eax + mov [esp+0],eax + + mov eax,1 + mov ecx, [edi+distbits_state] + shl eax,cl + dec eax + mov [esp+4],eax + + mov eax, [edi+wsize_state] + mov ecx, [edi+write_state] + mov edx, [edi+window_state] + + mov [esp+52],eax + mov [esp+48],ecx + mov [esp+56],edx + + mov ebp, [edi+hold_state] + mov ebx, [edi+bits_state] +; 321 "inffast.S" + mov esi, [esp+44] + mov ecx, [esp+20] + cmp ecx,esi + ja L_align_long + + add ecx,11 + sub ecx,esi + mov eax,12 + sub eax,ecx + lea edi, [esp+28] + rep movsb + mov ecx,eax + xor eax,eax + rep stosb + lea esi, [esp+28] + mov [esp+20],esi + jmp L_is_aligned + + +L_align_long: + test esi,3 + jz L_is_aligned + xor eax,eax + mov al, [esi] + inc esi + mov ecx,ebx + add ebx,8 + shl eax,cl + or ebp,eax + jmp L_align_long + +L_is_aligned: + mov edi, [esp+60] +; 366 "inffast.S" +L_check_mmx: + cmp dword ptr [inflate_fast_use_mmx],2 + je L_init_mmx + ja L_do_loop + + push eax + push ebx + push ecx + push edx + pushfd + mov eax, [esp] + xor dword ptr [esp],0200000h + + + + + popfd + pushfd + pop edx + xor edx,eax + jz L_dont_use_mmx + xor eax,eax + cpuid + cmp ebx,0756e6547h + jne L_dont_use_mmx + cmp ecx,06c65746eh + jne L_dont_use_mmx + cmp edx,049656e69h + jne L_dont_use_mmx + mov eax,1 + cpuid + shr eax,8 + and eax,15 + cmp eax,6 + jne L_dont_use_mmx + test edx,0800000h + jnz L_use_mmx + jmp L_dont_use_mmx +L_use_mmx: + mov dword ptr [inflate_fast_use_mmx],2 + jmp L_check_mmx_pop +L_dont_use_mmx: + mov dword ptr [inflate_fast_use_mmx],3 +L_check_mmx_pop: + pop edx + pop ecx + pop ebx + pop eax + jmp L_check_mmx +; 426 "inffast.S" +ALIGN 4 +L_do_loop: +; 437 "inffast.S" + cmp bl,15 + ja L_get_length_code + + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + +L_get_length_code: + mov edx, [esp+0] + mov ecx, [esp+8] + and edx,ebp + mov eax, [ecx+edx*4] + +L_dolen: + + + + + + + mov cl,ah + sub bl,ah + shr ebp,cl + + + + + + + test al,al + jnz L_test_for_length_base + + shr eax,16 + stosb + +L_while_test: + + + cmp [esp+16],edi + jbe L_break_loop + + cmp [esp+20],esi + ja L_do_loop + jmp L_break_loop + +L_test_for_length_base: +; 502 "inffast.S" + mov edx,eax + shr edx,16 + mov cl,al + + test al,16 + jz L_test_for_second_level_length + and cl,15 + jz L_save_len + cmp bl,cl + jae L_add_bits_to_len + + mov ch,cl + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + mov cl,ch + +L_add_bits_to_len: + mov eax,1 + shl eax,cl + dec eax + sub bl,cl + and eax,ebp + shr ebp,cl + add edx,eax + +L_save_len: + mov [esp+24],edx + + +L_decode_distance: +; 549 "inffast.S" + cmp bl,15 + ja L_get_distance_code + + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + +L_get_distance_code: + mov edx, [esp+4] + mov ecx, [esp+12] + and edx,ebp + mov eax, [ecx+edx*4] + + +L_dodist: + mov edx,eax + shr edx,16 + mov cl,ah + sub bl,ah + shr ebp,cl +; 584 "inffast.S" + mov cl,al + + test al,16 + jz L_test_for_second_level_dist + and cl,15 + jz L_check_dist_one + cmp bl,cl + jae L_add_bits_to_dist + + mov ch,cl + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + mov cl,ch + +L_add_bits_to_dist: + mov eax,1 + shl eax,cl + dec eax + sub bl,cl + and eax,ebp + shr ebp,cl + add edx,eax + jmp L_check_window + +L_check_window: +; 625 "inffast.S" + mov [esp+44],esi + mov eax,edi + sub eax, [esp+40] + + cmp eax,edx + jb L_clip_window + + mov ecx, [esp+24] + mov esi,edi + sub esi,edx + + sub ecx,3 + mov al, [esi] + mov [edi],al + mov al, [esi+1] + mov dl, [esi+2] + add esi,3 + mov [edi+1],al + mov [edi+2],dl + add edi,3 + rep movsb + + mov esi, [esp+44] + jmp L_while_test + +ALIGN 4 +L_check_dist_one: + cmp edx,1 + jne L_check_window + cmp [esp+40],edi + je L_check_window + + dec edi + mov ecx, [esp+24] + mov al, [edi] + sub ecx,3 + + mov [edi+1],al + mov [edi+2],al + mov [edi+3],al + add edi,4 + rep stosb + + jmp L_while_test + +ALIGN 4 +L_test_for_second_level_length: + + + + + test al,64 + jnz L_test_for_end_of_block + + mov eax,1 + shl eax,cl + dec eax + and eax,ebp + add eax,edx + mov edx, [esp+8] + mov eax, [edx+eax*4] + jmp L_dolen + +ALIGN 4 +L_test_for_second_level_dist: + + + + + test al,64 + jnz L_invalid_distance_code + + mov eax,1 + shl eax,cl + dec eax + and eax,ebp + add eax,edx + mov edx, [esp+12] + mov eax, [edx+eax*4] + jmp L_dodist + +ALIGN 4 +L_clip_window: +; 721 "inffast.S" + mov ecx,eax + mov eax, [esp+52] + neg ecx + mov esi, [esp+56] + + cmp eax,edx + jb L_invalid_distance_too_far + + add ecx,edx + cmp dword ptr [esp+48],0 + jne L_wrap_around_window + + sub eax,ecx + add esi,eax +; 749 "inffast.S" + mov eax, [esp+24] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + jmp L_do_copy1 + + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + jmp L_do_copy1 + +L_wrap_around_window: +; 793 "inffast.S" + mov eax, [esp+48] + cmp ecx,eax + jbe L_contiguous_in_window + + add esi, [esp+52] + add esi,eax + sub esi,ecx + sub ecx,eax + + + mov eax, [esp+24] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi, [esp+56] + mov ecx, [esp+48] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + jmp L_do_copy1 + +L_contiguous_in_window: +; 836 "inffast.S" + add esi,eax + sub esi,ecx + + + mov eax, [esp+24] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + +L_do_copy1: +; 862 "inffast.S" + mov ecx,eax + rep movsb + + mov esi, [esp+44] + jmp L_while_test +; 878 "inffast.S" +ALIGN 4 +L_init_mmx: + emms + + + + + + movd mm0,ebp + mov ebp,ebx +; 896 "inffast.S" + movd mm4,dword ptr [esp+0] + movq mm3,mm4 + movd mm5,dword ptr [esp+4] + movq mm2,mm5 + pxor mm1,mm1 + mov ebx, [esp+8] + jmp L_do_loop_mmx + +ALIGN 4 +L_do_loop_mmx: + psrlq mm0,mm1 + + cmp ebp,32 + ja L_get_length_code_mmx + + movd mm6,ebp + movd mm7,dword ptr [esi] + add esi,4 + psllq mm7,mm6 + add ebp,32 + por mm0,mm7 + +L_get_length_code_mmx: + pand mm4,mm0 + movd eax,mm4 + movq mm4,mm3 + mov eax, [ebx+eax*4] + +L_dolen_mmx: + movzx ecx,ah + movd mm1,ecx + sub ebp,ecx + + test al,al + jnz L_test_for_length_base_mmx + + shr eax,16 + stosb + +L_while_test_mmx: + + + cmp [esp+16],edi + jbe L_break_loop + + cmp [esp+20],esi + ja L_do_loop_mmx + jmp L_break_loop + +L_test_for_length_base_mmx: + + mov edx,eax + shr edx,16 + + test al,16 + jz L_test_for_second_level_length_mmx + and eax,15 + jz L_decode_distance_mmx + + psrlq mm0,mm1 + movd mm1,eax + movd ecx,mm0 + sub ebp,eax + and ecx, [inflate_fast_mask+eax*4] + add edx,ecx + +L_decode_distance_mmx: + psrlq mm0,mm1 + + cmp ebp,32 + ja L_get_dist_code_mmx + + movd mm6,ebp + movd mm7,dword ptr [esi] + add esi,4 + psllq mm7,mm6 + add ebp,32 + por mm0,mm7 + +L_get_dist_code_mmx: + mov ebx, [esp+12] + pand mm5,mm0 + movd eax,mm5 + movq mm5,mm2 + mov eax, [ebx+eax*4] + +L_dodist_mmx: + + movzx ecx,ah + mov ebx,eax + shr ebx,16 + sub ebp,ecx + movd mm1,ecx + + test al,16 + jz L_test_for_second_level_dist_mmx + and eax,15 + jz L_check_dist_one_mmx + +L_add_bits_to_dist_mmx: + psrlq mm0,mm1 + movd mm1,eax + movd ecx,mm0 + sub ebp,eax + and ecx, [inflate_fast_mask+eax*4] + add ebx,ecx + +L_check_window_mmx: + mov [esp+44],esi + mov eax,edi + sub eax, [esp+40] + + cmp eax,ebx + jb L_clip_window_mmx + + mov ecx,edx + mov esi,edi + sub esi,ebx + + sub ecx,3 + mov al, [esi] + mov [edi],al + mov al, [esi+1] + mov dl, [esi+2] + add esi,3 + mov [edi+1],al + mov [edi+2],dl + add edi,3 + rep movsb + + mov esi, [esp+44] + mov ebx, [esp+8] + jmp L_while_test_mmx + +ALIGN 4 +L_check_dist_one_mmx: + cmp ebx,1 + jne L_check_window_mmx + cmp [esp+40],edi + je L_check_window_mmx + + dec edi + mov ecx,edx + mov al, [edi] + sub ecx,3 + + mov [edi+1],al + mov [edi+2],al + mov [edi+3],al + add edi,4 + rep stosb + + mov ebx, [esp+8] + jmp L_while_test_mmx + +ALIGN 4 +L_test_for_second_level_length_mmx: + test al,64 + jnz L_test_for_end_of_block + + and eax,15 + psrlq mm0,mm1 + movd ecx,mm0 + and ecx, [inflate_fast_mask+eax*4] + add ecx,edx + mov eax, [ebx+ecx*4] + jmp L_dolen_mmx + +ALIGN 4 +L_test_for_second_level_dist_mmx: + test al,64 + jnz L_invalid_distance_code + + and eax,15 + psrlq mm0,mm1 + movd ecx,mm0 + and ecx, [inflate_fast_mask+eax*4] + mov eax, [esp+12] + add ecx,ebx + mov eax, [eax+ecx*4] + jmp L_dodist_mmx + +ALIGN 4 +L_clip_window_mmx: + + mov ecx,eax + mov eax, [esp+52] + neg ecx + mov esi, [esp+56] + + cmp eax,ebx + jb L_invalid_distance_too_far + + add ecx,ebx + cmp dword ptr [esp+48],0 + jne L_wrap_around_window_mmx + + sub eax,ecx + add esi,eax + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + jmp L_do_copy1_mmx + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + jmp L_do_copy1_mmx + +L_wrap_around_window_mmx: + + mov eax, [esp+48] + cmp ecx,eax + jbe L_contiguous_in_window_mmx + + add esi, [esp+52] + add esi,eax + sub esi,ecx + sub ecx,eax + + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi, [esp+56] + mov ecx, [esp+48] + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + jmp L_do_copy1_mmx + +L_contiguous_in_window_mmx: + + add esi,eax + sub esi,ecx + + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + +L_do_copy1_mmx: + + + mov ecx,edx + rep movsb + + mov esi, [esp+44] + mov ebx, [esp+8] + jmp L_while_test_mmx +; 1174 "inffast.S" +L_invalid_distance_code: + + + + + + mov ecx, invalid_distance_code_msg + mov edx,INFLATE_MODE_BAD + jmp L_update_stream_state + +L_test_for_end_of_block: + + + + + + test al,32 + jz L_invalid_literal_length_code + + mov ecx,0 + mov edx,INFLATE_MODE_TYPE + jmp L_update_stream_state + +L_invalid_literal_length_code: + + + + + + mov ecx, invalid_literal_length_code_msg + mov edx,INFLATE_MODE_BAD + jmp L_update_stream_state + +L_invalid_distance_too_far: + + + + mov esi, [esp+44] + mov ecx, invalid_distance_too_far_msg + mov edx,INFLATE_MODE_BAD + jmp L_update_stream_state + +L_update_stream_state: + + mov eax, [esp+88] + test ecx,ecx + jz L_skip_msg + mov [eax+24],ecx +L_skip_msg: + mov eax, [eax+28] + mov [eax+mode_state],edx + jmp L_break_loop + +ALIGN 4 +L_break_loop: +; 1243 "inffast.S" + cmp dword ptr [inflate_fast_use_mmx],2 + jne L_update_next_in + + + + mov ebx,ebp + +L_update_next_in: +; 1266 "inffast.S" + mov eax, [esp+88] + mov ecx,ebx + mov edx, [eax+28] + shr ecx,3 + sub esi,ecx + shl ecx,3 + sub ebx,ecx + mov [eax+12],edi + mov [edx+bits_state],ebx + mov ecx,ebx + + lea ebx, [esp+28] + cmp [esp+20],ebx + jne L_buf_not_used + + sub esi,ebx + mov ebx, [eax+0] + mov [esp+20],ebx + add esi,ebx + mov ebx, [eax+4] + sub ebx,11 + add [esp+20],ebx + +L_buf_not_used: + mov [eax+0],esi + + mov ebx,1 + shl ebx,cl + dec ebx + + + + + + cmp dword ptr [inflate_fast_use_mmx],2 + jne L_update_hold + + + + psrlq mm0,mm1 + movd ebp,mm0 + + emms + +L_update_hold: + + + + and ebp,ebx + mov [edx+hold_state],ebp + + + + + mov ebx, [esp+20] + cmp ebx,esi + jbe L_last_is_smaller + + sub ebx,esi + add ebx,11 + mov [eax+4],ebx + jmp L_fixup_out +L_last_is_smaller: + sub esi,ebx + neg esi + add esi,11 + mov [eax+4],esi + + + + +L_fixup_out: + + mov ebx, [esp+16] + cmp ebx,edi + jbe L_end_is_smaller + + sub ebx,edi + add ebx,257 + mov [eax+16],ebx + jmp L_done +L_end_is_smaller: + sub edi,ebx + neg edi + add edi,257 + mov [eax+16],edi + + + + + +L_done: + add esp,64 + popfd + pop ebx + pop ebp + pop esi + pop edi + ret +_inflate_fast endp + +_TEXT ends +end diff --git a/SkinInstaller/zlib/inffas8664.c b/SkinInstaller/zlib/inffas8664.c index e8af06fa..aa861a33 100644 --- a/SkinInstaller/zlib/inffas8664.c +++ b/SkinInstaller/zlib/inffas8664.c @@ -1,186 +1,186 @@ -/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding - * version for AMD64 on Windows using Microsoft C compiler - * - * Copyright (C) 1995-2003 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Copyright (C) 2003 Chris Anderson <christop@charm.net> - * Please use the copyright conditions above. - * - * 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant - * - * inffas8664.c call function inffas8664fnc in inffasx64.asm - * inffasx64.asm is automatically convert from AMD64 portion of inffas86.c - * - * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also - * slightly quicker on x86 systems because, instead of using rep movsb to copy - * data, it uses rep movsw, which moves data in 2-byte chunks instead of single - * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates - * from http://fedora.linux.duke.edu/fc1_x86_64 - * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with - * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, - * when decompressing mozilla-source-1.3.tar.gz. - * - * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from - * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at - * the moment. I have successfully compiled and tested this code with gcc2.96, - * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S - * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX - * enabled. I will attempt to merge the MMX code into this version. Newer - * versions of this and inffast.S can be found at - * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ - * - */ - -#include <stdio.h> -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -/* Mark Adler's comments from inffast.c: */ - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state->mode == LEN - strm->avail_in >= 6 - strm->avail_out >= 258 - start >= strm->avail_out - state->bits < 8 - - On return, state->mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm->avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for - output space. - */ - - - - typedef struct inffast_ar { -/* 64 32 x86 x86_64 */ -/* ar offset register */ -/* 0 0 */ void *esp; /* esp save */ -/* 8 4 */ void *ebp; /* ebp save */ -/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ -/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ -/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ -/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ -/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ -/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ -/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ -/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ -/* 80 40 */ size_t /*unsigned long */hold; /* edx rdx local strm->hold */ -/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ -/* 92 48 */ unsigned wsize; /* window size */ -/* 96 52 */ unsigned write; /* window write index */ -/*100 56 */ unsigned lmask; /* r12 mask for lcode */ -/*104 60 */ unsigned dmask; /* r13 mask for dcode */ -/*108 64 */ unsigned len; /* r14 match length */ -/*112 68 */ unsigned dist; /* r15 match distance */ -/*116 72 */ unsigned status; /* set when state chng*/ - } type_ar; -#ifdef ASMINF - -void inflate_fast(strm, start) -z_streamp strm; -unsigned start; /* inflate()'s starting value for strm->avail_out */ -{ - struct inflate_state FAR *state; - type_ar ar; - void inffas8664fnc(struct inffast_ar * par); - - - -#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64)) -#define PAD_AVAIL_IN 6 -#define PAD_AVAIL_OUT 258 -#else -#define PAD_AVAIL_IN 5 -#define PAD_AVAIL_OUT 257 -#endif - - /* copy state to local variables */ - state = (struct inflate_state FAR *)strm->state; - - ar.in = strm->next_in; - ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); - ar.out = strm->next_out; - ar.beg = ar.out - (start - strm->avail_out); - ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); - ar.wsize = state->wsize; - ar.write = state->wnext; - ar.window = state->window; - ar.hold = state->hold; - ar.bits = state->bits; - ar.lcode = state->lencode; - ar.dcode = state->distcode; - ar.lmask = (1U << state->lenbits) - 1; - ar.dmask = (1U << state->distbits) - 1; - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - - /* align in on 1/2 hold size boundary */ - while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { - ar.hold += (unsigned long)*ar.in++ << ar.bits; - ar.bits += 8; - } - - inffas8664fnc(&ar); - - if (ar.status > 1) { - if (ar.status == 2) - strm->msg = "invalid literal/length code"; - else if (ar.status == 3) - strm->msg = "invalid distance code"; - else - strm->msg = "invalid distance too far back"; - state->mode = BAD; - } - else if ( ar.status == 1 ) { - state->mode = TYPE; - } - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - ar.len = ar.bits >> 3; - ar.in -= ar.len; - ar.bits -= ar.len << 3; - ar.hold &= (1U << ar.bits) - 1; - - /* update state and return */ - strm->next_in = ar.in; - strm->next_out = ar.out; - strm->avail_in = (unsigned)(ar.in < ar.last ? - PAD_AVAIL_IN + (ar.last - ar.in) : - PAD_AVAIL_IN - (ar.in - ar.last)); - strm->avail_out = (unsigned)(ar.out < ar.end ? - PAD_AVAIL_OUT + (ar.end - ar.out) : - PAD_AVAIL_OUT - (ar.out - ar.end)); - state->hold = (unsigned long)ar.hold; - state->bits = ar.bits; - return; -} - -#endif +/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding + * version for AMD64 on Windows using Microsoft C compiler + * + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Copyright (C) 2003 Chris Anderson <christop@charm.net> + * Please use the copyright conditions above. + * + * 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant + * + * inffas8664.c call function inffas8664fnc in inffasx64.asm + * inffasx64.asm is automatically convert from AMD64 portion of inffas86.c + * + * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also + * slightly quicker on x86 systems because, instead of using rep movsb to copy + * data, it uses rep movsw, which moves data in 2-byte chunks instead of single + * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates + * from http://fedora.linux.duke.edu/fc1_x86_64 + * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with + * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, + * when decompressing mozilla-source-1.3.tar.gz. + * + * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from + * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at + * the moment. I have successfully compiled and tested this code with gcc2.96, + * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S + * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX + * enabled. I will attempt to merge the MMX code into this version. Newer + * versions of this and inffast.S can be found at + * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ + * + */ + +#include <stdio.h> +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* Mark Adler's comments from inffast.c: */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ + + + + typedef struct inffast_ar { +/* 64 32 x86 x86_64 */ +/* ar offset register */ +/* 0 0 */ void *esp; /* esp save */ +/* 8 4 */ void *ebp; /* ebp save */ +/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ +/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ +/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ +/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ +/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ +/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ +/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ +/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ +/* 80 40 */ size_t /*unsigned long */hold; /* edx rdx local strm->hold */ +/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ +/* 92 48 */ unsigned wsize; /* window size */ +/* 96 52 */ unsigned write; /* window write index */ +/*100 56 */ unsigned lmask; /* r12 mask for lcode */ +/*104 60 */ unsigned dmask; /* r13 mask for dcode */ +/*108 64 */ unsigned len; /* r14 match length */ +/*112 68 */ unsigned dist; /* r15 match distance */ +/*116 72 */ unsigned status; /* set when state chng*/ + } type_ar; +#ifdef ASMINF + +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + type_ar ar; + void inffas8664fnc(struct inffast_ar * par); + + + +#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64)) +#define PAD_AVAIL_IN 6 +#define PAD_AVAIL_OUT 258 +#else +#define PAD_AVAIL_IN 5 +#define PAD_AVAIL_OUT 257 +#endif + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + + ar.in = strm->next_in; + ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); + ar.out = strm->next_out; + ar.beg = ar.out - (start - strm->avail_out); + ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); + ar.wsize = state->wsize; + ar.write = state->wnext; + ar.window = state->window; + ar.hold = state->hold; + ar.bits = state->bits; + ar.lcode = state->lencode; + ar.dcode = state->distcode; + ar.lmask = (1U << state->lenbits) - 1; + ar.dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + /* align in on 1/2 hold size boundary */ + while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { + ar.hold += (unsigned long)*ar.in++ << ar.bits; + ar.bits += 8; + } + + inffas8664fnc(&ar); + + if (ar.status > 1) { + if (ar.status == 2) + strm->msg = "invalid literal/length code"; + else if (ar.status == 3) + strm->msg = "invalid distance code"; + else + strm->msg = "invalid distance too far back"; + state->mode = BAD; + } + else if ( ar.status == 1 ) { + state->mode = TYPE; + } + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + ar.len = ar.bits >> 3; + ar.in -= ar.len; + ar.bits -= ar.len << 3; + ar.hold &= (1U << ar.bits) - 1; + + /* update state and return */ + strm->next_in = ar.in; + strm->next_out = ar.out; + strm->avail_in = (unsigned)(ar.in < ar.last ? + PAD_AVAIL_IN + (ar.last - ar.in) : + PAD_AVAIL_IN - (ar.in - ar.last)); + strm->avail_out = (unsigned)(ar.out < ar.end ? + PAD_AVAIL_OUT + (ar.end - ar.out) : + PAD_AVAIL_OUT - (ar.out - ar.end)); + state->hold = (unsigned long)ar.hold; + state->bits = ar.bits; + return; +} + +#endif diff --git a/SkinInstaller/zlib/inffasx64.asm b/SkinInstaller/zlib/inffasx64.asm index 60a8d89b..41ec8239 100644 --- a/SkinInstaller/zlib/inffasx64.asm +++ b/SkinInstaller/zlib/inffasx64.asm @@ -1,396 +1,396 @@ -; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding -; version for AMD64 on Windows using Microsoft C compiler -; -; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c -; inffasx64.asm is called by inffas8664.c, which contain more info. - - -; to compile this file, I use option -; ml64.exe /Flinffasx64 /c /Zi inffasx64.asm -; with Microsoft Macro Assembler (x64) for AMD64 -; - -; This file compile with Microsoft Macro Assembler (x64) for AMD64 -; -; ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK -; -; (you can get Windows WDK with ml64 for AMD64 from -; http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price) -; - - -.code -inffas8664fnc PROC - -; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and -; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp -; -; All registers must be preserved across the call, except for -; rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch. - - - mov [rsp-8],rsi - mov [rsp-16],rdi - mov [rsp-24],r12 - mov [rsp-32],r13 - mov [rsp-40],r14 - mov [rsp-48],r15 - mov [rsp-56],rbx - - mov rax,rcx - - mov [rax+8], rbp ; /* save regs rbp and rsp */ - mov [rax], rsp - - mov rsp, rax ; /* make rsp point to &ar */ - - mov rsi, [rsp+16] ; /* rsi = in */ - mov rdi, [rsp+32] ; /* rdi = out */ - mov r9, [rsp+24] ; /* r9 = last */ - mov r10, [rsp+48] ; /* r10 = end */ - mov rbp, [rsp+64] ; /* rbp = lcode */ - mov r11, [rsp+72] ; /* r11 = dcode */ - mov rdx, [rsp+80] ; /* rdx = hold */ - mov ebx, [rsp+88] ; /* ebx = bits */ - mov r12d, [rsp+100] ; /* r12d = lmask */ - mov r13d, [rsp+104] ; /* r13d = dmask */ - ; /* r14d = len */ - ; /* r15d = dist */ - - - cld - cmp r10, rdi - je L_one_time ; /* if only one decode left */ - cmp r9, rsi - - jne L_do_loop - - -L_one_time: - mov r8, r12 ; /* r8 = lmask */ - cmp bl, 32 - ja L_get_length_code_one_time - - lodsd ; /* eax = *(uint *)in++ */ - mov cl, bl ; /* cl = bits, needs it for shifting */ - add bl, 32 ; /* bits += 32 */ - shl rax, cl - or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ - jmp L_get_length_code_one_time - -ALIGN 4 -L_while_test: - cmp r10, rdi - jbe L_break_loop - cmp r9, rsi - jbe L_break_loop - -L_do_loop: - mov r8, r12 ; /* r8 = lmask */ - cmp bl, 32 - ja L_get_length_code ; /* if (32 < bits) */ - - lodsd ; /* eax = *(uint *)in++ */ - mov cl, bl ; /* cl = bits, needs it for shifting */ - add bl, 32 ; /* bits += 32 */ - shl rax, cl - or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ - -L_get_length_code: - and r8, rdx ; /* r8 &= hold */ - mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ - - mov cl, ah ; /* cl = this.bits */ - sub bl, ah ; /* bits -= this.bits */ - shr rdx, cl ; /* hold >>= this.bits */ - - test al, al - jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ - - mov r8, r12 ; /* r8 = lmask */ - shr eax, 16 ; /* output this.val char */ - stosb - -L_get_length_code_one_time: - and r8, rdx ; /* r8 &= hold */ - mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ - -L_dolen: - mov cl, ah ; /* cl = this.bits */ - sub bl, ah ; /* bits -= this.bits */ - shr rdx, cl ; /* hold >>= this.bits */ - - test al, al - jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ - - shr eax, 16 ; /* output this.val char */ - stosb - jmp L_while_test - -ALIGN 4 -L_test_for_length_base: - mov r14d, eax ; /* len = this */ - shr r14d, 16 ; /* len = this.val */ - mov cl, al - - test al, 16 - jz L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */ - and cl, 15 ; /* op &= 15 */ - jz L_decode_distance ; /* if (!op) */ - -L_add_bits_to_len: - sub bl, cl - xor eax, eax - inc eax - shl eax, cl - dec eax - and eax, edx ; /* eax &= hold */ - shr rdx, cl - add r14d, eax ; /* len += hold & mask[op] */ - -L_decode_distance: - mov r8, r13 ; /* r8 = dmask */ - cmp bl, 32 - ja L_get_distance_code ; /* if (32 < bits) */ - - lodsd ; /* eax = *(uint *)in++ */ - mov cl, bl ; /* cl = bits, needs it for shifting */ - add bl, 32 ; /* bits += 32 */ - shl rax, cl - or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ - -L_get_distance_code: - and r8, rdx ; /* r8 &= hold */ - mov eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */ - -L_dodist: - mov r15d, eax ; /* dist = this */ - shr r15d, 16 ; /* dist = this.val */ - mov cl, ah - sub bl, ah ; /* bits -= this.bits */ - shr rdx, cl ; /* hold >>= this.bits */ - mov cl, al ; /* cl = this.op */ - - test al, 16 ; /* if ((op & 16) == 0) */ - jz L_test_for_second_level_dist - and cl, 15 ; /* op &= 15 */ - jz L_check_dist_one - -L_add_bits_to_dist: - sub bl, cl - xor eax, eax - inc eax - shl eax, cl - dec eax ; /* (1 << op) - 1 */ - and eax, edx ; /* eax &= hold */ - shr rdx, cl - add r15d, eax ; /* dist += hold & ((1 << op) - 1) */ - -L_check_window: - mov r8, rsi ; /* save in so from can use it's reg */ - mov rax, rdi - sub rax, [rsp+40] ; /* nbytes = out - beg */ - - cmp eax, r15d - jb L_clip_window ; /* if (dist > nbytes) 4.2% */ - - mov ecx, r14d ; /* ecx = len */ - mov rsi, rdi - sub rsi, r15 ; /* from = out - dist */ - - sar ecx, 1 - jnc L_copy_two ; /* if len % 2 == 0 */ - - rep movsw - mov al, [rsi] - mov [rdi], al - inc rdi - - mov rsi, r8 ; /* move in back to %rsi, toss from */ - jmp L_while_test - -L_copy_two: - rep movsw - mov rsi, r8 ; /* move in back to %rsi, toss from */ - jmp L_while_test - -ALIGN 4 -L_check_dist_one: - cmp r15d, 1 ; /* if dist 1, is a memset */ - jne L_check_window - cmp [rsp+40], rdi ; /* if out == beg, outside window */ - je L_check_window - - mov ecx, r14d ; /* ecx = len */ - mov al, [rdi-1] - mov ah, al - - sar ecx, 1 - jnc L_set_two - mov [rdi], al - inc rdi - -L_set_two: - rep stosw - jmp L_while_test - -ALIGN 4 -L_test_for_second_level_length: - test al, 64 - jnz L_test_for_end_of_block ; /* if ((op & 64) != 0) */ - - xor eax, eax - inc eax - shl eax, cl - dec eax - and eax, edx ; /* eax &= hold */ - add eax, r14d ; /* eax += len */ - mov eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/ - jmp L_dolen - -ALIGN 4 -L_test_for_second_level_dist: - test al, 64 - jnz L_invalid_distance_code ; /* if ((op & 64) != 0) */ - - xor eax, eax - inc eax - shl eax, cl - dec eax - and eax, edx ; /* eax &= hold */ - add eax, r15d ; /* eax += dist */ - mov eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/ - jmp L_dodist - -ALIGN 4 -L_clip_window: - mov ecx, eax ; /* ecx = nbytes */ - mov eax, [rsp+92] ; /* eax = wsize, prepare for dist cmp */ - neg ecx ; /* nbytes = -nbytes */ - - cmp eax, r15d - jb L_invalid_distance_too_far ; /* if (dist > wsize) */ - - add ecx, r15d ; /* nbytes = dist - nbytes */ - cmp dword ptr [rsp+96], 0 - jne L_wrap_around_window ; /* if (write != 0) */ - - mov rsi, [rsp+56] ; /* from = window */ - sub eax, ecx ; /* eax -= nbytes */ - add rsi, rax ; /* from += wsize - nbytes */ - - mov eax, r14d ; /* eax = len */ - cmp r14d, ecx - jbe L_do_copy ; /* if (nbytes >= len) */ - - sub eax, ecx ; /* eax -= nbytes */ - rep movsb - mov rsi, rdi - sub rsi, r15 ; /* from = &out[ -dist ] */ - jmp L_do_copy - -ALIGN 4 -L_wrap_around_window: - mov eax, [rsp+96] ; /* eax = write */ - cmp ecx, eax - jbe L_contiguous_in_window ; /* if (write >= nbytes) */ - - mov esi, [rsp+92] ; /* from = wsize */ - add rsi, [rsp+56] ; /* from += window */ - add rsi, rax ; /* from += write */ - sub rsi, rcx ; /* from -= nbytes */ - sub ecx, eax ; /* nbytes -= write */ - - mov eax, r14d ; /* eax = len */ - cmp eax, ecx - jbe L_do_copy ; /* if (nbytes >= len) */ - - sub eax, ecx ; /* len -= nbytes */ - rep movsb - mov rsi, [rsp+56] ; /* from = window */ - mov ecx, [rsp+96] ; /* nbytes = write */ - cmp eax, ecx - jbe L_do_copy ; /* if (nbytes >= len) */ - - sub eax, ecx ; /* len -= nbytes */ - rep movsb - mov rsi, rdi - sub rsi, r15 ; /* from = out - dist */ - jmp L_do_copy - -ALIGN 4 -L_contiguous_in_window: - mov rsi, [rsp+56] ; /* rsi = window */ - add rsi, rax - sub rsi, rcx ; /* from += write - nbytes */ - - mov eax, r14d ; /* eax = len */ - cmp eax, ecx - jbe L_do_copy ; /* if (nbytes >= len) */ - - sub eax, ecx ; /* len -= nbytes */ - rep movsb - mov rsi, rdi - sub rsi, r15 ; /* from = out - dist */ - jmp L_do_copy ; /* if (nbytes >= len) */ - -ALIGN 4 -L_do_copy: - mov ecx, eax ; /* ecx = len */ - rep movsb - - mov rsi, r8 ; /* move in back to %esi, toss from */ - jmp L_while_test - -L_test_for_end_of_block: - test al, 32 - jz L_invalid_literal_length_code - mov dword ptr [rsp+116], 1 - jmp L_break_loop_with_status - -L_invalid_literal_length_code: - mov dword ptr [rsp+116], 2 - jmp L_break_loop_with_status - -L_invalid_distance_code: - mov dword ptr [rsp+116], 3 - jmp L_break_loop_with_status - -L_invalid_distance_too_far: - mov dword ptr [rsp+116], 4 - jmp L_break_loop_with_status - -L_break_loop: - mov dword ptr [rsp+116], 0 - -L_break_loop_with_status: -; /* put in, out, bits, and hold back into ar and pop esp */ - mov [rsp+16], rsi ; /* in */ - mov [rsp+32], rdi ; /* out */ - mov [rsp+88], ebx ; /* bits */ - mov [rsp+80], rdx ; /* hold */ - - mov rax, [rsp] ; /* restore rbp and rsp */ - mov rbp, [rsp+8] - mov rsp, rax - - - - mov rsi,[rsp-8] - mov rdi,[rsp-16] - mov r12,[rsp-24] - mov r13,[rsp-32] - mov r14,[rsp-40] - mov r15,[rsp-48] - mov rbx,[rsp-56] - - ret 0 -; : -; : "m" (ar) -; : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", -; "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" -; ); - -inffas8664fnc ENDP -;_TEXT ENDS -END +; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding +; version for AMD64 on Windows using Microsoft C compiler +; +; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c +; inffasx64.asm is called by inffas8664.c, which contain more info. + + +; to compile this file, I use option +; ml64.exe /Flinffasx64 /c /Zi inffasx64.asm +; with Microsoft Macro Assembler (x64) for AMD64 +; + +; This file compile with Microsoft Macro Assembler (x64) for AMD64 +; +; ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK +; +; (you can get Windows WDK with ml64 for AMD64 from +; http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price) +; + + +.code +inffas8664fnc PROC + +; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and +; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp +; +; All registers must be preserved across the call, except for +; rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch. + + + mov [rsp-8],rsi + mov [rsp-16],rdi + mov [rsp-24],r12 + mov [rsp-32],r13 + mov [rsp-40],r14 + mov [rsp-48],r15 + mov [rsp-56],rbx + + mov rax,rcx + + mov [rax+8], rbp ; /* save regs rbp and rsp */ + mov [rax], rsp + + mov rsp, rax ; /* make rsp point to &ar */ + + mov rsi, [rsp+16] ; /* rsi = in */ + mov rdi, [rsp+32] ; /* rdi = out */ + mov r9, [rsp+24] ; /* r9 = last */ + mov r10, [rsp+48] ; /* r10 = end */ + mov rbp, [rsp+64] ; /* rbp = lcode */ + mov r11, [rsp+72] ; /* r11 = dcode */ + mov rdx, [rsp+80] ; /* rdx = hold */ + mov ebx, [rsp+88] ; /* ebx = bits */ + mov r12d, [rsp+100] ; /* r12d = lmask */ + mov r13d, [rsp+104] ; /* r13d = dmask */ + ; /* r14d = len */ + ; /* r15d = dist */ + + + cld + cmp r10, rdi + je L_one_time ; /* if only one decode left */ + cmp r9, rsi + + jne L_do_loop + + +L_one_time: + mov r8, r12 ; /* r8 = lmask */ + cmp bl, 32 + ja L_get_length_code_one_time + + lodsd ; /* eax = *(uint *)in++ */ + mov cl, bl ; /* cl = bits, needs it for shifting */ + add bl, 32 ; /* bits += 32 */ + shl rax, cl + or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ + jmp L_get_length_code_one_time + +ALIGN 4 +L_while_test: + cmp r10, rdi + jbe L_break_loop + cmp r9, rsi + jbe L_break_loop + +L_do_loop: + mov r8, r12 ; /* r8 = lmask */ + cmp bl, 32 + ja L_get_length_code ; /* if (32 < bits) */ + + lodsd ; /* eax = *(uint *)in++ */ + mov cl, bl ; /* cl = bits, needs it for shifting */ + add bl, 32 ; /* bits += 32 */ + shl rax, cl + or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ + +L_get_length_code: + and r8, rdx ; /* r8 &= hold */ + mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ + + mov cl, ah ; /* cl = this.bits */ + sub bl, ah ; /* bits -= this.bits */ + shr rdx, cl ; /* hold >>= this.bits */ + + test al, al + jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ + + mov r8, r12 ; /* r8 = lmask */ + shr eax, 16 ; /* output this.val char */ + stosb + +L_get_length_code_one_time: + and r8, rdx ; /* r8 &= hold */ + mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ + +L_dolen: + mov cl, ah ; /* cl = this.bits */ + sub bl, ah ; /* bits -= this.bits */ + shr rdx, cl ; /* hold >>= this.bits */ + + test al, al + jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ + + shr eax, 16 ; /* output this.val char */ + stosb + jmp L_while_test + +ALIGN 4 +L_test_for_length_base: + mov r14d, eax ; /* len = this */ + shr r14d, 16 ; /* len = this.val */ + mov cl, al + + test al, 16 + jz L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */ + and cl, 15 ; /* op &= 15 */ + jz L_decode_distance ; /* if (!op) */ + +L_add_bits_to_len: + sub bl, cl + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx ; /* eax &= hold */ + shr rdx, cl + add r14d, eax ; /* len += hold & mask[op] */ + +L_decode_distance: + mov r8, r13 ; /* r8 = dmask */ + cmp bl, 32 + ja L_get_distance_code ; /* if (32 < bits) */ + + lodsd ; /* eax = *(uint *)in++ */ + mov cl, bl ; /* cl = bits, needs it for shifting */ + add bl, 32 ; /* bits += 32 */ + shl rax, cl + or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ + +L_get_distance_code: + and r8, rdx ; /* r8 &= hold */ + mov eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */ + +L_dodist: + mov r15d, eax ; /* dist = this */ + shr r15d, 16 ; /* dist = this.val */ + mov cl, ah + sub bl, ah ; /* bits -= this.bits */ + shr rdx, cl ; /* hold >>= this.bits */ + mov cl, al ; /* cl = this.op */ + + test al, 16 ; /* if ((op & 16) == 0) */ + jz L_test_for_second_level_dist + and cl, 15 ; /* op &= 15 */ + jz L_check_dist_one + +L_add_bits_to_dist: + sub bl, cl + xor eax, eax + inc eax + shl eax, cl + dec eax ; /* (1 << op) - 1 */ + and eax, edx ; /* eax &= hold */ + shr rdx, cl + add r15d, eax ; /* dist += hold & ((1 << op) - 1) */ + +L_check_window: + mov r8, rsi ; /* save in so from can use it's reg */ + mov rax, rdi + sub rax, [rsp+40] ; /* nbytes = out - beg */ + + cmp eax, r15d + jb L_clip_window ; /* if (dist > nbytes) 4.2% */ + + mov ecx, r14d ; /* ecx = len */ + mov rsi, rdi + sub rsi, r15 ; /* from = out - dist */ + + sar ecx, 1 + jnc L_copy_two ; /* if len % 2 == 0 */ + + rep movsw + mov al, [rsi] + mov [rdi], al + inc rdi + + mov rsi, r8 ; /* move in back to %rsi, toss from */ + jmp L_while_test + +L_copy_two: + rep movsw + mov rsi, r8 ; /* move in back to %rsi, toss from */ + jmp L_while_test + +ALIGN 4 +L_check_dist_one: + cmp r15d, 1 ; /* if dist 1, is a memset */ + jne L_check_window + cmp [rsp+40], rdi ; /* if out == beg, outside window */ + je L_check_window + + mov ecx, r14d ; /* ecx = len */ + mov al, [rdi-1] + mov ah, al + + sar ecx, 1 + jnc L_set_two + mov [rdi], al + inc rdi + +L_set_two: + rep stosw + jmp L_while_test + +ALIGN 4 +L_test_for_second_level_length: + test al, 64 + jnz L_test_for_end_of_block ; /* if ((op & 64) != 0) */ + + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx ; /* eax &= hold */ + add eax, r14d ; /* eax += len */ + mov eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/ + jmp L_dolen + +ALIGN 4 +L_test_for_second_level_dist: + test al, 64 + jnz L_invalid_distance_code ; /* if ((op & 64) != 0) */ + + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx ; /* eax &= hold */ + add eax, r15d ; /* eax += dist */ + mov eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/ + jmp L_dodist + +ALIGN 4 +L_clip_window: + mov ecx, eax ; /* ecx = nbytes */ + mov eax, [rsp+92] ; /* eax = wsize, prepare for dist cmp */ + neg ecx ; /* nbytes = -nbytes */ + + cmp eax, r15d + jb L_invalid_distance_too_far ; /* if (dist > wsize) */ + + add ecx, r15d ; /* nbytes = dist - nbytes */ + cmp dword ptr [rsp+96], 0 + jne L_wrap_around_window ; /* if (write != 0) */ + + mov rsi, [rsp+56] ; /* from = window */ + sub eax, ecx ; /* eax -= nbytes */ + add rsi, rax ; /* from += wsize - nbytes */ + + mov eax, r14d ; /* eax = len */ + cmp r14d, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* eax -= nbytes */ + rep movsb + mov rsi, rdi + sub rsi, r15 ; /* from = &out[ -dist ] */ + jmp L_do_copy + +ALIGN 4 +L_wrap_around_window: + mov eax, [rsp+96] ; /* eax = write */ + cmp ecx, eax + jbe L_contiguous_in_window ; /* if (write >= nbytes) */ + + mov esi, [rsp+92] ; /* from = wsize */ + add rsi, [rsp+56] ; /* from += window */ + add rsi, rax ; /* from += write */ + sub rsi, rcx ; /* from -= nbytes */ + sub ecx, eax ; /* nbytes -= write */ + + mov eax, r14d ; /* eax = len */ + cmp eax, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* len -= nbytes */ + rep movsb + mov rsi, [rsp+56] ; /* from = window */ + mov ecx, [rsp+96] ; /* nbytes = write */ + cmp eax, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* len -= nbytes */ + rep movsb + mov rsi, rdi + sub rsi, r15 ; /* from = out - dist */ + jmp L_do_copy + +ALIGN 4 +L_contiguous_in_window: + mov rsi, [rsp+56] ; /* rsi = window */ + add rsi, rax + sub rsi, rcx ; /* from += write - nbytes */ + + mov eax, r14d ; /* eax = len */ + cmp eax, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* len -= nbytes */ + rep movsb + mov rsi, rdi + sub rsi, r15 ; /* from = out - dist */ + jmp L_do_copy ; /* if (nbytes >= len) */ + +ALIGN 4 +L_do_copy: + mov ecx, eax ; /* ecx = len */ + rep movsb + + mov rsi, r8 ; /* move in back to %esi, toss from */ + jmp L_while_test + +L_test_for_end_of_block: + test al, 32 + jz L_invalid_literal_length_code + mov dword ptr [rsp+116], 1 + jmp L_break_loop_with_status + +L_invalid_literal_length_code: + mov dword ptr [rsp+116], 2 + jmp L_break_loop_with_status + +L_invalid_distance_code: + mov dword ptr [rsp+116], 3 + jmp L_break_loop_with_status + +L_invalid_distance_too_far: + mov dword ptr [rsp+116], 4 + jmp L_break_loop_with_status + +L_break_loop: + mov dword ptr [rsp+116], 0 + +L_break_loop_with_status: +; /* put in, out, bits, and hold back into ar and pop esp */ + mov [rsp+16], rsi ; /* in */ + mov [rsp+32], rdi ; /* out */ + mov [rsp+88], ebx ; /* bits */ + mov [rsp+80], rdx ; /* hold */ + + mov rax, [rsp] ; /* restore rbp and rsp */ + mov rbp, [rsp+8] + mov rsp, rax + + + + mov rsi,[rsp-8] + mov rdi,[rsp-16] + mov r12,[rsp-24] + mov r13,[rsp-32] + mov r14,[rsp-40] + mov r15,[rsp-48] + mov rbx,[rsp-56] + + ret 0 +; : +; : "m" (ar) +; : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", +; "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" +; ); + +inffas8664fnc ENDP +;_TEXT ENDS +END diff --git a/SkinInstaller/zlib/match686.asm b/SkinInstaller/zlib/match686.asm index 3b09212f..69e0eed0 100644 --- a/SkinInstaller/zlib/match686.asm +++ b/SkinInstaller/zlib/match686.asm @@ -1,479 +1,479 @@ -; match686.asm -- Asm portion of the optimized longest_match for 32 bits x86 -; Copyright (C) 1995-1996 Jean-loup Gailly, Brian Raiter and Gilles Vollant. -; File written by Gilles Vollant, by converting match686.S from Brian Raiter -; for MASM. This is as assembly version of longest_match -; from Jean-loup Gailly in deflate.c -; -; http://www.zlib.net -; http://www.winimage.com/zLibDll -; http://www.muppetlabs.com/~breadbox/software/assembly.html -; -; For Visual C++ 4.x and higher and ML 6.x and higher -; ml.exe is distributed in -; http://www.microsoft.com/downloads/details.aspx?FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64 -; -; this file contain two implementation of longest_match -; -; this longest_match was written by Brian raiter (1998), optimized for Pentium Pro -; (and the faster known version of match_init on modern Core 2 Duo and AMD Phenom) -; -; for using an assembly version of longest_match, you need define ASMV in project -; -; compile the asm file running -; ml /coff /Zi /c /Flmatch686.lst match686.asm -; and do not include match686.obj in your project -; -; note: contrib of zLib 1.2.3 and earlier contained both a deprecated version for -; Pentium (prior Pentium Pro) and this version for Pentium Pro and modern processor -; with autoselect (with cpu detection code) -; if you want support the old pentium optimization, you can still use these version -; -; this file is not optimized for old pentium, but it compatible with all x86 32 bits -; processor (starting 80386) -; -; -; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2 - -;uInt longest_match(s, cur_match) -; deflate_state *s; -; IPos cur_match; /* current match */ - - NbStack equ 76 - cur_match equ dword ptr[esp+NbStack-0] - str_s equ dword ptr[esp+NbStack-4] -; 5 dword on top (ret,ebp,esi,edi,ebx) - adrret equ dword ptr[esp+NbStack-8] - pushebp equ dword ptr[esp+NbStack-12] - pushedi equ dword ptr[esp+NbStack-16] - pushesi equ dword ptr[esp+NbStack-20] - pushebx equ dword ptr[esp+NbStack-24] - - chain_length equ dword ptr [esp+NbStack-28] - limit equ dword ptr [esp+NbStack-32] - best_len equ dword ptr [esp+NbStack-36] - window equ dword ptr [esp+NbStack-40] - prev equ dword ptr [esp+NbStack-44] - scan_start equ word ptr [esp+NbStack-48] - wmask equ dword ptr [esp+NbStack-52] - match_start_ptr equ dword ptr [esp+NbStack-56] - nice_match equ dword ptr [esp+NbStack-60] - scan equ dword ptr [esp+NbStack-64] - - windowlen equ dword ptr [esp+NbStack-68] - match_start equ dword ptr [esp+NbStack-72] - strend equ dword ptr [esp+NbStack-76] - NbStackAdd equ (NbStack-24) - - .386p - - name gvmatch - .MODEL FLAT - - - -; all the +zlib1222add offsets are due to the addition of fields -; in zlib in the deflate_state structure since the asm code was first written -; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). -; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). -; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). - - zlib1222add equ 8 - -; Note : these value are good with a 8 bytes boundary pack structure - dep_chain_length equ 74h+zlib1222add - dep_window equ 30h+zlib1222add - dep_strstart equ 64h+zlib1222add - dep_prev_length equ 70h+zlib1222add - dep_nice_match equ 88h+zlib1222add - dep_w_size equ 24h+zlib1222add - dep_prev equ 38h+zlib1222add - dep_w_mask equ 2ch+zlib1222add - dep_good_match equ 84h+zlib1222add - dep_match_start equ 68h+zlib1222add - dep_lookahead equ 6ch+zlib1222add - - -_TEXT segment - -IFDEF NOUNDERLINE - public longest_match - public match_init -ELSE - public _longest_match - public _match_init -ENDIF - - MAX_MATCH equ 258 - MIN_MATCH equ 3 - MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) - - - -MAX_MATCH equ 258 -MIN_MATCH equ 3 -MIN_LOOKAHEAD equ (MAX_MATCH + MIN_MATCH + 1) -MAX_MATCH_8_ equ ((MAX_MATCH + 7) AND 0FFF0h) - - -;;; stack frame offsets - -chainlenwmask equ esp + 0 ; high word: current chain len - ; low word: s->wmask -window equ esp + 4 ; local copy of s->window -windowbestlen equ esp + 8 ; s->window + bestlen -scanstart equ esp + 16 ; first two bytes of string -scanend equ esp + 12 ; last two bytes of string -scanalign equ esp + 20 ; dword-misalignment of string -nicematch equ esp + 24 ; a good enough match size -bestlen equ esp + 28 ; size of best match so far -scan equ esp + 32 ; ptr to string wanting match - -LocalVarsSize equ 36 -; saved ebx byte esp + 36 -; saved edi byte esp + 40 -; saved esi byte esp + 44 -; saved ebp byte esp + 48 -; return address byte esp + 52 -deflatestate equ esp + 56 ; the function arguments -curmatch equ esp + 60 - -;;; Offsets for fields in the deflate_state structure. These numbers -;;; are calculated from the definition of deflate_state, with the -;;; assumption that the compiler will dword-align the fields. (Thus, -;;; changing the definition of deflate_state could easily cause this -;;; program to crash horribly, without so much as a warning at -;;; compile time. Sigh.) - -dsWSize equ 36+zlib1222add -dsWMask equ 44+zlib1222add -dsWindow equ 48+zlib1222add -dsPrev equ 56+zlib1222add -dsMatchLen equ 88+zlib1222add -dsPrevMatch equ 92+zlib1222add -dsStrStart equ 100+zlib1222add -dsMatchStart equ 104+zlib1222add -dsLookahead equ 108+zlib1222add -dsPrevLen equ 112+zlib1222add -dsMaxChainLen equ 116+zlib1222add -dsGoodMatch equ 132+zlib1222add -dsNiceMatch equ 136+zlib1222add - - -;;; match686.asm -- Pentium-Pro-optimized version of longest_match() -;;; Written for zlib 1.1.2 -;;; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com> -;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html -;;; -;; -;; 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. -;; - -;GLOBAL _longest_match, _match_init - - -;SECTION .text - -;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch) - -;_longest_match: - IFDEF NOUNDERLINE - longest_match proc near - ELSE - _longest_match proc near - ENDIF -.FPO (9, 4, 0, 0, 1, 0) - -;;; Save registers that the compiler may be using, and adjust esp to -;;; make room for our stack frame. - - push ebp - push edi - push esi - push ebx - sub esp, LocalVarsSize - -;;; Retrieve the function arguments. ecx will hold cur_match -;;; throughout the entire function. edx will hold the pointer to the -;;; deflate_state structure during the function's setup (before -;;; entering the main loop. - - mov edx, [deflatestate] - mov ecx, [curmatch] - -;;; uInt wmask = s->w_mask; -;;; unsigned chain_length = s->max_chain_length; -;;; if (s->prev_length >= s->good_match) { -;;; chain_length >>= 2; -;;; } - - mov eax, [edx + dsPrevLen] - mov ebx, [edx + dsGoodMatch] - cmp eax, ebx - mov eax, [edx + dsWMask] - mov ebx, [edx + dsMaxChainLen] - jl LastMatchGood - shr ebx, 2 -LastMatchGood: - -;;; chainlen is decremented once beforehand so that the function can -;;; use the sign flag instead of the zero flag for the exit test. -;;; It is then shifted into the high word, to make room for the wmask -;;; value, which it will always accompany. - - dec ebx - shl ebx, 16 - or ebx, eax - mov [chainlenwmask], ebx - -;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - - mov eax, [edx + dsNiceMatch] - mov ebx, [edx + dsLookahead] - cmp ebx, eax - jl LookaheadLess - mov ebx, eax -LookaheadLess: mov [nicematch], ebx - -;;; register Bytef *scan = s->window + s->strstart; - - mov esi, [edx + dsWindow] - mov [window], esi - mov ebp, [edx + dsStrStart] - lea edi, [esi + ebp] - mov [scan], edi - -;;; Determine how many bytes the scan ptr is off from being -;;; dword-aligned. - - mov eax, edi - neg eax - and eax, 3 - mov [scanalign], eax - -;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? -;;; s->strstart - (IPos)MAX_DIST(s) : NIL; - - mov eax, [edx + dsWSize] - sub eax, MIN_LOOKAHEAD - sub ebp, eax - jg LimitPositive - xor ebp, ebp -LimitPositive: - -;;; int best_len = s->prev_length; - - mov eax, [edx + dsPrevLen] - mov [bestlen], eax - -;;; Store the sum of s->window + best_len in esi locally, and in esi. - - add esi, eax - mov [windowbestlen], esi - -;;; register ush scan_start = *(ushf*)scan; -;;; register ush scan_end = *(ushf*)(scan+best_len-1); -;;; Posf *prev = s->prev; - - movzx ebx, word ptr [edi] - mov [scanstart], ebx - movzx ebx, word ptr [edi + eax - 1] - mov [scanend], ebx - mov edi, [edx + dsPrev] - -;;; Jump into the main loop. - - mov edx, [chainlenwmask] - jmp short LoopEntry - -align 4 - -;;; do { -;;; match = s->window + cur_match; -;;; if (*(ushf*)(match+best_len-1) != scan_end || -;;; *(ushf*)match != scan_start) continue; -;;; [...] -;;; } while ((cur_match = prev[cur_match & wmask]) > limit -;;; && --chain_length != 0); -;;; -;;; Here is the inner loop of the function. The function will spend the -;;; majority of its time in this loop, and majority of that time will -;;; be spent in the first ten instructions. -;;; -;;; Within this loop: -;;; ebx = scanend -;;; ecx = curmatch -;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) -;;; esi = windowbestlen - i.e., (window + bestlen) -;;; edi = prev -;;; ebp = limit - -LookupLoop: - and ecx, edx - movzx ecx, word ptr [edi + ecx*2] - cmp ecx, ebp - jbe LeaveNow - sub edx, 00010000h - js LeaveNow -LoopEntry: movzx eax, word ptr [esi + ecx - 1] - cmp eax, ebx - jnz LookupLoop - mov eax, [window] - movzx eax, word ptr [eax + ecx] - cmp eax, [scanstart] - jnz LookupLoop - -;;; Store the current value of chainlen. - - mov [chainlenwmask], edx - -;;; Point edi to the string under scrutiny, and esi to the string we -;;; are hoping to match it up with. In actuality, esi and edi are -;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is -;;; initialized to -(MAX_MATCH_8 - scanalign). - - mov esi, [window] - mov edi, [scan] - add esi, ecx - mov eax, [scanalign] - mov edx, 0fffffef8h; -(MAX_MATCH_8) - lea edi, [edi + eax + 0108h] ;MAX_MATCH_8] - lea esi, [esi + eax + 0108h] ;MAX_MATCH_8] - -;;; Test the strings for equality, 8 bytes at a time. At the end, -;;; adjust edx so that it is offset to the exact byte that mismatched. -;;; -;;; We already know at this point that the first three bytes of the -;;; strings match each other, and they can be safely passed over before -;;; starting the compare loop. So what this code does is skip over 0-3 -;;; bytes, as much as necessary in order to dword-align the edi -;;; pointer. (esi will still be misaligned three times out of four.) -;;; -;;; It should be confessed that this loop usually does not represent -;;; much of the total running time. Replacing it with a more -;;; straightforward "rep cmpsb" would not drastically degrade -;;; performance. - -LoopCmps: - mov eax, [esi + edx] - xor eax, [edi + edx] - jnz LeaveLoopCmps - mov eax, [esi + edx + 4] - xor eax, [edi + edx + 4] - jnz LeaveLoopCmps4 - add edx, 8 - jnz LoopCmps - jmp short LenMaximum -LeaveLoopCmps4: add edx, 4 -LeaveLoopCmps: test eax, 0000FFFFh - jnz LenLower - add edx, 2 - shr eax, 16 -LenLower: sub al, 1 - adc edx, 0 - -;;; Calculate the length of the match. If it is longer than MAX_MATCH, -;;; then automatically accept it as the best possible match and leave. - - lea eax, [edi + edx] - mov edi, [scan] - sub eax, edi - cmp eax, MAX_MATCH - jge LenMaximum - -;;; If the length of the match is not longer than the best match we -;;; have so far, then forget it and return to the lookup loop. - - mov edx, [deflatestate] - mov ebx, [bestlen] - cmp eax, ebx - jg LongerMatch - mov esi, [windowbestlen] - mov edi, [edx + dsPrev] - mov ebx, [scanend] - mov edx, [chainlenwmask] - jmp LookupLoop - -;;; s->match_start = cur_match; -;;; best_len = len; -;;; if (len >= nice_match) break; -;;; scan_end = *(ushf*)(scan+best_len-1); - -LongerMatch: mov ebx, [nicematch] - mov [bestlen], eax - mov [edx + dsMatchStart], ecx - cmp eax, ebx - jge LeaveNow - mov esi, [window] - add esi, eax - mov [windowbestlen], esi - movzx ebx, word ptr [edi + eax - 1] - mov edi, [edx + dsPrev] - mov [scanend], ebx - mov edx, [chainlenwmask] - jmp LookupLoop - -;;; Accept the current string, with the maximum possible length. - -LenMaximum: mov edx, [deflatestate] - mov dword ptr [bestlen], MAX_MATCH - mov [edx + dsMatchStart], ecx - -;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; -;;; return s->lookahead; - -LeaveNow: - mov edx, [deflatestate] - mov ebx, [bestlen] - mov eax, [edx + dsLookahead] - cmp ebx, eax - jg LookaheadRet - mov eax, ebx -LookaheadRet: - -;;; Restore the stack and return from whence we came. - - add esp, LocalVarsSize - pop ebx - pop esi - pop edi - pop ebp - - ret -; please don't remove this string ! -; Your can freely use match686 in any free or commercial app if you don't remove the string in the binary! - db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah - - - IFDEF NOUNDERLINE - longest_match endp - ELSE - _longest_match endp - ENDIF - - IFDEF NOUNDERLINE - match_init proc near - ret - match_init endp - ELSE - _match_init proc near - ret - _match_init endp - ENDIF - - -_TEXT ends -end +; match686.asm -- Asm portion of the optimized longest_match for 32 bits x86 +; Copyright (C) 1995-1996 Jean-loup Gailly, Brian Raiter and Gilles Vollant. +; File written by Gilles Vollant, by converting match686.S from Brian Raiter +; for MASM. This is as assembly version of longest_match +; from Jean-loup Gailly in deflate.c +; +; http://www.zlib.net +; http://www.winimage.com/zLibDll +; http://www.muppetlabs.com/~breadbox/software/assembly.html +; +; For Visual C++ 4.x and higher and ML 6.x and higher +; ml.exe is distributed in +; http://www.microsoft.com/downloads/details.aspx?FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64 +; +; this file contain two implementation of longest_match +; +; this longest_match was written by Brian raiter (1998), optimized for Pentium Pro +; (and the faster known version of match_init on modern Core 2 Duo and AMD Phenom) +; +; for using an assembly version of longest_match, you need define ASMV in project +; +; compile the asm file running +; ml /coff /Zi /c /Flmatch686.lst match686.asm +; and do not include match686.obj in your project +; +; note: contrib of zLib 1.2.3 and earlier contained both a deprecated version for +; Pentium (prior Pentium Pro) and this version for Pentium Pro and modern processor +; with autoselect (with cpu detection code) +; if you want support the old pentium optimization, you can still use these version +; +; this file is not optimized for old pentium, but it compatible with all x86 32 bits +; processor (starting 80386) +; +; +; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2 + +;uInt longest_match(s, cur_match) +; deflate_state *s; +; IPos cur_match; /* current match */ + + NbStack equ 76 + cur_match equ dword ptr[esp+NbStack-0] + str_s equ dword ptr[esp+NbStack-4] +; 5 dword on top (ret,ebp,esi,edi,ebx) + adrret equ dword ptr[esp+NbStack-8] + pushebp equ dword ptr[esp+NbStack-12] + pushedi equ dword ptr[esp+NbStack-16] + pushesi equ dword ptr[esp+NbStack-20] + pushebx equ dword ptr[esp+NbStack-24] + + chain_length equ dword ptr [esp+NbStack-28] + limit equ dword ptr [esp+NbStack-32] + best_len equ dword ptr [esp+NbStack-36] + window equ dword ptr [esp+NbStack-40] + prev equ dword ptr [esp+NbStack-44] + scan_start equ word ptr [esp+NbStack-48] + wmask equ dword ptr [esp+NbStack-52] + match_start_ptr equ dword ptr [esp+NbStack-56] + nice_match equ dword ptr [esp+NbStack-60] + scan equ dword ptr [esp+NbStack-64] + + windowlen equ dword ptr [esp+NbStack-68] + match_start equ dword ptr [esp+NbStack-72] + strend equ dword ptr [esp+NbStack-76] + NbStackAdd equ (NbStack-24) + + .386p + + name gvmatch + .MODEL FLAT + + + +; all the +zlib1222add offsets are due to the addition of fields +; in zlib in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). +; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). +; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). + + zlib1222add equ 8 + +; Note : these value are good with a 8 bytes boundary pack structure + dep_chain_length equ 74h+zlib1222add + dep_window equ 30h+zlib1222add + dep_strstart equ 64h+zlib1222add + dep_prev_length equ 70h+zlib1222add + dep_nice_match equ 88h+zlib1222add + dep_w_size equ 24h+zlib1222add + dep_prev equ 38h+zlib1222add + dep_w_mask equ 2ch+zlib1222add + dep_good_match equ 84h+zlib1222add + dep_match_start equ 68h+zlib1222add + dep_lookahead equ 6ch+zlib1222add + + +_TEXT segment + +IFDEF NOUNDERLINE + public longest_match + public match_init +ELSE + public _longest_match + public _match_init +ENDIF + + MAX_MATCH equ 258 + MIN_MATCH equ 3 + MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) + + + +MAX_MATCH equ 258 +MIN_MATCH equ 3 +MIN_LOOKAHEAD equ (MAX_MATCH + MIN_MATCH + 1) +MAX_MATCH_8_ equ ((MAX_MATCH + 7) AND 0FFF0h) + + +;;; stack frame offsets + +chainlenwmask equ esp + 0 ; high word: current chain len + ; low word: s->wmask +window equ esp + 4 ; local copy of s->window +windowbestlen equ esp + 8 ; s->window + bestlen +scanstart equ esp + 16 ; first two bytes of string +scanend equ esp + 12 ; last two bytes of string +scanalign equ esp + 20 ; dword-misalignment of string +nicematch equ esp + 24 ; a good enough match size +bestlen equ esp + 28 ; size of best match so far +scan equ esp + 32 ; ptr to string wanting match + +LocalVarsSize equ 36 +; saved ebx byte esp + 36 +; saved edi byte esp + 40 +; saved esi byte esp + 44 +; saved ebp byte esp + 48 +; return address byte esp + 52 +deflatestate equ esp + 56 ; the function arguments +curmatch equ esp + 60 + +;;; Offsets for fields in the deflate_state structure. These numbers +;;; are calculated from the definition of deflate_state, with the +;;; assumption that the compiler will dword-align the fields. (Thus, +;;; changing the definition of deflate_state could easily cause this +;;; program to crash horribly, without so much as a warning at +;;; compile time. Sigh.) + +dsWSize equ 36+zlib1222add +dsWMask equ 44+zlib1222add +dsWindow equ 48+zlib1222add +dsPrev equ 56+zlib1222add +dsMatchLen equ 88+zlib1222add +dsPrevMatch equ 92+zlib1222add +dsStrStart equ 100+zlib1222add +dsMatchStart equ 104+zlib1222add +dsLookahead equ 108+zlib1222add +dsPrevLen equ 112+zlib1222add +dsMaxChainLen equ 116+zlib1222add +dsGoodMatch equ 132+zlib1222add +dsNiceMatch equ 136+zlib1222add + + +;;; match686.asm -- Pentium-Pro-optimized version of longest_match() +;;; Written for zlib 1.1.2 +;;; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com> +;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html +;;; +;; +;; 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. +;; + +;GLOBAL _longest_match, _match_init + + +;SECTION .text + +;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch) + +;_longest_match: + IFDEF NOUNDERLINE + longest_match proc near + ELSE + _longest_match proc near + ENDIF +.FPO (9, 4, 0, 0, 1, 0) + +;;; Save registers that the compiler may be using, and adjust esp to +;;; make room for our stack frame. + + push ebp + push edi + push esi + push ebx + sub esp, LocalVarsSize + +;;; Retrieve the function arguments. ecx will hold cur_match +;;; throughout the entire function. edx will hold the pointer to the +;;; deflate_state structure during the function's setup (before +;;; entering the main loop. + + mov edx, [deflatestate] + mov ecx, [curmatch] + +;;; uInt wmask = s->w_mask; +;;; unsigned chain_length = s->max_chain_length; +;;; if (s->prev_length >= s->good_match) { +;;; chain_length >>= 2; +;;; } + + mov eax, [edx + dsPrevLen] + mov ebx, [edx + dsGoodMatch] + cmp eax, ebx + mov eax, [edx + dsWMask] + mov ebx, [edx + dsMaxChainLen] + jl LastMatchGood + shr ebx, 2 +LastMatchGood: + +;;; chainlen is decremented once beforehand so that the function can +;;; use the sign flag instead of the zero flag for the exit test. +;;; It is then shifted into the high word, to make room for the wmask +;;; value, which it will always accompany. + + dec ebx + shl ebx, 16 + or ebx, eax + mov [chainlenwmask], ebx + +;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + mov eax, [edx + dsNiceMatch] + mov ebx, [edx + dsLookahead] + cmp ebx, eax + jl LookaheadLess + mov ebx, eax +LookaheadLess: mov [nicematch], ebx + +;;; register Bytef *scan = s->window + s->strstart; + + mov esi, [edx + dsWindow] + mov [window], esi + mov ebp, [edx + dsStrStart] + lea edi, [esi + ebp] + mov [scan], edi + +;;; Determine how many bytes the scan ptr is off from being +;;; dword-aligned. + + mov eax, edi + neg eax + and eax, 3 + mov [scanalign], eax + +;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? +;;; s->strstart - (IPos)MAX_DIST(s) : NIL; + + mov eax, [edx + dsWSize] + sub eax, MIN_LOOKAHEAD + sub ebp, eax + jg LimitPositive + xor ebp, ebp +LimitPositive: + +;;; int best_len = s->prev_length; + + mov eax, [edx + dsPrevLen] + mov [bestlen], eax + +;;; Store the sum of s->window + best_len in esi locally, and in esi. + + add esi, eax + mov [windowbestlen], esi + +;;; register ush scan_start = *(ushf*)scan; +;;; register ush scan_end = *(ushf*)(scan+best_len-1); +;;; Posf *prev = s->prev; + + movzx ebx, word ptr [edi] + mov [scanstart], ebx + movzx ebx, word ptr [edi + eax - 1] + mov [scanend], ebx + mov edi, [edx + dsPrev] + +;;; Jump into the main loop. + + mov edx, [chainlenwmask] + jmp short LoopEntry + +align 4 + +;;; do { +;;; match = s->window + cur_match; +;;; if (*(ushf*)(match+best_len-1) != scan_end || +;;; *(ushf*)match != scan_start) continue; +;;; [...] +;;; } while ((cur_match = prev[cur_match & wmask]) > limit +;;; && --chain_length != 0); +;;; +;;; Here is the inner loop of the function. The function will spend the +;;; majority of its time in this loop, and majority of that time will +;;; be spent in the first ten instructions. +;;; +;;; Within this loop: +;;; ebx = scanend +;;; ecx = curmatch +;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) +;;; esi = windowbestlen - i.e., (window + bestlen) +;;; edi = prev +;;; ebp = limit + +LookupLoop: + and ecx, edx + movzx ecx, word ptr [edi + ecx*2] + cmp ecx, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow +LoopEntry: movzx eax, word ptr [esi + ecx - 1] + cmp eax, ebx + jnz LookupLoop + mov eax, [window] + movzx eax, word ptr [eax + ecx] + cmp eax, [scanstart] + jnz LookupLoop + +;;; Store the current value of chainlen. + + mov [chainlenwmask], edx + +;;; Point edi to the string under scrutiny, and esi to the string we +;;; are hoping to match it up with. In actuality, esi and edi are +;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is +;;; initialized to -(MAX_MATCH_8 - scanalign). + + mov esi, [window] + mov edi, [scan] + add esi, ecx + mov eax, [scanalign] + mov edx, 0fffffef8h; -(MAX_MATCH_8) + lea edi, [edi + eax + 0108h] ;MAX_MATCH_8] + lea esi, [esi + eax + 0108h] ;MAX_MATCH_8] + +;;; Test the strings for equality, 8 bytes at a time. At the end, +;;; adjust edx so that it is offset to the exact byte that mismatched. +;;; +;;; We already know at this point that the first three bytes of the +;;; strings match each other, and they can be safely passed over before +;;; starting the compare loop. So what this code does is skip over 0-3 +;;; bytes, as much as necessary in order to dword-align the edi +;;; pointer. (esi will still be misaligned three times out of four.) +;;; +;;; It should be confessed that this loop usually does not represent +;;; much of the total running time. Replacing it with a more +;;; straightforward "rep cmpsb" would not drastically degrade +;;; performance. + +LoopCmps: + mov eax, [esi + edx] + xor eax, [edi + edx] + jnz LeaveLoopCmps + mov eax, [esi + edx + 4] + xor eax, [edi + edx + 4] + jnz LeaveLoopCmps4 + add edx, 8 + jnz LoopCmps + jmp short LenMaximum +LeaveLoopCmps4: add edx, 4 +LeaveLoopCmps: test eax, 0000FFFFh + jnz LenLower + add edx, 2 + shr eax, 16 +LenLower: sub al, 1 + adc edx, 0 + +;;; Calculate the length of the match. If it is longer than MAX_MATCH, +;;; then automatically accept it as the best possible match and leave. + + lea eax, [edi + edx] + mov edi, [scan] + sub eax, edi + cmp eax, MAX_MATCH + jge LenMaximum + +;;; If the length of the match is not longer than the best match we +;;; have so far, then forget it and return to the lookup loop. + + mov edx, [deflatestate] + mov ebx, [bestlen] + cmp eax, ebx + jg LongerMatch + mov esi, [windowbestlen] + mov edi, [edx + dsPrev] + mov ebx, [scanend] + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; s->match_start = cur_match; +;;; best_len = len; +;;; if (len >= nice_match) break; +;;; scan_end = *(ushf*)(scan+best_len-1); + +LongerMatch: mov ebx, [nicematch] + mov [bestlen], eax + mov [edx + dsMatchStart], ecx + cmp eax, ebx + jge LeaveNow + mov esi, [window] + add esi, eax + mov [windowbestlen], esi + movzx ebx, word ptr [edi + eax - 1] + mov edi, [edx + dsPrev] + mov [scanend], ebx + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; Accept the current string, with the maximum possible length. + +LenMaximum: mov edx, [deflatestate] + mov dword ptr [bestlen], MAX_MATCH + mov [edx + dsMatchStart], ecx + +;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; +;;; return s->lookahead; + +LeaveNow: + mov edx, [deflatestate] + mov ebx, [bestlen] + mov eax, [edx + dsLookahead] + cmp ebx, eax + jg LookaheadRet + mov eax, ebx +LookaheadRet: + +;;; Restore the stack and return from whence we came. + + add esp, LocalVarsSize + pop ebx + pop esi + pop edi + pop ebp + + ret +; please don't remove this string ! +; Your can freely use match686 in any free or commercial app if you don't remove the string in the binary! + db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah + + + IFDEF NOUNDERLINE + longest_match endp + ELSE + _longest_match endp + ENDIF + + IFDEF NOUNDERLINE + match_init proc near + ret + match_init endp + ELSE + _match_init proc near + ret + _match_init endp + ENDIF + + +_TEXT ends +end diff --git a/Version.cs b/Version.cs index a137335d..e83f59ff 100644 --- a/Version.cs +++ b/Version.cs @@ -1,11 +1,11 @@ -namespace Rainmeter -{ - public class Version - { -#if X64 - public const string Informational = "3.2.0.2302 (64-bit)"; -#else - public const string Informational = "3.2.0.2302 (32-bit)"; -#endif - } -} +namespace Rainmeter +{ + public class Version + { +#if X64 + public const string Informational = "3.2.0.2302 (64-bit)"; +#else + public const string Informational = "3.2.0.2302 (32-bit)"; +#endif + } +} diff --git a/Version.h b/Version.h index 6ada6d1f..08a35157 100644 --- a/Version.h +++ b/Version.h @@ -1,9 +1,9 @@ -#pragma once -#define FILEVER 3,2,0,2302 -#define PRODUCTVER FILEVER -#define STRFILEVER "3.2.0.2302" -#define STRPRODUCTVER STRFILEVER -#define APPVERSION L"3.2.0" -#define RAINMETER_VERSION ((3 * 1000000) + (2 * 1000) + 0) -const int revision_number = 2302; -const bool revision_beta = true; +#pragma once +#define FILEVER 3,2,0,2302 +#define PRODUCTVER FILEVER +#define STRFILEVER "3.2.0.2302" +#define STRPRODUCTVER STRFILEVER +#define APPVERSION L"3.2.0" +#define RAINMETER_VERSION ((3 * 1000000) + (2 * 1000) + 0) +const int revision_number = 2302; +const bool revision_beta = true; diff --git a/packages/AvalonDock.2.0.2000/AvalonDock.2.0.2000.nupkg b/packages/AvalonDock.2.0.2000/AvalonDock.2.0.2000.nupkg deleted file mode 100644 index 0b3d5101ad6e7a95c9c210d79de9a7371b882120..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 588883 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 pq`@HJj%7D-I>ySj*>knJA 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%0AF?IHr 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 diff --git a/packages/AvalonDock.2.0.2000/AvalonDock.2.0.2000.nuspec b/packages/AvalonDock.2.0.2000/AvalonDock.2.0.2000.nuspec deleted file mode 100644 index 89e0af8f..00000000 --- a/packages/AvalonDock.2.0.2000/AvalonDock.2.0.2000.nuspec +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0"?> -<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> - <metadata> - <id>AvalonDock</id> - <version>2.0.2000</version> - <title>AvalonDock - Xceed Software Inc. - Xceed Software Inc. - http://avalondock.codeplex.com/license - http://avalondock.codeplex.com/ - false - AvalonDock is a docking windows control for WPF that lets you create customizable layouts using a full featured window docking system similar to what is found in many popular integrated development environements (IDEs) such as Visual Studio. It includes themes and samples to get you started. - Powerful and free WPF docking windows control. - v2.0.2000 is a bug-fix release - Copyright (c) 2007-2013 Xceed Software Inc. - en-US - WPF Docking - - \ No newline at end of file diff --git a/packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.Aero.dll b/packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.Aero.dll deleted file mode 100644 index 18ebf3724fb685e0159a8610102591937f007a13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88576 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

    *JATmm~FaRJF*&d?KDi2bPX0>0rfn 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 diff --git a/packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.Aero.pdb b/packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.Aero.pdb deleted file mode 100644 index 11d1792d36ed5d884c4e807fe7a6aadfcb8a55b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24064 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 diff --git a/packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.Metro.dll b/packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.Metro.dll deleted file mode 100644 index 4e391d41e3cfb250ba3da23cb3575aebd7cc642a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82432 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 QN&-p(N&-p(wIzXn0o1mOZU6uP diff --git a/packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.VS2010.dll b/packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.VS2010.dll deleted file mode 100644 index 71a35f5850d5924db91221d5fc68437bb214fe77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86528 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 H)>z;tk$(M} diff --git a/packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.VS2010.pdb b/packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.Themes.VS2010.pdb deleted file mode 100644 index bcb0c5010a694e3a7a0b187b3a8be5f8ccf49150..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13824 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�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

    {e

    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%0A-Jz;V`Ma3oayPvWYhY{ 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 diff --git a/packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.pdb b/packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.pdb deleted file mode 100644 index 483c6a1dcf997374fbaa816e3faf5842d672bfc1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1013248 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 z
      2uH0Ei3;B~EL9Q#^E(g*z;2SIp$ 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 HRtx+W5yh|z diff --git a/packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.xml b/packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.xml deleted file mode 100644 index abf092f2..00000000 --- a/packages/AvalonDock.2.0.2000/lib/net40/Xceed.Wpf.AvalonDock.xml +++ /dev/null @@ -1,4044 +0,0 @@ - - - - Xceed.Wpf.AvalonDock - - - - - Provides derived classes an opportunity to handle execute code before to the Parent property changes. - - - - - Provides derived classes an opportunity to handle changes to the Parent property. - - - - - Removes any empty container not directly referenced by other layout items - - - - - BackgroundWhileDragging Dependency Property - - - - - OpacityWhileDragging Dependency Property - - - - - Gets or sets the BackgroundWhileDragging property. This dependency property - indicates .... - - - - - Gets or sets the OpacityWhileDragging property. This dependency property - indicates .... - - - - - A static class for retail validated assertions. - Instead of breaking into the debugger an exception is thrown. - - - - - Ensure that the current thread's apartment state is what's expected. - - - The required apartment state for the current thread. - - - The message string for the exception to be thrown if the state is invalid. - - - Thrown if the calling thread's apartment state is not the same as the requiredState. - - - - - Ensure that an argument is neither null nor empty. - - The string to validate. - The name of the parameter that will be presented if an exception is thrown. - - - - Ensure that an argument is neither null nor does it consist only of whitespace. - - The string to validate. - The name of the parameter that will be presented if an exception is thrown. - - - Verifies that an argument is not null. - Type of the object to validate. Must be a class. - The object to validate. - The name of the parameter that will be presented if an exception is thrown. - - - Verifies that an argument is not null. - Type of the object to validate. Must be a class. - The object to validate. - The name of the parameter that will be presented if an exception is thrown. - - - Verifies that an argument is null. - Type of the object to validate. Must be a class. - The object to validate. - The name of the parameter that will be presented if an exception is thrown. - - - - Verifies the specified statement is true. Throws an ArgumentException if it's not. - - The statement to be verified as true. - Name of the parameter to include in the ArgumentException. - - - - Verifies the specified statement is true. Throws an ArgumentException if it's not. - - The statement to be verified as true. - Name of the parameter to include in the ArgumentException. - The message to include in the ArgumentException. - - - - Verifies that the specified value is within the expected range. The assertion fails if it isn't. - - The lower bound inclusive value. - The value to verify. - The upper bound exclusive value. - - - The native RGB macro. - - - - - Convert a native integer that represent a color with an alpha channel into a Color struct. - The integer that represents the color. Its bits are of the format 0xAARRGGBB. - A Color representation of the parameter. - - - From a list of BitmapFrames find the one that best matches the requested dimensions. - The methods used here are copied from Win32 sources. We want to be consistent with - system behaviors. - - - - Simple guard against the exceptions that File.Delete throws on null and empty strings. - - The path to delete. Unlike File.Delete, this can be null or empty. - - Note that File.Delete, and by extension SafeDeleteFile, does not throw an exception - if the file does not exist. - - - - GDI's DeleteObject - - - GDI+'s DisposeImage - - - - - Utility to help classes catenate their properties for implementing ToString(). - - The StringBuilder to catenate the results into. - The name of the property to be catenated. - The value of the property to be catenated. - - - - Generates ToString functionality for a struct. This is an expensive way to do it, - it exists for the sake of debugging while classes are in flux. - Eventually this should just be removed and the classes should - do this without reflection. - - - - - - - - Encodes a URL string. Duplicated functionality from System.Web.HttpUtility.UrlEncode. - - - - - Duplicated from System.Web.HttpUtility because System.Web isn't part of the client profile. - URL Encoding replaces ' ' with '+' and unsafe ASCII characters with '%XX'. - Safe characters are defined in RFC2396 (http://www.ietf.org/rfc/rfc2396.txt). - They are the 7-bit ASCII alphanumerics and the mark characters "-_.!~*'()". - This implementation does not treat '~' as a safe character to be consistent with the System.Web version. - - - - - Is this using WPF4? - - - There are a few specific bugs in Window in 3.5SP1 and below that require workarounds - when handling WM_NCCALCSIZE on the HWND. - - - - - Documents Read-Only Dependency Property - - - - - Provides a secure method for setting the Documents property. - This dependency property indicates the list of documents. - - The new value for the property. - - - - Anchorables Read-Only Dependency Property - - - - - Provides a secure method for setting the Anchorables property. - This dependency property indicates the list of anchorables. - - The new value for the property. - - - - SelectedDocument Dependency Property - - - - - Handles changes to the SelectedDocument property. - - - - - Provides derived classes an opportunity to handle changes to the SelectedDocument property. - - - - - SelectedAnchorable Dependency Property - - - - - Handles changes to the SelectedAnchorable property. - - - - - Provides derived classes an opportunity to handle changes to the SelectedAnchorable property. - - - - - Gets the Documents property. This dependency property - indicates the list of documents. - - - - - Gets the Anchorables property. This dependency property - indicates the list of anchorables. - - - - - Gets or sets the SelectedDocument property. This dependency property - indicates the selected document. - - - - - Gets or sets the SelectedAnchorable property. This dependency property - indicates the selected anchorable. - - - - - IsDragging Read-Only Dependency Property - - - - - Provides a secure method for setting the IsDragging property. - This dependency property indicates that this floating window is being dragged. - - The new value for the property. - - - - Handles changes to the IsDragging property. - - - - - Provides derived classes an opportunity to handle changes to the IsDragging property. - - - - - IsMaximized Read-Only Dependency Property - - - - - Provides a secure method for setting the IsMaximized property. - This dependency property indicates if the window is maximized. - - The new value for the property. - - - - Gets the IsDragging property. This dependency property - indicates that this floating window is being dragged. - - - - - Gets the IsMaximized property. This dependency property - indicates if the window is maximized. - - - - - Content Dependency Property - - - - - Handles changes to the Content property. - - - - - Provides derived classes an opportunity to handle changes to the Content property. - - - - - Gets or sets the Content property. This dependency property - indicates .... - - - - - Model Dependency Property - - - - - Handles changes to the Model property. - - - - - Provides derived classes an opportunity to handle changes to the Model property. - - - - - LayoutItem Read-Only Dependency Property - - - - - Provides a secure method for setting the LayoutItem property. - This dependency property indicates the LayoutItem attached to this tag item. - - The new value for the property. - - - - Gets or sets the Model property. This dependency property - indicates model attached to the anchorable tab item. - - - - - Gets the LayoutItem property. This dependency property - indicates the LayoutItem attached to this tag item. - - - - A static class for verifying assumptions. - - - - Executes the specified argument. - - The function to execute. - - - Obsolete: Use Standard.Assert.AreEqual instead of Assert.Equals - The generic type to compare for equality. - The first generic type data to compare. This is is the expected value. - The second generic type data to compare. This is the actual value. - - - - Verifies that two generic type data are equal. The assertion fails if they are not. - - The generic type to compare for equality. - The first generic type data to compare. This is is the expected value. - The second generic type data to compare. This is the actual value. - This breaks into the debugger in the case of a failed assertion. - - - - Verifies that two generic type data are not equal. The assertion fails if they are. - - The generic type to compare for inequality. - The first generic type data to compare. This is is the value that's not expected. - The second generic type data to compare. This is the actual value. - This breaks into the debugger in the case of a failed assertion. - - - - Verifies that if the specified condition is true, then so is the result. - The assertion fails if the condition is true but the result is false. - - if set to true [condition]. - - A second Boolean statement. If the first was true then so must this be. - If the first statement was false then the value of this is ignored. - - This breaks into the debugger in the case of a failed assertion. - - - - Lazy evaluation overload. Verifies that if a condition is true, then so is a secondary value. - - The conditional value. - A function to be evaluated for truth if the condition argument is true. - - This overload only evaluates the result if the first condition is true. - - - - - Verifies that a string has content. I.e. it is not null and it is not empty. - - The string to verify. - - - - Verifies that a string has content. I.e. it is not null and it is not purely whitespace. - - The string to verify. - - - - Verifies the specified value is not null. The assertion fails if it is. - - The generic reference type. - The value to check for nullness. - This breaks into the debugger in the case of a failed assertion. - - - - Verifies that the specified condition is false. The assertion fails if it is true. - - The expression that should be false. - This breaks into the debugger in the case of a failed assertion. - - - - Verifies that the specified condition is false. The assertion fails if it is true. - - The expression that should be false. - The message to display if the condition is true. - This breaks into the debugger in the case of a failed assertion. - - - - Verifies that the specified condition is true. The assertion fails if it is not. - - A condition that is expected to be true. - This breaks into the debugger in the case of a failed assertion. - - - - Verifies that the specified condition is true. The assertion fails if it is not. - - A condition that is expected to be true. - The message to write in case the condition is false. - This breaks into the debugger in the case of a failed assertion. - - - - This line should never be executed. The assertion always fails. - - This breaks into the debugger in the case of a failed assertion. - - - - This line should never be executed. The assertion always fails. - - The message to display if this function is executed. - This breaks into the debugger in the case of a failed assertion. - - - - Verifies that the specified object is null. The assertion fails if it is not. - - The item to verify is null. - - - - Verifies that the specified value is within the expected range. The assertion fails if it isn't. - - The lower bound inclusive value. - The value to verify. - The upper bound inclusive value. - - - - Verifies that the specified value is within the expected range. The assertion fails if it isn't. - - The lower bound inclusive value. - The value to verify. - The upper bound exclusive value. - - - - Verify the current thread's apartment state is what's expected. The assertion fails if it isn't - - - The expected apartment state for the current thread. - - This breaks into the debugger in the case of a failed assertion. - - - A function signature for Assert.Evaluate. - - - A function signature for Assert.Implies. - Returns the truth of a predicate. - - - - Get the input element that was focused before user left the layout element - - Element to look for - Input element - - - - Get the last window handle focused before user left the element passed as argument - - - - - - - Given a layout element tries to set the focus of the keyword where it was before user moved to another element - - - - - - Provides derived classes an opportunity to handle changes to the IsSelected property. - - - - - Provides derived classes an opportunity to handle changes to the IsActive property. - - - - - Test if the content can be closed - - - - - - Close the content - - Please note that usually the anchorable is only hidden (not closed). By default when user click the X button it only hides the content. - - - - Float the content in a popup window - - - - - Dock the content as document - - - - - Re-dock the content to its previous container - - - - - Event fired when the content is closed (i.e. removed definitely from the layout) - - - - - Event fired when the content is about to be closed (i.e. removed definitely from the layout) - - Please note that LayoutAnchorable also can be hidden. Usually user hide anchorables when click the 'X' button. To completely close - an anchorable the user should click the 'Close' menu item from the context menu. When an LayoutAnchorable is hidden its visibility changes to false and - IsHidden property is set to true. - Hanlde the Hiding event for the LayoutAnchorable to cancel the hide operation. - - - - Background Dependency Property - - - - - AnchorableStyle Dependency Property - - - - - Gets or sets the Background property. This dependency property - indicates background of the autohide childwindow. - - - - - Gets or sets the AnchorableStyle property. This dependency property - indicates the style to apply to the LayoutAnchorableControl hosted in this auto hide window. - - - - - SingleContentLayoutItem Dependency Property - - - - - Handles changes to the SingleContentLayoutItem property. - - - - - Provides derived classes an opportunity to handle changes to the SingleContentLayoutItem property. - - - - - Gets or sets the SingleContentLayoutItem property. This dependency property - indicates the layout item of the selected content when is shown a single anchorable pane. - - - - ShellItem attribute flags. SIATTRIBFLAGS_* - - - - Flags for SetTabProperties. STPF_* - - The native enum was called STPFLAG. - - - - Flags for Setting Taskbar Progress state. TBPF_* - - - The native enum was called TBPFLAG. - - - - - THUMBBUTTON mask. THB_* - - - - - THUMBBUTTON flags. THBF_* - - - - - GetPropertyStoreFlags. GPS_*. - - - These are new for Vista, but are used in downlevel components - - - - - KNOWNDESTCATEGORY. KDC_* - - - - Objects can be copied - DROPEFFECT_COPY - - - Objects can be moved - DROPEFFECT_MOVE - - - Objects can be linked - - DROPEFFECT_LINK. - - If this bit is set on an item in the shell folder, a - 'Create Shortcut' menu item will be added to the File - menu and context menus for the item. If the user selects - that command, your IContextMenu::InvokeCommand() will be called - with 'link'. - That flag will also be used to determine if 'Create Shortcut' - should be added when the item in your folder is dragged to another - folder. - - - - supports BindToObject(IID_IStorage) - - - Objects can be renamed - - - Objects can be deleted - - - Objects have property sheets - - - Objects are drop target - - - Object is encrypted (use alt color) - - - 'Slow' object - - - Ghosted icon - - - Shortcut (link) - - - Shared - - - Read-only - - - Hidden object - - - May contain children with SFGAO_FILESYSTEM - - - Support BindToObject(IID_IShellFolder) - - - Is a win32 file system object (file/folder/root) - - - May contain children with SFGAO_FOLDER (may be slow) - - - Invalidate cached information (may be slow) - - - Is this removeable media? - - - Object is compressed (use alt color) - - - Supports IShellFolder, but only implements CreateViewObject() (non-folder view) - - - Is a non-enumerated object (should be hidden) - - - Should show bold in explorer tree - - - Obsolete - - - Obsolete - - - Supports BindToObject(IID_IStream) - - - May contain children with SFGAO_STORAGE or SFGAO_STREAM - - - For determining storage capabilities, ie for open/save semantics - - - - Attributes that are masked out for PKEY_SFGAOFlags because they are considered - to cause slow calculations or lack context - (SFGAO_VALIDATE | SFGAO_ISSLOW | SFGAO_HASSUBFOLDER and others) - - - - - IShellFolder::EnumObjects grfFlags bits. Also called SHCONT - - - - - IShellFolder::GetDisplayNameOf/SetNameOf uFlags. Also called SHGDNF. - - - For compatibility with SIGDN, these bits must all sit in the LOW word. - - - - - SHELLITEMCOMPAREHINTF. SICHINT_*. - - - - iOrder based on display in a folder view - - - exact instance compare - - - iOrder based on canonical name (better performance) - - - - ShellItem enum. SIGDN_*. - - - - - STR_GPS_* - - - When requesting a property store through IShellFolder, you can specify the equivalent of - GPS_DEFAULT by passing in a null IBindCtx parameter. - - You can specify the equivalent of GPS_READWRITE by passing a mode of STGM_READWRITE | STGM_EXCLUSIVE - in the bind context - - Here are the string versions of GPS_ flags, passed to IShellFolder::BindToObject() via IBindCtx::RegisterObjectParam() - These flags are valid when requesting an IPropertySetStorage or IPropertyStore handler - - The meaning of these flags are described above. - - There is no STR_ equivalent for GPS_TEMPORARY because temporary property stores - are provided by IShellItem2 only -- not by the underlying IShellFolder. - - - - - WPARAM value for a THUMBBUTTON being clicked. - - - - fmtid - - - pid - - - PKEY_Title - - - PKEY_AppUserModel_ID - - - PKEY_AppUserModel_IsDestListSeparator - - - PKEY_AppUserModel_RelaunchCommand - - - PKEY_AppUserModel_RelaunchDisplayNameResource - - - PKEY_AppUserModel_RelaunchIconResource - - - Unknown Object Array - - - - Shell Namespace helper - - - - - Shell Namespace helper 2 - - - - - This function must be called first to validate use of other members. - - - - - This function adds a tab for hwnd to the taskbar. - - The HWND for which to add the tab. - - - - This function deletes a tab for hwnd from the taskbar. - - The HWND for which the tab is to be deleted. - - - - This function activates the tab associated with hwnd on the taskbar. - - The HWND for which the tab is to be actuvated. - - - - This function marks hwnd in the taskbar as the active tab. - - The HWND to activate. - - - - Marks a window as full-screen. - - The handle of the window to be marked. - A Boolean value marking the desired full-screen status of the window. - - Setting the value of fFullscreen to true, the Shell treats this window as a full-screen window, and the taskbar - is moved to the bottom of the z-order when this window is active. Setting the value of fFullscreen to false - removes the full-screen marking, but does not cause the Shell to treat the window as though it were - definitely not full-screen. With a false fFullscreen value, the Shell depends on its automatic detection facility - to specify how the window should be treated, possibly still flagging the window as full-screen. - - - - - Allows an application to retrieve the most recent and frequent documents opened in that app, as reported via SHAddToRecentDocs - - - - - Set the App User Model ID for the application retrieving this list. If an AppID is not provided via this method, - the system will use a heuristically determined ID. This method must be called before GetList. - - App Id. - - - - Retrieve an IEnumObjects or IObjectArray for IShellItems and/or IShellLinks. - Items may appear in both the frequent and recent lists. - - - - - - - Provides access to the App User Model ID on objects supporting this value. - - - - - Provides access to the ProgID associated with an object - - - - - Title Dependency Property - - - - - Handles changes to the Title property. - - - - - Provides derived classes an opportunity to handle changes to the Title property. - - - - - IconSource Dependency Property - - - - - Handles changes to the IconSource property. - - - - - Provides derived classes an opportunity to handle changes to the IconSource property. - - - - - ContentId Dependency Property - - - - - Handles changes to the ContentId property. - - - - - Provides derived classes an opportunity to handle changes to the ContentId property. - - - - - IsSelected Dependency Property - - - - - Handles changes to the IsSelected property. - - - - - Provides derived classes an opportunity to handle changes to the IsSelected property. - - - - - IsActive Dependency Property - - - - - Handles changes to the IsActive property. - - - - - Provides derived classes an opportunity to handle changes to the IsActive property. - - - - - CanClose Dependency Property - - - - - Handles changes to the CanClose property. - - - - - Provides derived classes an opportunity to handle changes to the CanClose property. - - - - - CanFloat Dependency Property - - - - - Handles changes to the CanFloat property. - - - - - Provides derived classes an opportunity to handle changes to the CanFloat property. - - - - - CloseCommand Dependency Property - - - - - Handles changes to the CloseCommand property. - - - - - Provides derived classes an opportunity to handle changes to the CloseCommand property. - - - - - Coerces the CloseCommand value. - - - - - FloatCommand Dependency Property - - - - - Handles changes to the FloatCommand property. - - - - - Provides derived classes an opportunity to handle changes to the FloatCommand property. - - - - - Coerces the FloatCommand value. - - - - - DockAsDocumentCommand Dependency Property - - - - - Handles changes to the DockAsDocumentCommand property. - - - - - Provides derived classes an opportunity to handle changes to the DockAsDocumentCommand property. - - - - - Coerces the DockAsDocumentCommand value. - - - - - CloseAllButThisCommand Dependency Property - - - - - Handles changes to the CloseAllButThisCommand property. - - - - - Provides derived classes an opportunity to handle changes to the CloseAllButThisCommand property. - - - - - Coerces the CloseAllButThisCommand value. - - - - - ActivateCommand Dependency Property - - - - - Handles changes to the ActivateCommand property. - - - - - Provides derived classes an opportunity to handle changes to the ActivateCommand property. - - - - - Coerces the ActivateCommand value. - - - - - NewVerticalTabGroupCommand Dependency Property - - - - - Handles changes to the NewVerticalTabGroupCommand property. - - - - - Provides derived classes an opportunity to handle changes to the NewVerticalTabGroupCommand property. - - - - - NewHorizontalTabGroupCommand Dependency Property - - - - - Handles changes to the NewHorizontalTabGroupCommand property. - - - - - Provides derived classes an opportunity to handle changes to the NewHorizontalTabGroupCommand property. - - - - - MoveToNextTabGroupCommand Dependency Property - - - - - Handles changes to the MoveToNextTabGroupCommand property. - - - - - Provides derived classes an opportunity to handle changes to the MoveToNextTabGroupCommand property. - - - - - MoveToPreviousTabGroupCommand Dependency Property - - - - - Handles changes to the MoveToPreviousTabGroupCommand property. - - - - - Provides derived classes an opportunity to handle changes to the MoveToPreviousTabGroupCommand property. - - - - - Gets or sets the Title property. This dependency property - indicates the title of the element. - - - - - Gets or sets the IconSource property. This dependency property - indicates icon associated with the item. - - - - - Gets or sets the ContentId property. This dependency property - indicates the content id used to retrive content when deserializing layouts. - - - - - Gets or sets the IsSelected property. This dependency property - indicates if the item is selected inside its container. - - - - - Gets or sets the IsActive property. This dependency property - indicates if the item is active in the UI. - - - - - Gets or sets the CanClose property. This dependency property - indicates if the item can be closed. - - - - - Gets or sets the CanFloat property. This dependency property - indicates if user can move the layout element dragging it to another position. - - - - - Gets or sets the CloseCommand property. This dependency property - indicates the command to execute when user click the document close button. - - - - - Gets or sets the FloatCommand property. This dependency property - indicates the command to execute when user click the float button. - - By default this command move the anchorable inside new floating window. - - - - Gets or sets the DockAsDocumentCommand property. This dependency property - indicates the command to execute when user click the DockAsDocument button. - - By default this command move the anchorable inside the last focused document pane. - - - - Gets or sets the CloseAllButThisCommand property. This dependency property - indicates the 'Close All But This' command. - - - - - Gets or sets the ActivateCommand property. This dependency property - indicates the command to execute when user wants to activate a content (either a Document or an Anchorable). - - - - - Gets or sets the NewVerticalTabGroupCommand property. This dependency property - indicates the new vertical tab group command. - - - - - Gets or sets the NewHorizontalTabGroupCommand property. This dependency property - indicates the new horizontal tab group command. - - - - - Gets or sets the MoveToNextTabGroupCommand property. This dependency property - indicates move to next tab group command. - - - - - Gets or sets the MoveToPreviousTabGroupCommand property. This dependency property - indicates move to rpevious tab group command. - - - - - Side Read-Only Dependency Property - - - - - Provides a secure method for setting the Side property. - This dependency property indicates the anchor side of the control. - - The new value for the property. - - - - Gets the Side property. This dependency property - indicates the anchor side of the control. - - - - The extent of the top of the window to treat as the caption. - - - - Gets or sets the ShowSystemMenu property. This dependency property - indicates if the system menu should be shown at right click on the caption. - - - - - Convert a point in device independent pixels (1/96") to a point in the system coordinates. - - A point in the logical coordinate system. - Returns the parameter converted to the system's coordinates. - - - - Convert a point in system coordinates to a point in device independent pixels (1/96"). - - A point in the physical coordinate system. - Returns the parameter converted to the device independent coordinate system. - - - The Window that's chrome is being modified. - - - Underlying HWND for the _window. - - - Object that describes the current modifications being made to the chrome. - - - Add and remove a native WindowStyle from the HWND. - The styles to be removed. These can be bitwise combined. - The styles to be added. These can be bitwise combined. - Whether the styles of the HWND were modified as a result of this call. - - - - Get the WindowState as the native HWND knows it to be. This isn't necessarily the same as what Window thinks. - - - - - Get the bounding rectangle for the window in physical coordinates. - - The bounding rectangle for the window. - - - - Update the items in the system menu based on the current, or assumed, WindowState. - - - The state to assume that the Window is in. This can be null to query the Window's state. - - - We want to update the menu while we have some control over whether the caption will be repainted. - - - - - Matrix of the HT values to return when responding to NC window messages. - - - - IID_IEnumIDList - - - IID_IEnumObjects - - - IID_IHTMLDocument2 - - - IID_IModalWindow - - - IID_IObjectArray - - - IID_IObjectCollection - - - IID_IPropertyNotifySink - - - IID_IPropertyStore - - - IID_IServiceProvider - - - IID_IShellFolder - - - IID_IShellLink - - - IID_IShellItem - - - IID_IShellItem2 - - - IID_IShellItemArray - - - IID_ITaskbarList - - - IID_ITaskbarList2 - - - IID_IUnknown - - - IID_IApplicationDestinations - - - IID_IApplicationDocumentLists - - - IID_ICustomDestinationList - - - IID_IObjectWithAppUserModelID - - - IID_IObjectWithProgID - - - IID_ITaskbarList3 - - - IID_ITaskbarList4 - - - CLSID_TaskbarList - IID_ITaskbarList - - - CLSID_EnumerableObjectCollection - IID_IEnumObjects. - - - CLSID_ShellLink - IID_IShellLink - - - CLSID_DestinationList - IID_ICustomDestinationList - - - CLSID_ApplicationDestinations - IID_IApplicationDestinations - - - CLSID_ApplicationDocumentLists - IID_IApplicationDocumentLists - - - - IsDraggingOver Attached Dependency Property - - - - - Gets the IsDraggingOver property. This dependency property - indicates if user is dragging a window over the target element. - - - - - Sets the IsDraggingOver property. This dependency property - indicates if user is dragging away a window from the target element. - - - - - DropDownContextMenu Dependency Property - - - - - DropDownContextMenuDataContext Dependency Property - - - - - Gets or sets the DropDownContextMenu property. This dependency property - indicates context menu to show when a right click is detected over the area occpied by the control. - - - - - Gets or sets the DropDownContextMenuDataContext property. This dependency property - indicates data context to attach when context menu is shown. - - - - - DropDownContextMenu Dependency Property - - - - - Handles changes to the DropDownContextMenu property. - - - - - Provides derived classes an opportunity to handle changes to the DropDownContextMenu property. - - - - - DropDownContextMenuDataContext Dependency Property - - - - - Gets or sets the DropDownContextMenu property. This dependency property - indicates drop down menu to show up when user click on an anchorable menu pin. - - - - - Gets or sets the DropDownContextMenuDataContext property. This dependency property - indicates data context to set for drop down context menu. - - - - - Model Dependency Property - - - - - Handles changes to the Model property. - - - - - Provides derived classes an opportunity to handle changes to the Model property. - - - - - LayoutItem Read-Only Dependency Property - - - - - Provides a secure method for setting the LayoutItem property. - This dependency property indicates the LayoutItem attached to this tag item. - - The new value for the property. - - - - Gets or sets the Model property. This dependency property - indicates the model attached to this view. - - - - - Gets the LayoutItem property. This dependency property - indicates the LayoutItem attached to this tag item. - - - - Display the system menu at a specified location. - The location to display the system menu, in logical screen coordinates. - - - - Private constructor. The public way to access this class is through the static Current property. - - - - - Hide this contents - - Add this content to collection of parent root. - - - - Show the content - - Try to show the content where it was previously hidden. - - - - Add the anchorable to a DockingManager layout - - - - - - - Get a value indicating if the anchorable is anchored to a border in an autohide status - - - - - Layout Dependency Property - - - - - Handles changes to the Layout property. - - - - - Provides derived classes an opportunity to handle changes to the property. - - - - - Coerces the value. - - - - - LayoutUpdateStrategy Dependency Property - - - - - DocumentPaneTemplate Dependency Property - - - - - Handles changes to the DocumentPaneTemplate property. - - - - - Provides derived classes an opportunity to handle changes to the DocumentPaneTemplate property. - - - - - AnchorablePaneTemplate Dependency Property - - - - - Handles changes to the AnchorablePaneDataTemplate property. - - - - - Provides derived classes an opportunity to handle changes to the AnchorablePaneDataTemplate property. - - - - - AnchorSideTemplate Dependency Property - - - - - AnchorGroupTemplate Dependency Property - - - - - AnchorTemplate Dependency Property - - - - - DocumentPaneControlStyle Dependency Property - - - - - Handles changes to the DocumentPaneControlStyle property. - - - - - Provides derived classes an opportunity to handle changes to the DocumentPaneControlStyle property. - - - - - AnchorablePaneControlStyle Dependency Property - - - - - Handles changes to the AnchorablePaneControlStyle property. - - - - - Provides derived classes an opportunity to handle changes to the AnchorablePaneControlStyle property. - - - - - DocumentHeaderTemplate Dependency Property - - - - - Handles changes to the DocumentHeaderTemplate property. - - - - - Provides derived classes an opportunity to handle changes to the DocumentHeaderTemplate property. - - - - - Coerces the DocumentHeaderTemplate value. - - - - - DocumentHeaderTemplateSelector Dependency Property - - - - - Handles changes to the DocumentHeaderTemplateSelector property. - - - - - Provides derived classes an opportunity to handle changes to the DocumentHeaderTemplateSelector property. - - - - - Coerces the DocumentHeaderTemplateSelector value. - - - - - DocumentTitleTemplate Dependency Property - - - - - Handles changes to the DocumentTitleTemplate property. - - - - - Provides derived classes an opportunity to handle changes to the DocumentTitleTemplate property. - - - - - Coerces the DocumentTitleTemplate value. - - - - - DocumentTitleTemplateSelector Dependency Property - - - - - Handles changes to the DocumentTitleTemplateSelector property. - - - - - Provides derived classes an opportunity to handle changes to the DocumentTitleTemplateSelector property. - - - - - Coerces the DocumentTitleTemplateSelector value. - - - - - AnchorableTitleTemplate Dependency Property - - - - - Handles changes to the AnchorableTitleTemplate property. - - - - - Provides derived classes an opportunity to handle changes to the AnchorableTitleTemplate property. - - - - - Coerces the AnchorableTitleTemplate value. - - - - - AnchorableTitleTemplateSelector Dependency Property - - - - - Handles changes to the AnchorableTitleTemplateSelector property. - - - - - Provides derived classes an opportunity to handle changes to the AnchorableTitleTemplateSelector property. - - - - - AnchorableHeaderTemplate Dependency Property - - - - - Handles changes to the AnchorableHeaderTemplate property. - - - - - Provides derived classes an opportunity to handle changes to the AnchorableHeaderTemplate property. - - - - - Coerces the AnchorableHeaderTemplate value. - - - - - AnchorableHeaderTemplateSelector Dependency Property - - - - - Handles changes to the AnchorableHeaderTemplateSelector property. - - - - - Provides derived classes an opportunity to handle changes to the AnchorableHeaderTemplateSelector property. - - - - - LayoutRootPanel Dependency Property - - - - - Handles changes to the LayoutRootPanel property. - - - - - Provides derived classes an opportunity to handle changes to the LayoutRootPanel property. - - - - - RightSidePanel Dependency Property - - - - - Handles changes to the RightSidePanel property. - - - - - Provides derived classes an opportunity to handle changes to the RightSidePanel property. - - - - - LeftSidePanel Dependency Property - - - - - Handles changes to the LeftSidePanel property. - - - - - Provides derived classes an opportunity to handle changes to the LeftSidePanel property. - - - - - TopSidePanel Dependency Property - - - - - Handles changes to the TopSidePanel property. - - - - - Provides derived classes an opportunity to handle changes to the TopSidePanel property. - - - - - BottomSidePanel Dependency Property - - - - - Handles changes to the BottomSidePanel property. - - - - - Provides derived classes an opportunity to handle changes to the BottomSidePanel property. - - - - - AutoHideWindow Read-Only Dependency Property - - - - - Provides a secure method for setting the AutoHideWindow property. - This dependency property indicates the currently shown autohide window. - - The new value for the property. - - - - Handles changes to the AutoHideWindow property. - - - - - Provides derived classes an opportunity to handle changes to the AutoHideWindow property. - - - - - LayoutItemTemplate Dependency Property - - - - - Handles changes to the AnchorableTemplate property. - - - - - Provides derived classes an opportunity to handle changes to the AnchorableTemplate property. - - - - - LayoutItemTemplateSelector Dependency Property - - - - - Handles changes to the LayoutItemTemplateSelector property. - - - - - Provides derived classes an opportunity to handle changes to the LayoutItemTemplateSelector property. - - - - - DocumentsSource Dependency Property - - - - - Handles changes to the DocumentsSource property. - - - - - Provides derived classes an opportunity to handle changes to the DocumentsSource property. - - - - - DocumentContextMenu Dependency Property - - - - - AnchorablesSource Dependency Property - - - - - Handles changes to the AnchorablesSource property. - - - - - Provides derived classes an opportunity to handle changes to the AnchorablesSource property. - - - - - ActiveContent Dependency Property - - - - - Handles changes to the ActiveContent property. - - - - - Provides derived classes an opportunity to handle changes to the ActiveContent property. - - - - - AnchorableContextMenu Dependency Property - - - - - Theme Dependency Property - - - - - Handles changes to the Theme property. - - - - - Provides derived classes an opportunity to handle changes to the Theme property. - - - - - GridSplitterWidth Dependency Property - - - - - GridSplitterHeight Dependency Property - - - - - DocumentPaneMenuItemHeaderTemplate Dependency Property - - - - - Handles changes to the DocumentPaneMenuItemHeaderTemplate property. - - - - - Provides derived classes an opportunity to handle changes to the DocumentPaneMenuItemHeaderTemplate property. - - - - - Coerces the DocumentPaneMenuItemHeaderTemplate value. - - - - - DocumentPaneMenuItemHeaderTemplateSelector Dependency Property - - - - - Handles changes to the DocumentPaneMenuItemHeaderTemplateSelector property. - - - - - Provides derived classes an opportunity to handle changes to the DocumentPaneMenuItemHeaderTemplateSelector property. - - - - - Coerces the DocumentPaneMenuItemHeaderTemplateSelector value. - - - - - IconContentTemplate Dependency Property - - - - - IconContentTemplateSelector Dependency Property - - - - - LayoutItemContainerStyle Dependency Property - - - - - Handles changes to the LayoutItemContainerStyle property. - - - - - Provides derived classes an opportunity to handle changes to the LayoutItemContainerStyle property. - - - - - LayoutItemContainerStyleSelector Dependency Property - - - - - Handles changes to the LayoutItemContainerStyleSelector property. - - - - - Provides derived classes an opportunity to handle changes to the LayoutItemContainerStyleSelector property. - - - - - Return the LayoutItem wrapper for the content passed as argument - - LayoutContent to search - Either a LayoutAnchorableItem or LayoutDocumentItem which contains the LayoutContent passed as argument - - - - ShowSystemMenu Dependency Property - - - - - AllowMixedOrientation Dependency Property - - - - - Gets or sets the Layout property. This dependency property - indicates layout tree. - - - - - Event fired when property changes - - - - - Event fired when property is about to be changed - - - - - Gets or sets the LayoutUpdateStrategy property. This dependency property - indicates the strategy class to call when AvalonDock needs to positionate a LayoutAnchorable inside an existing layout. - - Sometimes it's impossible to automatically insert an anchorable in the layout without specifing the target parent pane. - Set this property to an object that will be asked to insert the anchorable to the desidered position. - - - - Gets or sets the DocumentPaneDataTemplate property. This dependency property - indicates . - - - - - Gets or sets the AnchorablePaneTemplate property. This dependency property - indicates .... - - - - - Gets or sets the AnchorSideTemplate property. This dependency property - indicates .... - - - - - Gets or sets the AnchorGroupTemplate property. This dependency property - indicates the template used to render the AnchorGroup control. - - - - - Gets or sets the AnchorTemplate property. This dependency property - indicates .... - - - - - Gets or sets the DocumentPaneControlStyle property. This dependency property - indicates .... - - - - - Gets or sets the AnchorablePaneControlStyle property. This dependency property - indicates the style to apply to AnchorablePaneControl. - - - - - Gets or sets the DocumentHeaderTemplate property. This dependency property - indicates data template to use for document header. - - - - - Gets or sets the DocumentHeaderTemplateSelector property. This dependency property - indicates the template selector that is used when selcting the data template for the header. - - - - - Gets or sets the DocumentTitleTemplate property. This dependency property - indicates the datatemplate to use when creating the title for a document. - - - - - Gets or sets the DocumentTitleTemplateSelector property. This dependency property - indicates the data template selector to use when creating the data template for the title. - - - - - Gets or sets the AnchorableTitleTemplate property. This dependency property - indicates the data template to use for anchorables title. - - - - - Gets or sets the AnchorableTitleTemplateSelector property. This dependency property - indicates selctor to use when selecting data template for the title of anchorables. - - - - - Gets or sets the AnchorableHeaderTemplate property. This dependency property - indicates the data template to use for anchorable templates. - - - - - Gets or sets the AnchorableHeaderTemplateSelector property. This dependency property - indicates the selector to use when selecting the data template for anchorable headers. - - - - - Gets or sets the LayoutRootPanel property. This dependency property - indicates the layout panel control which is attached to the Layout.Root property. - - - - - Gets or sets the RightSidePanel property. This dependency property - indicates right side anchor panel. - - - - - Gets or sets the LeftSidePanel property. This dependency property - indicates the left side panel control. - - - - - Gets or sets the TopSidePanel property. This dependency property - indicates top side control panel. - - - - - Gets or sets the BottomSidePanel property. This dependency property - indicates bottom side panel control. - - - - - Gets the AutoHideWindow property. This dependency property - indicates the currently shown autohide window. - - - - - Gets or sets the AnchorableTemplate property. This dependency property - indicates the template to use to render anchorable and document contents. - - - - - Gets or sets the LayoutItemTemplateSelector property. This dependency property - indicates selector object to use for anchorable templates. - - - - - Gets or sets the DocumentsSource property. This dependency property - indicates the source collection of documents. - - - - - Event fired when a document is about to be closed - - Subscribers have the opportuniy to cancel the operation. - - - - Event fired after a document is closed - - - - - Gets or sets the DocumentContextMenu property. This dependency property - indicates context menu to show for documents. - - - - - Gets or sets the AnchorablesSource property. This dependency property - indicates source collection of anchorables. - - - - - Gets or sets the ActiveContent property. This dependency property - indicates the content currently active. - - - - - Gets or sets the AnchorableContextMenu property. This dependency property - indicates the context menu to show up for anchorables. - - - - - Gets or sets the Theme property. This dependency property - indicates the theme to use for AvalonDock controls. - - - - - Gets or sets the GridSplitterWidth property. This dependency property - indicates width of grid splitters. - - - - - Gets or sets the GridSplitterHeight property. This dependency property - indicates height of grid splitters. - - - - - Gets or sets the DocumentPaneMenuItemHeaderTemplate property. This dependency property - indicates the header template to use while creating menu items for the document panes. - - - - - Gets or sets the DocumentPaneMenuItemHeaderTemplateSelector property. This dependency property - indicates the data template selector to use for the menu items show when user select the DocumentPane document switch context menu. - - - - - Gets or sets the IconContentTemplate property. This dependency property - indicates the data template to use while extracting the icon from model. - - - - - Gets or sets the IconContentTemplateSelector property. This dependency property - indicates data template selector to use while selecting the datatamplate for content icons. - - - - - Gets or sets the LayoutItemContainerStyle property. This dependency property - indicates the style to apply to LayoutDocumentItem objects. A LayoutDocumentItem object is created when a new LayoutDocument is created inside the current Layout. - - - - - Gets or sets the LayoutItemContainerStyleSelector property. This dependency property - indicates style selector of the LayoutDocumentItemStyle. - - - - - Gets or sets the ShowSystemMenu property. This dependency property - indicates if floating windows should show the system menu when a custom context menu is not defined. - - - - - Gets or sets the AllowMixedOrientation property. This dependency property - indicates if the manager should allow mixed orientation for document panes. - - - - - Converts a value. - - The value produced by the binding source. - The type of the binding target property. - The converter parameter to use. - The culture to use in the converter. - - A converted value. If the method returns null, the valid null value is used. - - - - - Converts a value. - - The value that is produced by the binding target. - The type to convert to. - The converter parameter to use. - The culture to use in the converter. - - A converted value. If the method returns null, the valid null value is used. - - - - - Wraps a managed stream instance into an interface pointer consumable by COM. - - - - - Initializes a new instance of the ManagedIStream class with the specified managed Stream object. - - - The stream that this IStream reference is wrapping. - - - - - Creates a new stream object with its own seek pointer that - references the same bytes as the original stream. - - - When this method returns, contains the new stream object. This parameter is passed uninitialized. - - - For more information, see the existing documentation for IStream::Clone in the MSDN library. - This class doesn't implement Clone. A COMException is thrown if it is used. - - - - - Ensures that any changes made to a stream object that is open in transacted - mode are reflected in the parent storage. - - - A value that controls how the changes for the stream object are committed. - - - For more information, see the existing documentation for IStream::Commit in the MSDN library. - - - - - Copies a specified number of bytes from the current seek pointer in the - stream to the current seek pointer in another stream. - - - A reference to the destination stream. - - - The number of bytes to copy from the source stream. - - - On successful return, contains the actual number of bytes read from the source. - (Note the native signature is to a ULARGE_INTEGER*, so 64 bits are written - to this parameter on success.) - - - On successful return, contains the actual number of bytes written to the destination. - (Note the native signature is to a ULARGE_INTEGER*, so 64 bits are written - to this parameter on success.) - - - - - Restricts access to a specified range of bytes in the stream. - - - The byte offset for the beginning of the range. - - - The length of the range, in bytes, to restrict. - - - The requested restrictions on accessing the range. - - - For more information, see the existing documentation for IStream::LockRegion in the MSDN library. - This class doesn't implement LockRegion. A COMException is thrown if it is used. - - - - - Reads a specified number of bytes from the stream object into memory starting at the current seek pointer. - - - When this method returns, contains the data read from the stream. This parameter is passed uninitialized. - - - The number of bytes to read from the stream object. - - - A pointer to a ULONG variable that receives the actual number of bytes read from the stream object. - - - For more information, see the existing documentation for ISequentialStream::Read in the MSDN library. - - - - - Discards all changes that have been made to a transacted stream since the last Commit call. - - - This class doesn't implement Revert. A COMException is thrown if it is used. - - - - - Changes the seek pointer to a new location relative to the beginning of the - stream, to the end of the stream, or to the current seek pointer. - - - The displacement to add to dwOrigin. - - - The origin of the seek. The origin can be the beginning of the file, the current seek pointer, or the end of the file. - - - On successful return, contains the offset of the seek pointer from the beginning of the stream. - (Note the native signature is to a ULARGE_INTEGER*, so 64 bits are written - to this parameter on success.) - - - For more information, see the existing documentation for IStream::Seek in the MSDN library. - - - - - Changes the size of the stream object. - - - The new size of the stream as a number of bytes. - - - For more information, see the existing documentation for IStream::SetSize in the MSDN library. - - - - - Retrieves the STATSTG structure for this stream. - - - When this method returns, contains a STATSTG structure that describes this stream object. - This parameter is passed uninitialized. - - - Members in the STATSTG structure that this method does not return, thus saving some memory allocation operations. - - - - - Removes the access restriction on a range of bytes previously restricted with the LockRegion method. - - The byte offset for the beginning of the range. - - - The length, in bytes, of the range to restrict. - - - The access restrictions previously placed on the range. - - - For more information, see the existing documentation for IStream::UnlockRegion in the MSDN library. - This class doesn't implement UnlockRegion. A COMException is thrown if it is used. - - - - - Writes a specified number of bytes into the stream object starting at the current seek pointer. - - - The buffer to write this stream to. - - - The number of bytes to write to the stream. - - - On successful return, contains the actual number of bytes written to the stream object. - If the caller sets this pointer to null, this method does not provide the actual number - of bytes written. - - - - - Releases resources controlled by this object. - - - Dispose can be called multiple times, but trying to use the object - after it has been disposed will generally throw ObjectDisposedExceptions. - - - - - HIGHCONTRAST flags - - - - - BITMAPINFOHEADER Compression type. BI_*. - - - - - CombingRgn flags. RGN_* - - - - - Creates the intersection of the two combined regions. - - - - - Creates the union of two combined regions. - - - - - Creates the union of two combined regions except for any overlapping areas. - - - - - Combines the parts of hrgnSrc1 that are not part of hrgnSrc2. - - - - - Creates a copy of the region identified by hrgnSrc1. - - - - - For IWebBrowser2. OLECMDEXECOPT_* - - - - - For IWebBrowser2. OLECMDF_* - - - - - For IWebBrowser2. OLECMDID_* - - - - - For IWebBrowser2. READYSTATE_* - - - - - DATAOBJ_GET_ITEM_FLAGS. DOGIF_*. - - - - Use the system default, which is to display all error dialog boxes. - - - - The system does not display the critical-error-handler message box. - Instead, the system sends the error to the calling process. - - - - - 64-bit Windows: The system automatically fixes memory alignment faults and makes them - invisible to the application. It does this for the calling process and any descendant processes. - After this value is set for a process, subsequent attempts to clear the value are ignored. - - - - - The system does not display the general-protection-fault message box. - This flag should only be set by debugging applications that handle general - protection (GP) faults themselves with an exception handler. - - - - - The system does not display a message box when it fails to find a file. - Instead, the error is returned to the calling process. - - - - - Non-client hit test values, HT* - - - - - GetClassLongPtr values, GCLP_* - - - - - GetWindowLongPtr values, GWL_* - - - - - SystemMetrics. SM_* - - - - - SystemParameterInfo values, SPI_* - - - - - SystemParameterInfo flag values, SPIF_* - - - - - CS_* - - - - - WindowStyle values, WS_* - - - - - Window message values, WM_* - - - - - Window style extended values, WS_EX_* - - - - - GetDeviceCaps nIndex values. - - - - Number of bits per pixel - - - - - Number of planes - - - - - Logical pixels inch in X - - - - - Logical pixels inch in Y - - - - - "FILEOP_FLAGS", FOF_*. - - - - - EnableMenuItem uEnable values, MF_* - - - - - Possible return value for EnableMenuItem - - - - Specifies the type of visual style attribute to set on a window. - - - Non-client area window attributes will be set. - - - - DWMFLIP3DWINDOWPOLICY. DWMFLIP3D_* - - - - - DWMNCRENDERINGPOLICY. DWMNCRP_* - - - - - DWMWINDOWATTRIBUTE. DWMWA_* - - - - - WindowThemeNonClientAttributes - - - - Prevents the window caption from being drawn. - - - Prevents the system icon from being drawn. - - - Prevents the system icon menu from appearing. - - - Prevents mirroring of the question mark, even in right-to-left (RTL) layout. - - - A mask that contains all the valid bits. - - - - SetWindowPos options - - - - - ShowWindow options - - - - - SCF_ISSECURE - - - - - GDI+ Status codes - - - - - MSGFLT_*. New in Vista. Realiased in Windows 7. - - - - - Shell_NotifyIcon messages. NIM_* - - - - - SHAddToRecentDocuments flags. SHARD_* - - - - - Shell_NotifyIcon flags. NIF_* - - - - - Vista only. - - - - - Vista only. - - - - - Shell_NotifyIcon info flags. NIIF_* - - - - XP SP2 and later. - - - XP and later. - - - Vista and later. - - - Windows 7 and later - - - XP and later. Native version called NIIF_ICON_MASK. - - - - AC_* - - - - - The state of the icon. There are two flags that can be set independently. - NIS_HIDDEN = 1. The icon is hidden. - NIS_SHAREDICON = 2. The icon is shared. - - - - The idlist for the shell item that should be added to the recent docs folder. - - - The id of the application that should be associated with this recent doc. - - - Defines options that are used to set window visual style attributes. - - - - A combination of flags that modify window visual style attributes. - Can be a combination of the WTNCA constants. - - - - - A bitmask that describes how the values specified in dwFlags should be applied. - If the bit corresponding to a value in dwFlags is 0, that flag will be removed. - If the bit is 1, the flag will be added. - - - - Width of left border that retains its size. - - - Width of right border that retains its size. - - - Height of top border that retains its size. - - - Height of bottom border that retains its size. - - - Delegate declaration that matches native WndProc signatures. - - - Delegate declaration that matches native WndProc signatures. - - - Delegate declaration that matches managed WndProc signatures. - - - - Sets attributes to control how visual styles are applied to a specified window. - - - Handle to a window to apply changes to. - - - Value of type WINDOWTHEMEATTRIBUTETYPE that specifies the type of attribute to set. - The value of this parameter determines the type of data that should be passed in the pvAttribute parameter. - Can be the following value: - WTA_NONCLIENT (Specifies non-client related attributes). - pvAttribute must be a pointer of type WTA_OPTIONS. - - - A pointer that specifies attributes to set. Type is determined by the value of the eAttribute value. - - - Specifies the size, in bytes, of the data pointed to by pvAttribute. - - - - Overload of SystemParametersInfo for getting and setting NONCLIENTMETRICS. - - - Overload of SystemParametersInfo for getting and setting HIGHCONTRAST. - - - - Sets the User Model AppID for the current process, enabling Windows to retrieve this ID - - - - - - Retrieves the User Model AppID that has been explicitly set for the current process via SetCurrentProcessExplicitAppUserModelID - - - - - - Description Dependency Property - - - - - Handles changes to the Description property. - - - - - Provides derived classes an opportunity to handle changes to the Description property. - - - - - Gets or sets the Description property. This dependency property - indicates the description to display for the document item. - - - - - Model Dependency Property - - - - - Handles changes to the Model property. - - - - - Provides derived classes an opportunity to handle changes to the Model property. - - - - - LayoutItem Read-Only Dependency Property - - - - - Provides a secure method for setting the LayoutItem property. - This dependency property indicates the LayoutItem attached to this tag item. - - The new value for the property. - - - - Gets or sets the Model property. This dependency property - indicates the layout content model attached to the tab item. - - - - - Gets the LayoutItem property. This dependency property - indicates the LayoutItem attached to this tag item. - - - - - IsLeftSide Read-Only Dependency Property - - - - - Provides a secure method for setting the IsLeftSide property. - This dependency property indicates this control is anchored to left side. - - The new value for the property. - - - - IsTopSide Read-Only Dependency Property - - - - - Provides a secure method for setting the IsTopSide property. - This dependency property indicates this control is anchored to top side. - - The new value for the property. - - - - IsRightSide Read-Only Dependency Property - - - - - Provides a secure method for setting the IsRightSide property. - This dependency property indicates this control is anchored to right side. - - The new value for the property. - - - - IsBottomSide Read-Only Dependency Property - - - - - Provides a secure method for setting the IsBottomSide property. - This dependency property indicates if this panel is anchored to bottom side. - - The new value for the property. - - - - Gets the IsLeftSide property. This dependency property - indicates this control is anchored to left side. - - - - - Gets the IsTopSide property. This dependency property - indicates this control is anchored to top side. - - - - - Gets the IsRightSide property. This dependency property - indicates this control is anchored to right side. - - - - - Gets the IsBottomSide property. This dependency property - indicates if this panel is anchored to bottom side. - - - - - DoubleUtil uses fixed eps to provide fuzzy comparison functionality for doubles. - Note that FP noise is a big problem and using any of these compare - methods is not a complete solution, but rather the way to reduce - the probability of repeating unnecessary work. - - - - - Epsilon - more or less random, more or less small number. - - - - - AreClose returns whether or not two doubles are "close". That is, whether or - not they are within epsilon of each other. - There are plenty of ways for this to return false even for numbers which - are theoretically identical, so no code calling this should fail to work if this - returns false. - - The first double to compare. - The second double to compare. - The result of the AreClose comparision. - - - - LessThan returns whether or not the first double is less than the second double. - That is, whether or not the first is strictly less than *and* not within epsilon of - the other number. - There are plenty of ways for this to return false even for numbers which - are theoretically identical, so no code calling this should fail to work if this - returns false. - - The first double to compare. - The second double to compare. - The result of the LessThan comparision. - - - - GreaterThan returns whether or not the first double is greater than the second double. - That is, whether or not the first is strictly greater than *and* not within epsilon of - the other number. - There are plenty of ways for this to return false even for numbers which - are theoretically identical, so no code calling this should fail to work if this - returns false. - - The first double to compare. - The second double to compare. - The result of the GreaterThan comparision. - - - - LessThanOrClose returns whether or not the first double is less than or close to - the second double. That is, whether or not the first is strictly less than or within - epsilon of the other number. - There are plenty of ways for this to return false even for numbers which - are theoretically identical, so no code calling this should fail to work if this - returns false. - - The first double to compare. - The second double to compare. - The result of the LessThanOrClose comparision. - - - - GreaterThanOrClose returns whether or not the first double is greater than or close to - the second double. That is, whether or not the first is strictly greater than or within - epsilon of the other number. - There are plenty of ways for this to return false even for numbers which - are theoretically identical, so no code calling this should fail to work if this - returns false. - - The first double to compare. - The second double to compare. - The result of the GreaterThanOrClose comparision. - - - - Test to see if a double is a finite number (is not NaN or Infinity). - - The value to test. - Whether or not the value is a finite number. - - - - Test to see if a double a valid size value (is finite and > 0). - - The value to test. - Whether or not the value is a valid size value. - - - - Direct insert/remove operation has been perfomed to the group - - - - - An element below in the hierarchy as been added/removed - - - - - Converts a value. - - The value produced by the binding source. - The type of the binding target property. - The converter parameter to use. - The culture to use in the converter. - - A converted value. If the method returns null, the valid null value is used. - - - - - Converts a value. - - The value that is produced by the binding target. - The type to convert to. - The converter parameter to use. - The culture to use in the converter. - - A converted value. If the method returns null, the valid null value is used. - - - - - Model Dependency Property - - - - - Handles changes to the Model property. - - - - - Provides derived classes an opportunity to handle changes to the Model property. - - - - - LayoutItem Read-Only Dependency Property - - - - - Provides a secure method for setting the LayoutItem property. - This dependency property indicates the LayoutItem attached to this tag item. - - The new value for the property. - - - - Gets or sets the Model property. This dependency property - indicates the model attached to this view. - - - - - Gets the LayoutItem property. This dependency property - indicates the LayoutItem attached to this tag item. - - - - - Wrapper for common Win32 status codes. - - - - The operation completed successfully. - - - Incorrect function. - - - The system cannot find the file specified. - - - The system cannot find the path specified. - - - The system cannot open the file. - - - Access is denied. - - - The handle is invalid. - - - Not enough storage is available to complete this operation. - - - There are no more files. - - - The process cannot access the file because it is being used by another process. - - - The parameter is incorrect. - - - The data area passed to a system call is too small. - - - Cannot nest calls to LoadModule. - - - Illegal operation attempted on a registry key that has been marked for deletion. - - - Element not found. - - - There was no match for the specified key in the index. - - - An invalid device was specified. - - - The operation was canceled by the user. - - - The window class was already registered. - - - The specified datatype is invalid. - - - - Create a new Win32 error. - - The integer value of the error. - - - Performs HRESULT_FROM_WIN32 conversion. - The Win32 error being converted to an HRESULT. - The equivilent HRESULT value. - - - Performs HRESULT_FROM_WIN32 conversion. - The Win32 error being converted to an HRESULT. - The equivilent HRESULT value. - - - Performs the equivalent of Win32's GetLastError() - A Win32Error instance with the result of the native GetLastError - - - - Compare two Win32 error codes for equality. - - The first error code to compare. - The second error code to compare. - Whether the two error codes are the same. - - - - Compare two Win32 error codes for inequality. - - The first error code to compare. - The second error code to compare. - Whether the two error codes are not the same. - - - FACILITY_NULL - - - FACILITY_RPC - - - FACILITY_DISPATCH - - - FACILITY_STORAGE - - - FACILITY_ITF - - - FACILITY_WIN32 - - - FACILITY_WINDOWS - - - FACILITY_CONTROL - - - MSDN doced facility code for ESE errors. - - - FACILITY_WINCODEC (WIC) - - - Wrapper for HRESULT status codes. - - - S_OK - - - S_FALSE - - - E_PENDING - - - E_NOTIMPL - - - E_NOINTERFACE - - - E_POINTER - - - E_ABORT - - - E_FAIL - - - E_UNEXPECTED - - - STG_E_INVALIDFUNCTION - - - REGDB_E_CLASSNOTREG - - - DESTS_E_NO_MATCHING_ASSOC_HANDLER. Win7 internal error code for Jump Lists. - There is no Assoc Handler for the given item registered by the specified application. - - - DESTS_E_NORECDOCS. Win7 internal error code for Jump Lists. - The given item is excluded from the recent docs folder by the NoRecDocs bit on its registration. - - - DESTS_E_NOTALLCLEARED. Win7 internal error code for Jump Lists. - Not all of the items were successfully cleared - - - E_ACCESSDENIED - Win32Error ERROR_ACCESS_DENIED. - - - E_OUTOFMEMORY - Win32Error ERROR_OUTOFMEMORY. - - - E_INVALIDARG - Win32Error ERROR_INVALID_PARAMETER. - - - INTSAFE_E_ARITHMETIC_OVERFLOW - - - COR_E_OBJECTDISPOSED - - - WC_E_GREATERTHAN - - - WC_E_SYNTAX - - - - Create an HRESULT from an integer value. - - - - - - Get a string representation of this HRESULT. - - - - - - Convert the result of Win32 GetLastError() into a raised exception. - - - - - retrieve HRESULT_FACILITY - - - - - retrieve HRESULT_CODE - - - - - HideCommand Dependency Property - - - - - Handles changes to the HideCommand property. - - - - - Provides derived classes an opportunity to handle changes to the HideCommand property. - - - - - Coerces the HideCommand value. - - - - - AutoHideCommand Dependency Property - - - - - Handles changes to the AutoHideCommand property. - - - - - Provides derived classes an opportunity to handle changes to the AutoHideCommand property. - - - - - Coerces the AutoHideCommand value. - - - - - DockCommand Dependency Property - - - - - Handles changes to the DockCommand property. - - - - - Provides derived classes an opportunity to handle changes to the DockCommand property. - - - - - Coerces the DockCommand value. - - - - - CanHide Dependency Property - - - - - Handles changes to the CanHide property. - - - - - Provides derived classes an opportunity to handle changes to the CanHide property. - - - - - Gets or sets the HideCommand property. This dependency property - indicates the command to execute when an anchorable is hidden. - - - - - Gets or sets the AutoHideCommand property. This dependency property - indicates the command to execute when user click the auto hide button. - - By default this command toggles auto hide state for an anchorable. - - - - Gets or sets the DockCommand property. This dependency property - indicates the command to execute when user click the Dock button. - - By default this command moves the anchorable inside the container pane which previously hosted the object. - - - - Gets or sets the CanHide property. This dependency property - indicates if user can hide the anchorable item. - - - - - Model Dependency Property - - - - - Provides derived classes an opportunity to handle changes to the Model property. - - - - - LayoutItem Read-Only Dependency Property - - - - - Provides a secure method for setting the LayoutItem property. - This dependency property indicates the LayoutItem attached to this tag item. - - The new value for the property. - - - - Gets or sets the Model property. This dependency property - indicates model attached to this view. - - - - - Gets the LayoutItem property. This dependency property - indicates the LayoutItem attached to this tag item. - - - - - Special window handles - - - - - Changes an attribute of the specified window. The function also sets the 32-bit (long) value at the specified offset into the extra window memory. - - A handle to the window and, indirectly, the class to which the window belongs.. - The zero-based offset to the value to be set. Valid values are in the range zero through the number of bytes of extra window memory, minus the size of an integer. To set any other value, specify one of the following values: GWL_EXSTYLE, GWL_HINSTANCE, GWL_ID, GWL_STYLE, GWL_USERDATA, GWL_WNDPROC - The replacement value. - If the function succeeds, the return value is the previous value of the specified 32-bit integer. - If the function fails, the return value is zero. To get extended error information, call GetLastError. - - - - The MonitorFromRect function retrieves a handle to the display monitor that - has the largest area of intersection with a specified rectangle. - - Pointer to a RECT structure that specifies the rectangle of interest in - virtual-screen coordinates - Determines the function's return value if the rectangle does not intersect - any display monitor - - If the rectangle intersects one or more display monitor rectangles, the return value - is an HMONITOR handle to the display monitor that has the largest area of intersection with the rectangle. - If the rectangle does not intersect a display monitor, the return value depends on the value of dwFlags. - - - - - The MonitorFromWindow function retrieves a handle to the display monitor that has the largest area of intersection with the bounding rectangle of a specified window. - - A handle to the window of interest. - Determines the function's return value if the window does not intersect any display monitor. - If the window intersects one or more display monitor rectangles, the return value is an HMONITOR handle to the display monitor that has the largest area of intersection with the window. - If the window does not intersect a display monitor, the return value depends on the value of dwFlags. - - - - - The GetMonitorInfo function retrieves information about a display monitor. - - Handle to the display monitor of interest. - Pointer to a MONITORINFO or MONITORINFOEX structure that receives - information about the specified display monitor - If the function succeeds, the return value is nonzero. - If the function fails, the return value is zero. - - - - SetWindowPos Flags - - - - If the calling thread and the thread that owns the window are attached to different input queues, - the system posts the request to the thread that owns the window. This prevents the calling thread from - blocking its execution while other threads process the request. - SWP_ASYNCWINDOWPOS - - - Prevents generation of the WM_SYNCPAINT message. - SWP_DEFERERASE - - - Draws a frame (defined in the window's class description) around the window. - SWP_DRAWFRAME - - - Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to - the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE - is sent only when the window's size is being changed. - SWP_FRAMECHANGED - - - Hides the window. - SWP_HIDEWINDOW - - - Does not activate the window. If this flag is not set, the window is activated and moved to the - top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter - parameter). - SWP_NOACTIVATE - - - Discards the entire contents of the client area. If this flag is not specified, the valid - contents of the client area are saved and copied back into the client area after the window is sized or - repositioned. - SWP_NOCOPYBITS - - - Retains the current position (ignores X and Y parameters). - SWP_NOMOVE - - - Does not change the owner window's position in the Z order. - SWP_NOOWNERZORDER - - - Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to - the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent - window uncovered as a result of the window being moved. When this flag is set, the application must - explicitly invalidate or redraw any parts of the window and parent window that need redrawing. - SWP_NOREDRAW - - - Same as the SWP_NOOWNERZORDER flag. - SWP_NOREPOSITION - - - Prevents the window from receiving the WM_WINDOWPOSCHANGING message. - SWP_NOSENDCHANGING - - - Retains the current size (ignores the cx and cy parameters). - SWP_NOSIZE - - - Retains the current Z order (ignores the hWndInsertAfter parameter). - SWP_NOZORDER - - - Displays the window. - SWP_SHOWWINDOW - - - - The MONITORINFO structure contains information about a display monitor. - - - - - The size of the structure, in bytes. - - - - - A RECT structure that specifies the display monitor rectangle, expressed - in virtual-screen coordinates. - Note that if the monitor is not the primary display monitor, - some of the rectangle's coordinates may be negative values. - - - - - A RECT structure that specifies the work area rectangle of the display monitor, - expressed in virtual-screen coordinates. Note that if the monitor is not the primary - display monitor, some of the rectangle's coordinates may be negative values. - - - - - A set of flags that represent attributes of the display monitor. - - - - - A strongly-typed resource class, for looking up localized strings, etc. - - - - - Returns the cached ResourceManager instance used by this class. - - - - - Overrides the current thread's CurrentUICulture property for all - resource lookups using this strongly typed resource class. - - - - - Looks up a localized string similar to Auto Hide. - - - - - Looks up a localized string similar to Auto Hide. - - - - - Looks up a localized string similar to Hide. - - - - - Looks up a localized string similar to Window Position. - - - - - Looks up a localized string similar to Dock. - - - - - Looks up a localized string similar to Dock as Tabbed Document. - - - - - Looks up a localized string similar to Float. - - - - - Looks up a localized string similar to Hide. - - - - - Looks up a localized string similar to Close. - - - - - Looks up a localized string similar to Close All But This. - - - - - Looks up a localized string similar to Window Position. - - - - - Looks up a localized string similar to Dock as Tabbed Document. - - - - - Looks up a localized string similar to Float. - - - - - Looks up a localized string similar to Move To Next Tab Group. - - - - - Looks up a localized string similar to Move To Previous Tab Group. - - - - - Looks up a localized string similar to New Horizontal Tab Group. - - - - - Looks up a localized string similar to New Vertical Tab Group. - - - - - Looks up a localized string similar to Maximize. - - - - - Looks up a localized string similar to Restore. - - - - - IconTemplate Dependency Property - - - - - Handles changes to the IconTemplate property. - - - - - Provides derived classes an opportunity to handle changes to the IconTemplate property. - - - - - IconTemplateSelector Dependency Property - - - - - Handles changes to the IconTemplateSelector property. - - - - - Provides derived classes an opportunity to handle changes to the IconTemplateSelector property. - - - - - Gets or sets the IconTemplate property. This dependency property - indicates the data template for the icon. - - - - - Gets or sets the IconTemplateSelector property. This dependency property - indicates the DataTemplateSelector for the Icon. - - - - diff --git a/packages/AvalonDock.2.0.2000/lib/net40/de/Xceed.Wpf.AvalonDock.resources.dll b/packages/AvalonDock.2.0.2000/lib/net40/de/Xceed.Wpf.AvalonDock.resources.dll deleted file mode 100644 index 3005ea9adb669b3dc833d986841e965e67150d67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6144 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 diff --git a/packages/AvalonDock.2.0.2000/lib/net40/hu/Xceed.Wpf.AvalonDock.resources.dll b/packages/AvalonDock.2.0.2000/lib/net40/hu/Xceed.Wpf.AvalonDock.resources.dll deleted file mode 100644 index b09aea9846d9c36a2251ce8e42856900d65f242c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5632 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 diff --git a/packages/AvalonDock.2.0.2000/lib/net40/pt-BR/Xceed.Wpf.AvalonDock.resources.dll b/packages/AvalonDock.2.0.2000/lib/net40/pt-BR/Xceed.Wpf.AvalonDock.resources.dll deleted file mode 100644 index 8c9eb599a5ded3319c96b9048cc3899d4033b999..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6144 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 E4f+-;BLDyZ diff --git a/packages/AvalonDock.2.0.2000/lib/net40/ru/Xceed.Wpf.AvalonDock.resources.dll b/packages/AvalonDock.2.0.2000/lib/net40/ru/Xceed.Wpf.AvalonDock.resources.dll deleted file mode 100644 index 4c77c97e57e2ebb24dc481d41df8a076ce9eff18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6144 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 diff --git a/packages/AvalonDock.2.0.2000/lib/net40/zh-Hans/Xceed.Wpf.AvalonDock.resources.dll b/packages/AvalonDock.2.0.2000/lib/net40/zh-Hans/Xceed.Wpf.AvalonDock.resources.dll deleted file mode 100644 index c52a6daa0078458a6c9fb460a6cecd407546d38c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5632 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 L`@dG-tOfoDC6Y~i diff --git a/packages/ini-parser.2.1.1/README.md b/packages/ini-parser.2.1.1/README.md deleted file mode 100644 index e189676e..00000000 --- a/packages/ini-parser.2.1.1/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# INI File Parser - -A Mono-compatible .NET library for reading/writing INI data from IO streams, file streams, and strings. - -[![Build Status](https://travis-ci.org/rickyah/ini-parser.png?branch=master)](https://travis-ci.org/rickyah/ini-parser) - -## Installation - -The library is published to [NuGet](https://www.nuget.org/packages/ini-parser/) and can be installed on the command-line from the directory containing your solution. - -```bat -> nuget install ini-parser -``` - -Or, from the [Package Manager Console](http://docs.nuget.org/docs/start-here/using-the-package-manager-console) in Visual Studio - -```powershell -PM> Install-Package ini-parser -``` - -Or from the [NuGet Package Manager](http://visualstudiogallery.msdn.microsoft.com/27077b70-9dad-4c64-adcf-c7cf6bc9970c) extension built available for most flavors of Visual Studio! - -## Getting Started - -INI data is stored in nested dictionaries, so accessing the value associated to a key in a section is straightforward. Load the data using one of the provided methods. - -```csharp -var data = parser.ReadFile("Configuration.ini"); -``` - -Retrieve the value for a key inside of a named section. Values are always retrieved as `string`s. - -```csharp -var useFullScreen = data["UI"]["fullscreen"]; -``` - -Modify the value in the dictionary, not the value retrieved, and save to a new file or overwrite. - -```csharp -data["UI"]["fullscreen"] = "true"; -parser.WriteFile("Configuration.ini", data); -``` - -See the [wiki](https://github.com/rickyah/ini-parser/wiki) for more usage examples. - -## Contributing - -Do you have an idea to improve this library, or did you happen to run into a bug. Please share your idea or the bug you found in the issues page, or even better: feel free to fork and [contribute](https://github.com/rickyah/ini-parser/wiki/Contributing) to this project! - -## Version 2.0! -Since the INI format isn't really a "standard", this version introduces a simpler way to customize INI parsing: - - * Pass a configuration object to an `IniParser`, specifying the behaviour of the parser. A default implementation is used if none is provided. - - * Derive from `IniDataParser` and override the fine-grained parsing methods. - diff --git a/packages/ini-parser.2.1.1/content/LICENSE b/packages/ini-parser.2.1.1/content/LICENSE deleted file mode 100644 index fe5f7ed6..00000000 --- a/packages/ini-parser.2.1.1/content/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2008 Ricardo Amores Hernández - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/ini-parser.2.1.1/ini-parser.2.1.1.nupkg b/packages/ini-parser.2.1.1/ini-parser.2.1.1.nupkg deleted file mode 100644 index 92c0c00b551dfe86ecf1bce6adfac6114cb1c869..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34647 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 diff --git a/packages/ini-parser.2.1.1/ini-parser.2.1.1.nuspec b/packages/ini-parser.2.1.1/ini-parser.2.1.1.nuspec deleted file mode 100644 index d958ff15..00000000 --- a/packages/ini-parser.2.1.1/ini-parser.2.1.1.nuspec +++ /dev/null @@ -1,17 +0,0 @@ - - - - ini-parser - 2.1.1 - INI Parser - Ricardo Amores Hernández - Ricardo Amores Hernández - https://github.com/rickyah/ini-parser/master/blob/LICENSE.txt - https://github.com/rickyah/ini-parser - false - A Mono compatible .NET open source library for managing data from an INI file format. Allows reading/writing INI data to and from I/O streams, file streams, and/or plain strings. - A simple C# library for reading and writing INI files - - ini - - \ No newline at end of file diff --git a/packages/ini-parser.2.1.1/lib/INIFileParser.dll b/packages/ini-parser.2.1.1/lib/INIFileParser.dll deleted file mode 100644 index 7a088d18907d711e488820cf176b7a4118462f6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26112 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 CVHb=5 diff --git a/packages/ini-parser.2.1.1/lib/INIFileParser.pdb b/packages/ini-parser.2.1.1/lib/INIFileParser.pdb deleted file mode 100644 index ae7f260303e40f729d3ad64132261c32dfac9909..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 87552 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 W#2=12EP=xkI4ps~5_o4y;Qs-TZ - - - \ No newline at end of file