Browse Source

Add a few dir-related calls to plugin utilities

Signed-off-by: falkTX <falktx@falktx.com>
pull/491/head
falkTX 2 months ago
parent
commit
45618ccef9
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
2 changed files with 200 additions and 3 deletions
  1. +22
    -2
      distrho/DistrhoPluginUtils.hpp
  2. +178
    -1
      distrho/src/DistrhoUtils.cpp

+ 22
- 2
distrho/DistrhoPluginUtils.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2024 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2025 Filipe Coelho <falktx@falktx.com>
*
* 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
@@ -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.


+ 178
- 1
distrho/src/DistrhoUtils.cpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2024 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2025 Filipe Coelho <falktx@falktx.com>
*
* 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
@@ -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
@@ -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)


Loading…
Cancel
Save