X-Git-Url: https://main.carlh.net/gitweb/?p=ardour.git;a=blobdiff_plain;f=libs%2Fardour%2Ffilesystem_paths.cc;h=47b9994cc6c9229e6090e0f5128d98d50872e455;hp=cd78397f3e6e98b7d01939d93b9f3f7f2c91ae8e;hb=c8c6bca6587450ff64303dbc994a4cd28d6ce7aa;hpb=a39990dee0dd6688ef45b29aa96595e71276a0c6 diff --git a/libs/ardour/filesystem_paths.cc b/libs/ardour/filesystem_paths.cc index cd78397f3e..47b9994cc6 100644 --- a/libs/ardour/filesystem_paths.cc +++ b/libs/ardour/filesystem_paths.cc @@ -19,8 +19,9 @@ #include #include -#include "pbd/error.h" #include "pbd/compose.h" +#include "pbd/convert.h" +#include "pbd/error.h" #include #include @@ -28,7 +29,12 @@ #include "ardour/directory_names.h" #include "ardour/filesystem_paths.h" -#include "i18n.h" +#include "pbd/i18n.h" + +#ifdef PLATFORM_WINDOWS +#include "shlobj.h" +#include "pbd/windows_special_dirs.h" +#endif using namespace PBD; @@ -36,46 +42,155 @@ namespace ARDOUR { using std::string; +static std::string +user_config_directory_name (int version = -1) +{ + if (version < 0) { + version = atoi (X_(PROGRAM_VERSION)); + } + + /* ARDOUR::Profile may not be available when this is + called, so rely on build-time detection of the + product name etc. + */ + +#ifdef USE_TRACKS_CODE_FEATURES + /* Tracks does not use versioned configuration folders, which may or + may not be problematic in the future. + */ + return X_(PROGRAM_NAME); + +#else + const string config_dir_name = string_compose ("%1%2", X_(PROGRAM_NAME), version); + +#if defined (__APPLE__) || defined (PLATFORM_WINDOWS) + /* Use mixed-case folder name on OS X and Windows */ + return config_dir_name; +#else + /* use lower case folder name on Linux */ + return downcase (config_dir_name); +#endif +#endif +} + std::string -user_config_directory () +user_config_directory (int version) { std::string p; #ifdef __APPLE__ + p = Glib::build_filename (Glib::get_home_dir(), "Library/Preferences"); -#else - const char* c = 0; - /* adopt freedesktop standards, and put .ardour3 into $XDG_CONFIG_HOME or ~/.config - */ +#else + const char* c = 0; + /* adopt freedesktop standards, and put .ardour3 into $XDG_CONFIG_HOME or ~/.config */ if ((c = getenv ("XDG_CONFIG_HOME")) != 0) { p = c; } else { - const string home_dir = Glib::get_home_dir(); +#ifdef PLATFORM_WINDOWS + // Not technically the home dir (since it needs to be a writable folder) + const string home_dir = Glib::get_user_config_dir(); +#else + const string home_dir = Glib::get_home_dir(); +#endif if (home_dir.empty ()) { error << "Unable to determine home directory" << endmsg; exit (1); } - p = home_dir; + +#ifndef PLATFORM_WINDOWS p = Glib::build_filename (p, ".config"); +#endif + + } +#endif // end not __APPLE__ + + p = Glib::build_filename (p, user_config_directory_name (version)); + + if (version < 0) { + /* Only create the user config dir if the version was negative, + meaning "for the current version. + */ + if (!Glib::file_test (p, Glib::FILE_TEST_EXISTS)) { + if (g_mkdir_with_parents (p.c_str(), 0755)) { + error << string_compose (_("Cannot create Configuration directory %1 - cannot run"), + p) << endmsg; + exit (1); + } + } else if (!Glib::file_test (p, Glib::FILE_TEST_IS_DIR)) { + fatal << string_compose (_("Configuration directory %1 already exists and is not a directory/folder - cannot run"), + p) << endmsg; + abort(); /*NOTREACHED*/ + } } + + return p; +} + +std::string +user_cache_directory () +{ + static std::string p; + + if (!p.empty()) return p; + +#ifdef __APPLE__ + p = Glib::build_filename (Glib::get_home_dir(), "Library/Caches"); +#else + const char* c = 0; + + /* adopt freedesktop standards, and put .ardour3 into $XDG_CACHE_HOME + * defaulting to or ~/.config + */ + if ((c = getenv ("XDG_CACHE_HOME")) != 0) { + p = c; + } else { + +#ifdef PLATFORM_WINDOWS + // Not technically the home dir (since it needs to be a writable folder) + const string home_dir = Glib::get_user_data_dir(); +#else + const string home_dir = Glib::get_home_dir(); #endif + if (home_dir.empty ()) { + error << "Unable to determine home directory" << endmsg; + exit (1); + } + p = home_dir; - p = Glib::build_filename (p, user_config_dir_name); +#ifndef PLATFORM_WINDOWS + p = Glib::build_filename (p, ".cache"); +#endif + + } +#endif // end not __APPLE__ + + p = Glib::build_filename (p, user_config_directory_name ()); + +#ifdef PLATFORM_WINDOWS + /* On Windows Glib::get_user_data_dir is the folder to use for local + * (as opposed to roaming) application data. + * See documentation for CSIDL_LOCAL_APPDATA. + * Glib::get_user_data_dir() == GLib::get_user_config_dir() + * so we add an extra subdir *below* the config dir. + */ + p = Glib::build_filename (p, "cache"); +#endif if (!Glib::file_test (p, Glib::FILE_TEST_EXISTS)) { if (g_mkdir_with_parents (p.c_str(), 0755)) { - error << string_compose (_("Cannot create Configuration directory %1 - cannot run"), + error << string_compose (_("Cannot create cache directory %1 - cannot run"), p) << endmsg; exit (1); } } else if (!Glib::file_test (p, Glib::FILE_TEST_IS_DIR)) { - error << string_compose (_("Configuration directory %1 already exists and is not a directory/folder - cannot run"), + fatal << string_compose (_("Cache directory %1 already exists and is not a directory/folder - cannot run"), p) << endmsg; - exit (1); + abort(); /*NOTREACHED*/ } return p; @@ -84,52 +199,120 @@ user_config_directory () std::string ardour_dll_directory () { +#ifdef PLATFORM_WINDOWS + std::string dll_dir_path(windows_package_directory_path()); + dll_dir_path = Glib::build_filename (dll_dir_path, "lib"); + return Glib::build_filename (dll_dir_path, LIBARDOUR); +#else std::string s = Glib::getenv("ARDOUR_DLL_PATH"); if (s.empty()) { std::cerr << _("ARDOUR_DLL_PATH not set in environment - exiting\n"); ::exit (1); - } + } return s; +#endif } -SearchPath +#ifdef PLATFORM_WINDOWS +Searchpath +windows_search_path () +{ + std::string dll_dir_path(windows_package_directory_path()); + dll_dir_path = Glib::build_filename (dll_dir_path, "share"); + return Glib::build_filename (dll_dir_path, LIBARDOUR); +} + +std::string +windows_package_directory_path () +{ + char* package_dir = + g_win32_get_package_installation_directory_of_module (NULL); + + if (package_dir == NULL) { + fatal << string_compose (_("Cannot determine %1 package directory"), + PROGRAM_NAME) << endmsg; + abort(); /*NOTREACHED*/ + } + + std::string package_dir_path(package_dir); + g_free(package_dir); + return package_dir_path; +} +#endif + +Searchpath ardour_config_search_path () { - static SearchPath search_path; + static Searchpath search_path; if (search_path.empty()) { + // Start by adding the user's personal config folder search_path += user_config_directory(); - +#ifdef PLATFORM_WINDOWS + // On Windows, add am intermediate configuration folder + // (one that's guaranteed to be writable by all users). + const gchar* const *all_users_folder = g_get_system_config_dirs(); + // Despite its slightly odd name, the above returns a single entry which + // corresponds to 'All Users' on Windows (according to the documentation) + + if (all_users_folder) { + std::string writable_all_users_path = all_users_folder[0]; + writable_all_users_path += "\\"; + writable_all_users_path += PROGRAM_NAME; + writable_all_users_path += "\\.config"; +#ifdef _WIN64 + writable_all_users_path += "\\win64"; +#else + writable_all_users_path += "\\win32"; +#endif + search_path += writable_all_users_path; + } + + // now add a suitable config path from the bundle + search_path += windows_search_path (); +#endif + // finally, add any paths from ARDOUR_CONFIG_PATH if it exists std::string s = Glib::getenv("ARDOUR_CONFIG_PATH"); if (s.empty()) { - std::cerr << _("ARDOUR_CONFIG_PATH not set in environment - exiting\n"); - ::exit (1); + std::cerr << _("ARDOUR_CONFIG_PATH not set in environment\n"); + } else { + search_path += Searchpath (s); } - - search_path += SearchPath (s); } return search_path; } -SearchPath +Searchpath ardour_data_search_path () { - static SearchPath search_path; + static Searchpath search_path; if (search_path.empty()) { search_path += user_config_directory(); - +#ifdef PLATFORM_WINDOWS + search_path += windows_search_path (); +#endif std::string s = Glib::getenv("ARDOUR_DATA_PATH"); if (s.empty()) { - std::cerr << _("ARDOUR_DATA_PATH not set in environment - exiting\n"); - ::exit (1); + std::cerr << _("ARDOUR_DATA_PATH not set in environment\n"); + } else { + search_path += Searchpath (s); } - - search_path += SearchPath (s); } return search_path; } +string +been_here_before_path (int version) +{ + if (version < 0) { + version = atoi (PROGRAM_VERSION); + } + + return Glib::build_filename (user_config_directory (version), string (".a") + to_string (version, std::dec)); +} + + } // namespace ARDOUR