Преглед на файлове

Renamed CContext to CRenderContext to allow for the introduction of CAudioContext in following iterations
Improved logging and error reporting to be a bit more flexible

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

Alexis Maiquez преди 3 години
родител
ревизия
d370e028ff
променени са 38 файла, в които са добавени 408 реда и са изтрити 239 реда
  1. 5 2
      CMakeLists.txt
  2. 3 2
      README.md
  3. 73 67
      main.cpp
  4. 3 2
      src/WallpaperEngine/Assets/CDirectory.cpp
  5. 6 5
      src/WallpaperEngine/Assets/CPackage.cpp
  6. 9 7
      src/WallpaperEngine/Assets/CTexture.cpp
  7. 11 9
      src/WallpaperEngine/Audio/CAudioStream.cpp
  8. 2 1
      src/WallpaperEngine/Core/CObject.cpp
  9. 3 2
      src/WallpaperEngine/Core/CProject.cpp
  10. 7 9
      src/WallpaperEngine/Core/Core.cpp
  11. 6 6
      src/WallpaperEngine/Core/Objects/CEffect.cpp
  12. 3 3
      src/WallpaperEngine/Core/Objects/CSound.cpp
  13. 3 4
      src/WallpaperEngine/Core/Objects/Images/Materials/CPass.cpp
  14. 2 1
      src/WallpaperEngine/Core/Objects/Particles/CInitializer.cpp
  15. 12 25
      src/WallpaperEngine/Core/Objects/Particles/Initializers/CTurbulentVelocityRandom.cpp
  16. 3 1
      src/WallpaperEngine/Core/Projects/CProperty.cpp
  17. 3 2
      src/WallpaperEngine/Core/Projects/CPropertyCombo.cpp
  18. 2 1
      src/WallpaperEngine/Core/Projects/CPropertySlider.cpp
  19. 5 4
      src/WallpaperEngine/Core/UserSettings/CUserSettingBoolean.cpp
  20. 5 4
      src/WallpaperEngine/Core/UserSettings/CUserSettingFloat.cpp
  21. 5 4
      src/WallpaperEngine/Core/UserSettings/CUserSettingVector3.cpp
  22. 30 0
      src/WallpaperEngine/Logging/CLog.cpp
  23. 113 0
      src/WallpaperEngine/Logging/CLog.h
  24. 2 1
      src/WallpaperEngine/Render/CFBO.cpp
  25. 19 18
      src/WallpaperEngine/Render/CRenderContext.cpp
  26. 3 3
      src/WallpaperEngine/Render/CRenderContext.h
  27. 5 3
      src/WallpaperEngine/Render/CScene.cpp
  28. 1 1
      src/WallpaperEngine/Render/CScene.h
  29. 1 1
      src/WallpaperEngine/Render/CTextureCache.cpp
  30. 4 4
      src/WallpaperEngine/Render/CTextureCache.h
  31. 16 15
      src/WallpaperEngine/Render/CVideo.cpp
  32. 1 1
      src/WallpaperEngine/Render/CVideo.h
  33. 9 8
      src/WallpaperEngine/Render/CWallpaper.cpp
  34. 7 7
      src/WallpaperEngine/Render/CWallpaper.h
  35. 3 0
      src/WallpaperEngine/Render/Objects/CImage.cpp
  36. 13 5
      src/WallpaperEngine/Render/Objects/Effects/CPass.cpp
  37. 9 11
      src/WallpaperEngine/Render/Shaders/Compiler.cpp
  38. 1 0
      src/common.h

+ 5 - 2
CMakeLists.txt

