9f20457f21
GCC 16 on Arch Linux no longer implicitly includes certain standard headers. This causes 'not declared' errors for POSIX functions. - PiPedalCommon/src/CMakeLists.txt: Link asound library for ALSA sequencer - DBusDispatcher.cpp: Add <unistd.h> for read()/write()/close() - AuxInTest.cpp: Add <unistd.h> for sleep() - kconfigMain.cpp: Add <unistd.h> for getuid() - ModFileTypes.cpp: Add <mutex> for std::mutex/std::lock_guard
186 lines
7.1 KiB
C++
186 lines
7.1 KiB
C++
// Copyright (c) 2024 Robin Davies
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
// this software and associated documentation files (the "Software"), to deal in
|
|
// the Software without restriction, including without limitation the rights to
|
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
|
// subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
// copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
#include "ModFileTypes.hpp"
|
|
#include "util.hpp"
|
|
#include <stdexcept>
|
|
#include <iostream>
|
|
#include <mutex>
|
|
#include "ss.hpp"
|
|
#include "MimeTypes.hpp"
|
|
|
|
using namespace pipedal;
|
|
|
|
|
|
static std::mutex gModDirectoriesMutex;
|
|
static std::unique_ptr< std::vector<ModFileTypes::ModDirectory> > gModDirectories;
|
|
|
|
|
|
static std::vector<ModFileTypes::ModDirectory> *CreateModDirectories()
|
|
{
|
|
return new std::vector<ModFileTypes::ModDirectory>(
|
|
{
|
|
{"audioloop", "shared/audio/Loops", "Loops", {"audio/*"}}, // Audio Loops, meant to be used for looper-style plugins
|
|
{"audiorecording","shared/audio/Audio Recordings", "Audio Recordings",{"audio/*"}}, // Audio Recordings, triggered by plugins and stored in the unit
|
|
{"audiosample", "shared/audio/Samples", "Samples", {"audio/*"}}, // One-shot Audio Samples, meant to be used for sampler-style plugins
|
|
{"audiotrack", "shared/audio/Tracks", "Tracks", {"audio/*"}}, // Audio Tracks, meant to be used as full-performance/song or backtrack
|
|
{"cabsim", "CabIR", "Cab IRs", {"audio/*"}}, // Speaker Cabinets, meant as small IR audio files
|
|
|
|
{"h2drumkit", "shared/h2drumkit", "Hydrogen Drumkits",{".h2drumkit"}}, // Hydrogen Drumkits, must use h2drumkit file extension"
|
|
{"ir", "ReverbImpulseFiles", "Impulse Responses", {"audio/*"}}, // Impulse Responses
|
|
{"midiclip", "shared/midiClips", "MIDI Clips", {".mid", ".midi"}}, // MIDI Clips, to be used in sync with host tempo, must have mid or midi file extension
|
|
{"midisong", "shared/midiSongs", "MIDI Songs", {".mid", ".midi"}}, // MIDI Songs, meant to be used as full-performance/song or backtrack
|
|
{"sf2", "shared/sf2", "Sound Fonts", {".sf2", ".sf3"}}, // SF2 Instruments, must have sf2 or sf3 file extension
|
|
{"sfz", "shared/sfz", "Sfz Files", {".sfz"}}, // SFZ Instruments, must have sfz file extension
|
|
// extensions observed in the field.
|
|
{"audio", "shared/audio", "Audio", {"audio/*"}}, // all audio files (Ratatouille)
|
|
{"nammodel", "NeuralAmpModels", "Neural Amp Models", {".nam" ,".aidax"}}, // Ratatouille, Mike's NAM.
|
|
{"aidadspmodel", "shared/aidaaix", "AIDA IAX Models", {".json", ".aidax",".aidaiax"}}, // Ratatouille
|
|
{"mlmodel", "ToobMlModels", "ML Models", {".json"}}, //
|
|
|
|
|
|
// For plugins that don't secify a modDirectory (allows upload of arbitrary extension)
|
|
{"*", "shared/other", "Other", {".*"}}, //
|
|
|
|
});
|
|
}
|
|
|
|
|
|
|
|
const std::vector<ModFileTypes::ModDirectory>&ModFileTypes::ModDirectories()
|
|
{
|
|
std::lock_guard lock { gModDirectoriesMutex };
|
|
|
|
if (!gModDirectories)
|
|
{
|
|
gModDirectories = std::unique_ptr<std::vector<ModFileTypes::ModDirectory>>(CreateModDirectories());
|
|
}
|
|
return *gModDirectories;
|
|
}
|
|
|
|
|
|
const ModFileTypes::ModDirectory *ModFileTypes::GetModDirectory(const std::string &type)
|
|
{
|
|
for (const ModFileTypes::ModDirectory &modType : ModFileTypes::ModDirectories())
|
|
{
|
|
if (modType.modType == type)
|
|
{
|
|
return &modType;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
ModFileTypes::ModFileTypes(const std::string &fileTypes)
|
|
{
|
|
std::vector<std::string> types = split(fileTypes, ',');
|
|
for (const auto &type : types)
|
|
{
|
|
const ModDirectory *wellKnownType = GetModDirectory(type);
|
|
if (wellKnownType)
|
|
{
|
|
rootDirectories_.push_back(type);
|
|
modFileTypes_.push_back(type);
|
|
}
|
|
else
|
|
{
|
|
fileTypes_.push_back(type);
|
|
}
|
|
}
|
|
}
|
|
|
|
static std::filesystem::path getModDirectoryPath(
|
|
const std::filesystem::path &rootDirectory,
|
|
const std::string &modType)
|
|
{
|
|
auto wellKnownType = ModFileTypes::GetModDirectory(modType);
|
|
if (!wellKnownType)
|
|
{
|
|
throw std::runtime_error(SS("Can't find modFileType " << modType));
|
|
}
|
|
return rootDirectory / wellKnownType->pipedalPath;
|
|
}
|
|
void ModFileTypes::CreateDefaultDirectories(const std::filesystem::path &rootDirectory)
|
|
{
|
|
namespace fs = std::filesystem;
|
|
using namespace std;
|
|
try
|
|
{
|
|
for (const auto &modType : ModDirectories())
|
|
{
|
|
fs::path path = rootDirectory / modType.pipedalPath;
|
|
|
|
fs::create_directories(path);
|
|
}
|
|
|
|
if (!fs::exists(rootDirectory / "shared" / "audio" / "Cab IR Files"))
|
|
{
|
|
fs::create_symlink(
|
|
getModDirectoryPath(rootDirectory, "cabsim"),
|
|
rootDirectory / "shared" / "audio" / "Cab IR Files");
|
|
}
|
|
if (!fs::exists(rootDirectory / "shared" / "audio" / "Impulse Responses"))
|
|
{
|
|
fs::create_symlink(
|
|
getModDirectoryPath(rootDirectory, "ir"),
|
|
rootDirectory / "shared" / "audio" / "Impulse Responses");
|
|
}
|
|
}
|
|
catch (const std::exception &e)
|
|
{
|
|
cout << "Can't create default MOD directories. " << e.what() << endl;
|
|
}
|
|
}
|
|
|
|
static std::set<std::string> makeFileExtensions(const std::vector<std::string>&fileTypes)
|
|
{
|
|
std::set<std::string> result;
|
|
|
|
for (const std::string&fileType: fileTypes)
|
|
{
|
|
if (fileType.starts_with('.')) {
|
|
result.insert(fileType);
|
|
} else {
|
|
if (fileType == "audio/*")
|
|
{
|
|
const auto&audioExtensions = MimeTypes::instance().AudioExtensions();
|
|
result.insert(audioExtensions.begin(),audioExtensions.end());
|
|
} else if (fileType == "video/*")
|
|
{
|
|
const auto&videoExtensions = MimeTypes::instance().VideoExtensions();
|
|
result.insert(videoExtensions.begin(),videoExtensions.end());
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
ModFileTypes::ModDirectory::ModDirectory(
|
|
const std::string modType,
|
|
const std::string pipedalPath,
|
|
const std::string displayName,
|
|
const std::vector<std::string> fileTypes)
|
|
:modType(modType),
|
|
pipedalPath(pipedalPath),
|
|
displayName(displayName),
|
|
fileTypesX(fileTypes),
|
|
fileExtensions(makeFileExtensions(fileTypes))
|
|
{
|
|
}
|