Selaa lähdekoodia

Added support for running multiple X11 backgrounds off the same instance
Window mode now has extra settings for setting the position and size
Fixed audio not muting when --silent was used

Signed-off-by: Alexis Maiquez <almamu@almamu.com>

Alexis Maiquez 3 vuotta sitten
vanhempi
commit
b69ce8ba57
49 muutettua tiedostoa jossa 785 lisäystä ja 375 poistoa
  1. 6 0
      CMakeLists.txt
  2. 54 9
      src/WallpaperEngine/Application/CApplicationContext.cpp
  3. 13 2
      src/WallpaperEngine/Application/CApplicationContext.h
  4. 118 48
      src/WallpaperEngine/Application/CWallpaperApplication.cpp
  5. 12 6
      src/WallpaperEngine/Application/CWallpaperApplication.h
  6. 21 0
      src/WallpaperEngine/Assets/CCombinedContainer.cpp
  7. 1 0
      src/WallpaperEngine/Assets/CCombinedContainer.h
  8. 5 0
      src/WallpaperEngine/Assets/CContainer.cpp
  9. 9 0
      src/WallpaperEngine/Assets/CContainer.h
  10. 5 0
      src/WallpaperEngine/Assets/CDirectory.cpp
  11. 1 0
      src/WallpaperEngine/Assets/CDirectory.h
  12. 0 1
      src/WallpaperEngine/Audio/CAudioContext.cpp
  13. 1 1
      src/WallpaperEngine/Core/CObject.cpp
  14. 1 1
      src/WallpaperEngine/Core/CObject.h
  15. 3 3
      src/WallpaperEngine/Core/CProject.cpp
  16. 4 4
      src/WallpaperEngine/Core/CProject.h
  17. 3 3
      src/WallpaperEngine/Core/CScene.cpp
  18. 4 4
      src/WallpaperEngine/Core/CScene.h
  19. 2 2
      src/WallpaperEngine/Core/Objects/CEffect.cpp
  20. 2 2
      src/WallpaperEngine/Core/Objects/CEffect.h
  21. 1 1
      src/WallpaperEngine/Core/Objects/CImage.cpp
  22. 1 1
      src/WallpaperEngine/Core/Objects/CImage.h
  23. 1 3
      src/WallpaperEngine/Core/Objects/CParticle.cpp
  24. 1 1
      src/WallpaperEngine/Core/Objects/CParticle.h
  25. 2 2
      src/WallpaperEngine/Core/Objects/Images/CMaterial.cpp
  26. 2 2
      src/WallpaperEngine/Core/Objects/Images/CMaterial.h
  27. 2 2
      src/WallpaperEngine/FileSystem/FileSystem.cpp
  28. 1 1
      src/WallpaperEngine/FileSystem/FileSystem.h
  29. 1 0
      src/WallpaperEngine/Render/CFBO.h
  30. 1 1
      src/WallpaperEngine/Render/CObject.cpp
  31. 1 1
      src/WallpaperEngine/Render/CObject.h
  32. 39 229
      src/WallpaperEngine/Render/CRenderContext.cpp
  33. 14 29
      src/WallpaperEngine/Render/CRenderContext.h
  34. 21 3
      src/WallpaperEngine/Render/CTextureCache.cpp
  35. 4 1
      src/WallpaperEngine/Render/CVideo.cpp
  36. 2 2
      src/WallpaperEngine/Render/CWallpaper.cpp
  37. 1 1
      src/WallpaperEngine/Render/CWallpaper.h
  38. 6 0
      src/WallpaperEngine/Render/Drivers/COpenGLDriver.cpp
  39. 10 0
      src/WallpaperEngine/Render/Drivers/COpenGLDriver.h
  40. 2 0
      src/WallpaperEngine/Render/Drivers/CVideoDriver.h
  41. 23 0
      src/WallpaperEngine/Render/Drivers/Output/COutput.cpp
  42. 47 0
      src/WallpaperEngine/Render/Drivers/Output/COutput.h
  43. 77 0
      src/WallpaperEngine/Render/Drivers/Output/CWindowOutput.cpp
  44. 25 0
      src/WallpaperEngine/Render/Drivers/Output/CWindowOutput.h
  45. 183 0
      src/WallpaperEngine/Render/Drivers/Output/CX11Output.cpp
  46. 40 0
      src/WallpaperEngine/Render/Drivers/Output/CX11Output.h
  47. 5 2
      src/WallpaperEngine/Render/Objects/CSound.cpp
  48. 5 5
      src/WallpaperEngine/Render/Shaders/Compiler.cpp
  49. 2 2
      src/WallpaperEngine/Render/Shaders/Compiler.h

+ 6 - 0
CMakeLists.txt