@@ -37,6 +37,9 @@ add_executable(
         linux-wallpaperengine
         main.cpp
 
+        src/WallpaperEngine/Logging/CLog.cpp
+        src/WallpaperEngine/Logging/CLog.h
+
         src/WallpaperEngine/Assets/CPackageLoadException.cpp
         src/WallpaperEngine/Assets/CPackageLoadException.h
         src/WallpaperEngine/Assets/CAssetLoadException.cpp
@@ -80,8 +83,8 @@ add_executable(
         src/WallpaperEngine/Render/Shaders/Compiler.h
         src/WallpaperEngine/Render/Shaders/Compiler.cpp
 
-        src/WallpaperEngine/Render/CContext.h
-        src/WallpaperEngine/Render/CContext.cpp
+        src/WallpaperEngine/Render/CRenderContext.h
+        src/WallpaperEngine/Render/CRenderContext.cpp
         src/WallpaperEngine/Render/CTextureCache.h
         src/WallpaperEngine/Render/CTextureCache.cpp
 

+ 3 - 2
README.md

@@ -1,8 +1,9 @@
 <p align="center">
 	<a href="https://github.com/Almamu/linux-wallpaperengine/blob/main/LICENSE"><img src="https://img.shields.io/github/license/Almamu/linux-wallpaperengine" /></a>
-	<a href="https://github.com/Almamu/linux-wallpaperengine/pulse"><img src="https://img.shields.io/tokei/lines/github/Almamu/linux-wallpaperengine" /></a>
+    <a href="https://github.com/Almamu/linux-wallpaperengine/actions?query=branch%3Amain"><img src="https://img.shields.io/github/actions/workflow/status/Almamu/linux-wallpaperengine/cmake.yml?branch=main" /></a>
+    <a href="https://github.com/Almamu/linux-wallpaperengine/pulse"><img src="https://img.shields.io/tokei/lines/github/Almamu/linux-wallpaperengine" /></a>
 	<a href="https://www.codefactor.io/repository/github/almamu/linux-wallpaperengine"><img src="https://img.shields.io/codefactor/grade/github/Almamu/linux-wallpaperengine" /></a>
-	<a href="https://github.com/Almamu/linux-wallpaperengine/graphs/commit-activity"><img src="https://img.shields.io/github/commit-activity/w/Almamu/linux-wallpaperengine" /></a>
+	<a href="https://github.com/Almamu/linux-wallpaperengine/graphs/commit-activity"><img src="https://img.shields.io/github/commit-activity/m/Almamu/linux-wallpaperengine" /></a>
 	<a href="https://github.com/Almamu/linux-wallpaperengine/graphs/contributors"><img src="https://img.shields.io/github/contributors/Almamu/linux-wallpaperengine" /></a>
 	<a href="https://github.com/Almamu/linux-wallpaperengine/issues"><img src="https://img.shields.io/github/issues-raw/Almamu/linux-wallpaperengine" /></a>
 	<a href="https://github.com/Almamu/linux-wallpaperengine/issues?q=is%3Aissue+is%3Aopen+label%3A%22help%20wanted%22"><img src="https://img.shields.io/github/issues/Almamu/linux-wallpaperengine/help%20wanted?color=green" alt="help wanted"></a>

+ 73 - 67
main.cpp

@@ -12,9 +12,9 @@
 #include <libgen.h>
 
 #include "WallpaperEngine/Core/CProject.h"
-#include "WallpaperEngine/Render/CWallpaper.h"
-#include "WallpaperEngine/Render/CContext.h"
+#include "WallpaperEngine/Render/CRenderContext.h"
 #include "WallpaperEngine/Render/CVideo.h"
+#include "WallpaperEngine/Render/CWallpaper.h"
 
 #include "WallpaperEngine/Assets/CPackage.h"
 #include "WallpaperEngine/Assets/CDirectory.h"
@@ -22,6 +22,8 @@
 #include "WallpaperEngine/Assets/CCombinedContainer.h"
 #include "WallpaperEngine/Assets/CPackageLoadException.h"
 
+#include "common.h"
+
 float g_Time;
 float g_TimeLast;
 bool g_KeepRunning = true;
@@ -41,22 +43,21 @@ const char* backgrounds_default_paths [] = {
 
 void print_help (const char* route)
 {
-    std::cout
-        << "Usage: " << route << " [options] background_path/background_id" << std::endl
-        << std::endl
-        << "where background_path/background_id can be:" << std::endl
-        << "\tthe ID of the background (for autodetection on your steam installation)" << std::endl
-        << "\ta full path to the background's folder" << std::endl
-        << std::endl
-        << "options:" << std::endl
-        << "\t--silent\t\t\t\t\tMutes all the sound the wallpaper might produce" << std::endl
-        << "\t--volume <amount>\t\t\tSets the volume for all the sounds in the background" << std::endl
-        << "\t--screen-root <screen name>\tDisplay as screen's background" << std::endl
-        << "\t--fps <maximum-fps>\t\t\tLimits the FPS to the given number, useful to keep battery consumption low" << std::endl
-        << "\t--assets-dir <path>\t\t\tFolder where the assets are stored" << std::endl
-        << "\t--screenshot\t\t\t\tTakes a screenshot of the background" << std::endl
-        << "\t--list-properties\t\t\tList all the available properties and their possible values" << std::endl
-        << "\t--set-property <name=value>\tOverrides the default value of the given property" << std::endl;
+    sLog.out ("Usage: ", route, " [options] background_path/background_id");
+    sLog.out ("");
+    sLog.out ("where background_path/background_id can be:");
+    sLog.out ("\tthe ID of the background (for autodetection on your steam installation)");
+    sLog.out ("\ta full path to the background's folder");
+    sLog.out ("");
+    sLog.out ("options:");
+    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--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");
+    sLog.out ("\t--list-properties\t\t\tList all the available properties and their possible values");
+    sLog.out ("\t--set-property <name=value>\tOverrides the default value of the given property");
 }
 
 std::string stringPathFixes(const std::string& s)
@@ -80,7 +81,7 @@ void signalhandler(int sig)
     g_KeepRunning = false;
 }
 
-int validatePath(const char* path, std::string& final)
+int handleValidatePath (const char* path, std::string& final)
 {
     char finalPath [PATH_MAX];
     char* pointer = realpath (path, finalPath);
@@ -102,23 +103,36 @@ int validatePath(const char* path, std::string& final)
     return 0;
 }
 
+void validatePath(const char* path, std::string& final)
+{
+    int error = handleValidatePath (path, final);
+
+    switch (error)
+    {
+        case ENOTDIR:
+            sLog.exception ("Invalid directory, ", path, " is not a folder");
+            break;
+        case ENAMETOOLONG:
+            sLog.exception ("Path ", path, " too long");
+            break;
+        case 0:
+            return;
+        default:
+            sLog.exception ("Cannot find the specified folder");
+            break;
+    }
+}
+
 std::string getHomePath ()
 {
     char* home = getenv ("HOME");
 
     if (home == nullptr)
-        throw std::runtime_error ("$HOME doesn't exist");
+        sLog.exception ("Cannot find home directory for the current user");
 
     std::string homepath;
 
-    int error = validatePath (home, homepath);
-
-    if (error == ENOTDIR)
-        throw std::runtime_error ("Invalid user home path");
-    else if (error == ENAMETOOLONG)
-        throw std::runtime_error ("Cannot get user's home folder, path is too long");
-    else if (error != 0)
-        throw std::runtime_error ("Cannot find the home folder for the user");
+    validatePath (home, homepath);
 
     return homepath;
 }
@@ -127,7 +141,7 @@ void initGLFW ()
 {
     // first of all, initialize the window
     if (glfwInit () == GLFW_FALSE)
-        throw std::runtime_error ("Failed to initialize GLFW");
+        sLog.exception ("Failed to initialize GLFW");
 
     // initialize freeimage
     FreeImage_Initialise (TRUE);
@@ -150,18 +164,17 @@ void addPkg (CCombinedContainer* containers, const std::string& path, std::strin
 
         // add the package to the list
         containers->add (new WallpaperEngine::Assets::CPackage (scene_path));
-        std::cout << "Detected " << pkgfile << " file at " << scene_path << ". Adding to list of searchable paths" << std::endl;
+        sLog.out ("Detected ", pkgfile, " file at ", scene_path, ". Adding to list of searchable paths");
     }
     catch (CPackageLoadException& ex)
     {
         // ignore this error, the package file was not found
-        std::cout << "No " << pkgfile <<  " file found at " << path << ". Defaulting to normal folder storage" << std::endl;
+        sLog.out ("No ", pkgfile, " file found at ", path, ". Defaulting to normal folder storage");
     }
     catch (std::runtime_error& ex)
     {
         // the package was found but there was an error loading it (wrong header or something)
-        fprintf (stderr, "Failed to load scene.pkg file: %s\n", ex.what());
-        throw std::runtime_error ("Cannot load package file");
+        sLog.exception ("Failed to load scene.pkg file: ", ex.what());
     }
 }
 
@@ -312,8 +325,16 @@ void takeScreenshot (WallpaperEngine::Render::CWallpaper* wp, const std::string&
     glBindTexture (GL_TEXTURE_2D, GL_NONE);
 }
 
+void initLogging ()
+{
+    sLog.addOutput (new std::ostream (std::cout.rdbuf ()));
+    sLog.addError (new std::ostream (std::cerr.rdbuf ()));
+}
+
 int main (int argc, char* argv[])
 {
+    initLogging ();
+
     std::vector <std::string> screens;
     std::map <std::string, std::string> propertyOverrides;
 
@@ -376,7 +397,7 @@ int main (int argc, char* argv[])
 
             case 'p':
             case 'd':
-                std::cerr << "--dir/--pkg is deprecated and not used anymore" << std::endl;
+                sLog.error ("--dir/--pkg is deprecated and not used anymore");
                 path = stringPathFixes (optarg);
                 break;
 
@@ -433,7 +454,7 @@ int main (int argc, char* argv[])
         else if (extension == "jpg" || extension == "jpeg")
             screenshotFormat = FIF_JPEG;
         else
-            throw std::runtime_error ("Unsupported screenshot format...");
+            sLog.exception ("Unsupported screenshot format ", extension);
     }
 
     std::string homepath = getHomePath ();
@@ -446,7 +467,7 @@ int main (int argc, char* argv[])
         {
             std::string tmppath = homepath + "/" + *current + "/" + path;
 
-            int error = validatePath (tmppath.c_str (), tmppath);
+            int error = handleValidatePath (tmppath.c_str (), tmppath);
 
             if (error != 0)
                 continue;
@@ -455,14 +476,7 @@ int main (int argc, char* argv[])
         }
     }
 
-    int error = validatePath (path.c_str (), path);
-
-    if (error == ENOTDIR)
-        throw std::runtime_error ("The background path is not a folder");
-    else if (error == ENAMETOOLONG)
-        throw std::runtime_error ("Cannot get wallpaper's folder, path is too long");
-    else if (error != 0)
-        throw std::runtime_error ("Cannot find the specified folder");
+    validatePath (path.c_str (), path);
 
     // add a trailing slash to the path so the right file can be found
     path += "/";
@@ -481,13 +495,13 @@ int main (int argc, char* argv[])
         {
             std::string tmppath = homepath + "/" + *current;
 
-            error = validatePath (tmppath.c_str (), tmppath);
+            int error = handleValidatePath (tmppath.c_str (), tmppath);
 
             if (error != 0)
                 continue;
 
             assetsDir = tmppath;
-            std::cout << "Found wallpaper engine's assets at " << assetsDir << std::endl;
+            sLog.out ("Found wallpaper engine's assets at ", assetsDir);
             break;
         }
 
@@ -502,12 +516,12 @@ int main (int argc, char* argv[])
             std::string exepath = dirname (copy);
             exepath += "/assets";
 
-            error = validatePath (exepath.c_str (), exepath);
+            int error = handleValidatePath (exepath.c_str (), exepath);
 
             if (error == 0)
             {
                 assetsDir = exepath;
-                std::cout << "Found assets folder alongside the binary: " << assetsDir << std::endl;
+                sLog.out ("Found assets folder alongside the binary: ", assetsDir);
             }
 
             delete[] copy;
@@ -515,20 +529,12 @@ int main (int argc, char* argv[])
     }
     else
     {
-        error = validatePath (assetsDir.c_str (), assetsDir);
-
-        if (error == ENOTDIR)
-            throw std::runtime_error ("Invalid assets folder");
-        else if (error == ENAMETOOLONG)
-            throw std::runtime_error ("Cannot get assets folder, path is too long");
-        else if (error != 0)
-            throw std::runtime_error ("Cannot find the specified assets folder");
-
-        std::cout << "Found wallpaper engine's assets at " << assetsDir << " based on --assets-dir parameter" << std::endl;
+        validatePath (assetsDir.c_str (), assetsDir);
+        sLog.out ("Found wallpaper engine's assets at ", assetsDir, " based on --assets-dir parameter");
     }
 
     if (assetsDir.empty () == true)
-        throw std::runtime_error ("Cannot determine a valid path for the wallpaper engine assets");
+        sLog.exception ("Cannot determine a valid path for the wallpaper engine assets");
 
     // add containers to the list
     containers->add (new WallpaperEngine::Assets::CDirectory (assetsDir + "/"));
@@ -547,13 +553,13 @@ int main (int argc, char* argv[])
 
         if (override != propertyOverrides.end ())
         {
-            std::cout << "Applying override value for " << cur->getName () << std::endl;
+            sLog.out ("Applying override value for ", cur->getName ());
 
             cur->update (override->second);
         }
 
         if (shouldListPropertiesAndStop)
-            std::cout << cur->dump () << std::endl;
+            sLog.out (cur->dump ());
     }
 
     // halt if the list-properties option was specified
@@ -575,7 +581,7 @@ int main (int argc, char* argv[])
 
     if (window == nullptr)
     {
-        fprintf (stderr, "Failed to open a GLFW window");
+        sLog.error ("GLFW", "Failed to open a GLFW window");
         glfwTerminate ();
         return 2;
     }
