├── .gitignore ├── 3rdparty └── inc │ ├── CUESDK.h │ ├── CUESDKGlobal.h │ ├── CorsairKeyIdEnum.h │ ├── CorsairLedIdEnum.h │ ├── RzChromaSDKDefines.h │ ├── RzChromaSDKTypes.h │ ├── RzErrors.h │ ├── SimpleIni │ ├── LICENCE.txt │ ├── README.md │ └── SimpleIni.h │ └── spdlog │ ├── LICENSE │ ├── async_logger.h │ ├── common.h │ ├── details │ ├── async_log_helper.h │ ├── async_logger_impl.h │ ├── file_helper.h │ ├── log_msg.h │ ├── logger_impl.h │ ├── mpmc_bounded_q.h │ ├── null_mutex.h │ ├── os.h │ ├── pattern_formatter_impl.h │ ├── registry.h │ └── spdlog_impl.h │ ├── fmt │ ├── bundled │ │ ├── LICENSE.rst │ │ ├── format.cc │ │ ├── format.h │ │ ├── ostream.cc │ │ ├── ostream.h │ │ ├── posix.cc │ │ ├── posix.h │ │ ├── printf.cc │ │ ├── printf.h │ │ └── time.h │ ├── fmt.h │ └── ostr.h │ ├── formatter.h │ ├── logger.h │ ├── sinks │ ├── android_sink.h │ ├── ansicolor_sink.h │ ├── base_sink.h │ ├── dist_sink.h │ ├── file_sinks.h │ ├── msvc_sink.h │ ├── null_sink.h │ ├── ostream_sink.h │ ├── sink.h │ ├── stdout_sinks.h │ ├── syslog_sink.h │ ├── wincolor_sink.h │ └── windebug_sink.h │ ├── spdlog.h │ └── tweakme.h ├── CONTRIBUTORS.md ├── LICENSE ├── README.md ├── RETC.sln ├── _config.yml ├── retc-installer ├── .gitignore ├── RETC_Installer.nsi ├── build.py └── files │ ├── .gitignore │ ├── win32 │ ├── .gitignore │ └── WIN32 FILES HERE.txt │ └── win64 │ ├── .gitignore │ └── WIN64 FILES HERE.txt ├── rpc-midl ├── midl.vcxproj ├── rpc_retc.acf └── rpc_retc.idl ├── scripts └── build-version.ps1 ├── server-exe ├── .gitignore ├── ConfigManager.cpp ├── ConfigManager.h ├── CorsairSDK.cpp ├── CorsairSDK.h ├── EffectManager.cpp ├── EffectManager.h ├── LightingSDK.h ├── RPCReceiver.cpp ├── RPCReceiver.h ├── RazerSDK.cpp ├── RazerSDK.h ├── SDKLoader.cpp ├── SDKLoader.h ├── SDKManager.cpp ├── SDKManager.h ├── Server.rc ├── colorTransformation.h ├── commonData.h ├── gammaTransformation.h ├── server.cpp ├── server.h ├── server.vcxproj ├── server.vcxproj.filters ├── service.cpp └── utils.h └── shim-dll ├── .gitignore ├── ShimDLL.rc ├── shim.cpp ├── shim.vcxproj └── shim.vcxproj.filters /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/visualstudio,c++,c,windows 3 | 4 | ### C ### 5 | # Prerequisites 6 | *.d 7 | 8 | # Object files 9 | *.o 10 | *.ko 11 | *.obj 12 | *.elf 13 | 14 | # Linker output 15 | *.ilk 16 | *.map 17 | *.exp 18 | 19 | # Precompiled Headers 20 | *.gch 21 | *.pch 22 | 23 | # Libraries 24 | *.lib 25 | *.a 26 | *.la 27 | *.lo 28 | 29 | # Shared objects (inc. Windows DLLs) 30 | *.dll 31 | *.so 32 | *.so.* 33 | *.dylib 34 | 35 | # Executables 36 | *.exe 37 | *.out 38 | *.app 39 | *.i*86 40 | *.x86_64 41 | *.hex 42 | 43 | # Debug files 44 | *.dSYM/ 45 | *.su 46 | *.idb 47 | *.pdb 48 | 49 | # Kernel Module Compile Results 50 | *.mod* 51 | *.cmd 52 | modules.order 53 | Module.symvers 54 | Mkfile.old 55 | dkms.conf 56 | 57 | ### C++ ### 58 | # Prerequisites 59 | 60 | # Compiled Object files 61 | *.slo 62 | 63 | # Precompiled Headers 64 | 65 | # Compiled Dynamic libraries 66 | 67 | # Fortran module files 68 | *.mod 69 | *.smod 70 | 71 | # Compiled Static libraries 72 | *.lai 73 | 74 | # Executables 75 | 76 | ### Windows ### 77 | # Windows thumbnail cache files 78 | Thumbs.db 79 | ehthumbs.db 80 | ehthumbs_vista.db 81 | 82 | # Folder config file 83 | Desktop.ini 84 | 85 | # Recycle Bin used on file shares 86 | $RECYCLE.BIN/ 87 | 88 | # Windows Installer files 89 | *.cab 90 | *.msi 91 | *.msm 92 | *.msp 93 | 94 | # Windows shortcuts 95 | *.lnk 96 | 97 | ### VisualStudio ### 98 | ## Ignore Visual Studio temporary files, build results, and 99 | ## files generated by popular Visual Studio add-ons. 100 | ## 101 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 102 | 103 | # User-specific files 104 | *.suo 105 | *.user 106 | *.userosscache 107 | *.sln.docstates 108 | 109 | # User-specific files (MonoDevelop/Xamarin Studio) 110 | *.userprefs 111 | 112 | # Build results 113 | [Dd]ebug/ 114 | [Dd]ebugPublic/ 115 | [Rr]elease/ 116 | [Rr]eleases/ 117 | x64/ 118 | x86/ 119 | bld/ 120 | [Bb]in/ 121 | [Oo]bj/ 122 | [Ll]og/ 123 | 124 | # Visual Studio 2015 cache/options directory 125 | .vs/ 126 | # Uncomment if you have tasks that create the project's static files in wwwroot 127 | #wwwroot/ 128 | 129 | # MSTest test Results 130 | [Tt]est[Rr]esult*/ 131 | [Bb]uild[Ll]og.* 132 | 133 | # NUNIT 134 | *.VisualState.xml 135 | TestResult.xml 136 | 137 | # Build Results of an ATL Project 138 | [Dd]ebugPS/ 139 | [Rr]eleasePS/ 140 | dlldata.c 141 | 142 | # .NET Core 143 | project.lock.json 144 | project.fragment.lock.json 145 | artifacts/ 146 | **/Properties/launchSettings.json 147 | 148 | *_i.c 149 | *_p.c 150 | *_i.h 151 | *.meta 152 | *.pgc 153 | *.pgd 154 | *.rsp 155 | *.sbr 156 | *.tlb 157 | *.tli 158 | *.tlh 159 | *.tmp 160 | *.tmp_proj 161 | *.log 162 | *.vspscc 163 | *.vssscc 164 | .builds 165 | *.pidb 166 | *.svclog 167 | *.scc 168 | 169 | # Chutzpah Test files 170 | _Chutzpah* 171 | 172 | # Visual C++ cache files 173 | ipch/ 174 | *.aps 175 | *.ncb 176 | *.opendb 177 | *.opensdf 178 | *.sdf 179 | *.cachefile 180 | *.VC.db 181 | *.VC.VC.opendb 182 | 183 | # Visual Studio profiler 184 | *.psess 185 | *.vsp 186 | *.vspx 187 | *.sap 188 | 189 | # TFS 2012 Local Workspace 190 | $tf/ 191 | 192 | # Guidance Automation Toolkit 193 | *.gpState 194 | 195 | # ReSharper is a .NET coding add-in 196 | _ReSharper*/ 197 | *.[Rr]e[Ss]harper 198 | *.DotSettings.user 199 | 200 | # JustCode is a .NET coding add-in 201 | .JustCode 202 | 203 | # TeamCity is a build add-in 204 | _TeamCity* 205 | 206 | # DotCover is a Code Coverage Tool 207 | *.dotCover 208 | 209 | # Visual Studio code coverage results 210 | *.coverage 211 | *.coveragexml 212 | 213 | # NCrunch 214 | _NCrunch_* 215 | .*crunch*.local.xml 216 | nCrunchTemp_* 217 | 218 | # MightyMoose 219 | *.mm.* 220 | AutoTest.Net/ 221 | 222 | # Web workbench (sass) 223 | .sass-cache/ 224 | 225 | # Installshield output folder 226 | [Ee]xpress/ 227 | 228 | # DocProject is a documentation generator add-in 229 | DocProject/buildhelp/ 230 | DocProject/Help/*.HxT 231 | DocProject/Help/*.HxC 232 | DocProject/Help/*.hhc 233 | DocProject/Help/*.hhk 234 | DocProject/Help/*.hhp 235 | DocProject/Help/Html2 236 | DocProject/Help/html 237 | 238 | # Click-Once directory 239 | publish/ 240 | 241 | # Publish Web Output 242 | *.[Pp]ublish.xml 243 | *.azurePubxml 244 | # TODO: Comment the next line if you want to checkin your web deploy settings 245 | # but database connection strings (with potential passwords) will be unencrypted 246 | *.pubxml 247 | *.publishproj 248 | 249 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 250 | # checkin your Azure Web App publish settings, but sensitive information contained 251 | # in these scripts will be unencrypted 252 | PublishScripts/ 253 | 254 | # NuGet Packages 255 | *.nupkg 256 | # The packages folder can be ignored because of Package Restore 257 | **/packages/* 258 | # except build/, which is used as an MSBuild target. 259 | !**/packages/build/ 260 | # Uncomment if necessary however generally it will be regenerated when needed 261 | #!**/packages/repositories.config 262 | # NuGet v3's project.json files produces more ignorable files 263 | *.nuget.props 264 | *.nuget.targets 265 | 266 | # Microsoft Azure Build Output 267 | csx/ 268 | *.build.csdef 269 | 270 | # Microsoft Azure Emulator 271 | ecf/ 272 | rcf/ 273 | 274 | # Windows Store app package directories and files 275 | AppPackages/ 276 | BundleArtifacts/ 277 | Package.StoreAssociation.xml 278 | _pkginfo.txt 279 | 280 | # Visual Studio cache files 281 | # files ending in .cache can be ignored 282 | *.[Cc]ache 283 | # but keep track of directories ending in .cache 284 | !*.[Cc]ache/ 285 | 286 | # Others 287 | ClientBin/ 288 | ~$* 289 | *~ 290 | *.dbmdl 291 | *.dbproj.schemaview 292 | *.jfm 293 | *.pfx 294 | *.publishsettings 295 | orleans.codegen.cs 296 | 297 | # Since there are multiple workflows, uncomment next line to ignore bower_components 298 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 299 | #bower_components/ 300 | 301 | # RIA/Silverlight projects 302 | Generated_Code/ 303 | 304 | # Backup & report files from converting an old project file 305 | # to a newer Visual Studio version. Backup files are not needed, 306 | # because we have git ;-) 307 | _UpgradeReport_Files/ 308 | Backup*/ 309 | UpgradeLog*.XML 310 | UpgradeLog*.htm 311 | 312 | # SQL Server files 313 | *.mdf 314 | *.ldf 315 | 316 | # Business Intelligence projects 317 | *.rdl.data 318 | *.bim.layout 319 | *.bim_*.settings 320 | 321 | # Microsoft Fakes 322 | FakesAssemblies/ 323 | 324 | # GhostDoc plugin setting file 325 | *.GhostDoc.xml 326 | 327 | # Node.js Tools for Visual Studio 328 | .ntvs_analysis.dat 329 | node_modules/ 330 | 331 | # Typescript v1 declaration files 332 | typings/ 333 | 334 | # Visual Studio 6 build log 335 | *.plg 336 | 337 | # Visual Studio 6 workspace options file 338 | *.opt 339 | 340 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 341 | *.vbw 342 | 343 | # Visual Studio LightSwitch build output 344 | **/*.HTMLClient/GeneratedArtifacts 345 | **/*.DesktopClient/GeneratedArtifacts 346 | **/*.DesktopClient/ModelManifest.xml 347 | **/*.Server/GeneratedArtifacts 348 | **/*.Server/ModelManifest.xml 349 | _Pvt_Extensions 350 | 351 | # Paket dependency manager 352 | .paket/paket.exe 353 | paket-files/ 354 | 355 | # FAKE - F# Make 356 | .fake/ 357 | 358 | # JetBrains Rider 359 | .idea/ 360 | *.sln.iml 361 | 362 | # CodeRush 363 | .cr/ 364 | 365 | # Python Tools for Visual Studio (PTVS) 366 | __pycache__/ 367 | *.pyc 368 | 369 | # Cake - Uncomment if you are using it 370 | # tools/** 371 | # !tools/packages.config 372 | 373 | *.i-* 374 | 375 | rpc-midl/*.c 376 | rpc-midl/rpc_retc.h 377 | # End of https://www.gitignore.io/api/visualstudio,c++,c,windows -------------------------------------------------------------------------------- /3rdparty/inc/CUESDKGlobal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _LIB 4 | # if defined(_WIN32) || defined(WIN32) 5 | # if defined(CORSAIR_LIGHTING_SDK_DLL) || defined(CUESDK_EXPORTS) 6 | # define CORSAIR_LIGHTING_SDK_EXPORT __declspec(dllexport) 7 | # else 8 | # define CORSAIR_LIGHTING_SDK_EXPORT __declspec(dllimport) 9 | # endif 10 | # else 11 | # define CORSAIR_LIGHTING_SDK_EXPORT __attribute__((visibility("default"))) 12 | # endif // WIN32 13 | #else 14 | # define CORSAIR_LIGHTING_SDK_EXPORT 15 | #endif // !_LIB 16 | -------------------------------------------------------------------------------- /3rdparty/inc/CorsairKeyIdEnum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum CorsairKeyId 4 | { 5 | CorsairKey_Invalid = 0, 6 | 7 | CorsairKeyKb_G1 = 1, 8 | CorsairKeyKb_G2 = 2, 9 | CorsairKeyKb_G3 = 3, 10 | CorsairKeyKb_G4 = 4, 11 | CorsairKeyKb_G5 = 5, 12 | CorsairKeyKb_G6 = 6, 13 | CorsairKeyKb_G7 = 7, 14 | CorsairKeyKb_G8 = 8, 15 | CorsairKeyKb_G9 = 9, 16 | CorsairKeyKb_G10 = 10, 17 | CorsairKeyKb_G11 = 11, 18 | CorsairKeyKb_G12 = 12, 19 | CorsairKeyKb_G13 = 13, 20 | CorsairKeyKb_G14 = 14, 21 | CorsairKeyKb_G15 = 15, 22 | CorsairKeyKb_G16 = 16, 23 | CorsairKeyKb_G17 = 17, 24 | CorsairKeyKb_G18 = 18, 25 | 26 | CorsairKeyMouse_M1 = 19, 27 | CorsairKeyMouse_M2 = 20, 28 | CorsairKeyMouse_M3 = 21, 29 | CorsairKeyMouse_M4 = 22, 30 | CorsairKeyMouse_M5 = 23, 31 | CorsairKeyMouse_M6 = 24, 32 | CorsairKeyMouse_M7 = 25, 33 | CorsairKeyMouse_M8 = 26, 34 | CorsairKeyMouse_M9 = 27, 35 | CorsairKeyMouse_M10 = 28, 36 | CorsairKeyMouse_M11 = 29, 37 | CorsairKeyMouse_M12 = 30, 38 | 39 | CorsairKey_Last = CorsairKeyMouse_M12 40 | }; 41 | -------------------------------------------------------------------------------- /3rdparty/inc/RzChromaSDKDefines.h: -------------------------------------------------------------------------------- 1 | //! \file RzChromaSDKDefines.h 2 | //! \brief Definitions of global and static variables. 3 | 4 | #ifndef _RZSCHROMADKDEFINES_H_ 5 | #define _RZSCHROMADKDEFINES_H_ 6 | 7 | #pragma once 8 | 9 | #ifndef GUID_DEFINED 10 | #include 11 | #endif 12 | 13 | namespace ChromaSDK 14 | { 15 | // Keyboards 16 | //! Razer Blackwidow Chroma device. 17 | // {2EA1BB63-CA28-428D-9F06-196B88330BBB} 18 | static const GUID BLACKWIDOW_CHROMA = 19 | { 0x2ea1bb63, 0xca28, 0x428d, { 0x9f, 0x06, 0x19, 0x6b, 0x88, 0x33, 0x0b, 0xbb } }; 20 | 21 | //! Razer Blackwidow Chroma Tournament Edition device. 22 | // {ED1C1B82-BFBE-418F-B49D-D03F05B149DF} 23 | static const GUID BLACKWIDOW_CHROMA_TE = 24 | { 0xed1c1b82, 0xbfbe, 0x418f, { 0xb4, 0x9d, 0xd0, 0x3f, 0x5, 0xb1, 0x49, 0xdf } }; 25 | 26 | //! Razer Deathstalker device. 27 | // {18C5AD9B-4326-4828-92C4-2669A66D2283} 28 | static const GUID DEATHSTALKER_CHROMA = 29 | { 0x18c5ad9b, 0x4326, 0x4828, { 0x92, 0xc4, 0x26, 0x69, 0xa6, 0x6d, 0x22, 0x83 } }; 30 | 31 | //! Overwatch Keyboard. 32 | // {872AB2A9-7959-4478-9FED-15F6186E72E4} 33 | static const GUID OVERWATCH_KEYBOARD = 34 | { 0x872ab2a9, 0x7959, 0x4478, { 0x9f, 0xed, 0x15, 0xf6, 0x18, 0x6e, 0x72, 0xe4 } }; 35 | 36 | //! Razer Blackwidow X Chroma device. 37 | // {5AF60076-ADE9-43D4-B574-52599293B554} 38 | static const GUID BLACKWIDOW_X_CHROMA = 39 | { 0x5af60076, 0xade9, 0x43d4, { 0xb5, 0x74, 0x52, 0x59, 0x92, 0x93, 0xb5, 0x54 } }; 40 | 41 | //! Razer Blackwidow X TE Chroma device. 42 | // {2D84DD51-3290-4AAC-9A89-D8AFDE38B57C} 43 | static const GUID BLACKWIDOW_X_TE_CHROMA = 44 | { 0x2d84dd51, 0x3290, 0x4aac, { 0x9a, 0x89, 0xd8, 0xaf, 0xde, 0x38, 0xb5, 0x7c } }; 45 | 46 | //! Razer Omata Chroma 47 | // {803378C1-CC48-4970-8539-D828CC1D420A} 48 | static const GUID OMATA_CHROMA = 49 | { 0x803378c1, 0xcc48, 0x4970,{ 0x85, 0x39, 0xd8, 0x28, 0xcc, 0x1d, 0x42, 0xa } }; 50 | 51 | //! Razer Blade Stealth. 52 | // {C83BDFE8-E7FC-40E0-99DB-872E23F19891} 53 | static const GUID BLADE_STEALTH = 54 | { 0xc83bdfe8, 0xe7fc, 0x40e0, { 0x99, 0xdb, 0x87, 0x2e, 0x23, 0xf1, 0x98, 0x91 } }; 55 | 56 | //! Razer Blade 57 | // {F2BEDFAF-A0FE-4651-9D41-B6CE603A3DDD} 58 | static const GUID BLADE = 59 | { 0xf2bedfaf, 0xa0fe, 0x4651, { 0x9d, 0x41, 0xb6, 0xce, 0x60, 0x3a, 0x3d, 0xdd } }; 60 | 61 | //! Razer Blade Pro 62 | // {A73AC338-F0E5-4BF7-91AE-DD1F7E1737A5} 63 | static const GUID BLADE_PRO = 64 | { 0xa73ac338, 0xf0e5, 0x4bf7,{ 0x91, 0xae, 0xdd, 0x1f, 0x7e, 0x17, 0x37, 0xa5 } }; 65 | 66 | //! Razer Blackwidow Chroma v2 67 | // {608E743F-B402-44BD-A7A6-7AA9F574ECF4} 68 | static const GUID BLACKWIDOW_CHROMA2 = 69 | { 0x608e743f, 0xb402, 0x44bd,{ 0xa7, 0xa6, 0x7a, 0xa9, 0xf5, 0x74, 0xec, 0xf4 } }; 70 | 71 | 72 | 73 | // Mice 74 | //! Razer Deathadder Chroma device. 75 | // {AEC50D91-B1F1-452F-8E16-7B73F376FDF3} 76 | static const GUID DEATHADDER_CHROMA = 77 | { 0xaec50d91, 0xb1f1, 0x452f, { 0x8e, 0x16, 0x7b, 0x73, 0xf3, 0x76, 0xfd, 0xf3 } }; 78 | 79 | //! Razer Mamba Chroma Tournament Edition device. 80 | // {7EC00450-E0EE-4289-89D5-0D879C19061A} 81 | static const GUID MAMBA_CHROMA_TE = 82 | { 0x7ec00450, 0xe0ee, 0x4289, { 0x89, 0xd5, 0xd, 0x87, 0x9c, 0x19, 0x6, 0x1a } }; 83 | 84 | //! Razer Diamondback device. 85 | // {FF8A5929-4512-4257-8D59-C647BF9935D0} 86 | static const GUID DIAMONDBACK_CHROMA = 87 | { 0xff8a5929, 0x4512, 0x4257, { 0x8d, 0x59, 0xc6, 0x47, 0xbf, 0x99, 0x35, 0xd0 } }; 88 | 89 | //! Razer Mamba device. 90 | // {D527CBDC-EB0A-483A-9E89-66D50463EC6C} 91 | static const GUID MAMBA_CHROMA = 92 | { 0xd527cbdc, 0xeb0a, 0x483a, { 0x9e, 0x89, 0x66, 0xd5, 0x4, 0x63, 0xec, 0x6c } }; 93 | 94 | //! Razer Naga Epic device. 95 | // {D714C50B-7158-4368-B99C-601ACB985E98} 96 | static const GUID NAGA_EPIC_CHROMA = 97 | { 0xd714c50b, 0x7158, 0x4368, { 0xb9, 0x9c, 0x60, 0x1a, 0xcb, 0x98, 0x5e, 0x98 } }; 98 | 99 | //! Razer Naga device. 100 | // {F1876328-6CA4-46AE-BE04-BE812B414433} 101 | static const GUID NAGA_CHROMA = 102 | { 0xf1876328, 0x6ca4, 0x46ae, { 0xbe, 0x4, 0xbe, 0x81, 0x2b, 0x41, 0x44, 0x33 } }; 103 | 104 | //! Razer Orochi Chroma device. 105 | // {52C15681-4ECE-4DD9-8A52-A1418459EB34} 106 | static const GUID OROCHI_CHROMA = 107 | { 0x52c15681, 0x4ece, 0x4dd9, { 0x8a, 0x52, 0xa1, 0x41, 0x84, 0x59, 0xeb, 0x34 } }; 108 | 109 | //! Razer Naga Hex Chroma device. 110 | // {195D70F5-F285-4CFF-99F2-B8C0E9658DB4} 111 | static const GUID NAGA_HEX_CHROMA = 112 | { 0x195d70f5, 0xf285, 0x4cff, { 0x99, 0xf2, 0xb8, 0xc0, 0xe9, 0x65, 0x8d, 0xb4 } }; 113 | 114 | //! Razer DeathAdder Elite Chroma device. 115 | // {77834867-3237-4A9F-AD77-4A46C4183003} 116 | static const GUID DEATHADDER_ELITE_CHROMA = 117 | { 0x77834867, 0x3237, 0x4a9f,{ 0xad, 0x77, 0x4a, 0x46, 0xc4, 0x18, 0x30, 0x3 } }; 118 | 119 | 120 | // Headsets 121 | //! Razer Kraken 7.1 Chroma device. 122 | // {CD1E09A5-D5E6-4A6C-A93B-E6D9BF1D2092} 123 | static const GUID KRAKEN71_CHROMA = 124 | { 0xcd1e09a5, 0xd5e6, 0x4a6c, { 0xa9, 0x3b, 0xe6, 0xd9, 0xbf, 0x1d, 0x20, 0x92 } }; 125 | 126 | //! Razer ManO'War device. 127 | // {DF3164D7-5408-4A0E-8A7F-A7412F26BEBF} 128 | static const GUID MANOWAR_CHROMA = 129 | { 0xdf3164d7, 0x5408, 0x4a0e, { 0x8a, 0x7f, 0xa7, 0x41, 0x2f, 0x26, 0xbe, 0xbf } }; 130 | 131 | //! Razer Kraken 7.1 Chroma Refresh headset. 132 | // {7FB8A36E-9E74-4BB3-8C86-CAC7F7891EBD} 133 | static const GUID KRAKEN71_REFRESH_CHROMA = 134 | { 0x7fb8a36e, 0x9e74, 0x4bb3,{ 0x8c, 0x86, 0xca, 0xc7, 0xf7, 0x89, 0x1e, 0xbd } }; 135 | 136 | 137 | // Mouse mat 138 | //! Razer Firefly device. 139 | // {80F95A94-73D2-48CA-AE9A-0986789A9AF2} 140 | static const GUID FIREFLY_CHROMA = 141 | { 0x80f95a94, 0x73d2, 0x48ca, { 0xae, 0x9a, 0x9, 0x86, 0x78, 0x9a, 0x9a, 0xf2 } }; 142 | 143 | 144 | // Keypads 145 | //! Razer Tartarus device. 146 | // {00F0545C-E180-4AD1-8E8A-419061CE505E} 147 | static const GUID TARTARUS_CHROMA = 148 | { 0xf0545c, 0xe180, 0x4ad1, { 0x8e, 0x8a, 0x41, 0x90, 0x61, 0xce, 0x50, 0x5e } }; 149 | 150 | //! Razer Orbweaver device. 151 | // {9D24B0AB-0162-466C-9640-7A924AA4D9FD} 152 | static const GUID ORBWEAVER_CHROMA = 153 | { 0x9d24b0ab, 0x162, 0x466c, { 0x96, 0x40, 0x7a, 0x92, 0x4a, 0xa4, 0xd9, 0xfd } }; 154 | 155 | 156 | // Chroma Linked devices 157 | // {35F6F18D-1AE5-436C-A575-AB44A127903A} 158 | static const GUID LENOVO_Y900 = 159 | { 0x35f6f18d, 0x1ae5, 0x436c, { 0xa5, 0x75, 0xab, 0x44, 0xa1, 0x27, 0x90, 0x3a } }; 160 | 161 | // {47DB1FA7-6B9B-4EE6-B6F4-4071A3B2053B} 162 | static const GUID LENOVO_Y27 = 163 | { 0x47db1fa7, 0x6b9b, 0x4ee6, { 0xb6, 0xf4, 0x40, 0x71, 0xa3, 0xb2, 0x5, 0x3b } }; 164 | 165 | // {0201203B-62F3-4C50-83DD-598BABD208E0} 166 | static const GUID CORE_CHROMA = 167 | { 0x201203b, 0x62f3, 0x4c50, { 0x83, 0xdd, 0x59, 0x8b, 0xab, 0xd2, 0x8, 0xe0 } }; 168 | 169 | 170 | } 171 | 172 | #endif 173 | -------------------------------------------------------------------------------- /3rdparty/inc/RzErrors.h: -------------------------------------------------------------------------------- 1 | 2 | //! \file RzErrors.h 3 | //! \brief Error codes for Chroma SDK. If the error is not defined here, refer to WinError.h from the Windows SDK. 4 | 5 | #ifndef _RZERRORS_H_ 6 | #define _RZERRORS_H_ 7 | 8 | #pragma once 9 | 10 | // Error codes 11 | //! Invalid 12 | #define RZRESULT_INVALID -1L 13 | //! Success 14 | #define RZRESULT_SUCCESS 0L 15 | //! Access denied 16 | #define RZRESULT_ACCESS_DENIED 5L 17 | //! Invalid handle 18 | #define RZRESULT_INVALID_HANDLE 6L 19 | //! Not supported 20 | #define RZRESULT_NOT_SUPPORTED 50L 21 | //! Invalid parameter. 22 | #define RZRESULT_INVALID_PARAMETER 87L 23 | //! The service has not been started 24 | #define RZRESULT_SERVICE_NOT_ACTIVE 1062L 25 | //! Cannot start more than one instance of the specified program. 26 | #define RZRESULT_SINGLE_INSTANCE_APP 1152L 27 | //! Device not connected 28 | #define RZRESULT_DEVICE_NOT_CONNECTED 1167L 29 | //! Element not found. 30 | #define RZRESULT_NOT_FOUND 1168L 31 | //! Request aborted. 32 | #define RZRESULT_REQUEST_ABORTED 1235L 33 | //! An attempt was made to perform an initialization operation when initialization has already been completed. 34 | #define RZRESULT_ALREADY_INITIALIZED 1247L 35 | //! Resource not available or disabled 36 | #define RZRESULT_RESOURCE_DISABLED 4309L 37 | //! Device not available or supported 38 | #define RZRESULT_DEVICE_NOT_AVAILABLE 4319L 39 | //! The group or resource is not in the correct state to perform the requested operation. 40 | #define RZRESULT_NOT_VALID_STATE 5023L 41 | //! No more items 42 | #define RZRESULT_NO_MORE_ITEMS 259L 43 | //! General failure. 44 | #define RZRESULT_FAILED 2147500037L 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /3rdparty/inc/SimpleIni/LICENCE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2006-2013 Brodie Thiesfield 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /3rdparty/inc/SimpleIni/README.md: -------------------------------------------------------------------------------- 1 | simpleini 2 | ========= 3 | 4 | A cross-platform library that provides a simple API to read and write INI-style configuration files. It supports data files in ASCII, MBCS and Unicode. It is designed explicitly to be portable to any platform and has been tested on Windows, WinCE and Linux. Released as open-source and free using the MIT licence. 5 | 6 | # Feature Summary 7 | 8 | - MIT Licence allows free use in all software (including GPL and commercial) 9 | - multi-platform (Windows 95/98/ME/NT/2K/XP/2003, Windows CE, Linux, Unix) 10 | - loading and saving of INI-style configuration files 11 | - configuration files can have any newline format on all platforms 12 | - liberal acceptance of file format 13 | * key/values with no section 14 | * removal of whitespace around sections, keys and values 15 | - support for multi-line values (values with embedded newline characters) 16 | - optional support for multiple keys with the same name 17 | - optional case-insensitive sections and keys (for ASCII characters only) 18 | - saves files with sections and keys in the same order as they were loaded 19 | - preserves comments on the file, section and keys where possible. 20 | - supports both char or wchar_t programming interfaces 21 | - supports both MBCS (system locale) and UTF-8 file encodings 22 | - system locale does not need to be UTF-8 on Linux/Unix to load UTF-8 file 23 | - support for non-ASCII characters in section, keys, values and comments 24 | - support for non-standard character types or file encodings via user-written converter classes 25 | - support for adding/modifying values programmatically 26 | - compiles cleanly in the following compilers: 27 | * Windows/VC6 (warning level 3) 28 | * Windows/VC.NET 2003 (warning level 4) 29 | * Windows/VC 2005 (warning level 4) 30 | * Linux/gcc (-Wall) 31 | * Windows/MinGW GCC 32 | 33 | # Documentation 34 | 35 | Full documentation of the interface is available in doxygen format. 36 | 37 | # Examples 38 | 39 | These snippets are included with the distribution in the file snippets.cpp. 40 | 41 | ### SIMPLE USAGE 42 | 43 | ```c++ 44 | CSimpleIniA ini; 45 | ini.SetUnicode(); 46 | ini.LoadFile("myfile.ini"); 47 | const char * pVal = ini.GetValue("section", "key", "default"); 48 | ini.SetValue("section", "key", "newvalue"); 49 | ``` 50 | 51 | ### LOADING DATA 52 | 53 | ```c++ 54 | // load from a data file 55 | CSimpleIniA ini(a_bIsUtf8, a_bUseMultiKey, a_bUseMultiLine); 56 | SI_Error rc = ini.LoadFile(a_pszFile); 57 | if (rc < 0) return false; 58 | 59 | // load from a string 60 | std::string strData; 61 | rc = ini.LoadData(strData.c_str(), strData.size()); 62 | if (rc < 0) return false; 63 | ``` 64 | 65 | ### GETTING SECTIONS AND KEYS 66 | 67 | ```c++ 68 | // get all sections 69 | CSimpleIniA::TNamesDepend sections; 70 | ini.GetAllSections(sections); 71 | 72 | // get all keys in a section 73 | CSimpleIniA::TNamesDepend keys; 74 | ini.GetAllKeys("section-name", keys); 75 | ``` 76 | 77 | ### GETTING VALUES 78 | 79 | ```c++ 80 | // get the value of a key 81 | const char * pszValue = ini.GetValue("section-name", 82 | "key-name", NULL /*default*/); 83 | 84 | // get the value of a key which may have multiple 85 | // values. If bHasMultipleValues is true, then just 86 | // one value has been returned 87 | bool bHasMultipleValues; 88 | pszValue = ini.GetValue("section-name", "key-name", 89 | NULL /*default*/, &bHasMultipleValues); 90 | 91 | // get all values of a key with multiple values 92 | CSimpleIniA::TNamesDepend values; 93 | ini.GetAllValues("section-name", "key-name", values); 94 | 95 | // sort the values into the original load order 96 | values.sort(CSimpleIniA::Entry::LoadOrder()); 97 | 98 | // output all of the items 99 | CSimpleIniA::TNamesDepend::const_iterator i; 100 | for (i = values.begin(); i != values.end(); ++i) { 101 | printf("key-name = '%s'\n", i->pItem); 102 | } 103 | ``` 104 | 105 | ### MODIFYING DATA 106 | 107 | ```c++ 108 | // adding a new section 109 | rc = ini.SetValue("new-section", NULL, NULL); 110 | if (rc < 0) return false; 111 | printf("section: %s\n", rc == SI_INSERTED ? 112 | "inserted" : "updated"); 113 | 114 | // adding a new key ("new-section" will be added 115 | // automatically if it doesn't already exist) 116 | rc = ini.SetValue("new-section", "new-key", "value"); 117 | if (rc < 0) return false; 118 | printf("key: %s\n", rc == SI_INSERTED ? 119 | "inserted" : "updated"); 120 | 121 | // changing the value of a key 122 | rc = ini.SetValue("section", "key", "updated-value"); 123 | if (rc < 0) return false; 124 | printf("key: %s\n", rc == SI_INSERTED ? 125 | "inserted" : "updated"); 126 | ``` 127 | 128 | ### DELETING DATA 129 | 130 | ```c++ 131 | // deleting a key from a section. Optionally the entire 132 | // section may be deleted if it is now empty. 133 | ini.Delete("section-name", "key-name", 134 | true /*delete the section if empty*/); 135 | 136 | // deleting an entire section and all keys in it 137 | ini.Delete("section-name", NULL); 138 | ``` 139 | 140 | ### SAVING DATA 141 | 142 | ```c++ 143 | // save the data to a string 144 | rc = ini.Save(strData); 145 | if (rc < 0) return false; 146 | 147 | // save the data back to the file 148 | rc = ini.SaveFile(a_pszFile); 149 | if (rc < 0) return false; 150 | ``` 151 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Gabi Melman. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/async_logger.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | // Very fast asynchronous logger (millions of logs per second on an average desktop) 9 | // Uses pre allocated lockfree queue for maximum throughput even under large number of threads. 10 | // Creates a single back thread to pop messages from the queue and log them. 11 | // 12 | // Upon each log write the logger: 13 | // 1. Checks if its log level is enough to log the message 14 | // 2. Push a new copy of the message to a queue (or block the caller until space is available in the queue) 15 | // 3. will throw spdlog_ex upon log exceptions 16 | // Upon destruction, logs all remaining messages in the queue before destructing.. 17 | 18 | #include "common.h" 19 | #include "logger.h" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | namespace spdlog 27 | { 28 | 29 | namespace details 30 | { 31 | class async_log_helper; 32 | } 33 | 34 | class async_logger SPDLOG_FINAL :public logger 35 | { 36 | public: 37 | template 38 | async_logger(const std::string& name, 39 | const It& begin, 40 | const It& end, 41 | size_t queue_size, 42 | const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, 43 | const std::function& worker_warmup_cb = nullptr, 44 | const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), 45 | const std::function& worker_teardown_cb = nullptr); 46 | 47 | async_logger(const std::string& logger_name, 48 | sinks_init_list sinks, 49 | size_t queue_size, 50 | const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, 51 | const std::function& worker_warmup_cb = nullptr, 52 | const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), 53 | const std::function& worker_teardown_cb = nullptr); 54 | 55 | async_logger(const std::string& logger_name, 56 | sink_ptr single_sink, 57 | size_t queue_size, 58 | const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, 59 | const std::function& worker_warmup_cb = nullptr, 60 | const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), 61 | const std::function& worker_teardown_cb = nullptr); 62 | 63 | //Wait for the queue to be empty, and flush synchronously 64 | //Warning: this can potentially last forever as we wait it to complete 65 | void flush() override; 66 | 67 | // Error handler 68 | virtual void set_error_handler(log_err_handler) override; 69 | virtual log_err_handler error_handler() override; 70 | 71 | protected: 72 | void _sink_it(details::log_msg& msg) override; 73 | void _set_formatter(spdlog::formatter_ptr msg_formatter) override; 74 | void _set_pattern(const std::string& pattern, pattern_time_type pattern_time) override; 75 | 76 | private: 77 | std::unique_ptr _async_log_helper; 78 | }; 79 | } 80 | 81 | 82 | #include "details/async_logger_impl.h" 83 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/common.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) 17 | #include 18 | #include 19 | #endif 20 | 21 | #include "details/null_mutex.h" 22 | 23 | //visual studio upto 2013 does not support noexcept nor constexpr 24 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 25 | #define SPDLOG_NOEXCEPT throw() 26 | #define SPDLOG_CONSTEXPR 27 | #else 28 | #define SPDLOG_NOEXCEPT noexcept 29 | #define SPDLOG_CONSTEXPR constexpr 30 | #endif 31 | 32 | // final keyword support. On by default. See tweakme.h 33 | #if defined(SPDLOG_NO_FINAL) 34 | #define SPDLOG_FINAL 35 | #else 36 | #define SPDLOG_FINAL final 37 | #endif 38 | 39 | #if defined(__GNUC__) || defined(__clang__) 40 | #define SPDLOG_DEPRECATED __attribute__((deprecated)) 41 | #elif defined(_MSC_VER) 42 | #define SPDLOG_DEPRECATED __declspec(deprecated) 43 | #else 44 | #define SPDLOG_DEPRECATED 45 | #endif 46 | 47 | #include "fmt/fmt.h" 48 | 49 | namespace spdlog 50 | { 51 | 52 | class formatter; 53 | 54 | namespace sinks 55 | { 56 | class sink; 57 | } 58 | 59 | using log_clock = std::chrono::system_clock; 60 | using sink_ptr = std::shared_ptr < sinks::sink >; 61 | using sinks_init_list = std::initializer_list < sink_ptr >; 62 | using formatter_ptr = std::shared_ptr; 63 | #if defined(SPDLOG_NO_ATOMIC_LEVELS) 64 | using level_t = details::null_atomic_int; 65 | #else 66 | using level_t = std::atomic; 67 | #endif 68 | 69 | using log_err_handler = std::function; 70 | 71 | //Log level enum 72 | namespace level 73 | { 74 | typedef enum 75 | { 76 | trace = 0, 77 | debug = 1, 78 | info = 2, 79 | warn = 3, 80 | err = 4, 81 | critical = 5, 82 | off = 6 83 | } level_enum; 84 | 85 | #if !defined(SPDLOG_LEVEL_NAMES) 86 | #define SPDLOG_LEVEL_NAMES { "trace", "debug", "info", "warning", "error", "critical", "off" } 87 | #endif 88 | static const char* level_names[] SPDLOG_LEVEL_NAMES; 89 | 90 | static const char* short_level_names[] { "T", "D", "I", "W", "E", "C", "O" }; 91 | 92 | inline const char* to_str(spdlog::level::level_enum l) 93 | { 94 | return level_names[l]; 95 | } 96 | 97 | inline const char* to_short_str(spdlog::level::level_enum l) 98 | { 99 | return short_level_names[l]; 100 | } 101 | } //level 102 | 103 | 104 | // 105 | // Async overflow policy - block by default. 106 | // 107 | enum class async_overflow_policy 108 | { 109 | block_retry, // Block / yield / sleep until message can be enqueued 110 | discard_log_msg // Discard the message it enqueue fails 111 | }; 112 | 113 | // 114 | // Pattern time - specific time getting to use for pattern_formatter. 115 | // local time by default 116 | // 117 | enum class pattern_time_type 118 | { 119 | local, // log localtime 120 | utc // log utc 121 | }; 122 | 123 | // 124 | // Log exception 125 | // 126 | namespace details 127 | { 128 | namespace os 129 | { 130 | std::string errno_str(int err_num); 131 | } 132 | } 133 | class spdlog_ex: public std::exception 134 | { 135 | public: 136 | spdlog_ex(const std::string& msg):_msg(msg) 137 | {} 138 | spdlog_ex(const std::string& msg, int last_errno) 139 | { 140 | _msg = msg + ": " + details::os::errno_str(last_errno); 141 | } 142 | const char* what() const SPDLOG_NOEXCEPT override 143 | { 144 | return _msg.c_str(); 145 | } 146 | private: 147 | std::string _msg; 148 | 149 | }; 150 | 151 | // 152 | // wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined) 153 | // 154 | #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) 155 | using filename_t = std::wstring; 156 | #else 157 | using filename_t = std::string; 158 | #endif 159 | 160 | 161 | } //spdlog 162 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/details/async_logger_impl.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | // Async Logger implementation 9 | // Use an async_sink (queue per logger) to perform the logging in a worker thread 10 | 11 | #include "../details/async_log_helper.h" 12 | #include "../async_logger.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | template 20 | inline spdlog::async_logger::async_logger(const std::string& logger_name, 21 | const It& begin, 22 | const It& end, 23 | size_t queue_size, 24 | const async_overflow_policy overflow_policy, 25 | const std::function& worker_warmup_cb, 26 | const std::chrono::milliseconds& flush_interval_ms, 27 | const std::function& worker_teardown_cb) : 28 | logger(logger_name, begin, end), 29 | _async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, _err_handler, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb)) 30 | { 31 | } 32 | 33 | inline spdlog::async_logger::async_logger(const std::string& logger_name, 34 | sinks_init_list sinks_list, 35 | size_t queue_size, 36 | const async_overflow_policy overflow_policy, 37 | const std::function& worker_warmup_cb, 38 | const std::chrono::milliseconds& flush_interval_ms, 39 | const std::function& worker_teardown_cb) : 40 | async_logger(logger_name, sinks_list.begin(), sinks_list.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {} 41 | 42 | inline spdlog::async_logger::async_logger(const std::string& logger_name, 43 | sink_ptr single_sink, 44 | size_t queue_size, 45 | const async_overflow_policy overflow_policy, 46 | const std::function& worker_warmup_cb, 47 | const std::chrono::milliseconds& flush_interval_ms, 48 | const std::function& worker_teardown_cb) : 49 | async_logger(logger_name, 50 | { 51 | single_sink 52 | }, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {} 53 | 54 | 55 | inline void spdlog::async_logger::flush() 56 | { 57 | _async_log_helper->flush(true); 58 | } 59 | 60 | // Error handler 61 | inline void spdlog::async_logger::set_error_handler(spdlog::log_err_handler err_handler) 62 | { 63 | _err_handler = err_handler; 64 | _async_log_helper->set_error_handler(err_handler); 65 | 66 | } 67 | inline spdlog::log_err_handler spdlog::async_logger::error_handler() 68 | { 69 | return _err_handler; 70 | } 71 | 72 | 73 | inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter) 74 | { 75 | _formatter = msg_formatter; 76 | _async_log_helper->set_formatter(_formatter); 77 | } 78 | 79 | inline void spdlog::async_logger::_set_pattern(const std::string& pattern, pattern_time_type pattern_time) 80 | { 81 | _formatter = std::make_shared(pattern, pattern_time); 82 | _async_log_helper->set_formatter(_formatter); 83 | } 84 | 85 | 86 | inline void spdlog::async_logger::_sink_it(details::log_msg& msg) 87 | { 88 | try 89 | { 90 | #if defined(SPDLOG_ENABLE_MESSAGE_COUNTER) 91 | _incr_msg_counter(msg); 92 | #endif 93 | _async_log_helper->log(msg); 94 | if (_should_flush_on(msg)) 95 | _async_log_helper->flush(false); // do async flush 96 | } 97 | catch (const std::exception &ex) 98 | { 99 | _err_handler(ex.what()); 100 | } 101 | catch(...) 102 | { 103 | _err_handler("Unknown exception in logger " + _name); 104 | throw; 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/details/file_helper.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | // Helper class for file sink 9 | // When failing to open a file, retry several times(5) with small delay between the tries(10 ms) 10 | // Throw spdlog_ex exception on errors 11 | 12 | #include "../details/os.h" 13 | #include "../details/log_msg.h" 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace spdlog 23 | { 24 | namespace details 25 | { 26 | 27 | class file_helper 28 | { 29 | 30 | public: 31 | const int open_tries = 5; 32 | const int open_interval = 10; 33 | 34 | explicit file_helper() : 35 | _fd(nullptr) 36 | {} 37 | 38 | file_helper(const file_helper&) = delete; 39 | file_helper& operator=(const file_helper&) = delete; 40 | 41 | ~file_helper() 42 | { 43 | close(); 44 | } 45 | 46 | 47 | void open(const filename_t& fname, bool truncate = false) 48 | { 49 | 50 | close(); 51 | auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab"); 52 | _filename = fname; 53 | for (int tries = 0; tries < open_tries; ++tries) 54 | { 55 | if (!os::fopen_s(&_fd, fname, mode)) 56 | return; 57 | 58 | std::this_thread::sleep_for(std::chrono::milliseconds(open_interval)); 59 | } 60 | 61 | throw spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + " for writing", errno); 62 | } 63 | 64 | void reopen(bool truncate) 65 | { 66 | if (_filename.empty()) 67 | throw spdlog_ex("Failed re opening file - was not opened before"); 68 | open(_filename, truncate); 69 | 70 | } 71 | 72 | void flush() 73 | { 74 | std::fflush(_fd); 75 | } 76 | 77 | void close() 78 | { 79 | if (_fd) 80 | { 81 | std::fclose(_fd); 82 | _fd = nullptr; 83 | } 84 | } 85 | 86 | void write(const log_msg& msg) 87 | { 88 | size_t msg_size = msg.formatted.size(); 89 | auto data = msg.formatted.data(); 90 | if (std::fwrite(data, 1, msg_size, _fd) != msg_size) 91 | throw spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno); 92 | } 93 | 94 | size_t size() const 95 | { 96 | if (!_fd) 97 | throw spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename)); 98 | return os::filesize(_fd); 99 | } 100 | 101 | const filename_t& filename() const 102 | { 103 | return _filename; 104 | } 105 | 106 | static bool file_exists(const filename_t& fname) 107 | { 108 | return os::file_exists(fname); 109 | } 110 | 111 | // 112 | // return basename and extension: 113 | // 114 | // "mylog.txt" => ("mylog", ".txt") 115 | // "mylog" => ("mylog", "") 116 | // 117 | // the starting dot in filenames is ignored (hidden files): 118 | // 119 | // "my_folder/.mylog" => ("my_folder/.mylog") 120 | // "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt") 121 | 122 | static std::tuple split_by_extenstion(const filename_t& fname) 123 | { 124 | auto index = fname.rfind('.'); 125 | bool found_ext = index != filename_t::npos && index !=0 && fname[index - 1] != details::os::folder_sep; 126 | if (found_ext) 127 | return std::make_tuple(fname.substr(0, index), fname.substr(index)); 128 | else 129 | return std::make_tuple(fname, filename_t()); 130 | } 131 | 132 | private: 133 | FILE* _fd; 134 | filename_t _filename; 135 | }; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/details/log_msg.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #include "../common.h" 9 | #include "../details/os.h" 10 | 11 | 12 | #include 13 | #include 14 | 15 | namespace spdlog 16 | { 17 | namespace details 18 | { 19 | struct log_msg 20 | { 21 | log_msg() = default; 22 | log_msg(const std::string *loggers_name, level::level_enum lvl) : 23 | logger_name(loggers_name), 24 | level(lvl), 25 | msg_id(0) 26 | { 27 | #ifndef SPDLOG_NO_DATETIME 28 | time = os::now(); 29 | #endif 30 | 31 | #ifndef SPDLOG_NO_THREAD_ID 32 | thread_id = os::thread_id(); 33 | #endif 34 | } 35 | 36 | log_msg(const log_msg& other) = delete; 37 | log_msg& operator=(log_msg&& other) = delete; 38 | log_msg(log_msg&& other) = delete; 39 | 40 | 41 | const std::string *logger_name; 42 | level::level_enum level; 43 | log_clock::time_point time; 44 | size_t thread_id; 45 | fmt::MemoryWriter raw; 46 | fmt::MemoryWriter formatted; 47 | size_t msg_id; 48 | }; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/details/mpmc_bounded_q.h: -------------------------------------------------------------------------------- 1 | /* 2 | A modified version of Bounded MPMC queue by Dmitry Vyukov. 3 | 4 | Original code from: 5 | http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue 6 | 7 | licensed by Dmitry Vyukov under the terms below: 8 | 9 | Simplified BSD license 10 | 11 | Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved. 12 | Redistribution and use in source and binary forms, with or without modification, 13 | are permitted provided that the following conditions are met: 14 | 1. Redistributions of source code must retain the above copyright notice, this list of 15 | conditions and the following disclaimer. 16 | 17 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 18 | of conditions and the following disclaimer in the documentation and/or other materials 19 | provided with the distribution. 20 | 21 | THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED 22 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 23 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 24 | SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 27 | OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 29 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | The views and conclusions contained in the software and documentation are those of the authors and 33 | should not be interpreted as representing official policies, either expressed or implied, of Dmitry Vyukov. 34 | */ 35 | 36 | /* 37 | The code in its current form adds the license below: 38 | 39 | Copyright(c) 2015 Gabi Melman. 40 | Distributed under the MIT License (http://opensource.org/licenses/MIT) 41 | 42 | */ 43 | 44 | #pragma once 45 | 46 | #include "../common.h" 47 | 48 | #include 49 | #include 50 | 51 | namespace spdlog 52 | { 53 | namespace details 54 | { 55 | 56 | template 57 | class mpmc_bounded_queue 58 | { 59 | public: 60 | 61 | using item_type = T; 62 | mpmc_bounded_queue(size_t buffer_size) 63 | :max_size_(buffer_size), 64 | buffer_(new cell_t[buffer_size]), 65 | buffer_mask_(buffer_size - 1) 66 | { 67 | //queue size must be power of two 68 | if (!((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0))) 69 | throw spdlog_ex("async logger queue size must be power of two"); 70 | 71 | for (size_t i = 0; i != buffer_size; i += 1) 72 | buffer_[i].sequence_.store(i, std::memory_order_relaxed); 73 | enqueue_pos_.store(0, std::memory_order_relaxed); 74 | dequeue_pos_.store(0, std::memory_order_relaxed); 75 | } 76 | 77 | ~mpmc_bounded_queue() 78 | { 79 | delete[] buffer_; 80 | } 81 | 82 | 83 | bool enqueue(T&& data) 84 | { 85 | cell_t* cell; 86 | size_t pos = enqueue_pos_.load(std::memory_order_relaxed); 87 | for (;;) 88 | { 89 | cell = &buffer_[pos & buffer_mask_]; 90 | size_t seq = cell->sequence_.load(std::memory_order_acquire); 91 | intptr_t dif = static_cast(seq) - static_cast(pos); 92 | if (dif == 0) 93 | { 94 | if (enqueue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed)) 95 | break; 96 | } 97 | else if (dif < 0) 98 | { 99 | return false; 100 | } 101 | else 102 | { 103 | pos = enqueue_pos_.load(std::memory_order_relaxed); 104 | } 105 | } 106 | cell->data_ = std::move(data); 107 | cell->sequence_.store(pos + 1, std::memory_order_release); 108 | return true; 109 | } 110 | 111 | bool dequeue(T& data) 112 | { 113 | cell_t* cell; 114 | size_t pos = dequeue_pos_.load(std::memory_order_relaxed); 115 | for (;;) 116 | { 117 | cell = &buffer_[pos & buffer_mask_]; 118 | size_t seq = 119 | cell->sequence_.load(std::memory_order_acquire); 120 | intptr_t dif = static_cast(seq) - static_cast(pos + 1); 121 | if (dif == 0) 122 | { 123 | if (dequeue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed)) 124 | break; 125 | } 126 | else if (dif < 0) 127 | return false; 128 | else 129 | pos = dequeue_pos_.load(std::memory_order_relaxed); 130 | } 131 | data = std::move(cell->data_); 132 | cell->sequence_.store(pos + buffer_mask_ + 1, std::memory_order_release); 133 | return true; 134 | } 135 | 136 | bool is_empty() 137 | { 138 | size_t front, front1, back; 139 | // try to take a consistent snapshot of front/tail. 140 | do 141 | { 142 | front = enqueue_pos_.load(std::memory_order_acquire); 143 | back = dequeue_pos_.load(std::memory_order_acquire); 144 | front1 = enqueue_pos_.load(std::memory_order_relaxed); 145 | } 146 | while (front != front1); 147 | return back == front; 148 | } 149 | 150 | private: 151 | struct cell_t 152 | { 153 | std::atomic sequence_; 154 | T data_; 155 | }; 156 | 157 | size_t const max_size_; 158 | 159 | static size_t const cacheline_size = 64; 160 | typedef char cacheline_pad_t[cacheline_size]; 161 | 162 | cacheline_pad_t pad0_; 163 | cell_t* const buffer_; 164 | size_t const buffer_mask_; 165 | cacheline_pad_t pad1_; 166 | std::atomic enqueue_pos_; 167 | cacheline_pad_t pad2_; 168 | std::atomic dequeue_pos_; 169 | cacheline_pad_t pad3_; 170 | 171 | mpmc_bounded_queue(mpmc_bounded_queue const&) = delete; 172 | void operator= (mpmc_bounded_queue const&) = delete; 173 | }; 174 | 175 | } // ns details 176 | } // ns spdlog 177 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/details/null_mutex.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #include 9 | // null, no cost dummy "mutex" and dummy "atomic" int 10 | 11 | namespace spdlog 12 | { 13 | namespace details 14 | { 15 | struct null_mutex 16 | { 17 | void lock() {} 18 | void unlock() {} 19 | bool try_lock() 20 | { 21 | return true; 22 | } 23 | }; 24 | 25 | struct null_atomic_int 26 | { 27 | int value; 28 | null_atomic_int() = default; 29 | 30 | null_atomic_int(int val):value(val) 31 | {} 32 | 33 | int load(std::memory_order) const 34 | { 35 | return value; 36 | } 37 | 38 | void store(int val) 39 | { 40 | value = val; 41 | } 42 | }; 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/details/registry.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | // Loggers registy of unique name->logger pointer 9 | // An attempt to create a logger with an already existing name will be ignored 10 | // If user requests a non existing logger, nullptr will be returned 11 | // This class is thread safe 12 | 13 | #include "../details/null_mutex.h" 14 | #include "../logger.h" 15 | #include "../async_logger.h" 16 | #include "../common.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace spdlog 26 | { 27 | namespace details 28 | { 29 | template class registry_t 30 | { 31 | public: 32 | 33 | void register_logger(std::shared_ptr logger) 34 | { 35 | std::lock_guard lock(_mutex); 36 | auto logger_name = logger->name(); 37 | throw_if_exists(logger_name); 38 | _loggers[logger_name] = logger; 39 | } 40 | 41 | 42 | std::shared_ptr get(const std::string& logger_name) 43 | { 44 | std::lock_guard lock(_mutex); 45 | auto found = _loggers.find(logger_name); 46 | return found == _loggers.end() ? nullptr : found->second; 47 | } 48 | 49 | template 50 | std::shared_ptr create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end) 51 | { 52 | std::lock_guard lock(_mutex); 53 | throw_if_exists(logger_name); 54 | std::shared_ptr new_logger; 55 | if (_async_mode) 56 | new_logger = std::make_shared(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms, _worker_teardown_cb); 57 | else 58 | new_logger = std::make_shared(logger_name, sinks_begin, sinks_end); 59 | 60 | if (_formatter) 61 | new_logger->set_formatter(_formatter); 62 | 63 | if (_err_handler) 64 | new_logger->set_error_handler(_err_handler); 65 | 66 | new_logger->set_level(_level); 67 | 68 | 69 | //Add to registry 70 | _loggers[logger_name] = new_logger; 71 | return new_logger; 72 | } 73 | 74 | template 75 | std::shared_ptr create_async(const std::string& logger_name, size_t queue_size, const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function& worker_teardown_cb, const It& sinks_begin, const It& sinks_end) 76 | { 77 | std::lock_guard lock(_mutex); 78 | throw_if_exists(logger_name); 79 | auto new_logger = std::make_shared(logger_name, sinks_begin, sinks_end, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb); 80 | 81 | if (_formatter) 82 | new_logger->set_formatter(_formatter); 83 | 84 | if (_err_handler) 85 | new_logger->set_error_handler(_err_handler); 86 | 87 | new_logger->set_level(_level); 88 | 89 | //Add to registry 90 | _loggers[logger_name] = new_logger; 91 | return new_logger; 92 | } 93 | 94 | void apply_all(std::function)> fun) 95 | { 96 | std::lock_guard lock(_mutex); 97 | for (auto &l : _loggers) 98 | fun(l.second); 99 | } 100 | 101 | void drop(const std::string& logger_name) 102 | { 103 | std::lock_guard lock(_mutex); 104 | _loggers.erase(logger_name); 105 | } 106 | 107 | void drop_all() 108 | { 109 | std::lock_guard lock(_mutex); 110 | _loggers.clear(); 111 | } 112 | std::shared_ptr create(const std::string& logger_name, sinks_init_list sinks) 113 | { 114 | return create(logger_name, sinks.begin(), sinks.end()); 115 | } 116 | 117 | std::shared_ptr create(const std::string& logger_name, sink_ptr sink) 118 | { 119 | return create(logger_name, { sink }); 120 | } 121 | 122 | std::shared_ptr create_async(const std::string& logger_name, size_t queue_size, const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function& worker_teardown_cb, sinks_init_list sinks) 123 | { 124 | return create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks.begin(), sinks.end()); 125 | } 126 | 127 | std::shared_ptr create_async(const std::string& logger_name, size_t queue_size, const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function& worker_teardown_cb, sink_ptr sink) 128 | { 129 | return create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, { sink }); 130 | } 131 | 132 | void formatter(formatter_ptr f) 133 | { 134 | std::lock_guard lock(_mutex); 135 | _formatter = f; 136 | for (auto& l : _loggers) 137 | l.second->set_formatter(_formatter); 138 | } 139 | 140 | void set_pattern(const std::string& pattern) 141 | { 142 | std::lock_guard lock(_mutex); 143 | _formatter = std::make_shared(pattern); 144 | for (auto& l : _loggers) 145 | l.second->set_formatter(_formatter); 146 | } 147 | 148 | void set_level(level::level_enum log_level) 149 | { 150 | std::lock_guard lock(_mutex); 151 | for (auto& l : _loggers) 152 | l.second->set_level(log_level); 153 | _level = log_level; 154 | } 155 | 156 | void set_error_handler(log_err_handler handler) 157 | { 158 | for (auto& l : _loggers) 159 | l.second->set_error_handler(handler); 160 | _err_handler = handler; 161 | } 162 | 163 | void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function& worker_teardown_cb) 164 | { 165 | std::lock_guard lock(_mutex); 166 | _async_mode = true; 167 | _async_q_size = q_size; 168 | _overflow_policy = overflow_policy; 169 | _worker_warmup_cb = worker_warmup_cb; 170 | _flush_interval_ms = flush_interval_ms; 171 | _worker_teardown_cb = worker_teardown_cb; 172 | } 173 | 174 | void set_sync_mode() 175 | { 176 | std::lock_guard lock(_mutex); 177 | _async_mode = false; 178 | } 179 | 180 | static registry_t& instance() 181 | { 182 | static registry_t s_instance; 183 | return s_instance; 184 | } 185 | 186 | private: 187 | registry_t() {} 188 | registry_t(const registry_t&) = delete; 189 | registry_t& operator=(const registry_t&) = delete; 190 | 191 | void throw_if_exists(const std::string &logger_name) 192 | { 193 | if (_loggers.find(logger_name) != _loggers.end()) 194 | throw spdlog_ex("logger with name '" + logger_name + "' already exists"); 195 | } 196 | Mutex _mutex; 197 | std::unordered_map > _loggers; 198 | formatter_ptr _formatter; 199 | level::level_enum _level = level::info; 200 | log_err_handler _err_handler; 201 | bool _async_mode = false; 202 | size_t _async_q_size = 0; 203 | async_overflow_policy _overflow_policy = async_overflow_policy::block_retry; 204 | std::function _worker_warmup_cb = nullptr; 205 | std::chrono::milliseconds _flush_interval_ms; 206 | std::function _worker_teardown_cb = nullptr; 207 | }; 208 | #ifdef SPDLOG_NO_REGISTRY_MUTEX 209 | typedef registry_t registry; 210 | #else 211 | typedef registry_t registry; 212 | #endif 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/fmt/bundled/LICENSE.rst: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 - 2016, Victor Zverovich 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/fmt/bundled/ostream.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Formatting library for C++ - std::ostream support 3 | 4 | Copyright (c) 2012 - 2016, Victor Zverovich 5 | All rights reserved. 6 | 7 | For the license information refer to format.h. 8 | */ 9 | 10 | #include "ostream.h" 11 | 12 | namespace fmt { 13 | 14 | namespace internal { 15 | FMT_FUNC void write(std::ostream &os, Writer &w) { 16 | const char *data = w.data(); 17 | typedef internal::MakeUnsigned::Type UnsignedStreamSize; 18 | UnsignedStreamSize size = w.size(); 19 | UnsignedStreamSize max_size = 20 | internal::to_unsigned((std::numeric_limits::max)()); 21 | do { 22 | UnsignedStreamSize n = size <= max_size ? size : max_size; 23 | os.write(data, static_cast(n)); 24 | data += n; 25 | size -= n; 26 | } while (size != 0); 27 | } 28 | } 29 | 30 | FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) { 31 | MemoryWriter w; 32 | w.write(format_str, args); 33 | internal::write(os, w); 34 | } 35 | } // namespace fmt 36 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/fmt/bundled/ostream.h: -------------------------------------------------------------------------------- 1 | /* 2 | Formatting library for C++ - std::ostream support 3 | 4 | Copyright (c) 2012 - 2016, Victor Zverovich 5 | All rights reserved. 6 | 7 | For the license information refer to format.h. 8 | */ 9 | 10 | #ifndef FMT_OSTREAM_H_ 11 | #define FMT_OSTREAM_H_ 12 | 13 | #include "format.h" 14 | #include 15 | 16 | namespace fmt 17 | { 18 | 19 | namespace internal 20 | { 21 | 22 | template 23 | class FormatBuf : public std::basic_streambuf 24 | { 25 | private: 26 | typedef typename std::basic_streambuf::int_type int_type; 27 | typedef typename std::basic_streambuf::traits_type traits_type; 28 | 29 | Buffer &buffer_; 30 | 31 | public: 32 | FormatBuf(Buffer &buffer) : buffer_(buffer) {} 33 | 34 | protected: 35 | // The put-area is actually always empty. This makes the implementation 36 | // simpler and has the advantage that the streambuf and the buffer are always 37 | // in sync and sputc never writes into uninitialized memory. The obvious 38 | // disadvantage is that each call to sputc always results in a (virtual) call 39 | // to overflow. There is no disadvantage here for sputn since this always 40 | // results in a call to xsputn. 41 | 42 | int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE 43 | { 44 | if (!traits_type::eq_int_type(ch, traits_type::eof())) 45 | buffer_.push_back(static_cast(ch)); 46 | return ch; 47 | } 48 | 49 | std::streamsize xsputn(const Char *s, std::streamsize count) FMT_OVERRIDE 50 | { 51 | buffer_.append(s, s + count); 52 | return count; 53 | } 54 | }; 55 | 56 | Yes &convert(std::ostream &); 57 | 58 | struct DummyStream : std::ostream 59 | { 60 | DummyStream(); // Suppress a bogus warning in MSVC. 61 | // Hide all operator<< overloads from std::ostream. 62 | void operator<<(Null<>); 63 | }; 64 | 65 | No &operator<<(std::ostream &, int); 66 | 67 | template 68 | struct ConvertToIntImpl 69 | { 70 | // Convert to int only if T doesn't have an overloaded operator<<. 71 | enum 72 | { 73 | value = sizeof(convert(get() << get())) == sizeof(No) 74 | }; 75 | }; 76 | 77 | // Write the content of w to os. 78 | FMT_API void write(std::ostream &os, Writer &w); 79 | } // namespace internal 80 | 81 | // Formats a value. 82 | template 83 | void format_arg(BasicFormatter &f, 84 | const Char *&format_str, const T &value) 85 | { 86 | internal::MemoryBuffer buffer; 87 | 88 | internal::FormatBuf format_buf(buffer); 89 | std::basic_ostream output(&format_buf); 90 | output << value; 91 | 92 | BasicStringRef str(&buffer[0], buffer.size()); 93 | typedef internal::MakeArg< BasicFormatter > MakeArg; 94 | format_str = f.format(format_str, MakeArg(str)); 95 | } 96 | 97 | /** 98 | \rst 99 | Prints formatted data to the stream *os*. 100 | 101 | **Example**:: 102 | 103 | print(cerr, "Don't {}!", "panic"); 104 | \endrst 105 | */ 106 | FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args); 107 | FMT_VARIADIC(void, print, std::ostream &, CStringRef) 108 | } // namespace fmt 109 | 110 | #ifdef FMT_HEADER_ONLY 111 | # include "ostream.cc" 112 | #endif 113 | 114 | #endif // FMT_OSTREAM_H_ 115 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/fmt/bundled/posix.cc: -------------------------------------------------------------------------------- 1 | /* 2 | A C++ interface to POSIX functions. 3 | 4 | Copyright (c) 2012 - 2016, Victor Zverovich 5 | All rights reserved. 6 | 7 | For the license information refer to format.h. 8 | */ 9 | 10 | // Disable bogus MSVC warnings. 11 | #ifndef _CRT_SECURE_NO_WARNINGS 12 | # define _CRT_SECURE_NO_WARNINGS 13 | #endif 14 | 15 | #include "posix.h" 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #ifndef _WIN32 22 | # include 23 | #else 24 | # ifndef WIN32_LEAN_AND_MEAN 25 | # define WIN32_LEAN_AND_MEAN 26 | # endif 27 | # include 28 | # include 29 | 30 | # define O_CREAT _O_CREAT 31 | # define O_TRUNC _O_TRUNC 32 | 33 | # ifndef S_IRUSR 34 | # define S_IRUSR _S_IREAD 35 | # endif 36 | 37 | # ifndef S_IWUSR 38 | # define S_IWUSR _S_IWRITE 39 | # endif 40 | 41 | # ifdef __MINGW32__ 42 | # define _SH_DENYNO 0x40 43 | # endif 44 | 45 | #endif // _WIN32 46 | 47 | #ifdef fileno 48 | # undef fileno 49 | #endif 50 | 51 | namespace { 52 | #ifdef _WIN32 53 | // Return type of read and write functions. 54 | typedef int RWResult; 55 | 56 | // On Windows the count argument to read and write is unsigned, so convert 57 | // it from size_t preventing integer overflow. 58 | inline unsigned convert_rwcount(std::size_t count) { 59 | return count <= UINT_MAX ? static_cast(count) : UINT_MAX; 60 | } 61 | #else 62 | // Return type of read and write functions. 63 | typedef ssize_t RWResult; 64 | 65 | inline std::size_t convert_rwcount(std::size_t count) { return count; } 66 | #endif 67 | } 68 | 69 | fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT { 70 | if (file_ && FMT_SYSTEM(fclose(file_)) != 0) 71 | fmt::report_system_error(errno, "cannot close file"); 72 | } 73 | 74 | fmt::BufferedFile::BufferedFile( 75 | fmt::CStringRef filename, fmt::CStringRef mode) { 76 | FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0); 77 | if (!file_) 78 | FMT_THROW(SystemError(errno, "cannot open file {}", filename)); 79 | } 80 | 81 | void fmt::BufferedFile::close() { 82 | if (!file_) 83 | return; 84 | int result = FMT_SYSTEM(fclose(file_)); 85 | file_ = FMT_NULL; 86 | if (result != 0) 87 | FMT_THROW(SystemError(errno, "cannot close file")); 88 | } 89 | 90 | // A macro used to prevent expansion of fileno on broken versions of MinGW. 91 | #define FMT_ARGS 92 | 93 | int fmt::BufferedFile::fileno() const { 94 | int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_)); 95 | if (fd == -1) 96 | FMT_THROW(SystemError(errno, "cannot get file descriptor")); 97 | return fd; 98 | } 99 | 100 | fmt::File::File(fmt::CStringRef path, int oflag) { 101 | int mode = S_IRUSR | S_IWUSR; 102 | #if defined(_WIN32) && !defined(__MINGW32__) 103 | fd_ = -1; 104 | FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode)); 105 | #else 106 | FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode))); 107 | #endif 108 | if (fd_ == -1) 109 | FMT_THROW(SystemError(errno, "cannot open file {}", path)); 110 | } 111 | 112 | fmt::File::~File() FMT_NOEXCEPT { 113 | // Don't retry close in case of EINTR! 114 | // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html 115 | if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0) 116 | fmt::report_system_error(errno, "cannot close file"); 117 | } 118 | 119 | void fmt::File::close() { 120 | if (fd_ == -1) 121 | return; 122 | // Don't retry close in case of EINTR! 123 | // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html 124 | int result = FMT_POSIX_CALL(close(fd_)); 125 | fd_ = -1; 126 | if (result != 0) 127 | FMT_THROW(SystemError(errno, "cannot close file")); 128 | } 129 | 130 | fmt::LongLong fmt::File::size() const { 131 | #ifdef _WIN32 132 | // Use GetFileSize instead of GetFileSizeEx for the case when _WIN32_WINNT 133 | // is less than 0x0500 as is the case with some default MinGW builds. 134 | // Both functions support large file sizes. 135 | DWORD size_upper = 0; 136 | HANDLE handle = reinterpret_cast(_get_osfhandle(fd_)); 137 | DWORD size_lower = FMT_SYSTEM(GetFileSize(handle, &size_upper)); 138 | if (size_lower == INVALID_FILE_SIZE) { 139 | DWORD error = GetLastError(); 140 | if (error != NO_ERROR) 141 | FMT_THROW(WindowsError(GetLastError(), "cannot get file size")); 142 | } 143 | fmt::ULongLong long_size = size_upper; 144 | return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower; 145 | #else 146 | typedef struct stat Stat; 147 | Stat file_stat = Stat(); 148 | if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1) 149 | FMT_THROW(SystemError(errno, "cannot get file attributes")); 150 | FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(file_stat.st_size), 151 | "return type of File::size is not large enough"); 152 | return file_stat.st_size; 153 | #endif 154 | } 155 | 156 | std::size_t fmt::File::read(void *buffer, std::size_t count) { 157 | RWResult result = 0; 158 | FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count)))); 159 | if (result < 0) 160 | FMT_THROW(SystemError(errno, "cannot read from file")); 161 | return internal::to_unsigned(result); 162 | } 163 | 164 | std::size_t fmt::File::write(const void *buffer, std::size_t count) { 165 | RWResult result = 0; 166 | FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count)))); 167 | if (result < 0) 168 | FMT_THROW(SystemError(errno, "cannot write to file")); 169 | return internal::to_unsigned(result); 170 | } 171 | 172 | fmt::File fmt::File::dup(int fd) { 173 | // Don't retry as dup doesn't return EINTR. 174 | // http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html 175 | int new_fd = FMT_POSIX_CALL(dup(fd)); 176 | if (new_fd == -1) 177 | FMT_THROW(SystemError(errno, "cannot duplicate file descriptor {}", fd)); 178 | return File(new_fd); 179 | } 180 | 181 | void fmt::File::dup2(int fd) { 182 | int result = 0; 183 | FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd))); 184 | if (result == -1) { 185 | FMT_THROW(SystemError(errno, 186 | "cannot duplicate file descriptor {} to {}", fd_, fd)); 187 | } 188 | } 189 | 190 | void fmt::File::dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT { 191 | int result = 0; 192 | FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd))); 193 | if (result == -1) 194 | ec = ErrorCode(errno); 195 | } 196 | 197 | void fmt::File::pipe(File &read_end, File &write_end) { 198 | // Close the descriptors first to make sure that assignments don't throw 199 | // and there are no leaks. 200 | read_end.close(); 201 | write_end.close(); 202 | int fds[2] = {}; 203 | #ifdef _WIN32 204 | // Make the default pipe capacity same as on Linux 2.6.11+. 205 | enum { DEFAULT_CAPACITY = 65536 }; 206 | int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY)); 207 | #else 208 | // Don't retry as the pipe function doesn't return EINTR. 209 | // http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html 210 | int result = FMT_POSIX_CALL(pipe(fds)); 211 | #endif 212 | if (result != 0) 213 | FMT_THROW(SystemError(errno, "cannot create pipe")); 214 | // The following assignments don't throw because read_fd and write_fd 215 | // are closed. 216 | read_end = File(fds[0]); 217 | write_end = File(fds[1]); 218 | } 219 | 220 | fmt::BufferedFile fmt::File::fdopen(const char *mode) { 221 | // Don't retry as fdopen doesn't return EINTR. 222 | FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode)); 223 | if (!f) 224 | FMT_THROW(SystemError(errno, "cannot associate stream with file descriptor")); 225 | BufferedFile file(f); 226 | fd_ = -1; 227 | return file; 228 | } 229 | 230 | long fmt::getpagesize() { 231 | #ifdef _WIN32 232 | SYSTEM_INFO si; 233 | GetSystemInfo(&si); 234 | return si.dwPageSize; 235 | #else 236 | long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE)); 237 | if (size < 0) 238 | FMT_THROW(SystemError(errno, "cannot get memory page size")); 239 | return size; 240 | #endif 241 | } 242 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/fmt/bundled/printf.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Formatting library for C++ 3 | 4 | Copyright (c) 2012 - 2016, Victor Zverovich 5 | All rights reserved. 6 | 7 | For the license information refer to format.h. 8 | */ 9 | 10 | #include "format.h" 11 | #include "printf.h" 12 | 13 | namespace fmt { 14 | 15 | template 16 | void printf(BasicWriter &w, BasicCStringRef format, ArgList args); 17 | 18 | FMT_FUNC int fprintf(std::FILE *f, CStringRef format, ArgList args) { 19 | MemoryWriter w; 20 | printf(w, format, args); 21 | std::size_t size = w.size(); 22 | return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast(size); 23 | } 24 | 25 | #ifndef FMT_HEADER_ONLY 26 | 27 | template void PrintfFormatter::format(CStringRef format); 28 | template void PrintfFormatter::format(WCStringRef format); 29 | 30 | #endif // FMT_HEADER_ONLY 31 | 32 | } // namespace fmt 33 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/fmt/bundled/time.h: -------------------------------------------------------------------------------- 1 | /* 2 | Formatting library for C++ - time formatting 3 | 4 | Copyright (c) 2012 - 2016, Victor Zverovich 5 | All rights reserved. 6 | 7 | For the license information refer to format.h. 8 | */ 9 | 10 | #ifndef FMT_TIME_H_ 11 | #define FMT_TIME_H_ 12 | 13 | #include "format.h" 14 | #include 15 | 16 | #ifdef _MSC_VER 17 | # pragma warning(push) 18 | # pragma warning(disable: 4702) // unreachable code 19 | # pragma warning(disable: 4996) // "deprecated" functions 20 | #endif 21 | 22 | namespace fmt 23 | { 24 | template 25 | void format_arg(BasicFormatter &f, 26 | const char *&format_str, const std::tm &tm) 27 | { 28 | if (*format_str == ':') 29 | ++format_str; 30 | const char *end = format_str; 31 | while (*end && *end != '}') 32 | ++end; 33 | if (*end != '}') 34 | FMT_THROW(FormatError("missing '}' in format string")); 35 | internal::MemoryBuffer format; 36 | format.append(format_str, end + 1); 37 | format[format.size() - 1] = '\0'; 38 | Buffer &buffer = f.writer().buffer(); 39 | std::size_t start = buffer.size(); 40 | for (;;) 41 | { 42 | std::size_t size = buffer.capacity() - start; 43 | std::size_t count = std::strftime(&buffer[start], size, &format[0], &tm); 44 | if (count != 0) 45 | { 46 | buffer.resize(start + count); 47 | break; 48 | } 49 | if (size >= format.size() * 256) 50 | { 51 | // If the buffer is 256 times larger than the format string, assume 52 | // that `strftime` gives an empty result. There doesn't seem to be a 53 | // better way to distinguish the two cases: 54 | // https://github.com/fmtlib/fmt/issues/367 55 | break; 56 | } 57 | const std::size_t MIN_GROWTH = 10; 58 | buffer.reserve(buffer.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH)); 59 | } 60 | format_str = end + 1; 61 | } 62 | 63 | namespace internal 64 | { 65 | inline Null<> localtime_r(...) 66 | { 67 | return Null<>(); 68 | } 69 | inline Null<> localtime_s(...) 70 | { 71 | return Null<>(); 72 | } 73 | inline Null<> gmtime_r(...) 74 | { 75 | return Null<>(); 76 | } 77 | inline Null<> gmtime_s(...) 78 | { 79 | return Null<>(); 80 | } 81 | } 82 | 83 | // Thread-safe replacement for std::localtime 84 | inline std::tm localtime(std::time_t time) 85 | { 86 | struct LocalTime 87 | { 88 | std::time_t time_; 89 | std::tm tm_; 90 | 91 | LocalTime(std::time_t t): time_(t) {} 92 | 93 | bool run() 94 | { 95 | using namespace fmt::internal; 96 | return handle(localtime_r(&time_, &tm_)); 97 | } 98 | 99 | bool handle(std::tm *tm) 100 | { 101 | return tm != FMT_NULL; 102 | } 103 | 104 | bool handle(internal::Null<>) 105 | { 106 | using namespace fmt::internal; 107 | return fallback(localtime_s(&tm_, &time_)); 108 | } 109 | 110 | bool fallback(int res) 111 | { 112 | return res == 0; 113 | } 114 | 115 | bool fallback(internal::Null<>) 116 | { 117 | using namespace fmt::internal; 118 | std::tm *tm = std::localtime(&time_); 119 | if (tm) tm_ = *tm; 120 | return tm != FMT_NULL; 121 | } 122 | }; 123 | LocalTime lt(time); 124 | if (lt.run()) 125 | return lt.tm_; 126 | // Too big time values may be unsupported. 127 | FMT_THROW(fmt::FormatError("time_t value out of range")); 128 | return std::tm(); 129 | } 130 | 131 | // Thread-safe replacement for std::gmtime 132 | inline std::tm gmtime(std::time_t time) 133 | { 134 | struct GMTime 135 | { 136 | std::time_t time_; 137 | std::tm tm_; 138 | 139 | GMTime(std::time_t t): time_(t) {} 140 | 141 | bool run() 142 | { 143 | using namespace fmt::internal; 144 | return handle(gmtime_r(&time_, &tm_)); 145 | } 146 | 147 | bool handle(std::tm *tm) 148 | { 149 | return tm != FMT_NULL; 150 | } 151 | 152 | bool handle(internal::Null<>) 153 | { 154 | using namespace fmt::internal; 155 | return fallback(gmtime_s(&tm_, &time_)); 156 | } 157 | 158 | bool fallback(int res) 159 | { 160 | return res == 0; 161 | } 162 | 163 | bool fallback(internal::Null<>) 164 | { 165 | std::tm *tm = std::gmtime(&time_); 166 | if (tm != FMT_NULL) tm_ = *tm; 167 | return tm != FMT_NULL; 168 | } 169 | }; 170 | GMTime gt(time); 171 | if (gt.run()) 172 | return gt.tm_; 173 | // Too big time values may be unsupported. 174 | FMT_THROW(fmt::FormatError("time_t value out of range")); 175 | return std::tm(); 176 | } 177 | } //namespace fmt 178 | 179 | #ifdef _MSC_VER 180 | # pragma warning(pop) 181 | #endif 182 | 183 | #endif // FMT_TIME_H_ 184 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/fmt/fmt.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | // 9 | // Include a bundled header-only copy of fmtlib or an external one. 10 | // By default spdlog include its own copy. 11 | // 12 | 13 | #if !defined(SPDLOG_FMT_EXTERNAL) 14 | 15 | #ifndef FMT_HEADER_ONLY 16 | #define FMT_HEADER_ONLY 17 | #endif 18 | #ifndef FMT_USE_WINDOWS_H 19 | #define FMT_USE_WINDOWS_H 0 20 | #endif 21 | #include "bundled/format.h" 22 | #if defined(SPDLOG_FMT_PRINTF) 23 | #include "bundled/printf.h" 24 | #endif 25 | 26 | #else //external fmtlib 27 | 28 | #include 29 | #if defined(SPDLOG_FMT_PRINTF) 30 | #include 31 | #endif 32 | 33 | #endif 34 | 35 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/fmt/ostr.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | // include external or bundled copy of fmtlib's ostream support 9 | // 10 | #if !defined(SPDLOG_FMT_EXTERNAL) 11 | #include "fmt.h" 12 | #include "bundled/ostream.h" 13 | #else 14 | #include 15 | #endif 16 | 17 | 18 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/formatter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #include "details/log_msg.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace spdlog 15 | { 16 | namespace details 17 | { 18 | class flag_formatter; 19 | } 20 | 21 | class formatter 22 | { 23 | public: 24 | virtual ~formatter() {} 25 | virtual void format(details::log_msg& msg) = 0; 26 | }; 27 | 28 | class pattern_formatter SPDLOG_FINAL : public formatter 29 | { 30 | 31 | public: 32 | explicit pattern_formatter(const std::string& pattern, pattern_time_type pattern_time = pattern_time_type::local); 33 | pattern_formatter(const pattern_formatter&) = delete; 34 | pattern_formatter& operator=(const pattern_formatter&) = delete; 35 | void format(details::log_msg& msg) override; 36 | private: 37 | const std::string _pattern; 38 | const pattern_time_type _pattern_time; 39 | std::vector> _formatters; 40 | std::tm get_time(details::log_msg& msg); 41 | void handle_flag(char flag); 42 | void compile_pattern(const std::string& pattern); 43 | }; 44 | } 45 | 46 | #include "details/pattern_formatter_impl.h" 47 | 48 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/logger.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | // Thread safe logger (except for set_pattern(..), set_formatter(..) and set_error_handler()) 9 | // Has name, log level, vector of std::shared sink pointers and formatter 10 | // Upon each log write the logger: 11 | // 1. Checks if its log level is enough to log the message 12 | // 2. Format the message using the formatter function 13 | // 3. Pass the formatted message to its sinks to performa the actual logging 14 | 15 | #include "sinks/base_sink.h" 16 | #include "common.h" 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | namespace spdlog 23 | { 24 | 25 | class logger 26 | { 27 | public: 28 | logger(const std::string& logger_name, sink_ptr single_sink); 29 | logger(const std::string& name, sinks_init_list); 30 | template 31 | logger(const std::string& name, const It& begin, const It& end); 32 | 33 | virtual ~logger(); 34 | logger(const logger&) = delete; 35 | logger& operator=(const logger&) = delete; 36 | 37 | 38 | template void log(level::level_enum lvl, const char* fmt, const Args&... args); 39 | template void log(level::level_enum lvl, const char* msg); 40 | template void trace(const char* fmt, const Arg1&, const Args&... args); 41 | template void debug(const char* fmt, const Arg1&, const Args&... args); 42 | template void info(const char* fmt, const Arg1&, const Args&... args); 43 | template void warn(const char* fmt, const Arg1&, const Args&... args); 44 | template void error(const char* fmt, const Arg1&, const Args&... args); 45 | template void critical(const char* fmt, const Arg1&, const Args&... args); 46 | 47 | 48 | #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT 49 | template void log(level::level_enum lvl, const wchar_t* msg); 50 | template void log(level::level_enum lvl, const wchar_t* fmt, const Args&... args); 51 | template void trace(const wchar_t* fmt, const Args&... args); 52 | template void debug(const wchar_t* fmt, const Args&... args); 53 | template void info(const wchar_t* fmt, const Args&... args); 54 | template void warn(const wchar_t* fmt, const Args&... args); 55 | template void error(const wchar_t* fmt, const Args&... args); 56 | template void critical(const wchar_t* fmt, const Args&... args); 57 | #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT 58 | 59 | template void log(level::level_enum lvl, const T&); 60 | template void trace(const T&); 61 | template void debug(const T&); 62 | template void info(const T&); 63 | template void warn(const T&); 64 | template void error(const T&); 65 | template void critical(const T&); 66 | 67 | bool should_log(level::level_enum) const; 68 | void set_level(level::level_enum); 69 | level::level_enum level() const; 70 | const std::string& name() const; 71 | void set_pattern(const std::string&, pattern_time_type = pattern_time_type::local); 72 | void set_formatter(formatter_ptr); 73 | 74 | // automatically call flush() if message level >= log_level 75 | void flush_on(level::level_enum log_level); 76 | 77 | virtual void flush(); 78 | 79 | const std::vector& sinks() const; 80 | 81 | // error handler 82 | virtual void set_error_handler(log_err_handler); 83 | virtual log_err_handler error_handler(); 84 | 85 | protected: 86 | virtual void _sink_it(details::log_msg&); 87 | virtual void _set_pattern(const std::string&, pattern_time_type); 88 | virtual void _set_formatter(formatter_ptr); 89 | 90 | // default error handler: print the error to stderr with the max rate of 1 message/minute 91 | virtual void _default_err_handler(const std::string &msg); 92 | 93 | // return true if the given message level should trigger a flush 94 | bool _should_flush_on(const details::log_msg&); 95 | 96 | // increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)) 97 | void _incr_msg_counter(details::log_msg &msg); 98 | 99 | const std::string _name; 100 | std::vector _sinks; 101 | formatter_ptr _formatter; 102 | spdlog::level_t _level; 103 | spdlog::level_t _flush_level; 104 | log_err_handler _err_handler; 105 | std::atomic _last_err_time; 106 | std::atomic _msg_counter; 107 | }; 108 | } 109 | 110 | #include "details/logger_impl.h" 111 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/sinks/android_sink.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #if defined(__ANDROID__) 9 | 10 | #include "sink.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #if !defined(SPDLOG_ANDROID_RETRIES) 19 | #define SPDLOG_ANDROID_RETRIES 2 20 | #endif 21 | 22 | namespace spdlog 23 | { 24 | namespace sinks 25 | { 26 | 27 | /* 28 | * Android sink (logging using __android_log_write) 29 | * __android_log_write is thread-safe. No lock is needed. 30 | */ 31 | class android_sink : public sink 32 | { 33 | public: 34 | explicit android_sink(const std::string& tag = "spdlog", bool use_raw_msg = false): _tag(tag), _use_raw_msg(use_raw_msg) {} 35 | 36 | void log(const details::log_msg& msg) override 37 | { 38 | const android_LogPriority priority = convert_to_android(msg.level); 39 | const char *msg_output = (_use_raw_msg ? msg.raw.c_str() : msg.formatted.c_str()); 40 | 41 | // See system/core/liblog/logger_write.c for explanation of return value 42 | int ret = __android_log_write(priority, _tag.c_str(), msg_output); 43 | int retry_count = 0; 44 | while ((ret == -11/*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES)) 45 | { 46 | std::this_thread::sleep_for(std::chrono::milliseconds(5)); 47 | ret = __android_log_write(priority, _tag.c_str(), msg_output); 48 | retry_count++; 49 | } 50 | 51 | if (ret < 0) 52 | { 53 | throw spdlog_ex("__android_log_write() failed", ret); 54 | } 55 | } 56 | 57 | void flush() override 58 | { 59 | } 60 | 61 | private: 62 | static android_LogPriority convert_to_android(spdlog::level::level_enum level) 63 | { 64 | switch(level) 65 | { 66 | case spdlog::level::trace: 67 | return ANDROID_LOG_VERBOSE; 68 | case spdlog::level::debug: 69 | return ANDROID_LOG_DEBUG; 70 | case spdlog::level::info: 71 | return ANDROID_LOG_INFO; 72 | case spdlog::level::warn: 73 | return ANDROID_LOG_WARN; 74 | case spdlog::level::err: 75 | return ANDROID_LOG_ERROR; 76 | case spdlog::level::critical: 77 | return ANDROID_LOG_FATAL; 78 | default: 79 | return ANDROID_LOG_DEFAULT; 80 | } 81 | } 82 | 83 | std::string _tag; 84 | bool _use_raw_msg; 85 | }; 86 | 87 | } 88 | } 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/sinks/ansicolor_sink.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2017 spdlog authors. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #include "base_sink.h" 9 | #include "../common.h" 10 | #include "../details/os.h" 11 | 12 | #include 13 | #include 14 | 15 | namespace spdlog 16 | { 17 | namespace sinks 18 | { 19 | 20 | /** 21 | * This sink prefixes the output with an ANSI escape sequence color code depending on the severity 22 | * of the message. 23 | * If no color terminal detected, omit the escape codes. 24 | */ 25 | template 26 | class ansicolor_sink: public base_sink 27 | { 28 | public: 29 | ansicolor_sink(FILE* file): target_file_(file) 30 | { 31 | should_do_colors_ = details::os::in_terminal(file) && details::os::is_color_terminal(); 32 | colors_[level::trace] = cyan; 33 | colors_[level::debug] = cyan; 34 | colors_[level::info] = reset; 35 | colors_[level::warn] = yellow + bold; 36 | colors_[level::err] = red + bold; 37 | colors_[level::critical] = bold + on_red; 38 | colors_[level::off] = reset; 39 | } 40 | virtual ~ansicolor_sink() 41 | { 42 | _flush(); 43 | } 44 | 45 | void set_color(level::level_enum color_level, const std::string& color) 46 | { 47 | std::lock_guard lock(base_sink::_mutex); 48 | colors_[color_level] = color; 49 | } 50 | 51 | /// Formatting codes 52 | const std::string reset = "\033[00m"; 53 | const std::string bold = "\033[1m"; 54 | const std::string dark = "\033[2m"; 55 | const std::string underline = "\033[4m"; 56 | const std::string blink = "\033[5m"; 57 | const std::string reverse = "\033[7m"; 58 | const std::string concealed = "\033[8m"; 59 | 60 | // Foreground colors 61 | const std::string grey = "\033[30m"; 62 | const std::string red = "\033[31m"; 63 | const std::string green = "\033[32m"; 64 | const std::string yellow = "\033[33m"; 65 | const std::string blue = "\033[34m"; 66 | const std::string magenta = "\033[35m"; 67 | const std::string cyan = "\033[36m"; 68 | const std::string white = "\033[37m"; 69 | 70 | /// Background colors 71 | const std::string on_grey = "\033[40m"; 72 | const std::string on_red = "\033[41m"; 73 | const std::string on_green = "\033[42m"; 74 | const std::string on_yellow = "\033[43m"; 75 | const std::string on_blue = "\033[44m"; 76 | const std::string on_magenta = "\033[45m"; 77 | const std::string on_cyan = "\033[46m"; 78 | const std::string on_white = "\033[47m"; 79 | 80 | protected: 81 | virtual void _sink_it(const details::log_msg& msg) override 82 | { 83 | // Wrap the originally formatted message in color codes. 84 | // If color is not supported in the terminal, log as is instead. 85 | if (should_do_colors_) 86 | { 87 | const std::string& prefix = colors_[msg.level]; 88 | fwrite(prefix.data(), sizeof(char), prefix.size(), target_file_); 89 | fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), target_file_); 90 | fwrite(reset.data(), sizeof(char), reset.size(), target_file_); 91 | } 92 | else 93 | { 94 | fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), target_file_); 95 | } 96 | _flush(); 97 | } 98 | 99 | void _flush() override 100 | { 101 | fflush(target_file_); 102 | } 103 | FILE* target_file_; 104 | bool should_do_colors_; 105 | std::map colors_; 106 | }; 107 | 108 | 109 | template 110 | class ansicolor_stdout_sink: public ansicolor_sink 111 | { 112 | public: 113 | ansicolor_stdout_sink(): ansicolor_sink(stdout) 114 | {} 115 | }; 116 | 117 | template 118 | class ansicolor_stderr_sink: public ansicolor_sink 119 | { 120 | public: 121 | ansicolor_stderr_sink(): ansicolor_sink(stderr) 122 | {} 123 | }; 124 | 125 | typedef ansicolor_stdout_sink ansicolor_stdout_sink_mt; 126 | typedef ansicolor_stdout_sink ansicolor_stdout_sink_st; 127 | 128 | typedef ansicolor_stderr_sink ansicolor_stderr_sink_mt; 129 | typedef ansicolor_stderr_sink ansicolor_stderr_sink_st; 130 | 131 | } // namespace sinks 132 | } // namespace spdlog 133 | 134 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/sinks/base_sink.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | // 8 | // base sink templated over a mutex (either dummy or real) 9 | // concrete implementation should only override the _sink_it method. 10 | // all locking is taken care of here so no locking needed by the implementers.. 11 | // 12 | 13 | #include "sink.h" 14 | #include "../formatter.h" 15 | #include "../common.h" 16 | #include "../details/log_msg.h" 17 | 18 | #include 19 | 20 | namespace spdlog 21 | { 22 | namespace sinks 23 | { 24 | template 25 | class base_sink:public sink 26 | { 27 | public: 28 | base_sink():_mutex() {} 29 | virtual ~base_sink() = default; 30 | 31 | base_sink(const base_sink&) = delete; 32 | base_sink& operator=(const base_sink&) = delete; 33 | 34 | void log(const details::log_msg& msg) SPDLOG_FINAL override 35 | { 36 | std::lock_guard lock(_mutex); 37 | _sink_it(msg); 38 | } 39 | void flush() SPDLOG_FINAL override 40 | { 41 | std::lock_guard lock(_mutex); 42 | _flush(); 43 | } 44 | 45 | protected: 46 | virtual void _sink_it(const details::log_msg& msg) = 0; 47 | virtual void _flush() = 0; 48 | Mutex _mutex; 49 | }; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/sinks/dist_sink.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 David Schury, Gabi Melman 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #include "../details/log_msg.h" 9 | #include "../details/null_mutex.h" 10 | #include "base_sink.h" 11 | #include "sink.h" 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | // Distribution sink (mux). Stores a vector of sinks which get called when log is called 19 | 20 | namespace spdlog 21 | { 22 | namespace sinks 23 | { 24 | template 25 | class dist_sink: public base_sink 26 | { 27 | public: 28 | explicit dist_sink() :_sinks() {} 29 | dist_sink(const dist_sink&) = delete; 30 | dist_sink& operator=(const dist_sink&) = delete; 31 | virtual ~dist_sink() = default; 32 | 33 | protected: 34 | std::vector> _sinks; 35 | 36 | void _sink_it(const details::log_msg& msg) override 37 | { 38 | for (auto &sink : _sinks) 39 | { 40 | if( sink->should_log( msg.level)) 41 | { 42 | sink->log(msg); 43 | } 44 | } 45 | } 46 | 47 | void _flush() override 48 | { 49 | for (auto &sink : _sinks) 50 | sink->flush(); 51 | } 52 | 53 | public: 54 | 55 | 56 | void add_sink(std::shared_ptr sink) 57 | { 58 | std::lock_guard lock(base_sink::_mutex); 59 | _sinks.push_back(sink); 60 | } 61 | 62 | void remove_sink(std::shared_ptr sink) 63 | { 64 | std::lock_guard lock(base_sink::_mutex); 65 | _sinks.erase(std::remove(_sinks.begin(), _sinks.end(), sink), _sinks.end()); 66 | } 67 | }; 68 | 69 | typedef dist_sink dist_sink_mt; 70 | typedef dist_sink dist_sink_st; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/sinks/file_sinks.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #include "base_sink.h" 9 | #include "../details/null_mutex.h" 10 | #include "../details/file_helper.h" 11 | #include "../fmt/fmt.h" 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | namespace spdlog 22 | { 23 | namespace sinks 24 | { 25 | /* 26 | * Trivial file sink with single file as target 27 | */ 28 | template 29 | class simple_file_sink SPDLOG_FINAL : public base_sink < Mutex > 30 | { 31 | public: 32 | explicit simple_file_sink(const filename_t &filename, bool truncate = false):_force_flush(false) 33 | { 34 | _file_helper.open(filename, truncate); 35 | } 36 | 37 | void set_force_flush(bool force_flush) 38 | { 39 | _force_flush = force_flush; 40 | } 41 | 42 | protected: 43 | void _sink_it(const details::log_msg& msg) override 44 | { 45 | _file_helper.write(msg); 46 | if(_force_flush) 47 | _file_helper.flush(); 48 | } 49 | void _flush() override 50 | { 51 | _file_helper.flush(); 52 | } 53 | private: 54 | details::file_helper _file_helper; 55 | bool _force_flush; 56 | }; 57 | 58 | typedef simple_file_sink simple_file_sink_mt; 59 | typedef simple_file_sink simple_file_sink_st; 60 | 61 | /* 62 | * Rotating file sink based on size 63 | */ 64 | template 65 | class rotating_file_sink SPDLOG_FINAL : public base_sink < Mutex > 66 | { 67 | public: 68 | rotating_file_sink(const filename_t &base_filename, 69 | std::size_t max_size, std::size_t max_files) : 70 | _base_filename(base_filename), 71 | _max_size(max_size), 72 | _max_files(max_files), 73 | _current_size(0), 74 | _file_helper() 75 | { 76 | _file_helper.open(calc_filename(_base_filename, 0)); 77 | _current_size = _file_helper.size(); //expensive. called only once 78 | } 79 | 80 | // calc filename according to index and file extension if exists. 81 | // e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt". 82 | static filename_t calc_filename(const filename_t& filename, std::size_t index) 83 | { 84 | std::conditional::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w; 85 | if (index) 86 | { 87 | filename_t basename, ext; 88 | std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename); 89 | w.write(SPDLOG_FILENAME_T("{}.{}{}"), basename, index, ext); 90 | } 91 | else 92 | { 93 | w.write(SPDLOG_FILENAME_T("{}"), filename); 94 | } 95 | return w.str(); 96 | } 97 | 98 | protected: 99 | void _sink_it(const details::log_msg& msg) override 100 | { 101 | _current_size += msg.formatted.size(); 102 | if (_current_size > _max_size) 103 | { 104 | _rotate(); 105 | _current_size = msg.formatted.size(); 106 | } 107 | _file_helper.write(msg); 108 | } 109 | 110 | void _flush() override 111 | { 112 | _file_helper.flush(); 113 | } 114 | 115 | 116 | private: 117 | // Rotate files: 118 | // log.txt -> log.1.txt 119 | // log.1.txt -> log.2.txt 120 | // log.2.txt -> log.3.txt 121 | // log.3.txt -> delete 122 | void _rotate() 123 | { 124 | using details::os::filename_to_str; 125 | _file_helper.close(); 126 | for (auto i = _max_files; i > 0; --i) 127 | { 128 | filename_t src = calc_filename(_base_filename, i - 1); 129 | filename_t target = calc_filename(_base_filename, i); 130 | 131 | if (details::file_helper::file_exists(target)) 132 | { 133 | if (details::os::remove(target) != 0) 134 | { 135 | throw spdlog_ex("rotating_file_sink: failed removing " + filename_to_str(target), errno); 136 | } 137 | } 138 | if (details::file_helper::file_exists(src) && details::os::rename(src, target)) 139 | { 140 | throw spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno); 141 | } 142 | } 143 | _file_helper.reopen(true); 144 | } 145 | filename_t _base_filename; 146 | std::size_t _max_size; 147 | std::size_t _max_files; 148 | std::size_t _current_size; 149 | details::file_helper _file_helper; 150 | }; 151 | 152 | typedef rotating_file_sink rotating_file_sink_mt; 153 | typedef rotating_file_sinkrotating_file_sink_st; 154 | 155 | /* 156 | * Default generator of daily log file names. 157 | */ 158 | struct default_daily_file_name_calculator 159 | { 160 | // Create filename for the form filename.YYYY-MM-DD_hh-mm.ext 161 | static filename_t calc_filename(const filename_t& filename) 162 | { 163 | std::tm tm = spdlog::details::os::localtime(); 164 | filename_t basename, ext; 165 | std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename); 166 | std::conditional::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w; 167 | w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, ext); 168 | return w.str(); 169 | } 170 | }; 171 | 172 | /* 173 | * Generator of daily log file names in format basename.YYYY-MM-DD.ext 174 | */ 175 | struct dateonly_daily_file_name_calculator 176 | { 177 | // Create filename for the form basename.YYYY-MM-DD 178 | static filename_t calc_filename(const filename_t& filename) 179 | { 180 | std::tm tm = spdlog::details::os::localtime(); 181 | filename_t basename, ext; 182 | std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename); 183 | std::conditional::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w; 184 | w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, ext); 185 | return w.str(); 186 | } 187 | }; 188 | 189 | /* 190 | * Rotating file sink based on date. rotates at midnight 191 | */ 192 | template 193 | class daily_file_sink SPDLOG_FINAL :public base_sink < Mutex > 194 | { 195 | public: 196 | //create daily file sink which rotates on given time 197 | daily_file_sink( 198 | const filename_t& base_filename, 199 | int rotation_hour, 200 | int rotation_minute) : _base_filename(base_filename), 201 | _rotation_h(rotation_hour), 202 | _rotation_m(rotation_minute) 203 | { 204 | if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59) 205 | throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor"); 206 | _rotation_tp = _next_rotation_tp(); 207 | _file_helper.open(FileNameCalc::calc_filename(_base_filename)); 208 | } 209 | 210 | 211 | protected: 212 | void _sink_it(const details::log_msg& msg) override 213 | { 214 | if (std::chrono::system_clock::now() >= _rotation_tp) 215 | { 216 | _file_helper.open(FileNameCalc::calc_filename(_base_filename)); 217 | _rotation_tp = _next_rotation_tp(); 218 | } 219 | _file_helper.write(msg); 220 | } 221 | 222 | void _flush() override 223 | { 224 | _file_helper.flush(); 225 | } 226 | 227 | private: 228 | std::chrono::system_clock::time_point _next_rotation_tp() 229 | { 230 | auto now = std::chrono::system_clock::now(); 231 | time_t tnow = std::chrono::system_clock::to_time_t(now); 232 | tm date = spdlog::details::os::localtime(tnow); 233 | date.tm_hour = _rotation_h; 234 | date.tm_min = _rotation_m; 235 | date.tm_sec = 0; 236 | auto rotation_time = std::chrono::system_clock::from_time_t(std::mktime(&date)); 237 | if (rotation_time > now) 238 | return rotation_time; 239 | else 240 | return std::chrono::system_clock::time_point(rotation_time + std::chrono::hours(24)); 241 | } 242 | 243 | filename_t _base_filename; 244 | int _rotation_h; 245 | int _rotation_m; 246 | std::chrono::system_clock::time_point _rotation_tp; 247 | details::file_helper _file_helper; 248 | }; 249 | 250 | typedef daily_file_sink daily_file_sink_mt; 251 | typedef daily_file_sink daily_file_sink_st; 252 | } 253 | } 254 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/sinks/msvc_sink.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016 Alexander Dalshov. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #if defined(_WIN32) 9 | 10 | #include "base_sink.h" 11 | #include "../details/null_mutex.h" 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | namespace spdlog 19 | { 20 | namespace sinks 21 | { 22 | /* 23 | * MSVC sink (logging using OutputDebugStringA) 24 | */ 25 | template 26 | class msvc_sink : public base_sink < Mutex > 27 | { 28 | public: 29 | explicit msvc_sink() 30 | { 31 | } 32 | 33 | 34 | 35 | protected: 36 | void _sink_it(const details::log_msg& msg) override 37 | { 38 | OutputDebugStringA(msg.formatted.c_str()); 39 | } 40 | 41 | void _flush() override 42 | {} 43 | }; 44 | 45 | typedef msvc_sink msvc_sink_mt; 46 | typedef msvc_sink msvc_sink_st; 47 | 48 | } 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/sinks/null_sink.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #include "base_sink.h" 9 | #include "../details/null_mutex.h" 10 | 11 | #include 12 | 13 | namespace spdlog 14 | { 15 | namespace sinks 16 | { 17 | 18 | template 19 | class null_sink : public base_sink < Mutex > 20 | { 21 | protected: 22 | void _sink_it(const details::log_msg&) override 23 | {} 24 | 25 | void _flush() override 26 | {} 27 | 28 | }; 29 | typedef null_sink null_sink_st; 30 | typedef null_sink null_sink_mt; 31 | 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/sinks/ostream_sink.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #include "../details/null_mutex.h" 9 | #include "base_sink.h" 10 | 11 | #include 12 | #include 13 | 14 | namespace spdlog 15 | { 16 | namespace sinks 17 | { 18 | template 19 | class ostream_sink: public base_sink 20 | { 21 | public: 22 | explicit ostream_sink(std::ostream& os, bool force_flush=false) :_ostream(os), _force_flush(force_flush) {} 23 | ostream_sink(const ostream_sink&) = delete; 24 | ostream_sink& operator=(const ostream_sink&) = delete; 25 | virtual ~ostream_sink() = default; 26 | 27 | protected: 28 | void _sink_it(const details::log_msg& msg) override 29 | { 30 | _ostream.write(msg.formatted.data(), msg.formatted.size()); 31 | if (_force_flush) 32 | _ostream.flush(); 33 | } 34 | 35 | void _flush() override 36 | { 37 | _ostream.flush(); 38 | } 39 | 40 | std::ostream& _ostream; 41 | bool _force_flush; 42 | }; 43 | 44 | typedef ostream_sink ostream_sink_mt; 45 | typedef ostream_sink ostream_sink_st; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/sinks/sink.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | 7 | #pragma once 8 | 9 | #include "../details/log_msg.h" 10 | 11 | namespace spdlog 12 | { 13 | namespace sinks 14 | { 15 | class sink 16 | { 17 | public: 18 | sink() 19 | { 20 | _level = level::trace; 21 | } 22 | 23 | virtual ~sink() {} 24 | virtual void log(const details::log_msg& msg) = 0; 25 | virtual void flush() = 0; 26 | 27 | bool should_log(level::level_enum msg_level) const; 28 | void set_level(level::level_enum log_level); 29 | level::level_enum level() const; 30 | 31 | private: 32 | level_t _level; 33 | 34 | }; 35 | 36 | inline bool sink::should_log(level::level_enum msg_level) const 37 | { 38 | return msg_level >= _level.load(std::memory_order_relaxed); 39 | } 40 | 41 | inline void sink::set_level(level::level_enum log_level) 42 | { 43 | _level.store(log_level); 44 | } 45 | 46 | inline level::level_enum sink::level() const 47 | { 48 | return static_cast(_level.load(std::memory_order_relaxed)); 49 | } 50 | 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/sinks/stdout_sinks.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #include "../details/null_mutex.h" 9 | #include "base_sink.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace spdlog 16 | { 17 | namespace sinks 18 | { 19 | 20 | template 21 | class stdout_sink SPDLOG_FINAL : public base_sink 22 | { 23 | using MyType = stdout_sink; 24 | public: 25 | stdout_sink() 26 | {} 27 | static std::shared_ptr instance() 28 | { 29 | static std::shared_ptr instance = std::make_shared(); 30 | return instance; 31 | } 32 | protected: 33 | void _sink_it(const details::log_msg& msg) override 34 | { 35 | fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stdout); 36 | _flush(); 37 | } 38 | 39 | void _flush() override 40 | { 41 | fflush(stdout); 42 | } 43 | }; 44 | 45 | typedef stdout_sink stdout_sink_st; 46 | typedef stdout_sink stdout_sink_mt; 47 | 48 | 49 | template 50 | class stderr_sink SPDLOG_FINAL : public base_sink 51 | { 52 | using MyType = stderr_sink; 53 | public: 54 | stderr_sink() 55 | {} 56 | static std::shared_ptr instance() 57 | { 58 | static std::shared_ptr instance = std::make_shared(); 59 | return instance; 60 | } 61 | protected: 62 | void _sink_it(const details::log_msg& msg) override 63 | { 64 | fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stderr); 65 | _flush(); 66 | } 67 | 68 | void _flush() override 69 | { 70 | fflush(stderr); 71 | } 72 | }; 73 | 74 | typedef stderr_sink stderr_sink_mt; 75 | typedef stderr_sink stderr_sink_st; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/sinks/syslog_sink.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #include "../common.h" 9 | 10 | #ifdef SPDLOG_ENABLE_SYSLOG 11 | 12 | #include "sink.h" 13 | #include "../details/log_msg.h" 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | namespace spdlog 21 | { 22 | namespace sinks 23 | { 24 | /** 25 | * Sink that write to syslog using the `syscall()` library call. 26 | * 27 | * Locking is not needed, as `syslog()` itself is thread-safe. 28 | */ 29 | class syslog_sink : public sink 30 | { 31 | public: 32 | // 33 | syslog_sink(const std::string& ident = "", int syslog_option=0, int syslog_facility=LOG_USER): 34 | _ident(ident) 35 | { 36 | _priorities[static_cast(level::trace)] = LOG_DEBUG; 37 | _priorities[static_cast(level::debug)] = LOG_DEBUG; 38 | _priorities[static_cast(level::info)] = LOG_INFO; 39 | _priorities[static_cast(level::warn)] = LOG_WARNING; 40 | _priorities[static_cast(level::err)] = LOG_ERR; 41 | _priorities[static_cast(level::critical)] = LOG_CRIT; 42 | _priorities[static_cast(level::off)] = LOG_INFO; 43 | 44 | //set ident to be program name if empty 45 | ::openlog(_ident.empty()? nullptr:_ident.c_str(), syslog_option, syslog_facility); 46 | } 47 | ~syslog_sink() 48 | { 49 | ::closelog(); 50 | } 51 | 52 | syslog_sink(const syslog_sink&) = delete; 53 | syslog_sink& operator=(const syslog_sink&) = delete; 54 | 55 | void log(const details::log_msg &msg) override 56 | { 57 | ::syslog(syslog_prio_from_level(msg), "%s", msg.raw.str().c_str()); 58 | } 59 | 60 | void flush() override 61 | { 62 | } 63 | 64 | 65 | private: 66 | std::array _priorities; 67 | //must store the ident because the man says openlog might use the pointer as is and not a string copy 68 | const std::string _ident; 69 | 70 | // 71 | // Simply maps spdlog's log level to syslog priority level. 72 | // 73 | int syslog_prio_from_level(const details::log_msg &msg) const 74 | { 75 | return _priorities[static_cast(msg.level)]; 76 | } 77 | }; 78 | } 79 | } 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/sinks/wincolor_sink.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016 spdlog 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #include "base_sink.h" 9 | #include "../details/null_mutex.h" 10 | #include "../common.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace spdlog 18 | { 19 | namespace sinks 20 | { 21 | /* 22 | * Windows color console sink. Uses WriteConsoleA to write to the console with colors 23 | */ 24 | template 25 | class wincolor_sink: public base_sink 26 | { 27 | public: 28 | const WORD BOLD = FOREGROUND_INTENSITY; 29 | const WORD RED = FOREGROUND_RED; 30 | const WORD CYAN = FOREGROUND_GREEN | FOREGROUND_BLUE; 31 | const WORD WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; 32 | const WORD YELLOW = FOREGROUND_RED | FOREGROUND_GREEN; 33 | 34 | wincolor_sink(HANDLE std_handle): out_handle_(std_handle) 35 | { 36 | colors_[level::trace] = CYAN; 37 | colors_[level::debug] = CYAN; 38 | colors_[level::info] = WHITE | BOLD; 39 | colors_[level::warn] = YELLOW | BOLD; 40 | colors_[level::err] = RED | BOLD; // red bold 41 | colors_[level::critical] = BACKGROUND_RED | WHITE | BOLD; // white bold on red background 42 | colors_[level::off] = 0; 43 | } 44 | 45 | virtual ~wincolor_sink() 46 | { 47 | this->flush(); 48 | } 49 | 50 | wincolor_sink(const wincolor_sink& other) = delete; 51 | wincolor_sink& operator=(const wincolor_sink& other) = delete; 52 | 53 | protected: 54 | virtual void _sink_it(const details::log_msg& msg) override 55 | { 56 | auto color = colors_[msg.level]; 57 | auto orig_attribs = set_console_attribs(color); 58 | WriteConsoleA(out_handle_, msg.formatted.data(), static_cast(msg.formatted.size()), nullptr, nullptr); 59 | SetConsoleTextAttribute(out_handle_, orig_attribs); //reset to orig colors 60 | } 61 | 62 | virtual void _flush() override 63 | { 64 | // windows console always flushed? 65 | } 66 | 67 | // change the color for the given level 68 | void set_color(level::level_enum level, WORD color) 69 | { 70 | std::lock_guard lock(base_sink::_mutex); 71 | colors_[level] = color; 72 | } 73 | 74 | private: 75 | HANDLE out_handle_; 76 | std::map colors_; 77 | 78 | // set color and return the orig console attributes (for resetting later) 79 | WORD set_console_attribs(WORD attribs) 80 | { 81 | CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info; 82 | GetConsoleScreenBufferInfo(out_handle_, &orig_buffer_info); 83 | WORD back_color = orig_buffer_info.wAttributes; 84 | // retrieve the current background color 85 | back_color &= ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); 86 | // keep the background color unchanged 87 | SetConsoleTextAttribute(out_handle_, attribs | back_color); 88 | return orig_buffer_info.wAttributes; //return orig attribs 89 | } 90 | }; 91 | 92 | // 93 | // windows color console to stdout 94 | // 95 | template 96 | class wincolor_stdout_sink: public wincolor_sink 97 | { 98 | public: 99 | wincolor_stdout_sink() : wincolor_sink(GetStdHandle(STD_OUTPUT_HANDLE)) 100 | {} 101 | }; 102 | 103 | typedef wincolor_stdout_sink wincolor_stdout_sink_mt; 104 | typedef wincolor_stdout_sink wincolor_stdout_sink_st; 105 | 106 | // 107 | // windows color console to stderr 108 | // 109 | template 110 | class wincolor_stderr_sink: public wincolor_sink 111 | { 112 | public: 113 | wincolor_stderr_sink() : wincolor_sink(GetStdHandle(STD_ERROR_HANDLE)) 114 | {} 115 | }; 116 | 117 | typedef wincolor_stderr_sink wincolor_stderr_sink_mt; 118 | typedef wincolor_stderr_sink wincolor_stderr_sink_st; 119 | 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/sinks/windebug_sink.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2017 Alexander Dalshov. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #if defined(_WIN32) 9 | 10 | #include "msvc_sink.h" 11 | 12 | namespace spdlog 13 | { 14 | namespace sinks 15 | { 16 | 17 | /* 18 | * Windows debug sink (logging using OutputDebugStringA, synonym for msvc_sink) 19 | */ 20 | template 21 | using windebug_sink = msvc_sink; 22 | 23 | typedef msvc_sink_mt windebug_sink_mt; 24 | typedef msvc_sink_st windebug_sink_st; 25 | 26 | } 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/spdlog.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | // spdlog main header file. 6 | // see example.cpp for usage example 7 | 8 | #pragma once 9 | 10 | #define SPDLOG_VERSION "0.14.0" 11 | 12 | #include "tweakme.h" 13 | #include "common.h" 14 | #include "logger.h" 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | namespace spdlog 22 | { 23 | 24 | // 25 | // Return an existing logger or nullptr if a logger with such name doesn't exist. 26 | // example: spdlog::get("my_logger")->info("hello {}", "world"); 27 | // 28 | std::shared_ptr get(const std::string& name); 29 | 30 | 31 | // 32 | // Set global formatting 33 | // example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v"); 34 | // 35 | void set_pattern(const std::string& format_string); 36 | void set_formatter(formatter_ptr f); 37 | 38 | // 39 | // Set global logging level for 40 | // 41 | void set_level(level::level_enum log_level); 42 | 43 | // 44 | // Set global error handler 45 | // 46 | void set_error_handler(log_err_handler); 47 | 48 | // 49 | // Turn on async mode (off by default) and set the queue size for each async_logger. 50 | // effective only for loggers created after this call. 51 | // queue_size: size of queue (must be power of 2): 52 | // Each logger will pre-allocate a dedicated queue with queue_size entries upon construction. 53 | // 54 | // async_overflow_policy (optional, block_retry by default): 55 | // async_overflow_policy::block_retry - if queue is full, block until queue has room for the new log entry. 56 | // async_overflow_policy::discard_log_msg - never block and discard any new messages when queue overflows. 57 | // 58 | // worker_warmup_cb (optional): 59 | // callback function that will be called in worker thread upon start (can be used to init stuff like thread affinity) 60 | // 61 | // worker_teardown_cb (optional): 62 | // callback function that will be called in worker thread upon exit 63 | // 64 | void set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function& worker_teardown_cb = nullptr); 65 | 66 | // Turn off async mode 67 | void set_sync_mode(); 68 | 69 | 70 | // 71 | // Create and register multi/single threaded basic file logger. 72 | // Basic logger simply writes to given file without any limitations or rotations. 73 | // 74 | std::shared_ptr basic_logger_mt(const std::string& logger_name, const filename_t& filename, bool truncate = false); 75 | std::shared_ptr basic_logger_st(const std::string& logger_name, const filename_t& filename, bool truncate = false); 76 | 77 | // 78 | // Create and register multi/single threaded rotating file logger 79 | // 80 | std::shared_ptr rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files); 81 | std::shared_ptr rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files); 82 | 83 | // 84 | // Create file logger which creates new file on the given time (default in midnight): 85 | // 86 | std::shared_ptr daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0); 87 | std::shared_ptr daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0); 88 | 89 | // 90 | // Create and register stdout/stderr loggers 91 | // 92 | std::shared_ptr stdout_logger_mt(const std::string& logger_name); 93 | std::shared_ptr stdout_logger_st(const std::string& logger_name); 94 | std::shared_ptr stderr_logger_mt(const std::string& logger_name); 95 | std::shared_ptr stderr_logger_st(const std::string& logger_name); 96 | // 97 | // Create and register colored stdout/stderr loggers 98 | // 99 | std::shared_ptr stdout_color_mt(const std::string& logger_name); 100 | std::shared_ptr stdout_color_st(const std::string& logger_name); 101 | std::shared_ptr stderr_color_mt(const std::string& logger_name); 102 | std::shared_ptr stderr_color_st(const std::string& logger_name); 103 | 104 | 105 | // 106 | // Create and register a syslog logger 107 | // 108 | #ifdef SPDLOG_ENABLE_SYSLOG 109 | std::shared_ptr syslog_logger(const std::string& logger_name, const std::string& ident = "", int syslog_option = 0); 110 | #endif 111 | 112 | #if defined(__ANDROID__) 113 | std::shared_ptr android_logger(const std::string& logger_name, const std::string& tag = "spdlog"); 114 | #endif 115 | 116 | // Create and register a logger with a single sink 117 | std::shared_ptr create(const std::string& logger_name, const sink_ptr& sink); 118 | 119 | // Create and register a logger with multiple sinks 120 | std::shared_ptr create(const std::string& logger_name, sinks_init_list sinks); 121 | template 122 | std::shared_ptr create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end); 123 | 124 | 125 | // Create and register a logger with templated sink type 126 | // Example: 127 | // spdlog::create("mylog", "dailylog_filename"); 128 | template 129 | std::shared_ptr create(const std::string& logger_name, Args...); 130 | 131 | // Create and register an async logger with a single sink 132 | std::shared_ptr create_async(const std::string& logger_name, const sink_ptr& sink, size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function& worker_teardown_cb = nullptr); 133 | 134 | // Create and register an async logger with multiple sinks 135 | std::shared_ptr create_async(const std::string& logger_name, sinks_init_list sinks, size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function& worker_teardown_cb = nullptr); 136 | template 137 | std::shared_ptr create_async(const std::string& logger_name, const It& sinks_begin, const It& sinks_end, size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function& worker_teardown_cb = nullptr); 138 | 139 | // Register the given logger with the given name 140 | void register_logger(std::shared_ptr logger); 141 | 142 | // Apply a user defined function on all registered loggers 143 | // Example: 144 | // spdlog::apply_all([&](std::shared_ptr l) {l->flush();}); 145 | void apply_all(std::function)> fun); 146 | 147 | // Drop the reference to the given logger 148 | void drop(const std::string &name); 149 | 150 | // Drop all references from the registry 151 | void drop_all(); 152 | 153 | 154 | /////////////////////////////////////////////////////////////////////////////// 155 | // 156 | // Trace & Debug can be switched on/off at compile time for zero cost debug statements. 157 | // Uncomment SPDLOG_DEBUG_ON/SPDLOG_TRACE_ON in tweakme.h to enable. 158 | // SPDLOG_TRACE(..) will also print current file and line. 159 | // 160 | // Example: 161 | // spdlog::set_level(spdlog::level::trace); 162 | // SPDLOG_TRACE(my_logger, "some trace message"); 163 | // SPDLOG_TRACE(my_logger, "another trace message {} {}", 1, 2); 164 | // SPDLOG_DEBUG(my_logger, "some debug message {} {}", 3, 4); 165 | /////////////////////////////////////////////////////////////////////////////// 166 | 167 | #ifdef SPDLOG_TRACE_ON 168 | #define SPDLOG_STR_H(x) #x 169 | #define SPDLOG_STR_HELPER(x) SPDLOG_STR_H(x) 170 | #ifdef _MSC_VER 171 | #define SPDLOG_TRACE(logger, ...) logger->trace("[ " __FILE__ "(" SPDLOG_STR_HELPER(__LINE__) ") ] " __VA_ARGS__) 172 | #else 173 | #define SPDLOG_TRACE(logger, ...) logger->trace("[ " __FILE__ ":" SPDLOG_STR_HELPER(__LINE__) " ] " __VA_ARGS__) 174 | #endif 175 | #else 176 | #define SPDLOG_TRACE(logger, ...) 177 | #endif 178 | 179 | #ifdef SPDLOG_DEBUG_ON 180 | #define SPDLOG_DEBUG(logger, ...) logger->debug(__VA_ARGS__) 181 | #else 182 | #define SPDLOG_DEBUG(logger, ...) 183 | #endif 184 | 185 | } 186 | 187 | 188 | #include "details/spdlog_impl.h" 189 | -------------------------------------------------------------------------------- /3rdparty/inc/spdlog/tweakme.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | /////////////////////////////////////////////////////////////////////////////// 9 | // 10 | // Edit this file to squeeze more performance, and to customize supported features 11 | // 12 | /////////////////////////////////////////////////////////////////////////////// 13 | 14 | 15 | /////////////////////////////////////////////////////////////////////////////// 16 | // Under Linux, the much faster CLOCK_REALTIME_COARSE clock can be used. 17 | // This clock is less accurate - can be off by dozens of millis - depending on the kernel HZ. 18 | // Uncomment to use it instead of the regular clock. 19 | // 20 | // #define SPDLOG_CLOCK_COARSE 21 | /////////////////////////////////////////////////////////////////////////////// 22 | 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // Uncomment if date/time logging is not needed and never appear in the log pattern. 26 | // This will prevent spdlog from querying the clock on each log call. 27 | // 28 | // WARNING: If the log pattern contains any date/time while this flag is on, the result is undefined. 29 | // You must set new pattern(spdlog::set_pattern(..") without any date/time in it 30 | // 31 | // #define SPDLOG_NO_DATETIME 32 | /////////////////////////////////////////////////////////////////////////////// 33 | 34 | 35 | /////////////////////////////////////////////////////////////////////////////// 36 | // Uncomment if thread id logging is not needed (i.e. no %t in the log pattern). 37 | // This will prevent spdlog from querying the thread id on each log call. 38 | // 39 | // WARNING: If the log pattern contains thread id (i.e, %t) while this flag is on, the result is undefined. 40 | // 41 | // #define SPDLOG_NO_THREAD_ID 42 | /////////////////////////////////////////////////////////////////////////////// 43 | 44 | 45 | /////////////////////////////////////////////////////////////////////////////// 46 | // Uncomment to prevent spdlog from caching thread ids in thread local storage. 47 | // By default spdlog saves thread ids in tls to gain a few micros for each call. 48 | // 49 | // WARNING: if your program forks, UNCOMMENT this flag to prevent undefined thread ids in the children logs. 50 | // 51 | // #define SPDLOG_DISABLE_TID_CACHING 52 | /////////////////////////////////////////////////////////////////////////////// 53 | 54 | 55 | /////////////////////////////////////////////////////////////////////////////// 56 | // Uncomment if logger name logging is not needed. 57 | // This will prevent spdlog from copying the logger name on each log call. 58 | // 59 | // #define SPDLOG_NO_NAME 60 | /////////////////////////////////////////////////////////////////////////////// 61 | 62 | /////////////////////////////////////////////////////////////////////////////// 63 | // Uncomment to enable the SPDLOG_DEBUG/SPDLOG_TRACE macros. 64 | // 65 | // #define SPDLOG_DEBUG_ON 66 | // #define SPDLOG_TRACE_ON 67 | /////////////////////////////////////////////////////////////////////////////// 68 | 69 | 70 | /////////////////////////////////////////////////////////////////////////////// 71 | // Uncomment to avoid locking in the registry operations (spdlog::get(), spdlog::drop() spdlog::register()). 72 | // Use only if your code never modifies concurrently the registry. 73 | // Note that upon creating a logger the registry is modified by spdlog.. 74 | // 75 | // #define SPDLOG_NO_REGISTRY_MUTEX 76 | /////////////////////////////////////////////////////////////////////////////// 77 | 78 | 79 | /////////////////////////////////////////////////////////////////////////////// 80 | // Uncomment to avoid spdlog's usage of atomic log levels 81 | // Use only if your code never modifies a logger's log levels concurrently by different threads. 82 | // 83 | // #define SPDLOG_NO_ATOMIC_LEVELS 84 | /////////////////////////////////////////////////////////////////////////////// 85 | 86 | 87 | /////////////////////////////////////////////////////////////////////////////// 88 | // Uncomment to enable usage of wchar_t for file names on Windows. 89 | // 90 | // #define SPDLOG_WCHAR_FILENAMES 91 | /////////////////////////////////////////////////////////////////////////////// 92 | 93 | 94 | /////////////////////////////////////////////////////////////////////////////// 95 | // Uncomment to override default eol ("\n" or "\r\n" under Linux/Windows) 96 | // 97 | // #define SPDLOG_EOL ";-)\n" 98 | /////////////////////////////////////////////////////////////////////////////// 99 | 100 | 101 | /////////////////////////////////////////////////////////////////////////////// 102 | // Uncomment to use your own copy of the fmt library instead of spdlog's copy. 103 | // In this case spdlog will try to include so set your -I flag accordingly. 104 | // 105 | // #define SPDLOG_FMT_EXTERNAL 106 | /////////////////////////////////////////////////////////////////////////////// 107 | 108 | 109 | /////////////////////////////////////////////////////////////////////////////// 110 | // Uncomment to use printf-style messages in your logs instead of the usual 111 | // format-style used by default. 112 | // 113 | // #define SPDLOG_FMT_PRINTF 114 | /////////////////////////////////////////////////////////////////////////////// 115 | 116 | 117 | /////////////////////////////////////////////////////////////////////////////// 118 | // Uncomment to enable syslog (disabled by default) 119 | // 120 | // #define SPDLOG_ENABLE_SYSLOG 121 | /////////////////////////////////////////////////////////////////////////////// 122 | 123 | 124 | /////////////////////////////////////////////////////////////////////////////// 125 | // Uncomment to enable wchar_t support (convert to utf8) 126 | // 127 | #define SPDLOG_WCHAR_TO_UTF8_SUPPORT 128 | /////////////////////////////////////////////////////////////////////////////// 129 | 130 | 131 | /////////////////////////////////////////////////////////////////////////////// 132 | // Uncomment to prevent child processes from inheriting log file descriptors 133 | // 134 | // #define SPDLOG_PREVENT_CHILD_FD 135 | /////////////////////////////////////////////////////////////////////////////// 136 | 137 | 138 | /////////////////////////////////////////////////////////////////////////////// 139 | // Uncomment if your compiler doesn't support the "final" keyword. 140 | // The final keyword allows more optimizations in release 141 | // mode with recent compilers. See GCC's documentation for -Wsuggest-final-types 142 | // for instance. 143 | // 144 | // #define SPDLOG_NO_FINAL 145 | /////////////////////////////////////////////////////////////////////////////// 146 | 147 | 148 | /////////////////////////////////////////////////////////////////////////////// 149 | // Uncomment to enable message counting feature. 150 | // Use the %i in the logger pattern to display log message sequence id. 151 | // 152 | // #define SPDLOG_ENABLE_MESSAGE_COUNTER 153 | /////////////////////////////////////////////////////////////////////////////// 154 | 155 | 156 | /////////////////////////////////////////////////////////////////////////////// 157 | // Uncomment to customize level names (e.g. "MT TRACE") 158 | // 159 | // #define SPDLOG_LEVEL_NAMES { "MY TRACE", "MY DEBUG", "MY INFO", "MY WARNING", "MY ERROR", "MY CRITICAL", "OFF" } 160 | /////////////////////////////////////////////////////////////////////////////// 161 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | RETC community contributors 2 | ============================================ 3 | 4 | * **[t3nk3y](https://github.com/t3nk3y)** 5 | * NSIS powered installer 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## What is RETC 2 | RETC is a custom server application with a dll shim for clients, designed to be the middleman between the Razer Chroma SDK and various output sdks. 3 | I believe in performance so RETC is designed to run with the smallest amount of overhead possible. 4 | ## Installation: 5 | ### Automatic 6 | Follow the guide [how to install RETC](https://github.com/MartB/RETC/wiki/Installing). 7 | **tl:dr** 8 | Just download the latest installer executable [from here](https://github.com/MartB/RETC/releases/latest) and follow the installation steps. 9 | In both cases you should have working effects afterwards, if not proceed to the troubleshooting section. 10 | 11 | If you want to add a custom application see [Patching application](https://github.com/MartB/RETC#patching-application) 12 | ### Manual 13 | #### Patching application 14 | Copy both `RzChromaSDK.dll` and `RzChromaSDK64.dll` into the folder of the Application you want to use e.g `C:\Program Files\Overwatch`. 15 | 16 | **WARNING: 17 | Never move these dlls to a global dll loading path like `C:\Windows\System32` or the retc-server.exe directory itself otherwise you will end up crashing the application.** 18 | #### Preparing files 19 | Download the latest release from github or compile it yourself. 20 | Download and extract the corsair cue sdk from the [official corsair download page](http://downloads.corsair.com/download?item=Files/CUE/CUESDK_3.0.171.zip) 21 | Create a new folder called `retc-server` this will be the place where you start RETC from. 22 | ##### The following steps depend on your systems architecture 23 | i.e whether you are using a `64bit (x64, x86_64, AMD64, etc.)` or `32bit (x86, i386, etc)` system. 24 | ###### **64 Bit** 25 | Put the extracted `CUESDK\bin\amd64\CUESDK.x64_2015.dll` into the `retc-server` folder you just created. 26 | Copy the `retc-rpc-server-64.exe` from the github download into the same folder. 27 | 28 | ###### **32 Bit** 29 | Put the extracted `CUESDK\bin\i386\CUESDK_2015.dll` into the `retc-server` folder you just created. 30 | Copy the `retc-rpc-server.exe` from the github download into the same folder. 31 | # Usage 32 | **Choose one of the following sections depending on how you installed RETC.** 33 | ### Automatic installation 34 | The service should start right after the installation is done and should continue doing so on every boot. 35 | However if thats not the case check your services within windows and make sure you find a **RETC** service thats set to autostart. 36 | 37 | ### Manual installation 38 | Before you start any games run **either** `retc-rpc-server.exe` **or** `retc-rpc-server-64.exe`, depending on the system architecture you have, and **leave the console window open**. 39 | 40 | # Supported Output SDKs: 41 | ##### Only 1 output SDK is supported per device type (Keyboard, etc.). 42 | ### Corsair 43 | Only the effect types in the following list are supported. 44 | ``` 45 | Keyboards: 46 | CHROMA_NONE, CHROMA_STATIC, CHROMA_CUSTOM, CHROMA_CUSTOM_KEY 47 | Mice: 48 | CHROMA_NONE, CHROMA_STATIC, CHROMA_CUSTOM, CHROMA_CUSTOM2 49 | Headsets: 50 | CHROMA_NONE, CHROMA_STATIC, CHROMA_CUSTOM 51 | Mousepads: (since sdk version 2015) 52 | CHROMA_NONE, CHROMA_STATIC, CHROMA_CUSTOM 53 | ``` 54 | ### Razer 55 | **The razer sdk implementation is just forwarding to the real and installed sdk if available.** 56 | 57 | ### Which applications are supported? 58 | Pretty much every application that uses the Razer Chroma SDK through the supplied dlls is supported. 59 | Keep in mind that some (now deprecated) effects might not work correctly in some output sdks. 60 | 61 | # Troubleshooting: 62 | ## Corsair Output SDK 63 | ##### Did you start the Corsair Utility Engine ? 64 | ##### Did you enable the SDK in Corsair CUE ? 65 | ![cue-sdk-settings](http://i.imgur.com/c7d7hLR.png) 66 | ##### [error] [SDKLoader::load] LoadLibraryA(CUESDK[.x64_]2015.dll) failed with code 126 ? 67 | Download the latest VC++2015 x86 and x64 redistributable [from here](https://www.microsoft.com/en-us/download/details.aspx?id=48145) 68 | ## Razer Output SDK 69 | ##### Make sure Razer Synapse is installed properly and allows SDK access. 70 | ## General 71 | Take a look at the `server.log` it can help with your problems. 72 | ### Service 73 | Restart the RETC service from within `services.msc` (win+r and type it in). 74 | Then select the RTEC service, rightclick it and hit restart. 75 | ## Found an issue ? 76 | ### Try to fix it yourself. 77 | This is an opensource project if you think you can fix the issue yourself do so and shoot me a pull request. 78 | ### Create an Issue on github. 79 | If nothing works for you just report the issue and let the community help you. 80 | -------------------------------------------------------------------------------- /RETC.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 15 3 | VisualStudioVersion = 15.0.27130.2010 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RPC", "rpc-midl\midl.vcxproj", "{6536EBEC-014E-4D6B-97BE-223137694CA8}" 6 | EndProject 7 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Server", "server-exe\server.vcxproj", "{758DB128-9123-4E1B-A6C3-47323714123A}" 8 | EndProject 9 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShimDLL", "shim-dll\shim.vcxproj", "{758DB129-9123-4E1B-A6C3-47323714123A}" 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Debug|x64 = Debug|x64 15 | Release|Win32 = Release|Win32 16 | Release|x64 = Release|x64 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {6536EBEC-014E-4D6B-97BE-223137694CA8}.Debug|Win32.ActiveCfg = Debug|Win32 20 | {6536EBEC-014E-4D6B-97BE-223137694CA8}.Debug|Win32.Build.0 = Debug|Win32 21 | {6536EBEC-014E-4D6B-97BE-223137694CA8}.Debug|x64.ActiveCfg = Debug|x64 22 | {6536EBEC-014E-4D6B-97BE-223137694CA8}.Debug|x64.Build.0 = Debug|x64 23 | {6536EBEC-014E-4D6B-97BE-223137694CA8}.Release|Win32.ActiveCfg = Release|Win32 24 | {6536EBEC-014E-4D6B-97BE-223137694CA8}.Release|Win32.Build.0 = Release|Win32 25 | {6536EBEC-014E-4D6B-97BE-223137694CA8}.Release|x64.ActiveCfg = Release|x64 26 | {6536EBEC-014E-4D6B-97BE-223137694CA8}.Release|x64.Build.0 = Release|x64 27 | {758DB128-9123-4E1B-A6C3-47323714123A}.Debug|Win32.ActiveCfg = Debug|Win32 28 | {758DB128-9123-4E1B-A6C3-47323714123A}.Debug|Win32.Build.0 = Debug|Win32 29 | {758DB128-9123-4E1B-A6C3-47323714123A}.Debug|x64.ActiveCfg = Debug|x64 30 | {758DB128-9123-4E1B-A6C3-47323714123A}.Debug|x64.Build.0 = Debug|x64 31 | {758DB128-9123-4E1B-A6C3-47323714123A}.Release|Win32.ActiveCfg = Release|Win32 32 | {758DB128-9123-4E1B-A6C3-47323714123A}.Release|Win32.Build.0 = Release|Win32 33 | {758DB128-9123-4E1B-A6C3-47323714123A}.Release|x64.ActiveCfg = Release|x64 34 | {758DB128-9123-4E1B-A6C3-47323714123A}.Release|x64.Build.0 = Release|x64 35 | {758DB129-9123-4E1B-A6C3-47323714123A}.Debug|Win32.ActiveCfg = Debug|Win32 36 | {758DB129-9123-4E1B-A6C3-47323714123A}.Debug|Win32.Build.0 = Debug|Win32 37 | {758DB129-9123-4E1B-A6C3-47323714123A}.Debug|x64.ActiveCfg = Debug|x64 38 | {758DB129-9123-4E1B-A6C3-47323714123A}.Debug|x64.Build.0 = Debug|x64 39 | {758DB129-9123-4E1B-A6C3-47323714123A}.Release|Win32.ActiveCfg = Release|Win32 40 | {758DB129-9123-4E1B-A6C3-47323714123A}.Release|Win32.Build.0 = Release|Win32 41 | {758DB129-9123-4E1B-A6C3-47323714123A}.Release|x64.ActiveCfg = Release|x64 42 | {758DB129-9123-4E1B-A6C3-47323714123A}.Release|x64.Build.0 = Release|x64 43 | EndGlobalSection 44 | GlobalSection(SolutionProperties) = preSolution 45 | HideSolutionNode = FALSE 46 | EndGlobalSection 47 | GlobalSection(ExtensibilityGlobals) = postSolution 48 | SolutionGuid = {BF942D65-D62B-456A-8EB0-358C83FAFEB5} 49 | EndGlobalSection 50 | EndGlobal 51 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-midnight -------------------------------------------------------------------------------- /retc-installer/.gitignore: -------------------------------------------------------------------------------- 1 | *.dll 2 | *.exe -------------------------------------------------------------------------------- /retc-installer/build.py: -------------------------------------------------------------------------------- 1 | # Installer builder script for RETC 2 | import sys 3 | import os 4 | import distutils.dir_util 5 | import shutil 6 | 7 | CUE_SDK_DL_URL = "http://downloads.corsair.com/Files/CUE/CUESDK_3.0.234.zip" 8 | CUE_SDK_DLL_NAME_32 = "CUESDK_2015.dll" 9 | CUE_SDK_DLL_NAME_64 = "CUESDK.x64_2015.dll" 10 | 11 | SERVER_BUILD_PATH_32 = '../out/x86/Release/Server/' 12 | SERVER_BUILD_PATH_64 = '../out/x64/Release/Server/' 13 | 14 | CLIENT_BUILD_PATH_32 = '../out/x86/Release/ShimDLL/' 15 | CLIENT_BUILD_PATH_64 = '../out/x64/Release/ShimDLL/' 16 | 17 | THIRD_PARTY_INC_PATH = '../3rdparty/inc/' 18 | 19 | FILE_PATH = 'files/' 20 | FILE_PATH_32 = FILE_PATH + 'win32/' 21 | FILE_PATH_64 = FILE_PATH + 'win64/' 22 | TMP_PATH = FILE_PATH + 'tmp/' 23 | 24 | def checkFiles(list): 25 | for file in list: 26 | if not os.path.isfile(file): 27 | print("FileCheck: could not find",file) 28 | return False 29 | 30 | return True 31 | 32 | def checkFileAlternatives(list): 33 | for file in list: 34 | if os.path.isfile(file): 35 | return file 36 | 37 | return "" 38 | 39 | 40 | def findInList(list, string): 41 | return [s for s in list if string.lower() in s.lower()] 42 | 43 | class zipopfailed(Exception): pass 44 | def downloadAndExtractZipFile(url, ziplist): 45 | import urllib.request, urllib.error, urllib.parse 46 | import zipfile 47 | try: 48 | try: 49 | response = urllib.request.urlopen(url) 50 | except urllib.error.HTTPError as e: 51 | print("Download: http error",e.reason," url(",url,")") 52 | return False 53 | except urllib.error.URLError as e: 54 | print("Download: url error",e.reason," url(",url,")") 55 | return False 56 | 57 | data = response.read() 58 | fileName = url.split('/')[-1] 59 | print("Downloading: ",fileName) 60 | distutils.dir_util.mkpath(TMP_PATH) 61 | with open(TMP_PATH+fileName , 'wb') as file: 62 | file.write(data) 63 | 64 | with zipfile.ZipFile(TMP_PATH + fileName, 'r') as zip: 65 | fileList = zip.namelist() 66 | 67 | for entry in ziplist: 68 | print("Extracting: ", entry[0]) 69 | zipFileEntry = findInList(fileList, entry[0]) 70 | if not zipFileEntry: 71 | print("Did not find",entry[0],"in zip") 72 | raise zipopfailed() 73 | 74 | with open(entry[1], 'wb') as file: 75 | try: 76 | file.write(zip.read(zipFileEntry[0])) 77 | except IOError as e: 78 | print(e) 79 | raise zipopfailed() 80 | except zipopfailed: 81 | os.remove(TMP_PATH+fileName) 82 | return False 83 | 84 | os.remove(TMP_PATH+fileName) 85 | return True 86 | 87 | 88 | def downloadCueSdk(): 89 | return downloadAndExtractZipFile(CUE_SDK_DL_URL, [ 90 | (CUE_SDK_DLL_NAME_32, FILE_PATH_32 + CUE_SDK_DLL_NAME_32), 91 | (CUE_SDK_DLL_NAME_64, FILE_PATH_64 + CUE_SDK_DLL_NAME_64) 92 | ]) 93 | 94 | 95 | def copyBuildFiles(): 96 | buildFiles = [ 97 | ("../",FILE_PATH,"LICENSE"), 98 | ("../",FILE_PATH,"README.md"), 99 | (SERVER_BUILD_PATH_32, FILE_PATH_32, "retc-rpc-server-32.exe"), 100 | (SERVER_BUILD_PATH_64, FILE_PATH_64, "retc-rpc-server-64.exe"), 101 | (CLIENT_BUILD_PATH_32, FILE_PATH_32, "RzChromaSDK.dll"), 102 | (CLIENT_BUILD_PATH_64, FILE_PATH_64, "RzChromaSDK64.dll"), 103 | ] 104 | 105 | copyFiles(buildFiles) 106 | 107 | def copyLicenses(): 108 | licenses = [ 109 | (THIRD_PARTY_INC_PATH + "spdlog/LICENSE",FILE_PATH + "SPDLOG_LICENSE"), 110 | (THIRD_PARTY_INC_PATH + "SimpleIni/LICENCE.txt",FILE_PATH + "SIMPLEINI_LICENSE"), 111 | ] 112 | 113 | copyFiles(licenses) 114 | 115 | 116 | def copyFiles(buildFiles): 117 | for file in buildFiles: 118 | if len(file) > 2: 119 | shutil.copy2(file[0]+file[2], file[1]+file[2]) 120 | else: 121 | shutil.copy2(file[0], file[1]) 122 | 123 | def cleanBuildFiles(): 124 | print("Cleaning build files") 125 | try: 126 | shutil.rmtree(TMP_PATH) 127 | except OSError: 128 | pass 129 | else: 130 | print("Deleting", TMP_PATH) 131 | 132 | for root, dirs, files in os.walk(FILE_PATH): 133 | for file in files: 134 | if file.endswith((".dll",".exe","LICENSE", ".md")): 135 | filePath = os.path.join(root,file) 136 | print("Deleting", filePath) 137 | os.remove(filePath) 138 | 139 | def main(argv): 140 | if findInList(argv, "clean"): 141 | cleanBuildFiles() 142 | return 143 | 144 | cueSDKExists = checkFiles([ 145 | FILE_PATH_32 + CUE_SDK_DLL_NAME_32, 146 | FILE_PATH_64 + CUE_SDK_DLL_NAME_64 147 | ]) 148 | if not cueSDKExists and not downloadCueSdk(): 149 | print("Could not download cue sdk") 150 | return 151 | 152 | copyBuildFiles() 153 | copyLicenses() 154 | 155 | nsisExecutable = checkFileAlternatives([ 156 | "makensis.exe", 157 | os.environ["ProgramFiles"] + "\\NSIS\\makensis.exe", 158 | os.environ["ProgramFiles(x86)"] + "\\NSIS\\makensis.exe" 159 | ]) 160 | 161 | if nsisExecutable == "": 162 | print("NSIS Not found please install it from here: https://sourceforge.net/projects/nsis/") 163 | print("You also need the moreinfo plugin from here: http://nsis.sourceforge.net/MoreInfo_plug-in") 164 | return 165 | 166 | from subprocess import call 167 | call([nsisExecutable, "RETC_Installer.nsi"]) 168 | 169 | if __name__ == "__main__": 170 | main(sys.argv) 171 | -------------------------------------------------------------------------------- /retc-installer/files/.gitignore: -------------------------------------------------------------------------------- 1 | /* 2 | !.gitignore 3 | !/*/ -------------------------------------------------------------------------------- /retc-installer/files/win32/.gitignore: -------------------------------------------------------------------------------- 1 | *.dll 2 | *.exe -------------------------------------------------------------------------------- /retc-installer/files/win32/WIN32 FILES HERE.txt: -------------------------------------------------------------------------------- 1 | Place 32bit files here, including RETC binary, NSSM binary, RzChromaSDK DLL, and CorsairSDK DLL -------------------------------------------------------------------------------- /retc-installer/files/win64/.gitignore: -------------------------------------------------------------------------------- 1 | *.dll 2 | *.exe -------------------------------------------------------------------------------- /retc-installer/files/win64/WIN64 FILES HERE.txt: -------------------------------------------------------------------------------- 1 | Place 64bit files here, including RETC binary, NSSM binary, RzChromaSDK DLL, and CorsairSDK DLL -------------------------------------------------------------------------------- /rpc-midl/rpc_retc.acf: -------------------------------------------------------------------------------- 1 | [ 2 | explicit_handle 3 | ] 4 | 5 | interface rpc_retc 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /rpc-midl/rpc_retc.idl: -------------------------------------------------------------------------------- 1 | #if (__midl >= 501) 2 | midl_pragma warning(disable: 2111) 3 | #endif 4 | 5 | import "oaidl.idl"; 6 | 7 | [ 8 | uuid(5f4db48f-188e-4243-8570-5a9835640b95), 9 | version(2.5) 10 | ] 11 | 12 | interface rpc_retc 13 | { 14 | typedef GUID RZEFFECTID; 15 | typedef GUID RZDEVICEID; 16 | typedef LONG RZRESULT; 17 | typedef unsigned __int32 efsize_t; 18 | 19 | // If you change the order in the below enum adjust the order of genericEffectType and effectSize in server/src/common/commonData.h 20 | typedef enum RETCDeviceType 21 | { 22 | KEYBOARD, 23 | MOUSE, 24 | HEADSET, 25 | MOUSEPAD, 26 | KEYPAD, 27 | SYSTEM, 28 | HEADSET_STAND, 29 | ALL, 30 | ESIZE, // If you get that as type its invalid, goes always last! 31 | } RETCDeviceType; 32 | 33 | typedef BOOL supportArray_t[ESIZE]; 34 | typedef RZDEVICEID supportedDevices_t[ALL]; 35 | 36 | typedef struct RETCClientConfig 37 | { 38 | supportArray_t supportedDeviceTypes; 39 | supportedDevices_t emulatedDeviceIDS; 40 | } RETCClientConfig; 41 | 42 | typedef [context_handle] void* CONTEXT_HANDLE; 43 | typedef [ptr] RETCClientConfig* CONFIG_PTR; 44 | 45 | CONTEXT_HANDLE initialize([in] handle_t hBinding, [in, out] CONFIG_PTR config); 46 | 47 | RZRESULT playEffect(const RETCDeviceType deviceType, [in] const int type, [in, out, unique]RZEFFECTID *pEffectID, const efsize_t effectSize, [size_is(effectSize)] char effectData[*], CONTEXT_HANDLE hContext); 48 | 49 | RZRESULT setEffect([in] const RZEFFECTID effID, CONTEXT_HANDLE hContext); 50 | RZRESULT deleteEffect([in] const RZEFFECTID effID, CONTEXT_HANDLE hContext); 51 | 52 | void disconnect([in, out] CONTEXT_HANDLE* phContext); 53 | } 54 | -------------------------------------------------------------------------------- /scripts/build-version.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [String]$Project, 3 | [String]$GitRoot, 4 | [String]$ProjectURL="https://github.com/martb/retc/commit/" 5 | ) 6 | 7 | Push-Location -LiteralPath $GitRoot 8 | 9 | $FileHead = "`#pragma once`n`n" 10 | $FileTail = "`n" 11 | 12 | $Author = (git log -n 1 --format=format:"#define VERSION_AUTHOR `\`"%an `<%ae`>`\`";%n") | Out-String 13 | $Url = (git log -n 1 --format=format:"#define VERSION_URL `\`"$ProjectURL%H`\`";%n") | Out-String 14 | $Date = (git log -n 1 --format=format:"#define VERSION_DATE `\`"%ai`\`";%n") | Out-String 15 | $CommitMsg = (git log -n 1 --format=format:"#define VERSION_CMSG `\`"%f`\`";%n") | Out-String 16 | $GitTagLong = (git describe --long --tags) 17 | $Tag = ("#define VERSION_TAG `"$GitTagLong`";`n") 18 | 19 | $VerNo = $GitTagLong -match '(?<=v).*?(?=-)' 20 | $VerNo = $matches[0] 21 | $VerNoAr = $VerNo.Split(".") 22 | $VerNo = "" 23 | for ($i=0;$i -lt 4; $i++) { 24 | $v = "0" 25 | if ($i -lt $VerNoAr.length) { 26 | $v = $VerNoAr[$i] 27 | } 28 | 29 | $VerNo = $VerNo + $(if ($i -ne 0) {","}) + $v 30 | } 31 | 32 | $VerNo = "#define VERSION_NUMBER "+$VerNo+";`n" 33 | 34 | "Version updated for $Project\" + ( 35 | New-Item -Force -Path "$Project" -Name "version.h" -ItemType "file" -Value "$FileHead$Url$Author$Date$Tag$VerNo$CommitMsg$FileTail" 36 | ).Name + " Contents:" 37 | "" 38 | Get-Content "$Project\version.h" 39 | "" 40 | 41 | Pop-Location -------------------------------------------------------------------------------- /server-exe/.gitignore: -------------------------------------------------------------------------------- 1 | version.h -------------------------------------------------------------------------------- /server-exe/ConfigManager.cpp: -------------------------------------------------------------------------------- 1 | // This is an open source non-commercial project. Dear PVS-Studio, please check it. 2 | // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com 3 | 4 | #include "ConfigManager.h" 5 | #include "utils.h" 6 | #include 7 | #define CONFIG_FILENAME L"config.ini" 8 | 9 | ConfigManager::ConfigManager() { 10 | simpleIni = std::make_unique(); 11 | simpleIni->SetUnicode(); 12 | 13 | ReloadConfigFile(); 14 | } 15 | 16 | #define SUCCESS(cond) ((cond) >= SI_OK) 17 | 18 | void ConfigManager::ReloadConfigFile() const 19 | { 20 | simpleIni->Reset(); 21 | 22 | // It does not matter if this fails 23 | simpleIni->LoadFile(CONFIG_FILENAME); 24 | } 25 | 26 | // Please do not use these if you expect special characters > 7 bit to work 27 | std::string ConfigManager::GetAsciiString(const wchar_t* section, const wchar_t* key, const wchar_t* def) const { 28 | const std::wstring res = GetWString(section, key, def); 29 | return std::string(res.begin(), res.end()); 30 | } 31 | 32 | std::string ConfigManager::GetAsciiString(const wchar_t* section, const wchar_t* key, const std::string &def) const { 33 | std::wstring defConv(def.begin(), def.end()); 34 | return GetAsciiString(section, key, defConv.c_str()); 35 | } 36 | 37 | // Please do not use this if you rely on utf8, utf16. Use wstring instead 38 | std::string ConfigManager::GetUtf8StdString(const wchar_t* section, const wchar_t* key, const std::string &def) { 39 | return WSTR_CONVERTER.to_bytes(GetWString(section, key, WSTR_CONVERTER.from_bytes(def).c_str())); 40 | } 41 | 42 | const wchar_t* ConfigManager::GetWString(const wchar_t* section, const wchar_t* key, const wchar_t* def) const { 43 | return simpleIni->GetValue(section, key, def); 44 | } 45 | 46 | double ConfigManager::GetDouble(const wchar_t* section, const wchar_t* key, const double def) const { 47 | return simpleIni->GetDoubleValue(section, key, def); 48 | } 49 | 50 | bool ConfigManager::GetBool(const wchar_t* section, const wchar_t* key, const bool def) { 51 | return simpleIni->GetBoolValue(section, key, def); 52 | } 53 | 54 | long ConfigManager::GetLong(const wchar_t* section, const wchar_t* key, const long def) { 55 | return simpleIni->GetLongValue(section, key, def); 56 | } 57 | 58 | Vec3D ConfigManager::GetVec3D(const wchar_t * section, const wchar_t * key, const Vec3D &def) const { 59 | const auto rawValue = GetWString(section, key, nullptr); 60 | if (rawValue == nullptr) { 61 | return def; 62 | } 63 | 64 | std::wstringstream ws(rawValue); 65 | Vec3D ret; 66 | ws >> ret.x; 67 | ws >> ret.y; 68 | ws >> ret.z; 69 | 70 | if (ws.fail()) { 71 | LOG_E(L"Malformed vec3d section {0}, key {1}. Format: X.X Y.Y Z.Z (divided by spaces)", section, key); 72 | return def; 73 | } 74 | 75 | return ret; 76 | } 77 | 78 | bool ConfigManager::SetBool(const wchar_t* section, const wchar_t* key, const bool value) const { 79 | return SUCCESS(simpleIni->SetBoolValue(section, key, value)); 80 | } 81 | 82 | bool ConfigManager::SetLong(const wchar_t* section, const wchar_t* key, const long value) const { 83 | return SUCCESS(simpleIni->SetLongValue(section, key, value)); 84 | } 85 | 86 | bool ConfigManager::SetWString(const wchar_t* section, const wchar_t* key, const wchar_t* value) const { 87 | return SUCCESS(simpleIni->SetValue(section, key, value)); 88 | } 89 | 90 | bool ConfigManager::SetDouble(const wchar_t* section, const wchar_t* key, const double value) const { 91 | return SUCCESS(simpleIni->SetDoubleValue(section, key, value)); 92 | } 93 | 94 | bool ConfigManager::SetVec3D(const wchar_t* section, const wchar_t* key, const Vec3D &value) const { 95 | std::wstringstream ws; 96 | ws << value.x; 97 | ws << value.y; 98 | ws << value.z; 99 | 100 | if (ws.fail()) { 101 | LOG_E(L"Issue while saving vec3d section {0}, key {1}.", section, key); 102 | return false; 103 | } 104 | 105 | return SUCCESS(simpleIni->SetValue(section, key, ws.str().c_str())); 106 | } 107 | 108 | 109 | bool ConfigManager::SaveConfig() const { 110 | return SUCCESS(simpleIni->SaveFile(CONFIG_FILENAME)); 111 | } 112 | 113 | ConfigManager::~ConfigManager() 114 | { 115 | simpleIni->Reset(); 116 | } 117 | 118 | -------------------------------------------------------------------------------- /server-exe/ConfigManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define SI_SUPPORT_IOSTREAMS 3 | #include "SimpleIni/SimpleIni.h" 4 | 5 | #include 6 | #include 7 | 8 | struct Vec3D { 9 | double x, y, z; 10 | Vec3D() : x(0.0f), y(0.0f), z(0.0f) {} 11 | 12 | bool isZero() const { 13 | return x == 0.0f && y == 0.0f && z == 0.0f; //-V550 14 | } 15 | }; 16 | 17 | class ConfigManager { 18 | public: 19 | ~ConfigManager(); 20 | ConfigManager(); 21 | 22 | void ReloadConfigFile() const; 23 | 24 | std::string GetAsciiString(const wchar_t * section, const wchar_t * key, const wchar_t * def) const; 25 | std::string GetAsciiString(const wchar_t * section, const wchar_t * key, const std::string &def) const; 26 | 27 | std::string GetUtf8StdString(const wchar_t * section, const wchar_t * key, const std::string &def); 28 | 29 | const wchar_t * GetWString(const wchar_t * section, const wchar_t * key, const wchar_t * def) const; 30 | double GetDouble(const wchar_t * section, const wchar_t * key, double def) const; 31 | bool GetBool(const wchar_t * section, const wchar_t * key, bool def); 32 | long GetLong(const wchar_t * section, const wchar_t * key, long def); 33 | Vec3D GetVec3D(const wchar_t * section, const wchar_t *key, const Vec3D &def) const; 34 | 35 | bool SetBool(const wchar_t * section, const wchar_t * key, bool value) const; 36 | bool SetLong(const wchar_t * section, const wchar_t * key, long value) const; 37 | bool SetWString(const wchar_t * section, const wchar_t * key, const wchar_t * value) const; 38 | 39 | bool SetDouble(const wchar_t * section, const wchar_t * key, double value) const; 40 | bool SetVec3D(const wchar_t* section, const wchar_t* key, const Vec3D &value) const; 41 | 42 | bool SaveConfig() const; 43 | 44 | private: 45 | std::unique_ptr simpleIni; 46 | std::wstring_convert> WSTR_CONVERTER; 47 | 48 | }; -------------------------------------------------------------------------------- /server-exe/CorsairSDK.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "LightingSDK.h" 3 | #include "CUESDK.h" 4 | #include 5 | 6 | class CorsairSDK : public LightingSdk { 7 | public: 8 | CorsairSDK(); 9 | 10 | bool initialize() override; 11 | void reset() override; 12 | RZRESULT playEffect(RETCDeviceType deviceType, int effectType, const char data[]) override; 13 | 14 | private: 15 | RZRESULT prepareKeyboardEffect(int type, const char effectData[]); 16 | RZRESULT prepareMouseEffect(int type, const char effectData[]); 17 | RZRESULT prepareMousePadEffect(int type, const char effectData[]); 18 | RZRESULT prepareHeadsetEffect(int type, const char effectData[]); 19 | RZRESULT prepareHeadsetStandEffect(int type, const char effectData[]); 20 | 21 | // Helper functions 22 | CorsairLedColor convertLedColor(const COLORREF& color); 23 | static RETCDeviceType corsairToRetcDeviceType(CorsairDeviceType type); 24 | 25 | static bool findKeyboardLed(CorsairLedId ledid, int* row, int* col); 26 | static bool findMouseLed(CorsairLedId ledid, int* row, int* col); 27 | static CorsairLedId findMouseLedForRzled(ChromaSDK::Mouse::RZLED led); 28 | static ChromaSDK::Mouse::RZLED findMouseLedForCld(CorsairLedId led); 29 | static int findHeadsetStandLed(CorsairLedId ledid); 30 | 31 | static std::string errToString(const CorsairError& error); 32 | 33 | typedef std::vector ledIDVector; 34 | typedef std::vector ledColorVector; 35 | 36 | ledIDVector m_availableLeds[ALL]; 37 | ledColorVector m_outputColorVector; 38 | 39 | // DLL functions 40 | typedef bool (*CorsairSetLedsColors_t)(int, CorsairLedColor*); 41 | typedef bool (*CorsairSetLedsColorsAsync_t)(int, CorsairLedColor*, void (*CallbackType)(void*, bool, CorsairError), void*); 42 | typedef int (*CorsairGetDeviceCount_t)(); 43 | typedef CorsairDeviceInfo*(*CorsairGetDeviceInfo_t)(int); 44 | typedef CorsairLedPositions*(*CorsairGetLedPositions_t)(); 45 | typedef CorsairLedId (*CorsairGetLedIdForKeyName_t)(char); 46 | typedef bool (*CorsairRequestControl_t)(CorsairAccessMode); 47 | typedef CorsairProtocolDetails (*CorsairPerformProtocolHandshake_t)(); 48 | typedef CorsairError (*CorsairGetLastError_t)(); 49 | typedef CorsairLedPositions*(*CorsairGetLedPositionsByDeviceIndex_t)(int); 50 | 51 | SDKLoaderAssignNameToVariable(CorsairSetLedsColors) 52 | SDKLoaderAssignNameToVariable(CorsairSetLedsColorsAsync) 53 | SDKLoaderAssignNameToVariable(CorsairGetDeviceCount) 54 | SDKLoaderAssignNameToVariable(CorsairGetDeviceInfo) 55 | SDKLoaderAssignNameToVariable(CorsairGetLedPositions) 56 | SDKLoaderAssignNameToVariable(CorsairGetLedIdForKeyName) 57 | SDKLoaderAssignNameToVariable(CorsairRequestControl) 58 | SDKLoaderAssignNameToVariable(CorsairPerformProtocolHandshake) 59 | SDKLoaderAssignNameToVariable(CorsairGetLastError) 60 | SDKLoaderAssignNameToVariable(CorsairGetLedPositionsByDeviceIndex) 61 | }; 62 | -------------------------------------------------------------------------------- /server-exe/EffectManager.cpp: -------------------------------------------------------------------------------- 1 | // This is an open source non-commercial project. Dear PVS-Studio, please check it. 2 | // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com 3 | #include "EffectManager.h" 4 | 5 | 6 | EffectManager::~EffectManager() 7 | { 8 | clearEffects(); 9 | } 10 | 11 | bool EffectManager::storeEffect(const RETCDeviceType& deviceType, int effectType, RZEFFECTID* pEffectID, efsize_t effectSize, const char effectData[]) { 12 | internalEffectData effData; 13 | effData.type = effectType; 14 | effData.deviceType = deviceType; 15 | effData.data = new char[static_cast(effectSize)]; 16 | std::move(effectData, effectData + static_cast(effectSize), effData.data); 17 | 18 | RZEFFECTID newEffectID; 19 | if (!createUniqueEffectID(&newEffectID)) { 20 | return false; 21 | } 22 | 23 | *pEffectID = newEffectID; 24 | 25 | m_effectMap.insert(std::make_pair(newEffectID, effData)); 26 | 27 | return true; 28 | } 29 | 30 | bool EffectManager::deleteEffect(const RZEFFECTID& pEffectID) { 31 | auto it = m_effectMap.find(pEffectID); 32 | if (it == m_effectMap.end()) { 33 | return false; 34 | } 35 | 36 | delete[] it->second.data; 37 | m_effectMap.erase(it); 38 | 39 | return true; 40 | } 41 | 42 | void EffectManager::clearEffects() 43 | { 44 | std::for_each(m_effectMap.begin(), m_effectMap.end(), [](const auto &effect) -> void 45 | { 46 | delete [] effect.second.data; 47 | }); 48 | 49 | m_effectMap.clear(); 50 | } 51 | 52 | const internalEffectData* EffectManager::getEffect(const RZEFFECTID& pEffectID) { 53 | const auto& entry = m_effectMap.find(pEffectID); 54 | 55 | if (entry == m_effectMap.end()) { 56 | return nullptr; 57 | } 58 | 59 | return &entry->second; 60 | } 61 | -------------------------------------------------------------------------------- /server-exe/EffectManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "utils.h" 3 | #include "../rpc-midl/rpc_retc.h" 4 | 5 | 6 | typedef struct internalEffectData { 7 | int type; 8 | RETCDeviceType deviceType; 9 | char *data; 10 | } internalEffectData; 11 | 12 | 13 | class EffectManager { 14 | public: 15 | static bool createUniqueEffectID(RZEFFECTID* guid) { return CoCreateGuid(guid) == S_OK; } 16 | 17 | ~EffectManager(); 18 | bool storeEffect(const RETCDeviceType& deviceType, int effectType, RZEFFECTID* pEffectID, efsize_t effectSize, const char effectData[]); 19 | bool deleteEffect(const RZEFFECTID& pEffectID); 20 | void clearEffects(); 21 | 22 | const internalEffectData* getEffect(const RZEFFECTID& pEffectID); 23 | 24 | private: 25 | std::unordered_map m_effectMap; 26 | }; 27 | -------------------------------------------------------------------------------- /server-exe/LightingSDK.h: -------------------------------------------------------------------------------- 1 | // This is an open source non-commercial project. Dear PVS-Studio, please check it. 2 | // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com 3 | 4 | #pragma once 5 | #include 6 | #include 7 | 8 | #include "../rpc-midl/rpc_retc.h" 9 | #include "SDKLoader.h" 10 | #include "commonData.h" 11 | #include "colorTransformation.h" 12 | #include "gammaTransformation.h" 13 | 14 | #define SDKLoaderAssignNameToVariable(func) func## _t func; 15 | #define SDKLoaderMapNameToFunction(func) func = (func## _t)m_dllFunctionList[#func]; 16 | #define MAX_CONFIG_SECTION_LEN (size_t)64 17 | 18 | class LightingSdk { 19 | public: 20 | LightingSdk() { 21 | m_sdkLoader = nullptr; 22 | m_dllInstance = nullptr; 23 | std::fill(m_supportedDevices, m_supportedDevices + ALL, FALSE); 24 | } 25 | 26 | virtual ~LightingSdk() { 27 | unloadDLL(); 28 | } 29 | 30 | virtual bool initialize() = 0; 31 | virtual void reset() = 0; 32 | virtual RZRESULT playEffect(RETCDeviceType device, int type, const char data[]) = 0; 33 | 34 | bool init(SdkLoader* sdkLoader) { 35 | if (m_sdkDll.empty() || m_sdkName.empty()) { 36 | LOG_W("Skipped an invalid SDK due to missing DLL_NAME."); 37 | return false; 38 | } 39 | 40 | const auto& sdkConfString = (SDK_SUB_CONFIG_SECTION + m_sdkName); 41 | std::copy_n(std::begin(sdkConfString), std::min(sdkConfString.length(), MAX_CONFIG_SECTION_LEN), m_sdkConfigSection); 42 | 43 | if (!CONFIG->GetBool(m_sdkConfigSection, L"enabled", true)) { 44 | LOG_D(L"{0} load aborted disabled by config.", m_sdkName); 45 | return false; 46 | } 47 | 48 | if (!sdkLoader->load(m_dllInstance, m_sdkDll, m_dllFunctionList)) { 49 | LOG_E(L"{0} failed to load, please check if an update is available.", m_sdkName); 50 | return false; 51 | } 52 | 53 | m_sdkLoader = sdkLoader; 54 | 55 | if (CONFIG->GetBool(m_sdkConfigSection, L"enable_colortransformations", true)) { 56 | LOG_D(L"{0} color transformations enabled.", m_sdkName); 57 | 58 | if (!initializeColorTransformations()) { 59 | LOG_E(L"{0}: Error while trying to initialize the color transformations, continuing with partial init.", m_sdkName); 60 | } 61 | } 62 | 63 | 64 | LOG_I(L"{0} loaded {1} initializing SDK.", m_sdkName, m_sdkDll); 65 | return initialize(); 66 | } 67 | 68 | bool initializeColorTransformations() { 69 | // Gamma adjustment 70 | auto gammaTransformationValues = CONFIG->GetVec3D(m_sdkConfigSection, L"gamma_adjustment", Vec3D()); 71 | if (!gammaTransformationValues.isZero()) { // Skip the transformation if we got the default vector. 72 | m_activeColorTransformations.insert(std::make_unique(gammaTransformationValues)); 73 | } 74 | 75 | return true; 76 | } 77 | 78 | // r,g,b used as input and output 79 | void TRANSFORM_COLORS(uint8_t&r, uint8_t&g, uint8_t &b) { 80 | for (const auto &transformation : m_activeColorTransformations) { 81 | transformation->apply(r, g, b); 82 | } 83 | } 84 | 85 | // r,g,b used as output 86 | void CONVERT_AND_TRANSFORM_COLORS(const COLORREF& color, uint8_t &r, uint8_t&g, uint8_t&b) { 87 | r = GetRValue(color); 88 | g = GetGValue(color); 89 | b = GetBValue(color); 90 | 91 | return TRANSFORM_COLORS(r, g, b); 92 | } 93 | 94 | void setSupportFor(const RETCDeviceType type, const BOOL support) { 95 | m_supportedDevices[type] = support; 96 | } 97 | 98 | void enableSupportFor(const RETCDeviceType type) { 99 | setSupportFor(type, TRUE); 100 | } 101 | 102 | void disableSupportFor(const RETCDeviceType type) { 103 | setSupportFor(type, FALSE); 104 | } 105 | 106 | bool hasSupportFor(const RETCDeviceType deviceId) const { return m_supportedDevices[deviceId] != FALSE; } 107 | 108 | supportArray_t& getSupportedModes() { return m_supportedDevices; } 109 | 110 | const std::string& getSDKDll() const { return m_sdkDll; } 111 | const std::wstring& getSDKName() const { return m_sdkName; } 112 | 113 | void disconnect() { 114 | // Dont call reset because we cant guarantee that the sdk checks for a valid dll. 115 | if (m_dllInstance != nullptr) { 116 | reset(); 117 | } 118 | 119 | m_activeColorTransformations.clear(); 120 | unloadDLL(); 121 | } 122 | 123 | void unloadDLL() const { 124 | if (!m_sdkLoader || m_dllInstance == nullptr) { 125 | return; 126 | } 127 | 128 | m_sdkLoader->unload(m_sdkDll); 129 | } 130 | 131 | protected: 132 | function_list m_dllFunctionList; 133 | std::string m_sdkDll; 134 | std::wstring m_sdkName; 135 | wchar_t m_sdkConfigSection[MAX_CONFIG_SECTION_LEN] = {0}; 136 | 137 | supportArray_t m_supportedDevices{}; 138 | 139 | // Color transformation 140 | std::set> m_activeColorTransformations; 141 | 142 | private: 143 | SdkLoader* m_sdkLoader; 144 | HINSTANCE m_dllInstance; 145 | }; 146 | -------------------------------------------------------------------------------- /server-exe/RPCReceiver.cpp: -------------------------------------------------------------------------------- 1 | // This is an open source non-commercial project. Dear PVS-Studio, please check it. 2 | // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com 3 | 4 | #include "RPCReceiver.h" 5 | 6 | long PROCESSING_DELAY = 0; 7 | 8 | void* __RPC_USER midl_user_allocate(size_t size) { 9 | return malloc(size); 10 | } 11 | 12 | void __RPC_USER midl_user_free(void* p) { 13 | free(p); 14 | } 15 | 16 | RPCReceiver::RPCReceiver() { 17 | m_RpcStatus = RPC_S_OK; 18 | PROCESSING_DELAY = CONFIG->GetLong(L"rpc", L"processingdelay", 0); 19 | } 20 | 21 | void RpcServerListenThreadProc() { 22 | RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, FALSE); 23 | } 24 | 25 | RPC_STATUS RPCReceiver::startListening() { 26 | m_RpcStatus = RpcServerUseProtseqEp(RPC_WSTR(L"ncalrpc"), 0, RPC_WSTR(L"[retc-rpc]"), nullptr); 27 | 28 | if (!STATUS_OK(m_RpcStatus)) { 29 | return m_RpcStatus; 30 | } 31 | 32 | m_RpcStatus = RpcServerRegisterIf2(rpc_retc_v2_5_s_ifspec, nullptr, nullptr, RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH, RPC_C_LISTEN_MAX_CALLS_DEFAULT, static_cast(-1), nullptr); 33 | 34 | if (!STATUS_OK(m_RpcStatus)) { 35 | return m_RpcStatus; 36 | } 37 | 38 | m_listenThread = std::thread(RpcServerListenThreadProc); 39 | 40 | return m_RpcStatus; 41 | } 42 | 43 | bool RPCReceiver::shutdown() { 44 | RpcMgmtStopServerListening(nullptr); 45 | if (m_listenThread.joinable()) { 46 | m_listenThread.join(); 47 | } 48 | return true; 49 | } 50 | 51 | void RPCReceiver::reset() { 52 | m_RpcStatus = RPC_S_OK; 53 | } 54 | 55 | void __RPC_USER CONTEXT_HANDLE_rundown(CONTEXT_HANDLE hContext) { 56 | disconnect(&hContext); 57 | } 58 | 59 | extern std::unique_ptr sdk_manager; 60 | 61 | CONTEXT_HANDLE initialize(handle_t /*hBinding*/, RETCClientConfig * config) { 62 | if (!sdk_manager->initialize()) { 63 | return nullptr; 64 | } 65 | 66 | *config = *sdk_manager->getClientConfig().get(); 67 | return config; // just return something, we dont need to uniquely identify clients 68 | } 69 | 70 | RZRESULT playEffect(const RETCDeviceType deviceType, const int type, RZEFFECTID* pEffectID, const efsize_t effectSize, char* effectData, CONTEXT_HANDLE) { 71 | if (PROCESSING_DELAY > 0) { 72 | std::this_thread::sleep_for(std::chrono::milliseconds(PROCESSING_DELAY)); 73 | } 74 | 75 | return sdk_manager->playEffect(deviceType, type, pEffectID, effectSize, effectData); 76 | } 77 | 78 | RZRESULT setEffect(const RZEFFECTID effID, CONTEXT_HANDLE) { //-V813 c code 79 | return sdk_manager->setEffect(effID); 80 | } 81 | 82 | RZRESULT deleteEffect(const RZEFFECTID effID, CONTEXT_HANDLE) { //-V813 c code 83 | return sdk_manager->deleteEffect(effID); 84 | } 85 | 86 | void disconnect(CONTEXT_HANDLE* phContext) { 87 | sdk_manager->disconnect(); 88 | *phContext = nullptr; 89 | } 90 | -------------------------------------------------------------------------------- /server-exe/RPCReceiver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../rpc-midl/rpc_retc.h" 3 | #include "SDKManager.h" 4 | #include 5 | 6 | #define STATUS_OK(x) ((x) == RPC_S_OK) 7 | 8 | class RPCReceiver { 9 | public: 10 | RPCReceiver(); 11 | RPC_STATUS startListening(); 12 | void reset(); 13 | 14 | bool shutdown(); 15 | 16 | private: 17 | void setStatus(const RPC_STATUS stat) { m_RpcStatus = stat; } 18 | RPC_STATUS getStatus() const { return m_RpcStatus; } 19 | 20 | RPC_STATUS m_RpcStatus; 21 | std::thread m_listenThread; 22 | }; 23 | -------------------------------------------------------------------------------- /server-exe/RazerSDK.cpp: -------------------------------------------------------------------------------- 1 | // This is an open source non-commercial project. Dear PVS-Studio, please check it. 2 | // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com 3 | 4 | #include "RazerSDK.h" 5 | #include 6 | 7 | /** 8 | * This sdk is just forwarding to the real dll. 9 | * WARNING: If the "real" dll is the patched stub we created, this will enter an endless loop! 10 | * NEVER CREATE GLOBAL DLL OVERWRITES in System32 with this SDK enabled. 11 | */ 12 | RazerSDK::RazerSDK() { 13 | this->m_sdkName = L"RazerPassthrough"; 14 | 15 | #ifdef _WIN64 16 | this->m_sdkDll = "RzChromaSDK64.dll"; 17 | #else 18 | this->m_sdkDll = "RzChromaSDK.dll"; 19 | #endif 20 | this->m_dllFunctionList = { 21 | {"Init", nullptr}, 22 | {"UnInit", nullptr}, 23 | {"CreateKeyboardEffect", nullptr}, 24 | {"CreateMouseEffect", nullptr}, 25 | {"CreateHeadsetEffect", nullptr}, 26 | {"CreateMousepadEffect", nullptr}, 27 | {"CreateKeypadEffect", nullptr}, 28 | {"CreateChromaLinkEffect", nullptr}, 29 | {"SetEffect", nullptr}, 30 | {"DeleteEffect", nullptr}, 31 | {"QueryDevice", nullptr} 32 | }; 33 | } 34 | 35 | // This allows the use of the Razer Chroma Emulators in debug. 36 | #if defined (_DEBUG) 37 | #define devicePhysicallyPresent false 38 | #else 39 | #define devicePhysicallyPresent deviceInfo.Connected == 1 40 | #endif 41 | 42 | bool RazerSDK::initialize() { 43 | // Initialize dll functions 44 | SDKLoaderMapNameToFunction(Init); 45 | SDKLoaderMapNameToFunction(UnInit); 46 | SDKLoaderMapNameToFunction(CreateKeyboardEffect); 47 | SDKLoaderMapNameToFunction(CreateMouseEffect); 48 | SDKLoaderMapNameToFunction(CreateHeadsetEffect); 49 | SDKLoaderMapNameToFunction(CreateMousepadEffect); 50 | SDKLoaderMapNameToFunction(CreateKeypadEffect); 51 | SDKLoaderMapNameToFunction(CreateChromaLinkEffect); 52 | SDKLoaderMapNameToFunction(SetEffect); 53 | SDKLoaderMapNameToFunction(DeleteEffect); 54 | SDKLoaderMapNameToFunction(QueryDevice); 55 | 56 | const auto res = Init(); 57 | if (res != RZRESULT_SUCCESS) { 58 | LOG_E("failed with code {0}", res); 59 | return false; 60 | } 61 | 62 | // Check for connected razer devices. 63 | DEVICE_INFO_TYPE deviceInfo = {}; 64 | for (const auto &razerdevguid : LookupArrays::razerDevices) { 65 | if (QueryDevice(razerdevguid, deviceInfo) == RZRESULT_SUCCESS && devicePhysicallyPresent) { 66 | auto deviceType = razerToRETCDeviceTYPE(deviceInfo); 67 | if (deviceType == ESIZE) { 68 | continue; 69 | } 70 | 71 | if (CONFIG->GetBool(m_sdkConfigSection, L"overwritedevices", true)) { 72 | auto findResult = std::find_if(std::begin(LookupMaps::razerStringToDevID), std::end(LookupMaps::razerStringToDevID), [&](const auto &pair) { 73 | return pair.second == razerdevguid; 74 | }); 75 | 76 | if (findResult == std::end(LookupMaps::razerStringToDevID)) { 77 | LOG->error("Connected device is not fully supported by this application, please report it: {}", guidToString(razerdevguid)); 78 | } 79 | else { 80 | LOG->info(L"Found valid razer device altering emulated device id: {}", findResult->first.c_str()); 81 | CONFIG->SetWString(SDK_MAIN_CONFIG_SECTION, LookupArrays::EM_KEYS[deviceType], findResult->first.c_str()); 82 | } 83 | } 84 | 85 | enableSupportFor(deviceType); 86 | } 87 | } 88 | 89 | return true; 90 | } 91 | 92 | void RazerSDK::reset() { 93 | UnInit(); 94 | } 95 | 96 | RZRESULT RazerSDK::playEffect(RETCDeviceType device, int type, const char data[]) { 97 | RZRESULT res; 98 | switch (device) { 99 | case KEYBOARD: 100 | res = CreateKeyboardEffect(static_cast(type), PRZPARAM(data), nullptr); 101 | break; 102 | case MOUSE: 103 | res = CreateMouseEffect(static_cast(type), PRZPARAM(data), nullptr); 104 | break; 105 | case HEADSET: 106 | res = CreateHeadsetEffect(static_cast(type), PRZPARAM(data), nullptr); 107 | break; 108 | case MOUSEPAD: 109 | res = CreateMousepadEffect(static_cast(type), PRZPARAM(data), nullptr); 110 | break; 111 | case KEYPAD: 112 | res = CreateKeypadEffect(static_cast(type), PRZPARAM(data), nullptr); 113 | break; 114 | case SYSTEM: 115 | res = CreateChromaLinkEffect(static_cast(type), PRZPARAM(data), nullptr); 116 | break; 117 | default: 118 | res = RZRESULT_INVALID; 119 | break; 120 | } 121 | 122 | #ifdef _DEBUG 123 | if (res != RZRESULT_SUCCESS) { 124 | LOG_D("failed with {0}", res); 125 | } 126 | #endif 127 | 128 | return res; 129 | } 130 | 131 | RETCDeviceType RazerSDK::razerToRETCDeviceTYPE(DEVICE_INFO_TYPE devType) { 132 | switch (devType.DeviceType) { 133 | case DEVICE_INFO_TYPE::DEVICE_KEYBOARD: 134 | return KEYBOARD; 135 | case DEVICE_INFO_TYPE::DEVICE_MOUSE: 136 | return MOUSE; 137 | case DEVICE_INFO_TYPE::DEVICE_HEADSET: 138 | return HEADSET; 139 | case DEVICE_INFO_TYPE::DEVICE_MOUSEPAD: 140 | return MOUSEPAD; 141 | case DEVICE_INFO_TYPE::DEVICE_KEYPAD: 142 | return KEYPAD; 143 | case DEVICE_INFO_TYPE::DEVICE_SYSTEM: 144 | return SYSTEM; 145 | case DEVICE_INFO_TYPE::DEVICE_INVALID: 146 | return ESIZE; 147 | default: 148 | return ESIZE; 149 | } 150 | } -------------------------------------------------------------------------------- /server-exe/RazerSDK.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "LightingSDK.h" 3 | using namespace ChromaSDK; 4 | 5 | class RazerSDK : public LightingSdk { 6 | public: 7 | RazerSDK(); 8 | 9 | bool initialize() override; 10 | void reset() override; 11 | RZRESULT playEffect(RETCDeviceType device, int type, const char data[]) override; 12 | static RETCDeviceType razerToRETCDeviceTYPE(DEVICE_INFO_TYPE devType); 13 | 14 | private: 15 | // DLL functions 16 | typedef RZRESULT (*Init_t)(); 17 | typedef RZRESULT (*UnInit_t)(); 18 | typedef RZRESULT (*CreateKeyboardEffect_t)(Keyboard::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId); 19 | typedef RZRESULT (*CreateMouseEffect_t)(Mouse::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId); 20 | typedef RZRESULT (*CreateHeadsetEffect_t)(Headset::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId); 21 | typedef RZRESULT (*CreateMousepadEffect_t)(Mousepad::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId); 22 | typedef RZRESULT (*CreateKeypadEffect_t)(Keypad::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId); 23 | typedef RZRESULT (*CreateChromaLinkEffect_t)(ChromaLink::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID* pEffectId); 24 | 25 | typedef RZRESULT (*SetEffect_t)(RZEFFECTID EffectId); 26 | typedef RZRESULT (*DeleteEffect_t)(RZEFFECTID EffectId); 27 | typedef RZRESULT (*QueryDevice_t)(RZDEVICEID EffectId, DEVICE_INFO_TYPE& DeviceInfo); 28 | 29 | SDKLoaderAssignNameToVariable(Init) 30 | SDKLoaderAssignNameToVariable(UnInit) 31 | SDKLoaderAssignNameToVariable(CreateKeyboardEffect) 32 | SDKLoaderAssignNameToVariable(CreateMouseEffect) 33 | SDKLoaderAssignNameToVariable(CreateHeadsetEffect) 34 | SDKLoaderAssignNameToVariable(CreateMousepadEffect) 35 | SDKLoaderAssignNameToVariable(CreateKeypadEffect) 36 | SDKLoaderAssignNameToVariable(CreateChromaLinkEffect) 37 | SDKLoaderAssignNameToVariable(SetEffect) 38 | SDKLoaderAssignNameToVariable(DeleteEffect) 39 | SDKLoaderAssignNameToVariable(QueryDevice) 40 | }; 41 | -------------------------------------------------------------------------------- /server-exe/SDKLoader.cpp: -------------------------------------------------------------------------------- 1 | // This is an open source non-commercial project. Dear PVS-Studio, please check it. 2 | // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com 3 | 4 | #include "SDKLoader.h" 5 | 6 | SdkLoader::~SdkLoader() { 7 | destroy(); 8 | } 9 | 10 | void SdkLoader::destroy() { 11 | for (const auto& inst : m_dllInstances) { 12 | FreeLibrary(inst.second); 13 | } 14 | 15 | m_dllInstances.clear(); 16 | } 17 | 18 | bool SdkLoader::load(HINSTANCE& inst, const std::string& name, function_list& fList) { 19 | // Force user to call reload. 20 | if (isLoaded(name)) { 21 | LOG_D("DLL already loaded you should call reload!"); 22 | return false; 23 | } 24 | 25 | inst = LoadLibraryA(name.c_str()); 26 | 27 | if (!inst) { 28 | LOG_E("LoadLibraryA({0}) failed with code {1}", name, GetLastError()); 29 | return false; 30 | } 31 | 32 | for (auto& func : fList) { 33 | const auto funcPtrName = func.first.c_str(); 34 | const auto fptr = reinterpret_cast(GetProcAddress(inst, funcPtrName)); 35 | if (!fptr) { 36 | LOG_E("Could not find required method {0}, please check {1}.", funcPtrName, name); 37 | FreeLibrary(inst); 38 | return false; 39 | } 40 | func.second = fptr; 41 | } 42 | 43 | m_dllInstances.insert(make_pair(name, inst)); 44 | return true; 45 | } 46 | 47 | bool SdkLoader::reload(HINSTANCE& inst, const std::string& dllName, function_list& fList) { 48 | auto res = unload(dllName); 49 | if (!res) { 50 | res = unload(inst); 51 | } 52 | 53 | if (!res) { 54 | return false; 55 | } 56 | 57 | return load(inst, dllName, fList); 58 | } 59 | 60 | bool SdkLoader::isLoaded(const std::string& name) { 61 | return m_dllInstances.find(name) != m_dllInstances.end(); 62 | } 63 | 64 | bool SdkLoader::unload(const std::string& name) { 65 | const auto elem = m_dllInstances.find(name); 66 | 67 | if (elem == m_dllInstances.end()) { 68 | return false; 69 | } 70 | 71 | FreeLibrary(elem->second); 72 | m_dllInstances.erase(elem); 73 | 74 | return true; 75 | } 76 | 77 | bool SdkLoader::unload(HINSTANCE& inst) { 78 | for (auto& func : m_dllInstances) { 79 | if (func.second != inst) { 80 | continue; 81 | } 82 | 83 | FreeLibrary(func.second); 84 | m_dllInstances.erase(func.first); 85 | return true; 86 | } 87 | 88 | return false; 89 | } 90 | -------------------------------------------------------------------------------- /server-exe/SDKLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "utils.h" 3 | #include 4 | #include 5 | 6 | using function_list = std::unordered_map; 7 | using dll_instances = std::unordered_map; 8 | 9 | class SdkLoader { 10 | public: 11 | SdkLoader() = default; 12 | ~SdkLoader(); 13 | 14 | bool load(HINSTANCE& inst, const std::string& name, function_list& fList); 15 | bool reload(HINSTANCE& inst, const std::string& dllName, function_list& fList); 16 | bool isLoaded(const std::string& name); 17 | bool unload(const std::string& name); 18 | bool unload(HINSTANCE& inst); 19 | 20 | private: 21 | void destroy(); 22 | 23 | // Only for internal use 24 | std::unordered_map m_dllInstances; 25 | }; 26 | -------------------------------------------------------------------------------- /server-exe/SDKManager.cpp: -------------------------------------------------------------------------------- 1 | // This is an open source non-commercial project. Dear PVS-Studio, please check it. 2 | // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com 3 | 4 | #include "SDKManager.h" 5 | #include "RzErrors.h" 6 | #include "RazerSDK.h" 7 | #include "CorsairSDK.h" 8 | 9 | SdkManager::SdkManager() { 10 | m_sdkLoader = std::make_shared(); 11 | m_effectManager = std::make_unique(); 12 | m_bIsInitialized = false; 13 | 14 | /** 15 | * Register your sdk here, make sure the RazerSDK is always at the beginning. 16 | */ 17 | m_availableSDKs.insert(std::make_shared()); 18 | m_availableSDKs.insert(std::make_shared()); 19 | 20 | m_clientConfig = std::make_shared(); 21 | reset(); 22 | } 23 | 24 | void SdkManager::reset() { 25 | for (auto &sdkList : m_selectedSDKs) { 26 | sdkList.clear(); 27 | } 28 | 29 | std::fill(m_clientConfig->supportedDeviceTypes, m_clientConfig->supportedDeviceTypes + ESIZE, FALSE); 30 | std::fill(m_clientConfig->emulatedDeviceIDS, m_clientConfig->emulatedDeviceIDS + ALL, GUID_NULL); 31 | 32 | m_bIsInitialized = false; 33 | } 34 | 35 | void SdkManager::disconnect() { 36 | LOG_I("Disconnected cleaning up session."); 37 | for (auto&& sdk : m_availableSDKs) { 38 | sdk->disconnect(); 39 | } 40 | 41 | reset(); 42 | m_effectManager->clearEffects(); 43 | } 44 | 45 | bool SdkManager::initialize() { 46 | if (m_bIsInitialized) { 47 | LOG_E("SDKManager already initialized."); 48 | LOG_I("Hint: Only one concurrent session supported"); 49 | return false; 50 | } 51 | 52 | checkAvailability(); 53 | 54 | reloadEmulatedDevices(); 55 | m_bIsInitialized = true; 56 | return true; 57 | } 58 | 59 | void SdkManager::reloadEmulatedDevices() const 60 | { 61 | using namespace LookupMaps; 62 | using namespace LookupArrays; 63 | 64 | for (int idx = KEYBOARD; idx < ALL; idx++) { 65 | // Razers api does not do HEADSET_STAND support properly, so skip this for now. 66 | if (idx == HEADSET_STAND) { 67 | continue; 68 | } 69 | 70 | std::wstring lastConfigValue = CONFIG->GetWString(SDK_MAIN_CONFIG_SECTION, EM_KEYS[idx], EM_VALS[idx]); 71 | auto it = LookupMaps::razerStringToDevID.find(lastConfigValue); 72 | 73 | if (it != LookupMaps::razerStringToDevID.end()) { 74 | m_clientConfig->emulatedDeviceIDS[idx] = it->second; 75 | LOG->debug(L"{0} set to {1}", EM_KEYS[idx], lastConfigValue); 76 | } 77 | else { 78 | LOG->error(L"Invalid {0} value: {1} using default: {2}", EM_KEYS[idx], lastConfigValue, EM_VALS[idx]); 79 | lastConfigValue = EM_VALS[idx]; 80 | m_clientConfig->emulatedDeviceIDS[idx] = LookupMaps::razerStringToDevID.at(lastConfigValue); 81 | } 82 | } 83 | } 84 | 85 | void SdkManager::checkAvailability() { 86 | auto hasAnySDK = false; 87 | for (auto&& sdk : m_availableSDKs) { 88 | if (!sdk->init(m_sdkLoader.get())) { 89 | LOG_T(L"an sdk failed to initialize {0}", sdk->getSDKName()); 90 | continue; 91 | } 92 | 93 | auto& supportedDevices = sdk->getSupportedModes(); 94 | for (int devID = KEYBOARD; devID < ALL; devID++) { 95 | // Check if the device is not supported 96 | if (supportedDevices[devID] == FALSE) { 97 | continue; 98 | } 99 | 100 | m_selectedSDKs[devID].insert(sdk); 101 | m_clientConfig->supportedDeviceTypes[devID] = TRUE; 102 | hasAnySDK = true; 103 | } 104 | } 105 | 106 | // Force enable the mousepad support if a headset_stand is connected, this does not assign a sdk! 107 | if (m_clientConfig->supportedDeviceTypes[MOUSEPAD] == FALSE && m_clientConfig->supportedDeviceTypes[HEADSET_STAND] != FALSE) { 108 | m_clientConfig->supportedDeviceTypes[MOUSEPAD] = TRUE; 109 | } 110 | 111 | if (hasAnySDK) { 112 | m_clientConfig->supportedDeviceTypes[ALL] = TRUE; 113 | } 114 | } 115 | 116 | RZRESULT SdkManager::playEffectOnAllSDKs(const int effectType, const char effectData[]) const { 117 | auto res = RZRESULT_NOT_SUPPORTED; 118 | for (int devId = KEYBOARD; devId < ALL; devId++) { 119 | for (const auto& sdk : m_selectedSDKs[devId]) { 120 | res = sdk->playEffect(static_cast(devId), effectType, effectData); 121 | if (res != RZRESULT_SUCCESS) { 122 | LOG_D(L"SDK: {0} failed to play an effect.", sdk->getSDKName()); 123 | } 124 | } 125 | } 126 | 127 | return res; 128 | } 129 | 130 | RZRESULT SdkManager::playbackEffect(const RETCDeviceType& devType, const int effectType, const char effectData[]) { 131 | if (devType == ALL) { 132 | return playEffectOnAllSDKs(effectType, effectData); 133 | } 134 | 135 | auto res = RZRESULT_NOT_FOUND; 136 | 137 | for (auto&& sdk : m_selectedSDKs[devType]) { 138 | res = sdk->playEffect(devType, effectType, effectData); 139 | } 140 | 141 | // *WORKAROUND ALERT!* Send fake data to headset_stands based on the mousepad data. 142 | if (devType == MOUSEPAD) { 143 | for (auto&& sdk : m_selectedSDKs[HEADSET_STAND]) { 144 | res = sdk->playEffect(HEADSET_STAND, effectType, effectData); 145 | } 146 | } 147 | 148 | return res; 149 | } 150 | 151 | RZRESULT SdkManager::playEffect(const RETCDeviceType& devType, const int effectType, RZEFFECTID* pEffectId, const efsize_t size, const char effectData[]) { 152 | // Do we need to store the effect? 153 | if (pEffectId != nullptr) { 154 | const auto guid = *pEffectId; 155 | // If the client supplied a 0-guid, we will give him a new one as effect reference. 156 | if (guid == GUID_NULL) { 157 | // dont play the new effect, as its pre-programmed and is going to be played by SetEffect 158 | return m_effectManager->storeEffect(devType, effectType, pEffectId, size, effectData) ? RZRESULT_SUCCESS : RZRESULT_FAILED; 159 | } 160 | 161 | // Fallthrough, due to razer api quirk => playback directly 162 | } 163 | 164 | return playbackEffect(devType, effectType, effectData); 165 | } 166 | 167 | RZRESULT SdkManager::deleteEffect(const RZEFFECTID& effId) const { 168 | return m_effectManager->deleteEffect(effId) ? RZRESULT_SUCCESS : RZRESULT_NOT_FOUND; 169 | } 170 | 171 | RZRESULT SdkManager::setEffect(const RZEFFECTID& effId) { 172 | const auto& effectEntry = m_effectManager->getEffect(effId); 173 | 174 | if (!effectEntry) { 175 | return RZRESULT_NOT_FOUND; 176 | } 177 | 178 | return playbackEffect(effectEntry->deviceType, effectEntry->type, effectEntry->data); 179 | } 180 | -------------------------------------------------------------------------------- /server-exe/SDKManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "utils.h" 4 | #include "SDKLoader.h" 5 | #include "EffectManager.h" 6 | 7 | #include 8 | #include "LightingSDK.h" 9 | 10 | using sdk_list = std::set>; 11 | 12 | class SdkManager { 13 | public: 14 | SdkManager(); 15 | ~SdkManager() = default; 16 | 17 | void reset(); 18 | void disconnect(); 19 | 20 | bool initialize(); 21 | void reloadEmulatedDevices() const; 22 | 23 | std::shared_ptr getClientConfig() const { return m_clientConfig; } 24 | 25 | RZRESULT deleteEffect(const RZEFFECTID& effId) const; 26 | RZRESULT setEffect(const RZEFFECTID& effId); 27 | RZRESULT playEffect(const RETCDeviceType& devType, int effectType, RZEFFECTID* pEffectId, efsize_t size, const char effectData[]); 28 | 29 | private: 30 | void checkAvailability(); 31 | RZRESULT playEffectOnAllSDKs(int effectType, const char effectData[]) const; 32 | RZRESULT playbackEffect(const RETCDeviceType& devType, int effectType, const char effectData[]); 33 | 34 | std::shared_ptr m_sdkLoader; 35 | 36 | std::unique_ptr m_effectManager; 37 | sdk_list m_availableSDKs; 38 | 39 | std::shared_ptr m_clientConfig; 40 | 41 | std::array m_selectedSDKs; 42 | bool m_bIsInitialized{}; 43 | }; 44 | -------------------------------------------------------------------------------- /server-exe/Server.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartB/RETC/27a64e93d509c2412e18ede5dc513cece187bc70/server-exe/Server.rc -------------------------------------------------------------------------------- /server-exe/colorTransformation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | class ColorTransformation { 3 | public: 4 | virtual ~ColorTransformation() = default; 5 | // r,g,b must be 0-255 anything else might result in undefined behaviour. 6 | virtual void apply(uint8_t&r, uint8_t&g, uint8_t&b) = 0; 7 | }; -------------------------------------------------------------------------------- /server-exe/commonData.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../rpc-midl/rpc_retc.h" 3 | #include 4 | #include 5 | #include 6 | 7 | constexpr auto SDK_MAIN_CONFIG_SECTION = L"sdk"; 8 | constexpr auto SDK_SUB_CONFIG_SECTION = L"sdk."; 9 | 10 | namespace LookupArrays { 11 | using namespace ChromaSDK; 12 | static const int genericEffectType[ALL][CHROMA_RESERVED] = { 13 | {Keyboard::CHROMA_NONE ,Keyboard::CHROMA_WAVE, Keyboard::CHROMA_SPECTRUMCYCLING, Keyboard::CHROMA_BREATHING, -1 , Keyboard::CHROMA_REACTIVE, Keyboard::CHROMA_STATIC, Keyboard::CHROMA_CUSTOM}, 14 | {Mouse::CHROMA_NONE, Mouse::CHROMA_WAVE, Mouse::CHROMA_SPECTRUMCYCLING, Mouse::CHROMA_BREATHING, Mouse::CHROMA_BLINKING, Mouse::CHROMA_REACTIVE, Mouse::CHROMA_STATIC, Mouse::CHROMA_CUSTOM2}, 15 | {Headset::CHROMA_NONE, -1, Headset::CHROMA_SPECTRUMCYCLING, Headset::CHROMA_BREATHING, -1, -1, Headset::CHROMA_STATIC, Headset::CHROMA_CUSTOM}, // Headset 16 | {Mousepad::CHROMA_NONE, Mousepad::CHROMA_WAVE, Mousepad::CHROMA_SPECTRUMCYCLING, Mousepad::CHROMA_BREATHING, -1, -1, Mousepad::CHROMA_STATIC, Mousepad::CHROMA_CUSTOM}, // Mousepad 17 | {Keypad::CHROMA_NONE, Keypad::CHROMA_WAVE, Keypad::CHROMA_SPECTRUMCYCLING, Keypad::CHROMA_BREATHING, -1, Keypad::CHROMA_REACTIVE, Keypad::CHROMA_STATIC, Keypad::CHROMA_CUSTOM}, // Keypad 18 | {ChromaLink::CHROMA_NONE, -1, -1, -1, -1, -1, ChromaLink::CHROMA_STATIC, ChromaLink::CHROMA_CUSTOM }, // System leds aka chroma link 19 | {-1, 1, -1, -1, -1, -1, -1, -1} // Headset Stand leds (no corresponding device for razer => api defect) 20 | }; 21 | 22 | static const efsize_t effectSize[ESIZE][CHROMA_RESERVED] = { 23 | {sizeof(Keyboard::BREATHING_EFFECT_TYPE), sizeof(Keyboard::CUSTOM_EFFECT_TYPE), sizeof(Keyboard::REACTIVE_EFFECT_TYPE), sizeof(Keyboard::STATIC_EFFECT_TYPE), sizeof(SPECTRUMCYCLING_EFFECT_TYPE), sizeof(WAVE_EFFECT_TYPE), 0, sizeof(Keyboard::CUSTOM_KEY_EFFECT_TYPE)}, 24 | {sizeof(Mouse::BLINKING_EFFECT_TYPE), sizeof(Keyboard::BREATHING_EFFECT_TYPE), sizeof(Keyboard::CUSTOM_EFFECT_TYPE), sizeof(Keyboard::REACTIVE_EFFECT_TYPE), sizeof(SPECTRUMCYCLING_EFFECT_TYPE), sizeof(STATIC_EFFECT_TYPE), sizeof(WAVE_EFFECT_TYPE), sizeof(Mouse::CUSTOM_EFFECT_TYPE2)}, 25 | {sizeof(Headset::STATIC_EFFECT_TYPE), sizeof(Headset::BREATHING_EFFECT_TYPE), sizeof(SPECTRUMCYCLING_EFFECT_TYPE), sizeof(Headset::CUSTOM_EFFECT_TYPE), 0, 0, 0, 0}, 26 | {sizeof(Mousepad::BREATHING_EFFECT_TYPE), sizeof(Mousepad::CUSTOM_EFFECT_TYPE), sizeof(SPECTRUMCYCLING_EFFECT_TYPE), sizeof(Mousepad::STATIC_EFFECT_TYPE), sizeof(Mousepad::WAVE_EFFECT_TYPE), 0, 0, 0}, 27 | {sizeof(Keypad::BREATHING_EFFECT_TYPE), sizeof(Keypad::CUSTOM_EFFECT_TYPE), sizeof(Keypad::REACTIVE_EFFECT_TYPE), sizeof(SPECTRUMCYCLING_EFFECT_TYPE), sizeof(Keypad::STATIC_EFFECT_TYPE), sizeof(Keypad::WAVE_EFFECT_TYPE), 0, 0}, 28 | {sizeof(ChromaLink::CUSTOM_EFFECT_TYPE), sizeof(ChromaLink::STATIC_EFFECT_TYPE), 0, 0, 0, 0, 0, 0}, 29 | {0, 0, 0, 0, 0, 0, 0, 0,}, // Headset Stand leds (no corresponding device for razer => api defect) 30 | {sizeof(WAVE_EFFECT_TYPE), sizeof(SPECTRUMCYCLING_EFFECT_TYPE), sizeof(BREATHING_EFFECT_TYPE), sizeof(BLINKING_EFFECT_TYPE), sizeof(REACTIVE_EFFECT_TYPE), sizeof(STATIC_EFFECT_TYPE), sizeof(CUSTOM_EFFECT_TYPE), 0} 31 | }; 32 | 33 | static const GUID razerDevices[] = { 34 | // Keyboards 35 | BLACKWIDOW_CHROMA, BLACKWIDOW_CHROMA_TE, DEATHSTALKER_CHROMA, OVERWATCH_KEYBOARD, BLACKWIDOW_X_CHROMA, 36 | BLACKWIDOW_X_TE_CHROMA, OMATA_CHROMA, BLADE_STEALTH, BLADE, BLADE_PRO, BLACKWIDOW_CHROMA2, 37 | // Mice 38 | DEATHADDER_CHROMA, MAMBA_CHROMA_TE, DIAMONDBACK_CHROMA, MAMBA_CHROMA, NAGA_EPIC_CHROMA, NAGA_CHROMA, 39 | OROCHI_CHROMA, NAGA_HEX_CHROMA, DEATHADDER_ELITE_CHROMA, 40 | // Headsets 41 | KRAKEN71_CHROMA, MANOWAR_CHROMA, KRAKEN71_REFRESH_CHROMA, 42 | // Mousepads 43 | FIREFLY_CHROMA, 44 | // Keypads 45 | TARTARUS_CHROMA , ORBWEAVER_CHROMA, 46 | // Systems 47 | LENOVO_Y900, LENOVO_Y27, CORE_CHROMA 48 | }; 49 | 50 | // Emulated device related values 51 | static const wchar_t* EM_KEYS[] = { L"EM_KEYBOARD", L"EM_MOUSE", L"EM_HEADSET", L"EM_MOUSEPAD", L"EM_KEYPAD", L"EM_SYSTEM", L"!EM_!INVALID_HEADSET_STAND!" }; 52 | static const wchar_t* EM_VALS[] = { L"BLACKWIDOW_CHROMA", L"MAMBA_CHROMA", L"KRAKEN71_CHROMA", L"FIREFLY_CHROMA", L"ORBWEAVER_CHROMA", L"LENOVO_Y900", nullptr}; 53 | 54 | } 55 | 56 | namespace LookupMaps { 57 | using namespace ChromaSDK; 58 | 59 | static const std::map razerStringToDevID = { 60 | { L"BLACKWIDOW_CHROMA", BLACKWIDOW_CHROMA }, 61 | { L"BLACKWIDOW_CHROMA_TE", BLACKWIDOW_CHROMA_TE }, 62 | { L"DEATHSTALKER_CHROMA", DEATHSTALKER_CHROMA }, 63 | { L"OVERWATCH_KEYBOARD", OVERWATCH_KEYBOARD }, 64 | { L"BLACKWIDOW_X_CHROMA", BLACKWIDOW_X_CHROMA }, 65 | { L"BLACKWIDOW_X_TE_CHROMA", BLACKWIDOW_X_TE_CHROMA }, 66 | { L"OMATA_CHROMA", OMATA_CHROMA }, 67 | { L"BLADE_STEALTH", BLADE_STEALTH }, 68 | { L"BLADE", BLADE }, 69 | { L"BLADE_PRO", BLADE_PRO}, 70 | { L"BLACKWIDOW_CHROMA2", BLACKWIDOW_CHROMA2}, 71 | { L"DEATHADDER_CHROMA", DEATHADDER_CHROMA }, 72 | { L"MAMBA_CHROMA_TE", MAMBA_CHROMA_TE }, 73 | { L"DIAMONDBACK_CHROMA", DIAMONDBACK_CHROMA }, 74 | { L"MAMBA_CHROMA", MAMBA_CHROMA }, 75 | { L"NAGA_EPIC_CHROMA", NAGA_EPIC_CHROMA }, 76 | { L"NAGA_CHROMA", NAGA_CHROMA }, 77 | { L"OROCHI_CHROMA", OROCHI_CHROMA }, 78 | { L"NAGA_HEX_CHROMA", NAGA_HEX_CHROMA }, 79 | { L"DEATHADDER_ELITE_CHROMA", DEATHADDER_ELITE_CHROMA }, 80 | { L"KRAKEN71_CHROMA", KRAKEN71_CHROMA }, 81 | { L"MANOWAR_CHROMA", MANOWAR_CHROMA }, 82 | { L"KRAKEN71_REFRESH_CHROMA", KRAKEN71_REFRESH_CHROMA }, 83 | { L"FIREFLY_CHROMA", FIREFLY_CHROMA }, 84 | { L"TARTARUS_CHROMA", TARTARUS_CHROMA }, 85 | { L"ORBWEAVER_CHROMA", ORBWEAVER_CHROMA }, 86 | { L"LENOVO_Y900", LENOVO_Y900 }, 87 | { L"LENOVO_Y27", LENOVO_Y27 }, 88 | { L"CORE_CHROMA", CORE_CHROMA } 89 | }; 90 | } -------------------------------------------------------------------------------- /server-exe/gammaTransformation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "colorTransformation.h" 4 | 5 | class GammaTransformation : public ColorTransformation 6 | { 7 | 8 | public: 9 | GammaTransformation(Vec3D transformationValues) { 10 | LOG_I("Settings: r: {0} g: {1} b: {2}", transformationValues.x, transformationValues.y, transformationValues.z); 11 | // Create rgb gamma lookup table on startup => more performance 12 | for (auto i = 0; i <= 255; i++) { 13 | m_gammaArrayValues[RGB_CHANNELS::R][i] = (transformationValues.x != 0.0f) ? static_cast(pow(i / 255.0, 1.0 / transformationValues.x) * 255.0) : 0; //-V550 14 | m_gammaArrayValues[RGB_CHANNELS::G][i] = (transformationValues.y != 0.0f) ? static_cast(pow(i / 255.0, 1.0 / transformationValues.y) * 255.0) : 0; //-V550 15 | m_gammaArrayValues[RGB_CHANNELS::B][i] = (transformationValues.z != 0.0f) ? static_cast(pow(i / 255.0, 1.0 / transformationValues.z) * 255.0) : 0; //-V550 16 | } 17 | 18 | } 19 | 20 | void apply(uint8_t&r, uint8_t&g, uint8_t&b) override 21 | { 22 | r = m_gammaArrayValues[RGB_CHANNELS::R][r]; 23 | g = m_gammaArrayValues[RGB_CHANNELS::G][g]; 24 | b = m_gammaArrayValues[RGB_CHANNELS::B][b]; 25 | } 26 | 27 | private: 28 | enum RGB_CHANNELS { 29 | R, 30 | G, 31 | B, 32 | MAX 33 | }; 34 | 35 | typedef std::array, RGB_CHANNELS::MAX> RGB_GAMMA_ARRAY; 36 | RGB_GAMMA_ARRAY m_gammaArrayValues{}; 37 | }; 38 | -------------------------------------------------------------------------------- /server-exe/server.cpp: -------------------------------------------------------------------------------- 1 | // This is an open source non-commercial project. Dear PVS-Studio, please check it. 2 | // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com 3 | 4 | #include "RPCReceiver.h" 5 | #include 6 | 7 | // Global vars 8 | std::unique_ptr rpcReceiver(nullptr); 9 | std::unique_ptr sdk_manager(nullptr); 10 | std::unique_ptr CONFIG(nullptr); 11 | std::shared_ptr LOG(nullptr); 12 | 13 | // Main 14 | bool userCancelled = false; 15 | std::condition_variable cv; 16 | 17 | void cleanup() { 18 | if (rpcReceiver) { 19 | //-V547 20 | rpcReceiver->shutdown(); 21 | rpcReceiver.reset(); 22 | } 23 | 24 | if (sdk_manager) { 25 | //-V547 26 | sdk_manager.reset(); 27 | } 28 | 29 | if (CONFIG) { 30 | //-V547 31 | if (!CONFIG->SaveConfig()) { 32 | LOG->error("Failed to save config file."); 33 | } 34 | } 35 | } 36 | 37 | extern void requestTermination() { 38 | userCancelled = true; 39 | cv.notify_all(); 40 | } 41 | 42 | BOOL WINAPI consoleHandler(DWORD signal) { 43 | switch (signal) { 44 | case CTRL_C_EVENT: 45 | case CTRL_CLOSE_EVENT: 46 | requestTermination(); 47 | return TRUE; 48 | default: 49 | return FALSE; 50 | } 51 | } 52 | 53 | 54 | #if defined(_DEBUG) 55 | #define DEF_LOG_LEVEL spdlog::level::trace 56 | #define DEF_FLUSH_LEVEL spdlog::level::trace 57 | #else 58 | #define DEF_LOG_LEVEL spdlog::level::warn 59 | #define DEF_FLUSH_LEVEL spdlog::level::err 60 | #endif 61 | 62 | int SVCWorkerThread() { 63 | CONFIG.reset(new ConfigManager()); 64 | 65 | try { 66 | std::vector sinks; 67 | sinks.emplace_back(std::make_shared()); 68 | sinks.emplace_back(std::make_shared("server.log")); 69 | LOG = std::make_shared("logger", begin(sinks), end(sinks)); 70 | 71 | LOG->set_pattern(CONFIG->GetAsciiString(L"log", L"format", L"[%d.%m %H:%M:%S.%e][%l] %v")); 72 | spdlog::set_async_mode(1024); 73 | 74 | LOG->set_level(static_cast(CONFIG->GetLong(L"log", L"level", DEF_LOG_LEVEL))); 75 | LOG->flush_on(static_cast(CONFIG->GetLong(L"log", L"flush", DEF_FLUSH_LEVEL))); 76 | 77 | spdlog::set_error_handler([](const std::string& msg) { 78 | LOG->error("ERR: {}", msg); 79 | }); 80 | } 81 | catch (const spdlog::spdlog_ex& ex) { 82 | std::cout << "Log init failed: " << ex.what() << std::endl; 83 | return ERROR_CANTOPEN; 84 | } 85 | 86 | if (!SetConsoleCtrlHandler(consoleHandler, TRUE)) { 87 | LOG_E("Setting the console handler failed"); 88 | return ERROR_INVALID_HANDLE; 89 | } 90 | 91 | sdk_manager.reset(new SdkManager()); 92 | rpcReceiver.reset(new RPCReceiver()); 93 | 94 | const auto rpcStatus = rpcReceiver->startListening(); 95 | if (!STATUS_OK(rpcStatus)) { 96 | LOG_E(L"Starting the remote server failed, please make sure no other RETC instance is active. rpc-code: {0}", rpcStatus); 97 | cleanup(); 98 | return -1; 99 | } 100 | 101 | // We dont have stuff to do for now so we will just keep sleeping. 102 | std::mutex m; 103 | std::unique_lock lock(m); 104 | while (!userCancelled) { 105 | cv.wait(lock); 106 | } 107 | 108 | // Dont put code below this just add all your exit code to cleanup() 109 | cleanup(); 110 | return ERROR_SUCCESS; 111 | } 112 | -------------------------------------------------------------------------------- /server-exe/server.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "SDKManager.h" -------------------------------------------------------------------------------- /server-exe/server.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | src\SDKS\Corsair 6 | 7 | 8 | src\SDKS 9 | 10 | 11 | src\Network 12 | 13 | 14 | src\SDKS 15 | 16 | 17 | src\SDKS\Loader 18 | 19 | 20 | src 21 | 22 | 23 | src\Network\midl 24 | 25 | 26 | 27 | src\config 28 | 29 | 30 | src\SDKS\Razer 31 | 32 | 33 | src\Service 34 | 35 | 36 | 37 | 38 | src\common 39 | 40 | 41 | src\SDKS\Corsair 42 | 43 | 44 | src\Network 45 | 46 | 47 | src\SDKS 48 | 49 | 50 | src\SDKS\Loader 51 | 52 | 53 | src 54 | 55 | 56 | src\Network\midl 57 | 58 | 59 | src\common 60 | 61 | 62 | src\config 63 | 64 | 65 | src\SDKS\Razer 66 | 67 | 68 | src\ColorTransformations 69 | 70 | 71 | src\ColorTransformations 72 | 73 | 74 | 75 | 76 | {a85d222a-a239-4d86-a7e0-a6e4f6bbd66f} 77 | 78 | 79 | {904c91bc-2233-4c06-b898-db2d9b25ded8} 80 | 81 | 82 | {ed4616c2-395e-4b91-ac55-933f237b5c0c} 83 | 84 | 85 | {11dff16a-e72a-410b-b782-daab078f6142} 86 | 87 | 88 | {08a5cc24-9699-4266-81d7-376e688f74d9} 89 | 90 | 91 | {668ad942-dd8e-4bae-89f0-519231b81b2b} 92 | 93 | 94 | {561a4838-9ff0-4712-a77c-3d8bb40299bc} 95 | 96 | 97 | {257a3bb1-57b1-47b6-8b6b-68ecd7f81933} 98 | 99 | 100 | {ff229edb-146c-4197-b65d-6bbacf6acd32} 101 | 102 | 103 | {df5eb91d-a00f-447a-ad13-7f730bd8ac7e} 104 | 105 | 106 | {67b8e0d1-ca60-4d52-bf26-c456682a4ad1} 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /server-exe/service.cpp: -------------------------------------------------------------------------------- 1 | // This is an open source non-commercial project. Dear PVS-Studio, please check it. 2 | // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define SVC_NAME _T("RETC") 9 | #define SVC_FNAME _T("RETC Service") 10 | #define SVC_DESC _T("Allows programs that support the Razer Chroma SDK to use Corsair RGB devices. Visit https://github.com/MartB/RETC for more info.") 11 | 12 | // Forward declarations 13 | extern void requestTermination(); 14 | 15 | void InstallService(); 16 | void RemoveService(); 17 | VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv); 18 | VOID WINAPI ServiceController(DWORD); 19 | int SVCWorkerThread(); 20 | 21 | 22 | SERVICE_STATUS_HANDLE g_StatusHandle = nullptr; 23 | SERVICE_STATUS g_ServiceStatus = {0}; 24 | SERVICE_TABLE_ENTRY ServiceTableEntry[] = 25 | { 26 | {SVC_NAME, static_cast(ServiceMain)}, 27 | {nullptr, nullptr} 28 | }; 29 | 30 | int _tmain(const int argc, TCHAR* argv[]) { 31 | if (argc > 1) { 32 | if (wcscmp(argv[1], _T("install_service")) == 0) { 33 | InstallService(); 34 | return EXIT_SUCCESS; 35 | } 36 | 37 | if (wcscmp(argv[1], _T("remove_service")) == 0) { 38 | RemoveService(); 39 | return EXIT_SUCCESS; 40 | } 41 | } 42 | 43 | if (StartServiceCtrlDispatcher(ServiceTableEntry) == FALSE) { 44 | OutputDebugString(_T("Service start failed, falling back to normal launch.")); 45 | SVCWorkerThread(); 46 | return GetLastError(); 47 | } 48 | 49 | return EXIT_SUCCESS; 50 | } 51 | 52 | VOID WINAPI ServiceMain(DWORD, LPTSTR*) { 53 | g_StatusHandle = RegisterServiceCtrlHandler(SVC_NAME, ServiceController); 54 | 55 | if (g_StatusHandle == nullptr) { 56 | OutputDebugString(_T("RegisterServiceCtrlHandler failed")); 57 | return; 58 | } 59 | 60 | ZeroMemory(&g_ServiceStatus, sizeof(g_ServiceStatus)); 61 | g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 62 | g_ServiceStatus.dwControlsAccepted = 0; 63 | g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; 64 | g_ServiceStatus.dwWin32ExitCode = 0; 65 | g_ServiceStatus.dwServiceSpecificExitCode = 0; 66 | g_ServiceStatus.dwCheckPoint = 0; 67 | 68 | SetServiceStatus(g_StatusHandle, &g_ServiceStatus); 69 | 70 | // Start service thread 71 | auto serviceThread = std::thread([=] { 72 | SVCWorkerThread(); 73 | }); 74 | 75 | g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; 76 | g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; 77 | g_ServiceStatus.dwWin32ExitCode = 0; 78 | g_ServiceStatus.dwCheckPoint = 1; 79 | 80 | SetServiceStatus(g_StatusHandle, &g_ServiceStatus); 81 | 82 | // Wait until the server terminates 83 | serviceThread.join(); 84 | 85 | g_ServiceStatus.dwControlsAccepted = 0; 86 | g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; 87 | g_ServiceStatus.dwWin32ExitCode = 0; 88 | g_ServiceStatus.dwCheckPoint = 0; 89 | 90 | SetServiceStatus(g_StatusHandle, &g_ServiceStatus); 91 | } 92 | 93 | VOID WINAPI ServiceController(const DWORD ctrlCode) { 94 | if (ctrlCode != SERVICE_CONTROL_STOP) { 95 | return; 96 | } 97 | 98 | if (g_ServiceStatus.dwCurrentState != SERVICE_RUNNING) { 99 | return; 100 | } 101 | 102 | g_ServiceStatus.dwControlsAccepted = 0; 103 | g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; 104 | g_ServiceStatus.dwWin32ExitCode = 0; 105 | g_ServiceStatus.dwCheckPoint = 0; 106 | 107 | SetServiceStatus(g_StatusHandle, &g_ServiceStatus); 108 | 109 | // Call termination function in server.cpp 110 | requestTermination(); 111 | } 112 | 113 | void InstallService() { 114 | wchar_t szPath[MAX_PATH]; 115 | if (GetModuleFileName(nullptr, szPath, ARRAYSIZE(szPath)) == 0) { 116 | wprintf(L"GetModuleFileName err 0x%08lx\n", GetLastError()); 117 | return; 118 | } 119 | 120 | const auto svcManager = OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE); 121 | if (svcManager == nullptr) { 122 | wprintf(L"OpenSCManager err 0x%08lx\n", GetLastError()); 123 | return; 124 | } 125 | 126 | const auto svc = CreateService( 127 | svcManager, 128 | SVC_NAME, 129 | _T("RETC Service"), 130 | SERVICE_CHANGE_CONFIG | SERVICE_START, 131 | SERVICE_WIN32_OWN_PROCESS, 132 | SERVICE_AUTO_START, 133 | SERVICE_ERROR_NORMAL, 134 | szPath, 135 | nullptr, 136 | nullptr, 137 | nullptr, 138 | nullptr, 139 | nullptr 140 | ); 141 | 142 | if (svc == nullptr) { 143 | CloseServiceHandle(svcManager); 144 | 145 | const auto lastErrorCode = GetLastError(); 146 | if (lastErrorCode == ERROR_SERVICE_EXISTS) { 147 | RemoveService(); 148 | InstallService(); 149 | return; 150 | } 151 | 152 | wprintf(L"CreateService err 0x%08lx\n", GetLastError()); 153 | return; 154 | } 155 | 156 | wprintf(L"Installed %s service.\n", SVC_NAME); 157 | 158 | SERVICE_FAILURE_ACTIONS servFailActions; 159 | SC_ACTION failActions[3]; 160 | failActions[0].Type = SC_ACTION_RESTART; 161 | failActions[0].Delay = 2000; 162 | failActions[1].Type = SC_ACTION_RESTART; 163 | failActions[1].Delay = 2000; 164 | failActions[2].Type = SC_ACTION_RESTART; 165 | failActions[2].Delay = 2000; 166 | 167 | servFailActions.dwResetPeriod = 60 * 60 * 24; 168 | servFailActions.lpCommand = nullptr; 169 | servFailActions.lpRebootMsg = nullptr; 170 | servFailActions.cActions = 3; 171 | servFailActions.lpsaActions = failActions; 172 | 173 | ChangeServiceConfig2(svc, SERVICE_CONFIG_FAILURE_ACTIONS, &servFailActions); 174 | 175 | SERVICE_DESCRIPTION description = { 176 | SVC_DESC 177 | }; 178 | 179 | ChangeServiceConfig2(svc, SERVICE_CONFIG_DESCRIPTION, &description); 180 | 181 | // Start service 182 | StartService(svc, 0, nullptr); 183 | 184 | CloseServiceHandle(svcManager); 185 | CloseServiceHandle(svc); 186 | } 187 | 188 | 189 | void RemoveService() { 190 | 191 | // Open the local default service control manager database 192 | const auto svcManager = OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT); 193 | if (svcManager == nullptr) { 194 | wprintf(L"OpenSCManager err 0x%08lx\n", GetLastError()); 195 | return; 196 | } 197 | 198 | // Open the service with delete, stop, and query status permissions 199 | const auto svc = OpenService(svcManager, SVC_NAME, SERVICE_STOP | 200 | SERVICE_QUERY_STATUS | DELETE); 201 | if (svc == nullptr) { 202 | wprintf(L"OpenService failed w/err 0x%08lx\n", GetLastError()); 203 | CloseServiceHandle(svcManager); 204 | return; 205 | } 206 | 207 | SERVICE_STATUS ssSvcStatus = {}; 208 | if (ControlService(svc, SERVICE_CONTROL_STOP, &ssSvcStatus)) { 209 | wprintf(L"Stopping %s.", SVC_NAME); 210 | Sleep(500); 211 | 212 | while (QueryServiceStatus(svc, &ssSvcStatus)) { 213 | if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING) { 214 | Sleep(500); 215 | } 216 | else break; 217 | } 218 | #ifdef _DEBUG 219 | if (ssSvcStatus.dwCurrentState == SERVICE_STOPPED) { 220 | wprintf(L"service stopped.\n"); 221 | } 222 | else { 223 | wprintf(L"failed to stop service.\n"); 224 | } 225 | #endif 226 | } 227 | 228 | if (!DeleteService(svc)) { 229 | wprintf(L"DeleteService err 0x%08lx\n", GetLastError()); 230 | CloseServiceHandle(svcManager); 231 | CloseServiceHandle(svc); 232 | return; 233 | } 234 | 235 | wprintf(L"Removed %s service.\n", SVC_NAME); 236 | 237 | CloseServiceHandle(svcManager); 238 | CloseServiceHandle(svc); 239 | } 240 | -------------------------------------------------------------------------------- /server-exe/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "spdlog/spdlog.h" 3 | #include "ConfigManager.h" 4 | #include 5 | 6 | namespace std { 7 | template <> 8 | struct hash { 9 | size_t operator()(const GUID& guid) const noexcept { 10 | const auto p = reinterpret_cast(&guid); 11 | const hash hash; 12 | return hash(p[0]) ^ hash(p[1]); 13 | } 14 | }; 15 | } 16 | 17 | inline std::string guidToString(REFGUID guid) { 18 | char szGuid[40] = { 0 }; 19 | sprintf_s(szGuid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); 20 | return szGuid; 21 | } 22 | 23 | #define mkwordhilo(hi,lo) ((hi << 8) | lo); 24 | #define LOBYTE(w) ((BYTE)(((DWORD_PTR)(w)) & 0xff)) 25 | #define HIBYTE(w) ((BYTE)((((DWORD_PTR)(w)) >> 8) & 0xff)) 26 | 27 | extern std::unique_ptr CONFIG; 28 | extern std::shared_ptr LOG; 29 | #define LOG_E(...) LOG->error("[" __FUNCTION__ "] " __VA_ARGS__) 30 | #define LOG_W(...) LOG->warn("[" __FUNCTION__"] " __VA_ARGS__) 31 | #define LOG_I(...) LOG->info("[" __FUNCTION__"] " __VA_ARGS__) 32 | #define LOG_D(...) LOG->debug("[" __FUNCTION__"] " __VA_ARGS__) 33 | #define LOG_T(...) SPDLOG_TRACE(LOG, __VA_ARGS__); 34 | -------------------------------------------------------------------------------- /shim-dll/.gitignore: -------------------------------------------------------------------------------- 1 | version.h -------------------------------------------------------------------------------- /shim-dll/ShimDLL.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MartB/RETC/27a64e93d509c2412e18ede5dc513cece187bc70/shim-dll/ShimDLL.rc -------------------------------------------------------------------------------- /shim-dll/shim.cpp: -------------------------------------------------------------------------------- 1 | // This is an open source non-commercial project. Dear PVS-Studio, please check it. 2 | // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com 3 | 4 | #include 5 | #include "../rpc-midl/rpc_retc.h" 6 | #include "../server-exe/commonData.h" 7 | #include "RzErrors.h" 8 | #include "RzChromaSDKTypes.h" 9 | using namespace ChromaSDK; 10 | 11 | #define RzApi extern "C" __declspec (dllexport) 12 | 13 | RzApi RZRESULT Init(); 14 | RzApi RZRESULT UnInit(); 15 | 16 | RzApi RZRESULT CreateEffect(RZDEVICEID deviceId, EFFECT_TYPE effectId, PRZPARAM pParam, RZEFFECTID* pEffectId); 17 | RzApi RZRESULT CreateKeyboardEffect(Keyboard::EFFECT_TYPE effect, PRZPARAM pParam, RZEFFECTID* pEffectId); 18 | RzApi RZRESULT CreateMouseEffect(Mouse::EFFECT_TYPE effect, PRZPARAM pParam, RZEFFECTID* pEffectId); 19 | RzApi RZRESULT CreateHeadsetEffect(Headset::EFFECT_TYPE effect, PRZPARAM pParam, RZEFFECTID* pEffectId); 20 | RzApi RZRESULT CreateMousepadEffect(Mousepad::EFFECT_TYPE effect, PRZPARAM pParam, RZEFFECTID* pEffectId); 21 | RzApi RZRESULT CreateKeypadEffect(Keypad::EFFECT_TYPE effect, PRZPARAM pParam, RZEFFECTID* pEffectId); 22 | RzApi RZRESULT CreateChromaLinkEffect(ChromaLink::EFFECT_TYPE effect, PRZPARAM pParam, RZEFFECTID* pEffectId); 23 | 24 | RzApi RZRESULT SetEffect(RZEFFECTID EffectId); 25 | RzApi RZRESULT DeleteEffect(RZEFFECTID EffectId); 26 | 27 | RzApi RZRESULT QueryDevice(RZDEVICEID DeviceId, DEVICE_INFO_TYPE& DeviceInfo); 28 | 29 | ////////////////////////////////////////////////////////////////////////// 30 | // All functions in this block are not implemented. 31 | RzApi RZRESULT RegisterEventNotification(HWND hWnd); 32 | RzApi RZRESULT UnregisterEventNotification(); 33 | ////////////////////////////////////////////////////////////////////////// 34 | 35 | bool m_Initialized = false; 36 | bool isInitialized() { return m_Initialized; } 37 | 38 | CONTEXT_HANDLE rpcCTXHandle; 39 | RETCClientConfig *CONFIG; 40 | 41 | handle_t hRetcBinding = nullptr; 42 | 43 | #define ABORT_IF_NOT_INITIALIZED if (!m_Initialized) { return RZRESULT_NOT_VALID_STATE; } 44 | 45 | BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD /*callReason*/, LPVOID /*lpReserved*/) { 46 | return TRUE; 47 | } 48 | 49 | BOOL hasSupportFor(const RETCDeviceType type) { 50 | if (!isInitialized() || type >= ESIZE) { 51 | return false; 52 | } 53 | 54 | return CONFIG->supportedDeviceTypes[type]; 55 | } 56 | 57 | RZRESULT Init() { 58 | if (m_Initialized) { 59 | return RZRESULT_NOT_VALID_STATE; 60 | } 61 | 62 | RPC_WSTR szStringBinding = nullptr; 63 | 64 | auto status = RpcStringBindingCompose(nullptr, RPC_WSTR(L"ncalrpc"), nullptr, RPC_WSTR(L"[retc-rpc]"), nullptr, &szStringBinding); 65 | 66 | if (status) { 67 | return RZRESULT_SERVICE_NOT_ACTIVE; 68 | } 69 | 70 | status = RpcBindingFromStringBinding(szStringBinding, &hRetcBinding); 71 | 72 | if (status) { 73 | RpcStringFree(&szStringBinding); 74 | return RZRESULT_SERVICE_NOT_ACTIVE; 75 | } 76 | 77 | status = RpcStringFree(&szStringBinding); 78 | 79 | if (status) { 80 | return RZRESULT_SERVICE_NOT_ACTIVE; 81 | } 82 | 83 | status = RpcEpResolveBinding(hRetcBinding, rpc_retc_v2_5_c_ifspec); 84 | if (status) { 85 | return RZRESULT_SERVICE_NOT_ACTIVE; 86 | } 87 | 88 | RpcTryExcept 89 | CONFIG = new RETCClientConfig; 90 | rpcCTXHandle = initialize(hRetcBinding, CONFIG); 91 | if (CONFIG == nullptr) { 92 | return RZRESULT_SERVICE_NOT_ACTIVE; 93 | } 94 | 95 | m_Initialized = true; 96 | return RZRESULT_SUCCESS; 97 | RpcExcept(1) 98 | return RZRESULT_SERVICE_NOT_ACTIVE; 99 | RpcEndExcept 100 | } 101 | 102 | RZRESULT UnInit() { 103 | if (!m_Initialized) { 104 | return RZRESULT_NOT_VALID_STATE; 105 | } 106 | 107 | RpcTryExcept 108 | disconnect(&rpcCTXHandle); 109 | RpcExcept(1) 110 | return RZRESULT_NOT_VALID_STATE; 111 | RpcEndExcept 112 | 113 | const auto status = RpcBindingFree(&hRetcBinding); 114 | m_Initialized = false; 115 | delete CONFIG; 116 | return (!status) ? RZRESULT_SUCCESS : RZRESULT_NOT_VALID_STATE; 117 | } 118 | 119 | 120 | RZRESULT sendEffect(const RETCDeviceType deviceType, const int effectID, const PRZPARAM effectData, RZEFFECTID* pEffectId) { 121 | ABORT_IF_NOT_INITIALIZED; 122 | 123 | if (!hasSupportFor(deviceType)) { 124 | return RZRESULT_DEVICE_NOT_AVAILABLE; 125 | } 126 | 127 | const auto isNoneEffect = (effectID == CHROMA_NONE); 128 | const auto effectSize = isNoneEffect ? 0 : LookupArrays::effectSize[deviceType][effectID - 1]; 129 | 130 | if (effectSize == 0 && !isNoneEffect) { 131 | return RZRESULT_NOT_SUPPORTED; 132 | } 133 | 134 | RpcTryExcept 135 | return playEffect(deviceType, effectID, pEffectId, effectSize, reinterpret_cast(effectData), rpcCTXHandle); 136 | RpcExcept(1) 137 | return RZRESULT_NOT_VALID_STATE; 138 | RpcEndExcept 139 | } 140 | 141 | // ReSharper disable CppParameterMayBeConst 142 | RZRESULT CreateEffect(RZDEVICEID deviceId, EFFECT_TYPE effectId, PRZPARAM pParam, RZEFFECTID* pEffectId) { //-V813 143 | ABORT_IF_NOT_INITIALIZED; 144 | 145 | auto deviceType = ESIZE; 146 | if (deviceId == GUID_NULL) { 147 | deviceType = ALL; 148 | } 149 | else { 150 | for (int devID = KEYBOARD; devID < ALL; devID++) { 151 | if (deviceId == CONFIG->emulatedDeviceIDS[devID]) { 152 | deviceType = static_cast(devID); 153 | break; 154 | } 155 | } 156 | } 157 | 158 | if (deviceType == ESIZE) { 159 | return RZRESULT_DEVICE_NOT_AVAILABLE; 160 | } 161 | 162 | const auto realEffectID = (deviceType == ALL) ? effectId : LookupArrays::genericEffectType[deviceType][effectId]; 163 | return sendEffect(deviceType, realEffectID, pParam, pEffectId); 164 | } 165 | 166 | RZRESULT CreateKeyboardEffect(Keyboard::EFFECT_TYPE effect, PRZPARAM pParam, RZEFFECTID* pEffectId) { 167 | return sendEffect(KEYBOARD, effect, pParam, pEffectId); 168 | } 169 | 170 | RZRESULT CreateMouseEffect(Mouse::EFFECT_TYPE effect, PRZPARAM pParam, RZEFFECTID* pEffectId) { 171 | return sendEffect(MOUSE, effect, pParam, pEffectId); 172 | } 173 | 174 | RZRESULT CreateHeadsetEffect(Headset::EFFECT_TYPE effect, PRZPARAM pParam, RZEFFECTID* pEffectId) { 175 | return sendEffect(HEADSET, effect, pParam, pEffectId); 176 | } 177 | 178 | RZRESULT CreateMousepadEffect(Mousepad::EFFECT_TYPE effect, PRZPARAM pParam, RZEFFECTID* pEffectId) { 179 | return sendEffect(MOUSEPAD, effect, pParam, pEffectId); 180 | } 181 | 182 | RZRESULT CreateKeypadEffect(Keypad::EFFECT_TYPE effect, PRZPARAM pParam, RZEFFECTID* pEffectId) { 183 | return sendEffect(KEYPAD, effect, pParam, pEffectId); 184 | } 185 | 186 | RZRESULT CreateChromaLinkEffect(ChromaLink::EFFECT_TYPE effect, PRZPARAM pParam, RZEFFECTID * pEffectId) { 187 | return sendEffect(SYSTEM, effect, pParam, pEffectId); 188 | } 189 | 190 | RZRESULT SetEffect(RZEFFECTID EffectId) { //-V813 191 | ABORT_IF_NOT_INITIALIZED; 192 | 193 | RpcTryExcept 194 | return setEffect(EffectId, rpcCTXHandle); 195 | RpcExcept(1) 196 | return RZRESULT_NOT_VALID_STATE; 197 | RpcEndExcept 198 | } 199 | 200 | RZRESULT DeleteEffect(RZEFFECTID EffectId) { //-V813 201 | ABORT_IF_NOT_INITIALIZED; 202 | 203 | RpcTryExcept 204 | return deleteEffect(EffectId, rpcCTXHandle); 205 | RpcExcept(1) 206 | return RZRESULT_NOT_VALID_STATE; 207 | RpcEndExcept 208 | } 209 | 210 | RZRESULT QueryDevice(RZDEVICEID DeviceID, DEVICE_INFO_TYPE& DeviceInfo) { //-V813 211 | ABORT_IF_NOT_INITIALIZED; 212 | 213 | for (int devId = KEYBOARD; devId < ALL; devId++) { 214 | if (DeviceID == CONFIG->emulatedDeviceIDS[devId]) { 215 | DeviceInfo.Connected = CONFIG->supportedDeviceTypes[devId]; 216 | return RZRESULT_SUCCESS; 217 | } 218 | } 219 | 220 | DeviceInfo.Connected = FALSE; 221 | return RZRESULT_DEVICE_NOT_AVAILABLE; 222 | } 223 | 224 | RZRESULT RegisterEventNotification(HWND /*hWnd*/) { 225 | ABORT_IF_NOT_INITIALIZED; 226 | 227 | return RZRESULT_SUCCESS; 228 | } 229 | 230 | RZRESULT UnregisterEventNotification() { 231 | ABORT_IF_NOT_INITIALIZED; 232 | 233 | return RZRESULT_SUCCESS; 234 | } 235 | 236 | // ReSharper restore CppParameterMayBeConst 237 | 238 | 239 | void* __RPC_USER midl_user_allocate(const size_t size) { 240 | return malloc(size); 241 | } 242 | 243 | void __RPC_USER midl_user_free(void* p) { 244 | free(p); 245 | } 246 | -------------------------------------------------------------------------------- /shim-dll/shim.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | rpc 7 | 8 | 9 | 10 | 11 | {c1d96e26-2896-4bf5-a62d-6fd9065e4614} 12 | 13 | 14 | 15 | 16 | rpc 17 | 18 | 19 | 20 | 21 | 22 | --------------------------------------------------------------------------------