37#include "public.sdk/source/vst/hosting/module.h"
38#include "public.sdk/source/vst/utility/optional.h"
39#include "public.sdk/source/vst/utility/stringconvert.h"
43#include <sys/utsname.h>
46#if (__cplusplus >= 201707L)
47#if __has_include(<filesystem>)
48#define USE_EXPERIMENTAL_FS 0
49#elif __has_include(<experimental/filesystem>)
50#define USE_EXPERIMENTAL_FS 1
53#define USE_EXPERIMENTAL_FS 1
56#if USE_EXPERIMENTAL_FS == 1
57#include <experimental/filesystem>
58namespace filesystem = std::experimental::filesystem;
61namespace filesystem = std::filesystem;
74using Path = filesystem::path;
82 struct utsname unameData;
84 int res = uname (&unameData);
88 return {unameData.machine};
94 std::string appPath =
"";
96 pid_t pid = getpid ();
98 sprintf (buf,
"%d", pid);
99 std::string _link =
"/proc/";
101 _link.append (
"/exe");
103 int ch = readlink (_link.c_str (), proc, 1024);
109 std::string::size_type t = appPath.find_last_of (
"/");
110 appPath = appPath.substr (0, t);
112 return Path {appPath};
119 template <
typename T>
122 return reinterpret_cast<T
> (dlsym (mModule,
name));
127 factory = PluginFactory (
nullptr);
131 if (
auto moduleExit = getFunctionPointer<ModuleExitFunc> (
"ModuleExit"))
138 static Optional<Path>
getSOPath (
const std::string& inPath)
140 Path modulePath {inPath};
141 if (!filesystem::is_directory (modulePath))
144 auto stem = modulePath.stem ();
146 modulePath /=
"Contents";
147 if (!filesystem::is_directory (modulePath))
155 modulePath /= *machine +
"-linux";
156 if (!filesystem::is_directory (modulePath))
159 stem.replace_extension (
".so");
161 return Optional<Path> (std::move (modulePath));
164 bool load (
const std::string& inPath, std::string& errorDescription)
override
166 auto modulePath = getSOPath (inPath);
169 errorDescription = inPath +
" is not a module directory.";
173 mModule = dlopen (
reinterpret_cast<const char*
> (modulePath->generic_string ().data ()),
177 errorDescription =
"dlopen failed.\n";
178 errorDescription += dlerror ();
182 auto moduleEntry = getFunctionPointer<ModuleEntryFunc> (
"ModuleEntry");
186 "The shared library does not export the required 'ModuleEntry' function";
190 auto moduleExit = getFunctionPointer<ModuleExitFunc> (
"ModuleExit");
194 "The shared library does not export the required 'ModuleExit' function";
197 auto factoryProc = getFunctionPointer<GetFactoryProc> (
"GetPluginFactory");
201 "The shared library does not export the required 'GetPluginFactory' function";
205 if (!moduleEntry (mModule))
207 errorDescription =
"Calling 'ModuleEntry' failed";
210 auto f = Steinberg::FUnknownPtr<Steinberg::IPluginFactory> (owned (factoryProc ()));
213 errorDescription =
"Calling 'GetPluginFactory' returned nullptr";
220 void* mModule {
nullptr};
224void findFilesWithExt (
const std::string& path,
const std::string& ext, Module::PathList& pathList,
225 bool recursive =
true)
229 for (
auto& p : filesystem::directory_iterator (path))
231 if (p.path ().extension () == ext)
233 pathList.push_back (p.path ().generic_string ());
235 else if (recursive && p.status ().type () == filesystem::file_type::directory)
247void findModules (
const std::string& path, Module::PathList& pathList)
256Module::Ptr Module::create (
const std::string& path, std::string& errorDescription)
258 auto _module = std::make_shared<LinuxModule> ();
259 if (_module->load (path, errorDescription))
261 auto it = std::find_if (path.rbegin (), path.rend (),
262 [] (
const std::string::value_type& c) { return c ==
'/'; });
263 _module->path = path;
264 if (it != path.rend ())
265 _module->name = {it.base (), path.end ()};
272Module::PathList Module::getModulePaths ()
281 const auto systemPaths = {
"/usr/lib/vst3/",
"/usr/local/lib/vst3/"};
284 if (
auto homeDir = getenv (
"HOME"))
286 filesystem::path homePath (homeDir);
290 for (
auto path : systemPaths)
305Module::SnapshotList Module::getSnapshots (
const std::string& modulePath)
308 filesystem::path path (modulePath);
314 for (
auto& png : pngList)
316 filesystem::path p (png);
317 auto filename = p.filename ().generic_string ();
318 auto uid = Snapshot::decodeUID (filename);
321 auto scaleFactor = 1.;
322 if (
auto decodedScaleFactor = Snapshot::decodeScaleFactor (filename))
323 scaleFactor = *decodedScaleFactor;
325 Module::Snapshot::ImageDesc
desc;
326 desc.scaleFactor = scaleFactor;
327 desc.path = std::move (png);
329 for (
auto&
entry : result)
331 if (
entry.uid != *uid)
334 entry.images.emplace_back (std::move (
desc));
339 Module::Snapshot snapshot;
341 snapshot.images.emplace_back (std::move (
desc));
342 result.emplace_back (std::move (snapshot));
static ProjectFileIORegistry::AttributeWriterEntry entry
static Optional< Path > getSOPath(const std::string &inPath)
bool load(const std::string &inPath, std::string &errorDescription) override
T getFunctionPointer(const char *name)
bool(PLUGIN_API *)() ModuleExitFunc
bool(PLUGIN_API *)(void *) ModuleEntryFunc
void findModules(const std::string &path, Module::PathList &pathList)
Optional< Path > getApplicationPath()
Optional< std::string > getCurrentMachineName()
void findFilesWithExt(const std::string &path, const std::string &ext, Module::PathList &pathList, bool recursive=true)
const TranslatableString desc