@@ -593,19 +599,19 @@ int main (int argc, char* argv[])
     // initialize glew
     if (glewInitResult != GLEW_OK)
     {
-        fprintf (stderr, "Failed to initialize GLEW: %s", glewGetErrorString (glewInitResult));
+        sLog.error ("GLEW", "Failed to initialize GLEW: ", glewGetErrorString (glewInitResult));
         glfwTerminate ();
         return 3;
     }
 
     if (shouldEnableAudio == true && SDL_Init (SDL_INIT_AUDIO) < 0)
     {
-        std::cerr << "Cannot initialize SDL audio system, SDL_GetError: " << SDL_GetError() << std::endl;
-        std::cerr << "Continuing without audio support" << std::endl;
+        sLog.error ("SDL", "Cannot initialize SDL audio system, SDL_GetError: ", SDL_GetError());
+        sLog.error ("SDL", "Continuing without audio support");
     }
 
     // initialize custom context class
-    WallpaperEngine::Render::CContext* context = new WallpaperEngine::Render::CContext (screens, window, containers);
+    WallpaperEngine::Render::CRenderContext* context = new WallpaperEngine::Render::CRenderContext (screens, window, containers);
     // initialize mouse support
     context->setMouse (new CMouseInput (window));
     // set the default viewport
@@ -664,7 +670,7 @@ int main (int argc, char* argv[])
     // ensure this is updated as sometimes it might not come from a signal
     g_KeepRunning = false;
 
-    std::cout << "Stop requested" << std::endl;
+    sLog.out ("Stop requested");
 
     // terminate gl
     glfwTerminate ();

+ 3 - 2
src/WallpaperEngine/Assets/CDirectory.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include <sys/stat.h>
 
 #include "CDirectory.h"
@@ -12,10 +13,10 @@ CDirectory::CDirectory (std::string basepath) :
     struct stat buffer;
 
     if (stat (this->m_basepath.c_str (), &buffer) != 0)
-        throw std::runtime_error ("Cannot find " + this->m_basepath + ". This folder is required for wallpaper engine to work");
+        sLog.exception ("Cannot find ", this->m_basepath, ". This folder is required for wallpaper engine to work");
 
     if (!S_ISDIR(buffer.st_mode))
-        throw std::runtime_error ("Cannot find " + this->m_basepath + ". There's an assets file in it's place");
+        sLog.exception ("Cannot find ", this->m_basepath, ". There's an assets file in it's place");
 }
 
 CDirectory::~CDirectory ()

+ 6 - 5
src/WallpaperEngine/Assets/CPackage.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include "CPackage.h"
 #include "CAssetLoadException.h"
 #include "CPackageLoadException.h"
@@ -67,7 +68,7 @@ char* CPackage::readSizedString (FILE* fp)
     unsigned int length = 0;
 
     if (fread (&length, sizeof (unsigned int), 1, fp) != 1)
-        throw std::runtime_error ("Cannot read enough bytes from file");
+        sLog.exception ("Cannot read sized string length on file ", this->m_path);
 
     // account for 0 termination of the string
     length ++;
@@ -80,7 +81,7 @@ char* CPackage::readSizedString (FILE* fp)
 
     // read data from file
     if (fread (pointer, sizeof (char), length, fp) != length)
-        throw std::runtime_error ("Cannot read package version from file");
+        sLog.exception ("Not enough bytes to read string of length ", length, " on file ", this->m_path);
 
     return pointer;
 }
@@ -90,7 +91,7 @@ uint32_t CPackage::readInteger (FILE* fp)
     uint32_t output;
 
     if (fread (&output, sizeof (uint32_t), 1, fp) != 1)
-        throw std::runtime_error ("Cannot read integer value from file");
+        sLog.exception ("Not enough bytes to read an integer from file ", this->m_path);
 
     return output;
 }
@@ -159,7 +160,7 @@ void CPackage::loadFiles (FILE* fp)
 
         // with all the data we can jump to the offset and read the content
         if (fseek (fp, offset, SEEK_SET) != 0)
-            throw std::runtime_error ("Cannot find file in package");
+            sLog.exception ("Cannot find file ", (*cur).filename, " from package ", this->m_path);
 
         // allocate memory for the file's contents and read it from the file
         char* fileContents = new char [(*cur).length];
@@ -168,7 +169,7 @@ void CPackage::loadFiles (FILE* fp)
         {
             delete[] fileContents;
 
-            throw std::runtime_error ("Cannot read file contents from package");
+            sLog.exception ("Cannot read file ", (*cur).filename, " contents from package ", this->m_path);
         }
 
         // add the file to the map

+ 9 - 7
src/WallpaperEngine/Assets/CTexture.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include "CTexture.h"
 
 #include <string>
@@ -80,7 +81,7 @@ CTexture::CTexture (const void* fileData)
                 break;
             default:
                 delete this->m_header;
-                throw std::runtime_error ("Cannot determine the texture format");
+                sLog.exception ("Cannot determine texture format");
         }
     }
 
@@ -191,7 +192,7 @@ CTexture::CTexture (const void* fileData)
                     );
                     break;
                 default:
-                    throw std::runtime_error ("Cannot load texture, unknown format");
+                    sLog.exception ("Cannot load texture, unknown format", this->m_header->format);
             }
 
             // freeimage buffer won't be used anymore, so free memory
@@ -303,7 +304,7 @@ void CTexture::TextureMipmap::decompressData ()
         );
 
         if (!result)
-            throw std::runtime_error ("Cannot decompress texture data");
+            sLog.exception ("Cannot decompress texture data, LZ4_decompress_safe returned an error");
     }
 }
 
@@ -338,12 +339,12 @@ CTexture::TextureHeader* CTexture::parseHeader (const char* fileData)
 {
     // check the magic value on the header first
     if (memcmp (fileData, "TEXV0005", 9) != 0)
-        throw std::runtime_error ("unexpected texture container type");
+        sLog.exception ("unexpected texture container type: ", std::string_view (fileData, 9));
     // jump to the next value
     fileData += 9;
     // check the sub-magic value on the header
     if (memcmp (fileData, "TEXI0001", 9) != 0)
-        throw std::runtime_error ("unexpected texture sub-container type");
+        sLog.exception ("unexpected texture sub-container type: ", std::string_view (fileData, 9));
     // jump through the string again
     fileData += 9;
 
@@ -384,7 +385,7 @@ CTexture::TextureHeader* CTexture::parseHeader (const char* fileData)
     else
     {
         delete header;
-        throw std::runtime_error ("unknown texture format type");
+        sLog.exception ("unknown texture format type: ", std::string_view (fileData, 9));
     }
 
     for (uint32_t image = 0; image < header->imageCount; image ++)
@@ -417,7 +418,8 @@ CTexture::TextureHeader* CTexture::parseHeader (const char* fileData)
         }
         else
         {
-            throw std::runtime_error ("found animation information of unknown type");
+            delete header;
+            sLog.exception ("found animation information of unknown type: ", std::string_view (fileData, 9));
         }
 
         // get an integer pointer back to read the frame count

+ 11 - 9
src/WallpaperEngine/Audio/CAudioStream.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include "CAudioStream.h"
 #include <cassert>
 #include <iostream>
@@ -144,7 +145,7 @@ CAudioStream::CAudioStream (const void* buffer, int length)
     this->m_formatContext = avformat_alloc_context ();
 
     if (this->m_formatContext == nullptr)
-        throw std::runtime_error ("Cannot allocate format context");
+        sLog.exception ("Cannot allocate ffmpeg format context");
 
     this->m_buffer = buffer;
     this->m_length = length;
@@ -162,7 +163,7 @@ CAudioStream::CAudioStream (const void* buffer, int length)
     );
 
     if (this->m_formatContext->pb == nullptr)
-        throw std::runtime_error ("Cannot create avio context");
+        sLog.exception ("Cannot create avio context");
 
     // continue the normal load procedure
     this->loadCustomContent ();
@@ -185,9 +186,9 @@ void CAudioStream::loadCustomContent (const char* filename)
     AVCodecContext* avCodecContext = nullptr;
 
     if (avformat_open_input (&this->m_formatContext, filename, nullptr, nullptr) != 0)
-        throw std::runtime_error ("Cannot open audio file");
+        sLog.exception ("Cannot open audio file: ", filename);
     if (avformat_find_stream_info (this->m_formatContext, nullptr) < 0)
-        throw std::runtime_error ("Cannot determine file format");
+        sLog.exception ("Cannot determine file format: ", filename);
 
     // find the audio stream
     for (int i = 0; i< this->m_formatContext->nb_streams; i ++)
@@ -197,19 +198,19 @@ void CAudioStream::loadCustomContent (const char* filename)
     }
 
     if (this->m_audioStream == -1)
-        throw std::runtime_error ("Cannot find audio stream in file");
+        sLog.exception ("Cannot find an audio stream in file ", filename);
 
     // get the decoder for it and alloc the required context
     aCodec = avcodec_find_decoder (this->m_formatContext->streams [this->m_audioStream]->codecpar->codec_id);
 
     if (aCodec == nullptr)
-        throw std::runtime_error ("Cannot initialize audio decoder");
+        sLog.exception ("Cannot initialize audio decoder for file: ", filename);
 
     // alocate context
     avCodecContext = avcodec_alloc_context3 (aCodec);
 
     if (avcodec_parameters_to_context (avCodecContext, this->m_formatContext->streams [this->m_audioStream]->codecpar) != 0)
