From 9a82e82c87808076a34eb76c7f6b03922e056f7b Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Thu, 14 May 2020 19:11:17 +0200 Subject: [PATCH] Factor out directory finding from prefix detection This will also be used to locate the `yabridge.tmol` configuration file. --- src/common/configuration.h | 52 ++++++++++++++++++++++++++++++++++++++ src/plugin/utils.cpp | 19 +++++++------- src/plugin/utils.h | 3 ++- 3 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 src/common/configuration.h diff --git a/src/common/configuration.h b/src/common/configuration.h new file mode 100644 index 00000000..0f31fd01 --- /dev/null +++ b/src/common/configuration.h @@ -0,0 +1,52 @@ +// yabridge: a Wine VST bridge +// Copyright (C) 2020 Robbert van der Helm +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once + +#include +#include + +/** + * Starting from the starting file or directory, go up in the directory + * hierarchy until we find a file named `filename`. + * + * @param filename The name of the file we're looking for. This can also be a + * directory name since directories are also files. + * @param starting_from The directory to start searching in. If this is a file, + * then start searching in the directory the file is located in. + * @param predicate The predicate to use to check if the path matches a file. + * Needed as an easy way to limit the search to directories only since C++17 + * does not have any built in coroutines or generators. + * + * @return The path to the *file* found, or `std::nullopt` if the file could not + * be found. + */ +template +std::optional find_dominating_file( + const std::string& filename, + std::filesystem::path starting_dir, + F predicate = std::filesystem::exists) { + while (starting_dir != "") { + const std::filesystem::path candidate = starting_dir / filename; + if (predicate(candidate)) { + return candidate; + } + + starting_dir = starting_dir.parent_path(); + } + + return std::nullopt; +} diff --git a/src/plugin/utils.cpp b/src/plugin/utils.cpp index e464ebfb..92363912 100644 --- a/src/plugin/utils.cpp +++ b/src/plugin/utils.cpp @@ -28,6 +28,8 @@ // Generated inside of build directory #include +#include <../common/configuration.h> + namespace bp = boost::process; namespace fs = boost::filesystem; @@ -53,16 +55,13 @@ std::string create_logger_prefix(const fs::path& socket_path) { } std::optional find_wineprefix() { - // Try to locate the Wine prefix the plugin's .dll file is located in by - // finding the first parent directory that contains a directory named - // `dosdevices` - fs::path wineprefix_path = find_vst_plugin(); - while (wineprefix_path != "") { - if (fs::is_directory(wineprefix_path / "dosdevices")) { - return wineprefix_path; - } - - wineprefix_path = wineprefix_path.parent_path(); + // We need these string conversions because Boost still doesn't use + // std::filesystem paths + std::optional dosdevices_dir = + find_dominating_file("dosdevices", find_vst_plugin().string(), + std::filesystem::is_directory); + if (dosdevices_dir.has_value()) { + return dosdevices_dir->parent_path().string(); } return std::nullopt; diff --git a/src/plugin/utils.h b/src/plugin/utils.h index c2991080..9978511e 100644 --- a/src/plugin/utils.h +++ b/src/plugin/utils.h @@ -101,7 +101,8 @@ boost::filesystem::path find_vst_plugin(); /** * Locate the Wine prefix this file is located in, if it is inside of a wine - * prefix. + * prefix. This is done by locating the first parent directory that contains a + * directory named `dosdevices`. * * @return Either the path to the Wine prefix (containing the `drive_c?` * directory), or `std::nullopt` if it is not inside of a wine prefix.