#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2023 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #ifndef NUCLEX_PLATFORM_LOCATIONS_STANDARDDIRECTORYRESOLVER_H #define NUCLEX_PLATFORM_LOCATIONS_STANDARDDIRECTORYRESOLVER_H #include "Nuclex/Platform/Config.h" #include // for std::string #include // for std::optional #include // for std::atomic #include // for std::mutex // Rename this to simply "StandardDirectoryLookup"? // * Support looking up locations // * Install folder (/opt, /usr/local/bin or C:\Program Files) // * Data folder (different on Linux, same on Windows) // * Savegame folder // * Per-user settings folder // * Per-machine settings folder // * Temp folder // // * Support locating the user's audio library? // * Standard 'Music' folder from xuserdirs and Microsoft's shit // * Defined music libraries from popular audio players if retrievable namespace Nuclex { namespace Platform { namespace Locations { // ------------------------------------------------------------------------------------------- // /// /// Looks up and reports common directories based on a platform's conventients and /// any configuration that needs to be honored /// /// /// On Windows, this looks up the known folders via its classic Windows API interface /// and, for extended folders, via COM. On Linux, this follows the XDG specification /// which defines standard user directories and methods to override them via environment /// variable and the user-dirs.dirs file. /// class NUCLEX_PLATFORM_TYPE StandardDirectoryResolver { /// Initializes a new common directory resolver /// /// Name of the application subdirectory on Linux, should be all-lowercase and /// either a single word or as few words as possible separated by dashes. /// /// /// Name of the application subdirectory on Windows, should be in title case /// and use spaces inbetween words. /// /// /// This constructor is provided for your convenience, so you can keep macros /// selecting between Windows/Linux code paths to a minimum in your code. /// public: NUCLEX_PLATFORM_API StandardDirectoryResolver( const std::string &linuxStyleApplicationDirectoryName, const std::string &windowsStyleApplicationDirectoryName ) : #if defined(NUCLEX_PLATFORM_WINDOWS) StandardDirectoryResolver(windowsStyleApplicationDirectoryName) { (void)linuxStyleApplicationDirectoryName; // prevent unused variable warning } #else StandardDirectoryResolver(linuxStyleApplicationDirectoryName) { (void)windowsStyleApplicationDirectoryName; // prevent unused variable warning } #endif /// Initializes a new common directory resolver /// /// Name of the application subdirectory. If specified, it will be injected into /// any paths returned where appropriate. /// /// /// It is a good idea to also follow a platform's unwritten conventions. For Windows /// builds, passing a human-readable name (starting words with uppercase letters and /// using spaces if needed) is advices. For Linux builds, using an all-lowercase name /// without spaces will make it fit in better (though neither platform has any firm /// rules requiring this). /// public: NUCLEX_PLATFORM_API StandardDirectoryResolver( const std::string &applicationName = std::string() ); /// Frees all resources owned by the directory resolver public: NUCLEX_PLATFORM_API ~StandardDirectoryResolver(); /// Returns the directory your executable is running from /// The directory in which the running executable is stored /// /// /// On Windows systems, it has become the convention to also store static data files, /// such as images used in the UI, documentation ("help files") or a game's data files /// containing all its audio, textures and levels. /// /// /// Please use the directory returned by for /// such files instead. /// /// public: NUCLEX_PLATFORM_API std::string GetExecutableDirectory() const; /// Returns the directory your application's static data is stored in /// The directory in which static application data is stored /// /// Whereas this directory will be the same as the executable directory on Windows /// systems, on Linux it will point either to /opt/application-name or, /// when installed by a package manager that treats it as a standard application, /// to /usr/share/application-name. /// public: NUCLEX_PLATFORM_API std::string GetStaticDataDirectory() const; /// Retrieves the settings directory for user-specific settings /// The directory in which user-specific settings can be stored /// /// /// Use this to store user settings. Ideally, make it settings that only apply /// to the user, but not the machine the application is running on. That might be /// custom keyboard shortcuts, selected theme, favorites or turned-off notifications. /// /// /// Things stored in this directory could theoretically be moved to another system /// or downloaded from a server when the user logs in. Windows users call this /// "roaming" data. /// /// public: NUCLEX_PLATFORM_API std::string GetSettingsDirectory() const; /// Retrieves the state directory retaining the application's state /// The directory in which the application's state can be saved /// /// This directory is intended to store things that are either trivial (such as window /// layouts, most recently opened files and so on) and things that can not be ported /// to other systems, such as a list of running or monitored jobs on the system, but /// also the preferred graphics adapter or machine-specific performance adjustments. /// public: NUCLEX_PLATFORM_API std::string GetStateDirectory() const; /// Retrieves the cache directory for semi-temporary data /// The directory in which the application can cache things /// /// This directory is intended for files you would prefer to keep around, but which /// can be trivially regenerated by your application should they disappear. Windows /// applications generally just use the local appdata directory, but Linux systems /// reserve /var/cache/my-application/ for such cases. Cached data may be thumbnails /// or movie files, shaders specifically compiled for the installed GPU brand or /// an index database for files managed by your application. /// public: NUCLEX_PLATFORM_API std::string GetCacheDirectory() const; /// Retrieves the documents directory of the current user /// The directory in which created documents should be saved /// /// Documents are typically any files explicitly created by the user through a /// "save" dialog and that they may wish to share with others or copy /// around to other systems, TVs or phones. /// public: NUCLEX_PLATFORM_API std::string GetDocumentsDirectory() const; /// Retrieves the directory in which video games should store save states /// The directory in which video games should store save states /// /// Recent Windows versions introduced a special Saved Games directory /// for this purpose, whereas it has become semi-established practices to create /// a Saves Games\My Game directory in the user's Documents /// folder. Linux doesn't have an equivalent directory, but the best equivalent location /// is ~/.local/share/my-game/saves (it's state data, but it's important /// to the user and should move with them to the next system, so it belongs in /// ~/.local/share). /// public: NUCLEX_PLATFORM_API std::string GetSavedGameDirectory() const; /// Retrieves the system's temporary directory /// The directory in which temporary files can be stored /// /// This is for short-lived files your application may have to store for various reaons, /// such as when it has to invoke an external tool than only knows how to handle files. /// Windows systems usually have no automated that clean up the temp directory (the /// manually launched "Disk Cleanup" does it). On Linux systems, the contents /// of the temp directory generally vanish after a reboot, commonly because a ramdisk /// is used. /// public: NUCLEX_PLATFORM_API std::string GetTemporaryDirectory() const; // GetMediaDirectory() // MediaType::Music directory // MediaType::Pictures directory // MediaType::Videos directory // GetSaveGameDirectory() // GetDocumentsDirectory() /// Platform-specific code to locate the executable directory /// The full path to the directory holding the running executable private: static std::string locateExecutableDirectory(); /// Platform-specific code to locate the static data directory /// The full path to the directory holding static application data private: static std::string locateStaticDataDirectory(); /// Platform-specific code to locate the settings directory /// The full path to the directory holding application settings private: static std::string locateSettingsDirectory(); /// Platform-specific code to locate the state directory /// The full path to the directory holding the application's state private: static std::string locateStateDirectory(); /// Name of the application (directory) in the file system private: std::string applicationName; /// Can be held by the methods as directories are figured out private: mutable std::mutex updateMutex; /// Whether the executable directory has been determined yet private: mutable std::atomic executableDirectoryKnown; /// The path in which the running executable resides private: mutable std::string executableDirectory; /// Whether the static data directory has been determined yet private: mutable std::atomic staticDataDirectoryKnown; /// Path to the application's static data directory private: mutable std::string staticDataDirectory; /// Whether the settings directory has been determined yet private: mutable std::atomic settingsDirectoryKnown; /// Path to the settings directory private: mutable std::string settingsDirectory; /// Whether the state directory has been determined yet private: mutable std::atomic stateDirectoryKnown; /// Path to the state directory private: mutable std::string stateDirectory; }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Platform::Locations #endif // NUCLEX_PLATFORM_LOCATIONS_STANDARDDIRECTORYRESOLVER_H