-        throw std::runtime_error ("Cannot initialize audio decoder parameters");
+        sLog.exception ("Cannot initialize audio decoder parameters");
 
     // finally open
     avcodec_open2 (avCodecContext, aCodec, nullptr);
@@ -246,8 +247,9 @@ void CAudioStream::initialize ()
     requestedSpec.callback = audio_callback;
     requestedSpec.userdata = this;
 
-    if (SDL_OpenAudio (&requestedSpec, &finalSpec) < 0) {
-        std::cerr << "SDL_OpenAudio: " << SDL_GetError () << std::endl;
+    if (SDL_OpenAudio (&requestedSpec, &finalSpec) < 0)
+    {
+        sLog.error ("SDL_OpenAudio: ", SDL_GetError ());
         return;
     }
 

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

@@ -1,3 +1,4 @@
+#include "common.h"
 #include "CObject.h"
 
 #include <utility>
@@ -115,7 +116,7 @@ CObject* CObject::fromJSON (json data, CScene* scene, const CContainer* containe
     }
     else
     {
-        throw std::runtime_error (std::string ("Unkonwn object type detected ").append (*name_it));
+        sLog.exception ("Unknown object type detected: ", *name_it);
     }
 
     if (effects_it != data.end () && (*effects_it).is_array () == true)

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

@@ -1,3 +1,4 @@
+#include "common.h"
 #include <WallpaperEngine/Assets/CContainer.h>
 #include <WallpaperEngine/FileSystem/FileSystem.h>
 
@@ -38,9 +39,9 @@ CProject* CProject::fromFile (const std::string& filename, CContainer* container
         wallpaper = new CVideo (file.c_str ());
     }
     else if (type == "web")
-        throw std::runtime_error ("Web wallpapers not supported yet");
+        sLog.exception ("Web wallpapers are not supported yet");
     else
-        throw std::runtime_error ("Unsupported wallpaper type");
+        sLog.exception ("Unsupported wallpaper type: ", type);
 
     CProject* project = new CProject (
         title,

+ 7 - 9
src/WallpaperEngine/Core/Core.cpp

@@ -1,3 +1,5 @@
+#include "common.h"
+
 #include "Core.h"
 
 #include "WallpaperEngine/Core/UserSettings/CUserSettingBoolean.h"
@@ -82,9 +84,7 @@ nlohmann::json::iterator Core::jsonFindRequired (nlohmann::json& data, const cha
     auto value = data.find (key);
 
     if (value == data.end ())
-    {
-        throw std::runtime_error (notFoundMsg);
-    }
+        sLog.exception ("Cannot find required key (", key, ") in json: ", notFoundMsg);
 
     return value;
 }
@@ -94,9 +94,7 @@ nlohmann::json::iterator Core::jsonFindRequired (nlohmann::json::iterator& data,
     auto value = (*data).find (key);
 
     if (value == (*data).end ())
-    {
-        throw std::runtime_error (notFoundMsg);
-    }
+        sLog.exception ("Cannot find required key (", key, ") in json: ", notFoundMsg);
 
     return value;
 }
@@ -115,18 +113,18 @@ template <typename T> T Core::jsonFindDefault (nlohmann::json& data, const char
             value->type () != nlohmann::detail::value_t::number_integer &&
             value->type () != nlohmann::detail::value_t::number_unsigned)
         {
-            fprintf(stderr, "%s is not of type double or integer, returning default value\n", key);
+            sLog.error (key, " is not of type double or integer, returning default value");
             return defaultValue;
         }
     }
     else if (std::is_same <T, std::string>::value && value->type () != nlohmann::detail::value_t::string)
     {
-        fprintf (stderr, "%s is not of type string, returning default value\n", key);
+        sLog.error (key, " is not of type string, returning default value");
         return defaultValue;
     }
     else if (std::is_same <T, bool>::value && value->type () != nlohmann::detail::value_t::boolean)
     {
-        fprintf (stderr, "%s is not of type boolean, returning default value\n", key);
+        sLog.error (key, " is not of type boolean, returning default value");
         return defaultValue;
     }
 

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

@@ -1,3 +1,4 @@
+#include "common.h"
 #include "CEffect.h"
 
 #include <utility>
@@ -167,13 +168,14 @@ void CEffect::constantsFromJSON (json::const_iterator constants_it, Core::Object
         // if the constant is an object, that means the constant has some extra information
         // for the UI, take the value, which is what we need
 
+        // TODO: SUPPORT USER SETTINGS HERE
         if ((*cur).is_object () == true)
         {
             val = (*cur).find ("value");
 
             if (val == (*cur).end ())
             {
-                std::cerr << "Found object for shader constant without \"value\" member" << std::endl;
+                sLog.error ("Found object for shader constant without \"value\" member");
                 continue;
             }
         }
@@ -193,7 +195,7 @@ void CEffect::constantsFromJSON (json::const_iterator constants_it, Core::Object
         }
         else
         {
-            throw std::runtime_error ("unknown shader constant type");
+            sLog.exception ("unknown shader constant type ", *val);
         }
 
         pass->insertConstant (cur.key (), constant);
@@ -236,9 +238,7 @@ void CEffect::materialsFromJSON (json::const_iterator passes_it, CEffect* effect
         auto bind = (*cur).find ("bind");
 
         if (materialfile == (*cur).end ())
-        {
-            throw std::runtime_error ("Effect pass must have a material file");
-        }
+            sLog.exception ("Found an effect ", effect->m_name, " without material");
 
         Images::CMaterial* material = nullptr;
 
@@ -301,7 +301,7 @@ Effects::CFBO* CEffect::findFBO (const std::string& name)
         }
     }
 
-    throw std::runtime_error ("cannot find fbo named " + name);
+    sLog.exception ("cannot find fbo ", name);
 }
 
 void CEffect::insertDependency (const std::string& dep)

+ 3 - 3
src/WallpaperEngine/Core/Objects/CSound.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include "WallpaperEngine/Core/CObject.h"
 #include "CSound.h"
 
@@ -25,12 +26,11 @@ WallpaperEngine::Core::CObject* CSound::fromJSON (
         CUserSettingVector3* scale,
         const glm::vec3& angles)
 {
+    // TODO: PARSE AUDIO VOLUME
     auto sound_it = jsonFindRequired (data, "sound", "Sound information not present");
 
     if ((*sound_it).is_array () == false)
-    {
-        throw std::runtime_error ("Expected sound list");
-    }
+        sLog.exception ("Expected sound list on element ", name);
 
     CSound* sound = new CSound (
         scene,

+ 3 - 4
src/WallpaperEngine/Core/Objects/Images/Materials/CPass.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include "CPass.h"
 
 using namespace WallpaperEngine::Core::Objects::Effects::Constants;
@@ -27,9 +28,7 @@ CPass* CPass::fromJSON (json data)
     {
         // TODO: FETCH THIS FROM CImage TO MAKE IT COMPATIBLE WITH OLDER WALLPAPERS
         if ((*textures_it).is_array () == false)
-        {
-            throw std::runtime_error ("Textures for material must be a list");
-        }
+            sLog.exception ("Material's textures must be a list");
     }
 
     CPass* pass = new CPass (
@@ -73,7 +72,7 @@ CPass* CPass::fromJSON (json data)
             }
             else
             {
-                throw std::runtime_error ("unexpected non-integer combo");
+                sLog.exception ("unexpected non-integer combo on pass");
             }
         }
     }

+ 2 - 1
src/WallpaperEngine/Core/Objects/Particles/CInitializer.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include "CInitializer.h"
 
 #include "WallpaperEngine/Core/Objects/Particles/Initializers/CLifeTimeRandom.h"
@@ -51,7 +52,7 @@ CInitializer* CInitializer::fromJSON (json data)
     }
     else
     {
-        throw std::runtime_error ("Particle's got an unknown initializer");
+        sLog.exception ("Found unknown initializer for particles: ", *name_it);
     }
 }
 

+ 12 - 25
src/WallpaperEngine/Core/Objects/Particles/Initializers/CTurbulentVelocityRandom.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include "CTurbulentVelocityRandom.h"
 
 #include "WallpaperEngine/Core/Core.h"
@@ -13,37 +14,23 @@ CTurbulentVelocityRandom* CTurbulentVelocityRandom::fromJSON (json data, uint32_
     json::const_iterator timescale_it = data.find ("timescale");
 
     if (phasemax_it == data.end ())
-    {
-        throw std::runtime_error ("TurbulentVelocityRandom initializer must have a phasemax value");
-    }
-
+        sLog.exception ("TurbulentVelocityRandom initializer must have a phasemax value");
     if (scale_it == data.end ())
-    {
-        throw std::runtime_error ("TurbulentVelocityRandom initializer must have a scale value");
-    }
-
+        sLog.exception ("TurbulentVelocityRandom initializer must have a scale value");
     if (speedmax_it == data.end ())
-    {
-        throw std::runtime_error ("TurbulentVelocityRandom initializer must have a maximum speed value");
-    }
-
+        sLog.exception ("TurbulentVelocityRandom initializer must have a maximum speed value");
     if (speedmin_it == data.end ())
-    {
-        throw std::runtime_error ("TurbulentVelocityRandom initializer must have a minimum speed value");
-    }
-
+        sLog.exception ("TurbulentVelocityRandom initializer must have a minimum speed value");
     if (timescale_it == data.end ())
-    {
-        throw std::runtime_error ("TurbulentVelocityRandom initializer must have a timescale value");
-    }
+        sLog.exception ("TurbulentVelocityRandom initializer must have a timescale value");
 
     return new CTurbulentVelocityRandom (
-            id,
-            *phasemax_it,
-            *scale_it,
-            *timescale_it,
-            *speedmin_it,
-            *speedmax_it
+        id,
+        *phasemax_it,
+        *scale_it,
+        *timescale_it,
+        *speedmin_it,
+        *speedmax_it
     );
 }
 

