Plugin Presets.

This commit is contained in:
Robin Davies
2022-03-02 13:26:59 -05:00
parent f677b8b608
commit 2869ec0e00
32 changed files with 2401 additions and 914 deletions
+529 -467
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -58,7 +58,8 @@ public:
constexpr static const char* content_disposition = "Content-Disposition";
constexpr static const char* access_control_allow_origin = "Access-Control-Allow-Origin";
constexpr static const char* access_control_allow_methods= "Access-Control-Allow-Methods";
constexpr static const char* access_control_allow_headers = "Acess-Control-Allow-Headers";
constexpr static const char* access_control_allow_headers = "Access-Control-Allow-Headers";
constexpr static const char* access_control_request_headers = "Access-Control-Request-Headers";
constexpr static const char* origin = "Origin";
constexpr static const char* date = "Date";
};
+1
View File
@@ -101,6 +101,7 @@ add_custom_command(
set (PIPEDAL_SOURCES
PluginPreset.cpp PluginPreset.hpp
SysExec.cpp SysExec.hpp
BeastServer.cpp BeastServer.hpp HtmlHelper.cpp HtmlHelper.hpp pch.h Uri.cpp Uri.hpp
WifiConfigSettings.hpp WifiConfigSettings.cpp
+62 -37
View File
@@ -123,6 +123,9 @@ void Lv2Host::LilvUris::Initialize(LilvWorld*pWorld)
time_beatsPerMinute = lilv_new_uri(pWorld, LV2_TIME__beatsPerMinute);
time_speed = lilv_new_uri(pWorld, LV2_TIME__speed);
appliesTo = lilv_new_uri(pWorld,LV2_CORE__appliesTo);
}
@@ -151,6 +154,8 @@ void Lv2Host::LilvUris::Free()
time_beatsPerMinute.Free();
time_speed.Free();
appliesTo.Free();
isA.Free();
}
static std::string nodeAsString(const LilvNode *node)
@@ -535,8 +540,24 @@ static bool ports_sort_compare(std::shared_ptr<Lv2PortInfo> &p1, const std::shar
return p1->index() < p2->index();
}
bool Lv2PluginInfo::HasFactoryPresets(Lv2Host*lv2Host, const LilvPlugin*plugin)
{
NodesAutoFree nodes = lilv_plugin_get_related(plugin,lv2Host->lilvUris.pset_Preset);
bool result = false;
LILV_FOREACH(nodes, iNode, nodes)
{
result = true;
break;
}
return result;
}
Lv2PluginInfo::Lv2PluginInfo(Lv2Host *lv2Host, const LilvPlugin *pPlugin)
{
const LilvNode* pluginUri = lilv_plugin_get_uri(pPlugin);
this->has_factory_presets_ = HasFactoryPresets(lv2Host,pPlugin);
this->uri_ = nodeAsString(lilv_plugin_get_uri(pPlugin));
NodeAutoFree name = (lilv_plugin_get_name(pPlugin));
@@ -606,7 +627,10 @@ Lv2PluginInfo::Lv2PluginInfo(Lv2Host *lv2Host, const LilvPlugin *pPlugin)
}
std::sort(ports_.begin(), ports_.end(), ports_sort_compare);
this->is_valid_ = isValid;
}
std::vector<std::string> supportedFeatures = {
@@ -947,7 +971,8 @@ void Lv2Host::fn_LilvSetPortValueFunc(const char* port_symbol,
std::vector<ControlValue> Lv2Host::LoadPluginPreset(PedalBoardItem*pedalBoardItem, const std::string&presetUri)
std::vector<ControlValue> Lv2Host::LoadFactoryPluginPreset(
PedalBoardItem*pedalBoardItem, const std::string&presetUri)
{
std::vector<ControlValue> result;
@@ -1005,10 +1030,26 @@ std::vector<ControlValue> Lv2Host::LoadPluginPreset(PedalBoardItem*pedalBoardIte
return result;
}
std::vector<Lv2PluginPreset> Lv2Host::GetPluginPresets(const std::string &pluginUri)
{
std::vector<Lv2PluginPreset> result;
struct PresetCallbackState {
Lv2Host *pHost;
std::map<std::string,float> *values;
bool failed = false;
};
void Lv2Host::PortValueCallback(const char*symbol,void*user_data,const void* value,uint32_t size, uint32_t type)
{
PresetCallbackState *pState = static_cast<PresetCallbackState*>(user_data);
Lv2Host*pHost = pState->pHost;
if (type == pHost->urids->atom_Float)
{
(*pState->values)[symbol] = *static_cast<const float*>(value);
} else {
pState->failed = true;
}
}
PluginPresets Lv2Host::GetFactoryPluginPresets(const std::string &pluginUri)
{
const LilvPlugins*plugins = lilv_world_get_all_plugins(this->pWorld);
NodeAutoFree uriNode = lilv_new_uri(pWorld, pluginUri.c_str());
@@ -1021,42 +1062,31 @@ std::vector<Lv2PluginPreset> Lv2Host::GetPluginPresets(const std::string &plugin
throw PiPedalStateException("No such plugin.");
}
PluginPresets result;
result.pluginUri_ = pluginUri;
LilvNodes* presets = lilv_plugin_get_related(plugin, lilvUris.pset_Preset);
LILV_FOREACH(nodes, i, presets) {
const LilvNode* preset = lilv_nodes_get(presets, i);
lilv_world_load_resource(pWorld, preset);
LilvNodes* labels = lilv_world_find_nodes(
pWorld, preset, lilvUris.rdfs_label, NULL);
if (labels) {
const LilvNode* label = lilv_nodes_get_first(labels);
std::string presetName = nodeAsString(label);
result.push_back(Lv2PluginPreset(nodeAsString(preset),presetName));
lilv_nodes_free(labels);
} else {
std::stringstream s;
s << "Preset <" << nodeAsString(lilv_nodes_get(presets,i)) << "> has no rdfs:label.";
LilvState *state = lilv_state_new_from_world(pWorld,this->mapFeature.GetMap(),preset);
if (state != nullptr)
{
std::string label = lilv_state_get_label(state);
std::map<std::string,float> controlValues;
PresetCallbackState cbData { this, &controlValues,false};
lilv_state_emit_port_values(state,PortValueCallback,(void*)&cbData);
lilv_state_free(state);
Lv2Log::warning(s.str());
}
if (!cbData.failed)
{
result.presets_.push_back(PluginPreset(result.nextInstanceId_++,std::move(label),std::move(controlValues)));
}
}
}
lilv_nodes_free(presets);
auto& collation = std::use_facet<std::collate<char> >(std::locale());
auto compare = [&collation] (const Lv2PluginPreset&left, const Lv2PluginPreset&right)
{
return collation.compare(
left.name_.c_str(),
left.name_.c_str()+left.name_.size(),
right.name_.c_str(),
right.name_.c_str()+right.name_.size()) < 0;
};
std::sort(result.begin(),result.end(),compare);
return result;
return result;
}
@@ -1162,7 +1192,7 @@ json_map::storage_type<Lv2PluginInfo> Lv2PluginInfo::jmap{{
json_map::reference("ports", &Lv2PluginInfo::ports_),
json_map::reference("port_groups", &Lv2PluginInfo::port_groups_),
json_map::reference("is_valid", &Lv2PluginInfo::is_valid_),
json_map::reference("has_factory_presets", &Lv2PluginInfo::has_factory_presets_),
}};
json_map::storage_type<Lv2PluginUiInfo> Lv2PluginUiInfo::jmap{{
@@ -1217,8 +1247,3 @@ json_map::storage_type<Lv2PluginUiPortGroup> Lv2PluginUiPortGroup::jmap{{
MAP_REF(Lv2PluginUiPortGroup, name),
}};
JSON_MAP_BEGIN(Lv2PluginPreset)
JSON_MAP_REFERENCE(Lv2PluginPreset,presetUri)
JSON_MAP_REFERENCE(Lv2PluginPreset,name)
JSON_MAP_END()
+11 -21
View File
@@ -33,7 +33,7 @@
#include "lv2.h"
#include "Units.hpp"
#include "PluginPreset.hpp"
namespace pipedal {
@@ -60,23 +60,6 @@ class JackChannelSelection;
class Lv2PluginPreset {
public:
Lv2PluginPreset(const std::string &presetUri, const std::string&name)
: presetUri_(presetUri),
name_(name)
{
}
Lv2PluginPreset() { }
std::string presetUri_;
std::string name_;
DECLARE_JSON_MAP(Lv2PluginPreset);
};
class Lv2PluginClass {
public:
friend class Lv2Host;
@@ -321,6 +304,7 @@ public:
Lv2PluginInfo(Lv2Host*lv2Host,const LilvPlugin*);
Lv2PluginInfo() { }
private:
bool HasFactoryPresets(Lv2Host*lv2Host, const LilvPlugin*plugin);
std::string uri_;
std::string name_;
std::string plugin_class_;
@@ -328,6 +312,7 @@ private:
std::vector<std::string> required_features_;
std::vector<std::string> optional_features_;
std::vector<std::string> extensions_;
bool has_factory_presets_ = false;
std::string author_name_;
std::string author_homepage_;
@@ -353,6 +338,7 @@ public:
LV2_PROPERTY_GETSET(ports)
LV2_PROPERTY_GETSET(is_valid)
LV2_PROPERTY_GETSET(port_groups)
LV2_PROPERTY_GETSET(has_factory_presets)
const Lv2PortInfo& getPort(const std::string&symbol)
{
@@ -623,6 +609,9 @@ private:
LilvNodePtr time_beatsPerMinute;
LilvNodePtr time_speed;
LilvNodePtr appliesTo;
LilvNodePtr isA;
};
LilvUris lilvUris;
@@ -682,6 +671,7 @@ private:
virtual LV2_URID_Map* GetLv2UridMap() {
return this->mapFeature.GetMap();
}
static void PortValueCallback(const char*symbol,void*user_data,const void* value,uint32_t size, uint32_t type);
virtual Lv2Effect*CreateEffect(const PedalBoardItem &pedalBoardItem);
void LoadPluginClassesFromLilv();
@@ -733,9 +723,9 @@ public:
return this->mapFeature.UridToString(urid);
}
std::vector<Lv2PluginPreset> GetPluginPresets(const std::string &pluginUri);
std::vector<ControlValue> LoadPluginPreset(PedalBoardItem*pedalBoardItem, const std::string&presetUri);
PluginPresets GetFactoryPluginPresets(const std::string &pluginUri);
std::vector<ControlValue> LoadFactoryPluginPreset(PedalBoardItem*pedalBoardItem,
const std::string&presetUri);
};
+212 -124
View File
@@ -18,7 +18,7 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "pch.h"
#include <sched.h>
#include "PiPedalModel.hpp"
#include "JackHost.hpp"
#include "Lv2Log.hpp"
@@ -92,6 +92,10 @@ PiPedalModel::~PiPedalModel()
void PiPedalModel::LoadLv2PluginInfo(const PiPedalConfiguration&configuration)
{
storage.SetDataRoot(configuration.GetLocalStoragePath().c_str());
storage.Initialize();
// Not all Lv2 directories have the lv2 base declarations. Load a full set of plugin classes generated on a default /usr/local/lib/lv2 directory.
std::filesystem::path pluginClassesPath = configuration.GetDocRoot() / "plugin_classes.json";
try
@@ -109,6 +113,20 @@ void PiPedalModel::LoadLv2PluginInfo(const PiPedalConfiguration&configuration)
lv2Host.Load(configuration.GetLv2Path().c_str());
// Copy all presets out of Lilv data to json files
// so that we can close lilv while we're actually
// running.
for (const auto&plugin: lv2Host.GetPlugins())
{
if (plugin->has_factory_presets())
{
if (!storage.HasPluginPresets(plugin->uri()))
{
PluginPresets pluginPresets = lv2Host.GetFactoryPluginPresets(plugin->uri());
storage.SavePluginPresets(plugin->uri(),pluginPresets);
}
}
}
}
void PiPedalModel::Load(const PiPedalConfiguration &configuration)
@@ -117,8 +135,6 @@ void PiPedalModel::Load(const PiPedalConfiguration &configuration)
this->jackServerSettings.ReadJackConfiguration();
storage.SetDataRoot(configuration.GetLocalStoragePath().c_str());
storage.Initialize();
// lv2Host.Load(configuration.GetLv2Path().c_str());
@@ -131,7 +147,7 @@ void PiPedalModel::Load(const PiPedalConfiguration &configuration)
this->pedalBoard = currentPreset.preset_;
this->hasPresetChanged = currentPreset.modified_;
}
updateDefaults(&this->pedalBoard);
UpdateDefaults(&this->pedalBoard);
std::unique_ptr<JackHost> p{JackHost::CreateInstance(lv2Host.asIHost())};
this->jackHost = std::move(p);
@@ -150,6 +166,11 @@ void PiPedalModel::Load(const PiPedalConfiguration &configuration)
#endif
}
struct sched_param scheduler_params;
scheduler_params.sched_priority = 10;
memset(&scheduler_params,0,sizeof(sched_param));
sched_setscheduler(0,SCHED_RR,&scheduler_params);
this->jackConfiguration = jackHost->GetServerConfiguration();
if (this->jackConfiguration.isValid())
{
@@ -204,8 +225,8 @@ void PiPedalModel::RemoveNotificationSubsription(IPiPedalModelSubscriber *pSubsc
}
int64_t clientId = pSubscriber->GetClientId();
this->deleteMidiListeners(clientId);
this->deleteAtomOutputListeners(clientId);
this->DeleteMidiListeners(clientId);
this->DeleteAtomOutputListeners(clientId);
for (int i = 0; i < this->outstandingParameterRequests.size(); ++i)
{
@@ -218,17 +239,17 @@ void PiPedalModel::RemoveNotificationSubsription(IPiPedalModelSubscriber *pSubsc
}
}
void PiPedalModel::previewControl(int64_t clientId, int64_t pedalItemId, const std::string &symbol, float value)
void PiPedalModel::PreviewControl(int64_t clientId, int64_t pedalItemId, const std::string &symbol, float value)
{
jackHost->SetControlValue(pedalItemId, symbol, value);
}
void PiPedalModel::setControl(int64_t clientId, int64_t pedalItemId, const std::string &symbol, float value)
void PiPedalModel::SetControl(int64_t clientId, int64_t pedalItemId, const std::string &symbol, float value)
{
{
std::lock_guard<std::recursive_mutex> guard(mutex);
previewControl(clientId, pedalItemId, symbol, value);
PreviewControl(clientId, pedalItemId, symbol, value);
this->pedalBoard.SetControlValue(pedalItemId, symbol, value);
{
@@ -245,12 +266,12 @@ void PiPedalModel::setControl(int64_t clientId, int64_t pedalItemId, const std::
}
delete[] t;
this->setPresetChanged(clientId, true);
this->SetPresetChanged(clientId, true);
}
}
}
void PiPedalModel::fireJackConfigurationChanged(const JackConfiguration &jackConfiguration)
void PiPedalModel::FireJackConfigurationChanged(const JackConfiguration &jackConfiguration)
{
// noify subscribers.
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()];
@@ -266,7 +287,7 @@ void PiPedalModel::fireJackConfigurationChanged(const JackConfiguration &jackCon
delete[] t;
}
void PiPedalModel::fireBanksChanged(int64_t clientId)
void PiPedalModel::FireBanksChanged(int64_t clientId)
{
// noify subscribers.
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()];
@@ -282,7 +303,7 @@ void PiPedalModel::fireBanksChanged(int64_t clientId)
delete[] t;
}
void PiPedalModel::firePedalBoardChanged(int64_t clientId)
void PiPedalModel::FirePedalBoardChanged(int64_t clientId)
{
// noify subscribers.
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()];
@@ -303,25 +324,25 @@ void PiPedalModel::firePedalBoardChanged(int64_t clientId)
std::shared_ptr<Lv2PedalBoard> lv2PedalBoard{this->lv2Host.CreateLv2PedalBoard(this->pedalBoard)};
this->lv2PedalBoard = lv2PedalBoard;
jackHost->SetPedalBoard(lv2PedalBoard);
updateRealtimeVuSubscriptions();
updateRealtimeMonitorPortSubscriptions();
UpdateRealtimeVuSubscriptions();
UpdateRealtimeMonitorPortSubscriptions();
}
}
void PiPedalModel::setPedalBoard(int64_t clientId, PedalBoard &pedalBoard)
void PiPedalModel::SetPedalBoard(int64_t clientId, PedalBoard &pedalBoard)
{
{
std::lock_guard<std::recursive_mutex> guard(mutex);
this->pedalBoard = pedalBoard;
updateDefaults(&this->pedalBoard);
UpdateDefaults(&this->pedalBoard);
this->firePedalBoardChanged(clientId);
this->setPresetChanged(clientId, true);
this->FirePedalBoardChanged(clientId);
this->SetPresetChanged(clientId, true);
}
}
void PiPedalModel::setPedalBoardItemEnable(int64_t clientId, int64_t pedalItemId, bool enabled)
void PiPedalModel::SetPedalBoardItemEnable(int64_t clientId, int64_t pedalItemId, bool enabled)
{
std::lock_guard(this->mutex);
std::lock_guard<std::recursive_mutex> guard{mutex};
{
this->pedalBoard.SetItemEnabled(pedalItemId, enabled);
@@ -337,14 +358,14 @@ void PiPedalModel::setPedalBoardItemEnable(int64_t clientId, int64_t pedalItemId
t[i]->OnItemEnabledChanged(clientId, pedalItemId, enabled);
}
delete[] t;
this->setPresetChanged(clientId, true);
this->SetPresetChanged(clientId, true);
// Notify audo thread.
this->jackHost->SetBypass(pedalItemId, enabled);
}
}
void PiPedalModel::getPresets(PresetIndex *pResult)
void PiPedalModel::GetPresets(PresetIndex *pResult)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
@@ -352,29 +373,29 @@ void PiPedalModel::getPresets(PresetIndex *pResult)
pResult->presetChanged(this->hasPresetChanged);
}
PedalBoard PiPedalModel::getPreset(int64_t instanceId)
PedalBoard PiPedalModel::GetPreset(int64_t instanceId)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
return this->storage.GetPreset(instanceId);
}
void PiPedalModel::getBank(int64_t instanceId, BankFile *pResult)
void PiPedalModel::GetBank(int64_t instanceId, BankFile *pResult)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
this->storage.GetBankFile(instanceId, pResult);
}
void PiPedalModel::setPresetChanged(int64_t clientId, bool value)
void PiPedalModel::SetPresetChanged(int64_t clientId, bool value)
{
if (value != this->hasPresetChanged)
{
hasPresetChanged = value;
firePresetsChanged(clientId);
FirePresetsChanged(clientId);
}
}
void PiPedalModel::firePresetsChanged(int64_t clientId)
void PiPedalModel::FirePresetsChanged(int64_t clientId)
{
std::lock_guard(this->mutex);
std::lock_guard<std::recursive_mutex> guard{mutex};
{
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()];
@@ -385,7 +406,7 @@ void PiPedalModel::firePresetsChanged(int64_t clientId)
size_t n = this->subscribers.size();
PresetIndex presets;
getPresets(&presets);
GetPresets(&presets);
for (size_t i = 0; i < n; ++i)
{
@@ -394,66 +415,125 @@ void PiPedalModel::firePresetsChanged(int64_t clientId)
delete[] t;
}
}
void PiPedalModel::saveCurrentPreset(int64_t clientId)
void PiPedalModel::FirePluginPresetsChanged(const std::string & pluginUri)
{
std::lock_guard(this->mutex);
std::lock_guard<std::recursive_mutex> guard{mutex};
{
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()];
for (size_t i = 0; i < subscribers.size(); ++i)
{
t[i] = this->subscribers[i];
}
size_t n = this->subscribers.size();
storage.saveCurrentPreset(this->pedalBoard);
this->setPresetChanged(clientId, false);
for (size_t i = 0; i < n; ++i)
{
t[i]->OnPluginPresetsChanged(pluginUri);
}
delete[] t;
}
}
int64_t PiPedalModel::saveCurrentPresetAs(int64_t clientId, const std::string &name, int64_t saveAfterInstanceId)
void PiPedalModel::SaveCurrentPreset(int64_t clientId)
{
std::lock_guard(this->mutex);
std::lock_guard<std::recursive_mutex> guard{mutex};
storage.SaveCurrentPreset(this->pedalBoard);
this->SetPresetChanged(clientId, false);
}
uint64_t PiPedalModel::CopyPluginPreset(const std::string&pluginUri,uint64_t presetId)
{
uint64_t result = storage.CopyPluginPreset(pluginUri,presetId);
FirePluginPresetsChanged(pluginUri);
return result;
}
void PiPedalModel::UpdatePluginPresets(const PluginUiPresets&pluginPresets)
{
storage.UpdatePluginPresets(pluginPresets);
FirePluginPresetsChanged(pluginPresets.pluginUri_);
}
int64_t PiPedalModel::SavePluginPresetAs(int64_t instanceId, const std::string&name)
{
auto *item = this->pedalBoard.GetItem(instanceId);
if (!item)
{
throw PiPedalException("Plugin not found.");
}
std::map<std::string,float> values;
for (const auto & controlValue: item->controlValues())
{
values[controlValue.key()] = controlValue.value();
}
uint64_t presetId = storage.SavePluginPreset(item->uri(),name,values);
FirePluginPresetsChanged(item->uri());
return presetId;
}
int64_t PiPedalModel::SaveCurrentPresetAs(int64_t clientId, const std::string &name, int64_t saveAfterInstanceId)
{
std::lock_guard<std::recursive_mutex> guard{mutex};
int64_t result = storage.saveCurrentPresetAs(this->pedalBoard, name, saveAfterInstanceId);
this->hasPresetChanged = false;
firePresetsChanged(clientId);
FirePresetsChanged(clientId);
return result;
}
int64_t PiPedalModel::uploadPreset(const BankFile &bankFile, int64_t uploadAfter)
void PiPedalModel::UploadPluginPresets(const PluginPresets&pluginPresets)
{
std::lock_guard(this->mutex);
if (pluginPresets.pluginUri_.length() == 0)
{
throw PiPedalException("Invalid plugin presets.");
}
std::lock_guard<std::recursive_mutex> guard{mutex};
storage.SavePluginPresets(pluginPresets.pluginUri_,pluginPresets);
FirePluginPresetsChanged(pluginPresets.pluginUri_);
}
int64_t PiPedalModel::UploadPreset(const BankFile &bankFile, int64_t uploadAfter)
{
std::lock_guard<std::recursive_mutex> guard{mutex};
int64_t newPreset = this->storage.UploadPreset(bankFile, uploadAfter);
firePresetsChanged(-1);
FirePresetsChanged(-1);
return newPreset;
}
int64_t PiPedalModel::uploadBank(BankFile &bankFile, int64_t uploadAfter)
int64_t PiPedalModel::UploadBank(BankFile &bankFile, int64_t uploadAfter)
{
std::lock_guard(this->mutex);
std::lock_guard<std::recursive_mutex> guard{mutex};
int64_t newPreset = this->storage.UploadBank(bankFile, uploadAfter);
fireBanksChanged(-1);
FireBanksChanged(-1);
return newPreset;
}
void PiPedalModel::loadPreset(int64_t clientId, int64_t instanceId)
void PiPedalModel::LoadPreset(int64_t clientId, int64_t instanceId)
{
std::lock_guard(this->mutex);
std::lock_guard<std::recursive_mutex> guard{mutex};
if (storage.LoadPreset(instanceId))
{
this->pedalBoard = storage.GetCurrentPreset();
updateDefaults(&this->pedalBoard);
UpdateDefaults(&this->pedalBoard);
this->hasPresetChanged = false; // no fire.
this->firePedalBoardChanged(clientId);
this->firePresetsChanged(clientId); // fire now.
this->FirePedalBoardChanged(clientId);
this->FirePresetsChanged(clientId); // fire now.
}
}
int64_t PiPedalModel::copyPreset(int64_t clientId, int64_t from, int64_t to)
int64_t PiPedalModel::CopyPreset(int64_t clientId, int64_t from, int64_t to)
{
std::lock_guard(this->mutex);
std::lock_guard<std::recursive_mutex> guard{mutex};
int64_t result = storage.CopyPreset(from, to);
if (result != -1)
{
this->firePresetsChanged(clientId); // fire now.
this->FirePresetsChanged(clientId); // fire now.
}
else
{
@@ -461,51 +541,51 @@ int64_t PiPedalModel::copyPreset(int64_t clientId, int64_t from, int64_t to)
}
return result;
}
bool PiPedalModel::updatePresets(int64_t clientId, const PresetIndex &presets)
bool PiPedalModel::UpdatePresets(int64_t clientId, const PresetIndex &presets)
{
std::lock_guard(this->mutex);
std::lock_guard<std::recursive_mutex> guard{mutex};
storage.SetPresetIndex(presets);
firePresetsChanged(clientId);
FirePresetsChanged(clientId);
return true;
}
void PiPedalModel::moveBank(int64_t clientId, int from, int to)
void PiPedalModel::MoveBank(int64_t clientId, int from, int to)
{
std::lock_guard(this->mutex);
std::lock_guard<std::recursive_mutex> guard{mutex};
storage.MoveBank(from, to);
fireBanksChanged(clientId);
FireBanksChanged(clientId);
}
int64_t PiPedalModel::deleteBank(int64_t clientId, int64_t instanceId)
int64_t PiPedalModel::DeleteBank(int64_t clientId, int64_t instanceId)
{
std::lock_guard(this->mutex);
std::lock_guard<std::recursive_mutex> guard{mutex};
int64_t selectedBank = this->storage.GetBanks().selectedBank();
int64_t newSelection = storage.DeleteBank(instanceId);
int64_t newSelectedBank = this->storage.GetBanks().selectedBank();
this->fireBanksChanged(clientId); // fire now.
this->FireBanksChanged(clientId); // fire now.
if (newSelectedBank != selectedBank)
{
this->openBank(clientId, newSelectedBank);
this->OpenBank(clientId, newSelectedBank);
}
return newSelection;
}
int64_t PiPedalModel::deletePreset(int64_t clientId, int64_t instanceId)
int64_t PiPedalModel::DeletePreset(int64_t clientId, int64_t instanceId)
{
std::lock_guard(this->mutex);
std::lock_guard<std::recursive_mutex> guard{mutex};
int64_t newSelection = storage.DeletePreset(instanceId);
this->firePresetsChanged(clientId); // fire now.
this->FirePresetsChanged(clientId); // fire now.
return newSelection;
}
bool PiPedalModel::renamePreset(int64_t clientId, int64_t instanceId, const std::string &name)
bool PiPedalModel::RenamePreset(int64_t clientId, int64_t instanceId, const std::string &name)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
if (storage.RenamePreset(instanceId, name))
{
this->firePresetsChanged(clientId);
this->FirePresetsChanged(clientId);
return true;
}
else
@@ -514,7 +594,7 @@ bool PiPedalModel::renamePreset(int64_t clientId, int64_t instanceId, const std:
}
}
void PiPedalModel::setWifiConfigSettings(const WifiConfigSettings &wifiConfigSettings)
void PiPedalModel::SetWifiConfigSettings(const WifiConfigSettings &wifiConfigSettings)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
@@ -539,23 +619,23 @@ void PiPedalModel::setWifiConfigSettings(const WifiConfigSettings &wifiConfigSet
delete[] t;
}
}
WifiConfigSettings PiPedalModel::getWifiConfigSettings()
WifiConfigSettings PiPedalModel::GetWifiConfigSettings()
{
std::lock_guard<std::recursive_mutex> guard(mutex);
return this->storage.GetWifiConfigSettings();
}
JackConfiguration PiPedalModel::getJackConfiguration()
JackConfiguration PiPedalModel::GetJackConfiguration()
{
std::lock_guard<std::recursive_mutex> guard(mutex); // copy atomically.
return this->jackConfiguration;
}
void PiPedalModel::setJackChannelSelection(int64_t clientId, const JackChannelSelection &channelSelection)
void PiPedalModel::SetJackChannelSelection(int64_t clientId, const JackChannelSelection &channelSelection)
{
std::lock_guard<std::recursive_mutex> guard(mutex); // copy atomically.
this->storage.SetJackChannelSelection(channelSelection);
this->fireChannelSelectionChanged(clientId);
this->FireChannelSelectionChanged(clientId);
this->lv2Host.OnConfigurationChanged(jackConfiguration, channelSelection);
if (this->jackHost->IsOpen())
@@ -568,13 +648,13 @@ void PiPedalModel::setJackChannelSelection(int64_t clientId, const JackChannelSe
std::shared_ptr<Lv2PedalBoard> lv2PedalBoard{this->lv2Host.CreateLv2PedalBoard(this->pedalBoard)};
this->lv2PedalBoard = lv2PedalBoard;
jackHost->SetPedalBoard(lv2PedalBoard);
this->updateRealtimeVuSubscriptions();
this->UpdateRealtimeVuSubscriptions();
}
}
void PiPedalModel::fireChannelSelectionChanged(int64_t clientId)
void PiPedalModel::FireChannelSelectionChanged(int64_t clientId)
{
std::lock_guard(this->mutex);
std::lock_guard<std::recursive_mutex> guard{mutex};
{
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()];
@@ -594,7 +674,7 @@ void PiPedalModel::fireChannelSelectionChanged(int64_t clientId)
}
}
JackChannelSelection PiPedalModel::getJackChannelSelection()
JackChannelSelection PiPedalModel::GetJackChannelSelection()
{
std::lock_guard<std::recursive_mutex> guard(mutex);
JackChannelSelection t = this->storage.GetJackChannelSelection(this->jackConfiguration);
@@ -605,17 +685,17 @@ JackChannelSelection PiPedalModel::getJackChannelSelection()
return t;
}
int64_t PiPedalModel::addVuSubscription(int64_t instanceId)
int64_t PiPedalModel::AddVuSubscription(int64_t instanceId)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
int64_t subscriptionId = ++nextSubscriptionId;
activeVuSubscriptions.push_back(VuSubscription{subscriptionId, instanceId});
updateRealtimeVuSubscriptions();
UpdateRealtimeVuSubscriptions();
return subscriptionId;
}
void PiPedalModel::removeVuSubscription(int64_t subscriptionHandle)
void PiPedalModel::RemoveVuSubscription(int64_t subscriptionHandle)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
for (auto i = activeVuSubscriptions.begin(); i != activeVuSubscriptions.end(); ++i)
@@ -626,7 +706,7 @@ void PiPedalModel::removeVuSubscription(int64_t subscriptionHandle)
break;
}
}
updateRealtimeVuSubscriptions();
UpdateRealtimeVuSubscriptions();
}
void PiPedalModel::OnNotifyMidiValueChanged(int64_t instanceId, int portIndex, float value)
@@ -664,7 +744,7 @@ void PiPedalModel::OnNotifyMidiValueChanged(int64_t instanceId, int portIndex, f
}
delete[] t;
this->setPresetChanged(-1, true);
this->SetPresetChanged(-1, true);
return;
}
else
@@ -692,7 +772,7 @@ void PiPedalModel::OnNotifyMidiValueChanged(int64_t instanceId, int portIndex, f
}
delete[] t;
this->setPresetChanged(-1, true);
this->SetPresetChanged(-1, true);
return;
}
}
@@ -721,7 +801,7 @@ void PiPedalModel::OnNotifyVusSubscription(const std::vector<VuUpdate> &updates)
}
}
void PiPedalModel::updateRealtimeVuSubscriptions()
void PiPedalModel::UpdateRealtimeVuSubscriptions()
{
std::set<int64_t> addedInstances;
@@ -737,23 +817,23 @@ void PiPedalModel::updateRealtimeVuSubscriptions()
jackHost->SetVuSubscriptions(instanceids);
}
void PiPedalModel::updateRealtimeMonitorPortSubscriptions()
void PiPedalModel::UpdateRealtimeMonitorPortSubscriptions()
{
jackHost->SetMonitorPortSubscriptions(this->activeMonitorPortSubscriptions);
}
int64_t PiPedalModel::monitorPort(int64_t instanceId, const std::string &key, float updateInterval, PortMonitorCallback onUpdate)
int64_t PiPedalModel::MonitorPort(int64_t instanceId, const std::string &key, float updateInterval, PortMonitorCallback onUpdate)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
int64_t subscriptionId = ++nextSubscriptionId;
activeMonitorPortSubscriptions.push_back(
MonitorPortSubscription{subscriptionId, instanceId, key, updateInterval, onUpdate});
updateRealtimeMonitorPortSubscriptions();
UpdateRealtimeMonitorPortSubscriptions();
return subscriptionId;
}
void PiPedalModel::unmonitorPort(int64_t subscriptionHandle)
void PiPedalModel::UnmonitorPort(int64_t subscriptionHandle)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
@@ -762,7 +842,7 @@ void PiPedalModel::unmonitorPort(int64_t subscriptionHandle)
if ((*i).subscriptionHandle == subscriptionHandle)
{
activeMonitorPortSubscriptions.erase(i);
updateRealtimeMonitorPortSubscriptions();
UpdateRealtimeMonitorPortSubscriptions();
break;
}
}
@@ -785,7 +865,7 @@ void PiPedalModel::OnNotifyMonitorPort(const MonitorPortUpdate &update)
}
}
void PiPedalModel::getLv2Parameter(
void PiPedalModel::GetLv2Parameter(
int64_t clientId,
int64_t instanceId,
const std::string uri,
@@ -837,40 +917,40 @@ void PiPedalModel::getLv2Parameter(
this->jackHost->getRealtimeParameter(request);
}
BankIndex PiPedalModel::getBankIndex() const
BankIndex PiPedalModel::GetBankIndex() const
{
std::lock_guard<std::recursive_mutex> guard(const_cast<std::recursive_mutex&>(mutex));
return storage.GetBanks();
}
void PiPedalModel::renameBank(int64_t clientId, int64_t bankId, const std::string &newName)
void PiPedalModel::RenameBank(int64_t clientId, int64_t bankId, const std::string &newName)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
storage.RenameBank(bankId, newName);
fireBanksChanged(clientId);
FireBanksChanged(clientId);
}
int64_t PiPedalModel::saveBankAs(int64_t clientId, int64_t bankId, const std::string &newName)
int64_t PiPedalModel::SaveBankAs(int64_t clientId, int64_t bankId, const std::string &newName)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
int64_t newId = storage.SaveBankAs(bankId, newName);
fireBanksChanged(clientId);
FireBanksChanged(clientId);
return newId;
}
void PiPedalModel::openBank(int64_t clientId, int64_t bankId)
void PiPedalModel::OpenBank(int64_t clientId, int64_t bankId)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
storage.LoadBank(bankId);
fireBanksChanged(clientId);
FireBanksChanged(clientId);
firePresetsChanged(clientId);
FirePresetsChanged(clientId);
this->pedalBoard = storage.GetCurrentPreset();
updateDefaults(&this->pedalBoard);
UpdateDefaults(&this->pedalBoard);
this->hasPresetChanged = false;
this->firePedalBoardChanged(clientId);
this->FirePedalBoardChanged(clientId);
}
JackServerSettings PiPedalModel::GetJackServerSettings()
@@ -914,7 +994,7 @@ void PiPedalModel::SetJackServerSettings(const JackServerSettings &jackServerSet
storage.SaveCurrentPreset(currentPreset);
this->jackConfiguration.SetIsRestarting(true);
fireJackConfigurationChanged(this->jackConfiguration);
FireJackConfigurationChanged(this->jackConfiguration);
this->jackHost->UpdateServerConfiguration(
jackServerSettings,
[this](bool success, const std::string &errorMessage)
@@ -931,7 +1011,7 @@ void PiPedalModel::SetJackServerSettings(const JackServerSettings &jackServerSet
{
this->jackConfiguration.SetIsRestarting(false);
this->jackConfiguration.SetErrorStatus(errorMessage);
fireJackConfigurationChanged(this->jackConfiguration);
FireJackConfigurationChanged(this->jackConfiguration);
}
else
{
@@ -939,22 +1019,22 @@ void PiPedalModel::SetJackServerSettings(const JackServerSettings &jackServerSet
// so just sit tight and wait for the restart.
#ifdef JUNK
this->jackConfiguration.SetErrorStatus("");
fireJackConfigurationChanged(this->jackConfiguration);
FireJackConfigurationChanged(this->jackConfiguration);
// restart the pedalboard on a new instance.
std::shared_ptr<Lv2PedalBoard> lv2PedalBoard{this->lv2Host.CreateLv2PedalBoard(this->pedalBoard)};
this->lv2PedalBoard = lv2PedalBoard;
jackHost->SetPedalBoard(lv2PedalBoard);
updateRealtimeVuSubscriptions();
updateRealtimeMonitorPortSubscriptions();
UpdateRealtimeVuSubscriptions();
UpdateRealtimeMonitorPortSubscriptions();
#endif
}
});
}
}
void PiPedalModel::updateDefaults(PedalBoardItem *pedalBoardItem)
void PiPedalModel::UpdateDefaults(PedalBoardItem *pedalBoardItem)
{
std::shared_ptr<Lv2PluginInfo> t = lv2Host.GetPluginInfo(pedalBoardItem->uri());
const Lv2PluginInfo *pPlugin = t.get();
@@ -984,42 +1064,50 @@ void PiPedalModel::updateDefaults(PedalBoardItem *pedalBoardItem)
}
for (size_t i = 0; i < pedalBoardItem->topChain().size(); ++i)
{
updateDefaults(&(pedalBoardItem->topChain()[i]));
UpdateDefaults(&(pedalBoardItem->topChain()[i]));
}
for (size_t i = 0; i < pedalBoardItem->bottomChain().size(); ++i)
{
updateDefaults(&(pedalBoardItem->bottomChain()[i]));
UpdateDefaults(&(pedalBoardItem->bottomChain()[i]));
}
}
void PiPedalModel::updateDefaults(PedalBoard *pedalBoard)
void PiPedalModel::UpdateDefaults(PedalBoard *pedalBoard)
{
for (size_t i = 0; i < pedalBoard->items().size(); ++i)
{
updateDefaults(&(pedalBoard->items()[i]));
UpdateDefaults(&(pedalBoard->items()[i]));
}
}
std::vector<Lv2PluginPreset> PiPedalModel::GetPluginPresets(std::string pluginUri)
PluginPresets PiPedalModel::GetPluginPresets(const std::string& pluginUri)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
return lv2Host.GetPluginPresets(pluginUri);
return storage.GetPluginPresets(pluginUri);
}
void PiPedalModel::LoadPluginPreset(int64_t instanceId, const std::string &presetUri)
PluginUiPresets PiPedalModel::GetPluginUiPresets(const std::string& pluginUri)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
PedalBoardItem *pedalBoardItem = this->pedalBoard.GetItem(instanceId);
return storage.GetPluginUiPresets(pluginUri);
}
void PiPedalModel::LoadPluginPreset(int64_t pluginInstanceId, uint64_t presetInstanceId)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
PedalBoardItem *pedalBoardItem = this->pedalBoard.GetItem(pluginInstanceId);
if (pedalBoardItem != nullptr)
{
std::vector<ControlValue> controlValues = lv2Host.LoadPluginPreset(pedalBoardItem, presetUri);
jackHost->SetPluginPreset(instanceId, controlValues);
std::vector<ControlValue> controlValues = storage.GetPluginPresetValues(pedalBoardItem->uri(), presetInstanceId);
jackHost->SetPluginPreset(pluginInstanceId, controlValues);
for (size_t i = 0; i < controlValues.size(); ++i)
{
const ControlValue &value = controlValues[i];
this->pedalBoard.SetControlValue(instanceId, value.key(), value.value());
this->pedalBoard.SetControlValue(pluginInstanceId, value.key(), value.value());
}
IPiPedalModelSubscriber **t = new IPiPedalModelSubscriber *[this->subscribers.size()];
@@ -1030,13 +1118,13 @@ void PiPedalModel::LoadPluginPreset(int64_t instanceId, const std::string &prese
size_t n = this->subscribers.size();
for (size_t i = 0; i < n; ++i)
{
t[i]->OnLoadPluginPreset(instanceId, controlValues);
t[i]->OnLoadPluginPreset(pluginInstanceId, controlValues);
}
delete[] t;
}
}
void PiPedalModel::deleteAtomOutputListeners(int64_t clientId)
void PiPedalModel::DeleteAtomOutputListeners(int64_t clientId)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
for (size_t i = 0; i < atomOutputListeners.size(); ++i)
@@ -1050,7 +1138,7 @@ void PiPedalModel::deleteAtomOutputListeners(int64_t clientId)
jackHost->SetListenForAtomOutput(atomOutputListeners.size() != 0);
}
void PiPedalModel::deleteMidiListeners(int64_t clientId)
void PiPedalModel::DeleteMidiListeners(int64_t clientId)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
for (size_t i = 0; i < midiEventListeners.size(); ++i)
@@ -1111,7 +1199,7 @@ void PiPedalModel::OnNotifyMidiListen(bool isNote, uint8_t noteOrControl)
jackHost->SetListenForMidiEvent(midiEventListeners.size() != 0);
}
void PiPedalModel::listenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControlsOnly)
void PiPedalModel::ListenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControlsOnly)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
MidiListener listener{clientId, clientHandle, listenForControlsOnly};
@@ -1119,7 +1207,7 @@ void PiPedalModel::listenForMidiEvent(int64_t clientId, int64_t clientHandle, bo
jackHost->SetListenForMidiEvent(true);
}
void PiPedalModel::listenForAtomOutputs(int64_t clientId, int64_t clientHandle, uint64_t instanceId)
void PiPedalModel::ListenForAtomOutputs(int64_t clientId, int64_t clientHandle, uint64_t instanceId)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
AtomOutputListener listener{clientId, clientHandle, instanceId};
@@ -1127,7 +1215,7 @@ void PiPedalModel::listenForAtomOutputs(int64_t clientId, int64_t clientHandle,
jackHost->SetListenForAtomOutput(true);
}
void PiPedalModel::cancelListenForMidiEvent(int64_t clientId, int64_t clientHandle)
void PiPedalModel::CancelListenForMidiEvent(int64_t clientId, int64_t clientHandle)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
for (size_t i = 0; i < midiEventListeners.size(); ++i)
@@ -1144,7 +1232,7 @@ void PiPedalModel::cancelListenForMidiEvent(int64_t clientId, int64_t clientHand
jackHost->SetListenForMidiEvent(false);
}
}
void PiPedalModel::cancelListenForAtomOutputs(int64_t clientId, int64_t clientHandle)
void PiPedalModel::CancelListenForAtomOutputs(int64_t clientId, int64_t clientHandle)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
for (size_t i = 0; i < atomOutputListeners.size(); ++i)
+64 -55
View File
@@ -46,6 +46,7 @@ public:
virtual void OnControlChanged(int64_t clientId, int64_t pedalItemId, const std::string &symbol, float value) = 0;
virtual void OnPedalBoardChanged(int64_t clientId, const PedalBoard &pedalBoard) = 0;
virtual void OnPresetsChanged(int64_t clientId, const PresetIndex&presets) = 0;
virtual void OnPluginPresetsChanged(const std::string&pluginUri) = 0;
virtual void OnChannelSelectionChanged(int64_t clientId, const JackChannelSelection&channelSelection) = 0;
virtual void OnVuMeterUpdate(const std::vector<VuUpdate>& updates) = 0;
virtual void OnBankIndexChanged(const BankIndex& bankIndex) = 0;
@@ -77,8 +78,8 @@ private:
int64_t clientHandle;
uint64_t instanceId;
};
void deleteMidiListeners(int64_t clientId);
void deleteAtomOutputListeners(int64_t clientId);
void DeleteMidiListeners(int64_t clientId);
void DeleteAtomOutputListeners(int64_t clientId);
std::vector<MidiListener> midiEventListeners;
std::vector<AtomOutputListener> atomOutputListeners;
@@ -96,15 +97,16 @@ private:
std::vector<IPiPedalModelSubscriber*> subscribers;
void setPresetChanged(int64_t clientId,bool value);
void firePresetsChanged(int64_t clientId);
void firePedalBoardChanged(int64_t clientId);
void fireChannelSelectionChanged(int64_t clientId);
void fireBanksChanged(int64_t clientId);
void fireJackConfigurationChanged(const JackConfiguration&jackConfiguration);
void SetPresetChanged(int64_t clientId,bool value);
void FirePresetsChanged(int64_t clientId);
void FirePluginPresetsChanged(const std::string &pluginUri);
void FirePedalBoardChanged(int64_t clientId);
void FireChannelSelectionChanged(int64_t clientId);
void FireBanksChanged(int64_t clientId);
void FireJackConfigurationChanged(const JackConfiguration&jackConfiguration);
void updateDefaults(PedalBoardItem*pedalBoardItem);
void updateDefaults(PedalBoard*pedalBoard);
void UpdateDefaults(PedalBoardItem*pedalBoardItem);
void UpdateDefaults(PedalBoard*pedalBoard);
class VuSubscription {
@@ -117,8 +119,8 @@ private:
std::vector<MonitorPortSubscription> activeMonitorPortSubscriptions;
void updateRealtimeVuSubscriptions();
void updateRealtimeMonitorPortSubscriptions();
void UpdateRealtimeVuSubscriptions();
void UpdateRealtimeMonitorPortSubscriptions();
void OnVuUpdate(const std::vector<VuUpdate>& updates);
std::vector<RealtimeParameterRequest*> outstandingParameterRequests;
@@ -140,61 +142,68 @@ public:
void LoadLv2PluginInfo(const PiPedalConfiguration&configuration);
void Load(const PiPedalConfiguration&configuration);
const Lv2Host& getPlugins() const { return lv2Host; }
PedalBoard getCurrentPedalBoardCopy() {
const Lv2Host& GetLv2Host() const { return lv2Host; }
PedalBoard GetCurrentPedalBoardCopy()
{
std::lock_guard<std::recursive_mutex> guard(mutex);
return pedalBoard;
return pedalBoard; // can return a referece because we'd lose mutex protection
}
std::vector<Lv2PluginPreset> GetPluginPresets(std::string pluginUri);
void LoadPluginPreset(int64_t instanceId,const std::string &presetUri);
PluginUiPresets GetPluginUiPresets(const std::string& pluginUri);
PluginPresets GetPluginPresets(const std::string&pluginUri);
void LoadPluginPreset(int64_t pluginInstanceId,uint64_t presetInstanceId);
void AddNotificationSubscription(IPiPedalModelSubscriber* pSubscriber);
void RemoveNotificationSubsription(IPiPedalModelSubscriber* pSubscriber);
void setPedalBoardItemEnable(int64_t clientId, int64_t instanceId, bool enabled);
void setControl(int64_t clientId,int64_t pedalItemId, const std::string&symbol,float value);
void previewControl(int64_t clientId,int64_t pedalItemId, const std::string&symbol,float value);
void setPedalBoard(int64_t clientId,PedalBoard &pedalBoard);
void SetPedalBoardItemEnable(int64_t clientId, int64_t instanceId, bool enabled);
void SetControl(int64_t clientId,int64_t pedalItemId, const std::string&symbol,float value);
void PreviewControl(int64_t clientId,int64_t pedalItemId, const std::string&symbol,float value);
void SetPedalBoard(int64_t clientId,PedalBoard &pedalBoard);
void getPresets(PresetIndex*pResult);
PedalBoard getPreset(int64_t instanceId);
void getBank(int64_t instanceId, BankFile*pBank);
void GetPresets(PresetIndex*pResult);
PedalBoard GetPreset(int64_t instanceId);
void GetBank(int64_t instanceId, BankFile*pBank);
int64_t uploadBank(BankFile&bankFile, int64_t uploadAfter = -1);
int64_t uploadPreset(const BankFile&bankFile, int64_t uploadAfter = -1);
void saveCurrentPreset(int64_t clientId);
int64_t saveCurrentPresetAs(int64_t clientId, const std::string& name,int64_t saveAfterInstanceId = -1);
int64_t UploadBank(BankFile&bankFile, int64_t uploadAfter = -1);
int64_t UploadPreset(const BankFile&bankFile, int64_t uploadAfter = -1);
void UploadPluginPresets(const PluginPresets&pluginPresets);
void SaveCurrentPreset(int64_t clientId);
int64_t SaveCurrentPresetAs(int64_t clientId, const std::string& name,int64_t saveAfterInstanceId = -1);
int64_t SavePluginPresetAs(int64_t instanceId, const std::string&name);
void loadPreset(int64_t clientId, int64_t instanceId);
bool updatePresets(int64_t clientId,const PresetIndex&presets);
int64_t deletePreset(int64_t clientId,int64_t instanceId);
bool renamePreset(int64_t clientId,int64_t instanceId,const std::string&name);
int64_t copyPreset(int64_t clientId, int64_t fromIndex, int64_t toIndex);
void LoadPreset(int64_t clientId, int64_t instanceId);
bool UpdatePresets(int64_t clientId,const PresetIndex&presets);
void UpdatePluginPresets(const PluginUiPresets&pluginPresets);
int64_t DeletePreset(int64_t clientId,int64_t instanceId);
bool RenamePreset(int64_t clientId,int64_t instanceId,const std::string&name);
int64_t CopyPreset(int64_t clientId, int64_t fromIndex, int64_t toIndex);
uint64_t CopyPluginPreset(const std::string&pluginUri,uint64_t presetId);
void moveBank(int64_t clientId,int from, int to);
int64_t deleteBank(int64_t clientId, int64_t instanceId);
void MoveBank(int64_t clientId,int from, int to);
int64_t DeleteBank(int64_t clientId, int64_t instanceId);
int64_t duplicatePreset(int64_t clientId, int64_t instanceId) { return copyPreset(clientId,instanceId,-1); }
int64_t DuplicatePreset(int64_t clientId, int64_t instanceId) { return CopyPreset(clientId,instanceId,-1); }
JackConfiguration getJackConfiguration();
JackConfiguration GetJackConfiguration();
void setJackChannelSelection(int64_t clientId,const JackChannelSelection &channelSelection);
JackChannelSelection getJackChannelSelection();
void SetJackChannelSelection(int64_t clientId,const JackChannelSelection &channelSelection);
JackChannelSelection GetJackChannelSelection();
void setWifiConfigSettings(const WifiConfigSettings&wifiConfigSettings);
WifiConfigSettings getWifiConfigSettings();
void SetWifiConfigSettings(const WifiConfigSettings&wifiConfigSettings);
WifiConfigSettings GetWifiConfigSettings();
int64_t addVuSubscription(int64_t instanceId);
void removeVuSubscription(int64_t subscriptionHandle);
int64_t AddVuSubscription(int64_t instanceId);
void RemoveVuSubscription(int64_t subscriptionHandle);
int64_t monitorPort(int64_t instanceId,const std::string &key,float updateInterval, PortMonitorCallback onUpdate);
void unmonitorPort(int64_t subscriptionHandle);
int64_t MonitorPort(int64_t instanceId,const std::string &key,float updateInterval, PortMonitorCallback onUpdate);
void UnmonitorPort(int64_t subscriptionHandle);
void getLv2Parameter(
void GetLv2Parameter(
int64_t clientId,
int64_t instanceId,
const std::string uri,
@@ -202,22 +211,22 @@ public:
std::function<void (const std::string& error)> onError
);
BankIndex getBankIndex() const;
void renameBank(int64_t clientId,int64_t bankId, const std::string& newName);
int64_t saveBankAs(int64_t clientId,int64_t bankId, const std::string& newName);
void openBank(int64_t clientId,int64_t bankId);
BankIndex GetBankIndex() const;
void RenameBank(int64_t clientId,int64_t bankId, const std::string& newName);
int64_t SaveBankAs(int64_t clientId,int64_t bankId, const std::string& newName);
void OpenBank(int64_t clientId,int64_t bankId);
JackHostStatus getJackStatus() {
JackHostStatus GetJackStatus() {
return this->jackHost->getJackStatus();
}
JackServerSettings GetJackServerSettings();
void SetJackServerSettings(const JackServerSettings& jackServerSettings);
void listenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControlsOnly);
void cancelListenForMidiEvent(int64_t clientId, int64_t clientHandle);
void ListenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControlsOnly);
void CancelListenForMidiEvent(int64_t clientId, int64_t clientHandle);
void listenForAtomOutputs(int64_t clientId, int64_t clientHandle, uint64_t instanceId);
void cancelListenForAtomOutputs(int64_t clientId, int64_t clientHandle);
void ListenForAtomOutputs(int64_t clientId, int64_t clientHandle, uint64_t instanceId);
void CancelListenForAtomOutputs(int64_t clientId, int64_t clientHandle);
std::vector<AlsaDeviceInfo> GetAlsaDevices();
const std::filesystem::path& GetWebRoot() const;
+95 -44
View File
@@ -108,14 +108,14 @@ JSON_MAP_END()
class LoadPluginPresetBody {
public:
int64_t instanceId_;
std::string presetName_;
uint64_t pluginInstanceId_;
uint64_t presetInstanceId_;
DECLARE_JSON_MAP(LoadPluginPresetBody);
};
JSON_MAP_BEGIN(LoadPluginPresetBody)
JSON_MAP_REFERENCE(LoadPluginPresetBody, instanceId)
JSON_MAP_REFERENCE(LoadPluginPresetBody, presetName)
JSON_MAP_REFERENCE(LoadPluginPresetBody, pluginInstanceId)
JSON_MAP_REFERENCE(LoadPluginPresetBody, presetInstanceId)
JSON_MAP_END()
class FromToBody
@@ -189,6 +189,19 @@ JSON_MAP_REFERENCE(SaveCurrentPresetAsBody, name)
JSON_MAP_REFERENCE(SaveCurrentPresetAsBody, saveAfterInstanceId)
JSON_MAP_END()
class SavePluginPresetAsBody
{
public:
int64_t instanceId_ = -1;
std::string name_;
DECLARE_JSON_MAP(SavePluginPresetAsBody);
};
JSON_MAP_BEGIN(SavePluginPresetAsBody)
JSON_MAP_REFERENCE(SavePluginPresetAsBody, instanceId)
JSON_MAP_REFERENCE(SavePluginPresetAsBody, name)
JSON_MAP_END()
class RenameBankBody {
public:
int64_t bankId_;
@@ -231,6 +244,19 @@ JSON_MAP_REFERENCE(CopyPresetBody, fromId)
JSON_MAP_REFERENCE(CopyPresetBody, toId)
JSON_MAP_END()
class CopyPluginPresetBody
{
public:
std::string pluginUri_;
uint64_t instanceId_;
DECLARE_JSON_MAP(CopyPluginPresetBody);
};
JSON_MAP_BEGIN(CopyPluginPresetBody)
JSON_MAP_REFERENCE(CopyPluginPresetBody, pluginUri)
JSON_MAP_REFERENCE(CopyPluginPresetBody, instanceId)
JSON_MAP_END()
class PedalBoardItemEnabledBody
{
public:
@@ -374,11 +400,11 @@ public:
{
for (int i = 0; i < this->activePortMonitors.size(); ++i)
{
model.unmonitorPort(activePortMonitors[i].subscriptionHandle);
model.UnmonitorPort(activePortMonitors[i].subscriptionHandle);
}
for (int i = 0; i < this->activeVuSubscriptions.size(); ++i)
{
model.removeVuSubscription(activeVuSubscriptions[i].subscriptionHandle);
model.RemoveVuSubscription(activeVuSubscriptions[i].subscriptionHandle);
}
model.RemoveNotificationSubsription(this);
@@ -708,42 +734,42 @@ public:
{
ControlChangedBody message;
pReader->read(&message);
this->model.previewControl(message.clientId_, message.instanceId_, message.symbol_, message.value_);
this->model.PreviewControl(message.clientId_, message.instanceId_, message.symbol_, message.value_);
}
else if (message == "setControl")
{
ControlChangedBody message;
pReader->read(&message);
this->model.setControl(message.clientId_, message.instanceId_, message.symbol_, message.value_);
this->model.SetControl(message.clientId_, message.instanceId_, message.symbol_, message.value_);
}
else if (message == "listenForMidiEvent")
{
ListenForMidiEventBody body;
pReader->read(&body);
this->model.listenForMidiEvent(this->clientId,body.handle_, body.listenForControlsOnly_);
this->model.ListenForMidiEvent(this->clientId,body.handle_, body.listenForControlsOnly_);
}
else if (message == "cancelListenForMidiEvent")
{
uint64_t handle;
pReader->read(&handle);
this->model.cancelListenForMidiEvent(this->clientId,handle);
this->model.CancelListenForMidiEvent(this->clientId,handle);
}
else if (message == "listenForAtomOutput")
{
ListenForAtomOutputBody body;
pReader->read(&body);
this->model.listenForAtomOutputs(this->clientId,body.handle_, body.instanceId_);
this->model.ListenForAtomOutputs(this->clientId,body.handle_, body.instanceId_);
}
else if (message == "cancelListenForAtomOutput")
{
int64_t handle;
pReader->read(&handle);
this->model.cancelListenForMidiEvent(this->clientId,handle);
this->model.CancelListenForMidiEvent(this->clientId,handle);
}
else if (message == "getJackStatus")
{
JackHostStatus status = model.getJackStatus();
JackHostStatus status = model.GetJackStatus();
this->Reply(replyTo,"getJackStatus",status);
} else if (message == "getAlsaDevices")
{
@@ -762,13 +788,13 @@ public:
{
std::string uri;
pReader->read(&uri);
this->Reply(replyTo,"getPluginPresets",this->model.GetPluginPresets(uri));
this->Reply(replyTo,"getPluginPresets",this->model.GetPluginUiPresets(uri));
}
else if (message == "loadPluginPreset")
{
LoadPluginPresetBody body;
pReader->read(&body);
this->model.LoadPluginPreset(body.instanceId_,body.presetName_);
this->model.LoadPluginPreset(body.pluginInstanceId_,body.presetInstanceId_);
}
else if (message == "setJackServerSettings") {
@@ -792,11 +818,11 @@ public:
}
this->model.setWifiConfigSettings(wifiConfigSettings);
this->model.SetWifiConfigSettings(wifiConfigSettings);
this->Reply(replyTo,"setWifiConfigSettings");
}
else if (message == "getWifiConfigSettings") {
this->Reply(replyTo, "getWifiConfigSettings", model.getWifiConfigSettings());
this->Reply(replyTo, "getWifiConfigSettings", model.GetWifiConfigSettings());
}
@@ -805,42 +831,49 @@ public:
}
else if (message == "getBankIndex") {
BankIndex bankIndex = model.getBankIndex();
BankIndex bankIndex = model.GetBankIndex();
this->Reply(replyTo, "getBankIndex", bankIndex);
}
else if (message == "getJackConfiguration")
{
JackConfiguration configuration = this->model.getJackConfiguration();
JackConfiguration configuration = this->model.GetJackConfiguration();
this->Reply(replyTo, "getJackConfiguration", configuration);
}
else if (message == "getJackSettings")
{
JackChannelSelection selection = this->model.getJackChannelSelection();
JackChannelSelection selection = this->model.GetJackChannelSelection();
this->Reply(replyTo, "getJackSettings", selection);
}
else if (message == "saveCurrentPreset")
{
this->model.saveCurrentPreset(this->clientId);
this->model.SaveCurrentPreset(this->clientId);
}
else if (message == "saveCurrentPresetAs")
{
SaveCurrentPresetAsBody body;
pReader->read(&body);
int64_t result = this->model.saveCurrentPresetAs(this->clientId, body.name_, body.saveAfterInstanceId_);
int64_t result = this->model.SaveCurrentPresetAs(this->clientId, body.name_, body.saveAfterInstanceId_);
Reply(replyTo, "saveCurrentPresetsAs", result);
}
else if (message == "savePluginPresetAs")
{
SavePluginPresetAsBody body;
pReader->read(&body);
int64_t result = this->model.SavePluginPresetAs(body.instanceId_, body.name_);
Reply(replyTo, "saveCurrentPresetsAs", result);
}
else if (message == "getPresets")
{
PresetIndex presets;
this->model.getPresets(&presets);
this->model.GetPresets(&presets);
Reply(replyTo, "getPresets", presets);
}
else if (message == "setPedalBoardItemEnable")
{
PedalBoardItemEnabledBody body;
pReader->read(&body);
model.setPedalBoardItemEnable(body.clientId_, body.instanceId_, body.enabled_);
model.SetPedalBoardItemEnable(body.clientId_, body.instanceId_, body.enabled_);
}
else if (message == "setCurrentPedalBoard")
{
@@ -848,22 +881,22 @@ public:
SetCurrentPedalBoardBody body;
pReader->read(&body);
this->model.setPedalBoard(body.clientId_, body.pedalBoard_);
this->model.SetPedalBoard(body.clientId_, body.pedalBoard_);
}
}
else if (message == "currentPedalBoard")
{
auto pedalBoard = model.getCurrentPedalBoardCopy();
auto pedalBoard = model.GetCurrentPedalBoardCopy();
Reply(replyTo, "currentPedalBoard", pedalBoard);
}
else if (message == "plugins")
{
auto ui_plugins = model.getPlugins().GetUiPlugins();
auto ui_plugins = model.GetLv2Host().GetUiPlugins();
Reply(replyTo, "plugins", ui_plugins);
}
else if (message == "pluginClasses")
{
auto classes = model.getPlugins().GetLv2PluginClass();
auto classes = model.GetLv2Host().GetLv2PluginClass();
Reply(replyTo, "pluginClasses", classes);
}
else if (message == "hello")
@@ -875,7 +908,7 @@ public:
{
JackChannelSelection jackSettings;
pReader->read(&jackSettings);
this->model.setJackChannelSelection(this->clientId, jackSettings);
this->model.SetJackChannelSelection(this->clientId, jackSettings);
}
else if (message == "version")
{
@@ -887,20 +920,27 @@ public:
{
int64_t instanceId = 0;
pReader->read(&instanceId);
model.loadPreset(this->clientId, instanceId);
model.LoadPreset(this->clientId, instanceId);
}
else if (message == "updatePresets")
{
PresetIndex newIndex;
pReader->read(&newIndex);
bool result = model.updatePresets(this->clientId, newIndex);
bool result = model.UpdatePresets(this->clientId, newIndex);
this->Reply(replyTo, "updatePresets", result);
}
else if (message == "updatePluginPresets")
{
PluginUiPresets pluginPresets;
pReader->read(&pluginPresets);
model.UpdatePluginPresets(pluginPresets);
this->Reply(replyTo, "updatePluginPresets", true);
}
else if (message == "moveBank")
{
FromToBody body;
pReader->read(&body);
model.moveBank(this->clientId, body.from_, body.to_);
model.MoveBank(this->clientId, body.from_, body.to_);
this->Reply(replyTo, "moveBank");
}
else if (message == "shutdown")
@@ -920,14 +960,14 @@ public:
{
int64_t instanceId = 0;
pReader->read(&instanceId);
int64_t result = model.deletePreset(this->clientId, instanceId);
int64_t result = model.DeletePreset(this->clientId, instanceId);
this->Reply(replyTo, "deletePresetItem", result);
}
else if (message == "deleteBankItem")
{
int64_t instanceId = 0;
pReader->read(&instanceId);
uint64_t result = model.deleteBank(this->clientId, instanceId);
uint64_t result = model.DeleteBank(this->clientId, instanceId);
this->Reply(replyTo, "deleteBankItem", result);
}
else if (message == "renameBank")
@@ -948,7 +988,7 @@ public:
try {
model.renameBank(this->clientId,body.bankId_, body.newName_);
model.RenameBank(this->clientId,body.bankId_, body.newName_);
this->Reply(replyTo, "renameBank");
} catch (const std::exception &e)
{
@@ -960,7 +1000,7 @@ public:
int64_t bankId = -1;
pReader->read(&bankId);
try {
model.openBank(this->clientId,bankId);;
model.OpenBank(this->clientId,bankId);;
this->Reply(replyTo, "openBank");
} catch (const std::exception &e)
{
@@ -972,7 +1012,7 @@ public:
RenameBankBody body;
pReader->read(&body);
try {
int64_t newId = model.saveBankAs(this->clientId,body.bankId_, body.newName_);
int64_t newId = model.SaveBankAs(this->clientId,body.bankId_, body.newName_);
this->Reply(replyTo, "saveBankAs",newId);
} catch (const std::exception &e)
{
@@ -984,22 +1024,29 @@ public:
RenamePresetBody body;
pReader->read(&body);
bool result = model.renamePreset(body.clientId_, body.instanceId_, body.name_);
bool result = model.RenamePreset(body.clientId_, body.instanceId_, body.name_);
this->Reply(replyTo, "renamePresetItem", result);
}
else if (message == "copyPreset")
{
CopyPresetBody body;
pReader->read(&body);
int64_t result = model.copyPreset(body.clientId_, body.fromId_, body.toId_);
int64_t result = model.CopyPreset(body.clientId_, body.fromId_, body.toId_);
this->Reply(replyTo, "copyPreset", result);
}
else if (message == "copyPluginPreset")
{
CopyPluginPresetBody body;
pReader->read(&body);
uint64_t result = model.CopyPluginPreset(body.pluginUri_,body.instanceId_);
this->Reply(replyTo, "copyPluginPreset", result);
}
else if (message =="getLv2Parameter")
{
GetLv2ParameterBody body;
pReader->read(&body);
model.getLv2Parameter(
model.GetLv2Parameter(
this->clientId,
body.instanceId_,
body.uri_,
@@ -1018,7 +1065,7 @@ public:
MonitorPortBody body;
pReader->read(&body);
int64_t subscriptionHandle = model.monitorPort(
int64_t subscriptionHandle = model.MonitorPort(
body.instanceId_,
body.key_,
body.updateRate_,
@@ -1067,7 +1114,7 @@ public:
}
}
}
model.unmonitorPort(subscriptionHandle);
model.UnmonitorPort(subscriptionHandle);
}
}
else if (message == "addVuSubscription")
@@ -1076,7 +1123,7 @@ public:
pReader->read(&instanceId);
int64_t subscriptionHandle = model.addVuSubscription(instanceId);
int64_t subscriptionHandle = model.AddVuSubscription(instanceId);
{
std::lock_guard<std::recursive_mutex> guard(subscriptionMutex);
@@ -1100,7 +1147,7 @@ public:
}
}
}
model.removeVuSubscription(subscriptionHandle);
model.RemoveVuSubscription(subscriptionHandle);
}
else if (message == "imageList")
{
@@ -1194,6 +1241,10 @@ public:
body.presets_ = const_cast<PresetIndex *>(&presets);
Send("onPresetsChanged", body);
}
virtual void OnPluginPresetsChanged(const std::string&pluginUri)
{
Send("onPluginPresetsChanged", pluginUri);
}
virtual void OnJackConfigurationChanged(const JackConfiguration &jackConfiguration)
{
Send("onJackConfigurationChanged", jackConfiguration);
+47
View File
@@ -0,0 +1,47 @@
#include "PluginPreset.hpp"
using namespace pipedal;
JSON_MAP_BEGIN(PluginUiPreset)
JSON_MAP_REFERENCE(PluginUiPreset,label)
JSON_MAP_REFERENCE(PluginUiPreset,instanceId)
JSON_MAP_END()
JSON_MAP_BEGIN(PluginUiPresets)
JSON_MAP_REFERENCE(PluginUiPresets,pluginUri)
JSON_MAP_REFERENCE(PluginUiPresets,presets)
JSON_MAP_END()
JSON_MAP_BEGIN(PluginPresetIndexEntry)
JSON_MAP_REFERENCE(PluginPresetIndexEntry,pluginUri)
JSON_MAP_REFERENCE(PluginPresetIndexEntry,fileName)
JSON_MAP_END()
JSON_MAP_BEGIN(PluginPresetIndex)
JSON_MAP_REFERENCE(PluginPresetIndex,entries)
JSON_MAP_REFERENCE(PluginPresetIndex,nextInstanceId)
JSON_MAP_END()
JSON_MAP_BEGIN(PluginPreset)
JSON_MAP_REFERENCE(PluginPreset,instanceId)
JSON_MAP_REFERENCE(PluginPreset,label)
JSON_MAP_REFERENCE(PluginPreset,controlValues)
JSON_MAP_END()
JSON_MAP_BEGIN(PluginPresets)
JSON_MAP_REFERENCE(PluginPresets,pluginUri)
JSON_MAP_REFERENCE(PluginPresets,presets)
JSON_MAP_REFERENCE(PluginPresets,nextInstanceId)
JSON_MAP_END()
// JSON_MAP_BEGIN(PluginPreset)
// JSON_MAP_REFERENCE(PluginPreset,presetUri)
// JSON_MAP_REFERENCE(PluginPreset,name)
// JSON_MAP_REFERENCE(PluginPreset,factoryPreset)
// JSON_MAP_REFERENCE(PluginPreset,modified)
// JSON_MAP_REFERENCE(PluginPreset,selected)
// JSON_MAP_END()
+136
View File
@@ -0,0 +1,136 @@
// Copyright (c) 2021 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.
#pragma once
#include "json.hpp"
#include "PiPedalException.hpp"
#include <utility>
namespace pipedal {
class PluginPresetIndexEntry {
public:
PluginPresetIndexEntry() { }
PluginPresetIndexEntry(const std::string &pluginUri, const std::string&fileName)
: pluginUri_(pluginUri),
fileName_(fileName)
{
}
std::string pluginUri_;
std::string fileName_;
DECLARE_JSON_MAP(PluginPresetIndexEntry);
};
class PluginUiPreset {
public:
std::string label_;
uint64_t instanceId_;
DECLARE_JSON_MAP(PluginUiPreset);
};
class PluginUiPresets {
public:
std::string pluginUri_;
std::vector<PluginUiPreset> presets_;
DECLARE_JSON_MAP(PluginUiPresets);
};
class PluginPresetIndex {
public:
std::vector<PluginPresetIndexEntry> entries_;
uint64_t nextInstanceId_ = 1;
DECLARE_JSON_MAP(PluginPresetIndex);
};
class PluginPreset {
public:
PluginPreset() { }
PluginPreset(uint64_t instanceId, std::string&&label, std::map<std::string,float> && controlValues)
: instanceId_(instanceId),
label_(std::forward<std::string>(label)),
controlValues_(std::forward<std::map<std::string,float>>(controlValues))
{
}
PluginPreset(uint64_t instanceId, const std::string&label, const std::map<std::string,float> & controlValues)
: instanceId_(instanceId),
label_(label),
controlValues_(controlValues)
{
}
uint64_t instanceId_;
std::string label_;
std::map<std::string,float> controlValues_;
DECLARE_JSON_MAP(PluginPreset);
};
class PluginPresets {
public:
std::string pluginUri_;
std::vector<PluginPreset> presets_;
uint64_t nextInstanceId_ = 1;
const PluginPreset&GetPreset(uint64_t presetId) {
for (const auto&preset: presets_)
{
if (preset.instanceId_ == presetId)
{
return preset;
}
}
throw PiPedalException("Preset id not found.");
}
int Find(const std::string &label)
{
for (size_t i = 0; i < presets_.size(); ++i)
{
if (presets_[i].label_ == label)
{
return i;
}
}
return -1;
}
int Find(uint64_t instanceId)
{
for (size_t i = 0; i < presets_.size(); ++i)
{
if (presets_[i].instanceId_ == instanceId)
{
return i;
}
}
return -1;
}
DECLARE_JSON_MAP(PluginPresets);
};
} // namespace
+276 -1
View File
@@ -165,11 +165,13 @@ void Storage::Initialize()
try
{
std::filesystem::create_directories(this->GetPresetsDirectory());
std::filesystem::create_directories(this->GetPluginPresetsDirectory());
}
catch (const std::exception &e)
{
throw PiPedalStateException("Can't create presets directory. (" + (std::string)this->GetPresetsDirectory() + ") (" + e.what() + ")");
}
LoadPluginPresetIndex();
LoadBankIndex();
LoadCurrentBank();
try
@@ -205,6 +207,10 @@ std::filesystem::path Storage::GetPresetsDirectory() const
{
return this->dataRoot / "presets";
}
std::filesystem::path Storage::GetPluginPresetsDirectory() const
{
return this->dataRoot / "plugin_presets";
}
std::filesystem::path Storage::GetCurrentPresetPath() const
{
return this->dataRoot / "currentPreset.json";
@@ -255,6 +261,43 @@ void Storage::LoadBankIndex()
SaveBankIndex();
}
}
void Storage::LoadPluginPresetIndex()
{
try
{
auto path = GetPluginPresetsDirectory() / "index.json";
std::ifstream s;
if (std::filesystem::exists(path))
{
s.open(path);
json_reader reader(s);
reader.read(&pluginPresetIndex);
}
}
catch (const std::exception &)
{
}
}
void Storage::SavePluginPresetIndex()
{
if (pluginPresetIndexChanged)
{
pluginPresetIndexChanged = false;
std::ofstream os;
auto path = GetPluginPresetsDirectory() / "index.json";
os.open(path, std::ios_base::trunc);
if (os.fail())
{
throw PiPedalException(SS("Can't write to " << path));
}
json_writer writer(os);
writer.write(this->pluginPresetIndex);
}
}
void Storage::SaveBankIndex()
{
std::ofstream os;
@@ -374,7 +417,7 @@ bool Storage::LoadPreset(int64_t instanceId)
}
return true;
}
void Storage::saveCurrentPreset(const PedalBoard &pedalBoard)
void Storage::SaveCurrentPreset(const PedalBoard &pedalBoard)
{
auto &item = currentBank.getItem(currentBank.selectedPreset());
item.preset(pedalBoard);
@@ -860,6 +903,238 @@ bool Storage::RestoreCurrentPreset(CurrentPreset*pResult)
return false;
}
}
bool Storage::HasPluginPresets(const std::string &pluginUri) const
{
for (const auto &entry: this->pluginPresetIndex.entries_)
{
if (entry.pluginUri_ == pluginUri)
{
return true;
}
}
return false;
}
std::filesystem::path Storage::GetPluginPresetPath(const std::string &pluginUri) const
{
for (const auto &entry: this->pluginPresetIndex.entries_)
{
if (entry.pluginUri_ == pluginUri)
{
return this->GetPluginPresetsDirectory() / entry.fileName_;
}
}
throw PiPedalArgumentException("Plugin preset file not found.");
}
void Storage::SavePluginPresets(const std::string&pluginUri, const PluginPresets&presets)
{
std::string name;
std::filesystem::path path;
bool presetAdded = false;
if (!HasPluginPresets(pluginUri))
{
name = SS(pluginPresetIndex.nextInstanceId_ << ".json");
path = GetPluginPresetsDirectory() / name;
presetAdded = true;
} else {
path = GetPluginPresetPath(pluginUri);
}
auto tempPath = path.string()+".$$$";
{
std::ofstream os;
os.open(tempPath, std::ios_base::trunc);
if (os.fail())
{
throw PiPedalException(SS("Can't write to " << path));
}
json_writer writer(os);
writer.write(presets);
}
if (std::filesystem::exists(path))
{
std::filesystem::remove(path);
}
std::filesystem::rename(tempPath,path);
if (presetAdded)
{
pluginPresetIndex.entries_.push_back(
PluginPresetIndexEntry(
pluginUri,name
)
);
pluginPresetIndex.nextInstanceId_++;
this->pluginPresetIndexChanged = true;
SavePluginPresetIndex();
}
}
PluginPresets Storage::GetPluginPresets(const std::string&pluginUri) const
{
PluginPresets result;
if (!HasPluginPresets(pluginUri))
{
result.pluginUri_ = pluginUri;
return result;
}
std::filesystem::path path = GetPluginPresetPath(pluginUri);
std::ifstream s;
s.open(path);
if (s.fail())
{
return result;
}
json_reader reader(s);
reader.read(&result);
return result;
}
PluginUiPresets Storage::GetPluginUiPresets(const std::string&pluginUri) const
{
PluginPresets presets = GetPluginPresets(pluginUri);
PluginUiPresets result;
result.pluginUri_ = presets.pluginUri_;
for (size_t i = 0; i < presets.presets_.size(); ++i)
{
const auto& preset = presets.presets_[i];
result.presets_.push_back(
PluginUiPreset
{
preset.label_,
preset.instanceId_
}
);
}
return result;
}
std::vector<ControlValue> Storage::GetPluginPresetValues(const std::string&pluginUri, uint64_t instanceId)
{
auto presets = GetPluginPresets(pluginUri);
for (const auto & preset: presets.presets_)
{
if (preset.instanceId_ == instanceId)
{
std::vector<ControlValue> result;
for (const auto &valuePair: preset.controlValues_)
{
result.push_back(ControlValue(valuePair.first.c_str(),valuePair.second));
}
return result;
}
}
throw PiPedalException("Plugin preset not found.");
}
uint64_t Storage::SavePluginPreset(
const std::string&pluginUri,
const std::string&name,
const std::map<std::string,float> & values)
{
auto presets = GetPluginPresets(pluginUri);
uint64_t result = -1;
bool existing = false;
for (size_t i = 0; i < presets.presets_.size(); ++i)
{
auto & preset = presets.presets_[i];
if (preset.label_ == name)
{
preset.controlValues_ = values;
existing = true;
result = preset.instanceId_;
break;
}
}
if (!existing)
{
result = presets.nextInstanceId_++;
presets.presets_.push_back(
PluginPreset(
result,
name,
values
));
}
this->SavePluginPresets(pluginUri,presets);
return result;
}
void Storage::UpdatePluginPresets(const PluginUiPresets &pluginPresets)
{
// handles deletions, renaming, and reordering only.
// If you need to add a preset, you neet to call SavePluginPreset or DulicatePluginPreset instead.
PluginPresets presets = this->GetPluginPresets(pluginPresets.pluginUri_);
PluginPresets newPresets;
newPresets.pluginUri_ = pluginPresets.pluginUri_;
newPresets.nextInstanceId_ = presets.nextInstanceId_;
for (const auto&preset: pluginPresets.presets_)
{
PluginPreset newPreset = presets.GetPreset(preset.instanceId_);
newPreset.label_ = preset.label_;
newPresets.presets_.push_back(std::move(newPreset));
}
SavePluginPresets(newPresets.pluginUri_,newPresets);
}
static std::string stripCopySuffix(const std::string &s)
{
int pos = s.length()-1;
if (pos >= 0 && s[pos] == ')')
{
--pos;
while (pos >= 0 && s[pos] >= '0' && s[pos] <= '9')
{
--pos;
}
if (pos >= 0 && s[pos] == '(')
{
--pos;
}
while (pos >= 0 && s[pos] == ' ')
{
--pos;
}
return s.substr(0,pos+1);
}
return s;
}
uint64_t Storage::CopyPluginPreset(const std::string&pluginUri,uint64_t presetId)
{
PluginPresets presets = this->GetPluginPresets(pluginUri);
size_t pos = presets.Find(presetId);
if (pos == -1)
{
throw PiPedalException("Perset not found.");
}
PluginPreset t = presets.presets_[pos];
t.instanceId_ = presets.nextInstanceId_++;
std::string baseName = stripCopySuffix(t.label_);
std::string name = baseName;
if (presets.Find(name) != -1)
{
int nCopy = 1;
while (true)
{
name = SS(baseName << " (" << nCopy << ")");
if (presets.Find(name) == -1)
{
break;
}
++nCopy;
}
}
t.label_ = name;
presets.presets_.insert(presets.presets_.begin()+pos+1,t);
SavePluginPresets(presets.pluginUri_,presets);
return t.instanceId_;
}
JSON_MAP_BEGIN(CurrentPreset)
+18 -3
View File
@@ -22,6 +22,7 @@
#include <iostream>
#include "PedalBoard.hpp"
#include "Presets.hpp"
#include "PluginPreset.hpp"
#include "Banks.hpp"
#include "JackConfiguration.hpp"
#include "WifiConfigSettings.hpp"
@@ -45,17 +46,18 @@ private:
std::filesystem::path dataRoot;
BankIndex bankIndex;
BankFile currentBank;
PluginPresetIndex pluginPresetIndex;
private:
static std::string SafeEncodeName(const std::string& name);
static std::string SafeDecodeName(const std::string& name);
std::filesystem::path GetPresetsDirectory() const;
std::filesystem::path GetPluginPresetsDirectory() const;
std::filesystem::path GetIndexFileName() const;
std::filesystem::path GetBankFileName(const std::string & name) const;
std::filesystem::path GetChannelSelectionFileName();
std::filesystem::path GetCurrentPresetPath() const;
void LoadBankIndex();
void SaveBankIndex();
void ReIndex();
@@ -85,7 +87,7 @@ public:
void LoadWifiConfigSettings();
void LoadBank(int64_t instanceId);
const PedalBoard& GetCurrentPreset();
void saveCurrentPreset(const PedalBoard&pedalBoard);
void SaveCurrentPreset(const PedalBoard&pedalBoard);
int64_t saveCurrentPresetAs(const PedalBoard&pedalBoard, const std::string&namne,int64_t saveAfterInstanceId = -1);
void GetPresetIndex(PresetIndex*pResult);
@@ -117,7 +119,20 @@ public:
void SaveCurrentPreset(const CurrentPreset &currentPreset);
bool RestoreCurrentPreset(CurrentPreset*pResult);
private:
bool pluginPresetIndexChanged = false;
void LoadPluginPresetIndex();
void SavePluginPresetIndex();
std::filesystem::path GetPluginPresetPath(const std::string &pluginUri) const;
public:
bool HasPluginPresets(const std::string&pluginUri) const;
void SavePluginPresets(const std::string&pluginUri, const PluginPresets&presets);
PluginPresets GetPluginPresets(const std::string&pluginUri) const;
PluginUiPresets GetPluginUiPresets(const std::string&pluginUri) const;
std::vector<ControlValue> GetPluginPresetValues(const std::string&pluginUri, uint64_t instanceId);
uint64_t SavePluginPreset(const std::string&pluginUri, const std::string&name, const std::map<std::string,float> & values);
void UpdatePluginPresets(const PluginUiPresets &pluginPresets);
uint64_t CopyPluginPreset(const std::string&pluginUri,uint64_t presetId);
};
+3 -3
View File
@@ -614,7 +614,6 @@ void json_reader::throw_format_error(const char*error)
} else {
for (int i = 0; i < 40; ++i)
{
if (is_.peek()) break;
int c = get();
if (c == -1) break;
if (c == '\r') {
@@ -623,11 +622,12 @@ void json_reader::throw_format_error(const char*error)
{
s << "\\n";
} else {
s << c;
s << (char)c;
}
}
}
s << "'.";
throw PiPedalException(s.str());
std::string message = s.str();
throw PiPedalException(message);
}
+53 -1
View File
@@ -278,7 +278,7 @@ public:
os << text;
}
using string_view = boost::string_view;
json_writer(std::ostream &os, bool compressed = false, bool allowNaN = true)
json_writer(std::ostream &os, bool compressed = true, bool allowNaN = true)
: os(os)
, compressed(compressed)
, allowNaN_(allowNaN)
@@ -534,6 +534,26 @@ public:
end_object();
}
template <typename U>
void write(const std::map<std::string,U> &map)
{
start_object();
bool firstTime = true;
for (const auto&v : map)
{
if (!firstTime)
{
write_raw(",");
write_raw(CRLF);
}
indent();
firstTime = false;
write_member(v.first.c_str(),v.second);
}
end_object();
}
@@ -664,6 +684,38 @@ public:
read(*pObject);
}
template <typename U>
void read(std::map<std::string,U> *pMap)
{
char c;
consume('{');
while (true)
{
c = peek();
if (c == '}')
{
c = get();
break;
}
std::string key = read_string();
consume(':');
skip_whitespace();
U u;
this->read(&u);
(*pMap)[key] = u;
skip_whitespace();
if (peek() == ',')
{
c = get();
}
}
}
template<typename T>
void read(std::unique_ptr<T> *pUniquePtr)
{
+86 -20
View File
@@ -43,6 +43,7 @@ using namespace pipedal;
#define PRESET_EXTENSION ".piPreset"
#define BANK_EXTENSION ".piBank"
#define PLUGIN_PRESETS_EXTENSION ".piPluginPresets"
sem_t signalSemaphore;
@@ -91,23 +92,32 @@ public:
{
return false;
}
if (request_uri.segment(1) == "downloadPreset")
{
std::string strInstanceId = request_uri.query("id");
if (strInstanceId != "")
return true;
}
else if (request_uri.segment(1) == "uploadPreset")
std::string segment = request_uri.segment(1);
if (segment == "uploadPluginPresets")
{
return true;
}
if (request_uri.segment(1) == "downloadBank")
if (segment == "downloadPluginPresets")
{
return true;
}
if (segment == "downloadPreset")
{
std::string strInstanceId = request_uri.query("id");
if (strInstanceId != "")
return true;
}
else if (request_uri.segment(1) == "uploadBank")
else if (segment == "uploadPreset")
{
return true;
}
if (segment == "downloadBank")
{
std::string strInstanceId = request_uri.query("id");
if (strInstanceId != "")
return true;
}
else if (segment == "uploadBank")
{
return true;
}
@@ -124,11 +134,24 @@ public:
return result;
}
void GetPluginPresets(const uri &request_uri, std::string*pName,std::string *pContent)
{
std::string pluginUri = request_uri.query("id");
auto plugin = model->GetLv2Host().GetPluginInfo(pluginUri);
*pName = plugin->name();
PluginPresets pluginPresets = model->GetPluginPresets(pluginUri);
std::stringstream s;
json_writer writer(s);
writer.write(pluginPresets);
*pContent = s.str();
}
void GetPreset(const uri &request_uri, std::string *pName, std::string *pContent)
{
std::string strInstanceId = request_uri.query("id");
int64_t instanceId = std::stol(strInstanceId);
auto pedalBoard = model->getPreset(instanceId);
auto pedalBoard = model->GetPreset(instanceId);
// a certain elegance to using same file format for banks and presets.
BankFile file;
@@ -147,7 +170,7 @@ public:
std::string strInstanceId = request_uri.query("id");
int64_t instanceId = std::stol(strInstanceId);
BankFile bank;
model->getBank(instanceId, &bank);
model->GetBank(instanceId, &bank);
std::stringstream s;
json_writer writer(s, true); // do what we can to reduce the file size.
@@ -164,7 +187,19 @@ public:
{
try
{
if (request_uri.segment(1) == "downloadPreset")
std::string segment = request_uri.segment(1);
if (segment == "downloadPluginPresets")
{
std::string name;
std::string content;
GetPluginPresets(request_uri,&name,&content);
res.set(HttpField::content_type, "application/octet-stream");
res.set(HttpField::cache_control, "no-cache");
res.setContentLength(content.length());
res.set(HttpField::content_disposition, GetContentDispositionHeader(name, PLUGIN_PRESETS_EXTENSION));
return;
}
if (segment == "downloadPreset")
{
std::string name;
std::string content;
@@ -176,7 +211,7 @@ public:
res.set(HttpField::content_disposition, GetContentDispositionHeader(name, PRESET_EXTENSION));
return;
}
if (request_uri.segment(1) == "downloadBank")
if (segment == "downloadBank")
{
std::string name;
std::string content;
@@ -211,7 +246,19 @@ public:
{
try
{
if (request_uri.segment(1) == "downloadPreset")
std::string segment = request_uri.segment(1);
if (segment == "downloadPluginPresets")
{
std::string name;
std::string content;
GetPluginPresets(request_uri,&name,&content);
res.set(HttpField::content_type, "application/octet-stream");
res.set(HttpField::cache_control, "no-cache");
res.setContentLength(content.length());
res.set(HttpField::content_disposition, GetContentDispositionHeader(name, PLUGIN_PRESETS_EXTENSION));
res.setBody(content);
} else if (segment == "downloadPreset")
{
std::string name;
std::string content;
@@ -223,7 +270,7 @@ public:
res.set(HttpField::content_disposition, GetContentDispositionHeader(name, PRESET_EXTENSION));
res.setBody(content);
}
else if (request_uri.segment(1) == "downloadBank")
else if (segment == "downloadBank")
{
std::string name;
std::string content;
@@ -260,7 +307,26 @@ public:
{
try
{
if (request_uri.segment(1) == "uploadPreset")
std::string segment = request_uri.segment(1);
if (segment == "uploadPluginPresets")
{
const std::string& presetBody = req.body();
std::stringstream s(presetBody);
json_reader reader(s);
PluginPresets presets;
reader.read(&presets);
model->UploadPluginPresets(presets);
res.set(HttpField::content_type, "application/json");
res.set(HttpField::cache_control, "no-cache");
std::stringstream sResult;
sResult << -1;
std::string result = sResult.str();
res.setContentLength(result.length());
res.setBody(result);
} else if (segment == "uploadPreset")
{
const std::string& presetBody = req.body();
std::stringstream s(presetBody);
@@ -276,7 +342,7 @@ public:
BankFile bankFile;
reader.read(&bankFile);
uint64_t instanceId = model->uploadPreset(bankFile, uploadAfter);
uint64_t instanceId = model->UploadPreset(bankFile, uploadAfter);
res.set(HttpField::content_type, "application/json");
res.set(HttpField::cache_control, "no-cache");
@@ -287,7 +353,7 @@ public:
res.setBody(result);
}
else if (request_uri.segment(1) == "uploadBank")
else if (segment == "uploadBank")
{
const std::string& presetBody = req.body();
std::istringstream s(presetBody);
@@ -303,7 +369,7 @@ public:
BankFile bankFile;
reader.read(&bankFile);
uint64_t instanceId = model->uploadBank(bankFile, uploadAfter);
uint64_t instanceId = model->UploadBank(bankFile, uploadAfter);
res.set(HttpField::content_type, "application/json");
res.set(HttpField::cache_control, "no-cache");
@@ -430,7 +496,7 @@ int main(int argc, char *argv[])
if (help || parser.Arguments().size() == 0)
{
std::cout << "pipedald - Pipedal web socket server.\n"
"Copyright (c) 2021 Robin Davies.\n"
"Copyright (c) 2022 Robin Davies.\n"
"\n";
}
}