Compare commits

...

72 commits

Author SHA1 Message Date
Zarg
da0783dfd8 Added fullscreen-on-launch webmod 2025-12-15 23:56:38 +01:00
Zarg
adb360bd4a Choco push 5.0.21 2025-12-09 11:14:18 +01:00
Zarg
f6b08f6267 Bump to 5.0.21 and updated readme
- Bump to 5.0.21
- Updated Readme Animejanai section, added video guide and updated build link
- Updated App errors with more common issues
2025-12-09 11:12:28 +01:00
Zarg
90f8961641
Typo fixes - PR #99 from Dyras/patch-1
Spelling fixes in the readme
2025-12-08 01:08:38 +01:00
Zarg
be66d6be39
Added Winget Install Option - PR #175 from YusufKhalifadev/webview-windows-Winget
Added Winget Install Option
2025-12-08 01:05:53 +01:00
Zarg
3725f0b53d
Update installation instructions in README.md
- Added winget install
- Added (Recommended) note
2025-12-08 01:02:22 +01:00
Zarg
38349f0741 Updated ublock description and added 4.20.15 stremio runtime 2025-12-08 00:10:57 +01:00
Zarg
e197d8cc99 Server version bump to 4.20.15 2025-12-07 20:40:11 +01:00
YusufKhalifadev
4390983608 change icon 2025-12-06 14:07:00 +02:00
YusufKhalifadev
bca250f8dd Update README.md 2025-12-06 14:00:27 +02:00
Zarg
b4cad35041 Updated animejanai script to work with multi part releases
- Updated Script to work with multi part releases.
2025-10-22 17:29:08 +02:00
Zarg
7d1b63c993 Version Bump 5.0.20 2025-10-22 16:39:31 +02:00
Zarg
7add3f622b Added WebMods feature
- Added WebMods feature, allows loading custom js and css
2025-10-08 07:25:29 +02:00
Zarg
c5a6a7fb64 Choco 5.0.19 2025-08-20 23:11:59 +02:00
Zarg
a87bec252f Version Bump 5.0.19 2025-08-20 22:42:25 +02:00
Zarg
904c3f696c Fixed SubtitleDropped using decoded utf8 as msg
- Fixed SubtitleDropped using decoded utf8 as msg causing a wrong path to be shown in the ui
- Updated readme as chocolatey was not updated in a long time.
2025-08-20 21:08:04 +02:00
Zarg
9cef682930 Added Subtitle Dropped event 2025-08-20 20:03:19 +02:00
Johan
5665603bf2
Spelling fixes in the readme 2025-07-09 15:56:54 +02:00
Zarg
7434ac684f Fixed subtitle not loading if non ascii characters
- Added URI Decode before mpv sub-add
- Related Issue: https://github.com/Zaarrg/stremio-community-v5/issues/48#issuecomment-2994429258
2025-06-25 15:59:11 +02:00
Zarg
917dd8d52a Fix Play/Pause media key not working out of focus
- Fix media key out of focus not working [86](https://github.com/Zaarrg/stremio-community-v5/issues/86)
2025-06-04 18:13:23 +02:00
Zarg
d6c485de17 Update README.md
- Centered button
2025-05-26 07:00:27 +02:00
Zarg
21e6256532 Update README.md
- Added support button
2025-05-26 06:57:50 +02:00
Zarg
66fd305565 Update README.md
- Added Discord RPC example image and to the feature list
2025-05-26 06:55:59 +02:00
Zarg
9142d89a1e Version Bump 5.0.18 2025-05-26 06:17:53 +02:00
Zarg
76bbdf64a9 Added Discord RPC support
- Added Allow debug logs to cmakelist instead of debug runs
- Added Discord rpc SDK supporting buttons and type
- Added Discord RPC handling
- Added Discord RPC Events for each stremio site
- Added DiscordRPC settings toggle to disable RPC
- Changed App image to a cleaner one
2025-05-26 05:24:28 +02:00
Zarg
a67eebaf0d Added Stremio Service to installer and adjusted app icons
- Added Stremio Service install checkbox to the installer
- Adjusted App icons
2025-04-15 00:33:26 +02:00
Zarg
6c7faa5c61 replaced icons
- Changed icons, see issue 71 for more details: https://github.com/Zaarrg/stremio-community-v5/issues/71
2025-04-14 23:46:22 +02:00
Zarg
501f616717 Added check for stremio service
- Check for stremio service to use server.js of stremio service
2025-04-14 23:40:05 +02:00
Zarg
3117065f51 Update README.md
- Added better copyright disclaimer
2025-02-10 02:14:24 +01:00
Zarg
c1c4109b43 5.0.17 portable_config hotfix 2025-02-10 01:24:00 +01:00
Zarg
2530f8eb11 fix backup folder not being skipped 2025-02-10 01:14:59 +01:00
Zarg
347bf735ee Converted winhttp calls to curl 2025-02-07 07:45:44 +01:00
Zarg
252e8f2a1e Version Bump 5.0.17 + Readme fixes 2025-02-07 07:24:50 +01:00
Zarg
76d4355cd4 Stylus addon support, Fixed tray menu dpi, Fix drag and drop subs no delay option
- Fixed tray menu not scaling with DPI
- Added Stylus addon support + Handle for HandleStylusUsoInstall (Installing from uso archives)
- Fixed drag and dropped subtitles not being handled as "ExternalEmbedded" preventing delay setting
- Added zips of unpacked extensions for use in app.
2025-02-07 06:30:11 +01:00
Zarg
aa03891ed4 Update extensions.json
- Added missing uso-archive domain
2025-02-07 02:14:13 +01:00
Zarg
1b4f3c7397 Added Stylus extension meta data 2025-02-07 02:02:29 +01:00
Zarg
a44171d919 Update extensions.json
- Better fallback description
2025-02-06 23:12:35 +01:00
Zarg
7bf9738ab0 Added Fallback if addon not found in metadata list 2025-02-06 23:06:14 +01:00
Zarg
ffb9fdc557 updated default portable config location 2025-02-06 04:03:50 +01:00
Zarg
f7301f7518 Added anime skip intro script to default portable config 2025-02-06 04:00:43 +01:00
Zarg
003e561881 Update README.md
- Added default overwrites of Stremio for subtitles for clarification
2025-02-05 19:50:27 +01:00
Zarg
906c841e4f Removed hdr comparison as this is now fixed in stremio shell ng 2025-02-05 17:00:36 +01:00
Zarg
ec9bcc39ba Update README.md 2025-02-05 05:24:57 +01:00
Zarg
29d49d4d3e Version Bump 5.0.16 2025-02-05 04:45:21 +01:00
Zarg
81467603b5 Updated nsi installer for v16 release
- Added prompt to remove all data on update. Backups portable_config just in case of user modifications to it.
2025-02-05 03:42:27 +01:00
Zarg
0bfe1c012d Added explanation for Subtitle Customization and Latest Portable Config 2025-02-05 02:59:38 +01:00
Zarg
33dc1e942f Fix Initial volume always being 50
- Fixed current volume not being save to settings.ini causing initial volume to always be 50.
[Issue: https://github.com/Zaarrg/stremio-desktop-v5/issues/42]
2025-02-04 04:35:27 +01:00
Zarg
b159fd01e8 Added multi-threaded MPV command handling
- Improves initial load time allowing multiple commands to execute simultaneously
- Prevents blocking of ui thread on handling of many commands. e.g. loading ~30 external subtitles into mpv
2025-02-03 04:56:33 +01:00
Zarg
416dab85cf Added advanced Browser Extensions Support
- Added extension domain whitelist gotten from extensions.json on github for allowed domains to navigate for browser extension usage. App allow these domain to be navigated to other are open externally.
- Added script Queue to run scripts on navigation complete
- Added "Home" navigate event arg, to navigate back to home page
- Added Back to Stremio button when not on Stremio page
- Partial permid support with custom patch. Still some features not working.
2025-02-02 03:13:22 +01:00
Zarg
81e0ce17cb Update extensions.json
- Added allowed domains for navigating extensions
2025-02-02 02:53:54 +01:00
Zarg
af581f1f04 Fix missing Debug if statment + better extensions logos 2025-02-01 05:02:13 +01:00
Zarg
e09cbd2485 Update extensions.json 2025-02-01 04:43:31 +01:00
Zarg
6a950eec56 Added proper Browser Extension support
- Proper Browser Extension support with configuration page
- Map Browser Extension by name: id, this will then be used to add extensions as "addons" in stremio
- Reworked add_ContextMenuRequested to allow for "back" ctx on extension page.
- Added "navigate" to allow for navigation to chrome-extension://
2025-02-01 04:09:04 +01:00
Zarg
26ca7c6368 Added multiple webui endpoints to ensure reachability
- Added Multiple webui endpoints
- g_webuiUrls functions as priority list, index 0 highest priority
- Status is checked in separate thread after webview initialization
2025-01-31 20:33:32 +01:00
Zarg
a6438d97b9 Change to better web ui server 2025-01-30 02:56:22 +01:00
Zarg
ab811219a5 Facebook login fix 2025-01-27 02:24:23 +01:00
Zarg
71e4d246f3 Added --debug to build release with debug enabled 2025-01-27 02:13:14 +01:00
Zarg
d1b7990284 Added fsr shader
- Fsr shader see https://github.com/Zaarrg/stremio-desktop-v5/issues/25
2025-01-27 01:17:50 +01:00
Zarg
63c157df29 Hotfix window size not saved on tray app quit 2025-01-27 00:33:08 +01:00
Zarg
3a29630d13 Fix tray quit not saving window size 2025-01-27 00:27:25 +01:00
Zarg
baa268317f Version Bump 5.0.15 2025-01-27 00:13:10 +01:00
Zarg
3c2ce2f815 Change to send as String instead of Json Webview ipc 2025-01-26 23:00:50 +01:00
Zarg
b69b78caa4 Added subtitle drag and drop support 2025-01-26 22:03:48 +01:00
Zarg
bf83deab4b easynews addon not working fix 2025-01-26 21:03:41 +01:00
Zarg
054ff34ddb Blackscreen + Volume Control fix and more fixes
- Fixed Blackscreen and volume control being disabled bug.
- Fixed Alt+Tab not focusing webview correctly
- Added InitalVolume and VO (VideoOutput) to stremio-settings.ini.
- Added updater clean up which deletes all old installers.
2025-01-26 20:38:34 +01:00
Zarg
c0d7d1e9d2 Adjusted installer to remove everything from Webview2 except "Default" User Profile
- Adjusted installer to remove everything from Webview2 except "Default" User Profile to ensure fresh cache on update
2025-01-25 04:13:17 +01:00
Zarg
51df3c1956 More refactor fixes and stremio://detail support
- Fixed wrong errorMessage format being send
- Fixed when stremio:// protocol is used and the app is starting because of that not working
- Fixed node server paths sometimes being wrong
- Added support for stremio://detail as protocol
2025-01-25 03:43:35 +01:00
Zarg
5080a6cbcd Refactor fixes
- Fixed wrong mpv ended logic
- Fixed thumbfast logic missing
- Fixed fullscreen not working
2025-01-25 02:06:49 +01:00
Zarg
1976366f44 Full Refactor + Transport rewrite to use default qt transport
- Full Refactor
- Full transport rewrite to use qt default transport
- Saves window position on exit and restores on start
- Added filter to ublock extension to prevent thumbnail issues (possibly)
2025-01-25 00:46:32 +01:00
Zarg
37a20b1fe7 More splash screen stuck fixes + Version 5.0.14
- More fixes for stuck on splash screen
- Version bump to 5.0.14
2025-01-20 17:17:57 +01:00
Zarg
75c59224e1 Fix splash screen stuck
- Fixed stuck on splash screen for good... No idea why there was a function overwriting it the js script...
- Added exponential backoff for retry logic if page unreachable
2025-01-19 14:18:42 +01:00
Zarg
fcaa890966 Version Bump 5.0.13 2025-01-19 02:12:46 +01:00
61 changed files with 4900 additions and 3535 deletions

8
.idea/.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

7
.idea/discord.xml Normal file
View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="ASK" />
<option name="description" value="" />
</component>
</project>

View file

@ -1,62 +1,298 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="BackendCodeEditorSettings">
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CDeclarationWithImplicitIntType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConstevalIfIsAlwaysConstant/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractClassWithoutSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractVirtualFunctionCallInCtor/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAccessSpecifierWithNoDeclarations/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAwaiterTypeIsNotClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBooleanIncrementExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatBadCode/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatLegacyCode/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatMixedArgs/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooFewArgs/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooManyArgs/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCVQualifierCanNotBeAppliedToReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassCanBeFinal/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassIsIncomplete/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeedsConstructorBecauseOfUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCompileTimeConstantCanBeReplacedWithBooleanConstant/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConceptNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConditionalExpressionCanBeSimplified/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstValueFunctionReturnType/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCoroutineCallResolveError/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAArrayIndexOutOfBounds/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantConditions/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantFunctionResult/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantParameter/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFADeletedPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAEndlessLoop/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInfiniteRecursion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInvalidatedMemory/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesScope/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALoopConditionNotUpdated/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAMemoryLeak/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANotInitializedField/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANullDereference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFATimeOver/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableCode/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableFunctionCall/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreadVariable/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnusedValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesLocal/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesUncapturedLocal/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationSpecifierWithoutDeclarators/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorDisambiguatedAsFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorUsedBeforeInitialization/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultCaseNotHandledInSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultInitializationWithNoUserConstructor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultIsUsedAsIdentifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultedSpecialMemberFunctionIsImplicitlyDeleted/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeletingVoidPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTemplateWithoutTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTypeWithoutTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedEntity/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedOverridenMethod/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedRegisterStorageClassSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDereferenceOperatorLimitExceeded/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDiscardedPostfixOperatorResult/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenSyntaxError/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUndocumentedParameter/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUnresolvedReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEmptyDeclaration/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersOrder/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersPlacement/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceDoStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceForStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceFunctionDeclarationStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceIfStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceNestedNamespacesStyle/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingDestructorStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingFunctionStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceTypeAliasCodeStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceWhileStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityAssignedButNoRead/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityUsedOnlyInUnevaluatedContext/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnumeratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEqualOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEvaluationFailure/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExplicitSpecializationInNonNamespaceScope/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExpressionWithoutSideEffects/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalFunctionInFinalClass/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalNonOverridingVirtualFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForLoopCanBeReplacedWithWhile/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForwardEnumDeclarationWithoutUnderlyingType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionDoesntReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionResultShouldBeUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionalStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHeaderHasBeenAlreadyIncluded/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHiddenFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHidingFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIdenticalOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIfCanBeReplacedByConstexprIf/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppImplicitDefaultConstructorNotAvailable/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompatiblePointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompleteSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInconsistentNaming/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIntegralToPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInvalidLineContinuation/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppJoinDeclarationAndAssignment/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLambdaCaptureNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableWithNonTrivialDtorIsNeverUsed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLongFloat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeConst/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeStatic/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberInitializersOrder/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMismatchedClassTags/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingIncludeGuard/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingKeywordThrow/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtAddressOfClassRValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtBindingRValueToLvalueReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtCopyElisionInCopyInitDeclarator/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtDoubleUserConversionInCopyInit/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtNotInitializedStaticConstLocalVar/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtReinterpretCastFromNullptr/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterLiteral/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterWideLiteral/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMustBePublicVirtualToImplementInterface/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMutableSpecifierOnReferenceMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNoDiscardExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNodiscardFunctionWithoutReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExceptionSafeResourceAcquisition/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConversionOperator/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConvertingConstructor/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineFunctionDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineVariableDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNotAllPathsReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppObjectMemberMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppOutParameterMustBeWritten/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConstPtrOrRef/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNamesMismatch/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPassValueParameterByConstReference/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerConversionDropsQualifiers/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerToIntegralConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPolymorphicClassWithNonVirtualPublicDestructor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyErroneousEmptyStatements/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUnintendedObjectSlicing/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderIsNotIncluded/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderNotFound/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfBadFormat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfExtraArg/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfMissedArg/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfRiskyFormat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrivateSpecialMemberFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRangeBasedForIncompatibleReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedefinitionOfDefaultArgumentInOverrideFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBooleanExpressionArgument/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantCastExpression/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantComplexityInComparison/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConditionalExpression/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConstSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantControlFlowJump/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantDereferencingAndTakingAddress/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElaboratedTypeSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeyword/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeywordInsideCompoundStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyDeclaration/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantExportKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantFwdClassOrEnumSpecifier/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantInlineSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantLambdaParameterList/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantMemberInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantNamespaceDefinition/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantParentheses/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifierADL/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnMemberAllocationFunction/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnThreadLocalLocalVariable/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateArguments/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantVoidArgumentList/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantZeroInitializerInAggregateInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReinterpretCastFromVoidPtr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRemoveRedundantBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceMemsetWithZeroInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceTieWithStructuredBinding/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReturnNoValueInNonVoidFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSmartPointerVsMakeFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSomeObjectMembersMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSpecialFunctionWithoutNoexceptSpecification/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticAssertFailure/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticDataMemberInUnnamedStruct/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticSpecifierOnAnonymousNamespaceMember/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStringLiteralToCharPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTabsAreDisallowed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateArgumentsCanBeDeduced/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterShadowing/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppThrowExpressionCanBeReplacedWithRethrow/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScope/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScopeInitStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTypeAliasNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedDependentBaseClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedNonStaticDataMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnionMemberOfReferenceType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaEndRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnamedNamespaceInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnecessaryWhitespace/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnsignedZeroComparison/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnusedIncludeDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAlgorithmWithCount/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAssociativeContains/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAuto/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAutoForNumeric/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseElementsView/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseEraseAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseFamiliarTemplateSyntaxForGenericLambdas/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseRangeAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStdSize/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStructuredBinding/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseTypeTraitAlias/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUserDefinedLiteralSuffixDoesNotStartWithUnderscore/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUsingResultOfAssignmentAsCondition/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVariableCanBeMadeConstexpr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionCallInsideCtor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionInFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVolatileParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWarningDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongIncludesOrder/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongSlashesInIncludeDirective/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroConstantCanBeReplacedWithNullptr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroValuedExpressionUsedAsNullPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IfStdIsConstantEvaluatedCanBeReplaced/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/FREE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
@ -64,6 +300,11 @@
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
@ -75,506 +316,29 @@
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/FREE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSmartPointerVsMakeFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionalStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReinterpretCastFromVoidPtr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConvertingConstructor/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConversionOperator/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDiscardedPostfixOperatorResult/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstValueFunctionReturnType/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeConst/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeStatic/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVariableCanBeMadeConstexpr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConstPtrOrRef/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPassValueParameterByConstReference/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppThrowExpressionCanBeReplacedWithRethrow/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroConstantCanBeReplacedWithNullptr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCompileTimeConstantCanBeReplacedWithBooleanConstant/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIfCanBeReplacedByConstexprIf/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IfStdIsConstantEvaluatedCanBeReplaced/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConstevalIfIsAlwaysConstant/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassCanBeFinal/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStructuredBinding/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseTypeTraitAlias/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAlgorithmWithCount/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseRangeAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseElementsView/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStdSize/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForLoopCanBeReplacedWithWhile/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppJoinDeclarationAndAssignment/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceTieWithStructuredBinding/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceMemsetWithZeroInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAssociativeContains/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseEraseAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseFamiliarTemplateSyntaxForGenericLambdas/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScope/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScopeInitStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantNamespaceDefinition/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineFunctionDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineVariableDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrivateSpecialMemberFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHiddenFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHidingFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPolymorphicClassWithNonVirtualPublicDestructor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractClassWithoutSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompleteSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultCaseNotHandledInSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyErroneousEmptyStatements/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExpressionWithoutSideEffects/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNoDiscardExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionResultShouldBeUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingKeywordThrow/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTypeWithoutTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTemplateWithoutTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppImplicitDefaultConstructorNotAvailable/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeedsConstructorBecauseOfUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedNonStaticDataMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRangeBasedForIncompatibleReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroValuedExpressionUsedAsNullPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUnintendedObjectSlicing/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorDisambiguatedAsFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionInFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMustBePublicVirtualToImplementInterface/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationSpecifierWithoutDeclarators/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEmptyDeclaration/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesLocal/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesUncapturedLocal/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMismatchedClassTags/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUsingResultOfAssignmentAsCondition/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIntegralToPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerToIntegralConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompatiblePointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerConversionDropsQualifiers/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStringLiteralToCharPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExceptionSafeResourceAcquisition/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionCallInsideCtor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractVirtualFunctionCallInCtor/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInvalidLineContinuation/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfBadFormat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfRiskyFormat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfMissedArg/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfExtraArg/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatBadCode/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatLegacyCode/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatMixedArgs/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooFewArgs/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooManyArgs/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedEntity/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingIncludeGuard/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenSyntaxError/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUnresolvedReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUndocumentedParameter/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeletingVoidPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBooleanIncrementExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedRegisterStorageClassSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIdenticalOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEqualOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedefinitionOfDefaultArgumentInOverrideFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnamedNamespaceInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNamesMismatch/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultedSpecialMemberFunctionIsImplicitlyDeleted/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNodiscardFunctionWithoutReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantComplexityInComparison/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSpecialFunctionWithoutNoexceptSpecification/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnsignedZeroComparison/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterLiteral/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterWideLiteral/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAccessSpecifierWithNoDeclarations/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeyword/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeywordInsideCompoundStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantControlFlowJump/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyDeclaration/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantParentheses/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantLambdaParameterList/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantCastExpression/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHeaderHasBeenAlreadyIncluded/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateArgumentsCanBeDeduced/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateArguments/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticSpecifierOnAnonymousNamespaceMember/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnMemberAllocationFunction/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnThreadLocalLocalVariable/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantInlineSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConstSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBooleanExpressionArgument/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantVoidArgumentList/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantMemberInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVolatileParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalFunctionInFinalClass/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalNonOverridingVirtualFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElaboratedTypeSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantDereferencingAndTakingAddress/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConditionalExpression/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConditionalExpressionCanBeSimplified/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantExportKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantZeroInitializerInAggregateInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUserDefinedLiteralSuffixDoesNotStartWithUnderscore/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassIsIncomplete/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterShadowing/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMutableSpecifierOnReferenceMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultInitializationWithNoUserConstructor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExplicitSpecializationInNonNamespaceScope/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnionMemberOfReferenceType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedDependentBaseClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderIsNotIncluded/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderNotFound/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCoroutineCallResolveError/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAwaiterTypeIsNotClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppOutParameterMustBeWritten/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWarningDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticAssertFailure/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEvaluationFailure/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTypeAliasNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConceptNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnumeratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLambdaCaptureNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableWithNonTrivialDtorIsNeverUsed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityAssignedButNoRead/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityUsedOnlyInUnevaluatedContext/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppObjectMemberMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSomeObjectMembersMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorUsedBeforeInitialization/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnusedIncludeDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNotAllPathsReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CDeclarationWithImplicitIntType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionDoesntReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReturnNoValueInNonVoidFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCVQualifierCanNotBeAppliedToReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDereferenceOperatorLimitExceeded/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForwardEnumDeclarationWithoutUnderlyingType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaEndRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticDataMemberInUnnamedStruct/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultIsUsedAsIdentifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLongFloat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtReinterpretCastFromNullptr/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtBindingRValueToLvalueReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtAddressOfClassRValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtDoubleUserConversionInCopyInit/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtCopyElisionInCopyInitDeclarator/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtNotInitializedStaticConstLocalVar/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRemoveRedundantBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceIfStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceForStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceWhileStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceDoStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongIncludesOrder/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongSlashesInIncludeDirective/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceNestedNamespacesStyle/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceTypeAliasCodeStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceFunctionDeclarationStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberInitializersOrder/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingFunctionStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingDestructorStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAuto/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAutoForNumeric/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersPlacement/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersOrder/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnecessaryWhitespace/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTabsAreDisallowed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantConditions/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANullDereference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANotInitializedField/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALoopConditionNotUpdated/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFADeletedPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAMemoryLeak/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInvalidatedMemory/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesScope/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantParameter/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantFunctionResult/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAArrayIndexOutOfBounds/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableCode/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableFunctionCall/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAEndlessLoop/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInfiniteRecursion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnusedValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreadVariable/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFATimeOver/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInconsistentNaming/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSmartPointerVsMakeFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCStyleCast/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionalStyleCast/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReinterpretCastFromVoidPtr/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConvertingConstructor/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConversionOperator/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDiscardedPostfixOperatorResult/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstValueFunctionReturnType/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeConst/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeStatic/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMayBeConst/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConst/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVariableCanBeMadeConstexpr/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConstPtrOrRef/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPassValueParameterByConstReference/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppThrowExpressionCanBeReplacedWithRethrow/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroConstantCanBeReplacedWithNullptr/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCompileTimeConstantCanBeReplacedWithBooleanConstant/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIfCanBeReplacedByConstexprIf/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IfStdIsConstantEvaluatedCanBeReplaced/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConstevalIfIsAlwaysConstant/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassCanBeFinal/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStructuredBinding/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseTypeTraitAlias/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAlgorithmWithCount/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseRangeAlgorithm/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseElementsView/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStdSize/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForLoopCanBeReplacedWithWhile/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppJoinDeclarationAndAssignment/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceTieWithStructuredBinding/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceMemsetWithZeroInitialization/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAssociativeContains/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseEraseAlgorithm/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseFamiliarTemplateSyntaxForGenericLambdas/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScope/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScopeInitStatement/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantNamespaceDefinition/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineFunctionDefinitionInHeaderFile/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineVariableDefinitionInHeaderFile/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionIsNotImplemented/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrivateSpecialMemberFunctionIsNotImplemented/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHiddenFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHidingFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPolymorphicClassWithNonVirtualPublicDestructor/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractClassWithoutSpecifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompleteSwitchStatement/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultCaseNotHandledInSwitchStatement/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyErroneousEmptyStatements/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExpressionWithoutSideEffects/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNoDiscardExpression/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionResultShouldBeUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingKeywordThrow/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTypeWithoutTypenameKeyword/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTemplateWithoutTemplateKeyword/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppImplicitDefaultConstructorNotAvailable/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeedsConstructorBecauseOfUninitializedMember/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedNonStaticDataMember/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRangeBasedForIncompatibleReference/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroValuedExpressionUsedAsNullPointer/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUnintendedObjectSlicing/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUninitializedMember/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorDisambiguatedAsFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionInFinalClass/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMustBePublicVirtualToImplementInterface/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationSpecifierWithoutDeclarators/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEmptyDeclaration/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesLocal/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesUncapturedLocal/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMismatchedClassTags/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUsingResultOfAssignmentAsCondition/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIntegralToPointerConversion/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerToIntegralConversion/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompatiblePointerConversion/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerConversionDropsQualifiers/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStringLiteralToCharPointerConversion/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExceptionSafeResourceAcquisition/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionCallInsideCtor/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractVirtualFunctionCallInCtor/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInvalidLineContinuation/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfBadFormat/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfRiskyFormat/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfMissedArg/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfExtraArg/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatBadCode/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatLegacyCode/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatMixedArgs/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooFewArgs/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooManyArgs/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedEntity/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingIncludeGuard/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenSyntaxError/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUnresolvedReference/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUndocumentedParameter/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeletingVoidPointer/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBooleanIncrementExpression/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedRegisterStorageClassSpecifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIdenticalOperandsInBinaryExpression/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEqualOperandsInBinaryExpression/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedefinitionOfDefaultArgumentInOverrideFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnamedNamespaceInHeaderFile/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNamesMismatch/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultedSpecialMemberFunctionIsImplicitlyDeleted/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNodiscardFunctionWithoutReturnValue/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantComplexityInComparison/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractFinalClass/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSpecialFunctionWithoutNoexceptSpecification/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnsignedZeroComparison/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterLiteral/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterWideLiteral/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantAccessSpecifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAccessSpecifierWithNoDeclarations/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTypenameKeyword/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateKeyword/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeyword/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeywordInsideCompoundStatement/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantControlFlowJump/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyStatement/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyDeclaration/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantParentheses/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantLambdaParameterList/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantCastExpression/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHeaderHasBeenAlreadyIncluded/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateArgumentsCanBeDeduced/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateArguments/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticSpecifierOnAnonymousNamespaceMember/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnMemberAllocationFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnThreadLocalLocalVariable/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassAccessSpecifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantInlineSpecifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConstSpecifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBooleanExpressionArgument/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantVoidArgumentList/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantMemberInitializer/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassInitializer/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstParameterInDeclaration/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVolatileParameterInDeclaration/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalFunctionInFinalClass/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalNonOverridingVirtualFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElaboratedTypeSpecifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantDereferencingAndTakingAddress/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConditionalExpression/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConditionalExpressionCanBeSimplified/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantExportKeyword/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantZeroInitializerInAggregateInitialization/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUserDefinedLiteralSuffixDoesNotStartWithUnderscore/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassIsIncomplete/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterShadowing/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMutableSpecifierOnReferenceMember/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultInitializationWithNoUserConstructor/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExplicitSpecializationInNonNamespaceScope/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnionMemberOfReferenceType/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedDependentBaseClass/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderIsNotIncluded/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderNotFound/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCoroutineCallResolveError/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAwaiterTypeIsNotClass/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppOutParameterMustBeWritten/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWarningDirective/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticAssertFailure/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEvaluationFailure/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTypeAliasNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConceptNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnumeratorNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLambdaCaptureNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableWithNonTrivialDtorIsNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterNeverUsed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityAssignedButNoRead/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityUsedOnlyInUnevaluatedContext/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMightNotBeInitialized/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppObjectMemberMightNotBeInitialized/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSomeObjectMembersMightNotBeInitialized/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorUsedBeforeInitialization/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnusedIncludeDirective/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNotAllPathsReturnValue/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CDeclarationWithImplicitIntType/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionDoesntReturnValue/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReturnNoValueInNonVoidFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCVQualifierCanNotBeAppliedToReference/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDereferenceOperatorLimitExceeded/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForwardEnumDeclarationWithoutUnderlyingType/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaRegionDirective/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaEndRegionDirective/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticDataMemberInUnnamedStruct/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultIsUsedAsIdentifier/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLongFloat/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtReinterpretCastFromNullptr/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtBindingRValueToLvalueReference/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtAddressOfClassRValue/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtDoubleUserConversionInCopyInit/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtCopyElisionInCopyInitDeclarator/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtNotInitializedStaticConstLocalVar/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRemoveRedundantBraces/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceIfStatementBraces/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceForStatementBraces/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceWhileStatementBraces/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceDoStatementBraces/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongIncludesOrder/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongSlashesInIncludeDirective/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceNestedNamespacesStyle/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceTypeAliasCodeStyle/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceFunctionDeclarationStyle/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberInitializersOrder/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingFunctionStyle/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingDestructorStyle/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAuto/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAutoForNumeric/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersPlacement/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersOrder/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnecessaryWhitespace/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTabsAreDisallowed/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantConditions/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANullDereference/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANotInitializedField/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALoopConditionNotUpdated/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFADeletedPointer/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAMemoryLeak/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInvalidatedMemory/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesScope/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesFunction/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantParameter/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantFunctionResult/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAArrayIndexOutOfBounds/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableCode/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableFunctionCall/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAEndlessLoop/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInfiniteRecursion/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnusedValue/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreadVariable/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFATimeOver/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInconsistentNaming/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexRemoved" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexRemoved" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
</component>
</project>

View file

@ -4,5 +4,8 @@
<option name="pythonIntegrationState" value="YES" />
</component>
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
<component name="WestSettings"><![CDATA[{}]]></component>
<component name="JavaScriptSettings">
<option name="languageLevel" value="FLOW" />
</component>
<component name="WestSettings">{}</component>
</project>

8
.idea/modules.xml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/stremio-desktop-v5.iml" filepath="$PROJECT_DIR$/.idea/stremio-desktop-v5.iml" />
</modules>
</component>
</project>

View file

@ -1,24 +1,32 @@
cmake_minimum_required(VERSION 3.16)
project(stremio VERSION "5.0.12")
project(stremio VERSION "5.0.21")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
option(DEBUG_LOG "Allow debug logs" ON)
# Locate MPV
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
# 64-bit architecture
set(MPV_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/deps/libmpv/x86_64/include")
set(MPV_LIBRARY "${CMAKE_CURRENT_SOURCE_DIR}/deps/libmpv/x86_64/mpv.lib")
set(MPV_DLL "${CMAKE_CURRENT_SOURCE_DIR}/deps/libmpv/x86_64/libmpv-2.dll")
set(DISCORD_LIB "${CMAKE_CURRENT_SOURCE_DIR}/deps/discord-rpc/win64-static/lib/discord-rpc.lib")
set(DISCORD_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/deps/discord-rpc/win64-static/include")
else()
# 32-bit architecture
set(MPV_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/deps/libmpv/i686/include")
set(MPV_LIBRARY "${CMAKE_CURRENT_SOURCE_DIR}/deps/libmpv/i686/mpv.lib")
set(MPV_DLL "${CMAKE_CURRENT_SOURCE_DIR}/deps/libmpv/i686/libmpv-2.dll")
set(DISCORD_LIB "${CMAKE_CURRENT_SOURCE_DIR}/deps/discord-rpc/win32-static/lib/discord-rpc.lib")
set(DISCORD_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/deps/discord-rpc/win32-static/include")
endif()
include_directories(${DISCORD_INCLUDE_DIR})
include_directories(${MPV_INCLUDE_DIR})
find_package(OpenSSL REQUIRED)
@ -29,28 +37,55 @@ find_package(unofficial-webview2 CONFIG REQUIRED)
set(SOURCES
src/main.cpp
stremio.rc
src/core/globals.h
src/core/globals.cpp
src/utils/helpers.h
src/utils/helpers.cpp
src/utils/config.h
src/utils/config.cpp
src/utils/crashlog.h
src/utils/crashlog.cpp
src/mpv/player.h
src/mpv/player.cpp
src/node/server.cpp
src/node/server.h
src/tray/tray.h
src/tray/tray.cpp
src/ui/splash.h
src/ui/splash.cpp
src/updater/updater.cpp
src/updater/updater.h
src/webview/webview.h
src/webview/webview.cpp
src/ui/mainwindow.h
src/ui/mainwindow.cpp
src/resource.h
src/utils/extensions.cpp
src/utils/extensions.h
src/utils/discord.cpp
src/utils/discord.h
)
add_executable(${PROJECT_NAME} WIN32 ${SOURCES})
target_link_libraries(${PROJECT_NAME} PRIVATE
user32.lib
gdi32.lib
ole32.lib
oleaut32.lib
shell32.lib
advapi32.lib
gdiplus.lib
dwmapi.lib
Shcore.lib
Msimg32.lib
winhttp.lib
shlwapi.lib
nlohmann_json::nlohmann_json
unofficial::webview2::webview2
OpenSSL::SSL
OpenSSL::Crypto
CURL::libcurl
${MPV_LIBRARY}
${DISCORD_LIB}
)
target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<CONFIG:Debug>:DEBUG_BUILD>)
target_compile_definitions(${PROJECT_NAME} PRIVATE DEBUG_LOG)
# Copy MPV DLL
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD

139
README.md
View file

@ -40,8 +40,12 @@
<li>🔊 <strong>Dolby Atmos Support</strong>: Support for all mpv advanced audio features.</li>
<li>🖼️ <strong>Picture in Picture</strong>: Picture in Picture Mode Support</li>
<li>🌑 <strong>Dark Mode</strong>: Windows Dark mode support</li>
<li>💬 <strong>Discord Rich Presence</strong>: Show what you're watching in real-time on your Discord profile</li>
<li>🖼️ <strong>Thumbnail Preview</strong>: ThumbFast support to allow for preview thumbnails when seeking</li>
<li>📁 <strong>Local File Playback</strong>: Play any file MPV and ffmpeg supports, just use <strong>open with</strong> 'stremio' or <strong>drag and drop</strong></li>
<li>🔡 <strong>Local Subtitles</strong>: Add any Subtitle file using drag and drop while playing a video</li>
<li>🎨 <strong>Advanced Subtitles Styles</strong>: Style subtitles any way you like using <strong>mpv configuration</strong></li>
<li>📌 <strong>Advanced Auto Selection</strong>: Select multiple default Subtitle, Audio tracks as well as Subtitle Keywords to prioritize and filter out unwanted languages</li>
<li>🌀 <strong>Torrent Support</strong>: Play any local .torrent file or any magnet: link</li>
<li>📺 <strong>Chromecast Support</strong>: Cast Videos to your Chromecast</li>
<li> <strong>Easy Addon Install</strong>: Just use the install Button like stremio v4, no need to copy paste urls</li>
@ -62,16 +66,6 @@
- A side-by-side visual comparison of various features and enhancements in Stremio Desktop v5. Due to this being screenshots, HDR appears over-exposed.
<p align="center">
<strong>HDR Comparison</strong>
</p>
<p align="center">
<img src="https://i.imgur.com/ezh2YIa.png" alt="Stremio Web Desktop Screenshot" width="600" />
</p>
<p align="center">
<small><i>Stremio Desktop v5 vs Official Stremio v5.</i></small>
</p>
<p align="center">
<strong>Upscaler Comparison</strong>
</p>
@ -79,7 +73,7 @@
<img src="https://i.imgur.com/rLTmFC2.png" alt="Stremio Web Desktop Screenshot" width="600" />
</p>
<p align="center">
<small><i>Anime4k + Auto HDR vs Offical Stremio v5.</i></small>
<small><i>Anime4k + Auto HDR vs Official Stremio v5.</i></small>
</p>
<p align="center">
@ -92,15 +86,34 @@
<small><i>Best on local files using thumbfast. Size can be adjusted.</i></small>
</p>
<p align="center">
<strong>Discord Rich Presence</strong>
</p>
<p align="center">
<img src="https://i.imgur.com/V5YgSSx.png" alt="Discord Rich Presence Example"/>
</p>
<p align="center">
<small><i>Live activity like Discovering, Watching, or Paused updates in real-time.</i></small>
</p>
## 🔧 Installation
1. 🪟 **Windows x64 and x86**
1. 📥 **Installer**
1. 📥 **Installer (Recommended)**
- **Install using the** `Installer`. Download `stremio-5.0.0-x64.exe` or `stremio-5.0.0-x86.exe` and run it.
2. 💼 **Portable Version**
- **Install using the** `Archive`. Download `stremio-5.0.0-x64.7z` or `stremio-5.0.0-x86.7z` extract it and run `stremio.exe`
3. 🥄 **Scoop.sh**
3. 📦 **Winget**
```shell
# Install
winget install Zaarrg.StremioCommunity
# Update
winget upgrade Zaarrg.StremioCommunity
# Uninstall
winget uninstall Zaarrg.StremioCommunity
```
4. 🥄 **Scoop.sh**
```shell
# Install
scoop bucket add zarg https://github.com/zaarrg/scoop
@ -111,8 +124,9 @@
# Uninstall
scoop uninstall stremio-desktop-v5
```
4. 🍫 **Chocolatey**
5. ~~🍫 **Chocolatey**~~
```shell
⚠️ Note: Chocolatey is not updated use scoop or a other installation method!
# Install
choco install stremio-desktop-v5 -y
# Update
@ -120,14 +134,14 @@
# Uninstall
choco uninstall stremio-desktop-v5 -y
```
> **⏳ Note:** If you have stremio-desktop v4.x.x installed make sure to uninstall it first. Otherwise there might be issues.
2. 🚀 **Linux, macOS**
- Coming soon!
> **⏳ Note:** Linux and Mac release will take considerable time as they need their own build with os specific technology's
> **⏳ Note:** Linux and Mac release will take considerable time as they need their own build with OS specific technologies
## 🔍 **Mpv Upscalers**
@ -138,7 +152,7 @@
- 🎨 **[AnimeJaNai](https://github.com/the-database/mpv-upscale-2x_animejanai)**
- ❌ Not included by default.
- 📥 Download from the **Stremio-Desktop-v5** [release tab](https://github.com/Zaarrg/stremio-desktop-v5/releases/5.0.0-beta.7) the `stremio-animejanai-3.x.x.7z` for Stremio and drop the content of the 7z into `%localAppData%\Programs\LNV\Stremio-5\` and `replace all`
- 📥 Download from the **Stremio-Desktop-v5** [release tab](https://github.com/Zaarrg/stremio-community-v5/releases/tag/5.0.0-beta.20) the `stremio-animejanai-3.x.x.7z.001` and `stremio-animejanai-3.x.x.7z.002` for Stremio and drop the content of the 7z into `%localAppData%\Programs\LNV\Stremio-5\` and `replace all`
- 🛠️ **Changes made:**
- Removed `mpvnet.exe` as Stremio is used as the player.
- Adjusted `mpv.conf` to work with Stremio.
@ -150,6 +164,8 @@
- 🔢 `SHIFT+1` - `SHIFT+3` Select Quality, Balanced or Performance Profiles
- ⚙️ `CTRL+1` - `CTRL+9` Switch between Custom Profiles
- 🔗 For more, check [AnimeJaNai](https://github.com/the-database/mpv-upscale-2x_animejanai)
- 📺 **Installation Guide**
- See: [AnimeJaNai Youtube Installation Guide](https://www.youtube.com/watch?v=ZlPJ-M3kkdM)
> **⏳ Note:** When using AnimeJaNai on first playback Stremio will be unresponsive and a console will open to build the model via e.g. TensorRT. You will need to wait until the console closes for playback to start. This happens only once per model.
@ -161,7 +177,7 @@
## 🔍 **Mpv Addons**
- 🎥 **[ThumbFast](https://github.com/po5/thumbfast)**
- 🔧 Go in the `Stremio-Dekstop-v5` Repo to ``utils/mpv/thumbfast`` or [direct-link](https://github.com/Zaarrg/stremio-desktop-v5/tree/webview-windows/utils/mpv/thumbfast) and download ``thumbfast.7z``. Drag and Drop the archive contents into ``%localAppData%\Programs\LNV\Stremio-5``
- 🔧 Go in the `Stremio-Desktop-v5` Repo to ``utils/mpv/thumbfast`` or [direct-link](https://github.com/Zaarrg/stremio-desktop-v5/tree/webview-windows/utils/mpv/thumbfast) and download ``thumbfast.7z``. Drag and Drop the archive contents into ``%localAppData%\Programs\LNV\Stremio-5``
- 📁 Works best with local files as there is no **network bottleneck**. U can `Drag and Drop` any local file into **Stremio** or right click ``Open With > Stremio``
> **⏳ Note:** For more details visit [mpv-portable-configs](https://github.com/Zaarrg/stremio-desktop-v5/blob/webview-windows/utils/mpv/README.md)
@ -176,11 +192,12 @@
- Add any Browser Extension to Stremio by dropping the ``unpacked`` Extension into ``portable_config/extensions``
- On Start Extensions from ``portable_config/extensions`` are loaded.
- 👉 **To install extension:**
1. Get the ``unpacked`` Extensions from``%localAppData%\Microsoft\Edge SxS\User Data\Default\Extensions``.
1. Get the ``unpacked`` Extensions from``%localAppData%\Microsoft\Edge\User Data\Default\Extensions``.
2. Here look for the `mainfest.json` for example ublock `{string-id}/1.62.0_0/manifest.json` as all the content beside is the extension
3. Now we can copy the contents of ``{string-id}/1.62.0_0`` to ``%localAppData%\Programs\LNV\Stremio-5\portable_config\extensions\ublock``
4. Important is that the ``mainfest.json`` is located directly in ``portable_config\extensions\ublock``
5. **Done**. Restart app and addons will be loaded. If loading fails check ``portable_config\errors-{date}.txt``
- **Supported Extensions**: Some extension need support added manually. These extension can be downloaded [here](https://github.com/Zaarrg/stremio-desktop-v5/tree/webview-windows/extensions).
- ⚙️ **App Settings**
- **All App Settings** can be adjusted with ``portable_config\stremio-settings.ini``
@ -194,13 +211,31 @@
- 🔍 ``AllowZoom`` Allow zoom via `pinch action` or ``CTRL+Scroll``
- ❌ **App Errors**
- If the app does not start and instantly closes, check the error log in ``portable_config\errors-{date}.txt``
- ⚠️ **Common Issues**
- ❗ [WebView2](https://developer.microsoft.com/de-de/microsoft-edge/webview2/#download) not installed Installed by default using the installer but may have failed
- 🌎 Unreachable Web UI. Make sure you can reach the web ui hosted [here](https://zaarrg.github.io/stremio-web-shell-fixes/).
- ⚙️ Invalid MPV configuration like ``mpv.conf``, ``input.conf`` or ``scripts``
- 📄 Invalid ``stremio-settings.ini``
- 🧩 Invalid ``extensions``
- If the app does not start and instantly closes, check the error log in ``portable_config\errors-{date}.txt``
* ⚠️ **Common Issues**
* ❗ **WebView2 not available**
* The **installer** requires [WebView2](https://developer.microsoft.com/de-de/microsoft-edge/webview2/#download) to be installed.
* The **portable version** includes its own WebView2 runtime and does **not** require system installation.
* If a WebView-related error appears, install WebView2 or use the portable build.
* 🌎 **Unreachable Web UI**
The app loads the UI in the following order:
1. [https://stremio.zarg.me/](https://stremio.zarg.me/)
2. [https://zaarrg.github.io/stremio-web-shell-fixes/](https://zaarrg.github.io/stremio-web-shell-fixes/)
3. [https://web.stremio.com/](https://web.stremio.com/)
* If the UI appears stuck, press **F5** to reload.
* If the cached UI is outdated, use **Ctrl+F5** to clear cache and reload.
* ⚙️ **Invalid MPV configuration**
Invalid or unsupported config in `mpv.conf`, `input.conf`, or `scripts/` may prevent MPV from initializing.
* 📄 **Invalid `stremio-settings.ini`**
A default configuration is available:
[stremio-settings.ini](https://github.com/Zaarrg/stremio-desktop-v5/blob/webview-windows/utils/stremio/stremio-settings.ini)
* If corrupted, delete the file to let the app regenerate it.
* 🧩 **Invalid or incompatible extensions**
Extensions under `portable_config/extensions` may prevent startup.
* **uBlock** or similar blockers can cause infinite loading loops → remove them (see *Browser Extensions* section above).
* 🔁 **Server not running after sleep / incomplete restart**
If the PC went to sleep, the internal stremio server stops.
* Fully close the app via **Task Manager** and restart it.
> **⏳ Note:** A default stremio-settings.ini can be found [here](https://github.com/Zaarrg/stremio-desktop-v5/blob/webview-windows/utils/stremio/stremio-settings.ini)
@ -212,6 +247,7 @@ Enhance your Stremio experience by customizing the MPV player settings. Below ar
- The ``mpv.conf`` file can be found in the following location:
- **Installation Path:** ``%localAppData%\Programs\LNV\Stremio-5\portable_config\mpv.conf``
- **Shaders Folder:** Located within the installation directory ``..\Stremio-5\portable_config\shaders``.
- **Latest Portable Config:** Latest portable config can be found [here](https://raw.githubusercontent.com/Zaarrg/stremio-desktop-v5/webview-windows/utils/mpv/Default%20Portable%20Config.7z).
- **🎹 Usage example of `mpv.conf` for DV Content:**
```shell
@ -232,11 +268,48 @@ Enhance your Stremio experience by customizing the MPV player settings. Below ar
CTRL+4 no-osd change-list glsl-shaders set "~~/shaders/Anime4K_Clamp_Highlights.glsl;~~/shaders/Anime4K_Restore_CNN_VL.glsl;~~/shaders/Anime4K_Upscale_CNN_x2_VL.glsl;~~/shaders/Anime4K_Restore_CNN_M.glsl;~~/shaders/Anime4K_AutoDownscalePre_x2.glsl;~~/shaders/Anime4K_AutoDownscalePre_x4.glsl;~~/shaders/Anime4K_Upscale_CNN_x2_M.glsl"; show-text "Anime4K: Mode A+A (HQ)"
CTRL+5 no-osd change-list glsl-shaders set "~~/shaders/Anime4K_Clamp_Highlights.glsl;~~/shaders/Anime4K_Restore_CNN_Soft_VL.glsl;~~/shaders/Anime4K_Upscale_CNN_x2_VL.glsl;~~/shaders/Anime4K_AutoDownscalePre_x2.glsl;~~/shaders/Anime4K_AutoDownscalePre_x4.glsl;~~/shaders/Anime4K_Restore_CNN_Soft_M.glsl;~~/shaders/Anime4K_Upscale_CNN_x2_M.glsl"; show-text "Anime4K: Mode B+B (HQ)"
CTRL+6 no-osd change-list glsl-shaders set "~~/shaders/Anime4K_Clamp_Highlights.glsl;~~/shaders/Anime4K_Upscale_Denoise_CNN_x2_VL.glsl;~~/shaders/Anime4K_AutoDownscalePre_x2.glsl;~~/shaders/Anime4K_AutoDownscalePre_x4.glsl;~~/shaders/Anime4K_Restore_CNN_M.glsl;~~/shaders/Anime4K_Upscale_CNN_x2_M.glsl"; show-text "Anime4K: Mode C+A (HQ)"
CTRL+0 no-osd change-list glsl-shaders clr ""; show-text "GLSL shaders cleared"
```
> **⏳ Note:** Some keys might not work as key presses are converted from js event.codes to literal values for mpv
- **🔡 Subtitle Customization:**
- Subtitles can be full customized in the ``mpv.conf`` by adding the following:
```shell
# Adjust as needed -
sub-font="Comic Sans MS"
osd-font="Comic Sans MS"
osd-font-size=43
sub-font-size=43
sub-color=#e1fe00
sub-font-size=43
sub-color=#ffffff
sub-font-size=43
sub-border-color=#000000
sub-border-size=2
sub-shadow-offset=1
sub-shadow-color=#000000
sub-spacing=0
sub-margin-y=41
sub-line-spacing=0
ass-line-spacing=0
# To overwrite .ass subs use sub-ass=no or just use F2 to cycle subtitle modification levels
```
- Stremio by default overwrites the following:
```shell
# These 3 options are set using the web ui under the settings page
'subtitlesTextColor': 'sub-color',
'subtitlesBackgroundColor': 'sub-back-color',
'subtitlesOutlineColor': 'sub-border-color',
# Affected mpv sub settings by this are:
sub-color
sub-back-color # + Alias sub-shadow-color
sub-border-color # + Alias sub-outline-color
# All these need to be set via the web ui instead
```
## ⚙️ **Start Arguments**
Use these extra arguments when launching the application:
@ -255,9 +328,19 @@ If you want to build this app yourself, check the “[docs](https://github.com/Z
## ⚠️ **Disclaimer**
This project is not affiliated with **Stremio** in any way.
This fork is provided solely for educational and lawful use. **It does not support piracy or any form of copyright infringement.**
It is the users responsibility to ensure that any content accessed is fully compliant with the DMCA and all applicable copyright laws.
The project maintainers do not condone or support any illegal activities.
## 🤝 **Support Development**
If you enjoy this project and want to support further development, consider [buying me a coffee](https://ko-fi.com/zaarrg). Your support means a lot! ☕
<p align="center">
<a href="https://ko-fi.com/zaarrg">
<img src="https://img.shields.io/badge/Support%20me%20on%20Ko--fi-grey?style=for-the-badge&logo=ko-fi&logoColor=white" alt="Support me on Ko-fi">
</a>
</p>
<p align="center">
<strong>⭐ Made with ❤️ by <a href="https://github.com/Zaarrg">Zaarrg</a></strong>
</p>
</p>

View file

@ -235,27 +235,52 @@ function find7zExecutable() {
const version = releaseJson.tag_name || 'latest';
console.log(`Latest version: ${version}`);
// Step 2: Find the 'full-package' .7z asset
const assets = releaseJson.assets;
const fullPackageAsset = assets.find(asset => asset.name.includes('full-package') && asset.name.endsWith('.7z'));
// Step 2: Locate and download the 'full-package' asset(s) (single or multi-part)
const assets = releaseJson.assets || [];
const fullPackageCandidates = assets.filter(a =>
a.name.includes('full-package') &&
(a.name.endsWith('.7z') || /\.7z\.\d+$/.test(a.name))
);
if (!fullPackageAsset) {
throw new Error("No 'full-package' .7z asset found in the latest release.");
if (fullPackageCandidates.length === 0) {
throw new Error("No 'full-package' .7z or .7z.NNN assets found in the latest release.");
}
const downloadUrl = fullPackageAsset.browser_download_url;
const assetName = fullPackageAsset.name;
const downloadedFilePath = path.join(TEMP_DIR, assetName);
// Group by base name (strip .7z or .7z.NNN)
const groups = fullPackageCandidates.reduce((acc, a) => {
const base = a.name.replace(/\.7z(\.\d+)?$/, '');
(acc[base] ||= []).push(a);
return acc;
}, {});
console.log(`Downloading asset: ${assetName}`);
await downloadFile(downloadUrl, downloadedFilePath);
console.log(`Downloaded to ${downloadedFilePath}`);
// Pick the group with the most parts (typically only one group exists in a release)
const [selectedBase, selectedGroup] = Object.entries(groups)
.sort((a, b) => b[1].length - a[1].length)[0];
// Step 3: Extract the .7z archive
// Sort deterministically: .7z (treated like part 0) or .7z.001, .002, ...
const sortedAssets = selectedGroup.slice().sort((a, b) => {
const pa = (/\.7z\.(\d+)$/.exec(a.name)?.[1]) ? parseInt(/\.7z\.(\d+)$/.exec(a.name)[1], 10) : 0;
const pb = (/\.7z\.(\d+)$/.exec(b.name)?.[1]) ? parseInt(/\.7z\.(\d+)$/.exec(b.name)[1], 10) : 0;
return pa - pb;
});
// Download all parts into TEMP_DIR
const downloadedParts = [];
for (const asset of sortedAssets) {
const dest = path.join(TEMP_DIR, asset.name);
console.log(`Downloading asset: ${asset.name}`);
await downloadFile(asset.browser_download_url, dest);
downloadedParts.push(dest);
}
// For extraction: if multipart, 7-Zip expects we point at the .7z.001; if single, the .7z file itself
const archiveToExtract = downloadedParts[0];
// Step 3: Extract the archive (7-Zip will auto-detect and read all parts if .001 is used)
const extractDir = path.join(TEMP_DIR, 'extracted');
fs.mkdirSync(extractDir, { recursive: true });
console.log(`Extracting ${downloadedFilePath} to ${extractDir}...`);
execCommand(`${sevenZipPath} x "${downloadedFilePath}" -o"${extractDir}" -y`, TEMP_DIR);
console.log(`Extracting ${path.basename(archiveToExtract)} to ${extractDir}...`);
execCommand(`${sevenZipPath} x "${archiveToExtract}" -o"${extractDir}" -y`, TEMP_DIR);
console.log('Extraction complete.');
// Step 4: Identify the root directory inside the extracted folder
@ -346,7 +371,7 @@ function find7zExecutable() {
console.log('Cleanup complete.');
console.log('=== Build AnimeJaNai Script Completed Successfully ===');
process.exit(1);
process.exit(0);
} catch (error) {
console.error('Error during build:', error.message);
process.exit(1);

View file

@ -37,7 +37,7 @@ const DEFAULT_SETTINGS_FOLDER = path.join(SOURCE_DIR, 'utils', 'stremio');
const DEFAULT_NSIS = 'C:\\Program Files (x86)\\NSIS\\makensis.exe';
//VCPKG
const VCPKG_TRIPLET = ARCH === 'x86' ? 'x86-windows-static' : 'x64-windows-static';
const VCPKG_CMAKE = 'C:/bin/vcpkg/scripts/buildsystems/vcpkg.cmake';
const VCPKG_CMAKE = 'G:\\Documents\\Github\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake';
// ---------------------------------------------------------------------
// Main
@ -48,16 +48,17 @@ const VCPKG_CMAKE = 'C:/bin/vcpkg/scripts/buildsystems/vcpkg.cmake';
const args = process.argv.slice(2);
const buildInstaller = args.includes('--installer');
const buildPortable = args.includes('--portable');
const debugBuild = args.includes('--debug');
// 3) Run CMake + Ninja in ../cmake-build-release (64-bit)
if (!fs.existsSync(BUILD_DIR)) {
fs.mkdirSync(BUILD_DIR, { recursive: true });
}
console.log('\n=== Running CMake in cmake-build-release ===');
console.log(`\n=== Running CMake in cmake-build-${debugBuild ? "Debug" : "Release"} ===`);
process.chdir(BUILD_DIR);
execSync(
`cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=${VCPKG_CMAKE} -DVCPKG_TARGET_TRIPLET=${VCPKG_TRIPLET} ..`,
`cmake -G Ninja -DCMAKE_BUILD_TYPE=${debugBuild ? "Debug" : "Release"} -DCMAKE_TOOLCHAIN_FILE=${VCPKG_CMAKE} -DVCPKG_TARGET_TRIPLET=${VCPKG_TRIPLET} ..`,
{ stdio: 'inherit' }
);
console.log('=== Running Ninja in cmake-build-release ===');

View file

@ -0,0 +1,67 @@
{
"ublock": {
"name": "uBlock Origin",
"extension_name": "ublock",
"logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/UBlock_Origin.svg/2048px-UBlock_Origin.png",
"description": "uBlock Origin is not just an “ad blocker“, it's a wide-spectrum content blocker with CPU and memory efficiency as a primary feature. If stremio does not start and loads infinitely remove this extension.",
"types": ["Browser Extension", "other"],
"behaviorHints": {
"configurable": true,
"configurationRequired": false,
"adult": false,
"p2p": false
},
"page": "dashboard.html"
},
"premid": {
"name": "PreMiD",
"extension_name": "premid",
"logo": "https://cdn.rcd.gg/PreMiD/websites/P/PreMiD/assets/logo.png",
"description": "PreMiD is a simple, configurable utility that allows you to show what you're doing on the web in your Discord now playing status / Discord Rich Presence",
"types": ["Browser Extension", "other"],
"behaviorHints": {
"configurable": true,
"configurationRequired": false,
"adult": false,
"p2p": false
},
"page": "popup.html"
},
"stylus": {
"name": "Stylus",
"extension_name": "stylus",
"logo": "https://lh3.googleusercontent.com/2K8pc_5-2DkPam9b3oAWoITZ7IuIz68A5a8Ssg2_MNNHTPWPOPSBVTFdTmeVu9hi8GJxpKbvTekgwpeyGV6vXyBKH80",
"description": "Redesign the web with Stylus, a user styles manager. Stylus allows you to easily install themes and skins for many popular sites.",
"types": ["Browser Extension", "other"],
"behaviorHints": {
"configurable": true,
"configurationRequired": false,
"adult": false,
"p2p": false
},
"page": "manage.html"
},
"fallback": {
"name": "",
"extension_name": "",
"logo": "",
"description": "No description available. Create a GitHub issue to get this extension supported.",
"types": ["Browser Extension", "other"],
"behaviorHints": {
"configurable": true,
"configurationRequired": false,
"adult": false,
"p2p": false
},
"page": ""
},
"domains": [
"https://discord.com",
"https://premid.app",
"https://login.premid.app",
"https://uso.kkx.one",
"https://userstyles.world",
"https://raw.githubusercontent.com/uso-archive",
"chrome-extension://"
]
}

Binary file not shown.

Binary file not shown.

BIN
images/stremio2.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

BIN
images/stremio2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

111
src/core/globals.cpp Normal file
View file

@ -0,0 +1,111 @@
#include "globals.h"
// Window & instance
TCHAR szWindowClass[] = APP_NAME;
TCHAR szTitle[] = APP_TITLE;
HINSTANCE g_hInst = nullptr;
HWND g_hWnd = nullptr;
HBRUSH g_darkBrush = nullptr;
HANDLE g_hMutex = nullptr;
HHOOK g_hMouseHook = nullptr;
std::vector<std::wstring> g_webuiUrls = {
L"https://stremio.zarg.me/",
L"https://zaarrg.github.io/stremio-web-shell-fixes/",
L"https://web.stremio.com/"
};
std::vector<std::wstring> g_domainWhitelist;
std::string g_updateUrl= "https://raw.githubusercontent.com/Zaarrg/stremio-desktop-v5/refs/heads/webview-windows/version/version.json";
std::wstring g_extensionsDetailsUrl= L"https://raw.githubusercontent.com/Zaarrg/stremio-desktop-v5/refs/heads/webview-windows/extensions/extensions.json";
std::wstring g_webuiUrl;
// Command-line args
bool g_streamingServer = true;
bool g_autoupdaterForceFull = false;
// mpv
mpv_handle* g_mpv = nullptr;
std::set<std::string> g_observedProps;
bool g_initialSet = false;
std::string g_initialVO = "gpu-next";
int g_currentVolume = 50;
const std::vector<std::wstring> g_subtitleExtensions = {
L".srt", L".ass", L".ssa", L".sub", L".vtt", L".ttml",
L".dfxp", L".smi", L".sami", L".sup", L".scc",
L".xml", L".lrc", L".pjs", L".mpl", L".usf",
L".qtvr"
};
// Node
std::atomic_bool g_nodeRunning = false;
std::thread g_nodeThread;
HANDLE g_nodeProcess = nullptr;
HANDLE g_nodeOutPipe = nullptr;
HANDLE g_nodeInPipe = nullptr;
// WebView2
wil::com_ptr<ICoreWebView2Controller4> g_webviewController;
wil::com_ptr<ICoreWebView2Profile8> g_webviewProfile;
wil::com_ptr<ICoreWebView2_21> g_webview;
// Tray
std::vector<MenuItem> g_menuItems;
NOTIFYICONDATA g_nid = {0};
bool g_showWindow = true;
bool g_alwaysOnTop= false;
bool g_isFullscreen = false;
bool g_closeOnExit = false;
bool g_useDarkTheme = false;
bool g_isPipMode = false;
int g_thumbFastHeight = 0;
int g_hoverIndex = -1;
HFONT g_hMenuFont = nullptr;
HANDLE g_serverJob = nullptr;
HWND g_trayHwnd = nullptr;
// Ini Settings
bool g_pauseOnMinimize = true;
bool g_pauseOnLostFocus = false;
bool g_allowZoom = false;
bool g_isRpcOn = true;
// Tray sizes
int g_tray_itemH = 31;
int g_tray_sepH = 8;
int g_tray_w = 200;
int g_font_height = 12;
// Splash
HWND g_hSplash = nullptr;
HBITMAP g_hSplashImage = nullptr;
float g_splashOpacity= 1.0f;
int g_pulseDirection = -1;
ULONG_PTR g_gdiplusToken = 0;
// Pending messages
std::vector<nlohmann::json> g_outboundMessages;
std::wstring g_launchProtocol;
std::atomic<bool> g_isAppReady = false;
std::atomic<bool> g_waitStarted(false);
// Extensions
std::map<std::wstring, std::wstring> g_extensionMap;
std::vector<std::wstring> g_scriptQueue;
// Updater
std::atomic_bool g_updaterRunning = false;
std::filesystem::path g_installerPath;
std::thread g_updaterThread;
const char* public_key_pem = R"(-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoXoJRQ81xOT3Gx6+hsWM
ZiD4PwtLdxxNhEdL/iK0yp6AdO/L0kcSHk9YCPPx0XPK9sssjSV5vCbNE/2IJxnh
/mV+3GAMmXgMvTL+DZgrHafnxe1K50M+8Z2z+uM5YC9XDLppgnC6OrUjwRqNHrKI
T1vcgKf16e/TdKj8xlgadoHBECjv6dr87nbHW115bw8PVn2tSk/zC+QdUud+p6KV
zA6+FT9ZpHJvdS3R0V0l7snr2cwapXF6J36aLGjJ7UviRFVWEEsQaKtAAtTTBzdD
4B9FJ2IJb/ifdnVzeuNTDYApCSE1F89XFWN9FoDyw7Jkk+7u4rsKjpcnCDTd9ziG
kwIDAQAB
-----END PUBLIC KEY-----)";
// ThumbFast
std::atomic<bool> g_ignoreHover(false);
std::chrono::steady_clock::time_point g_ignoreUntil;

158
src/core/globals.h Normal file
View file

@ -0,0 +1,158 @@
#ifndef GLOBALS_H
#define GLOBALS_H
#include <windows.h>
#include <shellapi.h>
#include <dwmapi.h>
#include <string>
#include <thread>
#include <atomic>
#include <set>
#include <vector>
#include <chrono>
#include <filesystem>
#include <wil/com.h>
#include "nlohmann/json.hpp"
#include "mpv/client.h"
#include <WebView2.h>
#include <WebView2EnvironmentOptions.h>
// For our JSON convenience
using json = nlohmann::json;
// -----------------------------------------------------------------------------
// App info
// -----------------------------------------------------------------------------
#define APP_TITLE "Stremio - Freedom to Stream"
#define APP_NAME "Stremio"
#define APP_CLASS L"Stremio"
#define APP_VERSION "5.0.21"
// -----------------------------------------------------------------------------
// Globals
// -----------------------------------------------------------------------------
extern TCHAR szWindowClass[];
extern TCHAR szTitle[];
extern HINSTANCE g_hInst;
extern HWND g_hWnd;
extern HBRUSH g_darkBrush;
extern HANDLE g_hMutex;
extern HHOOK g_hMouseHook;
extern std::vector<std::wstring> g_webuiUrls;
extern std::vector<std::wstring> g_domainWhitelist;
extern std::string g_updateUrl;
extern std::wstring g_extensionsDetailsUrl;
extern std::wstring g_webuiUrl;
// Args
extern bool g_streamingServer;
extern bool g_autoupdaterForceFull;
// mpv
extern mpv_handle* g_mpv;
extern std::set<std::string> g_observedProps;
extern bool g_initialSet;
extern std::string g_initialVO;
extern int g_currentVolume;
extern const std::vector<std::wstring> g_subtitleExtensions;
// custom messages
#define WM_MPV_WAKEUP (WM_APP + 2)
#define WM_TRAYICON (WM_APP + 1)
// Node server
extern std::atomic_bool g_nodeRunning;
extern std::thread g_nodeThread;
extern HANDLE g_nodeProcess;
extern HANDLE g_nodeOutPipe;
extern HANDLE g_nodeInPipe;
// WebView2
extern wil::com_ptr<ICoreWebView2Controller4> g_webviewController;
extern wil::com_ptr<ICoreWebView2Profile8> g_webviewProfile;
extern wil::com_ptr<ICoreWebView2_21> g_webview;
// Tray IDs
#define ID_TRAY_SHOWWINDOW 1001
#define ID_TRAY_ALWAYSONTOP 1002
#define ID_TRAY_CLOSE_ON_EXIT 1003
#define ID_TRAY_USE_DARK_THEME 1004
#define ID_TRAY_PAUSE_MINIMIZED 1005
#define ID_TRAY_PAUSE_FOCUS_LOST 1006
#define ID_TRAY_PICTURE_IN_PICTURE 1007
#define ID_TRAY_QUIT 1008
struct MenuItem
{
UINT id;
bool checked;
bool separator;
std::wstring text;
};
extern std::vector<MenuItem> g_menuItems;
extern NOTIFYICONDATA g_nid;
extern bool g_showWindow;
extern bool g_alwaysOnTop;
extern bool g_isFullscreen;
extern bool g_closeOnExit;
extern bool g_useDarkTheme;
extern bool g_isPipMode;
extern int g_thumbFastHeight;
extern int g_hoverIndex;
extern HFONT g_hMenuFont;
extern HANDLE g_serverJob;
extern HWND g_trayHwnd;
// Ini Settings
extern bool g_pauseOnMinimize;
extern bool g_pauseOnLostFocus;
extern bool g_allowZoom;
extern bool g_isRpcOn;
// Tray sizes
extern int g_tray_itemH;
extern int g_tray_sepH;
extern int g_tray_w;
extern int g_font_height;
// Splash
extern HWND g_hSplash;
extern HBITMAP g_hSplashImage;
extern float g_splashOpacity;
extern int g_pulseDirection;
extern ULONG_PTR g_gdiplusToken;
// App Ready and Event Queue
#define WM_NOTIFY_FLUSH (WM_USER + 101)
#define WM_REACHABILITY_DONE (WM_USER + 200)
extern std::vector<nlohmann::json> g_outboundMessages;
extern std::wstring g_launchProtocol;
extern std::atomic<bool> g_isAppReady;
extern std::atomic<bool> g_waitStarted;
// Extensions
extern std::map<std::wstring, std::wstring> g_extensionMap;
extern std::vector<std::wstring> g_scriptQueue;
// Updater
extern std::atomic_bool g_updaterRunning;
extern std::filesystem::path g_installerPath;
extern std::thread g_updaterThread;
extern const char* public_key_pem;
// Thumb Fast
extern std::atomic<bool> g_ignoreHover;
extern std::chrono::steady_clock::time_point g_ignoreUntil;
constexpr std::chrono::milliseconds IGNORE_DURATION(200);
// -----------------------------------------------------------------------------
// Functions declared here if you need them globally
// -----------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
#endif // GLOBALS_H

File diff suppressed because it is too large Load diff

283
src/mpv/player.cpp Normal file
View file

@ -0,0 +1,283 @@
#include "player.h"
#include <iostream>
#include <cctype>
#include "../core/globals.h"
#include "../utils/crashlog.h"
#include "../utils/helpers.h"
#include "../ui/mainwindow.h"
// Helper for mpv node => JSON
static nlohmann::json mpvNodeToJson(const mpv_node* node);
static nlohmann::json mpvNodeArrayToJson(const mpv_node_list* list)
{
using json = nlohmann::json;
json j = json::array();
if(!list) return j;
for(int i=0; i<list->num; i++){
j.push_back(mpvNodeToJson(&list->values[i]));
}
return j;
}
static nlohmann::json mpvNodeMapToJson(const mpv_node_list* list)
{
using json = nlohmann::json;
json j = json::object();
if(!list) return j;
for(int i=0; i<list->num; i++){
const char* key = (list->keys && list->keys[i]) ? list->keys[i] : "";
mpv_node &val = list->values[i];
j[key] = mpvNodeToJson(&val);
}
return j;
}
static nlohmann::json mpvNodeToJson(const mpv_node* node)
{
using json = nlohmann::json;
if(!node) return nullptr;
switch(node->format)
{
case MPV_FORMAT_STRING:
return node->u.string ? node->u.string : "";
case MPV_FORMAT_INT64:
return (long long)node->u.int64;
case MPV_FORMAT_DOUBLE:
return node->u.double_;
case MPV_FORMAT_FLAG:
return (bool)node->u.flag;
case MPV_FORMAT_NODE_ARRAY:
return mpvNodeArrayToJson(node->u.list);
case MPV_FORMAT_NODE_MAP:
return mpvNodeMapToJson(node->u.list);
default:
return "<unhandled mpv_node format>";
}
}
// Helper to properly capitalize mpv error
static std::string capitalizeFirstLetter(const std::string& input) {
if (input.empty()) return input;
std::string result = input;
result[0] = std::toupper(result[0]);
return result;
}
// Forward
static void MpvWakeup(void* ctx)
{
PostMessage((HWND)ctx, WM_MPV_WAKEUP, 0, 0);
}
void HandleMpvEvents()
{
if(!g_mpv) return;
while(true){
mpv_event* ev = mpv_wait_event(g_mpv, 0);
if(!ev || ev->event_id==MPV_EVENT_NONE) break;
if(ev->error<0) {
std::cerr<<"mpv event error="<<mpv_error_string(ev->error)<<"\n";
}
switch(ev->event_id)
{
case MPV_EVENT_PROPERTY_CHANGE:
{
mpv_event_property* prop=(mpv_event_property*)ev->data;
if(!prop||!prop->name)break;
json j;
j["type"] ="mpv-prop-change";
j["id"] =(int64_t)ev->reply_userdata;
j["name"] = prop->name;
if(ev->error<0)
j["error"]=mpv_error_string(ev->error);
switch(prop->format)
{
case MPV_FORMAT_INT64:
if(prop->data)
j["data"]=(long long)(*(int64_t*)prop->data);
else
j["data"]=nullptr;
break;
case MPV_FORMAT_DOUBLE:
if(prop->data)
j["data"]=*(double*)prop->data;
else
j["data"]=nullptr;
break;
case MPV_FORMAT_FLAG:
if(prop->data)
j["data"]=(*(int*)prop->data!=0);
else
j["data"]=false;
break;
case MPV_FORMAT_STRING:
if(prop->data){
const char*s=*(char**)prop->data;
j["data"]=(s? s:"");
} else {
j["data"]="";
}
break;
case MPV_FORMAT_NODE:
j["data"]=mpvNodeToJson((mpv_node*)prop->data);
break;
default:
j["data"]=nullptr;
break;
}
if (j["name"] == "volume" && g_initialSet) {
g_currentVolume = j["data"];
}
SendToJS("mpv-prop-change", j);
break;
}
case MPV_EVENT_END_FILE:
{
mpv_event_end_file* ef=(mpv_event_end_file*)ev->data;
nlohmann::json j;
j["type"]="mpv-event-ended";
switch(ef->reason){
case MPV_END_FILE_REASON_EOF:
j["reason"]="quit";
SendToJS("mpv-event-ended", j);
break;
case MPV_END_FILE_REASON_ERROR: {
std::string errorString = mpv_error_string(ef->error);
std::string capitalizedErrorString = capitalizeFirstLetter(errorString);
j["reason"]="error";
if(ef->error<0)
j["error"]= capitalizedErrorString;
SendToJS("mpv-event-ended", j);
AppendToCrashLog("[MPV]: " + capitalizedErrorString);
break;
}
default:
j["reason"]="other";
break;
}
break;
}
case MPV_EVENT_SHUTDOWN:
{
std::cout<<"mpv EVENT_SHUTDOWN => terminate\n";
mpv_terminate_destroy(g_mpv);
g_mpv=nullptr;
break;
}
default:
// ignore
break;
}
}
}
void HandleMpvCommand(const std::vector<std::string>& args)
{
std::thread([args](){
if(!g_mpv || args.empty()) return;
std::vector<const char*> cargs;
for(auto &s: args) {
cargs.push_back(s.c_str());
}
cargs.push_back(nullptr);
mpv_command(g_mpv, cargs.data());
}).detach();
}
void HandleMpvSetProp(const std::vector<std::string>& args)
{
std::thread([args](){
if(!g_mpv || args.size()<2) return;
std::string val=args[1];
if(val=="true") val="yes";
if(val=="false") val="no";
mpv_set_property_string(g_mpv, args[0].c_str(), val.c_str());
}).detach();
}
void HandleMpvObserveProp(const std::vector<std::string>& args)
{
std::thread([args](){
if(!g_mpv || args.empty()) return;
std::string pname=args[0];
g_observedProps.insert(pname);
mpv_observe_property(g_mpv,0,pname.c_str(),MPV_FORMAT_NODE);
std::cout<<"Observing prop="<<pname<<"\n";
}).detach();
}
void pauseMPV(bool allowed)
{
if(!allowed) return;
std::vector<std::string> pauseArgs = { "pause", "true" };
HandleMpvSetProp(pauseArgs);
}
bool InitMPV(HWND hwnd)
{
g_mpv = mpv_create();
if(!g_mpv){
std::cerr<<"mpv_create failed\n";
AppendToCrashLog("[MPV]: Create failed");
return false;
}
// portable_config
std::wstring exeDir = GetExeDirectory();
std::wstring cfg = exeDir + L"\\portable_config";
CreateDirectoryW(cfg.c_str(), nullptr);
// Convert config path to UTF-8
int needed = WideCharToMultiByte(CP_UTF8, 0, cfg.c_str(), -1, nullptr, 0, nullptr, nullptr);
std::string utf8(needed, 0);
WideCharToMultiByte(CP_UTF8, 0, cfg.c_str(), -1, &utf8[0], needed, nullptr, nullptr);
mpv_set_option_string(g_mpv, "config-dir", utf8.c_str());
mpv_set_option_string(g_mpv, "load-scripts","yes");
mpv_set_option_string(g_mpv, "config","yes");
mpv_set_option_string(g_mpv, "terminal","yes");
mpv_set_option_string(g_mpv, "msg-level","all=v");
int64_t wid=(int64_t)hwnd;
mpv_set_option(g_mpv,"wid", MPV_FORMAT_INT64, &wid);
mpv_set_wakeup_callback(g_mpv, MpvWakeup, hwnd);
if(mpv_initialize(g_mpv)<0){
std::cerr<<"mpv_initialize failed\n";
AppendToCrashLog("[MPV]: Initialize failed");
return false;
}
// Set VO
mpv_set_option_string(g_mpv,"vo","gpu-next");
// demux/caching
mpv_set_property_string(g_mpv,"demuxer-lavf-probesize", "524288");
mpv_set_property_string(g_mpv,"demuxer-lavf-analyzeduration","0.5");
mpv_set_property_string(g_mpv,"demuxer-max-bytes","300000000");
mpv_set_property_string(g_mpv,"demuxer-max-packets","150000000");
mpv_set_property_string(g_mpv,"cache","yes");
mpv_set_property_string(g_mpv,"cache-pause","no");
mpv_set_property_string(g_mpv,"cache-secs","60");
mpv_set_property_string(g_mpv,"vd-lavc-threads","0");
mpv_set_property_string(g_mpv,"ad-lavc-threads","0");
mpv_set_property_string(g_mpv,"audio-fallback-to-null","yes");
mpv_set_property_string(g_mpv,"audio-client-name",APP_NAME);
mpv_set_property_string(g_mpv,"title",APP_NAME);
return true;
}
void CleanupMPV()
{
if(g_mpv){
mpv_terminate_destroy(g_mpv);
g_mpv=nullptr;
}
}

21
src/mpv/player.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef PLAYER_H
#define PLAYER_H
#include <string>
#include <vector>
#include <windows.h>
#include "nlohmann/json.hpp"
bool InitMPV(HWND hwnd);
void CleanupMPV();
void HandleMpvEvents();
// Commands
void HandleMpvCommand(const std::vector<std::string>& args);
void HandleMpvSetProp(const std::vector<std::string>& args);
void HandleMpvObserveProp(const std::vector<std::string>& args);
// For pausing
void pauseMPV(bool allowed);
#endif // PLAYER_H

144
src/node/server.cpp Normal file
View file

@ -0,0 +1,144 @@
#include "server.h"
#include <windows.h>
#include <shlobj.h>
#include <string>
#include <thread>
#include <atomic>
#include <iostream>
#include "../core/globals.h"
#include "../ui/mainwindow.h"
#include "../utils/crashlog.h"
#include "../utils/helpers.h"
static void NodeOutputThreadProc()
{
char buf[1024];
DWORD readSz=0;
while(g_nodeRunning){
BOOL ok = ReadFile(g_nodeOutPipe, buf, sizeof(buf)-1, &readSz, nullptr);
if(!ok || readSz==0) break;
buf[readSz]='\0';
std::cout<<"[node] "<<buf;
}
std::cout<<"NodeOutputThreadProc done.\n";
}
bool StartNodeServer()
{
std::wstring exeDir = GetExeDirectory();
std::wstring exePath = exeDir + L"\\stremio-runtime.exe";
std::wstring scriptPath = exeDir + L"\\server.js";
if (!FileExists(exePath) || !FileExists(scriptPath)) {
// Check alternative path in %localappdata%
wchar_t localAppData[MAX_PATH];
if (SUCCEEDED(SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, localAppData))) {
std::wstring altDir = std::wstring(localAppData) + L"\\Programs\\StremioService";
std::wstring altExePath = altDir + L"\\stremio-runtime.exe";
std::wstring altScriptPath = altDir + L"\\server.js";
if (FileExists(altExePath) && FileExists(altScriptPath)) {
exePath = altExePath;
scriptPath = altScriptPath;
exeDir = altDir;
} else {
AppendToCrashLog(L"[NODE]: Missing stremio-runtime.exe and server.js in both exeDir and localappdata.");
return false;
}
} else {
AppendToCrashLog(L"[NODE]: Failed to retrieve local app data path.");
return false;
}
}
if (!g_serverJob) {
g_serverJob = CreateJobObject(nullptr, nullptr);
if(!g_serverJob){
AppendToCrashLog(L"[NODE]: Failed to create Job Object.");
return false;
}
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo = {0};
jobInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
SetInformationJobObject(g_serverJob, JobObjectExtendedLimitInformation, &jobInfo, sizeof(jobInfo));
}
SECURITY_ATTRIBUTES sa;ZeroMemory(&sa, sizeof(sa));
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
HANDLE outR=nullptr, outW=nullptr;
if(!CreatePipe(&outR,&outW,&sa,0)){
AppendToCrashLog(L"[NODE]: CreatePipe fail1");
return false;
}
SetHandleInformation(outR,HANDLE_FLAG_INHERIT,0);
HANDLE inR=nullptr, inW=nullptr;
if(!CreatePipe(&inR,&inW,&sa,0)){
AppendToCrashLog(L"[NODE]: CreatePipe fail2");
CloseHandle(outR);CloseHandle(outW);
return false;
}
SetHandleInformation(inW,HANDLE_FLAG_INHERIT,0);
STARTUPINFOW si;ZeroMemory(&si,sizeof(si));
si.cb=sizeof(si);
si.hStdOutput=outW; si.hStdError=outW; si.hStdInput=inR;
si.dwFlags=STARTF_USESTDHANDLES;
PROCESS_INFORMATION pi;ZeroMemory(&pi,sizeof(pi));
std::wstring cmdLine = L"\"stremio-runtime.exe\" \"server.js\"";
SetEnvironmentVariableW(L"NO_CORS", L"1");
BOOL success = CreateProcessW(
nullptr, &cmdLine[0],
nullptr,nullptr, TRUE,
CREATE_NO_WINDOW,nullptr,nullptr,
&si, &pi
);
CloseHandle(inR);
CloseHandle(outW);
if(!success){
std::wstring err = L"Failed to launch stremio-runtime.exe\nGetLastError=" + std::to_wstring(GetLastError());
AppendToCrashLog(err);
CloseHandle(inW);CloseHandle(outR);
return false;
}
// Ensure the process belongs to the job
AssignProcessToJobObject(g_serverJob, pi.hProcess);
g_nodeProcess = pi.hProcess;
CloseHandle(pi.hThread);
g_nodeRunning = true;
g_nodeOutPipe = outR;
g_nodeInPipe = inW;
g_nodeThread = std::thread(NodeOutputThreadProc);
std::cout<<"Node server started.\n";
// Let front-end know:
nlohmann::json j;
j["type"] ="ServerStarted";
g_outboundMessages.push_back(j);
PostMessage(g_hWnd, WM_NOTIFY_FLUSH, 0, 0);
return true;
}
void StopNodeServer()
{
if(g_nodeRunning){
g_nodeRunning=false;
if(g_nodeProcess){
TerminateProcess(g_nodeProcess,0);
WaitForSingleObject(g_nodeProcess,INFINITE);
CloseHandle(g_nodeProcess); g_nodeProcess=nullptr;
}
if(g_nodeThread.joinable()) g_nodeThread.join();
if(g_nodeOutPipe){CloseHandle(g_nodeOutPipe); g_nodeOutPipe=nullptr;}
if(g_nodeInPipe){CloseHandle(g_nodeInPipe); g_nodeInPipe=nullptr;}
std::cout<<"Node server stopped.\n";
}
}

7
src/node/server.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef SERVER_H
#define SERVER_H
bool StartNodeServer();
void StopNodeServer();
#endif // SERVER_H

View file

@ -1,6 +1,7 @@
#ifndef RESOURCE_H
#define RESOURCE_H
#define IDR_SPLASH_PNG 101
#define IDR_MAINFRAME 101
#define IDR_SPLASH_PNG 102
#endif
#endif // RESOURCE_H

344
src/tray/tray.cpp Normal file
View file

@ -0,0 +1,344 @@
#include "tray.h"
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include <windowsx.h>
#include "../core/globals.h"
#include "../utils/crashlog.h"
#include "../utils/helpers.h"
#include "../ui/mainwindow.h"
#include "../resource.h"
static LRESULT CALLBACK DarkTrayMenuProc(HWND, UINT, WPARAM, LPARAM);
static HWND CreateDarkTrayMenuWindow();
static void ShowDarkTrayMenu();
static void CreateRoundedRegion(HWND hWnd, int w, int h, int radius);
void CreateTrayIcon(HWND hWnd)
{
g_nid.cbSize=sizeof(NOTIFYICONDATA);
g_nid.hWnd=hWnd;
g_nid.uID=1;
g_nid.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP;
g_nid.uCallbackMessage=WM_TRAYICON;
HICON hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDR_MAINFRAME));
g_nid.hIcon = hIcon;
_tcscpy_s(g_nid.szTip, _T("Stremio SingleInstance"));
Shell_NotifyIcon(NIM_ADD,&g_nid);
}
void RemoveTrayIcon()
{
Shell_NotifyIcon(NIM_DELETE,&g_nid);
if(g_nid.hIcon){
DestroyIcon(g_nid.hIcon);
g_nid.hIcon=nullptr;
}
}
void LoadCustomMenuFont()
{
if (g_hMenuFont) {
DeleteObject(g_hMenuFont);
g_hMenuFont = nullptr;
}
LOGFONTW lf = { 0 };
lf.lfHeight = -g_font_height;
lf.lfWeight = FW_MEDIUM;
wcscpy_s(lf.lfFaceName, L"Arial Rounded MT");
lf.lfQuality = CLEARTYPE_QUALITY;
g_hMenuFont = CreateFontIndirectW(&lf);
// fallback to system menu font if custom is not available
if (!g_hMenuFont) {
NONCLIENTMETRICSW ncm = { sizeof(ncm) };
if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
{
ncm.lfMenuFont.lfQuality = CLEARTYPE_QUALITY;
g_hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont);
}
}
if (!g_hMenuFont) {
std::cerr << "Failed to load custom menu font.\n";
AppendToCrashLog("[FONT]: Failed to load custom menu font");
}
}
void ShowTrayMenu(HWND hWnd)
{
ShowDarkTrayMenu();
}
static HWND CreateDarkTrayMenuWindow()
{
static bool s_classRegistered = false;
if (!s_classRegistered)
{
WNDCLASSEXW wcex = { sizeof(wcex) };
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = DarkTrayMenuProc;
wcex.hInstance = GetModuleHandle(nullptr);
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = nullptr;
wcex.lpszClassName = L"DarkTrayMenuWnd";
RegisterClassExW(&wcex);
s_classRegistered = true;
}
HWND hMenuWnd = CreateWindowExW(
WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
L"DarkTrayMenuWnd",
L"",
WS_POPUP,
0, 0, 200, 200,
nullptr, nullptr, GetModuleHandle(nullptr), nullptr
);
if(!hMenuWnd) {
DWORD errorCode = GetLastError();
std::string errorMessage = "[TRAY]: Failed to create tray" + std::to_string(errorCode);
std::cerr << errorMessage << "\n";
AppendToCrashLog(errorMessage);
}
g_trayHwnd = hMenuWnd;
return hMenuWnd;
}
static void CreateRoundedRegion(HWND hWnd, int w, int h, int radius)
{
HRGN hrgn = CreateRoundRectRgn(0, 0, w, h, radius, radius);
SetWindowRgn(hWnd, hrgn, TRUE);
}
static void ShowDarkTrayMenu()
{
g_menuItems.clear();
g_menuItems.push_back({ ID_TRAY_SHOWWINDOW, g_showWindow, false, L"Show Window" });
g_menuItems.push_back({ ID_TRAY_ALWAYSONTOP, g_alwaysOnTop, false, L"Always on Top" });
g_menuItems.push_back({ ID_TRAY_PICTURE_IN_PICTURE, g_isPipMode, false, L"Picture in Picture" });
g_menuItems.push_back({ ID_TRAY_PAUSE_MINIMIZED, g_pauseOnMinimize, false, L"Pause Minimized" });
g_menuItems.push_back({ ID_TRAY_PAUSE_FOCUS_LOST, g_pauseOnLostFocus, false, L"Pause Unfocused" });
g_menuItems.push_back({ ID_TRAY_CLOSE_ON_EXIT, g_closeOnExit, false, L"Close on Exit" });
g_menuItems.push_back({ ID_TRAY_USE_DARK_THEME, g_useDarkTheme, false, L"Use Dark Theme" });
g_menuItems.push_back({ 0, false, true, L"" });
g_menuItems.push_back({ ID_TRAY_QUIT, false, false, L"Quit" });
HWND hMenuWnd = CreateDarkTrayMenuWindow();
int itemH = g_tray_itemH;
int sepH = g_tray_sepH;
int w = g_tray_w;
int totalH = 0;
for (auto &it: g_menuItems) {
totalH += it.separator ? sepH : itemH;
}
POINT cursor;
GetCursorPos(&cursor);
int posX = cursor.x;
int posY = cursor.y - totalH;
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
if (posX + w > screenWidth) {
posX = cursor.x - w;
}
if (posX < 0) posX = 0;
if (posY < 0) posY = 0;
if (posY + totalH > screenHeight) posY = screenHeight - totalH;
SetCapture(hMenuWnd);
SetWindowPos(hMenuWnd, HWND_TOPMOST, posX, posY, w, totalH, SWP_SHOWWINDOW);
CreateRoundedRegion(hMenuWnd, w, totalH, 10);
ShowWindow(hMenuWnd, SW_SHOW);
UpdateWindow(hMenuWnd);
SetForegroundWindow(hMenuWnd);
SetFocus(hMenuWnd);
}
static LRESULT CALLBACK DarkTrayMenuProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_ACTIVATE:
if (LOWORD(wParam) == WA_INACTIVE) {
DestroyWindow(hWnd);
}
break;
case WM_KILLFOCUS:
case WM_CAPTURECHANGED:
DestroyWindow(hWnd);
break;
case WM_ERASEBKGND:
return 1;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
RECT rcClient;
GetClientRect(hWnd, &rcClient);
COLORREF bgBase, bgHover, txtNormal, txtCheck, lineColor;
if (g_useDarkTheme)
{
bgBase = RGB(30,30,30);
bgHover = RGB(50,50,50);
txtNormal= RGB(200,200,200);
txtCheck = RGB(200,200,200);
lineColor= RGB(80,80,80);
}
else
{
bgBase = RGB(240,240,240);
bgHover = RGB(200,200,200);
txtNormal= RGB(0,0,0);
txtCheck = RGB(0,0,0);
lineColor= RGB(160,160,160);
}
HDC memDC = CreateCompatibleDC(hdc);
HBITMAP memBmp = CreateCompatibleBitmap(hdc, rcClient.right, rcClient.bottom);
HGDIOBJ oldMemBmp = SelectObject(memDC, memBmp);
HBRUSH bgBrush = CreateSolidBrush(bgBase);
FillRect(memDC, &rcClient, bgBrush);
DeleteObject(bgBrush);
int y = 0;
int itemH = g_tray_itemH;
int sepH = g_tray_sepH;
for (int i=0; i<(int)g_menuItems.size(); i++)
{
auto &it = g_menuItems[i];
if(it.separator)
{
int midY = y + sepH/2;
HPEN oldPen = (HPEN)SelectObject(memDC, CreatePen(PS_SOLID,1,lineColor));
MoveToEx(memDC, 5, midY, nullptr);
LineTo(memDC, rcClient.right-5, midY);
DeleteObject(SelectObject(memDC, oldPen));
y += sepH;
}
else
{
bool hovered = (i == g_hoverIndex);
RECT itemRc = {0, y, rcClient.right, y+itemH};
HBRUSH itemBg = CreateSolidBrush(hovered ? bgHover : bgBase);
FillRect(memDC, &itemRc, itemBg);
DeleteObject(itemBg);
if(it.checked)
{
RECT cbox = { 4, y, 20, y+itemH };
SetTextColor(memDC, txtCheck);
SetBkMode(memDC, TRANSPARENT);
DrawTextW(memDC, L"\u2713", -1, &cbox, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
SetBkMode(memDC, TRANSPARENT);
SetTextColor(memDC, txtNormal);
HFONT oldFnt = (HFONT)SelectObject(memDC, g_hMenuFont);
RECT textRc = { 24, y, rcClient.right-5, y+itemH };
DrawTextW(memDC, it.text.c_str(), -1, &textRc, DT_SINGLELINE | DT_VCENTER | DT_LEFT);
SelectObject(memDC, oldFnt);
y += itemH;
}
}
BitBlt(hdc, 0,0, rcClient.right, rcClient.bottom, memDC, 0,0, SRCCOPY);
SelectObject(memDC, oldMemBmp);
DeleteObject(memBmp);
DeleteDC(memDC);
EndPaint(hWnd, &ps);
return 0;
}
case WM_MOUSEMOVE:
{
int xPos = GET_X_LPARAM(lParam);
int yPos = GET_Y_LPARAM(lParam);
int itemH = g_tray_itemH, sepH = g_tray_sepH;
int curY = 0, hover = -1;
for(int i=0; i<(int)g_menuItems.size(); i++)
{
auto &it = g_menuItems[i];
int h = it.separator ? sepH : itemH;
if(!it.separator && yPos>=curY && yPos<(curY+h)) {
hover = i;
break;
}
curY += h;
}
if(hover != g_hoverIndex){
g_hoverIndex = hover;
InvalidateRect(hWnd, nullptr, FALSE);
}
SetCursor(LoadCursor(nullptr, hover!=-1 ? IDC_HAND : IDC_ARROW));
break;
}
case WM_LBUTTONUP:
{
POINT pt; GetCursorPos(&pt);
RECT rc; GetWindowRect(hWnd, &rc);
bool inside = PtInRect(&rc, pt);
if(g_hMouseHook) {
UnhookWindowsHookEx(g_hMouseHook);
g_hMouseHook = nullptr;
}
if(inside && g_hoverIndex >= 0 && g_hoverIndex < (int)g_menuItems.size())
{
auto &it = g_menuItems[g_hoverIndex];
if (!it.separator)
{
PostMessage(g_hWnd, WM_COMMAND, it.id, 0);
}
}
DestroyWindow(hWnd);
break;
}
case WM_DESTROY:
g_hoverIndex = -1;
if (g_hMouseHook) {
UnhookWindowsHookEx(g_hMouseHook);
g_hMouseHook = nullptr;
}
ReleaseCapture();
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
void TogglePictureInPicture(HWND hWnd, bool enable)
{
LONG style = GetWindowLong(hWnd, GWL_STYLE);
if(enable) {
g_alwaysOnTop = true;
style &= ~WS_CAPTION;
SetWindowLong(hWnd, GWL_STYLE, style);
SetWindowPos(hWnd, HWND_TOPMOST,0,0,0,0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_FRAMECHANGED);
} else {
g_alwaysOnTop = false;
style |= WS_CAPTION;
SetWindowLong(hWnd, GWL_STYLE, style);
SetWindowPos(hWnd, HWND_NOTOPMOST,0,0,0,0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_FRAMECHANGED);
}
g_isPipMode = enable;
if(g_webview) {
nlohmann::json j;
if(enable)
SendToJS("showPictureInPicture", j);
else
SendToJS("hidePictureInPicture", j);
}
}

14
src/tray/tray.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef TRAY_H
#define TRAY_H
#include <windows.h>
void CreateTrayIcon(HWND hWnd);
void RemoveTrayIcon();
void ShowTrayMenu(HWND hWnd);
void LoadCustomMenuFont();
void TogglePictureInPicture(HWND hWnd, bool enable);
#endif // TRAY_H

593
src/ui/mainwindow.cpp Normal file
View file

@ -0,0 +1,593 @@
#include "mainwindow.h"
#include <fstream>
#include <iostream>
#include <windowsx.h>
#include <ShlObj.h>
#include "../core/globals.h"
#include "../resource.h"
#include "../utils/crashlog.h"
#include "../utils/helpers.h"
#include "../utils/config.h"
#include "../mpv/player.h"
#include "../tray/tray.h"
#include "../ui/splash.h"
#include "../webview/webview.h"
#include "../updater/updater.h"
#include "../utils/discord.h"
// Single-instance
bool FocusExistingInstance(const std::wstring &protocolArg)
{
HWND hExistingWnd = FindWindowW(APP_CLASS, nullptr);
if(hExistingWnd) {
if(IsIconic(hExistingWnd)) {
ShowWindow(hExistingWnd, SW_RESTORE);
} else if(!IsWindowVisible(hExistingWnd)) {
ShowWindow(hExistingWnd, SW_SHOW);
}
SetForegroundWindow(hExistingWnd);
SetFocus(hExistingWnd);
if(!protocolArg.empty()) {
COPYDATASTRUCT cds;
cds.dwData = 1;
cds.cbData = static_cast<DWORD>(protocolArg.size() * sizeof(wchar_t));
cds.lpData = (PVOID)protocolArg.c_str();
SendMessage(hExistingWnd, WM_COPYDATA, 0, (LPARAM)&cds);
}
return true;
}
return false;
}
bool CheckSingleInstance(int argc, char* argv[], std::wstring &outProtocolArg)
{
g_hMutex = CreateMutexW(nullptr, FALSE, L"SingleInstanceMtx_StremioWebShell");
if(!g_hMutex){
std::wcerr << L"CreateMutex failed => fallback to multi.\n";
AppendToCrashLog("CreateMutex failed => fallback to multi.");
return true;
}
std::wstring protocolArg;
for(int i=1; i<argc; ++i){
int size_needed = MultiByteToWideChar(CP_UTF8, 0, argv[i], -1, NULL, 0);
if(size_needed > 0){
std::wstring argW(size_needed - 1, 0);
MultiByteToWideChar(CP_UTF8, 0, argv[i], -1, &argW[0], size_needed);
if(argW.rfind(L"stremio://",0)==0 || argW.rfind(L"magnet:",0)==0 || FileExists(argW)) {
protocolArg = argW;
break;
}
}
}
if(GetLastError()==ERROR_ALREADY_EXISTS){
FocusExistingInstance(protocolArg);
return false;
}
outProtocolArg = protocolArg;
return true;
}
void ToggleFullScreen(HWND hWnd, bool enable)
{
static WINDOWPLACEMENT prevPlc={sizeof(prevPlc)};
if(enable==g_isFullscreen) return;
g_isFullscreen = enable;
if(enable){
GetWindowPlacement(hWnd, &prevPlc);
MONITORINFO mi={sizeof(mi)};
if(GetMonitorInfoW(MonitorFromWindow(hWnd,MONITOR_DEFAULTTOPRIMARY), &mi)){
SetWindowLongW(hWnd,GWL_STYLE,WS_POPUP|WS_VISIBLE);
SetWindowPos(hWnd,HWND_TOP,
mi.rcMonitor.left, mi.rcMonitor.top,
mi.rcMonitor.right - mi.rcMonitor.left,
mi.rcMonitor.bottom - mi.rcMonitor.top,
SWP_FRAMECHANGED|SWP_SHOWWINDOW);
}
} else {
SetWindowLongW(hWnd,GWL_STYLE,WS_OVERLAPPEDWINDOW|WS_VISIBLE);
SetWindowPlacement(hWnd,&prevPlc);
SetWindowPos(hWnd,nullptr,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED|SWP_SHOWWINDOW);
}
}
// Dark/Light theme
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#endif
static void UpdateTheme(HWND hWnd)
{
if(g_useDarkTheme){
BOOL dark = TRUE;
DwmSetWindowAttribute(hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &dark, sizeof(dark));
} else {
BOOL dark = FALSE;
DwmSetWindowAttribute(hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &dark, sizeof(dark));
}
}
// Handling inbound/outbound Messages
void SendToJS(const std::string &eventName, const nlohmann::json &eventData)
{
static int nextId = 1;
nlohmann::json msg;
msg["type"] = 1;
msg["object"] = "transport";
msg["id"] = nextId++;
msg["args"] = { eventName, eventData };
// Serialize to wstring + Post
std::string payload = msg.dump();
std::wstring wpayload(payload.begin(), payload.end());
g_webview->PostWebMessageAsString(wpayload.c_str());
#ifdef DEBUG_LOG
std::cout << "[Native->JS] " << payload << "\n";
#endif
}
void HandleEvent(const std::string &ev, std::vector<std::string> &args)
{
if(ev=="mpv-command"){
if(!args.empty() && args[0] == "loadfile" && args.size() > 1) {
if (args[1].rfind("http://", 0) != 0 && args[1].rfind("https://", 0) != 0) {
args[1] = decodeURIComponent(args[1]);
}
std::vector<std::string> voArgs = {"vo",g_initialVO};
HandleMpvSetProp(voArgs);
std::vector<std::string> volumeArgs = {"volume", std::to_string(g_currentVolume)};
HandleMpvSetProp(volumeArgs);
g_initialSet = true;
}
HandleMpvCommand(args);
} else if(ev=="mpv-set-prop"){
HandleMpvSetProp(args);
} else if(ev=="mpv-observe-prop"){
HandleMpvObserveProp(args);
} else if(ev=="app-ready"){
g_isAppReady=true;
HideSplash();
PostMessage(g_hWnd, WM_NOTIFY_FLUSH, 0, 0);
} else if(ev=="update-requested"){
RunInstallerAndExit();
} else if(ev == "seek-hover") {
if (g_thumbFastHeight == 0) return;
if(g_ignoreHover) {
auto now = std::chrono::steady_clock::now();
if(now < g_ignoreUntil) {
return;
}
g_ignoreHover = false;
}
// Expecting arguments: hovered_seconds, x, y
if(args.size() < 3) {
std::cerr << "seek-hover requires at least 3 arguments.\n";
return;
}
// Convert the y-coordinate from string to an integer
int yCoord = 0;
try {
yCoord = std::stoi(args[2]);
} catch(const std::exception &e) {
std::cerr << "Error converting y coordinate: " << e.what() << "\n";
return;
}
// Subtract the thumb fast height from y
int adjustedY = yCoord - g_thumbFastHeight;
// Prepare command for thumbfast with adjusted y-coordinate
std::vector<std::string> cmdArgs = {
"script-message-to",
"thumbfast",
"thumb",
args[0], // hovered_seconds
args[1], // x
std::to_string(adjustedY) // y with offset
};
HandleMpvCommand(cmdArgs);
}
else if(ev == "seek-leave") {
if (g_thumbFastHeight == 0) return;
// Set ignore flag and calculate ignore-until timestamp
g_ignoreHover = true;
g_ignoreUntil = std::chrono::steady_clock::now() + IGNORE_DURATION;
std::vector<std::string> cmdArgs = {
"script-message-to",
"thumbfast",
"clear"
};
HandleMpvCommand(cmdArgs);
} else if(ev=="start-drag"){
ReleaseCapture();
SendMessageW(g_hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
} else if(ev=="refresh"){
refreshWeb(args.size()>0 && args[0]=="all");
} else if(ev=="app-error"){
if(!args.empty() && args.size()>0 && args[0] == "shellComm"){
if(!g_isAppReady && !g_waitStarted.exchange(true)){
WaitAndRefreshIfNeeded();
}
}
} else if (ev=="open-external") {
std::wstring uri(args[0].begin(), args[0].end());
ShellExecuteW(nullptr, L"open", uri.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
} else if (ev=="navigate") {
std::wstring uri(args[0].begin(), args[0].end());
if (args[0] == "home") {
g_webview->Navigate(g_webuiUrl.c_str());
} else {
g_webview->Navigate(uri.c_str());
}
} else if (ev == "activity") {
SetDiscordPresenceFromArgs(args);
} else {
std::cout<<"Unknown event="<<ev<<"\n";
}
}
void HandleInboundJSON(const std::string &msg)
{
try {
#ifdef DEBUG_LOG
std::cout << "[JS -> NATIVE]: " << msg << std::endl;
#endif
auto j = nlohmann::json::parse(msg);
int type = 0;
if (j.contains("type") && j["type"].is_number()) {
type = j["type"].get<int>();
}
if (type == 3) {
// 3 = Init event
nlohmann::json root;
root["id"] = 0;
nlohmann::json transportObj;
json extData = {};
if (!g_extensionMap.empty()) {
for (auto& [name, id] : g_extensionMap) {
extData[WStringToUtf8(name)] = WStringToUtf8(id);
}
}
transportObj["properties"] = {
1,
nlohmann::json::array({0, "shellVersion", 0, APP_VERSION}),
nlohmann::json::array({0, "BrowserExtensions", 0, extData}),
};
transportObj["signals"] = {
nlohmann::json::array({0, "handleInboundJSONSignal"}),
};
nlohmann::json methods = nlohmann::json::array();
methods.push_back(nlohmann::json::array({"onEvent", "handleInboundJSON"}));
transportObj["methods"] = methods;
root["data"]["transport"] = transportObj;
std::string payload = root.dump();
std::wstring wpayload(payload.begin(), payload.end());
g_webview->PostWebMessageAsString(wpayload.c_str());
return;
}
if (type == 6 && j.contains("method"))
{
std::string methodName = j["method"].get<std::string>();
if (methodName == "handleInboundJSON" || methodName == "onEvent")
{
if (j["args"].is_array() && !j["args"].empty())
{
std::string ev;
if (j["args"][0].is_string()) {
ev = j["args"][0].get<std::string>();
} else {
ev = "Unknown";
}
std::vector<std::string> argVec;
if (j["args"].size() > 1)
{
auto &second = j["args"][1];
if (second.is_array())
{
for (auto &x: second)
{
if (x.is_string()) argVec.push_back(x.get<std::string>());
else argVec.push_back(x.dump());
}
}
else if (second.is_string()) {
argVec.push_back(second.get<std::string>());
}
else {
argVec.push_back(second.dump());
}
}
HandleEvent(ev, argVec);
}
else {
std::cout << "[WARN] invokeMethod=handleInboundJSON => no args array?\n";
}
}
return;
}
std::cout<<"Unknown Inbound event="<<msg<<"\n";
} catch(std::exception &ex) {
std::cerr<<"JSON parse error:"<<ex.what()<<"\n";
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_CREATE:
{
HICON hIconBig = LoadIcon(g_hInst, MAKEINTRESOURCE(IDR_MAINFRAME));
HICON hIconSmall = LoadIcon(g_hInst, MAKEINTRESOURCE(IDR_MAINFRAME));
SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIconBig);
SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSmall);
CreateTrayIcon(hWnd);
UpdateTheme(hWnd);
break;
}
case WM_DPICHANGED:
{
RECT* const newRect = reinterpret_cast<RECT*>(lParam);
SetWindowPos(hWnd, NULL, newRect->left, newRect->top,
newRect->right - newRect->left,
newRect->bottom - newRect->top,
SWP_NOZORDER | SWP_NOACTIVATE);
break;
}
case WM_NOTIFY_FLUSH: {
if (g_isAppReady) {
for(const auto& pendingMsg : g_outboundMessages) {
SendToJS(pendingMsg["type"], pendingMsg);
}
g_outboundMessages.clear();
if(!g_launchProtocol.empty()) {
COPYDATASTRUCT cds;
cds.dwData = 1;
cds.cbData = static_cast<DWORD>((g_launchProtocol.size()+1) * sizeof(wchar_t));
cds.lpData = (PVOID)g_launchProtocol.c_str();
SendMessage(g_hWnd, WM_COPYDATA, (WPARAM)g_hWnd, (LPARAM)&cds);
g_launchProtocol.clear();
}
}
break;
}
case WM_REACHABILITY_DONE: {
// wParam is a pointer to a std::wstring we allocated in the thread
std::wstring* pUrl = reinterpret_cast<std::wstring*>(wParam);
if(pUrl)
{
if (!pUrl->empty() && g_webview)
{
std::wcout << L"[WEBVIEW]: Navigating to " << *pUrl << std::endl;
g_webview->Navigate(pUrl->c_str());
}
else
{
MessageBoxW(nullptr,
L"All endpoints are unreachable",
L"WebView2 Initialization Error",
MB_ICONERROR | MB_OK);
}
delete pUrl;
}
break;
}
case WM_HOTKEY:
{
// PlayPause Hotkey
if (wParam == 1) {
std::vector<std::string> args = {"cycle", "pause"};
HandleMpvCommand(args);
}
break;
}
case WM_SETTINGCHANGE:
{
UpdateTheme(hWnd);
break;
}
case WM_TRAYICON:
{
if(LOWORD(lParam)==WM_RBUTTONUP) {
ShowTrayMenu(hWnd);
}
if(lParam==WM_LBUTTONDBLCLK){
ShowWindow(hWnd, SW_RESTORE);
SetForegroundWindow(hWnd);
}
break;
}
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case ID_TRAY_SHOWWINDOW:
g_showWindow = !g_showWindow;
ShowWindow(hWnd, g_showWindow?SW_SHOW:SW_HIDE);
break;
case ID_TRAY_ALWAYSONTOP:
g_alwaysOnTop=!g_alwaysOnTop;
SetWindowPos(hWnd,
g_alwaysOnTop?HWND_TOPMOST:HWND_NOTOPMOST,
0,0,0,0,
SWP_NOMOVE|SWP_NOSIZE);
break;
case ID_TRAY_CLOSE_ON_EXIT:
g_closeOnExit=!g_closeOnExit;
SaveSettings();
break;
case ID_TRAY_USE_DARK_THEME:
g_useDarkTheme=!g_useDarkTheme;
SaveSettings();
UpdateTheme(hWnd);
break;
case ID_TRAY_PICTURE_IN_PICTURE:
TogglePictureInPicture(hWnd, !g_isPipMode);
break;
case ID_TRAY_PAUSE_FOCUS_LOST:
g_pauseOnLostFocus=!g_pauseOnLostFocus;
SaveSettings();
break;
case ID_TRAY_PAUSE_MINIMIZED:
g_pauseOnMinimize=!g_pauseOnMinimize;
SaveSettings();
break;
case ID_TRAY_QUIT:
if(g_mpv) mpv_command_string(g_mpv,"quit");
WINDOWPLACEMENT wp;
wp.length = sizeof(wp);
if (GetWindowPlacement(hWnd, &wp)) {
SaveWindowPlacement(wp);
}
DestroyWindow(hWnd);
break;
}
break;
}
case WM_COPYDATA:
{
PCOPYDATASTRUCT pcds = (PCOPYDATASTRUCT)lParam;
if (pcds && pcds->dwData == 1 && pcds->lpData) {
// Assuming data is a wide string containing the URL or file path
std::wstring receivedUrl((wchar_t*)pcds->lpData, pcds->cbData / sizeof(wchar_t));
std::wcout << L"Received URL in main instance: " << receivedUrl << std::endl;
// Check if received URL is a file and exists
if (FileExists(receivedUrl)) {
// Extract file extension
size_t dotPos = receivedUrl.find_last_of(L".");
std::wstring extension = (dotPos != std::wstring::npos) ? receivedUrl.substr(dotPos) : L"";
if (extension == L".torrent") {
// Handle .torrent files
std::string utf8FilePath = WStringToUtf8(receivedUrl);
std::ifstream ifs(utf8FilePath, std::ios::binary);
if (!ifs) {
std::cerr << "Error: Could not open torrent file.\n";
break;
}
std::vector<unsigned char> fileBuffer(
(std::istreambuf_iterator<char>(ifs)),
(std::istreambuf_iterator<char>())
);
json j;
j["type"] = "OpenTorrent";
j["data"] = fileBuffer;
SendToJS("OpenTorrent", j);
} else {
// Handle other media files
std::string utf8FilePath = WStringToUtf8(receivedUrl);
json j;
j["type"] = "OpenFile";
j["path"] = utf8FilePath;
SendToJS("OpenFile", j);
}
} else if (receivedUrl.rfind(L"stremio://detail", 0) == 0) {
std::string utf8Url = WStringToUtf8(receivedUrl);
json j;
j["type"] = "ReplaceLocation";
j["path"] = utf8Url;
SendToJS("ReplaceLocation", j);
} else if (receivedUrl.rfind(L"stremio://", 0) == 0) {
// Handle stremio:// protocol
std::string utf8Url = WStringToUtf8(receivedUrl);
json j;
j["type"] = "AddonInstall";
j["path"] = utf8Url;
SendToJS("AddonInstall", j);
} else if (receivedUrl.rfind(L"magnet:", 0) == 0) {
std::string utf8Url = WStringToUtf8(receivedUrl);
json j;
j["type"] = "OpenTorrent";
j["magnet"] = utf8Url;
SendToJS("OpenTorrent", j);
} else {
std::wcout << L"Received URL is neither a valid file nor a stremio:// protocol." << std::endl;
}
}
return 0;
}
case WM_CLOSE:
{
WINDOWPLACEMENT wp;
wp.length = sizeof(wp);
if (GetWindowPlacement(hWnd, &wp)) {
// Save to ini
SaveWindowPlacement(wp);
}
if(g_closeOnExit) {
DestroyWindow(hWnd);
} else {
ShowWindow(hWnd, SW_HIDE);
pauseMPV(g_pauseOnMinimize);
g_showWindow=false;
}
return 0;
}
case WM_ACTIVATE:
{
if(LOWORD(wParam)==WA_INACTIVE){
pauseMPV(g_pauseOnLostFocus);
}
if (LOWORD(wParam) != WA_INACTIVE)
{
SetFocus(hWnd);
if (g_webview && g_webviewController) {
g_webviewController->MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC);
}
}
break;
}
case WM_SIZE:
{
if(wParam==SIZE_MINIMIZED){
pauseMPV(g_pauseOnMinimize);
}
if(g_webviewController){
RECT rc; GetClientRect(hWnd,&rc);
g_webviewController->put_Bounds(rc);
}
if(g_hSplash){
int w = LOWORD(lParam);
int h = HIWORD(lParam);
SetWindowPos(g_hSplash,nullptr,0,0,w,h,SWP_NOZORDER);
}
break;
}
case WM_MPV_WAKEUP:
HandleMpvEvents();
break;
case WM_DESTROY:
{
// release mutex
if(g_hMutex) { CloseHandle(g_hMutex); g_hMutex=nullptr; }
PostQuitMessage(0);
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

22
src/ui/mainwindow.h Normal file
View file

@ -0,0 +1,22 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <string>
#include <windows.h>
#include "nlohmann/json.hpp"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
// Helper for single-instance
bool CheckSingleInstance(int argc, char* argv[], std::wstring &outProtocolArg);
bool FocusExistingInstance(const std::wstring& protocolArg);
// Our "ToggleFullScreen" logic
void ToggleFullScreen(HWND hWnd, bool enable);
// Webview
void HandleInboundJSON(const std::string &msg);
void SendToJS(const std::string &eventName, const nlohmann::json &eventData);
void HandleEvent(const std::string &ev, std::vector<std::string> &args);
#endif // MAINWINDOW_H

180
src/ui/splash.cpp Normal file
View file

@ -0,0 +1,180 @@
#include "splash.h"
#include <gdiplus.h>
#include <iostream>
#include "../core/globals.h"
#include "../utils/crashlog.h"
#include "../resource.h"
LRESULT CALLBACK SplashWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_TIMER:
{
const float baseStep = 0.01f;
const float splashSpeed = 1.1f;
float actualStep = baseStep * splashSpeed;
g_splashOpacity += actualStep * g_pulseDirection;
if(g_splashOpacity <= 0.3f) {
g_splashOpacity = 0.3f;
g_pulseDirection = 1;
} else if(g_splashOpacity >= 1.0f) {
g_splashOpacity = 1.0f;
g_pulseDirection = -1;
}
InvalidateRect(hWnd, nullptr, FALSE);
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
RECT rc; GetClientRect(hWnd, &rc);
int winW = rc.right - rc.left;
int winH = rc.bottom - rc.top;
HDC memDC = CreateCompatibleDC(hdc);
HBITMAP memBmp = CreateCompatibleBitmap(hdc, winW, winH);
HGDIOBJ oldMemBmp = SelectObject(memDC, memBmp);
HBRUSH bgBrush = CreateSolidBrush(RGB(12, 11, 17));
FillRect(memDC, &rc, bgBrush);
DeleteObject(bgBrush);
if(g_hSplashImage)
{
BITMAP bm;
GetObject(g_hSplashImage, sizeof(bm), &bm);
int imgWidth = bm.bmWidth;
int imgHeight= bm.bmHeight;
int destX = (winW - imgWidth)/2;
int destY = (winH - imgHeight)/2;
HDC imgDC = CreateCompatibleDC(memDC);
HGDIOBJ oldImgBmp = SelectObject(imgDC, g_hSplashImage);
BLENDFUNCTION blend = {};
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = (BYTE)(g_splashOpacity * 255);
blend.AlphaFormat = AC_SRC_ALPHA;
HBITMAP tempBmp = CreateCompatibleBitmap(memDC, imgWidth, imgHeight);
HDC tempDC = CreateCompatibleDC(memDC);
HGDIOBJ oldTempBmp = SelectObject(tempDC, tempBmp);
BitBlt(tempDC, 0, 0, imgWidth, imgHeight, imgDC, 0, 0, SRCCOPY);
AlphaBlend(memDC, destX, destY, imgWidth, imgHeight, tempDC, 0, 0, imgWidth, imgHeight, blend);
SelectObject(tempDC, oldTempBmp);
DeleteObject(tempBmp);
DeleteDC(tempDC);
SelectObject(imgDC, oldImgBmp);
DeleteDC(imgDC);
}
BitBlt(hdc, 0,0, winW, winH, memDC, 0,0, SRCCOPY);
SelectObject(memDC, oldMemBmp);
DeleteObject(memBmp);
DeleteDC(memDC);
EndPaint(hWnd, &ps);
break;
}
case WM_DESTROY:
KillTimer(hWnd, 1);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
void CreateSplashScreen(HWND parent)
{
WNDCLASSEXW splashWcex = {0};
splashWcex.cbSize = sizeof(WNDCLASSEXW);
splashWcex.lpfnWndProc = SplashWndProc;
splashWcex.hInstance = g_hInst;
splashWcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
splashWcex.lpszClassName = L"SplashScreenClass";
RegisterClassExW(&splashWcex);
RECT rcClient;
GetClientRect(parent, &rcClient);
int width = rcClient.right - rcClient.left;
int height = rcClient.bottom - rcClient.top;
g_hSplash = CreateWindowExW(
0,
L"SplashScreenClass",
nullptr,
WS_CHILD | WS_VISIBLE,
0, 0, width, height,
parent,
nullptr,
g_hInst,
nullptr
);
if(!g_hSplash) {
DWORD errorCode = GetLastError();
std::string errorMessage = "[SPLASH]: Failed to create splash. Error=" + std::to_string(errorCode);
std::cerr << errorMessage << "\n";
AppendToCrashLog(errorMessage);
return;
}
HRSRC hRes = FindResource(g_hInst, MAKEINTRESOURCE(IDR_SPLASH_PNG), RT_RCDATA);
if(!hRes) {
std::cerr << "Could not find PNG resource.\n";
} else {
HGLOBAL hData = LoadResource(g_hInst, hRes);
DWORD size = SizeofResource(g_hInst, hRes);
void* pData = LockResource(hData);
if(!pData) {
std::cerr << "LockResource returned null.\n";
} else {
IStream* pStream = nullptr;
if(CreateStreamOnHGlobal(nullptr, TRUE, &pStream) == S_OK)
{
ULONG written = 0;
pStream->Write(pData, size, &written);
LARGE_INTEGER liZero = {};
pStream->Seek(liZero, STREAM_SEEK_SET, nullptr);
Gdiplus::Bitmap bitmap(pStream);
if(bitmap.GetLastStatus()==Gdiplus::Ok)
{
HBITMAP hBmp = NULL;
if(bitmap.GetHBITMAP(Gdiplus::Color(0,0,0,0), &hBmp) == Gdiplus::Ok) {
g_hSplashImage = hBmp;
} else {
std::cerr << "Failed to create HBITMAP from embedded PNG.\n";
}
} else {
std::cerr << "Failed to decode embedded PNG data.\n";
}
pStream->Release();
}
}
}
SetTimer(g_hSplash, 1, 4, nullptr);
SetWindowPos(g_hSplash, HWND_TOP, 0, 0, width, height, SWP_SHOWWINDOW);
InvalidateRect(g_hSplash, nullptr, TRUE);
}
void HideSplash()
{
if(g_hSplash) {
KillTimer(g_hSplash, 1);
DestroyWindow(g_hSplash);
g_hSplash = nullptr;
}
if(g_hSplashImage) {
DeleteObject(g_hSplashImage);
g_hSplashImage = nullptr;
}
}

11
src/ui/splash.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef SPLASH_H
#define SPLASH_H
#include <windows.h>
void CreateSplashScreen(HWND parent);
void HideSplash();
LRESULT CALLBACK SplashWndProc(HWND, UINT, WPARAM, LPARAM);
#endif // SPLASH_H

294
src/updater/updater.cpp Normal file
View file

@ -0,0 +1,294 @@
#include "updater.h"
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/sha.h>
#include <curl/curl.h>
#include "../core/globals.h"
#include "../utils/crashlog.h"
#include "../utils/helpers.h"
#include "../node/server.h"
#include <fstream>
#include <sstream>
#include <iomanip>
#include <iostream>
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
std::string* s = reinterpret_cast<std::string*>(userp);
s->append(reinterpret_cast<char*>(contents), size * nmemb);
return size * nmemb;
}
// Download to string
static bool DownloadString(const std::string& url, std::string& outData)
{
CURL* curl = curl_easy_init();
if(!curl) return false;
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outData);
CURLcode res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return res == CURLE_OK;
}
// Download to file
static bool DownloadFile(const std::string& url, const std::filesystem::path& dest)
{
CURL* curl = curl_easy_init();
if(!curl) return false;
FILE* fp = _wfopen(dest.c_str(), L"wb");
if(!fp){
curl_easy_cleanup(curl);
return false;
}
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
CURLcode res = curl_easy_perform(curl);
fclose(fp);
curl_easy_cleanup(curl);
return (res == CURLE_OK);
}
// Compute sha256
static std::string FileChecksum(const std::filesystem::path& filepath)
{
std::ifstream file(filepath, std::ios::binary);
if(!file) return "";
SHA256_CTX ctx;
SHA256_Init(&ctx);
char buf[4096];
while(file.read(buf, sizeof(buf))) {
SHA256_Update(&ctx, buf, file.gcount());
}
if(file.gcount()>0) {
SHA256_Update(&ctx, buf, file.gcount());
}
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_Final(hash, &ctx);
std::ostringstream oss;
for(int i=0; i<SHA256_DIGEST_LENGTH; ++i)
oss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
return oss.str();
}
static bool VerifySignature(const std::string& data, const std::string& signatureBase64)
{
// Load public key from embedded PEM
BIO* bio = BIO_new_mem_buf(public_key_pem, -1);
EVP_PKEY* pubKey = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr);
BIO_free(bio);
if(!pubKey) return false;
// remove whitespace
std::string cleanedSig;
for(char c : signatureBase64){
if(!isspace((unsigned char)c)) {
cleanedSig.push_back(c);
}
}
// base64 decode
BIO* b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
BIO* bmem = BIO_new_mem_buf(cleanedSig.data(), (int)cleanedSig.size());
bmem = BIO_push(b64, bmem);
std::vector<unsigned char> signature(512);
int sig_len = BIO_read(bmem, signature.data(), (int)signature.size());
BIO_free_all(bmem);
if(sig_len <= 0) {
EVP_PKEY_free(pubKey);
return false;
}
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
EVP_PKEY_CTX* pctx = nullptr;
bool result = false;
if(EVP_DigestVerifyInit(ctx, &pctx, EVP_sha256(), NULL, pubKey)==1){
if(EVP_DigestVerifyUpdate(ctx, data.data(), data.size())==1){
result = (EVP_DigestVerifyFinal(ctx, signature.data(), sig_len)==1);
}
}
EVP_MD_CTX_free(ctx);
EVP_PKEY_free(pubKey);
return result;
}
void RunAutoUpdaterOnce()
{
g_updaterRunning = true;
std::cout<<"Checking for Updates.\n";
std::string versionContent;
if(!DownloadString(g_updateUrl, versionContent)) {
AppendToCrashLog("[UPDATER]: Failed to download version.json");
return;
}
nlohmann::json versionJson;
try {
versionJson = nlohmann::json::parse(versionContent);
} catch(...) { return; }
std::string versionDescUrl = versionJson["versionDesc"].get<std::string>();
std::string signatureBase64 = versionJson["signature"].get<std::string>();
// get version-details
std::string detailsContent;
if(!DownloadString(versionDescUrl, detailsContent)) {
AppendToCrashLog("[UPDATER]: Failed to download version details");
return;
}
if(!VerifySignature(detailsContent, signatureBase64)) {
AppendToCrashLog("[UPDATER]: Signature verification failed");
return;
}
nlohmann::json detailsJson;
try {
detailsJson = nlohmann::json::parse(detailsContent);
} catch(...) { return; }
// Compare shellVersion
std::string remoteShellVersion = detailsJson["shellVersion"].get<std::string>();
bool needsFullUpdate = (remoteShellVersion != APP_VERSION);
auto files = detailsJson["files"];
std::vector<std::string> partialUpdateKeys = { "server.js" };
// prepare temp dir
wchar_t buf[MAX_PATH];
GetTempPathW(MAX_PATH, buf);
std::filesystem::path tempDir = std::filesystem::path(buf) / L"stremio_updater";
std::filesystem::create_directories(tempDir);
// handle full update
if(needsFullUpdate || g_autoupdaterForceFull) {
bool allDownloadsSuccessful = true;
// check architecture
std::string key = "windows";
SYSTEM_INFO systemInfo;
GetNativeSystemInfo(&systemInfo);
if(systemInfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64){
key = "windows-x64";
} else if(systemInfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL) {
key = "windows-x86";
}
if(files.contains(key) && files[key].contains("url") && files[key].contains("checksum")) {
std::string url = files[key]["url"].get<std::string>();
std::string expectedChecksum = files[key]["checksum"].get<std::string>();
std::string filename = url.substr(url.find_last_of('/') + 1);
std::filesystem::path installerPath = tempDir / std::wstring(filename.begin(), filename.end());
// Cleanup: Delete all files in tempDir except the current installer
for (const auto& entry : std::filesystem::directory_iterator(tempDir)) {
if (entry.path() != installerPath) {
try {
std::filesystem::remove_all(entry.path());
} catch (const std::exception& e) {
AppendToCrashLog("[UPDATER]: Cleanup failed for " + entry.path().string() + ": " + e.what());
}
}
}
if(std::filesystem::exists(installerPath)) {
if(FileChecksum(installerPath) != expectedChecksum) {
std::filesystem::remove(installerPath);
if(!DownloadFile(url, installerPath)) {
AppendToCrashLog("[UPDATER]: Failed to re-download installer");
allDownloadsSuccessful = false;
}
}
} else {
if(!DownloadFile(url, installerPath)) {
AppendToCrashLog("[UPDATER]: Failed to download installer");
allDownloadsSuccessful = false;
}
}
if(FileChecksum(installerPath) != expectedChecksum) {
AppendToCrashLog("[UPDATER]: Installer file corrupted: " + installerPath.string());
allDownloadsSuccessful = false;
}
if(allDownloadsSuccessful) {
g_installerPath = installerPath;
}
} else {
allDownloadsSuccessful = false;
}
if(allDownloadsSuccessful) {
std::cout<<"Full update needed!\n";
nlohmann::json j;
j["type"] = "requestUpdate";
g_outboundMessages.push_back(j);
PostMessage(g_hWnd, WM_NOTIFY_FLUSH, 0, 0);
} else {
std::cout<<"Installer download failed. Skipping update prompt.\n";
}
}
// partial update
if(!needsFullUpdate) {
std::wstring exeDir;
{
wchar_t pathBuf[MAX_PATH];
GetModuleFileNameW(nullptr, pathBuf, MAX_PATH);
exeDir = pathBuf;
size_t pos = exeDir.find_last_of(L"\\/");
if(pos!=std::wstring::npos) exeDir.erase(pos);
}
for(const auto& key : partialUpdateKeys) {
if(files.contains(key) && files[key].contains("url") && files[key].contains("checksum")) {
std::string url = files[key]["url"].get<std::string>();
std::string expectedChecksum = files[key]["checksum"].get<std::string>();
std::filesystem::path localFilePath = std::filesystem::path(exeDir) / std::wstring(key.begin(), key.end());
if(std::filesystem::exists(localFilePath)) {
if(FileChecksum(localFilePath) == expectedChecksum) {
continue; // no update needed
}
}
if(!DownloadFile(url, localFilePath)) {
AppendToCrashLog("[UPDATER]: Failed to download partial file " + key);
} else {
if(FileChecksum(localFilePath) != expectedChecksum) {
AppendToCrashLog("[UPDATER]: Downloaded file corrupted " + localFilePath.string());
continue;
}
if(key=="server.js") {
StopNodeServer();
StartNodeServer();
}
}
}
}
}
std::cout<<"[UPDATER]: Update check done!\n";
}
void RunInstallerAndExit()
{
if(g_installerPath.empty()) {
AppendToCrashLog("[UPDATER]: Installer path not set.");
return;
}
// pass /overrideInstallDir
wchar_t exeDir[MAX_PATH];
GetModuleFileNameW(nullptr, exeDir, MAX_PATH);
std::wstring dir(exeDir);
size_t pos = dir.find_last_of(L"\\/");
if(pos!=std::wstring::npos) {
dir.erase(pos);
}
std::wstring arguments = L"/overrideInstallDir=\"" + dir + L"\"";
HINSTANCE result = ShellExecuteW(nullptr, L"open", g_installerPath.c_str(), arguments.c_str(), nullptr, SW_HIDE);
if ((INT_PTR)result <= 32) {
AppendToCrashLog(L"[UPDATER]: Failed to start installer via ShellExecute.");
}
PostQuitMessage(0);
exit(0);
}

7
src/updater/updater.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef UPDATER_H
#define UPDATER_H
void RunAutoUpdaterOnce();
void RunInstallerAndExit();
#endif // UPDATER_H

165
src/utils/config.cpp Normal file
View file

@ -0,0 +1,165 @@
#include <windows.h>
#include <string>
#include "config.h"
#include <sstream>
#include "../core/globals.h"
#include "../utils/helpers.h"
// Return the path to "portable_config/stremio-settings.ini"
static std::wstring GetIniPath()
{
std::wstring exeDir = GetExeDirectory();
std::wstring pcDir = exeDir + L"\\portable_config";
CreateDirectoryW(pcDir.c_str(), nullptr); // ensure it exists
return pcDir + L"\\stremio-settings.ini";
}
void LoadSettings()
{
std::wstring iniPath = GetIniPath();
wchar_t buffer[16];
GetPrivateProfileStringW(L"General", L"CloseOnExit", L"0", buffer, _countof(buffer), iniPath.c_str());
g_closeOnExit = (wcscmp(buffer, L"1") == 0);
GetPrivateProfileStringW(L"General", L"UseDarkTheme", L"1", buffer, _countof(buffer), iniPath.c_str());
g_useDarkTheme = (wcscmp(buffer, L"1") == 0);
g_thumbFastHeight = GetPrivateProfileIntW(L"General", L"ThumbFastHeight", 0, iniPath.c_str());
g_allowZoom = GetPrivateProfileIntW(L"General", L"AllowZoom", 0, iniPath.c_str());
g_pauseOnMinimize = (GetPrivateProfileIntW(L"General", L"PauseOnMinimize", 1, iniPath.c_str()) == 1);
g_pauseOnLostFocus = (GetPrivateProfileIntW(L"General", L"PauseOnLostFocus", 0, iniPath.c_str()) == 1);
g_isRpcOn = (GetPrivateProfileIntW(L"General", L"DiscordRPC", 1, iniPath.c_str()) == 1);
//Mpv
wchar_t voBuffer[32];
GetPrivateProfileStringW(L"MPV", L"VideoOutput", L"gpu-next", voBuffer, 32, iniPath.c_str());
char narrowVO[32];
WideCharToMultiByte(CP_UTF8, 0, voBuffer, -1, narrowVO, 32, NULL, NULL);
g_initialVO = narrowVO;
g_currentVolume = GetPrivateProfileIntW(L"MPV", L"InitialVolume", 50, iniPath.c_str());
}
void SaveSettings()
{
std::wstring iniPath = GetIniPath();
const wchar_t* closeVal = g_closeOnExit ? L"1" : L"0";
const wchar_t* darkVal = g_useDarkTheme ? L"1" : L"0";
const wchar_t* pauseMinVal = g_pauseOnMinimize ? L"1" : L"0";
const wchar_t* pauseFocVal = g_pauseOnLostFocus ? L"1" : L"0";
const wchar_t* allowZoomVal = g_allowZoom ? L"1" : L"0";
const wchar_t* rpcVal = g_isRpcOn ? L"1" : L"0";
WritePrivateProfileStringW(L"General", L"CloseOnExit", closeVal, iniPath.c_str());
WritePrivateProfileStringW(L"General", L"UseDarkTheme", darkVal, iniPath.c_str());
WritePrivateProfileStringW(L"General", L"PauseOnMinimize", pauseMinVal, iniPath.c_str());
WritePrivateProfileStringW(L"General", L"PauseOnLostFocus", pauseFocVal, iniPath.c_str());
WritePrivateProfileStringW(L"General", L"AllowZoom", allowZoomVal, iniPath.c_str());
WritePrivateProfileStringW(L"General", L"DiscordRPC", rpcVal, iniPath.c_str());
WriteIntToIni(L"MPV", L"InitialVolume", g_currentVolume, iniPath);
}
static void WriteIntToIni(const std::wstring &section, const std::wstring &key, int value, const std::wstring &iniPath)
{
std::wstringstream ws;
ws << value;
WritePrivateProfileStringW(section.c_str(), key.c_str(), ws.str().c_str(), iniPath.c_str());
}
// This helper reads an integer from the .ini, returning `defaultVal` if not found
static int ReadIntFromIni(const std::wstring &section, const std::wstring &key, int defaultVal, const std::wstring &iniPath)
{
return GetPrivateProfileIntW(section.c_str(), key.c_str(), defaultVal, iniPath.c_str());
}
/**
* Optional helper:
* Check if the given rectangle is on a valid monitor.
* If completely off-screen, we re-center it on the primary monitor so the user sees it.
*/
static void EnsureRectOnScreen(RECT &rc)
{
HMONITOR hMon = MonitorFromRect(&rc, MONITOR_DEFAULTTONULL);
if(hMon)
{
return;
}
MONITORINFO mi = {0};
mi.cbSize = sizeof(mi);
HMONITOR hPrimary = MonitorFromPoint({0,0}, MONITOR_DEFAULTTOPRIMARY);
if(!hPrimary || !GetMonitorInfoW(hPrimary, &mi)) {
return;
}
int width = rc.right - rc.left;
int height = rc.bottom - rc.top;
int workWidth = mi.rcWork.right - mi.rcWork.left;
int workHeight = mi.rcWork.bottom - mi.rcWork.top;
// Center the rect in the primary monitor's WORK area
int newLeft = mi.rcWork.left + (workWidth - width)/2;
int newTop = mi.rcWork.top + (workHeight - height)/2;
rc.left = newLeft;
rc.top = newTop;
rc.right = newLeft + width;
rc.bottom = newTop + height;
}
/**
* SaveWindowPlacement:
* Writes showCmd (normal vs. maximized) and the normal window rectangle
* into the [Window] section of our .ini.
*/
void SaveWindowPlacement(const WINDOWPLACEMENT &wp)
{
std::wstring iniPath = GetIniPath();
WriteIntToIni(L"Window", L"ShowCmd", (int)wp.showCmd, iniPath);
WriteIntToIni(L"Window", L"Left", wp.rcNormalPosition.left, iniPath);
WriteIntToIni(L"Window", L"Top", wp.rcNormalPosition.top, iniPath);
WriteIntToIni(L"Window", L"Right", wp.rcNormalPosition.right, iniPath);
WriteIntToIni(L"Window", L"Bottom", wp.rcNormalPosition.bottom, iniPath);
}
/**
* LoadWindowPlacement:
* Reads ShowCmd + window rectangle from [Window].
* If not found or incomplete, returns false => use default behavior.
* If found, also ensures the rect is at least partially visible on a monitor.
*/
bool LoadWindowPlacement(WINDOWPLACEMENT &wp)
{
wp.length = sizeof(wp);
wp.flags = 0;
std::wstring iniPath = GetIniPath();
// We default to SW_SHOWNORMAL if not found
int showCmd = ReadIntFromIni(L"Window", L"ShowCmd", SW_SHOWNORMAL, iniPath);
wp.showCmd = (UINT)showCmd;
// If any of these are -1 => means not found
int left = ReadIntFromIni(L"Window", L"Left", -1, iniPath);
int top = ReadIntFromIni(L"Window", L"Top", -1, iniPath);
int right = ReadIntFromIni(L"Window", L"Right", -1, iniPath);
int bottom = ReadIntFromIni(L"Window", L"Bottom", -1, iniPath);
if(left == -1 || top == -1 || right == -1 || bottom == -1)
{
// No saved geometry
return false;
}
wp.rcNormalPosition.left = left;
wp.rcNormalPosition.top = top;
wp.rcNormalPosition.right = right;
wp.rcNormalPosition.bottom = bottom;
// Edge-case: if user had it on a disconnected monitor => re-center
EnsureRectOnScreen(wp.rcNormalPosition);
return true;
}

9
src/utils/config.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef CONFIG_H
#define CONFIG_H
void LoadSettings();
void SaveSettings();
void SaveWindowPlacement(const WINDOWPLACEMENT &wp);
bool LoadWindowPlacement(WINDOWPLACEMENT &wp);
static void WriteIntToIni(const std::wstring &section, const std::wstring &key, int value, const std::wstring &iniPath);
#endif // CONFIG_H

72
src/utils/crashlog.cpp Normal file
View file

@ -0,0 +1,72 @@
#include "crashlog.h"
#include <fstream>
#include <iomanip>
#include <ctime>
#include "../core/globals.h"
#include "../mpv/player.h"
#include "../node/server.h"
#include "../tray/tray.h"
#include "../utils/helpers.h"
#include <gdiplus.h>
#include <sstream>
#include "discord_rpc.h"
#include "config.h"
static std::wstring GetDailyCrashLogPath()
{
std::time_t t = std::time(nullptr);
std::tm localTime;
localtime_s(&localTime, &t);
std::wstringstream filename;
filename << L"\\errors-"
<< localTime.tm_mday << L"."
<< (localTime.tm_mon + 1) << L"."
<< (localTime.tm_year + 1900) << L".txt";
std::wstring exeDir = GetExeDirectory();
std::wstring pcDir = exeDir + L"\\portable_config";
return pcDir + filename.str();
}
void AppendToCrashLog(const std::wstring& message)
{
std::wofstream logFile;
logFile.open(GetDailyCrashLogPath(), std::ios::app);
if(!logFile.is_open()) {
return;
}
std::time_t t = std::time(nullptr);
std::tm localTime;
localtime_s(&localTime, &t);
logFile << L"[" << std::put_time(&localTime, L"%H:%M:%S") << L"] "
<< message << std::endl;
}
void AppendToCrashLog(const std::string& message)
{
std::wstring wmsg(message.begin(), message.end());
AppendToCrashLog(wmsg);
}
void Cleanup()
{
//Save Settings
SaveSettings();
// Shut down mpv
CleanupMPV();
// Shut down Node
StopNodeServer();
// Remove tray icon
RemoveTrayIcon();
// GDI+ cleanup
if(g_gdiplusToken) {
Gdiplus::GdiplusShutdown(g_gdiplusToken);
}
Discord_Shutdown();
UnregisterHotKey(g_hWnd, 1);
}

10
src/utils/crashlog.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef CRASHLOG_H
#define CRASHLOG_H
#include <string>
void AppendToCrashLog(const std::wstring& message);
void AppendToCrashLog(const std::string& message);
void Cleanup();
#endif // CRASHLOG_H

166
src/utils/discord.cpp Normal file
View file

@ -0,0 +1,166 @@
#include <iostream>
#include "../core/globals.h"
#include "crashlog.h"
#include "discord_rpc.h"
void Discord_Ready(const DiscordUser* user) {
std::cout << "[DISCORD]: Connected to Discord user: " + std::string(user->username);
}
void Discord_Disconnected(int errorCode, const char* message) {
std::cout << "[DISCORD]: Disconnected (" + std::to_string(errorCode) + "): " + std::string(message);
}
void Discord_Error(int errorCode, const char* message) {
std::cout << "[DISCORD]: Error (" + std::to_string(errorCode) + "): " + std::string(message);
AppendToCrashLog("[DISCORD]: Error (" + std::to_string(errorCode) + "): " + std::string(message));
}
void InitializeDiscord()
{
DiscordEventHandlers handlers{};
memset(&handlers, 0, sizeof(handlers));
handlers.ready = Discord_Ready;
handlers.disconnected = Discord_Disconnected;
handlers.errored = Discord_Error;
Discord_Initialize("1361448446862692492", &handlers, 1, nullptr);
}
// Encapsulated presence setters
static void SetDiscordWatchingPresence(
const std::vector<std::string>& args
) {
// expects:
// 0: generic "watching" identifier
// 1: type (movie, series)
// 2: title
// 3: season
// 4: episode
// 5: episode name
// 6: episode thumbnail (small image) (Optional)
// 7: show/movie image (large image)
// 8: elapsed seconds
// 9: duration seconds
// 10: isPaused ("yes" or "no") (Optional)
// 11: more detail button link (imdb link) (Optional)
// 12: watch on stremio button link (stremio link) (Optional)
DiscordRichPresence discordPresence{};
memset(&discordPresence, 0, sizeof(discordPresence));
discordPresence.type = DISCORD_ACTIVITY_TYPE_WATCHING;
// Common fields (required)
discordPresence.details = args[2].c_str(); // Title
discordPresence.largeImageKey = args[7].c_str();
discordPresence.largeImageText = args[2].c_str();
// Handle paused state (optional)
bool isPaused = (!args[10].empty() && args[10] == "yes");
if (isPaused) {
discordPresence.state = "Paused";
discordPresence.startTimestamp = 0;
discordPresence.endTimestamp = 0;
} else {
std::time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
int elapsedSeconds = std::stoi(args[8]);
int durationSeconds = std::stoi(args[9]);
discordPresence.startTimestamp = currentTime - elapsedSeconds;
discordPresence.endTimestamp = currentTime + (durationSeconds - elapsedSeconds);
if (args[1] == "series") {
// Series-specific fields
std::string state = args[5] + " (S" + args[3] + "-E" + args[4] + ")";
discordPresence.state = state.c_str();
if (!args[6].empty()) {
discordPresence.smallImageKey = args[6].c_str();
discordPresence.smallImageText = args[5].c_str();
}
} else {
discordPresence.state = "Enjoying a Movie";
}
}
// Buttons setup (optional)
if (!args[11].empty()) {
discordPresence.button1Label = "More Details";
discordPresence.button1Url = args[11].c_str();
}
if (!args[12].empty()) {
discordPresence.button2Label = "Watch on Stremio";
discordPresence.button2Url = args[12].c_str();
}
Discord_UpdatePresence(&discordPresence);
}
static void SetDiscordMetaDetailPresence(const std::vector<std::string>& args) {
// args structure:
// 0: embed type ("meta-detail")
// 1: type ("movie" or "series")
// 2: title
// 3: image URL
DiscordRichPresence discordPresence{};
memset(&discordPresence, 0, sizeof(discordPresence));
discordPresence.type = DISCORD_ACTIVITY_TYPE_WATCHING;
discordPresence.details = args[2].c_str(); // Title (show/movie)
discordPresence.largeImageKey = args[3].c_str();
discordPresence.largeImageText = args[2].c_str();
// Engaging state
discordPresence.state = args[1] == "movie"
? "Exploring a Movie"
: "Exploring a Series";
Discord_UpdatePresence(&discordPresence);
}
static void SetDiscordDiscoverPresence(const char *const details, const char *const state) {
std::cout << "[DISCORD]: Setting discover Presence";
DiscordRichPresence discordPresence{};
memset(&discordPresence, 0, sizeof(discordPresence));
discordPresence.type = DISCORD_ACTIVITY_TYPE_WATCHING;
discordPresence.state = state;
discordPresence.details = details;
discordPresence.largeImageKey = "https://raw.githubusercontent.com/Stremio/stremio-web/refs/heads/development/images/icon.png";
discordPresence.largeImageText = "Stremio";
Discord_UpdatePresence(&discordPresence);
}
void SetDiscordPresenceFromArgs(const std::vector<std::string>& args) {
if (!g_isRpcOn || args.empty()) {
return;
}
const std::string& embedType = args[0];
if (embedType == "watching" && args.size() >= 12) {
SetDiscordWatchingPresence(args);
} else if (embedType == "meta-detail" && args.size() >= 4) {
SetDiscordMetaDetailPresence(args);
} else if (embedType == "board") {
SetDiscordDiscoverPresence("Resuming Favorites", "On Board");
} else if (embedType == "discover") {
SetDiscordDiscoverPresence("Finding New Gems", "In Discover");
} else if (embedType == "library") {
SetDiscordDiscoverPresence("Revisiting Old Favorites", "In Library");
} else if (embedType == "calendar") {
SetDiscordDiscoverPresence("Planning My Next Binge", "On Calendar");
} else if (embedType == "addons") {
SetDiscordDiscoverPresence("Exploring Add-ons", "In Add-ons");
} else if (embedType == "settings") {
SetDiscordDiscoverPresence("Tuning Preferences", "In Settings");
} else if (embedType == "search") {
SetDiscordDiscoverPresence("Searching for Shows & Movies", "In Search");
} else if (embedType == "clear") {
Discord_ClearPresence();
}
// Add more presence types here...
}

7
src/utils/discord.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef STREMIO_DISCORD_H
#define STREMIO_DISCORD_H
void InitializeDiscord();
void SetDiscordPresenceFromArgs(const std::vector<std::string>& args);
#endif

68
src/utils/extensions.cpp Normal file
View file

@ -0,0 +1,68 @@
#include "extensions.h"
#include <iostream>
#include <string>
#include "../core/globals.h"
bool HandleExtensions(const std::wstring& finalUri) {
bool handledPremid = HandlePremidLogin(finalUri);
bool handledStylus = HandleStylusUsoInstall(finalUri);
return handledPremid || handledStylus;
}
bool HandlePremidLogin(const std::wstring& finalUri) {
if (finalUri.rfind(L"https://login.premid.app", 0) == 0 && finalUri.rfind(L"https://discord.com", 0) != 0) {
std::wstring extensionId;
auto it = std::find_if(g_extensionMap.begin(), g_extensionMap.end(),
[](const std::pair<std::wstring, std::wstring>& p) -> bool {
return p.first.find(L"premid") != std::wstring::npos;
});
if (it != g_extensionMap.end()) {
extensionId = it->second;
} else {
std::wcout << L"[EXTENSIONS]: Extension id not found\n";
g_webview->Navigate(g_webuiUrl.c_str());
return true;
}
std::wstring codeParam;
size_t codePos = finalUri.find(L"code=");
if (codePos != std::wstring::npos) {
codePos += 5; // Move past "code="
size_t ampPos = finalUri.find(L'&', codePos);
if (ampPos == std::wstring::npos) {
codeParam = finalUri.substr(codePos);
} else {
codeParam = finalUri.substr(codePos, ampPos - codePos);
}
}
std::wstring script = L"globalThis.getAuthorizationCode(\"" + codeParam + L"\");";
g_scriptQueue.push_back(script);
std::wstring uri = L"chrome-extension://" + extensionId + L"/popup.html";
g_webview->Navigate(uri.c_str());
return true;
}
return false;
}
bool HandleStylusUsoInstall(const std::wstring& finalUri) {
if (finalUri.rfind(L"https://raw.githubusercontent.com/uso-archive", 0) == 0) {
std::wstring extensionId;
auto it = std::find_if(g_extensionMap.begin(), g_extensionMap.end(),
[](const std::pair<std::wstring, std::wstring>& p) -> bool {
return p.first.find(L"stylus") != std::wstring::npos;
});
if (it != g_extensionMap.end()) {
extensionId = it->second;
} else {
std::wcout << L"[EXTENSIONS]: Extension id not found\n";
g_webview->Navigate(g_webuiUrl.c_str());
return true;
}
std::wstring uri = L"chrome-extension://" + extensionId + L"/install-usercss.html?updateUrl=" + finalUri;
g_webview->Navigate(uri.c_str());
return true;
}
return false;
}

10
src/utils/extensions.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef EXTENSIONS_H
#define EXTENSIONS_H
#include <string>
bool HandleExtensions(const std::wstring& finalUri);
bool HandlePremidLogin(const std::wstring& finalUri);
bool HandleStylusUsoInstall(const std::wstring& finalUri);
#endif //EXTENSIONS_H

348
src/utils/helpers.cpp Normal file
View file

@ -0,0 +1,348 @@
#include "helpers.h"
#include <fstream>
#include <iostream>
#include <shellscalingapi.h>
#include <tlhelp32.h>
#include <VersionHelpers.h>
#include <winhttp.h>
#include <curl/curl.h>
#include "../core/globals.h"
std::string WStringToUtf8(const std::wstring &wstr)
{
if (wstr.empty()) {
return {};
}
int neededSize = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), nullptr, 0, nullptr, nullptr);
if (neededSize <= 0) {
return {};
}
std::string result(neededSize, '\0');
WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), &result[0], neededSize, nullptr, nullptr);
// remove trailing null
while(!result.empty() && result.back()=='\0') {
result.pop_back();
}
return result;
}
std::wstring Utf8ToWstring(const std::string& utf8Str)
{
if (utf8Str.empty()) {
return std::wstring();
}
int size_needed = MultiByteToWideChar(CP_UTF8, 0, utf8Str.data(), (int)utf8Str.size(), NULL, 0);
if (size_needed == 0) {
return std::wstring();
}
std::wstring wstr(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, utf8Str.data(), (int)utf8Str.size(), &wstr[0], size_needed);
return wstr;
}
bool FileExists(const std::wstring& path)
{
DWORD attributes = GetFileAttributesW(path.c_str());
return (attributes != INVALID_FILE_ATTRIBUTES &&
!(attributes & FILE_ATTRIBUTE_DIRECTORY));
}
bool DirectoryExists(const std::wstring& dirPath)
{
DWORD attributes = GetFileAttributesW(dirPath.c_str());
return (attributes != INVALID_FILE_ATTRIBUTES &&
(attributes & FILE_ATTRIBUTE_DIRECTORY));
}
bool IsDuplicateProcessRunning(const std::vector<std::wstring>& targetProcesses)
{
DWORD currentPid = GetCurrentProcessId();
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE) {
return false;
}
PROCESSENTRY32W processEntry;
processEntry.dwSize = sizeof(PROCESSENTRY32W);
if (!Process32FirstW(hSnapshot, &processEntry)) {
CloseHandle(hSnapshot);
return false;
}
do {
if (processEntry.th32ProcessID == currentPid) {
continue;
}
std::wstring exeName(processEntry.szExeFile);
for (const auto& target : targetProcesses) {
if (_wcsicmp(exeName.c_str(), target.c_str()) == 0) {
CloseHandle(hSnapshot);
return true;
}
}
} while (Process32NextW(hSnapshot, &processEntry));
CloseHandle(hSnapshot);
return false;
}
// For local files
std::string decodeURIComponent(const std::string& encoded) {
std::string result;
result.reserve(encoded.size());
for (size_t i = 0; i < encoded.size(); ++i) {
char c = encoded[i];
if (c == '%' && i + 2 < encoded.size() &&
std::isxdigit(static_cast<unsigned char>(encoded[i + 1])) &&
std::isxdigit(static_cast<unsigned char>(encoded[i + 2]))) {
// Convert the two hex digits to a character
std::string hex = encoded.substr(i + 1, 2);
char decodedChar = static_cast<char>(std::strtol(hex.c_str(), nullptr, 16));
result.push_back(decodedChar);
i += 2;
} else {
result.push_back(c);
}
}
return result;
}
std::wstring GetExeDirectory()
{
wchar_t buf[MAX_PATH];
GetModuleFileNameW(nullptr,buf,MAX_PATH);
std::wstring path(buf);
size_t pos=path.find_last_of(L"\\/");
if(pos!=std::wstring::npos)
path.erase(pos);
return path;
}
bool isSubtitle(const std::wstring& filePath) {
std::wstring lowerFilePath = filePath;
std::transform(lowerFilePath.begin(), lowerFilePath.end(), lowerFilePath.begin(), towlower);
return std::any_of(g_subtitleExtensions.begin(), g_subtitleExtensions.end(),
[&](const std::wstring& ext) { return lowerFilePath.ends_with(ext); });
}
bool IsEndpointReachable(const std::wstring& url)
{
std::string urlUtf8 = WStringToUtf8(url);
CURL* curl = curl_easy_init();
if (!curl)
return false;
curl_easy_setopt(curl, CURLOPT_URL, urlUtf8.c_str());
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3L);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
curl_easy_cleanup(curl);
return false;
}
long response_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
curl_easy_cleanup(curl);
return (response_code >= 200 && response_code < 300);
}
std::wstring GetFirstReachableUrl() {
for (const auto& url : g_webuiUrls) {
if (IsEndpointReachable(url)) {
return url;
}
}
// Fallback to first URL or handle error
return g_webuiUrls.empty() ? L"" : g_webuiUrls[0];
}
bool URLContainsAny(const std::wstring& url) {
if (std::find(g_domainWhitelist.begin(), g_domainWhitelist.end(), g_webuiUrl) == g_domainWhitelist.end()) {
g_domainWhitelist.push_back(g_webuiUrl);
}
return std::any_of(g_domainWhitelist.begin(), g_domainWhitelist.end(), [&](const std::wstring& sub) {
return url.find(sub) != std::wstring::npos;
});
}
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
size_t totalSize = size * nmemb;
std::string* str = static_cast<std::string*>(userp);
str->append(static_cast<char*>(contents), totalSize);
return totalSize;
}
bool FetchAndParseWhitelist()
{
std::string urlUtf8 = WStringToUtf8(g_extensionsDetailsUrl);
CURL* curl = curl_easy_init();
if (!curl)
return false;
std::string response;
curl_easy_setopt(curl, CURLOPT_URL, urlUtf8.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3L);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
CURLcode res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if (res != CURLE_OK)
return false;
try {
json j = json::parse(response);
if (j.contains("domains") && j["domains"].is_array()) {
g_domainWhitelist.clear();
for (const auto& domain : j["domains"]) {
if (domain.is_string()) {
g_domainWhitelist.push_back(Utf8ToWstring(domain.get<std::string>()));
}
}
return true;
}
} catch (...) {
std::wcout << L"[HELPER]: Failed json parsing of domain whitelist for extensions..." << std::endl;
}
return false;
}
void ScaleWithDPI() {
if (!g_hWnd) return;
UINT dpi = 96;
HMONITOR hMonitor = MonitorFromWindow(g_hWnd, MONITOR_DEFAULTTOPRIMARY);
HRESULT hr = GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpi, nullptr);
if (FAILED(hr)) {
// Fall back to using g_hWnd's DPI if GetDpiForMonitor is unavailable
if (IsWindowsVersionOrGreater(10, 0, 1607))
{
dpi = GetDpiForWindow(g_hWnd);
}
else
{
HDC hdc = GetDC(g_hWnd);
dpi = GetDeviceCaps(hdc, LOGPIXELSX);
ReleaseDC(g_hWnd, hdc);
}
}
// Lambda to scale a value based on current DPI
auto ScaleValue = [dpi](int value) -> int {
return MulDiv(value, dpi, 96);
};
g_tray_itemH = ScaleValue(g_tray_itemH);
g_tray_sepH = ScaleValue(g_tray_sepH);
g_tray_w = ScaleValue(g_tray_w);
g_font_height = ScaleValue(g_font_height);
}
// ---- UTF-8 file read
bool ReadFileUtf8(const std::wstring& path, std::string& out)
{
std::ifstream f(path, std::ios::binary);
if (!f) return false;
f.seekg(0, std::ios::end);
std::streamsize size = f.tellg();
f.seekg(0, std::ios::beg);
out.resize(static_cast<size_t>(size));
if (size > 0) f.read(&out[0], size);
return true;
}
// ---- tiny Base64
std::string Base64Encode(const std::string& in)
{
static const char* T = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::string out;
out.reserve(((in.size() + 2) / 3) * 4);
int val = 0, valb = -6;
for (uint8_t c : in) {
val = (val << 8) + c;
valb += 8;
while (valb >= 0) {
out.push_back(T[(val >> valb) & 0x3F]);
valb -= 6;
}
}
if (valb > -6) out.push_back(T[((val << 8) >> (valb + 8)) & 0x3F]);
while (out.size() % 4) out.push_back('=');
return out;
}
// ---- wrap CSS text into a safe injector (decodes UTF-8 from base64)
std::wstring MakeInjectCssScript(const std::wstring& idSafe, const std::string& cssUtf8)
{
const std::string b64 = Base64Encode(cssUtf8);
const std::wstring wb64 = Utf8ToWstring(b64);
std::wstringstream ss;
ss <<
L"(function(){try{"
L"if(window.top!==window)return;"
L"var id='webmods-css-" << idSafe << L"';"
L"function inject(){"
L"try{"
L"var root=document.head||document.documentElement||document.body;"
L"if(!root){"
L"document.addEventListener('DOMContentLoaded',inject,{once:true});"
L"document.addEventListener('readystatechange',function(){"
L"if(document.readyState==='interactive'||document.readyState==='complete')inject();"
L"},{once:true});"
L"setTimeout(inject,25);"
L"return;"
L"}"
L"if(document.getElementById(id))return;"
L"var bin=atob('" << wb64 << L"');"
L"var bytes=new Uint8Array(bin.length);"
L"for(var i=0;i<bin.length;i++)bytes[i]=bin.charCodeAt(i);"
L"var css='';"
L"try{css=new TextDecoder('utf-8').decode(bytes);}catch(e){css=decodeURIComponent(escape(bin));}"
L"var s=document.createElement('style');"
L"s.id=id;"
L"s.textContent=css;"
L"root.appendChild(s);"
L"}catch(e){console.error('webmods css inject tick failed:',e);setTimeout(inject,50);}"
L"}"
L"inject();"
L"}catch(e){console.error('webmods css inject failed:',e);}})();";
return ss.str();
}
// ---- wrap JS text into a safe executor
std::wstring MakeInjectJsScript(const std::wstring&,const std::string& jsUtf8)
{
const std::string b64 = Base64Encode(jsUtf8);
const std::wstring wb64 = Utf8ToWstring(b64);
std::wstringstream ss;
ss <<
L"(function(){try{"
L"if(window.top!==window)return;"
L"function run(){"
L"try{"
L"var bin=atob('" << wb64 << L"');"
L"var bytes=new Uint8Array(bin.length);"
L"for(var i=0;i<bin.length;i++)bytes[i]=bin.charCodeAt(i);"
L"var js='';"
L"try{js=new TextDecoder('utf-8').decode(bytes);}catch(e){js=decodeURIComponent(escape(bin));}"
L"(0,eval)(js);"
L"}catch(e){console.error('webmods js exec tick failed:',e);setTimeout(run,25);}"
L"}"
L"run();"
L"}catch(e){console.error('webmods js exec failed:',e);}})();";
return ss.str();
}

25
src/utils/helpers.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef HELPERS_H
#define HELPERS_H
#include <windows.h>
#include <string>
#include <vector>
#include <filesystem>
std::string WStringToUtf8(const std::wstring &wstr);
std::wstring Utf8ToWstring(const std::string& utf8Str);
std::string decodeURIComponent(const std::string& encoded);
std::wstring GetExeDirectory();
std::wstring GetFirstReachableUrl();
std::wstring MakeInjectCssScript(const std::wstring& idSafe, const std::string& cssUtf8);
std::wstring MakeInjectJsScript(const std::wstring& idSafe, const std::string& jsUtf8);
bool FileExists(const std::wstring& path);
bool DirectoryExists(const std::wstring& dirPath);
bool IsDuplicateProcessRunning(const std::vector<std::wstring>& targetProcesses);
bool isSubtitle(const std::wstring& filePath);
bool URLContainsAny(const std::wstring& url);
bool FetchAndParseWhitelist();
void ScaleWithDPI();
bool ReadFileUtf8(const std::wstring& path, std::string& out);
#endif // HELPERS_H

718
src/webview/webview.cpp Normal file
View file

@ -0,0 +1,718 @@
#include "webview.h"
#include <string>
#include <thread>
#include <cmath>
#include <fstream>
#include <iostream>
#include <Shlwapi.h>
#include <wrl.h>
#include "../core/globals.h"
#include "../utils/crashlog.h"
#include "../utils/helpers.h"
#include "../ui/mainwindow.h"
#include "../utils/extensions.h"
static const wchar_t* EXEC_SHELL_SCRIPT = LR"JS_CODE(
try {
console.log('Shell JS injected');
if (window.self === window.top && !window.qt) {
window.qt = {
webChannelTransport: {
send: window.chrome.webview.postMessage,
onmessage: (ev) => {
// Will be overwritten by ShellTransport
console.log('Received message from WebView2:', ev);
}
}
};
window.chrome.webview.addEventListener('message', (ev) => {
window.qt.webChannelTransport.onmessage(ev);
});
window.onload = () => {
try {
initShellComm();
} catch (e) {
const errorMessage = {
type: 6,
object: "transport",
method: "handleInboundJSON",
id: 888,
args: [
"app-error",
[ "shellComm" ]
]
};
window.chrome.webview.postMessage(JSON.stringify(errorMessage));
}
};
}
} catch(e) {
console.error("Error exec initShellComm:", e);
const errorMessage = {
type: 6,
object: "transport",
method: "handleInboundJSON",
id: 888,
args: [
"app-error",
[ "shellComm" ]
]
};
if(window.chrome && window.chrome.webview && window.chrome.webview.postMessage) {
window.chrome.webview.postMessage(JSON.stringify(errorMessage));
}
};
)JS_CODE";
static const wchar_t* INJECTED_KEYDOWN_SCRIPT = LR"JS(
(function() {
window.addEventListener('keydown', function(event) {
if (event.code === 'F5') {
event.preventDefault();
const ctrlPressed = event.ctrlKey || event.metaKey;
const msg = {
type: 6,
object: "transport",
method: "handleInboundJSON",
id: 999,
args: [
"refresh",
[ ctrlPressed ? "all" : "no" ]
]
};
window.chrome.webview.postMessage(JSON.stringify(msg));
}
});
})();
)JS";
static const wchar_t* INJECTED_BUTTON_SCRIPT = LR"JS(
(function() {
// Create the button element
var btn = document.createElement('button');
btn.id = 'goBackStremioBtn';
// Style the button:
btn.style.position = 'fixed';
btn.style.bottom = '15px';
btn.style.right = '15px';
btn.style.zIndex = '9999';
btn.style.backgroundColor = '#121024'; // Purple
btn.style.color = 'white';
btn.style.border = 'none';
btn.style.borderRadius = '30px';
btn.style.padding = '12px 20px';
btn.style.fontSize = '16px';
btn.style.fontWeight = 'bold';
btn.style.display = 'flex';
btn.style.alignItems = 'center';
btn.style.boxShadow = '0 4px 6px rgba(0,0,0,0.1)';
btn.style.cursor = 'pointer';
btn.style.transition = 'background-color 0.3s ease';
// Hover effect:
btn.addEventListener('mouseenter', function() {
btn.style.backgroundColor = '#211e39'; // Gray
});
btn.addEventListener('mouseleave', function() {
btn.style.backgroundColor = '#121024';
});
// Create an image element for the logo
var img = document.createElement('img');
img.src = 'https://stremio.zarg.me/images/stremio_symbol.png';
img.alt = 'Logo';
img.style.height = '24px';
img.style.width = '24px';
img.style.marginRight = '8px';
img.addEventListener('error', function() {
img.style.display = 'none';
});
// Create a text element
var txt = document.createElement('span');
txt.textContent = 'Back to Stremio';
// Append the logo and text to the button
btn.appendChild(img);
btn.appendChild(txt);
// On click go home
btn.addEventListener('click', function() {
const payload = {
type: 6,
object: "transport",
method: "handleInboundJSON",
id: 666,
args: [
"navigate",
[ "home" ]
]
};
window.chrome.webview.postMessage(JSON.stringify(payload));
});
// Append the button to the document body
document.body.appendChild(btn);
})();
)JS";
void WaitAndRefreshIfNeeded()
{
std::thread([](){
const int maxAttempts = 10;
const int initialWaitTime = 5;
const int maxWaitTime = 60;
std::cout << "[WEBVIEW]: Web Page could not be reached, retrying..." << std::endl;
for(int attempt=0; attempt<maxAttempts; ++attempt)
{
int waitTime = (int)(initialWaitTime * pow(1.25, attempt));
if(waitTime>maxWaitTime) waitTime = maxWaitTime;
std::this_thread::sleep_for(std::chrono::seconds(waitTime));
if(g_isAppReady){
std::cout << "[WEBVIEW]: Web Page ready!" << std::endl;
g_waitStarted.store(false);
return;
}
std::cout << "[WEBVIEW]: Refreshing attempt " << (attempt+1) << std::endl;
refreshWeb(false);
}
if(!g_isAppReady) {
AppendToCrashLog("[WEBVIEW]: Could not load after attempts");
MessageBoxW(nullptr,
L"Web page could not be loaded after multiple attempts. Make sure the Web UI is reachable.",
L"WebView2 Page load fail",
MB_ICONERROR | MB_OK
);
PostQuitMessage(1);
exit(1);
}
}).detach();
}
void InitWebView2(HWND hWnd)
{
std::cout << "[WEBVIEW]: Starting webview..." << std::endl;
// Setup environment
Microsoft::WRL::ComPtr<ICoreWebView2EnvironmentOptions> options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
if(options){
options->put_AdditionalBrowserArguments(
L"--autoplay-policy=no-user-gesture-required --disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection"
);
Microsoft::WRL::ComPtr<ICoreWebView2EnvironmentOptions6> options6;
if(SUCCEEDED(options.As(&options6))) {
options6->put_AreBrowserExtensionsEnabled(TRUE);
}
Microsoft::WRL::ComPtr<ICoreWebView2EnvironmentOptions5> options5;
if(SUCCEEDED(options.As(&options5))) {
options5->put_EnableTrackingPrevention(TRUE);
}
}
// Check for local Edge runtime in "portable_config/EdgeWebView"
std::wstring exeDir;
{
wchar_t buf[MAX_PATH];
GetModuleFileNameW(nullptr, buf, MAX_PATH);
exeDir = buf;
size_t pos = exeDir.find_last_of(L"\\/");
if(pos!=std::wstring::npos) exeDir.erase(pos);
}
std::wstring browserDir = exeDir + L"\\portable_config\\EdgeWebView";
const wchar_t* browserExecutableFolder = nullptr;
if(DirectoryExists(browserDir)) {
browserExecutableFolder = browserDir.c_str();
std::wcout << L"[WEBVIEW]: Using local WebView2: " << browserDir << std::endl;
}
HRESULT hr = CreateCoreWebView2EnvironmentWithOptions(
browserExecutableFolder, nullptr, options.Get(),
Microsoft::WRL::Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
[hWnd](HRESULT res, ICoreWebView2Environment* env)->HRESULT
{
if(!env) return E_FAIL;
env->CreateCoreWebView2Controller(
hWnd,
Microsoft::WRL::Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
[hWnd](HRESULT result, ICoreWebView2Controller* rawController)->HRESULT
{
if (FAILED(result) || !rawController) return E_FAIL;
std::cout << "[WEBVIEW]: Initializing WebView..." << std::endl;
wil::com_ptr<ICoreWebView2Controller> m_webviewController = rawController;
if (!m_webviewController) return E_FAIL;
g_webviewController = m_webviewController.try_query<ICoreWebView2Controller4>();
if (!g_webviewController) return E_FAIL;
wil::com_ptr<ICoreWebView2> coreWebView;
g_webviewController->get_CoreWebView2(&coreWebView);
g_webview = coreWebView.try_query<ICoreWebView2_21>();
if (!g_webview) return E_FAIL;
wil::com_ptr<ICoreWebView2Profile> webView2Profile;
g_webview->get_Profile(&webView2Profile);
g_webviewProfile = webView2Profile.try_query<ICoreWebView2Profile8>();
if (!g_webviewProfile) return E_FAIL;
wil::com_ptr<ICoreWebView2Settings> webView2Settings;
g_webview->get_Settings(&webView2Settings);
auto settings = webView2Settings.try_query<ICoreWebView2Settings8>();
if (!settings) return E_FAIL;
if(settings) {
#ifndef DEBUG_LOG
settings->put_AreDevToolsEnabled(FALSE);
#endif
settings->put_IsStatusBarEnabled(FALSE);
settings->put_AreBrowserAcceleratorKeysEnabled(FALSE);
std::wstring customUA = std::wstring(L"StremioShell/") + Utf8ToWstring(APP_VERSION);
settings->put_UserAgent(customUA.c_str());
if(!g_allowZoom) {
settings->put_IsZoomControlEnabled(FALSE);
settings->put_IsPinchZoomEnabled(FALSE);
}
}
// Set background color
COREWEBVIEW2_COLOR col={0,0,0,0};
g_webviewController->put_DefaultBackgroundColor(col);
RECT rc; GetClientRect(hWnd,&rc);
g_webviewController->put_Bounds(rc);
g_webview->AddScriptToExecuteOnDocumentCreated(EXEC_SHELL_SCRIPT,nullptr);
g_webview->AddScriptToExecuteOnDocumentCreated(INJECTED_KEYDOWN_SCRIPT,nullptr);
SetupWebMods();
SetupExtensions();
SetupWebMessageHandler();
std::thread([](){
std::wcout << L"[WEBVIEW]: Checking web ui endpoints..." << std::endl;
std::wstring foundUrl = GetFirstReachableUrl();
std::wstring* pResult = new std::wstring(foundUrl);
g_webuiUrl = foundUrl;
PostMessage(g_hWnd, WM_REACHABILITY_DONE, (WPARAM)pResult, 0);
FetchAndParseWhitelist();
}).detach();
return S_OK;
}).Get()
);
return S_OK;
}).Get()
);
if(FAILED(hr)) {
std::wstring msg = L"[WEBVIEW]: CreateCoreWebView2EnvironmentWithOptions failed => " + std::to_wstring(hr);
AppendToCrashLog(msg);
MessageBoxW(nullptr, msg.c_str(), L"WebView2 Initialization Error", MB_ICONERROR | MB_OK);
PostQuitMessage(1);
exit(1);
}
}
static void SetupWebMessageHandler()
{
if(!g_webview) return;
EventRegistrationToken navToken;
g_webview->add_NavigationCompleted(
Microsoft::WRL::Callback<ICoreWebView2NavigationCompletedEventHandler>(
[](ICoreWebView2* sender, ICoreWebView2NavigationCompletedEventArgs* args)->HRESULT
{
BOOL isSuccess;
args->get_IsSuccess(&isSuccess);
// Retrieve the final URL
wil::unique_cotaskmem_string rawUri;
sender->get_Source(&rawUri);
std::wstring finalUri = rawUri ? rawUri.get() : L"";
std::wcout << L"[WEBVIEW]: Navigation try to " << finalUri << std::endl;
// Add back to stremio button if not on stremio
if (finalUri.find(g_webuiUrl) == std::wstring::npos) {
sender->ExecuteScript(INJECTED_BUTTON_SCRIPT, nullptr);
}
if(isSuccess) {
std::cout<<"[WEBVIEW]: Navigation Complete - Success\n";
sender->ExecuteScript(EXEC_SHELL_SCRIPT, nullptr);
// Flush the script queue.
if (!g_scriptQueue.empty()) {
for (const auto &script : g_scriptQueue) {
sender->ExecuteScript(script.c_str(), nullptr);
}
g_scriptQueue.clear();
}
} else {
std::cout<<"[WEBVIEW]: Navigation failed\n";
if(g_hSplash && !g_waitStarted.exchange(true)) {
WaitAndRefreshIfNeeded();
}
HandleExtensions(finalUri);
}
return S_OK;
}).Get(),
&navToken
);
EventRegistrationToken contentToken;
g_webview->add_ContentLoading(
Microsoft::WRL::Callback<ICoreWebView2ContentLoadingEventHandler>(
[](ICoreWebView2* sender, ICoreWebView2ContentLoadingEventArgs* args) -> HRESULT {
std::cout<<"[WEBVIEW]: Content loaded\n";
sender->ExecuteScript(EXEC_SHELL_SCRIPT, nullptr);
return S_OK;
}
).Get(),
&contentToken
);
EventRegistrationToken domToken;
g_webview->add_DOMContentLoaded(
Microsoft::WRL::Callback<ICoreWebView2DOMContentLoadedEventHandler>(
[](ICoreWebView2* sender, ICoreWebView2DOMContentLoadedEventArgs* args)->HRESULT
{
sender->ExecuteScript(EXEC_SHELL_SCRIPT, nullptr);
return S_OK;
}).Get(),
&domToken
);
EventRegistrationToken contextMenuToken;
g_webview->add_ContextMenuRequested(
Microsoft::WRL::Callback<ICoreWebView2ContextMenuRequestedEventHandler>(
[](ICoreWebView2* sender, ICoreWebView2ContextMenuRequestedEventArgs* args) -> HRESULT {
// Existing variable declarations
wil::com_ptr<ICoreWebView2ContextMenuItemCollection> items;
HRESULT hr = args->get_MenuItems(&items);
if (FAILED(hr) || !items) return hr;
#ifdef DEBUG_LOG
return S_OK; //DEV TOOLS DEBUG ONLY
#endif
// Get current URL
wil::unique_cotaskmem_string currentUri;
sender->get_Source(&currentUri);
std::wstring uri(currentUri.get());
bool isExtensionUrl = uri.starts_with(L"chrome-extension://");
// Get context menu target
wil::com_ptr<ICoreWebView2ContextMenuTarget> target;
hr = args->get_ContextMenuTarget(&target);
BOOL isEditable = FALSE;
if (SUCCEEDED(hr) && target) {
target->get_IsEditable(&isEditable);
}
UINT count = 0;
items->get_Count(&count);
if (!isEditable) {
// Allow only Back command (ID 33000) for extension URLs
std::set<INT32> allowedCommands = isExtensionUrl ?
std::set<INT32>{33000} :
std::set<INT32>{};
for (UINT i = 0; i < count;) {
wil::com_ptr<ICoreWebView2ContextMenuItem> item;
hr = items->GetValueAtIndex(i, &item);
if (FAILED(hr)) {
i++;
continue;
}
INT32 commandId;
item->get_CommandId(&commandId);
if (allowedCommands.find(commandId) == allowedCommands.end()) {
items->RemoveValueAtIndex(i);
items->get_Count(&count);
} else {
i++;
}
}
return S_OK;
}
// Define allowed command IDs for filtering
std::set<INT32> allowedCommandIds = {
50151, // Cut
50150, // Copy
50152, // Paste
50157, // Paste as plain text
50156 // Select all
};
for (UINT i = 0; i < count;) {
wil::com_ptr<ICoreWebView2ContextMenuItem> item;
hr = items->GetValueAtIndex(i, &item);
if (FAILED(hr)) {
i++;
continue;
}
INT32 commandId;
item->get_CommandId(&commandId);
if (allowedCommandIds.find(commandId) == allowedCommandIds.end()) {
items->RemoveValueAtIndex(i);
items->get_Count(&count);
} else {
i++;
}
}
return S_OK;
}).Get(),
&contextMenuToken
);
EventRegistrationToken msgToken;
g_webview->add_WebMessageReceived(
Microsoft::WRL::Callback<ICoreWebView2WebMessageReceivedEventHandler>(
[](ICoreWebView2* /*sender*/, ICoreWebView2WebMessageReceivedEventArgs* args)->HRESULT
{
wil::unique_cotaskmem_string msgRaw;
args->TryGetWebMessageAsString(&msgRaw);
if(!msgRaw) return S_OK;
std::wstring wstr(msgRaw.get());
std::string str = WStringToUtf8(wstr);
HandleInboundJSON(str);
return S_OK;
}).Get(),
&msgToken
);
EventRegistrationToken newWindowToken;
g_webview->add_NewWindowRequested(
Microsoft::WRL::Callback<ICoreWebView2NewWindowRequestedEventHandler>(
[](ICoreWebView2* /*sender*/, ICoreWebView2NewWindowRequestedEventArgs* args) -> HRESULT
{
// Mark the event as handled to prevent default behavior
args->put_Handled(TRUE);
wil::unique_cotaskmem_string uri;
if (SUCCEEDED(args->get_Uri(&uri)) && uri)
{
std::wstring wuri(uri.get());
// Check if the URI is a local file (starts with "file://")
if (wuri.rfind(L"file://", 0) == 0)
{
std::wstring filePath = wuri.substr(8);
std::string utf8FilePath = WStringToUtf8(filePath);
std::string decodedFilePathUtf8 = decodeURIComponent(utf8FilePath);
std::string baseName = std::filesystem::path(decodedFilePathUtf8).filename().string();
if (isSubtitle(filePath)) {
std::vector<std::string> subaddArgs = {"sub-add",decodedFilePathUtf8, "select", baseName + " External", "Other Tracks"};
HandleEvent("mpv-command", subaddArgs);
json j;
j["type"] = "SubtitleDropped";
j["path"] = utf8FilePath;
SendToJS("SubtitleDropped", j);
return S_OK;
}
json j;
j["type"] = "FileDropped";
j["path"] = decodedFilePathUtf8;
SendToJS("FileDropped", j);
return S_OK;
}
if (URLContainsAny(wuri)) {
g_webview->Navigate(wuri.c_str());
return S_OK;
}
// For non-file URIs, open externally
ShellExecuteW(nullptr, L"open", uri.get(), nullptr, nullptr, SW_SHOWNORMAL);
}
return S_OK;
}
).Get(),
&newWindowToken
);
// For redirects like window.location.replace
EventRegistrationToken navstartedToken;
g_webview->add_NavigationStarting(
Microsoft::WRL::Callback<ICoreWebView2NavigationStartingEventHandler>(
[](ICoreWebView2* sender, ICoreWebView2NavigationStartingEventArgs* args) -> HRESULT
{
wil::unique_cotaskmem_string uri;
args->get_Uri(&uri);
std::wstring destination(uri.get());
if (!URLContainsAny(destination)) {
args->put_Cancel(TRUE);
ShellExecuteW(nullptr, L"open", uri.get(), nullptr, nullptr, SW_SHOWNORMAL);
}
return S_OK;
}
).Get(),
&navstartedToken
);
// FullScreen
EventRegistrationToken cfeToken;
g_webview->add_ContainsFullScreenElementChanged(
Microsoft::WRL::Callback<ICoreWebView2ContainsFullScreenElementChangedEventHandler>(
[](ICoreWebView2* sender, IUnknown* /*args*/) -> HRESULT
{
// FullScreen Toggle Handle
BOOL inFull = FALSE;
sender->get_ContainsFullScreenElement(&inFull);
ToggleFullScreen(g_hWnd, inFull != FALSE);
return S_OK;
}
).Get(),
&cfeToken
);
}
static void SetupExtensions()
{
if(!g_webview || !g_webviewProfile) return;
// e.g. from "portable_config/extensions"
std::wstring exeDir;
{
wchar_t buf[MAX_PATH];
GetModuleFileNameW(nullptr, buf, MAX_PATH);
exeDir = buf;
size_t pos = exeDir.find_last_of(L"\\/");
if(pos!=std::wstring::npos) exeDir.erase(pos);
}
std::wstring extensionsRoot = exeDir + L"\\portable_config\\extensions";
try {
for(const auto& entry : std::filesystem::directory_iterator(extensionsRoot)) {
if(entry.is_directory()) {
std::wstring folderName = entry.path().filename().wstring();
HRESULT hr = g_webviewProfile->AddBrowserExtension(
entry.path().wstring().c_str(),
Microsoft::WRL::Callback<ICoreWebView2ProfileAddBrowserExtensionCompletedHandler>(
[folderName](HRESULT result, ICoreWebView2BrowserExtension* extension)->HRESULT
{
if (SUCCEEDED(result) && extension)
{
wil::unique_cotaskmem_string extId;
HRESULT hrId = extension->get_Id(&extId);
if (SUCCEEDED(hrId) && extId)
{
// Store extension ID in the global map
g_extensionMap[folderName] = extId.get();
std::wcout << L"[EXTENSIONS]: " << folderName
<< L" => " << extId.get() << std::endl;
}
std::wcout << L"[EXTENSIONS]: Added extension " << folderName << std::endl;
} else {
std::wstring err = L"[EXTENSIONS]: Failed to add extension => " + std::to_wstring(result);
AppendToCrashLog(err);
}
return S_OK;
}).Get()
);
if(FAILED(hr)) {
std::wstring err = L"[EXTENSIONS]: AddBrowserExtension failed => " + std::to_wstring(hr);
AppendToCrashLog(err);
}
}
}
} catch(...) {
std::cout<<"[EXTENSIONS]: No extensions folder or iteration failed.\n";
}
}
static void SetupWebMods()
{
if (!g_webview) return;
wchar_t buf[MAX_PATH];
GetModuleFileNameW(nullptr, buf, MAX_PATH);
std::wstring exeDir = buf;
size_t pos = exeDir.find_last_of(L"\\/");
if (pos != std::wstring::npos) exeDir.erase(pos);
const std::filesystem::path root = std::filesystem::path(exeDir) / L"portable_config" / L"webmods";
if (!std::filesystem::exists(root) || !std::filesystem::is_directory(root)) {
std::wcout << L"[WEBMODS] Folder not found: " << root.wstring() << std::endl;
return;
}
std::vector<std::filesystem::path> cssFiles, jsFiles;
for (const auto& e : std::filesystem::recursive_directory_iterator(root)) {
if (!e.is_regular_file()) continue;
auto ext = e.path().extension().wstring();
std::transform(ext.begin(), ext.end(), ext.begin(), ::towlower);
if (ext == L".map" || ext == L".bak" || ext == L".tmp") continue;
if (ext == L".css") cssFiles.push_back(e.path());
else if (ext == L".js") jsFiles.push_back(e.path());
}
auto relStr = [&](const std::filesystem::path& p){
try { return std::filesystem::relative(p, root).wstring(); }
catch(...) { return p.wstring(); }
};
auto sorter = [&](const std::filesystem::path& a, const std::filesystem::path& b){
auto ra = relStr(a), rb = relStr(b);
return _wcsicmp(ra.c_str(), rb.c_str()) < 0;
};
std::sort(cssFiles.begin(), cssFiles.end(), sorter);
std::sort(jsFiles.begin(), jsFiles.end(), sorter);
auto makeId = [&](const std::filesystem::path& p){
std::wstring id = relStr(p);
for (auto& ch : id) if (!iswalnum(ch)) ch = L'_';
return id;
};
for (const auto& p : cssFiles) {
std::string content;
if (!ReadFileUtf8(p.wstring(), content)) continue;
const std::wstring id = makeId(p);
const std::wstring script = MakeInjectCssScript(id, content);
g_webview->AddScriptToExecuteOnDocumentCreated(script.c_str(), nullptr);
std::wcout << L"[WEBMODS] CSS: " << relStr(p) << std::endl;
}
for (const auto& p : jsFiles) {
std::string content;
if (!ReadFileUtf8(p.wstring(), content)) continue;
const std::wstring id = makeId(p);
const std::wstring script = MakeInjectJsScript(id, content);
g_webview->AddScriptToExecuteOnDocumentCreated(script.c_str(), nullptr);
std::wcout << L"[WEBMODS] JS: " << relStr(p) << std::endl;
}
}
void refreshWeb(const bool refreshAll) {
if (g_webviewProfile && refreshAll)
{
HRESULT hr = g_webviewProfile->ClearBrowsingData(
COREWEBVIEW2_BROWSING_DATA_KINDS_DISK_CACHE |
COREWEBVIEW2_BROWSING_DATA_KINDS_CACHE_STORAGE |
COREWEBVIEW2_BROWSING_DATA_KINDS_SERVICE_WORKERS |
COREWEBVIEW2_BROWSING_DATA_KINDS_FILE_SYSTEMS |
COREWEBVIEW2_BROWSING_DATA_KINDS_WEB_SQL |
COREWEBVIEW2_BROWSING_DATA_KINDS_INDEXED_DB,
Microsoft::WRL::Callback<ICoreWebView2ClearBrowsingDataCompletedHandler>(
[](HRESULT result) -> HRESULT {
std::cout << "[BROWSER]: Cleared browser cache successfully" << std::endl;
return S_OK;
}
).Get()
);
if (FAILED(hr)) {
std::cout << "[BROWSER]: Could not clear browser cache" << std::endl;
}
}
if (g_webview) {
g_webview->Reload();
}
}

14
src/webview/webview.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef WEBVIEW_H
#define WEBVIEW_H
#include <windows.h>
#include <string>
void InitWebView2(HWND hWnd);
void WaitAndRefreshIfNeeded();
void refreshWeb(bool refreshAll);
static void SetupWebMessageHandler();
static void SetupExtensions();
static void SetupWebMods();
#endif // WEBVIEW_H

View file

@ -3,5 +3,5 @@
#define IDR_MAINFRAME 101
IDR_MAINFRAME ICON "images/stremio.ico"
IDR_MAINFRAME ICON "images/stremio2.ico"
IDR_SPLASH_PNG RCDATA "images/stremio.png"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>stremio-desktop-v5</id>
<version>5.0.12</version>
<version>5.0.21</version>
<title>Stremio Desktop v5</title>
<authors>Zarg</authors>
<owners>Zarg</owners>

View file

@ -11,12 +11,12 @@ $packageArgs = @{
if ([Environment]::Is64BitOperatingSystem) {
$packageArgs['url'] = 'https://github.com/Zaarrg/stremio-desktop-v5/releases/download/5.0.0-beta.12/Stremio.5.0.12-x64.exe'
$packageArgs['checksum'] = 'e7c045800d502874b8e083427aa81d316625c658fa804e67156dddd4f03ea6ed'
$packageArgs['url'] = 'https://github.com/Zaarrg/stremio-desktop-v5/releases/download/5.0.0-beta.21/Stremio.5.0.21-x64.exe'
$packageArgs['checksum'] = '6b2597e3179355fb59b62df762d65dbe3e493f96471fa3cf17e1620fadd0a1d7'
$packageArgs['checksumType'] = 'sha256'
} else {
$packageArgs['url'] = 'https://github.com/Zaarrg/stremio-desktop-v5/releases/download/5.0.0-beta.12/Stremio.5.0.12-x86.exe'
$packageArgs['checksum'] = '715ec5def305a019849b3a5e402398b53b5ed242f065266384f4428ed4c39818'
$packageArgs['url'] = 'https://github.com/Zaarrg/stremio-desktop-v5/releases/download/5.0.0-beta.21/Stremio.5.0.21-x86.exe'
$packageArgs['checksum'] = 'f2dfad202ae03b26a1d584d9a4e8747be6e0b078e6c6c5773d57632bdfe3aee0'
$packageArgs['checksumType'] = 'sha256'
}

Binary file not shown.

View file

@ -5,6 +5,7 @@ CTRL+3 no-osd change-list glsl-shaders set "~~/shaders/Anime4K_Clamp_Highlights.
CTRL+4 no-osd change-list glsl-shaders set "~~/shaders/Anime4K_Clamp_Highlights.glsl;~~/shaders/Anime4K_Restore_CNN_VL.glsl;~~/shaders/Anime4K_Upscale_CNN_x2_VL.glsl;~~/shaders/Anime4K_Restore_CNN_M.glsl;~~/shaders/Anime4K_AutoDownscalePre_x2.glsl;~~/shaders/Anime4K_AutoDownscalePre_x4.glsl;~~/shaders/Anime4K_Upscale_CNN_x2_M.glsl"; show-text "Anime4K: Mode A+A (HQ)"
CTRL+5 no-osd change-list glsl-shaders set "~~/shaders/Anime4K_Clamp_Highlights.glsl;~~/shaders/Anime4K_Restore_CNN_Soft_VL.glsl;~~/shaders/Anime4K_Upscale_CNN_x2_VL.glsl;~~/shaders/Anime4K_AutoDownscalePre_x2.glsl;~~/shaders/Anime4K_AutoDownscalePre_x4.glsl;~~/shaders/Anime4K_Restore_CNN_Soft_M.glsl;~~/shaders/Anime4K_Upscale_CNN_x2_M.glsl"; show-text "Anime4K: Mode B+B (HQ)"
CTRL+6 no-osd change-list glsl-shaders set "~~/shaders/Anime4K_Clamp_Highlights.glsl;~~/shaders/Anime4K_Upscale_Denoise_CNN_x2_VL.glsl;~~/shaders/Anime4K_AutoDownscalePre_x2.glsl;~~/shaders/Anime4K_AutoDownscalePre_x4.glsl;~~/shaders/Anime4K_Restore_CNN_M.glsl;~~/shaders/Anime4K_Upscale_CNN_x2_M.glsl"; show-text "Anime4K: Mode C+A (HQ)"
CTRL+7 no-osd change-list glsl-shaders set "~~/shaders/FSR.glsl"; show-text "FSR"
CTRL+0 no-osd change-list glsl-shaders clr ""; show-text "GLSL shaders cleared"
# Audio Normalization

View file

@ -0,0 +1,151 @@
MAX_SPEED = 100
NORMAL_SPEED = 1
ONE_SECOND = 1
skip = false
-- Max noise (dB) and min silence duration (s) to trigger
opts = { quietness = -30, duration = 0.5 }
function setOptions()
local options = require 'mp.options'
options.read_options(opts)
end
function setTime(time)
mp.set_property_number('time-pos', time)
end
function getTime()
return mp.get_property_native('time-pos')
end
function setSpeed(speed)
mp.set_property('speed', speed)
end
function setPause(state)
mp.set_property_bool('pause', state)
end
function setMute(state)
mp.set_property_bool('mute', state)
end
function initAudioFilter()
local af_table = mp.get_property_native('af')
af_table[#af_table + 1] = {
enabled = false,
label = 'silencedetect',
name = 'lavfi',
params = { graph = 'silencedetect=noise=' .. opts.quietness .. 'dB:d=' .. opts.duration }
}
mp.set_property_native('af', af_table)
end
function initVideoFilter()
local vf_table = mp.get_property_native('vf')
vf_table[#vf_table + 1] = {
enabled = false,
label = 'blackout',
name = 'lavfi',
params = { graph = '' }
}
mp.set_property_native('vf', vf_table)
end
function setAudioFilter(state)
local af_table = mp.get_property_native('af')
if #af_table > 0 then
for i = #af_table, 1, -1 do
if af_table[i].label == 'silencedetect' then
af_table[i].enabled = state
mp.set_property_native('af', af_table)
break
end
end
end
end
function dim(state)
local dim = { width = 0, height = 0 }
if state == true then
dim.width = mp.get_property_native('width')
dim.height = mp.get_property_native('height')
end
return dim.width .. 'x' .. dim.height
end
function setVideoFilter(state)
local vf_table = mp.get_property_native('vf')
if #vf_table > 0 then
for i = #vf_table, 1, -1 do
if vf_table[i].label == 'blackout' then
vf_table[i].enabled = state
vf_table[i].params = { graph = 'nullsink,color=c=black:s=' .. dim(state) }
mp.set_property_native('vf', vf_table)
break
end
end
end
end
function silenceTrigger(name, value)
if value == '{}' or value == nil then
return
end
local skipTime = tonumber(string.match(value, '%d+%.?%d+'))
local currTime = getTime()
if skipTime == nil or skipTime < currTime + ONE_SECOND then
return
end
stopSkip()
setTime(skipTime)
skip = false
end
function setAudioTrigger(state)
if state == true then
mp.observe_property('af-metadata/silencedetect', 'string', silenceTrigger)
else
mp.unobserve_property(silenceTrigger)
end
end
function startSkip()
startTime = getTime()
-- This audio filter detects moments of silence
setAudioFilter(true)
-- This video filter makes fast-forward faster
setVideoFilter(true)
setAudioTrigger(true)
setPause(false)
setMute(true)
setSpeed(MAX_SPEED)
end
function stopSkip()
setAudioFilter(false)
setVideoFilter(false)
setAudioTrigger(false)
setMute(false)
setSpeed(NORMAL_SPEED)
end
function keypress()
skip = not skip
if skip then
startSkip()
else
stopSkip()
setTime(startTime)
end
end
setOptions(opts)
initAudioFilter()
initVideoFilter()
mp.add_key_binding('Tab', 'skip-key', keypress)

View file

@ -1,12 +1,12 @@
{
"version": "5.0.12",
"version": "5.0.21",
"description": "Stremio Desktop v5 Community",
"homepage": "https://github.com/Zaarrg/stremio-desktop-v5",
"license": "GPL-3.0",
"architecture": {
"64bit": {
"url": "https://github.com/Zaarrg/stremio-desktop-v5/releases/download/5.0.0-beta.12/Stremio.5.0.12-x64.exe",
"hash": "e7c045800d502874b8e083427aa81d316625c658fa804e67156dddd4f03ea6ed",
"url": "https://github.com/Zaarrg/stremio-desktop-v5/releases/download/5.0.0-beta.21/Stremio.5.0.21-x64.exe",
"hash": "6b2597e3179355fb59b62df762d65dbe3e493f96471fa3cf17e1620fadd0a1d7",
"installer": {
"args": [
"/S"
@ -24,8 +24,8 @@
}
},
"32bit": {
"url": "https://github.com/Zaarrg/stremio-desktop-v5/releases/download/5.0.0-beta.12/Stremio.5.0.12-x86.exe",
"hash": "715ec5def305a019849b3a5e402398b53b5ed242f065266384f4428ed4c39818",
"url": "https://github.com/Zaarrg/stremio-desktop-v5/releases/download/5.0.0-beta.21/Stremio.5.0.21-x86.exe",
"hash": "f2dfad202ae03b26a1d584d9a4e8747be6e0b078e6c6c5773d57632bdfe3aee0",
"installer": {
"args": [
"/S"

View file

@ -5,3 +5,6 @@ ThumbFastHeight=0
PauseOnMinimize=1
PauseOnLostFocus=0
AllowZoom=0
[MPV]
VideoOutput=gpu-next
InitialVolume=50

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -70,15 +70,13 @@ RequestExecutionLevel user
;Define UI settings
;!define MUI_UI_HEADERIMAGE_RIGHT "../../../images/icon.png"
!define MUI_ICON "../../../images/stremio.ico"
!define MUI_UNICON "../../../images/stremio.ico"
!define MUI_ICON "../../../images/stremio2.ico"
!define MUI_UNICON "../../../images/stremio2.ico"
; WARNING; these bmps have to be generated in BMP3 - convert SMTH BMP3:SMTH.bmp
!define MUI_WELCOMEFINISHPAGE_BITMAP "windows-installer.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "windows-installer.bmp"
!define MUI_ABORTWARNING
!define MUI_FINISHPAGE_LINK "www.stremio.com"
!define MUI_FINISHPAGE_LINK_LOCATION "${APP_URL}"
!define MUI_FINISHPAGE_RUN "$INSTDIR\stremio.exe"
; Hack...
@ -145,25 +143,53 @@ Var AssociateMagnetCheckbox
Var AssociateMediaCheckbox
Var AssociateTorrentCheckbox
Var checkbox_value
Var InstallStremioServiceCheckbox
Function fin_pg_options
${NSD_CreateCheckbox} 180 -100 100% 8u "Associate ${APP_NAME} with .torrent files"
; Install Stremio Service checkbox (top)
${NSD_CreateCheckbox} 180 -100 100% 8u "Install Stremio Service"
Pop $InstallStremioServiceCheckbox
SetCtlColors $InstallStremioServiceCheckbox '0xFF0000' '0xFFFFFF'
${NSD_Uncheck} $InstallStremioServiceCheckbox
; Leave a visual gap here (e.g., 20 pixels)
${NSD_CreateCheckbox} 180 -70 100% 8u "Associate ${APP_NAME} with .torrent files"
Pop $AssociateTorrentCheckbox
SetCtlColors $AssociateTorrentCheckbox '0xFF0000' '0xFFFFFF'
${NSD_Check} $AssociateTorrentCheckbox
${NSD_CreateCheckbox} 180 -80 100% 8u "Associate ${APP_NAME} with magnet links"
${NSD_CreateCheckbox} 180 -50 100% 8u "Associate ${APP_NAME} with magnet links"
Pop $AssociateMagnetCheckbox
SetCtlColors $AssociateMagnetCheckbox '0xFF0000' '0xFFFFFF'
${NSD_Check} $AssociateMagnetCheckbox
${NSD_CreateCheckbox} 180 -60 100% 8u "Associate ${APP_NAME} as media player"
${NSD_CreateCheckbox} 180 -30 100% 8u "Associate ${APP_NAME} as media player"
Pop $AssociateMediaCheckbox
SetCtlColors $AssociateMediaCheckbox '0xFF0000' '0xFFFFFF'
${NSD_Check} $AssociateMediaCheckbox
FunctionEnd
Function fin_pg_leave
; Check "Install Stremio Service" checkbox state
${NSD_GetState} $InstallStremioServiceCheckbox $checkbox_value
${If} $checkbox_value == ${BST_CHECKED}
SetDetailsPrint textonly
DetailPrint "Installing Stremio Service..."
SetDetailsPrint none
; Extract StremioServiceSetup.exe
File "/oname=$PLUGINSDIR\StremioServiceSetup.exe" "..\StremioServiceSetup.exe"
ExecWait '"$PLUGINSDIR\StremioServiceSetup.exe" /silent' $R0
SetDetailsPrint textonly
${If} $R0 == 0
DetailPrint "Stremio Service installed successfully."
${Else}
DetailPrint "Failed to install Stremio Service (error: $R0)."
MessageBox MB_OK|MB_ICONEXCLAMATION "Error installing Stremio Service (error code: $R0)."
${EndIf}
SetDetailsPrint none
${EndIf}
${NSD_GetState} $AssociateTorrentCheckbox $checkbox_value
${If} $checkbox_value == ${BST_CHECKED}
!insertmacro APP_ASSOCIATE "torrent" "stremio" "BitTorrent file" "$INSTDIR\stremio.exe,0" "Play with Stremio" "$INSTDIR\stremio.exe $\"%1$\""
@ -229,10 +255,64 @@ Function fin_pg_leave
${EndIf}
FunctionEnd
!macro RemoveAllExceptDefaultProfile un
Function ${un}RemoveAllExceptDefaultProfile
; Hardcoded values for your scenario
StrCpy $R0 "Default" ; Directory to exclude
StrCpy $R1 "$INSTDIR\stremio.exe.WebView2\EBWebView" ; Root directory to operate on
Push $R2
Push $R3
Push $R4
ClearErrors
FindFirst $R3 $R2 "$R1\*.*"
IfErrors Exit
Top:
; Skip special directories "." and ".."
StrCmp $R2 "." Next
StrCmp $R2 ".." Next
; Skip the excluded directory
StrCmp $R2 $R0 Next
; Build full path for the current item
StrCpy $R4 "$R1\$R2"
; Check if the current item is a directory
IfFileExists "$R4\*.*" isDir notDir
notDir:
; It's a file, so delete it
Delete "$R4"
Goto Next
isDir:
; It's a directory, remove it recursively
RMDir /r "$R4"
Next:
ClearErrors
FindNext $R3 $R2
IfErrors Exit
Goto Top
Exit:
FindClose $R3
Pop $R4
Pop $R3
Pop $R2
FunctionEnd
!macroend
!insertmacro RemoveAllExceptDefaultProfile ""
!insertmacro RemoveAllExceptDefaultProfile "un."
; ---------------------------------------------------
; Removes everything from $INSTDIR except the
; "stremio.exe.WebView2" folder.
; "stremio.exe.WebView2\stremio.exe.WebView2\EBWebView" and "portable_config" folder.
; ---------------------------------------------------
!macro RemoveAllExceptWebView2 un
Function ${un}RemoveAllExceptWebView2
@ -254,6 +334,14 @@ Function ${un}RemoveAllExceptWebView2
StrCmp $R2 "." Next
StrCmp $R2 ".." Next
; Check if this items name begins with our backup folder prefix.
; Copy the first 23 characters ("portable_config_backup_") into $R5.
StrCpy $R5 $R2 23
StrCmp $R5 "portable_config_backup_" 0 notBackup
; If equal, skip deletion for this folder.
Goto next
notBackup:
; Skip the excluded directory
StrCmp $R2 $R0 Next
@ -286,6 +374,7 @@ Function ${un}RemoveAllExceptWebView2
Pop $R4
Pop $R3
Pop $R2
Call ${un}RemoveAllExceptDefaultProfile
FunctionEnd
!macroend
@ -413,6 +502,86 @@ done:
; --- End custom override logic ---
FunctionEnd
Var TIMESTAMP
Var day
Var month
Var year
Var day_name
Var hours
Var minutes
Var seconds
Function GetTimestamp
; Get local time.
${GetTime} "" "L" $day $month $year $day_name $hours $minutes $seconds
; Construct the timestamp string.
; Example: if day="01", month="04", year="2025", hours="16", minutes="05", seconds="50",
; the resulting string will be: "20250401_160550"
StrCpy $TIMESTAMP "$year$month$day_$hours$minutes$seconds"
FunctionEnd
Function BackupPortableConfig
; Check if portable_config exists; if so, back it up.
IfFileExists "$INSTDIR\portable_config\*.*" 0 backup_done
; Get the current timestamp (sets the global variable $TIMESTAMP)
Call GetTimestamp
; Rename portable_config to portable_config_backup_<TIMESTAMP>
Rename "$INSTDIR\portable_config" "$INSTDIR\portable_config_backup_$TIMESTAMP"
backup_done:
FunctionEnd
Function RemoveAll
; Prepare registers for deletion loop
Push $R2
Push $R3
Push $R4
Push $R5
ClearErrors
FindFirst $R3 $R2 "$INSTDIR\*.*"
IfErrors removeAllDone
loop:
; Skip special directories "." and ".."
StrCmp $R2 "." next
StrCmp $R2 ".." next
; Check if this items name begins with our backup folder prefix.
; Copy the first 23 characters ("portable_config_backup_") into $R5.
StrCpy $R5 $R2 23
StrCmp $R5 "portable_config_backup_" 0 notBackup
; If equal, skip deletion for this folder.
Goto next
notBackup:
; Build the full path of this item.
StrCpy $R4 "$INSTDIR\$R2"
; Check whether it's a file or a directory.
IfFileExists "$R4\*.*" isDir notDir
notDir:
Delete "$R4"
Goto next
isDir:
RMDir /r "$R4"
next:
ClearErrors
FindNext $R3 $R2
IfErrors removeAllDone
Goto loop
removeAllDone:
FindClose $R3
Pop $R5
Pop $R4
Pop $R3
Pop $R2
FunctionEnd
Section ; App Files
!insertmacro checkIfAppIsRunning "$(appIsRunningInstallError)"
@ -421,7 +590,16 @@ Section ; App Files
; Hide details
SetDetailsPrint None
Call RemoveAllExceptWebView2
; *** Prompt the user whether to delete all user data ***
IfSilent +3
MessageBox MB_YESNO|MB_ICONQUESTION "Install latest portable configuration? A backup of your portable_config folder will be created if it has been modified. Continue?" IDNO SkipDataDeletion
Call BackupPortableConfig
Call RemoveAllExceptWebView2
Goto DataDeletionDone
SkipDataDeletion:
Call RemoveAllExceptWebView2
DataDeletionDone:
;Set output path to InstallDir
SetOutPath "$INSTDIR"

Binary file not shown.

View file

@ -1,17 +1,17 @@
{
"shellVersion": "5.0.12",
"shellVersion": "5.0.21",
"files": {
"windows-x64": {
"url": "https://github.com/Zaarrg/stremio-desktop-v5/releases/download/5.0.0-beta.12/Stremio.5.0.12-x64.exe",
"checksum": "e7c045800d502874b8e083427aa81d316625c658fa804e67156dddd4f03ea6ed"
"url": "https://github.com/Zaarrg/stremio-desktop-v5/releases/download/5.0.0-beta.21/Stremio.5.0.21-x64.exe",
"checksum": "6b2597e3179355fb59b62df762d65dbe3e493f96471fa3cf17e1620fadd0a1d7"
},
"windows-x86": {
"url": "https://github.com/Zaarrg/stremio-desktop-v5/releases/download/5.0.0-beta.12/Stremio.5.0.12-x86.exe",
"checksum": "715ec5def305a019849b3a5e402398b53b5ed242f065266384f4428ed4c39818"
"url": "https://github.com/Zaarrg/stremio-desktop-v5/releases/download/5.0.0-beta.21/Stremio.5.0.21-x86.exe",
"checksum": "f2dfad202ae03b26a1d584d9a4e8747be6e0b078e6c6c5773d57632bdfe3aee0"
},
"server.js": {
"url": "https://dl.strem.io/server/v4.20.11/desktop/server.js",
"checksum": "d900b0525bac3531aa6ce98e1a3c8a3b1d1b1daa069a7f6fcbddea5625f1f791"
"url": "https://dl.strem.io/server/v4.20.15/desktop/server.js",
"checksum": "fcc4c5e620effda04c9e1d29a76aa087ec86fd08a747cdcbdccc5bb8f0ec4818"
}
}
}

View file

@ -1,5 +1,5 @@
{
"upToDate": false,
"versionDesc": "https://raw.githubusercontent.com/Zaarrg/stremio-desktop-v5/refs/heads/webview-windows/version/version-details.json",
"signature": "HPabSeveBkHa9ayQbtWU4vz0FEmAyErAMVQcaLjxSGzg5w/63K6UE3k76pS62usiUMPJXrxATxgq/KVUzHMHtGOxJyyOe//xp4IN2zBf4oae4paHdSMI2sRU2Yy5qzuw+kbygB3NKGUyfuRPOtf/kqoKhzx0jfAeZ6F2Q+7e4df6torYD0rPN6Vn0l1yIgtPBfcv5zrqxVIaLQV4AVFV76f4Hw/RFeHwf1JnNUTG0NwgSP17jV9vWA3aPiZCVVv5FCvOh2nrBMnpx66c44zg3XKlS4z0irjLeYBQWNJhB6lBnF5WpR6B23gcCnb+IiI3bZ3AmsmYki7xZtJS1dCKtA=="
"signature": "DfGpCnyvD/jWmw+hhdaAlay2sYvSpPsmsMDOrplWbvBYqZtwrfXLuZXnL+HkEP6kVclwRPBE2Kg2/2+UN3BP44Zn2N8UtGEMQLgu8TIAeq51JPUzv8ab9dumS8OXRHFG+x2sK4EjyobnIKJBm0nhpHzZyVuIXUIQsniynFyXdvRJxerZS9zXivJ9WgXNSgpM5tJt2xKqkuJtZ+Ckt//G3SeseC/vn4TehVX9d+aLGVM3pdLAnVferq9VV9iMZw8pQ+tK6HrhwzGP+sFsEIQsPNxFaLV1K1ODxKChnH2cYdLEjF62QlBilZG/SARn5NNRxTTGGCa/Guy4VZ30OsUh8A=="
}