+ 3 - 1
src/WallpaperEngine/Core/Projects/CProperty.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include <iostream>
 #include "CProperty.h"
 #include "CPropertyColor.h"
@@ -25,7 +26,8 @@ CProperty* CProperty::fromJSON (json data, const std::string& name)
 
 
     // show the error and ignore this property
-    std::cout << "Unexpected type for property:" << *type << std::endl << data << std::endl;
+    sLog.error ("Unexpected type for property: ", *type);
+    sLog.error (data);
 
     return nullptr;
 }

+ 3 - 2
src/WallpaperEngine/Core/Projects/CPropertyCombo.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include <sstream>
 
 #include "CPropertyCombo.h"
@@ -20,7 +21,7 @@ CPropertyCombo* CPropertyCombo::fromJSON (json data, const std::string& name)
     );
 
     if (options->is_array () == false)
-        throw std::runtime_error ("Property combo options should be an array");
+        sLog.exception ("Property combo options should be an array");
 
     auto cur = (*options).begin ();
     auto end = (*options).end ();
@@ -86,7 +87,7 @@ void CPropertyCombo::update (const std::string& value)
     }
 
     if (found == false)
-        throw std::runtime_error ("Assigning invalid value to property");
+        sLog.exception ("Assigning invalid value to property ", this->m_name);
 
     this->m_defaultValue = value;
 }

+ 2 - 1
src/WallpaperEngine/Core/Projects/CPropertySlider.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include <sstream>
 #include "CPropertySlider.h"
 
@@ -61,7 +62,7 @@ void CPropertySlider::update (const std::string& value)
     double newValue = atof (value.c_str ());
 
     if (newValue < this->m_min || newValue > this->m_max)
-        throw std::runtime_error ("Slider value is out of range");
+        sLog.exception ("Slider value (", newValue, ") is out of range (", this->m_min, ",", this->m_max, ")");
 
     this->m_value = newValue;
 }

+ 5 - 4
src/WallpaperEngine/Core/UserSettings/CUserSettingBoolean.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include "CUserSettingBoolean.h"
 #include "WallpaperEngine/Core/Core.h"
 
@@ -50,13 +51,13 @@ CUserSettingBoolean* CUserSettingBoolean::fromJSON (nlohmann::json& data)
         }
         else
         {
-            fprintf (stderr, "Boolean property doesn't have user member, this could mean an scripted value\n");
+            sLog.error ("Boolean property doesn't have user member, this could mean an scripted value");
         }
     }
     else
     {
         if (data.is_boolean () == false)
-            throw std::runtime_error ("Expected boolean value on user settings");
+            sLog.error ("Expected boolean value on user setting");
 
         defaultValue = data.get<bool> ();
     }
@@ -89,14 +90,14 @@ bool CUserSettingBoolean::processValue (const std::vector<Projects::CProperty*>&
             if (cur->is <CPropertyBoolean> ())
                 return cur->as <CPropertyBoolean> ()->getValue ();
 
-            throw std::runtime_error ("Property without condition must match type (boolean)");
+            sLog.exception ("Property without condition must match type boolean");
         }
 
         // TODO: properly validate this as the combos might be more than just strings?
         if (cur->is <CPropertyCombo> ())
             return cur->as <CPropertyCombo> ()->getValue () == this->m_expectedValue;
 
-        throw std::runtime_error ("Boolean property with condition doesn't match against combo value");
+        sLog.exception ("Boolean property with condition doesn't match against combo value");
     }
 
     return this->m_default;

+ 5 - 4
src/WallpaperEngine/Core/UserSettings/CUserSettingFloat.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include "CUserSettingFloat.h"
 #include "WallpaperEngine/Core/Core.h"
 
@@ -47,13 +48,13 @@ CUserSettingFloat* CUserSettingFloat::fromJSON (nlohmann::json& data)
         }
         else
         {
-            fprintf (stderr, "Boolean property doesn't have user member, this could mean an scripted value\n");
+            sLog.error ("Float property doesn't have user member, this could mean an scripted value");
         }
     }
     else
     {
         if (data.is_number () == false)
-            throw std::runtime_error ("Expected numeric value on user settings");
+            sLog.exception ("Expected numeric value on user settings");
 
         defaultValue = data.get<double> ();
     }
@@ -86,10 +87,10 @@ double CUserSettingFloat::processValue (const std::vector<Projects::CProperty*>&
             if (cur->is <CPropertySlider> ())
                 return cur->as <CPropertySlider> ()->getValue ();
 
-            throw std::runtime_error ("Property without condition must match type (slider)");
+            sLog.exception ("Property without condition must match type (slider)");
         }
 
-        throw std::runtime_error ("Boolean property with condition doesn't match against combo value");
+        sLog.exception ("Float property with condition doesn't match against combo value");
     }
 
     return this->m_default;

+ 5 - 4
src/WallpaperEngine/Core/UserSettings/CUserSettingVector3.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include "CUserSettingVector3.h"
 #include "WallpaperEngine/Core/Core.h"
 
@@ -48,13 +49,13 @@ CUserSettingVector3* CUserSettingVector3::fromJSON (nlohmann::json& data)
         }
         else
         {
-            fprintf (stderr, "Float color property doesn't have user member, this could mean an scripted value\n");
+            sLog.error ("Vector property doesn't have user member, this could mean an scripted value");
         }
     }
     else
     {
         if (data.is_string () == false)
-            throw std::runtime_error ("Expected float color value on user settings");
+            sLog.exception ("Expected vector value on user settings");
 
         defaultValue = WallpaperEngine::Core::aToColorf (data.get <std::string> ().c_str ());
     }
@@ -93,10 +94,10 @@ glm::vec3 CUserSettingVector3::processValue (const std::vector<Projects::CProper
                     cur->as <CPropertySlider> ()->getValue ()
                 };
 
-            throw std::runtime_error ("Property without condition must match type (color)");
+            sLog.exception ("Property without condition must match type (vector3)");
         }
 
-        throw std::runtime_error ("Color property with condition doesn't match against combo value");
+        sLog.exception ("Vector property with condition doesn't match against combo value");
     }
 
     return this->m_default;

+ 30 - 0
src/WallpaperEngine/Logging/CLog.cpp

@@ -0,0 +1,30 @@
+#include "CLog.h"
+
+#include <cassert>
+
+using namespace WallpaperEngine::Logging;
+
+CLog::CLog()
+{
+    assert (this->sInstance == nullptr);
+}
+
+CLog& CLog::get ()
+{
+    if (sInstance == nullptr)
+        sInstance.reset (new CLog ());
+
+    return *sInstance;
+}
+
+void CLog::addOutput (std::ostream* stream)
+{
+    this->mOutputs.push_back (stream);
+}
+
+void CLog::addError (std::ostream* stream)
+{
+    this->mErrors.push_back (stream);
+}
+
+std::shared_ptr <CLog> CLog::sInstance = nullptr;

+ 113 - 0
src/WallpaperEngine/Logging/CLog.h

