Skip to content

Commit

Permalink
Add a few dir-related calls to plugin utilities
Browse files Browse the repository at this point in the history
Signed-off-by: falkTX <[email protected]>
  • Loading branch information
falkTX committed Feb 9, 2025
1 parent 56732ba commit 45618cc
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 3 deletions.
24 changes: 22 additions & 2 deletions distrho/DistrhoPluginUtils.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2024 Filipe Coelho <[email protected]>
* Copyright (C) 2012-2025 Filipe Coelho <[email protected]>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
Expand Down Expand Up @@ -37,9 +37,29 @@ START_NAMESPACE_DISTRHO
*/
const char* getBinaryFilename();

/**
Get an OS-specific directory intended to store persistent configuration data about the plugin.@n
Calling this function will ensure the dictory exists on the filesystem.@n
The returned path already includes DISTRHO_PLUGIN_NAME and final OS separator.
*/
const char* getConfigDir();

/**
Get an OS-specific directory intended to store "documents" for the plugin.@n
Calling this function will ensure the dictory exists on the filesystem.@n
The returned path already includes DISTRHO_PLUGIN_NAME and final OS separator.
*/
const char* getDocumentsDir();

/**
Get the user "home" directory.@n
This function is provided only for convenience, it should not be needed under normal circunstances.
*/
const char* getHomeDir();

/**
Get a string representation of the current plugin format we are building against.@n
This can be "JACK/Standalone", "LADSPA", "DSSI", "LV2", "VST2" or "VST3".@n
This can be "AudioUnit", "JACK/Standalone", "LADSPA", "DSSI", "LV2", "VST2" or "VST3" or "CLAP".@n
This string is purely informational and must not be used to tweak plugin behaviour.
@note DO NOT CHANGE PLUGIN BEHAVIOUR BASED ON PLUGIN FORMAT.
Expand Down
179 changes: 178 additions & 1 deletion distrho/src/DistrhoUtils.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2024 Filipe Coelho <[email protected]>
* Copyright (C) 2012-2025 Filipe Coelho <[email protected]>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
Expand All @@ -23,13 +23,19 @@
#include "../DistrhoStandaloneUtils.hpp"

#ifdef DISTRHO_OS_WINDOWS
# include <direct.h>
# include <shlobj.h>
# include <windows.h>
#else
# ifndef STATIC_BUILD
# include <dlfcn.h>
# endif
# include <fcntl.h>
# include <limits.h>
# include <pwd.h>
# include <stdlib.h>
# include <sys/stat.h>
# include <unistd.h>
#endif

#ifdef DISTRHO_OS_WINDOWS
Expand Down Expand Up @@ -76,6 +82,177 @@ const char* getBinaryFilename()
return filename;
}

const char* getConfigDir()
{
#if defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WASM) || defined(DISTRHO_OS_WINDOWS)
return getDocumentsDir();
#else
static String dir;

if (dir.isEmpty())
{
if (const char* const xdgEnv = getenv("XDG_CONFIG_HOME"))
dir = xdgEnv;

if (dir.isEmpty())
{
dir = getHomeDir();
dir += "/.config";
}

// ensure main config dir exists
if (access(dir, F_OK) != 0)
mkdir(dir, 0755);

// and also our custom subdir
dir += "/" DISTRHO_PLUGIN_NAME "/";
if (access(dir, F_OK) != 0)
mkdir(dir, 0755);
}

return dir;
#endif
}

const char* getDocumentsDir()
{
static String dir;

if (dir.isEmpty())
{
#if defined(DISTRHO_OS_MAC)
dir = getHomeDir();
dir += "/Documents/" DISTRHO_PLUGIN_NAME "/";
#elif defined(DISTRHO_OS_WASM)
dir = getHomeDir();
dir += "/";
#elif defined(DISTRHO_OS_WINDOWS)
WCHAR wpath[MAX_PATH];
if (SHGetFolderPathW(nullptr, CSIDL_MYDOCUMENTS, nullptr, SHGFP_TYPE_CURRENT, wpath) == S_OK)
{
CHAR apath[MAX_PATH];
if (WideCharToMultiByte(CP_UTF8, 0, wpath, -1, apath, MAX_PATH, nullptr, nullptr) != 0)
{
dir = apath;
dir += "\\" DISTRHO_PLUGIN_NAME "\\";
wcscat(wpath, L"\\" DISTRHO_PLUGIN_NAME "\\");
}
}
#else
String xdgDirsConfigPath(getConfigDir());
xdgDirsConfigPath += "/user-dirs.dirs";

if (FILE* const f = std::fopen(xdgDirsConfigPath, "r"))
{
std::fseek(f, 0, SEEK_END);
const long size = std::ftell(f);
std::fseek(f, 0, SEEK_SET);

// something is wrong if config dirs file is longer than 1MiB!
if (size > 0 && size < 1024 * 1024)
{
if (char* filedata = static_cast<char*>(std::malloc(size)))
{
for (long r = 0, total = 0; total < size;)
{
r = std::fread(filedata + total, 1, size - total, f);

if (r == 0)
{
std::free(filedata);
filedata = nullptr;
break;
}

total += r;
}

if (filedata != nullptr)
{
if (char* const xdgDocsDir = std::strstr(filedata, "XDG_DOCUMENTS_DIR=\""))
{
if (char* const xdgDocsDirNL = std::strstr(xdgDocsDir, "\"\n"))
{
*xdgDocsDirNL = '\0';
String sdir(xdgDocsDir + 19);

if (sdir.startsWith("$HOME"))
{
dir = getHomeDir();
dir += sdir.buffer() + 5;
}
else
{
dir = sdir;
}

// ensure main config dir exists
if (access(dir, F_OK) != 0)
mkdir(dir, 0755);
}
}

std::free(filedata);
}
}
}

std::fclose(f);
}

// ${XDG_CONFIG_HOME}/user-dirs.dirs does not exist or has bad data
if (dir.isEmpty())
{
dir = getDocumentsDir();
dir += DISTRHO_PLUGIN_NAME "/";
}
#endif

// ensure our custom subdir exists
if (dir.isNotEmpty())
{
#ifdef DISTRHO_OS_WINDOWS
_wmkdir(wpath);
#else
if (access(dir, F_OK) != 0)
mkdir(dir, 0755);
#endif
}
}

return dir;
}

const char* getHomeDir()
{
static String dir;

if (dir.isEmpty())
{
#ifdef DISTRHO_OS_WINDOWS
WCHAR wpath[MAX_PATH];
if (SHGetFolderPathW(nullptr, CSIDL_PROFILE, nullptr, SHGFP_TYPE_CURRENT, wpath) == S_OK)
{
CHAR apath[MAX_PATH];
if (WideCharToMultiByte(CP_UTF8, 0, wpath, -1, apath, MAX_PATH, nullptr, nullptr) != 0)
dir = apath;
}
#else
if (const char* const homeEnv = getenv("HOME"))
dir = homeEnv;

if (dir.isEmpty())
if (struct passwd* const pwd = getpwuid(getuid()))
dir = pwd->pw_dir;

if (dir.isNotEmpty() && ! dir.endsWith('/'))
dir += "/";
#endif
}

return dir;
}

const char* getPluginFormatName() noexcept
{
#if defined(DISTRHO_PLUGIN_TARGET_AU)
Expand Down

0 comments on commit 45618cc

Please sign in to comment.