@@ -105,6 +105,12 @@ add_executable(
     src/WallpaperEngine/Render/Shaders/Compiler.h
     src/WallpaperEngine/Render/Shaders/Compiler.cpp
 
+    src/WallpaperEngine/Render/Drivers/Output/COutput.cpp
+    src/WallpaperEngine/Render/Drivers/Output/COutput.h
+    src/WallpaperEngine/Render/Drivers/Output/CX11Output.cpp
+    src/WallpaperEngine/Render/Drivers/Output/CX11Output.h
+    src/WallpaperEngine/Render/Drivers/Output/CWindowOutput.cpp
+    src/WallpaperEngine/Render/Drivers/Output/CWindowOutput.h
     src/WallpaperEngine/Render/Drivers/COpenGLDriver.h
     src/WallpaperEngine/Render/Drivers/COpenGLDriver.cpp
     src/WallpaperEngine/Render/Drivers/CVideoDriver.h

+ 54 - 9
src/WallpaperEngine/Application/CApplicationContext.cpp

@@ -14,6 +14,8 @@ using namespace WallpaperEngine::Application;
 
 struct option long_options [] = {
     {"screen-root",     required_argument, nullptr, 'r'},
+	{"bg",				required_argument, nullptr, 'b'},
+	{"window",			optional_argument, nullptr, 'w'},
     {"pkg",             required_argument, nullptr, 'p'},
     {"dir",             required_argument, nullptr, 'd'},
     {"silent",          no_argument,       nullptr, 's'},
@@ -52,10 +54,21 @@ CApplicationContext::CApplicationContext (int argc, char* argv[]) :
 {
     int c;
 
-    while ((c = getopt_long (argc, argv, "r:p:d:shf:a:", long_options, nullptr)) != -1)
+	std::string lastScreen;
+
+    while ((c = getopt_long (argc, argv, "b:r:p:d:shf:a:w::", long_options, nullptr)) != -1)
     {
         switch (c)
         {
+			case 'b':
+				if (lastScreen.empty ())
+					sLog.exception ("--bg has to go after a --screen-root argument");
+
+				// no need to check for previous screen being in the list, as it's the only way for this variable
+				// to have any value
+				this->screenSettings.insert_or_assign (lastScreen, this->validatePath (optarg));
+				break;
+
             case 'o':
                 {
                     std::string value = optarg;
@@ -77,13 +90,41 @@ CApplicationContext::CApplicationContext (int argc, char* argv[]) :
                 break;
 
             case 'r':
-                screens.emplace_back (optarg);
+				if (this->screenSettings.find (optarg) != this->screenSettings.end ())
+					sLog.exception ("Cannot specify the same screen more than once: ", optarg);
+				if (this->windowMode == EXPLICIT_WINDOW)
+					sLog.exception ("Cannot run in both background and window mode");
+
+				this->windowMode = X11_BACKGROUND;
+				lastScreen = optarg;
+                this->screenSettings.insert_or_assign (lastScreen, "");
                 break;
 
+			case 'w':
+				if (this->windowMode == X11_BACKGROUND)
+					sLog.exception ("Cannot run in both background and window mode");
+
+				if (optarg != nullptr)
+				{
+					this->windowMode = EXPLICIT_WINDOW;
+					// read window geometry
+					char* pos = optarg;
+
+					if (pos != nullptr)
+						this->windowGeometry.x = atoi (pos);
+					if ((pos = strchr (pos, '.')) != nullptr)
+						this->windowGeometry.y = atoi (pos + 1);
+					if ((pos = strchr (pos + 1, '.')) != nullptr)
+						this->windowGeometry.z = atoi (pos + 1);
+					if ((pos = strchr (pos + 1, '.')) != nullptr)
+						this->windowGeometry.w = atoi (pos + 1);
+				}
+				break;
+
             case 'p':
             case 'd':
                 sLog.error ("--dir/--pkg is deprecated and not used anymore");
-                this->background = stringPathFixes (optarg);
+                this->background = this->validatePath (stringPathFixes (optarg));
                 break;
 
             case 's':
@@ -110,6 +151,10 @@ CApplicationContext::CApplicationContext (int argc, char* argv[]) :
                 this->takeScreenshot = true;
                 this->screenshot = stringPathFixes (optarg);
                 break;
+
+			default:
+				sLog.out ("Default on path parsing: ", optarg);
+				break;
         }
     }
 
@@ -117,7 +162,7 @@ CApplicationContext::CApplicationContext (int argc, char* argv[]) :
     {
         if (optind < argc && strlen (argv [optind]) > 0)
         {
-            this->background = argv [optind];
+            this->background = this->validatePath (argv [optind]);
         }
         else
         {
@@ -126,17 +171,16 @@ CApplicationContext::CApplicationContext (int argc, char* argv[]) :
     }
 
     // perform some extra validation on the inputs
-    this->validatePath ();
     this->validateAssets ();
     this->validateScreenshot ();
 }
 
-void CApplicationContext::validatePath ()
+std::string CApplicationContext::validatePath (const std::string& path)
 {
-    if (this->background.find ('/') != std::string::npos)
-        return;
+	if (path.find ('/') == std::string::npos)
+		return Steam::FileSystem::workshopDirectory (WORKSHOP_APP_ID, path);
 
-    this->background = Steam::FileSystem::workshopDirectory (WORKSHOP_APP_ID, this->background);
+	return path;
 }
 
 void CApplicationContext::validateAssets ()
@@ -191,6 +235,7 @@ void CApplicationContext::printHelp (const char* route)
     sLog.out ("\t--silent\t\t\t\t\tMutes all the sound the wallpaper might produce");
     sLog.out ("\t--volume <amount>\t\t\tSets the volume for all the sounds in the background");
     sLog.out ("\t--screen-root <screen name>\tDisplay as screen's background");
+	sLog.out ("\t--window <geometry>\tRuns in window mode, geometry has to be XxYxWxH");
     sLog.out ("\t--fps <maximum-fps>\t\t\tLimits the FPS to the given number, useful to keep battery consumption low");
     sLog.out ("\t--assets-dir <path>\t\t\tFolder where the assets are stored");
     sLog.out ("\t--screenshot\t\t\t\tTakes a screenshot of the background");

+ 13 - 2
src/WallpaperEngine/Application/CApplicationContext.h

@@ -6,6 +6,8 @@
 #include <string>
 #include <vector>
 
+#include <glm/vec4.hpp>
+
 namespace WallpaperEngine::Application
 {
     class CApplicationContext
@@ -13,7 +15,15 @@ namespace WallpaperEngine::Application
     public:
         CApplicationContext (int argc, char* argv[]);
 
-        std::vector <std::string> screens;
+		enum WINDOW_MODE
+		{
+			NORMAL_WINDOW = 0,
+			X11_BACKGROUND = 1,
+			EXPLICIT_WINDOW = 2,
+		};
+
+		glm::ivec4 windowGeometry;
+        std::map <std::string, std::string> screenSettings;
         std::map <std::string, std::string> properties;
         std::string background;
         std::filesystem::path assets;
@@ -24,9 +34,10 @@ namespace WallpaperEngine::Application
         bool audioEnabled;
         bool onlyListProperties;
         FREE_IMAGE_FORMAT screenshotFormat;
+		WINDOW_MODE windowMode;
 
     private:
-        void validatePath ();
+		std::string validatePath (const std::string& path);
         void validateAssets ();
         void validateScreenshot ();
         static void printHelp (const char* route);

+ 118 - 48
src/WallpaperEngine/Application/CWallpaperApplication.cpp

@@ -5,9 +5,13 @@
 #include "WallpaperEngine/Core/CVideo.h"
 #include "WallpaperEngine/Logging/CLog.h"
 #include "WallpaperEngine/Render/CRenderContext.h"
+#include "WallpaperEngine/Render/Drivers/Output/CX11Output.h"
+#include "WallpaperEngine/Render/Drivers/Output/CWindowOutput.h"
+#include "Steam/FileSystem/FileSystem.h"
 
 #include <unistd.h>
 
+
 float g_Time;
 float g_TimeLast;
 bool g_KeepRunning = true;
@@ -18,30 +22,32 @@ using namespace WallpaperEngine::Application;
 using namespace WallpaperEngine::Core;
 
 CWallpaperApplication::CWallpaperApplication (CApplicationContext& context) :
-    m_context (context)
+    m_context (context),
+	m_defaultProject (nullptr)
 {
     // copy state to global variables for now
     g_AudioVolume = context.audioVolume;
     g_AudioEnabled = context.audioEnabled;
-    this->setupContainer ();
-    this->loadProject ();
+    this->loadProjects ();
     this->setupProperties ();
 }
 
-void CWallpaperApplication::setupContainer ()
+void CWallpaperApplication::setupContainer (CCombinedContainer& container, const std::string& bg) const
 {
-    this->m_vfs.add (new CDirectory (this->m_context.background));
-    this->m_vfs.addPkg (std::filesystem::path (this->m_context.background) / "scene.pkg");
-    this->m_vfs.addPkg (std::filesystem::path (this->m_context.background) / "gifscene.pkg");
-    this->m_vfs.add (new CDirectory (this->m_context.assets));
+	std::filesystem::path basepath = bg;
+
+    container.add (new CDirectory (basepath));
+	container.addPkg (basepath / "scene.pkg");
+	container.addPkg (basepath / "gifscene.pkg");
+	container.add (new CDirectory (this->m_context.assets));
 #if !NDEBUG
-	this->m_vfs.add (new CDirectory ("../share/"));
+	container.add (new CDirectory ("../share/"));
 #else
 	this->m_vfs.add (new CDirectory (DATADIR));
 #endif /* DEBUG */
 
     // TODO: move this somewhere else?
-    CVirtualContainer* container = new CVirtualContainer ();
+    CVirtualContainer* virtualContainer = new CVirtualContainer ();
 
     //
     // Had to get a little creative with the effects to achieve the same bloom effect without any custom code
@@ -50,7 +56,7 @@ void CWallpaperApplication::setupContainer ()
     //
 
     // add the effect file for screen bloom
-    container->add (
+	virtualContainer->add (
         "effects/wpenginelinux/bloomeffect.json",
         "{"
         "\t\"name\":\"camerabloom_wpengine_linux\","
@@ -111,7 +117,7 @@ void CWallpaperApplication::setupContainer ()
     );
 
     // add some model for the image element even if it's going to waste rendering cycles
-    container->add (
+	virtualContainer->add (
         "models/wpenginelinux.json",
         "{"
         "\t\"material\":\"materials/wpenginelinux.json\""
@@ -119,7 +125,7 @@ void CWallpaperApplication::setupContainer ()
     );
 
     // models require materials, so add that too
-    container->add (
+	virtualContainer->add (
         "materials/wpenginelinux.json",
         "{"
         "\t\"passes\":"
@@ -136,47 +142,74 @@ void CWallpaperApplication::setupContainer ()
         "}"
     );
 
-    this->m_vfs.add (container);
+	container.add (virtualContainer);
 }
 
-void CWallpaperApplication::loadProject ()
+void CWallpaperApplication::loadProjects ()
 {
-    this->m_project = CProject::fromFile ("project.json", this->m_vfs);
-    // go to the right folder so the videos will play
-    // TODO: stop doing chdir and use full path
-    if (this->m_project->getWallpaper ()->is <WallpaperEngine::Core::CVideo> ())
-        chdir (this->m_context.background.c_str ());
+	for (const auto& it : this->m_context.screenSettings)
+	{
+		// ignore the screen settings if there was no background specified
+		// the default will be used
+		if (it.second.empty())
+			continue;
+
+		this->m_projects.insert_or_assign (
+			it.first,
+			this->loadProject (it.second)
+		);
+	}
+
+	// load the default project if required
+	if (!this->m_context.background.empty ())
+		this->m_defaultProject = this->loadProject (this->m_context.background);
 }
 
-void CWallpaperApplication::setupProperties ()
+CProject* CWallpaperApplication::loadProject (const std::string& bg)
 {
-    // show properties if required
-    for (auto cur : this->m_project->getProperties ())
-    {
-        // update the value of the property
-        auto override = this->m_context.properties.find (cur->getName ());
+	CCombinedContainer* container = new CCombinedContainer ();
 
-        if (override != this->m_context.properties.end ())
-        {
-            sLog.out ("Applying override value for ", cur->getName ());
+	this->setupContainer (*container, bg);
 
-            cur->update (override->second);
-        }
+	// TODO: Change this to pointer instead of reference
+    return CProject::fromFile ("project.json", container);
+}
 
-        if (this->m_context.onlyListProperties)
-            sLog.out (cur->dump ());
-    }
+void CWallpaperApplication::setupPropertiesForProject (CProject* project)
+{
+	// show properties if required
+	for (auto cur : project->getProperties ())
+	{
+		// update the value of the property
+		auto override = this->m_context.properties.find (cur->getName ());
+
+		if (override != this->m_context.properties.end ())
+		{
+			sLog.out ("Applying override value for ", cur->getName ());
+
+			cur->update (override->second);
+		}
+
+		if (this->m_context.onlyListProperties)
+			sLog.out (cur->dump ());
+	}
+}
+
+void CWallpaperApplication::setupProperties ()
+{
+	for (const auto& it : this->m_projects)
+		this->setupPropertiesForProject (it.second);
+
+	if (this->m_defaultProject != nullptr)
+		this->setupPropertiesForProject (this->m_defaultProject);
 }
 
-void CWallpaperApplication::takeScreenshot (WallpaperEngine::Render::CWallpaper* wp, const std::filesystem::path& filename, FREE_IMAGE_FORMAT format)
+void CWallpaperApplication::takeScreenshot (const Render::CRenderContext& context, const std::filesystem::path& filename, FREE_IMAGE_FORMAT format)
 {
-    GLint width, height;
+	// this should be getting called at the end of the frame, so the right thing should be bound already
 
-    // bind texture and get the size
-    glBindFramebuffer (GL_FRAMEBUFFER, wp->getWallpaperFramebuffer ());
-    glBindTexture (GL_TEXTURE_2D, wp->getWallpaperTexture ());
-    glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
-    glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
+	int width = context.getOutput ()->getFullWidth ();
+	int height = context.getOutput ()->getFullHeight ();
 
     // make room for storing the pixel data
     uint8_t* buffer = new uint8_t [width * height * sizeof (uint8_t) * 3];
@@ -222,15 +255,42 @@ void CWallpaperApplication::show ()
     // initialize audio context
     WallpaperEngine::Audio::CAudioContext audioContext (audioDriver);
     // initialize OpenGL driver
-    WallpaperEngine::Render::Drivers::COpenGLDriver videoDriver (this->m_project->getTitle ().c_str ());
+    WallpaperEngine::Render::Drivers::COpenGLDriver videoDriver ("wallpaperengine");
     // initialize the input subsystem
     WallpaperEngine::Input::CInputContext inputContext (videoDriver);
+	// output requested
+	WallpaperEngine::Render::Drivers::Output::COutput* output;
+
+	// initialize the requested output
+	switch (this->m_context.windowMode)
+	{
+		case CApplicationContext::EXPLICIT_WINDOW:
+		case CApplicationContext::NORMAL_WINDOW:
+			output = new WallpaperEngine::Render::Drivers::Output::CWindowOutput (this->m_context, videoDriver);
+			break;
+
+		case CApplicationContext::X11_BACKGROUND:
+			output = new WallpaperEngine::Render::Drivers::Output::CX11Output (this->m_context, videoDriver);
+			break;
+	}
+
     // initialize render context
-    WallpaperEngine::Render::CRenderContext context (this->m_context.screens, videoDriver, inputContext, this->m_vfs, *this);
-    // ensure the context knows what wallpaper to render
-    context.setWallpaper (
-        WallpaperEngine::Render::CWallpaper::fromWallpaper (this->m_project->getWallpaper (), context, audioContext)
-    );
+    WallpaperEngine::Render::CRenderContext context (output, videoDriver, inputContext, *this);
+
+	// set all the specific wallpapers required
+	for (const auto& it : this->m_projects)
+	{
+		context.setWallpaper (
+			it.first,
+			WallpaperEngine::Render::CWallpaper::fromWallpaper (it.second->getWallpaper (), context, audioContext)
+		);
+	}
+
+    // set the default rendering wallpaper if available
+	if (this->m_defaultProject != nullptr)
+		context.setDefaultWallpaper (
+			WallpaperEngine::Render::CWallpaper::fromWallpaper (this->m_defaultProject->getWallpaper (), context, audioContext)
+		);
 
     float startTime, endTime, minimumTime = 1.0f / this->m_context.maximumFPS;
 
@@ -255,7 +315,7 @@ void CWallpaperApplication::show ()
 
         if (this->m_context.takeScreenshot && videoDriver.getFrameCounter () == 5)
         {
-            this->takeScreenshot (context.getWallpaper (), this->m_context.screenshot, this->m_context.screenshotFormat);
+            this->takeScreenshot (context, this->m_context.screenshot, this->m_context.screenshotFormat);
             // disable screenshot just in case the counter overflows
             this->m_context.takeScreenshot = false;
         }
@@ -272,4 +332,14 @@ void CWallpaperApplication::show ()
 void CWallpaperApplication::signal (int signal)
 {
     g_KeepRunning = false;
+}
+
+const std::map <std::string, CProject*>& CWallpaperApplication::getProjects () const
+{
+	return this->m_projects;
+}
+
+CProject* CWallpaperApplication::getDefaultProject () const
+{
+	return this->m_defaultProject;
 }

+ 12 - 6
src/WallpaperEngine/Application/CWallpaperApplication.h

@@ -5,10 +5,12 @@
 #include "WallpaperEngine/Assets/CCombinedContainer.h"
 #include "WallpaperEngine/Core/CProject.h"
 #include "WallpaperEngine/Render/CWallpaper.h"
+#include "WallpaperEngine/Render/CRenderContext.h"
 
 namespace WallpaperEngine::Render
 {
     class CWallpaper;
+	class CRenderContext;
 }
 
 namespace WallpaperEngine::Application
@@ -22,15 +24,19 @@ namespace WallpaperEngine::Application
 
         void show ();
         void signal (int signal);
+		const std::map <std::string, Core::CProject*>& getProjects () const;
+		Core::CProject* getDefaultProject () const;
 
-    private:
-        void setupContainer ();
-        void loadProject ();
+	private:
+        void setupContainer (CCombinedContainer& container, const std::string& bg) const;
+		void loadProjects ();
+        Core::CProject* loadProject (const std::string& bg);
         void setupProperties ();
-        void takeScreenshot (WallpaperEngine::Render::CWallpaper* wp, const std::filesystem::path& filename, FREE_IMAGE_FORMAT format);
+		void setupPropertiesForProject (Core::CProject* project);
+        void takeScreenshot (const Render::CRenderContext& context, const std::filesystem::path& filename, FREE_IMAGE_FORMAT format);
 
-        Core::CProject* m_project;
+        Core::CProject* m_defaultProject;
         CApplicationContext& m_context;
-        CCombinedContainer m_vfs;
+		std::map <std::string, Core::CProject*> m_projects;
     };
 }

+ 21 - 0
src/WallpaperEngine/Assets/CCombinedContainer.cpp

@@ -37,6 +37,27 @@ void CCombinedContainer::addPkg (const std::filesystem::path& path)
     }
 }
 
+
+std::filesystem::path CCombinedContainer::resolveRealFile (std::string filename) const
+{
+    for (auto cur : this->m_containers)
+    {
+        try
+        {
+            // try to read the file on the current container, if the file doesn't exists
+            // an exception will be thrown
+            return cur->resolveRealFile (filename);
+        }
+        catch (CAssetLoadException& ex)
+        {
+            // not found in this container, next try
+        }
+    }
+
+    // no container was able to load the file, abort!
+    throw CAssetLoadException (filename, "Cannot resolve file in any of the containers");
+}
+
 const void* CCombinedContainer::readFile (std::string filename, uint32_t* length) const
 {
     for (auto cur : this->m_containers)

+ 1 - 0
src/WallpaperEngine/Assets/CCombinedContainer.h

@@ -21,6 +21,7 @@ namespace WallpaperEngine::Assets
         void add (CContainer* container);
         void addPkg (const std::filesystem::path& path);
 
+		std::filesystem::path resolveRealFile (std::string filename) const override;
         const void* readFile (std::string filename, uint32_t* length = nullptr) const override;
 
     private:

+ 5 - 0
src/WallpaperEngine/Assets/CContainer.cpp

@@ -9,6 +9,11 @@
 
 using namespace WallpaperEngine::Assets;
 
+std::filesystem::path CContainer::resolveRealFile (std::string filename) const
+{
+	throw CAssetLoadException (filename, "Cannot resolve physical file in this container");
+}
+
 const ITexture* CContainer::readTexture (std::string filename) const
 {
     // get the texture's filename (usually .tex)

+ 9 - 0
src/WallpaperEngine/Assets/CContainer.h

@@ -1,5 +1,6 @@
 #pragma once
 
+#include <filesystem>
 #include <string>
 #include "WallpaperEngine/Assets/ITexture.h"
 
@@ -8,6 +9,14 @@ namespace WallpaperEngine::Assets
     class CContainer
     {
     public:
+		/**
+		 * Resolves the full path to the specified file in the filesystem
+		 *
+		 * @param filename
+		 * @return
+		 */
+		virtual std::filesystem::path resolveRealFile (std::string filename) const;
+
         /**
          * Reads the given file from the container and returns it's data
          * Additionally sets a length parameter to return back the file's length

+ 5 - 0
src/WallpaperEngine/Assets/CDirectory.cpp

@@ -24,6 +24,11 @@ CDirectory::CDirectory (std::filesystem::path  basepath) :
 CDirectory::~CDirectory ()
 = default;
 
+std::filesystem::path CDirectory::resolveRealFile (std::string filename) const
+{
+	return std::filesystem::path (this->m_basepath) / filename;
+}
+
 const void* CDirectory::readFile (std::string filename, uint32_t* length) const
 {
     std::filesystem::path final = std::filesystem::path (this->m_basepath) / filename;

+ 1 - 0
src/WallpaperEngine/Assets/CDirectory.h

@@ -16,6 +16,7 @@ namespace WallpaperEngine::Assets
         explicit CDirectory (std::filesystem::path basepath);
         ~CDirectory ();
 
+		std::filesystem::path resolveRealFile (std::string filename) const override;
         const void* readFile (std::string filename, uint32_t* length) const override;
     private:
         std::filesystem::path m_basepath;

+ 0 - 1
src/WallpaperEngine/Audio/CAudioContext.cpp

@@ -7,7 +7,6 @@ using namespace WallpaperEngine::Audio::Drivers;
 CAudioContext::CAudioContext (CAudioDriver& driver) :
     m_driver (driver)
 {
-
 }
 
 void CAudioContext::addStream (CAudioStream* stream)

+ 1 - 1
src/WallpaperEngine/Core/CObject.cpp

@@ -35,7 +35,7 @@ CObject::CObject (
 {
 }
 
-CObject* CObject::fromJSON (json data, CScene* scene, const CContainer& container)
+CObject* CObject::fromJSON (json data, CScene* scene, CContainer* container)
 {
     std::string json = data.dump ();
 

+ 1 - 1
src/WallpaperEngine/Core/CObject.h

@@ -33,7 +33,7 @@ namespace WallpaperEngine::Core
     {
         friend class CScene;
     public:
-        static CObject* fromJSON (json data, CScene* scene, const CContainer& container);
+        static CObject* fromJSON (json data, CScene* scene, CContainer* container);
 
         template<class T> const T* as () const { assert (is <T> ()); return (const T*) this; }
         template<class T> T* as () { assert (is <T> ()); return (T*) this; }

+ 3 - 3
src/WallpaperEngine/Core/CProject.cpp

@@ -9,14 +9,14 @@
 using namespace WallpaperEngine::Core;
 using namespace WallpaperEngine::Assets;
 
-CProject::CProject (std::string title, std::string type, CContainer& container) :
+CProject::CProject (std::string title, std::string type, CContainer* container) :
     m_title (std::move (title)),
     m_type (std::move (type)),
     m_container (container)
 {
 }
 
-CProject* CProject::fromFile (const std::string& filename, CContainer& container)
+CProject* CProject::fromFile (const std::string& filename, CContainer* container)
 {
     json content = json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container));
 
@@ -85,7 +85,7 @@ const std::vector<Projects::CProperty*>& CProject::getProperties () const
     return this->m_properties;
 }
 
-CContainer& CProject::getContainer ()
+CContainer* CProject::getContainer ()
 {
     return this->m_container;
 }

+ 4 - 4
src/WallpaperEngine/Core/CProject.h

@@ -16,7 +16,7 @@ namespace WallpaperEngine::Core
     class CProject
     {
     public:
-        static CProject* fromFile (const std::string& filename, CContainer& container);
+        static CProject* fromFile (const std::string& filename, CContainer* container);
 
         CWallpaper* getWallpaper () const;
 
@@ -24,10 +24,10 @@ namespace WallpaperEngine::Core
         const std::string& getType () const;
         const std::vector<Projects::CProperty*>& getProperties () const;
 
-        CContainer& getContainer ();
+        CContainer* getContainer ();
 
     protected:
-        CProject (std::string title, std::string type, CContainer& container);
+        CProject (std::string title, std::string type, CContainer* container);
 
 		void setWallpaper (CWallpaper* wallpaper);
         void insertProperty (Projects::CProperty* property);
@@ -37,6 +37,6 @@ namespace WallpaperEngine::Core
         std::string m_title;
         std::string m_type;
         CWallpaper* m_wallpaper;
-        CContainer& m_container;
+        CContainer* m_container;
     };
 }

+ 3 - 3
src/WallpaperEngine/Core/CScene.cpp

@@ -10,7 +10,7 @@ using namespace WallpaperEngine::Core;
 
 CScene::CScene (
 		CProject& project,
-        CContainer& container,
+        CContainer* container,
         Scenes::CCamera* camera,
         glm::vec3 ambientColor,
         CUserSettingBoolean* bloom,
@@ -52,7 +52,7 @@ CScene::CScene (
 {
 }
 
-CScene* CScene::fromFile (const std::string& filename, CProject& project, CContainer& container)
+CScene* CScene::fromFile (const std::string& filename, CProject& project, CContainer* container)
 {
     std::string stringContent = WallpaperEngine::FileSystem::loadFullFile (filename, container);
     json content = json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container));
@@ -128,7 +128,7 @@ void CScene::insertObject (CObject* object)
     }
 }
 
-CContainer& CScene::getContainer ()
+CContainer* CScene::getContainer ()
 {
     return this->m_container;
 }

+ 4 - 4
src/WallpaperEngine/Core/CScene.h

@@ -17,7 +17,7 @@ namespace WallpaperEngine::Core
     class CScene : public CWallpaper
     {
     public:
-        static CScene* fromFile (const std::string& filename, CProject& project, CContainer& container);
+        static CScene* fromFile (const std::string& filename, CProject& project, CContainer* container);
 
         const std::map<uint32_t, CObject*>& getObjects () const;
         const std::vector<CObject*>& getObjectsByRenderOrder () const;
@@ -46,7 +46,7 @@ namespace WallpaperEngine::Core
 
         CScene (
 				CProject& project,
-                CContainer& container,
+                CContainer* container,
                 Scenes::CCamera* camera,
                 glm::vec3 ambientColor,
                 CUserSettingBoolean* bloom,
@@ -71,9 +71,9 @@ namespace WallpaperEngine::Core
 
         void insertObject (CObject* object);
 
-        CContainer& getContainer ();
+        CContainer* getContainer ();
     private:
-        CContainer& m_container;
+        CContainer* m_container;
         Scenes::CCamera* m_camera;
 
         // data from general section on the json

+ 2 - 2
src/WallpaperEngine/Core/Objects/CEffect.cpp

@@ -36,7 +36,7 @@ CEffect::CEffect (
 {
 }
 
-CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, Core::CObject* object, const CContainer& container)
+CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, Core::CObject* object, CContainer* container)
 {
     auto file_it = jsonFindRequired (data, "file", "Object effect must have a file");
     auto effectpasses_it = data.find ("passes");
@@ -202,7 +202,7 @@ void CEffect::dependencyFromJSON (json::const_iterator dependencies_it, CEffect*
         effect->insertDependency (cur);
 }
 
-void CEffect::materialsFromJSON (json::const_iterator passes_it, CEffect* effect, const CContainer& container)
+void CEffect::materialsFromJSON (json::const_iterator passes_it, CEffect* effect, CContainer* container)
 {
     for (const auto& cur : (*passes_it))
     {

+ 2 - 2
src/WallpaperEngine/Core/Objects/CEffect.h

@@ -35,7 +35,7 @@ namespace WallpaperEngine::Core::Objects
             CUserSettingBoolean* visible
         );
 
-        static CEffect* fromJSON (json data, CUserSettingBoolean* visible, Core::CObject* object, const CContainer& container);
+        static CEffect* fromJSON (json data, CUserSettingBoolean* visible, Core::CObject* object, CContainer* container);
 
         const std::vector<std::string>& getDependencies () const;
         const std::vector<Images::CMaterial*>& getMaterials () const;
@@ -48,7 +48,7 @@ namespace WallpaperEngine::Core::Objects
         static void combosFromJSON (json::const_iterator combos_it, Core::Objects::Images::Materials::CPass* pass);
         static void fbosFromJSON (json::const_iterator fbos_it, CEffect* effect);
         static void dependencyFromJSON (json::const_iterator dependencies_it, CEffect* effect);
-        static void materialsFromJSON (json::const_iterator passes_it, CEffect* effect, const CContainer& container);
+        static void materialsFromJSON (json::const_iterator passes_it, CEffect* effect, CContainer* container);
 
         void insertDependency (const std::string& dep);
         void insertMaterial (Images::CMaterial* material);

+ 1 - 1
src/WallpaperEngine/Core/Objects/CImage.cpp

@@ -44,7 +44,7 @@ CImage::CImage (
 WallpaperEngine::Core::CObject* CImage::fromJSON (
     CScene* scene,
     json data,
-    const CContainer& container,
+    CContainer* container,
     CUserSettingBoolean* visible,
     uint32_t id,
     std::string name,

+ 1 - 1
src/WallpaperEngine/Core/Objects/CImage.h

@@ -29,7 +29,7 @@ namespace WallpaperEngine::Core::Objects
         static CObject* fromJSON (
             CScene* scene,
             json data,
-            const CContainer& container,
+            CContainer* container,
             CUserSettingBoolean* visible,
             uint32_t id,
             std::string name,

+ 1 - 3
src/WallpaperEngine/Core/Objects/CParticle.cpp

@@ -8,7 +8,7 @@ using namespace WallpaperEngine::Core::Objects;
 CParticle* CParticle::fromFile (
     CScene* scene,
     const std::string& filename,
-    const CContainer& container,
+    CContainer* container,
     CUserSettingBoolean* visible,
     uint32_t id,
     std::string name,
@@ -34,10 +34,8 @@ CParticle* CParticle::fromFile (
     );
 
     if (controlpoint_it != data.end ())
-    {
         for (const auto& cur : (*controlpoint_it))
             particle->insertControlPoint (Particles::CControlPoint::fromJSON (cur));
-    }
 
     for (const auto& cur : (*emitter_it))
         particle->insertEmitter (Particles::CEmitter::fromJSON (cur));

+ 1 - 1
src/WallpaperEngine/Core/Objects/CParticle.h

@@ -19,7 +19,7 @@ namespace WallpaperEngine::Core::Objects
         static CParticle* fromFile (
                 CScene* scene,
                 const std::string& filename,
-                const CContainer& container,
+                CContainer* container,
                 CUserSettingBoolean* visible,
                 uint32_t id,
                 std::string name,

+ 2 - 2
src/WallpaperEngine/Core/Objects/Images/CMaterial.cpp

@@ -16,13 +16,13 @@ CMaterial::CMaterial (std::string  name) :
 {
 }
 
-CMaterial* CMaterial::fromFile (const std::string& filename, const CContainer& container)
+CMaterial* CMaterial::fromFile (const std::string& filename, CContainer* container)
 {
     return fromJSON (
         filename, json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container))
     );
 }
-CMaterial* CMaterial::fromFile (const std::string& filename, const std::string& target, const CContainer& container)
+CMaterial* CMaterial::fromFile (const std::string& filename, const std::string& target, CContainer* container)
 {
     return fromJSON (
         filename, json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container)), target

+ 2 - 2
src/WallpaperEngine/Core/Objects/Images/CMaterial.h

@@ -14,9 +14,9 @@ namespace WallpaperEngine::Core::Objects::Images
     class CMaterial
     {
     public:
-        static CMaterial* fromFile (const std::string& filename, const CContainer& container);
+        static CMaterial* fromFile (const std::string& filename, CContainer* container);
         static CMaterial* fromJSON (const std::string& name, json data);
-        static CMaterial* fromFile (const std::string& filename, const std::string& target, const CContainer& container);
+        static CMaterial* fromFile (const std::string& filename, const std::string& target, CContainer* container);
         static CMaterial* fromJSON (const std::string& name, json data, const std::string& target);
 
         void insertPass (Materials::CPass* mass);

+ 2 - 2
src/WallpaperEngine/FileSystem/FileSystem.cpp

@@ -5,10 +5,10 @@
 
 using namespace WallpaperEngine;
 
-std::string FileSystem::loadFullFile (const std::string& file, const WallpaperEngine::Assets::CContainer& containers)
+std::string FileSystem::loadFullFile (const std::string& file, WallpaperEngine::Assets::CContainer* containers)
 {
     uint32_t length = 0;
-    const void* contents = containers.readFile (file, &length);
+    const void* contents = containers->readFile (file, &length);
 
     // build a new buffer that can fit in the string
     char* filedata = new char [length + 1];

+ 1 - 1
src/WallpaperEngine/FileSystem/FileSystem.h

@@ -17,5 +17,5 @@ namespace WallpaperEngine::FileSystem
      * @param file
      * @return
      */
-    std::string loadFullFile (const std::string& file, const WallpaperEngine::Assets::CContainer& containers);
+    std::string loadFullFile (const std::string& file, WallpaperEngine::Assets::CContainer* containers);
 }

+ 1 - 0
src/WallpaperEngine/Render/CFBO.h

@@ -12,6 +12,7 @@ namespace WallpaperEngine::Render
     {
     public:
         CFBO (std::string name, ITexture::TextureFormat format, ITexture::TextureFlags flags, float scale, uint32_t realWidth, uint32_t realHeight, uint32_t textureWidth, uint32_t textureHeight);
+		// TODO: ADD DESTRUCTOR TO FREE RESOURCES
 
         const std::string& getName () const;
         const float& getScale () const;

+ 1 - 1
src/WallpaperEngine/Render/CObject.cpp

@@ -20,7 +20,7 @@ CScene* CObject::getScene () const
     return this->m_scene;
 }
 
-const CContainer& CObject::getContainer () const
+CContainer* CObject::getContainer () const
 {
     return this->getScene ()->getContainer ();
 }

+ 1 - 1
src/WallpaperEngine/Render/CObject.h

@@ -21,7 +21,7 @@ namespace WallpaperEngine::Render
         virtual void render () = 0;
 
         CScene* getScene () const;
-        const CContainer& getContainer () const;
+        CContainer* getContainer () const;
         int getId () const;
 
     protected:

+ 39 - 229
src/WallpaperEngine/Render/CRenderContext.cpp

@@ -12,190 +12,39 @@
 #include "CRenderContext.h"
 #include "CVideo.h"
 
-#define DEFAULT_WINDOW_WIDTH 1280
-#define DEFAULT_WINDOW_HEIGHT 720
-
 using namespace WallpaperEngine::Render;
 
-XErrorHandler originalErrorHandler;
-
-void CustomXIOErrorExitHandler (Display* dsp, void* userdata)
-{
-    auto context = static_cast <CRenderContext*> (userdata);
-
-#if !NDEBUG
-    sLog.debugerror ("Critical XServer error detected. Attempting to recover...");
-#endif /* DEBUG */
-
-    // refetch all the resources
-    context->initialize ();
-}
-
-int CustomXErrorHandler (Display* dpy, XErrorEvent* event)
-{
-#if !NDEBUG
-    sLog.debugerror ("Detected X error");
-#endif /* DEBUG */
-
-    // call the original handler so we can keep some information reporting
-    originalErrorHandler (dpy, event);
-
-    return 0;
-}
-
-int CustomXIOErrorHandler (Display* dsp)
-{
-#if !NDEBUG
-    sLog.debugerror ("Detected X error");
-#endif /* DEBUG */
-
-    return 0;
-}
-
-CRenderContext::CRenderContext (std::vector <std::string> screens, CVideoDriver& driver, CInputContext& input, CContainer& container, CWallpaperApplication& app) :
-    m_wallpaper (nullptr),
-    m_screens (std::move (screens)),
-    m_driver (driver),
-    m_container (container),
-    m_app (app),
-    m_input (input),
-    m_textureCache (new CTextureCache (*this)),
-	m_display (nullptr),
-	m_pixmap (0),
-	m_gc (nullptr),
-	m_image (nullptr),
-	m_imageData (nullptr),
-	m_fbo (nullptr)
-{
-    this->initialize ();
-}
-
-void CRenderContext::initialize ()
-{
-    if (this->m_screens.empty ())
-        this->setupWindow ();
-    else
-        this->setupScreens ();
-}
-
-void CRenderContext::setupWindow ()
-{
-    this->m_driver.showWindow ();
-    this->m_driver.resizeWindow ({DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT});
-}
-
-void CRenderContext::setupScreens ()
-{
-    this->m_viewports.clear ();
-
-    this->m_display = XOpenDisplay (nullptr);
-
-    // set the error handling to try and recover from X disconnections
-#ifdef HAVE_XSETIOERROREXITHANDLER
-    XSetIOErrorExitHandler (this->m_display, CustomXIOErrorExitHandler, this);
-#endif /* HAVE_XSETIOERROREXITHANDLER */
-    originalErrorHandler = XSetErrorHandler (CustomXErrorHandler);
-    XSetIOErrorHandler (CustomXIOErrorHandler);
-
-    int xrandr_result, xrandr_error;
-
-    if (!XRRQueryExtension (this->m_display, &xrandr_result, &xrandr_error))
-    {
-        sLog.error ("XRandr is not present, cannot detect specified screens, running in window mode");
-        return;
-    }
-
-    Window root = DefaultRootWindow (this->m_display);
-    int fullWidth = DisplayWidth (this->m_display, DefaultScreen (this->m_display));
-    int fullHeight = DisplayHeight (this->m_display, DefaultScreen (this->m_display));
-    XRRScreenResources* screenResources = XRRGetScreenResources (this->m_display, DefaultRootWindow (this->m_display));
-
-    // there are some situations where xrandr returns null (like screen not using the extension)
-    if (screenResources == nullptr)
-        return;
-
-    // create the pixmap and gc used for this display, most situations only have one "display"
-    this->m_pixmap = XCreatePixmap (this->m_display, DefaultRootWindow (this->m_display), fullWidth, fullHeight, 24);
-    this->m_gc = XCreateGC (this->m_display, this->m_pixmap, 0, nullptr);
-    // fill the whole pixmap with black for now
-    XFillRectangle (this->m_display, this->m_pixmap, this->m_gc, 0, 0, fullWidth, fullHeight);
-
-    for (int i = 0; i < screenResources->noutput; i ++)
-    {
-        XRROutputInfo* info = XRRGetOutputInfo (this->m_display, screenResources, screenResources->outputs [i]);
-
-        // there are some situations where xrandr returns null (like screen not using the extension)
-        if (info == nullptr || info->connection != RR_Connected)
-            continue;
-
-        for (const auto& cur : this->m_screens)
-        {
-            if (strcmp (info->name, cur.c_str ()) != 0)
-                continue;
-
-            XRRCrtcInfo* crtc = XRRGetCrtcInfo (this->m_display, screenResources, info->crtc);
-
-            sLog.out ("Found requested screen: ", info->name, " -> ", crtc->x, "x", crtc->y, ":", crtc->width, "x", crtc->height);
-
-            this->m_viewports.push_back ({{crtc->x, crtc->y, crtc->width, crtc->height}, cur});
-
-            XRRFreeCrtcInfo (crtc);
-        }
-
-        XRRFreeOutputInfo (info);
-    }
-
-    XRRFreeScreenResources (screenResources);
-
-    // create the fbo that will handle the screen
-    this->m_fbo = new CFBO(
-        "_sc_FullFrameBuffer",
-        ITexture::TextureFormat::ARGB8888,
-        ITexture::TextureFlags::NoFlags,
-        1.0,
-        fullWidth, fullHeight,
-        fullWidth, fullHeight
-    );
-
-    // set the window background so the pixmap is drawn
-    XSetWindowBackgroundPixmap(this->m_display, root, this->m_pixmap);
-
-    this->m_imageData = new char [fullWidth * fullHeight * 4];
-
-    // create the image for X11 to be able to copy it over
-    this->m_image = XCreateImage (this->m_display, CopyFromParent, 24, ZPixmap, 0, this->m_imageData, fullWidth, fullHeight, 32, 0);
-}
-
-CRenderContext::~CRenderContext ()
+CRenderContext::CRenderContext (const COutput* output, CVideoDriver& driver, CInputContext& input, CWallpaperApplication& app) :
+	m_defaultWallpaper (nullptr),
+	m_output (output),
+	m_driver (driver),
+	m_app (app),
+	m_input (input),
+	m_textureCache (new CTextureCache (*this))
 {
-    if (!this->m_screens.empty ())
-    {
-        // free any used resource
-        XDestroyImage (this->m_image);
-        XFreeGC (this->m_display, this->m_gc);
-        XFreePixmap (this->m_display, this->m_pixmap);
-        XCloseDisplay (this->m_display);
-    }
 }
 
-void CRenderContext::renderScreens ()
+void CRenderContext::render ()
 {
-    bool firstFrame = true;
-    bool renderFrame = true;
-    int fullWidth = DisplayWidth (this->m_display, DefaultScreen (this->m_display));
-    int fullHeight = DisplayHeight (this->m_display, DefaultScreen (this->m_display));
-    Window root = DefaultRootWindow (this->m_display);
+	bool firstFrame = true;
+	bool renderFrame = true;
 
-    for (const auto& cur : this->m_viewports)
+    for (const auto& cur : this->m_output->getViewports ())
     {
 #if !NDEBUG
-		std::string str = "Rendering to screen " + cur.name;
+		std::string str = "Rendering to output " + cur.first;
 
 		glPushDebugGroup (GL_DEBUG_SOURCE_APPLICATION, 0, -1, str.c_str ());
 #endif /* DEBUG */
 
-        // render the background
-        this->m_wallpaper->render (cur.viewport, false, renderFrame, firstFrame);
+		// search the background in the viewport selection
+		auto ref = this->m_wallpapers.find (cur.first);
+
+		// render the background
+		if (ref != this->m_wallpapers.end ())
+			ref->second->render (cur.second.viewport, this->m_output->renderVFlip (), renderFrame, firstFrame);
+		else
+			this->m_defaultWallpaper->render (cur.second.viewport, this->m_output->renderVFlip (), renderFrame, firstFrame);
         // scenes need to render a new frame for each viewport as they produce different results
         // but videos should only be rendered once per group of viewports
         firstFrame = false;
@@ -205,61 +54,27 @@ void CRenderContext::renderScreens ()
     }
 
     // read the full texture into the image
-    glReadPixels (0, 0, fullWidth, fullHeight, GL_BGRA, GL_UNSIGNED_BYTE, (void*) this->m_imageData);
-
-    // put the image back into the screen
-    XPutImage (this->m_display, this->m_pixmap, this->m_gc, this->m_image, 0, 0, 0, 0, fullWidth, fullHeight);
-
-    // _XROOTPMAP_ID & ESETROOT_PMAP_ID allow other programs (compositors) to
-    // edit the background. Without these, other programs will clear the screen.
-    // it also forces the compositor to refresh the background (tested with picom)
-    Atom prop_root = XInternAtom(this->m_display, "_XROOTPMAP_ID", False);
-    Atom prop_esetroot = XInternAtom(this->m_display, "ESETROOT_PMAP_ID", False);
-    XChangeProperty(this->m_display, root, prop_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &this->m_pixmap, 1);
-    XChangeProperty(this->m_display, root, prop_esetroot, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &this->m_pixmap, 1);
-
-    XClearWindow(this->m_display, root);
-    XFlush(this->m_display);
+	if (this->m_output->haveImageBuffer ())
+		glReadPixels (
+			0, 0, this->m_output->getFullWidth (), this->m_output->getFullHeight (),
+			GL_BGRA, GL_UNSIGNED_BYTE,
+			this->m_output->getImageBuffer ()
+		);
+
+	// update the output with the given image
+	this->m_output->updateRender ();
+	// finally swap buffers
+    this->m_driver.swapBuffers ();
 }
 
-void CRenderContext::renderWindow ()
+void CRenderContext::setDefaultWallpaper (CWallpaper* wallpaper)
 {
-    // render the background to the window directly
-    this->m_wallpaper->render ({0, 0, this->m_driver.getFramebufferSize ()}, true);
+	this->m_defaultWallpaper = wallpaper;
 }
 
-void CRenderContext::render ()
+void CRenderContext::setWallpaper (const std::string& display, CWallpaper* wallpaper)
 {
-    if (this->m_wallpaper == nullptr)
-        return;
-
-	if (this->m_viewports.empty ())
-		this->renderWindow ();
-	else
-		this->renderScreens ();
-
-    this->m_driver.swapBuffers ();
-}
-
-void CRenderContext::setWallpaper (CWallpaper* wallpaper)
-{
-    this->m_wallpaper = wallpaper;
-
-    // update the wallpaper's texcoords based on the mode we're running
-    if (!this->m_screens.empty ())
-    {
-        GLfloat texCoords [] = {
-            0.0f, 1.0f,
-            1.0f, 1.0f,
-            0.0f, 0.0f,
-            0.0f, 0.0f,
-            1.0f, 1.0f,
-            1.0f, 0.0f
-        };
-
-        this->m_wallpaper->updateTexCoord (texCoords, sizeof (texCoords));
-        this->m_wallpaper->setDestinationFramebuffer (this->m_fbo->getFramebuffer ());
-    }
+	this->m_wallpapers.insert_or_assign (display, wallpaper);
 }
 
 CInputContext& CRenderContext::getInputContext () const
@@ -267,19 +82,14 @@ CInputContext& CRenderContext::getInputContext () const
     return this->m_input;
 }
 
-CWallpaper* CRenderContext::getWallpaper () const
-{
-    return this->m_wallpaper;
-}
-
-const CContainer& CRenderContext::getContainer () const
+const CWallpaperApplication& CRenderContext::getApp () const
 {
-    return this->m_container;
+    return this->m_app;
 }
 
-const CWallpaperApplication& CRenderContext::getApp () const
+const COutput* CRenderContext::getOutput () const
 {
-    return this->m_app;
+	return this->m_output;
 }
 
 const ITexture* CRenderContext::resolveTexture (const std::string& name)

+ 14 - 29
src/WallpaperEngine/Render/CRenderContext.h

@@ -9,12 +9,19 @@
 #include "WallpaperEngine/Input/CInputContext.h"
 #include "WallpaperEngine/Input/CMouseInput.h"
 #include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
+#include "WallpaperEngine/Render/Drivers/Output/COutput.h"
 #include <X11/Xlib.h>
 
 using namespace WallpaperEngine::Application;
 using namespace WallpaperEngine::Assets;
 using namespace WallpaperEngine::Input;
 using namespace WallpaperEngine::Render::Drivers;
+using namespace WallpaperEngine::Render::Drivers::Output;
+
+namespace WallpaperEngine::Render::Drivers::Output
+{
+	class COutput;
+}
 
 namespace WallpaperEngine::Render::Drivers
 {
@@ -34,45 +41,23 @@ namespace WallpaperEngine::Render
     class CRenderContext
     {
     public:
-        CRenderContext (std::vector <std::string> screens, CVideoDriver& driver, CInputContext& input, CContainer& container, CWallpaperApplication& app);
-        ~CRenderContext ();
+        CRenderContext (const COutput* output, CVideoDriver& driver, CInputContext& input, CWallpaperApplication& app);
 
-        void initialize ();
         void render ();
-        void setWallpaper (CWallpaper* wallpaper);
+		void setDefaultWallpaper (CWallpaper* wallpaper);
+		void setWallpaper (const std::string& display, CWallpaper* wallpaper);
         CInputContext& getInputContext () const;
-        void setMouse (CMouseInput* mouse);
-        CWallpaper* getWallpaper () const;
-        const CContainer& getContainer () const;
         const CWallpaperApplication& getApp () const;
+		const COutput* getOutput () const;
         const ITexture* resolveTexture (const std::string& name);
 
     private:
-        void setupScreens ();
-        void setupWindow ();
-
-        void renderScreens ();
-        void renderWindow ();
-
-        struct viewport
-        {
-            glm::ivec4 viewport;
-            std::string name;
-        };
-
-        Display* m_display;
-        Pixmap m_pixmap;
-        GC m_gc;
-        XImage* m_image;
         CVideoDriver& m_driver;
-        char* m_imageData;
-        CFBO* m_fbo;
-        std::vector <std::string> m_screens;
-        std::vector <viewport> m_viewports;
-        CWallpaper* m_wallpaper;
+		std::map <std::string, CWallpaper*> m_wallpapers;
+        CWallpaper* m_defaultWallpaper;
         CInputContext& m_input;
-        CContainer& m_container;
         CWallpaperApplication& m_app;
         CTextureCache* m_textureCache;
+		const COutput* m_output;
     };
 }

+ 21 - 3
src/WallpaperEngine/Render/CTextureCache.cpp

@@ -1,6 +1,9 @@
 #include "CTextureCache.h"
 
+#include "WallpaperEngine/Assets/CAssetLoadException.h"
+
 using namespace WallpaperEngine::Render;
+using namespace WallpaperEngine::Assets;
 
 CTextureCache::CTextureCache (CRenderContext& context) :
     m_context (context)
@@ -17,11 +20,26 @@ const ITexture* CTextureCache::resolve (const std::string& filename)
     if (found != this->m_textureCache.end ())
         return (*found).second;
 
-    const ITexture* texture = this->m_context.getContainer ().readTexture (filename);
+	// search for the texture in all the different containers just in case
+	for (auto it : this->m_context.getApp ().getProjects ())
+	{
+		const ITexture* texture = it.second->getContainer ()->readTexture (filename);
+
+		this->store (filename, texture);
+
+		return texture;
+	}
+
+	if (this->m_context.getApp ().getDefaultProject () != nullptr)
+	{
+		const ITexture* texture = this->m_context.getApp ().getDefaultProject ()->getContainer ()->readTexture (filename);
+
+		this->store (filename, texture);
 
-    this->store (filename, texture);
+		return texture;
+	}
 
-    return texture;
+	throw CAssetLoadException (filename, "Cannot find file");
 }
 
 void CTextureCache::store (std::string name, const ITexture* texture)

+ 4 - 1
src/WallpaperEngine/Render/CVideo.cpp

@@ -54,8 +54,11 @@ CVideo::CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& aud
     if (mpv_render_context_create (&this->m_mpvGl, this->m_mpv, params) < 0)
         sLog.exception ("Failed to initialize MPV's GL context");
 
+	std::filesystem::path videopath = this->getVideo ()->getProject ().getContainer ()->resolveRealFile (this->getVideo ()->getFilename ());
+
+	// build the path to the video file
     const char* command [] = {
-        "loadfile", this->getVideo ()->getFilename ().c_str (), nullptr
+        "loadfile", videopath.c_str (), nullptr
     };
 
     if (mpv_command (this->m_mpv, command) < 0)

+ 2 - 2
src/WallpaperEngine/Render/CWallpaper.cpp

@@ -61,9 +61,9 @@ CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRend
 CWallpaper::~CWallpaper ()
 = default;
 
-const CContainer& CWallpaper::getContainer () const
+CContainer* CWallpaper::getContainer () const
 {
-    return this->m_context.getContainer ();
+    return this->m_wallpaperData->getProject ().getContainer ();
 }
 
 WallpaperEngine::Core::CWallpaper* CWallpaper::getWallpaperData () const

+ 1 - 1
src/WallpaperEngine/Render/CWallpaper.h

@@ -38,7 +38,7 @@ namespace WallpaperEngine::Render
         /**
          * @return The container to resolve files for this wallpaper
          */
-        const CContainer& getContainer () const;
+        CContainer* getContainer () const;
 
         /**
          * @return The current context rendering this wallpaper

+ 6 - 0
src/WallpaperEngine/Render/Drivers/COpenGLDriver.cpp

@@ -62,6 +62,12 @@ void COpenGLDriver::resizeWindow (glm::ivec2 size)
     glfwSetWindowSize (this->m_window, size.x, size.y);
 }
 
+void COpenGLDriver::resizeWindow (glm::ivec4 sizeandpos)
+{
+	glfwSetWindowPos (this->m_window, sizeandpos.x, sizeandpos.y);
+    glfwSetWindowSize (this->m_window, sizeandpos.z, sizeandpos.w);
+}
+
 void COpenGLDriver::showWindow ()
 {
     glfwShowWindow (this->m_window);

+ 10 - 0
src/WallpaperEngine/Render/Drivers/COpenGLDriver.h

@@ -3,9 +3,17 @@
 #include <GL/glew.h>
 #include <GLFW/glfw3.h>
 #include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
+#include "WallpaperEngine/Application/CApplicationContext.h"
+
+namespace WallpaperEngine::Application
+{
+	class CApplicationContext;
+}
 
 namespace WallpaperEngine::Render::Drivers
 {
+	using namespace WallpaperEngine::Application;
+
     class COpenGLDriver : public CVideoDriver
     {
     public:
@@ -15,6 +23,7 @@ namespace WallpaperEngine::Render::Drivers
         float getRenderTime () override;
         bool closeRequested () override;
         void resizeWindow (glm::ivec2 size) override;
+		void resizeWindow (glm::ivec4 sizeandpos) override;
         void showWindow () override;
         void hideWindow () override;
         glm::ivec2 getFramebufferSize () override;
@@ -22,6 +31,7 @@ namespace WallpaperEngine::Render::Drivers
         uint32_t getFrameCounter () override;
 
         GLFWwindow* getWindow ();
+
     private:
         GLFWwindow* m_window;
         uint32_t m_frameCounter;

+ 2 - 0
src/WallpaperEngine/Render/Drivers/CVideoDriver.h

@@ -1,5 +1,6 @@
 #pragma once
 
+#include <glm/vec4.hpp>
 #include <glm/vec2.hpp>
 
 namespace WallpaperEngine::Render::Drivers
@@ -10,6 +11,7 @@ namespace WallpaperEngine::Render::Drivers
         virtual float getRenderTime () = 0;
         virtual bool closeRequested () = 0;
         virtual void resizeWindow (glm::ivec2 size) = 0;
+		virtual void resizeWindow (glm::ivec4 size) = 0;
         virtual void showWindow () = 0;
         virtual void hideWindow () = 0;
         virtual glm::ivec2 getFramebufferSize () = 0;

+ 23 - 0
src/WallpaperEngine/Render/Drivers/Output/COutput.cpp

@@ -0,0 +1,23 @@
+#include "COutput.h"
+
+using namespace WallpaperEngine::Render::Drivers::Output;
+
+COutput::COutput (CApplicationContext& context) :
+	m_context (context)
+{
+}
+
+const std::map <std::string, COutput::ScreenInfo>& COutput::getViewports () const
+{
+	return this->m_viewports;
+}
+
+int COutput::getFullWidth () const
+{
+	return this->m_fullWidth;
+}
+
+int COutput::getFullHeight () const
+{
+	return this->m_fullHeight;
+}

+ 47 - 0
src/WallpaperEngine/Render/Drivers/Output/COutput.h

@@ -0,0 +1,47 @@
+#pragma once
+
+#include <map>
+#include <string>
+#include <glm/vec4.hpp>
+
+#include "WallpaperEngine/Application/CApplicationContext.h"
+
+using namespace WallpaperEngine::Application;
+
+namespace WallpaperEngine::Application
+{
+	class CApplicationContext;
+}
+
+namespace WallpaperEngine::Render::Drivers::Output
+{
+	class COutput
+	{
+	public:
+		COutput (CApplicationContext& context);
+
+		virtual void reset () = 0;
+
+		int getFullWidth () const;
+		int getFullHeight () const;
+
+		struct ScreenInfo
+		{
+			glm::ivec4 viewport;
+			std::string name;
+		};
+
+		virtual bool renderVFlip () const = 0;
+		virtual bool renderMultiple () const = 0;
+		virtual bool haveImageBuffer () const = 0;
+		const std::map <std::string, ScreenInfo>& getViewports () const;
+		virtual void* getImageBuffer () const = 0;
+		virtual void updateRender () const = 0;
+
+	protected:
+		mutable int m_fullWidth;
+		mutable int m_fullHeight;
+		mutable std::map <std::string, ScreenInfo> m_viewports;
+		CApplicationContext& m_context;
+	};
+}

+ 77 - 0
src/WallpaperEngine/Render/Drivers/Output/CWindowOutput.cpp

@@ -0,0 +1,77 @@
+#include "CWindowOutput.h"
+#include "WallpaperEngine/Logging/CLog.h"
+
+using namespace WallpaperEngine::Render::Drivers::Output;
+
+CWindowOutput::CWindowOutput (CApplicationContext& context, CVideoDriver& driver) :
+	COutput (context),
+	m_driver (driver)
+{
+	if (
+		this->m_context.windowMode != Application::CApplicationContext::NORMAL_WINDOW &&
+		this->m_context.windowMode != Application::CApplicationContext::EXPLICIT_WINDOW)
+		sLog.exception ("Inititalizing window output when not in output mode, how did you get here?!");
+
+	// window should be visible
+	driver.showWindow ();
+
+	if (this->m_context.windowMode == Application::CApplicationContext::EXPLICIT_WINDOW)
+	{
+		this->m_fullWidth = this->m_context.windowGeometry.z;
+		this->m_fullHeight = this->m_context.windowGeometry.w;
+		this->repositionWindow ();
+	}
+	else
+	{
+		// take the size from the driver (default window size)
+		this->m_fullWidth = this->m_driver.getFramebufferSize ().x;
+		this->m_fullHeight = this->m_driver.getFramebufferSize ().y;
+	}
+
+	// register the default viewport
+	this->m_viewports ["default"] = {{0, 0, this->m_fullWidth, this->m_fullHeight}, "default"};
+}
+
+void CWindowOutput::repositionWindow ()
+{
+	// reposition the window
+	this->m_driver.resizeWindow (this->m_context.windowGeometry);
+}
+
+void CWindowOutput::reset ()
+{
+	if (this->m_context.windowMode == Application::CApplicationContext::EXPLICIT_WINDOW)
+		this->repositionWindow ();
+}
+
+bool CWindowOutput::renderVFlip () const
+{
+	return true;
+}
+
+bool CWindowOutput::renderMultiple () const
+{
+	return false;
+}
+
+bool CWindowOutput::haveImageBuffer () const
+{
+	return false;
+}
+
+void* CWindowOutput::getImageBuffer () const
+{
+	return nullptr;
+}
+void CWindowOutput::updateRender () const
+{
+	if (this->m_context.windowMode != Application::CApplicationContext::NORMAL_WINDOW)
+		return;
+
+	// take the size from the driver (default window size)
+	this->m_fullWidth = this->m_driver.getFramebufferSize ().x;
+	this->m_fullHeight = this->m_driver.getFramebufferSize ().y;
+
+	// update the default viewport
+	this->m_viewports ["default"] = {{0, 0, this->m_fullWidth, this->m_fullHeight}, "default"};
+}

+ 25 - 0
src/WallpaperEngine/Render/Drivers/Output/CWindowOutput.h

@@ -0,0 +1,25 @@
+#pragma once
+
+#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
+#include "COutput.h"
+
+namespace WallpaperEngine::Render::Drivers::Output
+{
+	class CWindowOutput : public COutput
+	{
+	public:
+		CWindowOutput (CApplicationContext& context, CVideoDriver& driver);
+
+		void reset () override;
+		bool renderVFlip () const override;
+		bool renderMultiple () const override;
+		bool haveImageBuffer () const override;
+		void* getImageBuffer () const override;
+		void updateRender () const override;
+
+	private:
+		void repositionWindow ();
+
+		CVideoDriver& m_driver;
+	};
+}

+ 183 - 0
src/WallpaperEngine/Render/Drivers/Output/CX11Output.cpp

@@ -0,0 +1,183 @@
+#include "common.h"
+#include "CX11Output.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xrandr.h>
+
+using namespace WallpaperEngine::Render::Drivers::Output;
+
+XErrorHandler originalErrorHandler;
+
+void CustomXIOErrorExitHandler (Display* dsp, void* userdata)
+{
+    auto context = static_cast <CX11Output*> (userdata);
+
+#if !NDEBUG
+    sLog.debugerror ("Critical XServer error detected. Attempting to recover...");
+#endif /* DEBUG */
+
+    // refetch all the resources
+    context->reset ();
+}
+
+int CustomXErrorHandler (Display* dpy, XErrorEvent* event)
+{
+#if !NDEBUG
+    sLog.debugerror ("Detected X error");
+#endif /* DEBUG */
+
+    // call the original handler so we can keep some information reporting
+    originalErrorHandler (dpy, event);
+
+    return 0;
+}
+
+int CustomXIOErrorHandler (Display* dsp)
+{
+#if !NDEBUG
+    sLog.debugerror ("Detected X error");
+#endif /* DEBUG */
+
+    return 0;
+}
+
+CX11Output::CX11Output (CApplicationContext& context, CVideoDriver& driver) :
+	COutput (context),
+	m_driver (driver)
+{
+	this->m_display = XOpenDisplay (nullptr);
+	this->loadScreenInfo ();
+}
+CX11Output::~CX11Output ()
+{
+	this->free ();
+	XCloseDisplay (this->m_display);
+}
+
+void CX11Output::reset ()
+{
+	// first free whatever we have right now
+	this->free ();
+	// re-load screen info
+	this->loadScreenInfo ();
+}
+
+void CX11Output::free ()
+{
+	// free all the resources we've got
+	XDestroyImage (this->m_image);
+	XFreeGC (this->m_display, this->m_gc);
+	XFreePixmap (this->m_display, this->m_pixmap);
+	delete this->m_imageData;
+}
+
+void* CX11Output::getImageBuffer () const
+{
+	return this->m_imageData;
+}
+
+bool CX11Output::renderVFlip () const
+{
+	return false;
+}
+
+bool CX11Output::renderMultiple () const
+{
+	return this->m_viewports.size () > 1;
+}
+
+bool CX11Output::haveImageBuffer () const
+{
+	return true;
+}
+
+void CX11Output::loadScreenInfo ()
+{
+	// reset the viewports
+	this->m_viewports.clear ();
+
+    // set the error handling to try and recover from X disconnections
+#ifdef HAVE_XSETIOERROREXITHANDLER
+    XSetIOErrorExitHandler (this->m_display, CustomXIOErrorExitHandler, this);
+#endif /* HAVE_XSETIOERROREXITHANDLER */
+    originalErrorHandler = XSetErrorHandler (CustomXErrorHandler);
+    XSetIOErrorHandler (CustomXIOErrorHandler);
+
+	int xrandr_result, xrandr_error;
+
+	if (!XRRQueryExtension (this->m_display, &xrandr_result, &xrandr_error))
+	{
+		sLog.error ("XRandr is not present, cannot detect specified screens, running in window mode");
+		return;
+	}
+
+	this->m_root = DefaultRootWindow (this->m_display);
+	this->m_fullWidth = DisplayWidth (this->m_display, DefaultScreen (this->m_display));
+	this->m_fullHeight = DisplayHeight (this->m_display, DefaultScreen (this->m_display));
+	XRRScreenResources* screenResources = XRRGetScreenResources (this->m_display, DefaultRootWindow (this->m_display));
+
+	if (screenResources == nullptr)
+	{
+		sLog.error ("Cannot detect screen sizes using xrandr, running in window mode");
+		return;
+	}
+
+	for (int i = 0; i < screenResources->noutput; i ++)
+	{
+		XRROutputInfo* info = XRRGetOutputInfo (this->m_display, screenResources, screenResources->outputs [i]);
+
+		// screen not in use, ignore it
+		if (info == nullptr || info->connection != RR_Connected)
+			continue;
+
+		// only keep info of registered screens
+		if (this->m_context.screenSettings.find (info->name) == this->m_context.screenSettings.end ())
+			continue;
+
+		XRRCrtcInfo* crtc = XRRGetCrtcInfo (this->m_display, screenResources, info->crtc);
+
+		sLog.out ("Found requested screen: ", info->name, " -> ", crtc->x, "x", crtc->y, ":", crtc->width, "x", crtc->height);
+
+		this->m_viewports [info->name] =
+		{
+			{crtc->x, crtc->y, crtc->width, crtc->height},
+			info->name
+		};
+
+		XRRFreeCrtcInfo (crtc);
+	}
+
+	XRRFreeScreenResources (screenResources);
+
+	// create pixmap so we can draw things in there
+	this->m_pixmap = XCreatePixmap (this->m_display, this->m_root, this->m_fullWidth, this->m_fullHeight, 24);
+	this->m_gc = XCreateGC (this->m_display, this->m_pixmap, 0, nullptr);
+	// pre-fill it with black
+	XFillRectangle (this->m_display, this->m_pixmap, this->m_gc, 0, 0, this->m_fullWidth, this->m_fullHeight);
+	// set the window background as our pixmap
+	XSetWindowBackgroundPixmap (this->m_display, this->m_root, this->m_pixmap);
+	// allocate space for the image's data
+	this->m_imageData = new char [this->m_fullWidth * this->m_fullHeight * 4];
+	// create an image so we can copy it over
+	this->m_image = XCreateImage (this->m_display, CopyFromParent, 24, ZPixmap, 0, this->m_imageData, this->m_fullWidth, this->m_fullHeight, 32, 0);
+	// setup driver's render changing the window's size
+	this->m_driver.resizeWindow ({this->m_fullWidth, this->m_fullHeight});
+}
+
+void CX11Output::updateRender () const
+{
+    // put the image back into the screen
+    XPutImage (this->m_display, this->m_pixmap, this->m_gc, this->m_image, 0, 0, 0, 0, this->m_fullWidth, this->m_fullHeight);
+
+    // _XROOTPMAP_ID & ESETROOT_PMAP_ID allow other programs (compositors) to
+    // edit the background. Without these, other programs will clear the screen.
+    // it also forces the compositor to refresh the background (tested with picom)
+    Atom prop_root = XInternAtom(this->m_display, "_XROOTPMAP_ID", False);
+    Atom prop_esetroot = XInternAtom(this->m_display, "ESETROOT_PMAP_ID", False);
+    XChangeProperty(this->m_display, this->m_root, prop_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &this->m_pixmap, 1);
+    XChangeProperty(this->m_display, this->m_root, prop_esetroot, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &this->m_pixmap, 1);
+
+    XClearWindow(this->m_display, this->m_root);
+    XFlush(this->m_display);
+}

+ 40 - 0
src/WallpaperEngine/Render/Drivers/Output/CX11Output.h

@@ -0,0 +1,40 @@
+#pragma once
+
+#include <map>
+#include <string>
+#include <glm/vec4.hpp>
+
+#include <X11/Xlib.h>
+
+#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
+#include "COutput.h"
+
+namespace WallpaperEngine::Render::Drivers::Output
+{
+	class CX11Output : public COutput
+	{
+	public:
+		CX11Output (CApplicationContext& context, CVideoDriver& driver);
+		~CX11Output ();
+
+		void reset () override;
+
+		bool renderVFlip () const override;
+		bool renderMultiple () const override;
+		bool haveImageBuffer () const override;
+		void* getImageBuffer () const override;
+		void updateRender () const override;
+
+	private:
+		void loadScreenInfo ();
+		void free ();
+
+		Display* m_display;
+		Pixmap m_pixmap;
+		Window m_root;
+		GC m_gc;
+		char* m_imageData;
+		XImage* m_image;
+		CVideoDriver& m_driver;
+	};
+}

+ 5 - 2
src/WallpaperEngine/Render/Objects/CSound.cpp

@@ -2,13 +2,16 @@
 
 #include "CSound.h"
 
+extern bool g_AudioEnabled;
+
 using namespace WallpaperEngine::Render::Objects;
 
 CSound::CSound (CScene* scene, Core::Objects::CSound* sound) :
     CObject (scene, Type, sound),
     m_sound (sound)
 {
-    this->load ();
+	if (g_AudioEnabled)
+	    this->load ();
 }
 
 void CSound::load ()
@@ -16,7 +19,7 @@ void CSound::load ()
     for (const auto& cur : this->m_sound->getSounds ())
     {
         uint32_t filesize = 0;
-        const void* filebuffer = this->getContainer ().readFile (cur, &filesize);
+        const void* filebuffer = this->getContainer ()->readFile (cur, &filesize);
 
         auto stream = new Audio::CAudioStream (this->getScene ()->getAudioContext (), filebuffer, filesize);
 

+ 5 - 5
src/WallpaperEngine/Render/Shaders/Compiler.cpp

@@ -29,7 +29,7 @@ using namespace WallpaperEngine::Assets;
 namespace WallpaperEngine::Render::Shaders
 {
     Compiler::Compiler (
-            const CContainer& container,
+            CContainer* container,
             std::string filename,
             Type type,
             std::map <std::string, int>* combos,
@@ -50,11 +50,11 @@ namespace WallpaperEngine::Render::Shaders
         m_baseCombos ()
     {
         if (type == Type_Vertex)
-            this->m_content = this->m_container.readVertexShader (this->m_file);
+            this->m_content = this->m_container->readVertexShader (this->m_file);
         else if (type == Type_Pixel)
-            this->m_content = this->m_container.readFragmentShader (this->m_file);
+            this->m_content = this->m_container->readFragmentShader (this->m_file);
         else if (type == Type_Include)
-            this->m_content = this->m_container.readIncludeShader (this->m_file);
+            this->m_content = this->m_container->readIncludeShader (this->m_file);
 
         // clone the combos into the baseCombos to keep track of values that must be embedded no matter what
         for (const auto& cur : *this->m_combos)
@@ -650,7 +650,7 @@ namespace WallpaperEngine::Render::Shaders
 		file += ".json";
 
 		std::string tmp = file;
-		std::string patchContents = this->m_container.readFileAsString (file);
+		std::string patchContents = this->m_container->readFileAsString (file);
 
 		json data = json::parse (patchContents);
 		auto patches = data.find ("patches");

+ 2 - 2
src/WallpaperEngine/Render/Shaders/Compiler.h

@@ -51,7 +51,7 @@ namespace WallpaperEngine::Render::Shaders
          * @param recursive Whether the compiler should add base definitions or not
          */
         Compiler (
-            const CContainer& container,
+            CContainer* container,
             std::string filename,
             Type type,
             std::map<std::string, int>* combos,
@@ -264,7 +264,7 @@ namespace WallpaperEngine::Render::Shaders
          /**
           * The container to load files from
           */
-         const CContainer& m_container;
+         CContainer* m_container;
          /**
           * List of textures that the shader expects (inferred from sampler2D and it's JSON data)
           */