@@ -0,0 +1,113 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <ostream>
+#include <sstream>
+
+namespace WallpaperEngine::Logging
+{
+    /**
+     * Singleton class, simplifies logging for the whole app
+     */
+    class CLog
+    {
+    public:
+        CLog ();
+
+        void addOutput (std::ostream* stream);
+        void addError (std::ostream* stream);
+
+        template<typename... Data>
+        void out (Data... data)
+        {
+            // buffer the string first
+            std::stringbuf buffer;
+            std::ostream bufferStream (&buffer);
+
+            ((bufferStream << std::forward<Data>(data)), ...);
+
+            // then send it to all the outputs configured
+            for (auto cur : this->mOutputs)
+                *cur << buffer.str () << std::endl;
+        }
+
+        template<typename... Data>
+        void debug (Data... data)
+        {
+#if DEBUG && !ERRORONLY
+            // buffer the string first
+            std::stringbuf buffer;
+            std::ostream bufferStream (&buffer);
+
+            ((bufferStream << std::forward<Data> (data)), ...);
+
+            // then send it to all the outputs configured
+            for (auto cur : this->mOutputs)
+                *cur << buffer.str () << std::endl;
+#endif /* DEBUG */
+        }
+
+        template<typename... Data>
+        void debugerror (Data... data)
+        {
+#if DEBUG && ERRORONLY
+            // buffer the string first
+            std::stringbuf buffer;
+            std::ostream bufferStream (&buffer);
+
+            ((bufferStream << std::forward<Data>(data)), ...);
+
+            // then send it to all the outputs configured
+            for (auto cur : this->mOutputs)
+                *cur << buffer.str () << std::endl;
+#endif /* DEBUG */
+        }
+
+        template<typename... Data>
+        void error (Data... data)
+        {
+            // buffer the string first
+            std::stringbuf buffer;
+            std::ostream bufferStream (&buffer);
+
+            ((bufferStream << std::forward<Data>(data)), ...);
+
+            // then send it to all the outputs configured
+            for (auto cur : this->mErrors)
+                *cur << buffer.str () << std::endl;
+        }
+
+        template<class EX, typename... Data>
+        [[noreturn]] void exception (Data... data)
+        {
+            // buffer the string first
+            std::stringbuf buffer;
+            std::ostream bufferStream (&buffer);
+
+            ((bufferStream << std::forward<Data>(data)), ...);
+
+            // then send it to all the outputs configured
+            for (auto cur : this->mErrors)
+                *cur << buffer.str () << std::endl;
+
+            // now throw the exception
+            throw EX (buffer.str ());
+        }
+
+        template<typename... Data>
+        [[noreturn]] void exception (Data... data)
+        {
+            this->exception <std::runtime_error> (data...);
+        }
+
+        static CLog& get ();
+
+    private:
+        std::vector <std::ostream*> mOutputs;
+        std::vector <std::ostream*> mErrors;
+        static std::shared_ptr<CLog> sInstance;
+    };
+}
+
+#define sLog (WallpaperEngine::Logging::CLog::get ())

+ 2 - 1
src/WallpaperEngine/Render/CFBO.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include "CFBO.h"
 
 using namespace WallpaperEngine::Render;
