From b0e223ff3c8eb34bfe676a8e412b4c9f717cce08 Mon Sep 17 00:00:00 2001 From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> Date: Fri, 12 Apr 2024 16:54:30 -0400 Subject: [PATCH] misc: add an API to set the client app's resource directory path This approach allows client apps that install ringtones (and any other resources) in custom locations to specify that directory at runtime. This will take precedence over the build time data directory supplied for platforms which install to a fixed path. https: //git.jami.net/savoirfairelinux/jami-client-qt/-/issues/1619 Change-Id: I81616f79196e645a5ad677d6956be6a2ffcd976a --- CMakeLists.txt | 2 +- bin/osxmain.cpp | 11 +++----- bin/winmain.cpp | 11 +++----- configure.ac | 2 +- meson.build | 2 +- src/account.cpp | 5 +++- src/client/configurationmanager.cpp | 6 ++++ src/fileutils.cpp | 34 ++++++++++++----------- src/fileutils.h | 21 ++++++++++---- src/jami/configurationmanager_interface.h | 5 ++++ 10 files changed, 60 insertions(+), 39 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dd183360d..6c109c48c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.16) project(jami-core - VERSION 15.2.0 + VERSION 15.3.0 LANGUAGES C CXX) set(PACKAGE_NAME "Jami Daemon") set (CMAKE_CXX_STANDARD 17) diff --git a/bin/osxmain.cpp b/bin/osxmain.cpp index deb81ce087..772245de47 100644 --- a/bin/osxmain.cpp +++ b/bin/osxmain.cpp @@ -26,6 +26,7 @@ #include <getopt.h> #include <string> #include <chrono> +#include <filesystem> #include "jami.h" #include "callmanager_interface.h" @@ -194,13 +195,9 @@ signal_handler(int code) int main(int argc, char *argv []) { - // make a copy as we don't want to modify argv[0], copy it to a vector to - // guarantee that memory is correctly managed/exception safe - std::string programName {argv[0]}; - std::vector<char> writable(programName.size() + 1); - std::copy(programName.begin(), programName.end(), writable.begin()); - - jami::fileutils::set_program_dir(writable.data()); + // Set the program's directory path as the resource directory path. + std::filesystem::path programPath(argv[0]); + jami::fileutils::set_resource_dir_path(programPath.parent_path()); #ifdef TOP_BUILDDIR if (!getenv("CODECS_PATH")) diff --git a/bin/winmain.cpp b/bin/winmain.cpp index f83254255d..106cc9afdd 100644 --- a/bin/winmain.cpp +++ b/bin/winmain.cpp @@ -24,6 +24,7 @@ #include <signal.h> #include <getopt.h> #include <string> +#include <filesystem> #include "jami.h" #include "callmanager_interface.h" @@ -210,13 +211,9 @@ signal_handler(int code) int main(int argc, char *argv []) { - // make a copy as we don't want to modify argv[0], copy it to a vector to - // guarantee that memory is correctly managed/exception safe - std::string programName {argv[0]}; - std::vector<char> writable(programName.size() + 1); - std::copy(std::begin(programName), std::end(programName),std::begin(writable)); - - jami::fileutils::set_program_dir(writable.data()); + // Set the program's directory path as the resource directory path. + std::filesystem::path programPath(argv[0]); + jami::fileutils::set_resource_dir_path(programPath.parent_path()); print_title(); diff --git a/configure.ac b/configure.ac index a06483b447..20fe517a59 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl Jami - configure.ac dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([Jami Daemon],[15.2.0],[jami@gnu.org],[jami]) +AC_INIT([Jami Daemon],[15.3.0],[jami@gnu.org],[jami]) dnl Clear the implicit flags that default to '-g -O2', otherwise they dnl take precedence over the values we set via the diff --git a/meson.build b/meson.build index 10f9de9795..f23e7d3b49 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('jami-daemon', ['c', 'cpp'], - version: '15.2.0', + version: '15.3.0', license: 'GPL3+', default_options: ['cpp_std=gnu++17', 'buildtype=debugoptimized'], meson_version:'>= 0.56' diff --git a/src/account.cpp b/src/account.cpp index b2b8767d3c..3c6617ff54 100644 --- a/src/account.cpp +++ b/src/account.cpp @@ -157,7 +157,10 @@ Account::loadDefaultCodecs() void Account::loadConfig() { setActiveCodecs(config_->activeCodecs); - auto ringtoneDir = fmt::format("{}/{}", JAMI_DATADIR, RINGDIR); + + // Try to get the client-defined resource base directory, if any. If not set, use the default + // JAMI_DATADIR that was set at build time. + auto ringtoneDir = fileutils::get_resource_dir_path() / RINGDIR; ringtonePath_ = fileutils::getFullPath(ringtoneDir, config_->ringtonePath); // If the user defined a custom ringtone, the file may not exists // In this case, fallback on the default ringtone path diff --git a/src/client/configurationmanager.cpp b/src/client/configurationmanager.cpp index b98dcbd891..2ea5644db6 100644 --- a/src/client/configurationmanager.cpp +++ b/src/client/configurationmanager.cpp @@ -1159,4 +1159,10 @@ isAllModerators(const std::string& accountId) return jami::Manager::instance().isAllModerators(accountId); } +void +setResourceDirPath(const std::string& resourceDir) +{ + jami::fileutils::set_resource_dir_path(resourceDir); +} + } // namespace libjami diff --git a/src/fileutils.cpp b/src/fileutils.cpp index 3a04ec8448..ea26aecaa1 100644 --- a/src/fileutils.cpp +++ b/src/fileutils.cpp @@ -14,12 +14,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include "logger.h" #include "fileutils.h" +#include "logger.h" #include "archiver.h" #include "compiler_intrinsics.h" #include "base64.h" @@ -119,6 +120,21 @@ winGetEnv(const wchar_t* name) namespace jami { namespace fileutils { +static std::filesystem::path resource_dir_path; + +void +set_resource_dir_path(const std::filesystem::path& resourceDirPath) +{ + resource_dir_path = resourceDirPath; +} + +const std::filesystem::path& +get_resource_dir_path() +{ + static const std::filesystem::path jami_default_data_dir(JAMI_DATADIR); + return resource_dir_path.empty() ? jami_default_data_dir : resource_dir_path; +} + std::string expand_path(const std::string& path) { @@ -411,20 +427,6 @@ writeArchive(const std::string& archive_str, } } -#if defined(__ANDROID__) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS) -#else -static char* program_dir = NULL; -void -set_program_dir(char* program_path) -{ -#ifdef _MSC_VER - _splitpath(program_path, nullptr, program_dir, nullptr, nullptr); -#else - program_dir = dirname(program_path); -#endif -} -#endif - std::filesystem::path get_cache_dir(const char* pkg) { @@ -473,7 +475,7 @@ get_home_dir_impl() if (SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_PROFILE, nullptr, 0, path))) { return jami::to_string(path); } - return program_dir; + return {}; #else // 1) try getting user's home directory from the environment diff --git a/src/fileutils.h b/src/fileutils.h index cb9e518cb7..b5dbeb0786 100644 --- a/src/fileutils.h +++ b/src/fileutils.h @@ -55,12 +55,23 @@ const std::filesystem::path& get_data_dir(); const std::filesystem::path& get_cache_dir(); /** - * Check directory existence and create it with given mode if it doesn't. - * @param path to check, relative or absolute - * @param dir last directory creation mode - * @param parents default mode for all created directories except the last + * Set the program's resource directory path. This is used for clients that may be installed in different + * locations and are deployed with ringtones and other resources in an application relative directory. + * @param resource_dir_path The path to the ringtone directory. + */ +LIBJAMI_PUBLIC void set_resource_dir_path(const std::filesystem::path& resourceDirPath); + +/** + * Get the resource directory path that was set with set_resource_dir_path. + * @return The resource directory path. + */ +const std::filesystem::path& get_resource_dir_path(); + +/** + * Expand the given path. + * @param path The path to be expanded. + * @return The expanded path as a string. */ -LIBJAMI_PUBLIC void set_program_dir(char* program_path); // public because bin/main.cpp uses it std::string expand_path(const std::string& path); bool isPathRelative(const std::filesystem::path& path); diff --git a/src/jami/configurationmanager_interface.h b/src/jami/configurationmanager_interface.h index d0e9f3eb9d..8d841ff582 100644 --- a/src/jami/configurationmanager_interface.h +++ b/src/jami/configurationmanager_interface.h @@ -329,6 +329,11 @@ LIBJAMI_PUBLIC void setAllModerators(const std::string& accountId, bool allModer */ LIBJAMI_PUBLIC bool isAllModerators(const std::string& accountId); +/** + * Set the resource directory path + */ +LIBJAMI_PUBLIC void setResourceDirPath(const std::string& resourceDirPath); + struct LIBJAMI_PUBLIC AudioSignal { struct LIBJAMI_PUBLIC DeviceEvent -- GitLab