ApplicationContext.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. #pragma once
  2. #include <cstdint>
  3. #include <filesystem>
  4. #include <map>
  5. #include <optional>
  6. #include <string>
  7. #include <vector>
  8. #include <glm/vec2.hpp>
  9. #include <glm/vec4.hpp>
  10. #include "ApplicationState.h"
  11. #include "WallpaperEngine/Data/JSON.h"
  12. #include "../Render/TextureProvider.h"
  13. #include "WallpaperEngine/Render/WallpaperState.h"
  14. #include "WallpaperEngine/Data/Model/Project.h"
  15. namespace WallpaperEngine::Application {
  16. using namespace WallpaperEngine::Data::Assets;
  17. class ApplicationContext {
  18. public:
  19. ApplicationContext (int argc, char* argv[]);
  20. void loadSettingsFromArgv ();
  21. /**
  22. * Resolves whether an object/layer should be force-shown or force-hidden based on the
  23. * --disable-object/--enable-object overrides, matching id or name against either.
  24. *
  25. * @return true to force visible, false to force hidden, nullopt to leave the scene's own value alone
  26. */
  27. [[nodiscard]] std::optional<bool> resolveObjectVisibility (int id, const std::string& name) const;
  28. /** true to force visible, false to force hidden, nullopt to leave the scene's own value, from --disable-effect/--enable-effect */
  29. [[nodiscard]] std::optional<bool> resolveEffectVisibility (int id, const std::string& name) const;
  30. /**
  31. * Resolves the --audio-sensitivity multiplier for an object/layer, matching id or name, or
  32. * falling back to a "*" wildcard default if one was given and no more specific match exists.
  33. *
  34. * @return the configured multiplier, or nullopt if this object has no override (use the
  35. * wallpaper's original minvalue/maxvalue unchanged)
  36. */
  37. [[nodiscard]] std::optional<float> resolveAudioSensitivity (int id, const std::string& name) const;
  38. /**
  39. * Resolves the --sound-volume override for a Sound object, matching id or name, or falling
  40. * back to a "*" wildcard default if one was given and no more specific match exists.
  41. *
  42. * @return the configured volume (0-1), or nullopt if this object has no override (use the
  43. * wallpaper's original volume unchanged)
  44. */
  45. [[nodiscard]] std::optional<float> resolveSoundVolume (int id, const std::string& name) const;
  46. enum WINDOW_MODE {
  47. NORMAL_WINDOW = 0,
  48. /** Draw to the window server desktop */
  49. DESKTOP_BACKGROUND = 1,
  50. EXPLICIT_WINDOW = 2,
  51. };
  52. /**
  53. * Wayland-only: which wlr-layer-shell layer to anchor the wallpaper surface to.
  54. * Different compositors treat layers differently; e.g. niri's
  55. * `place-within-backdrop` layer-rule only applies to BACKGROUND surfaces.
  56. */
  57. enum WAYLAND_LAYER {
  58. WAYLAND_LAYER_BACKGROUND = 0,
  59. WAYLAND_LAYER_BOTTOM = 1,
  60. WAYLAND_LAYER_TOP = 2,
  61. WAYLAND_LAYER_OVERLAY = 3,
  62. };
  63. struct PlaylistSettings {
  64. uint32_t delayMinutes = 60;
  65. std::string mode = "timer";
  66. std::string order = "sequential";
  67. bool updateOnPause = false;
  68. bool videoSequence = false;
  69. };
  70. struct PlaylistDefinition {
  71. std::string name;
  72. std::vector<std::filesystem::path> items;
  73. PlaylistSettings settings;
  74. };
  75. struct SpanGroup {
  76. std::vector<std::string> screens;
  77. std::filesystem::path background;
  78. WallpaperEngine::Render::WallpaperState::TextureUVsScaling scaling
  79. = WallpaperEngine::Render::WallpaperState::TextureUVsScaling::DefaultUVs;
  80. TextureFlags clamp = TextureFlags_ClampUVsBorder;
  81. /** Manual zoom factor layered on top of the scaling mode, see --zoom */
  82. float zoom = 1.0f;
  83. /** Re-centers a cropping scaling mode/zoom's visible window, see --offset */
  84. glm::vec2 offset = { 0.0f, 0.0f };
  85. /** Color shown outside the wallpaper's bounds when clamp is border, see --corner-color */
  86. glm::vec4 cornerColor = { 0.0f, 0.0f, 0.0f, 1.0f };
  87. };
  88. struct {
  89. struct {
  90. bool onlyListProperties;
  91. bool onlyListObjects;
  92. bool onlyListAudioObjects;
  93. bool onlyListEffects;
  94. bool dumpStructure;
  95. bool disableParticles;
  96. /** Grows a scene's render canvas to fit every image layer that extends past it, see --expand-canvas */
  97. bool expandCanvas;
  98. /** Objects/layers to force-hide, matched by id or name */
  99. std::vector<std::string> disabledObjects;
  100. /** Objects/layers to force-show, matched by id or name */
  101. std::vector<std::string> enabledObjects;
  102. /** Object effects (bloom, blur, glow, etc) to force-hide, matched by effect id or editor name */
  103. std::vector<std::string> disabledEffects;
  104. /** Object effects to force-show, matched by effect id or editor name */
  105. std::vector<std::string> enabledEffects;
  106. /** Audio-reactive pulse amplitude multiplier per object, matched by id or name; 0 = locked/no pulse */
  107. std::map<std::string, float> audioSensitivity;
  108. /** Sound object volume override (0-1), matched by id or name; see --sound-volume */
  109. std::map<std::string, float> soundVolume;
  110. std::filesystem::path assets;
  111. /** Background to load (provided as the final argument) as fallback for multi-screen setups */
  112. std::filesystem::path defaultBackground;
  113. std::map<std::string, std::filesystem::path> screenBackgrounds;
  114. std::map<std::string, std::string> properties;
  115. std::map<std::string, WallpaperEngine::Render::WallpaperState::TextureUVsScaling> screenScalings;
  116. std::map<std::string, TextureFlags> screenClamps;
  117. /** Manual zoom factor for different screens, layered on top of the scaling mode */
  118. std::map<std::string, float> screenZooms;
  119. /** Re-centers a cropping scaling mode/zoom's visible window for different screens, see --offset */
  120. std::map<std::string, glm::vec2> screenOffsets;
  121. /** Corner color for different screens, shown outside the wallpaper's bounds when clamp is border */
  122. std::map<std::string, glm::vec4> screenCornerColors;
  123. std::map<std::string, PlaylistDefinition> screenPlaylists;
  124. /** Playlist used in window mode */
  125. std::optional<PlaylistDefinition> defaultPlaylist;
  126. /** Span groups: multiple monitors sharing one stretched wallpaper */
  127. std::vector<SpanGroup> spanGroups;
  128. /**
  129. * Internal, not advertised in --help: marks this process as a disposable CEF host for a
  130. * single Web wallpaper instead of embedding CEF in the main engine process. Requires
  131. * webHostShm/Width/Height.
  132. */
  133. bool webHost;
  134. std::string webHostShm;
  135. uint32_t webHostWidth;
  136. uint32_t webHostHeight;
  137. /** Where SIGUSR1 hotswap requests are read from, see --control-file */
  138. std::optional<std::filesystem::path> controlFile;
  139. } general;
  140. struct {
  141. WINDOW_MODE mode;
  142. int maximumFPS;
  143. /** Global playback speed multiplier for animations, particles and effects, see --speed */
  144. float playbackSpeed;
  145. /** Freezes scene time entirely (scripts, particles, effects and puppet meshes all stop advancing), see --disable-animations */
  146. bool freezeAnimations;
  147. bool pauseOnFullscreen;
  148. /**
  149. * Wayland-only: if true, only consider fullscreen toplevels that are also activated.
  150. * Useful for compositors with "virtual" fullscreen windows (e.g. scrollable tiling).
  151. */
  152. bool pauseOnFullscreenOnlyWhenActive;
  153. /**
  154. * Wayland-only: list of app_id substrings to ignore for fullscreen pause.
  155. * Example: "firefox" will match "org.mozilla.firefox".
  156. */
  157. std::vector<std::string> fullscreenPauseIgnoreAppIds;
  158. struct {
  159. bool baseOnly;
  160. bool noSolidFinal;
  161. bool passLog;
  162. /** Logs mean scene brightness every 30 frames */
  163. bool brightnessLog;
  164. /** Renders puppets in their static bind pose, ignoring animation clips entirely */
  165. bool noPuppetAnimation;
  166. std::optional<int> objectFilter;
  167. std::vector<int> skipObjects;
  168. std::vector<int> skipEffects;
  169. } debug;
  170. struct {
  171. glm::ivec4 geometry;
  172. TextureFlags clamp;
  173. WallpaperEngine::Render::WallpaperState::TextureUVsScaling scalingMode;
  174. /** Manual zoom factor layered on top of scalingMode, see --zoom */
  175. float zoom;
  176. /** Re-centers a cropping scaling mode/zoom's visible window, see --offset */
  177. glm::vec2 offset;
  178. /** Corner color shown outside the wallpaper's bounds when clamp is border, see --corner-color */
  179. glm::vec4 cornerColor;
  180. } window;
  181. struct {
  182. WAYLAND_LAYER layer;
  183. } wayland;
  184. } render;
  185. struct {
  186. bool enabled;
  187. /** 0-128 */
  188. int volume;
  189. bool automute;
  190. bool audioprocessing;
  191. /** Only this screen (matches --screen-root names) produces audio; nullopt = no restriction */
  192. std::optional<std::string> audioScreen;
  193. /** 0-128, applied to non-video (scene sound + web) backgrounds instead of volume; nullopt = use volume */
  194. std::optional<int> ambientVolume;
  195. } audio;
  196. struct {
  197. bool enabled;
  198. bool disableparallax;
  199. /** Clamps parallax displacement so an image never slides past its own edges (no black corners) */
  200. bool clampParallaxToImageSize;
  201. } mouse;
  202. struct {
  203. bool take;
  204. /** In frames, not seconds */
  205. uint32_t delay;
  206. std::filesystem::path path;
  207. } screenshot;
  208. } settings = {
  209. .general = {
  210. .onlyListProperties = false,
  211. .onlyListObjects = false,
  212. .onlyListAudioObjects = false,
  213. .onlyListEffects = false,
  214. .dumpStructure = false,
  215. .disabledObjects = {},
  216. .enabledObjects = {},
  217. .disabledEffects = {},
  218. .enabledEffects = {},
  219. .audioSensitivity = {},
  220. .soundVolume = {},
  221. .assets = "",
  222. .defaultBackground = "",
  223. .screenBackgrounds = {},
  224. .properties = {},
  225. .screenScalings = {},
  226. .screenClamps = {},
  227. .screenZooms = {},
  228. .screenOffsets = {},
  229. .screenCornerColors = {},
  230. .screenPlaylists = {},
  231. .defaultPlaylist = std::nullopt,
  232. .spanGroups = {},
  233. .webHost = false,
  234. .webHostShm = "",
  235. .webHostWidth = 0,
  236. .webHostHeight = 0,
  237. .controlFile = std::nullopt,
  238. },
  239. .render = {
  240. .mode = NORMAL_WINDOW,
  241. .maximumFPS = 60,
  242. .playbackSpeed = 1.0f,
  243. .freezeAnimations = false,
  244. .pauseOnFullscreen = true,
  245. .pauseOnFullscreenOnlyWhenActive = false,
  246. .fullscreenPauseIgnoreAppIds = {},
  247. .debug = {
  248. .baseOnly = false,
  249. .noSolidFinal = false,
  250. .passLog = false,
  251. .brightnessLog = false,
  252. .noPuppetAnimation = false,
  253. .objectFilter = std::nullopt,
  254. .skipObjects = {},
  255. .skipEffects = {},
  256. },
  257. .window = {
  258. .geometry = {},
  259. .clamp = TextureFlags_ClampUVsBorder,
  260. .scalingMode = WallpaperEngine::Render::WallpaperState::TextureUVsScaling::DefaultUVs,
  261. .zoom = 1.0f,
  262. .offset = { 0.0f, 0.0f },
  263. .cornerColor = { 0.0f, 0.0f, 0.0f, 1.0f },
  264. },
  265. .wayland = {
  266. .layer = WAYLAND_LAYER_BOTTOM,
  267. },
  268. },
  269. .audio = {
  270. .enabled = true,
  271. .volume = 15,
  272. .automute = false,
  273. .audioprocessing = true,
  274. .audioScreen = std::nullopt,
  275. .ambientVolume = std::nullopt,
  276. },
  277. .mouse = {
  278. .enabled = true,
  279. .disableparallax = false,
  280. .clampParallaxToImageSize = true,
  281. },
  282. .screenshot = {
  283. .take = false,
  284. .delay = 5,
  285. .path = "",
  286. },
  287. };
  288. ApplicationState state;
  289. [[nodiscard]] int getArgc () const;
  290. [[nodiscard]] char** getArgv () const;
  291. private:
  292. int m_argc;
  293. char** m_argv;
  294. void validateAssets ();
  295. void validateScreenshot () const;
  296. static std::filesystem::path translateBackground (const std::string& bgIdOrPath);
  297. void loadPlaylistsFromConfig ();
  298. std::filesystem::path resolvePlaylistItemPath (const std::string& raw) const;
  299. std::filesystem::path configFilePath () const;
  300. std::optional<WallpaperEngine::Data::JSON::JSON> parseConfigJson (const std::filesystem::path& path) const;
  301. PlaylistSettings parsePlaylistSettings (const WallpaperEngine::Data::JSON::JSON& playlistJson) const;
  302. std::vector<std::filesystem::path>
  303. collectPlaylistItems (const WallpaperEngine::Data::JSON::JSON& playlistJson, const std::string& name) const;
  304. std::optional<PlaylistDefinition> buildPlaylistDefinition (
  305. const WallpaperEngine::Data::JSON::JSON& playlistJson, const std::string& fallbackName
  306. ) const;
  307. void registerPlaylist (PlaylistDefinition&& definition);
  308. [[nodiscard]] const PlaylistDefinition& getPlaylistFromConfig (const std::string& name);
  309. std::map<std::string, PlaylistDefinition> m_configPlaylists;
  310. bool m_loadedConfigPlaylists = false;
  311. };
  312. } // namespace WallpaperEngine::Application