@@ -62,7 +63,7 @@ CFBO::CFBO (
 
     // ensure first framebuffer is okay
     if (glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
-        throw std::runtime_error ("Framebuffers are not properly set");
+        sLog.exception ("Framebuffers are not properly set");
 
     // clear the framebuffer
     glClear (GL_COLOR_BUFFER_BIT);

+ 19 - 18
src/WallpaperEngine/Render/CContext.cpp → src/WallpaperEngine/Render/CRenderContext.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include <iostream>
 #include <unistd.h>
 
@@ -8,7 +9,7 @@
 #include <GL/glew.h>
 #include <GL/glx.h>
 
-#include "CContext.h"
+#include "CRenderContext.h"
 #include "CVideo.h"
 
 using namespace WallpaperEngine::Render;
@@ -17,10 +18,10 @@ XErrorHandler originalErrorHandler;
 
 void CustomXIOErrorExitHandler (Display* dsp, void* userdata)
 {
-    auto context = static_cast <CContext*> (userdata);
+    auto context = static_cast <CRenderContext*> (userdata);
 
 #ifdef DEBUG
-    std::cerr << "Critical XServer error detected. Attempting to recover..." << std::endl;
+    sLog.debugerror ("Critical XServer error detected. Attempting to recover...");
 #endif /* DEBUG */
 
     // refetch all the resources
@@ -30,7 +31,7 @@ void CustomXIOErrorExitHandler (Display* dsp, void* userdata)
 int CustomXErrorHandler (Display* dpy, XErrorEvent* event)
 {
 #ifdef DEBUG
-    std::cerr << "Detected X error" << std::endl;
+    sLog.debugerror ("Detected X error");
 #endif /* DEBUG */
 
     // call the original handler so we can keep some information reporting
@@ -42,13 +43,13 @@ int CustomXErrorHandler (Display* dpy, XErrorEvent* event)
 int CustomXIOErrorHandler (Display* dsp)
 {
 #ifdef DEBUG
-    std::cerr << "Detected X IO error" << std::endl;
+    sLog.debugerror ("Detected X error");
 #endif /* DEBUG */
 
     return 0;
 }
 
-CContext::CContext (std::vector <std::string> screens, GLFWwindow* window, CContainer* container) :
+CRenderContext::CRenderContext (std::vector <std::string> screens, GLFWwindow* window, CContainer* container) :
     m_wallpaper (nullptr),
     m_screens (std::move (screens)),
     m_isRootWindow (m_screens.empty () == false),
@@ -60,7 +61,7 @@ CContext::CContext (std::vector <std::string> screens, GLFWwindow* window, CCont
     this->initializeViewports ();
 }
 
-void CContext::initializeViewports ()
+void CRenderContext::initializeViewports ()
 {
     if (this->m_isRootWindow == false || this->m_screens.empty () == true)
         return;
@@ -81,7 +82,7 @@ void CContext::initializeViewports ()
 
     if (!XRRQueryExtension (this->m_display, &xrandr_result, &xrandr_error))
     {
-        std::cerr << "XRandr is not present, cannot detect specified screens, running in window mode" << std::endl;
+        sLog.error ("XRandr is not present, cannot detect specified screens, running in window mode");
         return;
     }
 
@@ -120,7 +121,7 @@ void CContext::initializeViewports ()
             {
                 XRRCrtcInfo* crtc = XRRGetCrtcInfo (this->m_display, screenResources, info->crtc);
 
-                std::cout << "Found requested screen: " << info->name << " -> " << crtc->x << "x" << crtc->y << ":" << crtc->width << "x" << crtc->height << std::endl;
+                sLog.out ("Found requested screen: ", info->name, " -> ", crtc->x, "x", crtc->y, ":", crtc->width, "x", crtc->height);
 
                 glm::ivec4 viewport = {
                     crtc->x, crtc->y, crtc->width, crtc->height
@@ -156,7 +157,7 @@ void CContext::initializeViewports ()
     this->m_image = XCreateImage (this->m_display, CopyFromParent, 24, ZPixmap, 0, this->m_imageData, fullWidth, fullHeight, 32, 0);
 }
 
-CContext::~CContext()
+CRenderContext::~CRenderContext ()
 {
     if (this->m_screens.empty () == false)
     {
@@ -168,7 +169,7 @@ CContext::~CContext()
     }
 }
 
-void CContext::render ()
+void CRenderContext::render ()
 {
     if (this->m_wallpaper == nullptr)
         return;
@@ -227,7 +228,7 @@ void CContext::render ()
         this->m_wallpaper->render (this->m_defaultViewport, true);
 }
 
-void CContext::setWallpaper (CWallpaper* wallpaper)
+void CRenderContext::setWallpaper (CWallpaper* wallpaper)
 {
     this->m_wallpaper = wallpaper;
 
@@ -248,32 +249,32 @@ void CContext::setWallpaper (CWallpaper* wallpaper)
     }
 }
 
-void CContext::setDefaultViewport (glm::vec4 defaultViewport)
+void CRenderContext::setDefaultViewport (glm::vec4 defaultViewport)
 {
     this->m_defaultViewport = defaultViewport;
 }
 
-CMouseInput* CContext::getMouse () const
+CMouseInput* CRenderContext::getMouse () const
 {
     return this->m_mouse;
 }
 
-void CContext::setMouse (CMouseInput* mouse)
+void CRenderContext::setMouse (CMouseInput* mouse)
 {
     this->m_mouse = mouse;
 }
 
-CWallpaper* CContext::getWallpaper () const
+CWallpaper* CRenderContext::getWallpaper () const
 {
     return this->m_wallpaper;
 }
 
-const CContainer* CContext::getContainer () const
+const CContainer* CRenderContext::getContainer () const
 {
     return this->m_container;
 }
 
-const ITexture* CContext::resolveTexture (const std::string& name)
+const ITexture* CRenderContext::resolveTexture (const std::string& name)
 {
     return this->m_textureCache->resolve (name);
 }

+ 3 - 3
src/WallpaperEngine/Render/CContext.h → src/WallpaperEngine/Render/CRenderContext.h

@@ -15,11 +15,11 @@ namespace WallpaperEngine::Render
     class CWallpaper;
     class CTextureCache;
 
-    class CContext
+    class CRenderContext
     {
     public:
-        CContext (std::vector <std::string> screens, GLFWwindow* window, CContainer* container);
-        ~CContext ();
+        CRenderContext (std::vector <std::string> screens, GLFWwindow* window, CContainer* container);
+        ~CRenderContext ();
 
         void initializeViewports ();
         void render ();

+ 5 - 3
src/WallpaperEngine/Render/CScene.cpp

@@ -1,3 +1,5 @@
+#include "common.h"
+
 #include "WallpaperEngine/Core/Objects/CImage.h"
 #include "WallpaperEngine/Core/Objects/CSound.h"
 
@@ -12,7 +14,7 @@ extern float g_TimeLast;
 using namespace WallpaperEngine;
 using namespace WallpaperEngine::Render;
 
-CScene::CScene (Core::CScene* scene, CContext* context) :
+CScene::CScene (Core::CScene* scene, CRenderContext* context) :
     CWallpaper (scene, Type, context)
 {
     // setup the scene camera
@@ -206,8 +208,8 @@ Render::CObject* CScene::createObject (Core::CObject* object)
         }
         catch (std::runtime_error ex)
         {
-            std::cerr << "Cannot setup image resource: " << std::endl;
-            std::cerr << ex.what () << std::endl;
+            // this error message is already printed, so just show extra info about it
+            sLog.error ("Cannot setup image ", image->getImage ()->getName ());
         }
 
         renderObject = image;

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

@@ -15,7 +15,7 @@ namespace WallpaperEngine::Render
     class CScene : public CWallpaper
     {
     public:
-        CScene (Core::CScene* scene, CContext* context);
+        CScene (Core::CScene* scene, CRenderContext* context);
 
         CCamera* getCamera () const;
 

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

@@ -2,7 +2,7 @@
 
 using namespace WallpaperEngine::Render;
 
-CTextureCache::CTextureCache (CContext* context) :
+CTextureCache::CTextureCache (CRenderContext* context) :
     m_context (context)
 {
 }

+ 4 - 4
src/WallpaperEngine/Render/CTextureCache.h

@@ -4,18 +4,18 @@
 #include <string>
 
 #include "WallpaperEngine/Assets/ITexture.h"
-#include "WallpaperEngine/Render/CContext.h"
+#include "WallpaperEngine/Render/CRenderContext.h"
 
 using namespace WallpaperEngine::Assets;
 
 namespace WallpaperEngine::Render
 {
-    class CContext;
+    class CRenderContext;
 
     class CTextureCache
     {
     public:
-        CTextureCache (CContext* context);
+        CTextureCache (CRenderContext* context);
         ~CTextureCache ();
 
         /**
@@ -36,7 +36,7 @@ namespace WallpaperEngine::Render
         void store (std::string name, const ITexture* texture);
 
     private:
-        CContext* m_context;
+        CRenderContext* m_context;
         std::map<std::string, const ITexture*> m_textureCache;
     };
 }

+ 16 - 15
src/WallpaperEngine/Render/CVideo.cpp

@@ -1,16 +1,17 @@
+#include "common.h"
 #include "CVideo.h"
 
 using namespace WallpaperEngine;
 using namespace WallpaperEngine::Render;
 
-CVideo::CVideo (Core::CVideo* video, CContext* context) :
+CVideo::CVideo (Core::CVideo* video, CRenderContext* context) :
     CWallpaper (video, Type, context)
 {
     if (avformat_open_input (&m_formatCtx, video->getFilename ().c_str (), NULL, NULL) < 0)
-        throw std::runtime_error ("Failed to open video file");
+        sLog.exception ("Failed to open video file ", video->getFilename ());
 
     if (avformat_find_stream_info (m_formatCtx, NULL) < 0)
-        throw std::runtime_error ("Failed to get stream info");
+        sLog.exception ("Failed to get stream info for video file ", video->getFilename ());
 
     // Find first video stream
     for (int i = 0; i < m_formatCtx->nb_streams; i++)
@@ -34,32 +35,32 @@ CVideo::CVideo (Core::CVideo* video, CContext* context) :
 
     // Only video stream is required
     if (m_videoStream == -1)
-        throw std::runtime_error ("Failed to find video stream");
+        sLog.exception ("Failed to find video stream for file ", video->getFilename ());
 
     const AVCodec* codec = avcodec_find_decoder (m_formatCtx->streams [m_videoStream]->codecpar->codec_id);
     if (codec == nullptr)
-        throw std::runtime_error ("Failed to find codec");
+        sLog.exception ("Failed to find codec for video ", video->getFilename ());
 
     m_codecCtx = avcodec_alloc_context3 (codec);
     if (avcodec_parameters_to_context (m_codecCtx, m_formatCtx->streams [m_videoStream]->codecpar))
-        throw std::runtime_error ("Failed to copy codec parameters");
+        sLog.exception ("Failed to copy codec parameters when playing video ", video->getFilename ());
 
     if (avcodec_open2 (m_codecCtx, codec, NULL) < 0)
-        throw std::runtime_error ("Failed to open codec");
+        sLog.exception ("Failed to open coded for playback of video ", video->getFilename ());
 
     // initialize audio if there's any audio stream
     if (m_audioStream != -1)
     {
         const AVCodec* audioCodec = avcodec_find_decoder (m_formatCtx->streams [m_audioStream]->codecpar->codec_id);
         if (audioCodec == nullptr)
-            throw std::runtime_error ("Failed to find codec");
+            sLog.exception ("Failed to find coded for audio in video ", video->getFilename ());
 
         AVCodecContext* audioContext = avcodec_alloc_context3 (audioCodec);
         if (avcodec_parameters_to_context (audioContext, m_formatCtx->streams [m_audioStream]->codecpar))
-            throw std::runtime_error ("Failed to copy codec parameters");
+            sLog.exception ("Failed to setup audio context for video ", video->getFilename ());
 
         if (avcodec_open2 (audioContext, audioCodec, NULL) < 0)
-            throw std::runtime_error ("Failed to open codec");
+            sLog.exception ("Failed to open audio coded for video ", video->getFilename ());
 
         this->m_audio = new Audio::CAudioStream (audioContext);
     }
@@ -67,7 +68,7 @@ CVideo::CVideo (Core::CVideo* video, CContext* context) :
     m_videoFrame = av_frame_alloc ();
     m_videoFrameRGB = av_frame_alloc ();
     if (m_videoFrameRGB == nullptr)
-        throw std::runtime_error ("Failed to allocate video frame");
+        sLog.exception ("Cannot allocate video frame");
 
     GLfloat texCoords [] = {
         0.0f, 1.0f,
@@ -189,7 +190,7 @@ void CVideo::getNextFrame ()
         else if (readError < 0)
         {
             char err[AV_ERROR_MAX_STRING_SIZE];
-            throw std::runtime_error (av_make_error_string (err, AV_ERROR_MAX_STRING_SIZE, readError));
+            sLog.exception (av_make_error_string (err, AV_ERROR_MAX_STRING_SIZE, readError));
         }
         
     } while (packet.stream_index != m_videoStream /*&& packet.stream_index != m_audioStream*/);
@@ -281,7 +282,7 @@ void CVideo::setupShaders ()
         // free the buffer
         delete[] logBuffer;
         // throw an exception
-        throw std::runtime_error (message);
+        sLog.exception (message);
     }
 
     // reserve shaders in OpenGL
@@ -317,7 +318,7 @@ void CVideo::setupShaders ()
         // free the buffer
         delete[] logBuffer;
         // throw an exception
-        throw std::runtime_error (message);
+        sLog.exception (message);
     }
 
     // create the final program
@@ -345,7 +346,7 @@ void CVideo::setupShaders ()
         // free the buffer
         delete[] logBuffer;
         // throw an exception
-        throw std::runtime_error (message);
+        sLog.exception (message);
     }
 
     // after being liked shaders can be dettached and deleted

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

@@ -18,7 +18,7 @@ namespace WallpaperEngine::Render
     class CVideo : public CWallpaper
     {
     public:
-        CVideo (Core::CVideo* video, CContext* context);
+        CVideo (Core::CVideo* video, CRenderContext* context);
 
         Core::CVideo* getVideo ();
 

+ 9 - 8
src/WallpaperEngine/Render/CWallpaper.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include "CWallpaper.h"
 #include "CScene.h"
 #include "CVideo.h"
@@ -8,7 +9,7 @@
 
 using namespace WallpaperEngine::Render;
 
-CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CContext* context) :
+CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext* context) :
     m_wallpaperData (wallpaperData),
     m_type (std::move(type)),
     m_context (context),
@@ -109,7 +110,7 @@ void CWallpaper::setupShaders ()
         // free the buffer
         delete[] logBuffer;
         // throw an exception
-        throw std::runtime_error (message);
+        sLog.exception (message);
     }
 
     // reserve shaders in OpenGL
@@ -145,7 +146,7 @@ void CWallpaper::setupShaders ()
         // free the buffer
         delete[] logBuffer;
         // throw an exception
-        throw std::runtime_error (message);
+        sLog.exception (message);
     }
 
     // create the final program
@@ -173,7 +174,7 @@ void CWallpaper::setupShaders ()
         // free the buffer
         delete[] logBuffer;
         // throw an exception
-        throw std::runtime_error (message);
+        sLog.exception (message);
     }
 
     // after being liked shaders can be dettached and deleted
@@ -351,7 +352,7 @@ void CWallpaper::setupFramebuffers ()
     );
 }
 
-CContext* CWallpaper::getContext ()
+CRenderContext* CWallpaper::getContext ()
 {
     return this->m_context;
 }
@@ -376,7 +377,7 @@ CFBO* CWallpaper::findFBO (const std::string& name) const
     auto it = this->m_fbos.find (name);
 
     if (it == this->m_fbos.end ())
-        throw std::runtime_error ("Cannot find given FBO");
+        sLog.exception ("Cannot find FBO ", name);
 
     return it->second;
 }
@@ -386,12 +387,12 @@ CFBO* CWallpaper::getFBO () const
     return this->m_sceneFBO;
 }
 
-CWallpaper* CWallpaper::fromWallpaper (Core::CWallpaper* wallpaper, CContext* context)
+CWallpaper* CWallpaper::fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext* context)
 {
     if (wallpaper->is <Core::CScene> () == true)
         return new WallpaperEngine::Render::CScene (wallpaper->as <Core::CScene> (), context);
     else if (wallpaper->is <Core::CVideo> () == true)
         return new WallpaperEngine::Render::CVideo (wallpaper->as <Core::CVideo> (), context);
     else
-        throw std::runtime_error ("Unsupported wallpaper type");
+        sLog.exception ("Unsupported wallpaper type");
 }

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

@@ -7,15 +7,15 @@
 #include "WallpaperEngine/Core/CScene.h"
 #include "WallpaperEngine/Core/CVideo.h"
 
-#include "WallpaperEngine/Assets/CContainer.h"
 #include "CFBO.h"
-#include "CContext.h"
+#include "CRenderContext.h"
+#include "WallpaperEngine/Assets/CContainer.h"
 
 using namespace WallpaperEngine::Assets;
 
 namespace WallpaperEngine::Render
 {
-    class CContext;
+    class CRenderContext;
 
     class CWallpaper
     {
@@ -25,7 +25,7 @@ namespace WallpaperEngine::Render
 
         template<class T> bool is () { return this->m_type == T::Type; }
 
-        CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CContext* context);
+        CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRenderContext* context);
         ~CWallpaper ();
 
         /**
@@ -41,7 +41,7 @@ namespace WallpaperEngine::Render
         /**
          * @return The current context rendering this wallpaper
          */
-        CContext* getContext ();
+        CRenderContext* getContext ();
 
         /**
          * @return The scene's framebuffer
@@ -95,7 +95,7 @@ namespace WallpaperEngine::Render
          *
          * @return
          */
-        static CWallpaper* fromWallpaper (Core::CWallpaper* wallpaper, CContext* context);
+        static CWallpaper* fromWallpaper (Core::CWallpaper* wallpaper, CRenderContext* context);
 
     protected:
         /**
@@ -149,6 +149,6 @@ namespace WallpaperEngine::Render
         /**
          * Context that is using this wallpaper
          */
-        CContext* m_context;
+        CRenderContext* m_context;
     };
 }

+ 3 - 0
src/WallpaperEngine/Render/Objects/CImage.cpp

@@ -334,6 +334,7 @@ void CImage::setupPasses ()
 
     for (; cur != end; cur ++)
     {
+        // TODO: PROPERLY CHECK EFFECT'S VISIBILITY AND TAKE IT INTO ACCOUNT
         Effects::CPass* pass = *cur;
         const CFBO* prevDrawTo = drawTo;
         GLuint spacePosition = (first) ? this->getCopySpacePosition () : this->getPassSpacePosition ();
@@ -356,6 +357,7 @@ void CImage::setupPasses ()
         // determine if it's the last element in the list as this is a screen-copy-like process
         else if (std::next (cur) == end && this->getImage ()->isVisible () == true)
         {
+            // TODO: PROPERLY CHECK EFFECT'S VISIBILITY AND TAKE IT INTO ACCOUNT
             spacePosition = this->getSceneSpacePosition ();
             drawTo = this->getScene ()->getFBO ();
             projection = &this->m_modelViewProjectionScreen;
@@ -423,6 +425,7 @@ void CImage::render ()
 
     for (; cur != end; cur ++)
     {
+        // TODO: PROPERLY CHECK EFFECT'S VISIBILITY AND TAKE IT INTO ACCOUNT
         if (std::next (cur) == end)
             glColorMask (true, true, true, false);
 

+ 13 - 5
src/WallpaperEngine/Render/Objects/Effects/CPass.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include <sstream>
 #include "CPass.h"
 #include "WallpaperEngine/Render/CFBO.h"
@@ -383,7 +384,7 @@ GLuint CPass::compileShader (Render::Shaders::Compiler* shader, GLuint type)
         // free the buffer
         delete[] logBuffer;
         // throw an exception
-        throw std::runtime_error (buffer.str());
+        sLog.exception (buffer.str ());
     }
 
     return shaderID;
@@ -459,7 +460,7 @@ void CPass::setupShaders ()
         // free the buffer
         delete[] logBuffer;
         // throw an exception
-        throw std::runtime_error (message);
+        sLog.exception (message);
     }
 
     if (DEBUG)
@@ -562,7 +563,7 @@ void CPass::setupUniforms ()
                 }
                 catch (std::runtime_error& ex)
                 {
-                    std::cerr << "Cannot resolve texture " << textureName << " for fragment shader: " << ex.what () << std::endl;
+                    sLog.error ("Cannot resolve texture ", textureName, " for fragment shader ", ex.what ());
                 }
 
                 fragCur ++;
@@ -591,7 +592,7 @@ void CPass::setupUniforms ()
                 }
                 catch (std::runtime_error& ex)
                 {
-                    std::cerr << "Cannot resolve texture " << textureName << " for vertex shader: " << ex.what () << std::endl;
+                    sLog.error ("Cannot resolve texture ", textureName, " for vertex shader ", ex.what ());
                 }
 
                 vertCur ++;
@@ -800,7 +801,14 @@ void CPass::setupShaderVariables ()
                 }
                 else
                 {
-                    throw std::runtime_error ("Constant and pixel/vertex variable are not of the same type");
+                    sLog.exception (
+                        "Constant ",
+                        (*cur).first,
+                        " type does not match pixel/vertex shader variable and cannot be converted (",
+                        (*cur).second->getType (),
+                        " to ",
+                        var->getType ()
+                    );
                 }
             }
             else

+ 9 - 11
src/WallpaperEngine/Render/Shaders/Compiler.cpp

@@ -1,3 +1,4 @@
+#include "common.h"
 #include <iostream>
 #include <fstream>
 #include <string>
@@ -248,7 +249,7 @@ namespace WallpaperEngine::Render::Shaders
     void Compiler::precompile()
     {
         // TODO: SEPARATE THIS IN TWO SO THE COMBOS ARE DETECTED FIRST AND WE DO NOT REQUIRE DOUBLE COMPILATION OF THE SHADER'S SOURCE
-    #define BREAK_IF_ERROR if (this->m_error == true) { throw std::runtime_error ("ERROR PRE-COMPILING SHADER" + this->m_errorInfo); }
+    #define BREAK_IF_ERROR if (this->m_error == true) { sLog.exception ("ERROR PRE-COMPILING SHADER.", this->m_errorInfo); }
         // parse the shader and find #includes and such things and translate them to the correct name
         // also remove any #version definition to prevent errors
         std::string::const_iterator it = this->m_content.begin ();
@@ -560,13 +561,10 @@ namespace WallpaperEngine::Render::Shaders
 
         finalCode += this->m_compiledContent;
 
-        if (DEBUG && this->m_recursive == false && !ERRORONLY)
+        if (this->m_recursive == false)
         {
-            if (this->m_type == Type_Vertex)
-                std::cout << "======================== COMPILED VERTEX SHADER " << this->m_file.c_str () << " ========================" << std::endl;
-            else
-                std::cout << "======================== COMPILED FRAGMENT SHADER " << this->m_file.c_str () << " ========================" << std::endl;
-            std::cout << finalCode << std::endl;
+            sLog.debug("======================== COMPILED ", (this->m_type == Type_Vertex ? "VERTEX" : "FRAGMENT"), " SHADER ", this->m_file, " ========================");
+            sLog.debug(finalCode);
         }
 
         // store the final final code here
@@ -601,7 +599,7 @@ namespace WallpaperEngine::Render::Shaders
             }
             else if ((*defvalue).is_number_float ())
             {
-                throw std::runtime_error ("float combos not supported");
+                sLog.exception ("float combos are not supported in shader ", this->m_file, ". ", *combo);
             }
             else if ((*defvalue).is_number_integer ())
             {
@@ -609,11 +607,11 @@ namespace WallpaperEngine::Render::Shaders
             }
             else if ((*defvalue).is_string ())
             {
-                throw std::runtime_error ("string combos not supported");
+                sLog.exception ("string combos are not supported in shader ", this->m_file, ". ", *combo);
             }
             else
             {
-                throw std::runtime_error ("cannot parse combo information, unknown type");
+                sLog.exception ("cannot parse combo information ", *combo, ". unknown type for ", defvalue->dump ());
             }
         }
     }
@@ -635,7 +633,7 @@ namespace WallpaperEngine::Render::Shaders
         if (constant == this->m_constants.end () && defvalue == data.end ())
         {
             if (type != "sampler2D")
-                throw std::runtime_error ("cannot parse parameter data");
+                sLog.exception ("Cannot parse parameter data for ", name, " in shader ", this->m_file);
         }
 
         Variables::CShaderVariable* parameter = nullptr;

+ 1 - 0
src/common.h

@@ -0,0 +1 @@
+#include "WallpaperEngine/Logging/CLog.h"