This commit is contained in:
Robin Davies
2022-02-01 18:51:38 -05:00
parent dddd6a85d5
commit caa2aa1312
26 changed files with 1245 additions and 114 deletions
+2 -1
View File
@@ -212,6 +212,7 @@ set (REACT_BUILD_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../build/react/build/)
set (REACT_NOTICES_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../build/src/notices.txt)
set (DEBIAN_COPYRIGHT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../debian/copyright)
# generate Copyright section of settings page.
# warning: there may be multiple versions. Pick the latest.
if(EXISTS "/usr/share/doc/libboost1.74-dev")
@@ -222,7 +223,7 @@ elseif(EXISTS "/usr/share/doc/libboost1.67-dev")
set (BOOST_COPYRIGHT_DIR "libboost1.67-dev")
else()
message(ERROR "Boost libary version has changed. Please update me.")
endif()
endif()
add_custom_command(OUTPUT ${REACT_NOTICES_FILE}
+1
View File
@@ -44,6 +44,7 @@ namespace pipedal {
virtual void GatherParameter(RealtimeParameterRequest*pRequest) = 0;
virtual std::string AtomToJson(uint8_t*pAtom) = 0;
virtual std::string GetAtomObjectType(uint8_t*pData) = 0;
virtual void SetAudioOutputBuffer(int index, float*buffer) = 0;
+44 -11
View File
@@ -130,10 +130,12 @@ private:
RingBuffer<true, false> inputRingBuffer;
RingBuffer<false, true> outputRingBuffer;
RingBufferReader<true, false> realtimeReader;
RingBufferWriter<false, true> realtimeWriter;
RingBufferReader<false, true> hostReader;
RingBufferWriter<true, false> hostWriter;
RingBufferWriter<true,false> x;
RealtimeRingBufferReader realtimeReader;
RealtimeRingBufferWriter realtimeWriter;
HostRingBufferReader hostReader;
HostRingBufferWriter hostWriter;
JackChannelSelection channelSelection;
bool active = false;
@@ -577,7 +579,7 @@ private:
pedalBoard->ResetAtomBuffers();
pedalBoard->ProcessParameterRequests(pParameterRequests);
processed = pedalBoard->Run(inputBuffers, outputBuffers, (uint32_t)nframes);
processed = pedalBoard->Run(inputBuffers, outputBuffers, (uint32_t)nframes,&realtimeWriter);
if (processed)
{
if (this->realtimeVuBuffers != nullptr)
@@ -723,6 +725,8 @@ public:
Lv2Log::error("Audio processing terminated unexpectedly.");
realtimeWriter.AudioStopped();
}
std::vector<uint8_t> atomBuffer;
bool terminateThread;
void ThreadProc()
{
@@ -871,6 +875,26 @@ public:
this->pNotifyCallbacks->OnNotifyVusSubscription(*updates);
}
this->hostWriter.AckVuUpdate(); // please sir, can I have some more?
} else if (command == RingBufferCommand::AtomOutput)
{
uint64_t instanceId;
hostReader.read(&instanceId);
size_t extraBytes;
hostReader.read(&extraBytes);
if (atomBuffer.size() < extraBytes)
{
atomBuffer.resize(extraBytes);
}
hostReader.read(extraBytes,&(atomBuffer[0]));
IEffect *pEffect = currentPedalBoard->GetEffect(instanceId);
if (pEffect != nullptr &&this->pNotifyCallbacks && listenForAtomOutput)
{
std::string atomType = pEffect->GetAtomObjectType(&atomBuffer[0]);
auto json = pEffect->AtomToJson(&(atomBuffer[0]));
this->pNotifyCallbacks->OnNotifyAtomOutput(instanceId,atomType,json);
}
}
else if (command == RingBufferCommand::FreeVuSubscriptions)
{
@@ -1175,7 +1199,7 @@ public:
}
}
virtual void SetBypass(long instanceId, bool enabled)
virtual void SetBypass(uint64_t instanceId, bool enabled)
{
std::lock_guard guard(mutex);
if (active && this->currentPedalBoard)
@@ -1189,7 +1213,7 @@ public:
}
}
virtual void SetPluginPreset(long instanceId, const std::vector<ControlValue> &values)
virtual void SetPluginPreset(uint64_t instanceId, const std::vector<ControlValue> &values)
{
std::lock_guard guard(mutex);
if (active && this->currentPedalBoard)
@@ -1210,7 +1234,7 @@ public:
}
}
void SetControlValue(long instanceId, const std::string &symbol, float value)
void SetControlValue(uint64_t instanceId, const std::string &symbol, float value)
{
std::lock_guard guard(mutex);
if (active && this->currentPedalBoard)
@@ -1273,6 +1297,7 @@ public:
result.subscriptionHandle = subscription.subscriptionHandle;
result.instanceIndex = this->currentPedalBoard->GetIndexOfInstanceId(subscription.instanceid);
IEffect *pEffect = this->currentPedalBoard->GetEffect(subscription.instanceid);
result.portIndex = pEffect->GetControlIndex(subscription.key);
result.sampleRate = (int)(this->GetSampleRate() * subscription.updateInterval);
result.samplesToNextCallback = result.sampleRate;
@@ -1296,8 +1321,11 @@ public:
for (size_t i = 0; i < subscriptions.size(); ++i)
{
pSubscriptions->subscriptions.push_back(
MakeRealtimeSubscription(subscriptions[i]));
if (this->currentPedalBoard->GetEffect(subscriptions[i].instanceid) != nullptr)
{
pSubscriptions->subscriptions.push_back(
MakeRealtimeSubscription(subscriptions[i]));
}
}
this->hostWriter.SetMonitorPortSubscriptions(pSubscriptions);
}
@@ -1453,12 +1481,17 @@ public:
return result;
}
volatile bool listenForMidiEvent;
volatile bool listenForMidiEvent = false;
volatile bool listenForAtomOutput = false;
virtual void SetListenForMidiEvent(bool listen)
{
this->listenForMidiEvent = listen;
}
virtual void SetListenForAtomOutput(bool listen)
{
this->listenForAtomOutput = listen;
}
};
int JackHostImpl::jackInstanceId = 0;
+7 -4
View File
@@ -23,8 +23,8 @@
#include "Lv2PedalBoard.hpp"
#include "VuUpdate.hpp"
#include "RingBuffer.hpp"
#include "json.hpp"
#include "JackHost.hpp"
#include "JackServerSettings.hpp"
#include <functional>
#include "PiPedalAlsa.hpp"
@@ -97,6 +97,7 @@ public:
virtual void OnNotifyMonitorPort(const MonitorPortUpdate &update) = 0;
virtual void OnNotifyMidiValueChanged(int64_t instanceId, int portIndex, float value) = 0;
virtual void OnNotifyMidiListen(bool isNote, uint8_t noteOrControl) = 0;
virtual void OnNotifyAtomOutput(uint64_t instanceId, const std::string&atomType,const std::string&atomJson) = 0;
};
@@ -119,6 +120,7 @@ public:
};
class IHost;
class JackHost {
@@ -134,6 +136,7 @@ public:
virtual void SetNotificationCallbacks(IJackHostCallbacks *pNotifyCallbacks) = 0;
virtual void SetListenForMidiEvent(bool listen) = 0;
virtual void SetListenForAtomOutput(bool listen) = 0;
virtual void Open(const JackChannelSelection & channelSelection) = 0;
@@ -145,9 +148,9 @@ public:
virtual void SetPedalBoard(const std::shared_ptr<Lv2PedalBoard> &pedalBoard) = 0;
virtual void SetControlValue(long instanceId,const std::string&symbol, float value) = 0;
virtual void SetPluginPreset(long isntanceId, const std::vector<ControlValue> & values) = 0;
virtual void SetBypass(long instanceId, bool enabled) = 0;
virtual void SetControlValue(uint64_t instanceId,const std::string&symbol, float value) = 0;
virtual void SetPluginPreset(uint64_t instanceId, const std::vector<ControlValue> & values) = 0;
virtual void SetBypass(uint64_t instanceId, bool enabled) = 0;
virtual bool IsOpen() const = 0;
+80 -11
View File
@@ -38,6 +38,8 @@
#include "lv2/units.lv2/units.h"
#include "lv2/atom.lv2/util.h"
#include "JackHost.hpp"
#include <exception>
#include "RingBufferReader.hpp"
using namespace pipedal;
@@ -93,6 +95,10 @@ Lv2Effect::Lv2Effect(
LilvInstance *pInstance = lilv_plugin_instantiate(pPlugin, pHost->GetSampleRate(), myFeatures);
this->pInstance = pInstance;
if (this->pInstance == nullptr)
{
throw PiPedalException("Failed to create plugin.");
}
if (info_->hasExtension(LV2_WORKER__interface))
{
@@ -329,7 +335,7 @@ static inline void CopyBuffer(float *input, float *output, uint32_t frames)
}
}
void Lv2Effect::Run(uint32_t samples)
void Lv2Effect::Run(uint32_t samples,uint64_t instanceId, RealtimeRingBufferWriter *realtimeRingBufferWriter)
{
// close off the atom input frame.
if (this->inputAtomBuffers.size() != 0)
@@ -425,7 +431,9 @@ void Lv2Effect::Run(uint32_t samples)
this->currentBypassDx = currentBypassDx;
this->bypassSamplesRemaining = bypassSamplesRemaining;
}
}
RelayOutputMessages(instanceId,realtimeRingBufferWriter);
}
LV2_Worker_Status Lv2Effect::worker_schedule_fn(LV2_Worker_Schedule_Handle handle,
@@ -510,6 +518,30 @@ void Lv2Effect::RequestParameter(LV2_URID uridUri)
lv2_atom_forge_pop(&inputForgeRt, &objectFrame);
}
void Lv2Effect::RelayOutputMessages(uint64_t instanceId,RealtimeRingBufferWriter *realtimeRingBufferWriter)
{
LV2_Atom_Sequence*controlOutput = (LV2_Atom_Sequence*)GetAtomOutputBuffer();
if (controlOutput == nullptr)
{
return;
}
LV2_ATOM_SEQUENCE_FOREACH(controlOutput, ev)
{
// frame_offset = ev->time.frames; // not really interested.
if (lv2_atom_forge_is_object_type(&this->outputForgeRt, ev->body.type))
{
const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;
if (obj->body.otype != uris.patch_Set) // patch_Set is handled elsewhere.
{
realtimeRingBufferWriter->AtomOutput(instanceId,obj->atom.size +sizeof(obj->atom),(uint8_t*)obj);
}
}
}
}
void Lv2Effect::GatherParameter(RealtimeParameterRequest *pRequest)
{
LV2_Atom_Sequence*controlInput = (LV2_Atom_Sequence*)GetAtomOutputBuffer();
@@ -544,12 +576,13 @@ void Lv2Effect::GatherParameter(RealtimeParameterRequest *pRequest)
LV2_URID key = ((const LV2_Atom_URID *)property)->body;
if (key == pRequest->uridUri)
{
if (value->size > sizeof(pRequest->response))
int atom_size = value->size + sizeof(LV2_Atom);
if (atom_size > sizeof(pRequest->response))
{
pRequest->errorMessage = "Response is too large.";
} else {
pRequest->responseLength = value->size;
memcpy(pRequest->response,value,value->size);
pRequest->responseLength = atom_size;
memcpy(pRequest->response,value,atom_size);
}
break;
}
@@ -559,6 +592,16 @@ void Lv2Effect::GatherParameter(RealtimeParameterRequest *pRequest)
}
}
std::string Lv2Effect::GetAtomObjectType(uint8_t*pData)
{
LV2_Atom_Object *pAtom = (LV2_Atom_Object*)pData;
if (pAtom->atom.type != uris.atom_Object)
{
throw std::invalid_argument("Not an Lv2 Object");
}
return pHost->Lv2UriudToString(pAtom->body.otype);
}
std::string Lv2Effect::AtomToJson(uint8_t*pData)
{
std::stringstream s;
@@ -569,6 +612,18 @@ std::string Lv2Effect::AtomToJson(uint8_t*pData)
return s.str();
}
static std::string UriToFieldName(const std::string&uri){
int pos;
for (pos = uri.length(); pos >= 0; --pos)
{
char c = uri[pos];
if (c == '#' || c == '/' || c == ':')
{
break;
}
}
return uri.substr(pos+1);
}
void Lv2Effect::WriteAtom(json_writer &writer, LV2_Atom*pAtom)
{
if (pAtom->type == uris.atom_Blank)
@@ -612,7 +667,7 @@ void Lv2Effect::WriteAtom(json_writer &writer, LV2_Atom*pAtom)
LV2_Atom_Vector *pVector = (LV2_Atom_Vector*)pAtom;
writer.start_array();
{
size_t n = (pAtom->size-sizeof(LV2_Atom_Vector))/pVector->body.child_size;
size_t n = (pAtom->size-sizeof(pVector->body))/pVector->body.child_size;
char *pItems = ((char*)pAtom) + sizeof(LV2_Atom_Vector);
if (pVector->body.child_type == uris.atom_float)
{
@@ -662,22 +717,36 @@ void Lv2Effect::WriteAtom(json_writer &writer, LV2_Atom*pAtom)
writer.start_object();
const LV2_Atom_Object *obj = (const LV2_Atom_Object *)pAtom;
std::string id = pHost->Lv2UriudToString(obj->body.id);
std::string type = pHost->Lv2UriudToString(obj->body.otype);
writer.write_json_member("id",id.c_str());
writer.write_json_member("lv2Type",type.c_str());
bool firstMember = true;
if (obj->body.id != 0)
{
std::string id = pHost->Lv2UriudToString(obj->body.id);
writer.write_member("id",id.c_str());
firstMember = false;
}
if (obj->body.otype != 0)
{
std::string type = pHost->Lv2UriudToString(obj->body.otype);
writer.write_member("lv2Type",type.c_str());
if (!firstMember)
{
writer.write_raw(",");
}
firstMember = false;
}
LV2_ATOM_OBJECT_FOREACH (obj, prop) {
if (!firstMember) {
writer.write_raw(",");
}
firstMember = false;
std::string key = pHost->Lv2UriudToString(prop->key);
key = UriToFieldName(key);
writer.write(key);
writer.write_raw(": ");
LV2_Atom *value = &(prop->value);
WriteAtom(writer,value);
}
writer.end_object();
+9 -2
View File
@@ -33,9 +33,12 @@
#include "lv2/lv2plug.in/ns/extensions/units/units.h"
#include "lv2/atom.lv2/forge.h"
namespace pipedal
{
class RealtimeRingBufferWriter;
class Lv2Effect : public IEffect
{
private:
@@ -144,7 +147,7 @@ namespace pipedal
Uris uris;
long instanceId;
uint64_t instanceId;
BufferPool bufferPool;
static LV2_Worker_Status worker_schedule_fn(LV2_Worker_Schedule_Handle handle,
@@ -167,6 +170,8 @@ namespace pipedal
virtual void RequestParameter(LV2_URID uridUri);
virtual void GatherParameter(RealtimeParameterRequest*pRequest);
virtual void RelayOutputMessages(uint64_t instanceId,RealtimeRingBufferWriter *realtimeRingBufferWriter);
virtual uint8_t*GetAtomInputBuffer() {
if (this->inputAtomBuffers.size() == 0) return nullptr;
return (uint8_t*)this->inputAtomBuffers[0];
@@ -178,6 +183,8 @@ namespace pipedal
}
virtual std::string AtomToJson(uint8_t*pAtom);
virtual std::string GetAtomObjectType(uint8_t*pData);
@@ -261,7 +268,7 @@ namespace pipedal
}
void Activate();
void Run(uint32_t samples);
void Run(uint32_t samples, uint64_t instanceId,RealtimeRingBufferWriter *realtimeRingBufferWriter);
void Deactivate();
};
+6 -6
View File
@@ -44,7 +44,7 @@ std::vector<float *> Lv2PedalBoard::AllocateAudioBuffers(int nChannels)
return result;
}
int Lv2PedalBoard::GetControlIndex(long instanceId, const std::string &symbol)
int Lv2PedalBoard::GetControlIndex(uint64_t instanceId, const std::string &symbol)
{
for (int i = 0; i < realtimeEffects.size(); ++i)
{
@@ -109,7 +109,7 @@ std::vector<float *> Lv2PedalBoard::PrepareItems(
{
pEffect = pLv2Effect;
long instanceId = pEffect->GetInstanceId();
uint64_t instanceId = pEffect->GetInstanceId();
if (inputBuffers.size() == 1)
{
@@ -142,9 +142,9 @@ std::vector<float *> Lv2PedalBoard::PrepareItems(
}
this->processActions.push_back(
[pLv2Effect](uint32_t frames)
[pLv2Effect,this,instanceId](uint32_t frames)
{
pLv2Effect->Run(frames);
pLv2Effect->Run(frames,instanceId,this->ringBufferWriter);
});
}
}
@@ -356,9 +356,9 @@ static void Copy(float *input, float *output, uint32_t samples)
output[i] = input[i];
}
}
bool Lv2PedalBoard::Run(float **inputBuffers, float **outputBuffers, uint32_t samples)
bool Lv2PedalBoard::Run(float **inputBuffers, float **outputBuffers, uint32_t samples, RealtimeRingBufferWriter*ringBufferWriter)
{
this->ringBufferWriter = ringBufferWriter;
for (int i = 0; i < this->pedalBoardInputBuffers.size(); ++i)
{
if (inputBuffers[i] == nullptr)
+7 -4
View File
@@ -32,6 +32,7 @@ namespace pipedal {
class RealtimeVuBuffers;
class RealtimeParameterRequest;
class RealtimeRingBufferWriter;
class Lv2PedalBoard {
IHost *pHost = nullptr;
@@ -54,6 +55,8 @@ class Lv2PedalBoard {
float *CreateNewAudioBuffer();
RealtimeRingBufferWriter *ringBufferWriter;
enum class MappingType {
Linear,
Circular,
@@ -94,14 +97,14 @@ public:
void Prepare(IHost *pHost,const PedalBoard&pedalBoard);
int GetIndexOfInstanceId(long instanceId) {
int GetIndexOfInstanceId(uint64_t instanceId) {
for (int i = 0; i < this->realtimeEffects.size(); ++i)
{
if (this->realtimeEffects[i]->GetInstanceId() == instanceId) return i;
}
return -1;
}
IEffect*GetEffect(long instanceId) {
IEffect*GetEffect(uint64_t instanceId) {
for (int i = 0; i < realtimeEffects.size(); ++i) {
if (realtimeEffects[i]->GetInstanceId() == instanceId)
{
@@ -112,7 +115,7 @@ public:
}
void Activate();
void Deactivate();
bool Run(float**inputBuffers, float**outputBuffers,uint32_t samples);
bool Run(float**inputBuffers, float**outputBuffers,uint32_t samples, RealtimeRingBufferWriter*realtimeWriter);
void ResetAtomBuffers();
@@ -126,7 +129,7 @@ public:
int GetControlIndex(long instanceId,const std::string&symbol);
int GetControlIndex(uint64_t instanceId,const std::string&symbol);
void SetControlValue(int effectIndex, int portIndex, float value);
void SetBypass(int effectIndex,bool enabled);
+2 -2
View File
@@ -96,7 +96,7 @@ bool PedalBoard::SetControlValue(long pedalItemId, const std::string &symbol, fl
PedalBoardItem PedalBoard::MakeEmptyItem()
{
long instanceId = NextInstanceId();
uint64_t instanceId = NextInstanceId();
PedalBoardItem result;
result.instanceId(instanceId);
@@ -109,7 +109,7 @@ PedalBoardItem PedalBoard::MakeEmptyItem()
PedalBoardItem PedalBoard::MakeSplit()
{
long instanceId = NextInstanceId();
uint64_t instanceId = NextInstanceId();
PedalBoardItem result;
result.instanceId(instanceId);
+2 -2
View File
@@ -122,8 +122,8 @@ public:
class PedalBoard {
std::string name_;
std::vector<PedalBoardItem> items_;
long nextInstanceId_ = 0;
long NextInstanceId() { return ++nextInstanceId_; }
uint64_t nextInstanceId_ = 0;
uint64_t NextInstanceId() { return ++nextInstanceId_; }
public:
bool SetControlValue(long pedalItemId, const std::string &symbol, float value);
+114 -40
View File
@@ -53,7 +53,7 @@ PiPedalModel::PiPedalModel()
void PiPedalModel::Close()
{
std::lock_guard lock(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()];
@@ -186,13 +186,13 @@ IPiPedalModelSubscriber *PiPedalModel::GetNotificationSubscriber(int64_t clientI
void PiPedalModel::AddNotificationSubscription(IPiPedalModelSubscriber *pSubscriber)
{
std::lock_guard lock(this->mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
this->subscribers.push_back(pSubscriber);
}
void PiPedalModel::RemoveNotificationSubsription(IPiPedalModelSubscriber *pSubscriber)
{
{
std::lock_guard lock(this->mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
for (auto it = this->subscribers.begin(); it != this->subscribers.end(); ++it)
{
@@ -205,6 +205,7 @@ void PiPedalModel::RemoveNotificationSubsription(IPiPedalModelSubscriber *pSubsc
int64_t clientId = pSubscriber->GetClientId();
this->deleteMidiListeners(clientId);
this->deleteAtomOutputListeners(clientId);
for (int i = 0; i < this->outstandingParameterRequests.size(); ++i)
{
@@ -226,7 +227,7 @@ void PiPedalModel::previewControl(int64_t clientId, int64_t pedalItemId, const s
void PiPedalModel::setControl(int64_t clientId, int64_t pedalItemId, const std::string &symbol, float value)
{
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
previewControl(clientId, pedalItemId, symbol, value);
this->pedalBoard.SetControlValue(pedalItemId, symbol, value);
{
@@ -309,7 +310,7 @@ void PiPedalModel::firePedalBoardChanged(int64_t clientId)
void PiPedalModel::setPedalBoard(int64_t clientId, PedalBoard &pedalBoard)
{
{
std::lock_guard guard(this->mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
this->pedalBoard = pedalBoard;
updateDefaults(&this->pedalBoard);
@@ -345,7 +346,7 @@ void PiPedalModel::setPedalBoardItemEnable(int64_t clientId, int64_t pedalItemId
void PiPedalModel::getPresets(PresetIndex *pResult)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
this->storage.GetPresetIndex(pResult);
pResult->presetChanged(this->hasPresetChanged);
@@ -353,12 +354,12 @@ void PiPedalModel::getPresets(PresetIndex *pResult)
PedalBoard PiPedalModel::getPreset(int64_t instanceId)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
return this->storage.GetPreset(instanceId);
}
void PiPedalModel::getBank(int64_t instanceId, BankFile *pResult)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
this->storage.GetBankFile(instanceId, pResult);
}
@@ -501,7 +502,7 @@ int64_t PiPedalModel::deletePreset(int64_t clientId, int64_t instanceId)
}
bool PiPedalModel::renamePreset(int64_t clientId, int64_t instanceId, const std::string &name)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
if (storage.RenamePreset(instanceId, name))
{
this->firePresetsChanged(clientId);
@@ -515,7 +516,7 @@ bool PiPedalModel::renamePreset(int64_t clientId, int64_t instanceId, const std:
void PiPedalModel::setWifiConfigSettings(const WifiConfigSettings &wifiConfigSettings)
{
std::lock_guard lock(this->mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
ShutdownClient::SetWifiConfig(wifiConfigSettings);
@@ -540,19 +541,19 @@ void PiPedalModel::setWifiConfigSettings(const WifiConfigSettings &wifiConfigSet
}
WifiConfigSettings PiPedalModel::getWifiConfigSettings()
{
std::lock_guard lock(this->mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
return this->storage.GetWifiConfigSettings();
}
JackConfiguration PiPedalModel::getJackConfiguration()
{
std::lock_guard lock(this->mutex); // copy atomically.
std::lock_guard<std::recursive_mutex> guard(mutex); // copy atomically.
return this->jackConfiguration;
}
void PiPedalModel::setJackChannelSelection(int64_t clientId, const JackChannelSelection &channelSelection)
{
std::lock_guard lock(this->mutex); // copy atomically.
std::lock_guard<std::recursive_mutex> guard(mutex); // copy atomically.
this->storage.SetJackChannelSelection(channelSelection);
this->fireChannelSelectionChanged(clientId);
@@ -595,7 +596,7 @@ void PiPedalModel::fireChannelSelectionChanged(int64_t clientId)
JackChannelSelection PiPedalModel::getJackChannelSelection()
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
JackChannelSelection t = this->storage.GetJackChannelSelection(this->jackConfiguration);
if (this->jackConfiguration.isValid())
{
@@ -606,7 +607,7 @@ JackChannelSelection PiPedalModel::getJackChannelSelection()
int64_t PiPedalModel::addVuSubscription(int64_t instanceId)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
int64_t subscriptionId = ++nextSubscriptionId;
activeVuSubscriptions.push_back(VuSubscription{subscriptionId, instanceId});
@@ -616,7 +617,7 @@ int64_t PiPedalModel::addVuSubscription(int64_t instanceId)
}
void PiPedalModel::removeVuSubscription(int64_t subscriptionHandle)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
for (auto i = activeVuSubscriptions.begin(); i != activeVuSubscriptions.end(); ++i)
{
if ((*i).subscriptionHandle == subscriptionHandle)
@@ -630,7 +631,7 @@ void PiPedalModel::removeVuSubscription(int64_t subscriptionHandle)
void PiPedalModel::OnNotifyMidiValueChanged(int64_t instanceId, int portIndex, float value)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
PedalBoardItem *item = this->pedalBoard.GetItem(instanceId);
if (item)
{
@@ -702,7 +703,7 @@ void PiPedalModel::OnNotifyMidiValueChanged(int64_t instanceId, int portIndex, f
}
void PiPedalModel::OnNotifyVusSubscription(const std::vector<VuUpdate> &updates)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
for (size_t i = 0; i < updates.size(); ++i)
{
// take a snapshot incase a client unsusbscribes in the notification handler (in which case the mutex won't protect us)
@@ -743,7 +744,7 @@ void PiPedalModel::updateRealtimeMonitorPortSubscriptions()
int64_t PiPedalModel::monitorPort(int64_t instanceId, const std::string &key, float updateInterval, PortMonitorCallback onUpdate)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
int64_t subscriptionId = ++nextSubscriptionId;
activeMonitorPortSubscriptions.push_back(
MonitorPortSubscription{subscriptionId, instanceId, key, updateInterval, onUpdate});
@@ -754,7 +755,7 @@ int64_t PiPedalModel::monitorPort(int64_t instanceId, const std::string &key, fl
}
void PiPedalModel::unmonitorPort(int64_t subscriptionHandle)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
for (auto i = activeMonitorPortSubscriptions.begin(); i != activeMonitorPortSubscriptions.end(); ++i)
{
@@ -766,9 +767,11 @@ void PiPedalModel::unmonitorPort(int64_t subscriptionHandle)
}
}
}
void PiPedalModel::OnNotifyMonitorPort(const MonitorPortUpdate &update)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
for (auto i = activeMonitorPortSubscriptions.begin(); i != activeMonitorPortSubscriptions.end(); ++i)
{
@@ -793,7 +796,7 @@ void PiPedalModel::getLv2Parameter(
[this](RealtimeParameterRequest *pParameter)
{
{
std::lock_guard guard(this->mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
bool cancelled = true;
for (auto i = this->outstandingParameterRequests.begin();
i != this->outstandingParameterRequests.end(); ++i)
@@ -829,27 +832,27 @@ void PiPedalModel::getLv2Parameter(
onRequestComplete,
clientId, instanceId, urid, onSuccess, onError);
std::lock_guard guard(constMutex(mutex));
std::lock_guard<std::recursive_mutex> guard(mutex);
outstandingParameterRequests.push_back(request);
this->jackHost->getRealtimeParameter(request);
}
BankIndex PiPedalModel::getBankIndex() const
{
std::lock_guard guard(constMutex(mutex));
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)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
storage.RenameBank(bankId, newName);
fireBanksChanged(clientId);
}
int64_t PiPedalModel::saveBankAs(int64_t clientId, int64_t bankId, const std::string &newName)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
int64_t newId = storage.SaveBankAs(bankId, newName);
fireBanksChanged(clientId);
return newId;
@@ -857,7 +860,7 @@ int64_t PiPedalModel::saveBankAs(int64_t clientId, int64_t bankId, const std::st
void PiPedalModel::openBank(int64_t clientId, int64_t bankId)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
storage.LoadBank(bankId);
fireBanksChanged(clientId);
@@ -872,13 +875,13 @@ void PiPedalModel::openBank(int64_t clientId, int64_t bankId)
JackServerSettings PiPedalModel::GetJackServerSettings()
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
return this->jackServerSettings;
}
void PiPedalModel::SetJackServerSettings(const JackServerSettings &jackServerSettings)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
if (!ShutdownClient::CanUseShutdownClient())
{
@@ -916,7 +919,7 @@ void PiPedalModel::SetJackServerSettings(const JackServerSettings &jackServerSet
jackServerSettings,
[this](bool success, const std::string &errorMessage)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
if (!success)
{
std::stringstream s;
@@ -998,14 +1001,14 @@ void PiPedalModel::updateDefaults(PedalBoard *pedalBoard)
std::vector<Lv2PluginPreset> PiPedalModel::GetPluginPresets(std::string pluginUri)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
return lv2Host.GetPluginPresets(pluginUri);
}
void PiPedalModel::LoadPluginPreset(int64_t instanceId, const std::string &presetUri)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
PedalBoardItem *pedalBoardItem = this->pedalBoard.GetItem(instanceId);
if (pedalBoardItem != nullptr)
@@ -1033,9 +1036,23 @@ void PiPedalModel::LoadPluginPreset(int64_t instanceId, const std::string &prese
}
}
void PiPedalModel::deleteAtomOutputListeners(int64_t clientId)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
for (size_t i = 0; i < atomOutputListeners.size(); ++i)
{
if (atomOutputListeners[i].clientId == clientId)
{
atomOutputListeners.erase(atomOutputListeners.begin() + i);
--i;
}
}
jackHost->SetListenForAtomOutput(atomOutputListeners.size() != 0);
}
void PiPedalModel::deleteMidiListeners(int64_t clientId)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
for (size_t i = 0; i < midiEventListeners.size(); ++i)
{
if (midiEventListeners[i].clientId == clientId)
@@ -1047,9 +1064,34 @@ void PiPedalModel::deleteMidiListeners(int64_t clientId)
jackHost->SetListenForMidiEvent(midiEventListeners.size() != 0);
}
void PiPedalModel::OnNotifyAtomOutput(uint64_t instanceId, const std::string&atomType,const std::string&atomJson)
{
std::lock_guard<std::recursive_mutex> guard(mutex);
for (int i = 0; i < atomOutputListeners.size(); ++i)
{
auto &listener = atomOutputListeners[i];
if (listener.instanceId == instanceId)
{
auto subscriber = this->GetNotificationSubscriber(listener.clientId);
if (subscriber)
{
subscriber->OnNotifyAtomOutput(listener.clientHandle,instanceId,atomType,atomJson);
} else {
atomOutputListeners.erase(atomOutputListeners.begin() + i);
--i;
}
}
}
jackHost->SetListenForAtomOutput(atomOutputListeners.size() != 0);
}
void PiPedalModel::OnNotifyMidiListen(bool isNote, uint8_t noteOrControl)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
for (int i = 0; i < midiEventListeners.size(); ++i)
{
@@ -1060,9 +1102,10 @@ void PiPedalModel::OnNotifyMidiListen(bool isNote, uint8_t noteOrControl)
if (subscriber)
{
subscriber->OnNotifyMidiListener(listener.clientHandle, isNote, noteOrControl);
} else {
midiEventListeners.erase(midiEventListeners.begin() + i);
--i;
}
midiEventListeners.erase(midiEventListeners.begin() + i);
--i;
}
}
jackHost->SetListenForMidiEvent(midiEventListeners.size() != 0);
@@ -1070,17 +1113,48 @@ void PiPedalModel::OnNotifyMidiListen(bool isNote, uint8_t noteOrControl)
void PiPedalModel::listenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControlsOnly)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
MidiListener listener{clientId, clientHandle, listenForControlsOnly};
midiEventListeners.push_back(listener);
jackHost->SetListenForMidiEvent(true);
}
void PiPedalModel::cancelListenForMidiEvent(int64_t clientId, int64_t clientHandled)
void PiPedalModel::listenForAtomOutputs(int64_t clientId, int64_t clientHandle, uint64_t instanceId)
{
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
AtomOutputListener listener{clientId, clientHandle, instanceId};
atomOutputListeners.push_back(listener);
jackHost->SetListenForAtomOutput(true);
}
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)
{
midiEventListeners.erase(midiEventListeners.begin() + i);
const auto& listener = midiEventListeners[i];
if (listener.clientId == clientId && listener.clientHandle == clientHandle)
{
midiEventListeners.erase(midiEventListeners.begin() + i);
break;
}
}
if (midiEventListeners.size() == 0)
{
jackHost->SetListenForMidiEvent(false);
}
}
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)
{
const auto&listener = atomOutputListeners[i];
if (listener.clientId == clientId && listener.clientHandle == clientHandle)
{
atomOutputListeners.erase(atomOutputListeners.begin() + i);
break;
}
}
if (midiEventListeners.size() == 0)
{
+18 -4
View File
@@ -54,6 +54,7 @@ public:
virtual void OnLoadPluginPreset(int64_t instanceId,const std::vector<ControlValue>&controlValues) = 0;
virtual void OnMidiValueChanged(int64_t instanceId, const std::string&symbol, float value) = 0;
virtual void OnNotifyMidiListener(int64_t clientHandle, bool isNote, uint8_t noteOrControl) = 0;
virtual void OnNotifyAtomOutput(int64_t clientModel,uint64_t instanceId,const std::string&atomType, const std::string&atomJson) = 0;
virtual void OnWifiConfigSettingsChanged(const WifiConfigSettings&wifiConfigSettings) = 0;
virtual void Close() = 0;
};
@@ -61,6 +62,7 @@ public:
class PiPedalModel: private IJackHostCallbacks {
private:
PiPedalAlsaDevices alsaDevices;
std::recursive_mutex mutex;
class MidiListener {
@@ -69,13 +71,20 @@ private:
int64_t clientHandle;
bool listenForControlsOnly;
};
class AtomOutputListener {
public:
int64_t clientId;
int64_t clientHandle;
uint64_t instanceId;
};
void deleteMidiListeners(int64_t clientId);
void deleteAtomOutputListeners(int64_t clientId);
std::vector<MidiListener> midiEventListeners;
std::vector<AtomOutputListener> atomOutputListeners;
JackServerSettings jackServerSettings;
Lv2Host lv2Host;
std::recursive_mutex mutex;
PedalBoard pedalBoard;
Storage storage;
bool hasPresetChanged = false;
@@ -120,7 +129,7 @@ private: // IJackHostCallbacks
virtual void OnNotifyMonitorPort(const MonitorPortUpdate &update);
virtual void OnNotifyMidiValueChanged(int64_t instanceId, int portIndex, float value);
virtual void OnNotifyMidiListen(bool isNote, uint8_t noteOrControl);
virtual void OnNotifyAtomOutput(uint64_t instanceId, const std::string&atomType,const std::string&atomJson);
public:
PiPedalModel();
@@ -132,7 +141,7 @@ public:
const Lv2Host& getPlugins() const { return lv2Host; }
PedalBoard getCurrentPedalBoardCopy() {
std::lock_guard guard(mutex);
std::lock_guard<std::recursive_mutex> guard(mutex);
return pedalBoard;
}
std::vector<Lv2PluginPreset> GetPluginPresets(std::string pluginUri);
@@ -204,8 +213,13 @@ public:
void SetJackServerSettings(const JackServerSettings& jackServerSettings);
void listenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControlsOnly);
void cancelListenForMidiEvent(int64_t clientId, int64_t clientHandled);
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);
std::vector<AlsaDeviceInfo> GetAlsaDevices();
};
} // namespace pipedal.
+124 -14
View File
@@ -53,6 +53,21 @@ JSON_MAP_REFERENCE(NotifyMidiListenerBody, isNote)
JSON_MAP_REFERENCE(NotifyMidiListenerBody, noteOrControl)
JSON_MAP_END()
class NotifyAtomOutputBody {
public:
int64_t clientHandle_;
uint64_t instanceId_;
std::string atomJson_;
DECLARE_JSON_MAP(NotifyAtomOutputBody);
};
JSON_MAP_BEGIN(NotifyAtomOutputBody)
JSON_MAP_REFERENCE(NotifyAtomOutputBody, clientHandle)
JSON_MAP_REFERENCE(NotifyAtomOutputBody, instanceId)
JSON_MAP_REFERENCE(NotifyAtomOutputBody, atomJson)
JSON_MAP_END()
class ListenForMidiEventBody {
public:
bool listenForControlsOnly_;
@@ -65,6 +80,18 @@ JSON_MAP_REFERENCE(ListenForMidiEventBody, listenForControlsOnly)
JSON_MAP_REFERENCE(ListenForMidiEventBody, handle)
JSON_MAP_END()
class ListenForAtomOutputBody {
public:
uint64_t instanceId_;
int64_t handle_;
DECLARE_JSON_MAP(ListenForAtomOutputBody);
};
JSON_MAP_BEGIN(ListenForAtomOutputBody)
JSON_MAP_REFERENCE(ListenForAtomOutputBody, instanceId)
JSON_MAP_REFERENCE(ListenForAtomOutputBody, handle)
JSON_MAP_END()
class OnLoadPluginPresetBody {
public:
@@ -390,7 +417,7 @@ private:
writer.end_array();
{
std::lock_guard guard(this->writeMutex);
std::lock_guard<std::recursive_mutex> guard(this->writeMutex);
this->send(s.str());
}
}
@@ -421,7 +448,7 @@ private:
}
writer.end_array();
{
std::lock_guard guard(this->writeMutex);
std::lock_guard<std::recursive_mutex> guard(this->writeMutex);
this->send(s.str());
}
}
@@ -448,7 +475,7 @@ private:
writer.end_array();
{
std::lock_guard guard(this->writeMutex);
std::lock_guard<std::recursive_mutex> guard(this->writeMutex);
this->send(s.str());
}
}
@@ -526,7 +553,7 @@ private:
{
}
};
std::mutex requestMutex;
std::recursive_mutex requestMutex;
std::vector<IRequestReservation *> requestReservations;
std::atomic<int> nextRequestId{1};
@@ -543,7 +570,7 @@ public:
onSuccess,
onError);
{
std::lock_guard lock(requestMutex);
std::lock_guard<std::recursive_mutex> lock(requestMutex);
requestReservations.push_back(reservation);
}
std::stringstream s(ios_base::out);
@@ -563,7 +590,7 @@ public:
}
writer.end_array();
{
std::lock_guard guard(this->writeMutex);
std::lock_guard<std::recursive_mutex> guard(this->writeMutex);
this->send(s.str());
}
}
@@ -595,7 +622,7 @@ public:
bool waitingForPortMonitorAck(uint64_t subscriptionId)
{
{
std::lock_guard guard(subscriptionMutex);
std::lock_guard<std::recursive_mutex> guard(subscriptionMutex);
for (int i = 0; i < this->activePortMonitors.size(); ++i)
{
auto &portMonitor = activePortMonitors[i];
@@ -613,7 +640,7 @@ public:
void portMonitorAck(uint64_t subscriptionId)
{
{
std::lock_guard guard(subscriptionMutex);
std::lock_guard<std::recursive_mutex> guard(subscriptionMutex);
for (int i = 0; i < this->activePortMonitors.size(); ++i)
{
auto &portMonitor = activePortMonitors[i];
@@ -632,7 +659,7 @@ public:
{
IRequestReservation *reservation = nullptr;
{
std::lock_guard guard(this->requestMutex);
std::lock_guard<std::recursive_mutex> guard(this->requestMutex);
for (auto i = this->requestReservations.begin(); i != this->requestReservations.end(); ++i)
{
if ((*i)->GetReservationid() == reply)
@@ -686,6 +713,19 @@ public:
pReader->read(&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_);
}
else if (message == "cancelListenForAtomOutput")
{
int64_t handle;
pReader->read(&handle);
this->model.cancelListenForMidiEvent(this->clientId,handle);
}
else if (message == "getJackStatus")
{
JackHostStatus status = model.getJackStatus();
@@ -989,7 +1029,7 @@ public:
}
});
{
std::lock_guard guard(subscriptionMutex);
std::lock_guard<std::recursive_mutex> guard(subscriptionMutex);
activePortMonitors.push_back(
PortMonitorSubscription{subscriptionHandle, body.instanceId_,false, body.key_});
}
@@ -1002,7 +1042,7 @@ public:
pReader->read(&subscriptionHandle);
{
{
std::lock_guard guard(subscriptionMutex);
std::lock_guard<std::recursive_mutex> guard(subscriptionMutex);
for (auto i = this->activePortMonitors.begin(); i != this->activePortMonitors.end(); ++i)
{
if ((*i).subscriptionHandle == subscriptionHandle)
@@ -1024,7 +1064,7 @@ public:
int64_t subscriptionHandle = model.addVuSubscription(instanceId);
{
std::lock_guard guard(subscriptionMutex);
std::lock_guard<std::recursive_mutex> guard(subscriptionMutex);
activeVuSubscriptions.push_back(VuSubscription{subscriptionHandle, instanceId});
}
this->Reply(replyTo, "addVuSubscriptin", subscriptionHandle);
@@ -1034,7 +1074,7 @@ public:
int64_t subscriptionHandle = -1;
pReader->read(&subscriptionHandle);
{
std::lock_guard guard(subscriptionMutex);
std::lock_guard<std::recursive_mutex> guard(subscriptionMutex);
for (auto i = activeVuSubscriptions.begin(); i != activeVuSubscriptions.end(); ++i)
{
@@ -1152,7 +1192,7 @@ public:
virtual void OnVuMeterUpdate(const std::vector<VuUpdate> &updates)
{
std::lock_guard guard(subscriptionMutex);
std::lock_guard<std::recursive_mutex> guard(subscriptionMutex);
if (updateRequestOutstanding < 5) // throttle to accomodate a web page that can't keep up.
{
vuUpdateDropped = false;
@@ -1255,6 +1295,76 @@ public:
}
}
int outstandingNotifyAtomOutputs = 0;
class PendingNotifyAtomOutput {
public:
int64_t clientHandle;
uint64_t instanceId;
std::string atomType;
std::string json;
};
std::vector<PendingNotifyAtomOutput> pendingNotifyAtomOutputs;
void OnAckNotifyAtomOutput() {
std::lock_guard<std::recursive_mutex> guard(subscriptionMutex);
if (--outstandingNotifyAtomOutputs <= 0)
{
outstandingNotifyAtomOutputs = 0;
if (pendingNotifyAtomOutputs.size() != 0)
{
PendingNotifyAtomOutput t = pendingNotifyAtomOutputs[0];
pendingNotifyAtomOutputs.erase(pendingNotifyAtomOutputs.begin());
OnNotifyAtomOutput(
t.clientHandle,
t.instanceId,
t.atomType,
t.json);
}
}
}
virtual void OnNotifyAtomOutput(int64_t clientHandle,uint64_t instanceId,const std::string&atomType, const std::string&atomJson)
{
NotifyAtomOutputBody body;
body.clientHandle_ = clientHandle;
body.instanceId_ = instanceId;
body.atomJson_ = atomJson;
{
std::lock_guard<std::recursive_mutex> guard(subscriptionMutex);
if (outstandingNotifyAtomOutputs != 0)
{
for (size_t i = 0; i < pendingNotifyAtomOutputs.size(); ++i)
{
auto &output = pendingNotifyAtomOutputs[i];
if (output.clientHandle == clientHandle && output.instanceId == instanceId && output.atomType == atomType)
{
output.json = atomJson;
return;
}
}
pendingNotifyAtomOutputs.push_back(PendingNotifyAtomOutput{ clientHandle, instanceId,atomType,atomJson });
return;
}
++outstandingNotifyAtomOutputs;
}
Request<bool>("onNotifyAtomOut",body,
[this] (const bool& value)
{
this->OnAckNotifyAtomOutput();
},
[] (const std::exception &e) {
}
);
}
virtual void OnNotifyMidiListener(int64_t clientHandle, bool isNote, uint8_t noteOrControl)
{
NotifyMidiListenerBody body;
+1 -1
View File
@@ -33,7 +33,7 @@ public:
};
class PedalBoardPreset {
long instanceId_;
uint64_t instanceId_;
std::string displayName_;
std::vector<std::unique_ptr<PedalPreset> > values_;
public:
+63
View File
@@ -163,6 +163,69 @@ namespace pipedal
return true;
}
}
// Write two disjoint areas of memory atomically.
bool write(size_t bytes, uint8_t *data, size_t bytes2, uint8_t*data2)
{
if (MULTI_WRITER)
{
std::lock_guard guard(write_mutex);
if (writeSpace() <= bytes+sizeof(bytes2)+bytes2) {
return false;
}
size_t index = this->writePosition;
for (size_t i = 0; i < bytes; ++i)
{
buffer[(index+i) & ringBufferMask] = data[i];
}
index = (index+bytes) & ringBufferMask;
for (size_t i = 0; i < sizeof(bytes2); ++i)
{
buffer[(index+i) & ringBufferMask] = ((char*)&bytes2)[i];
}
index = (index+sizeof(bytes2)) & ringBufferMask;
for (size_t i = 0; i < bytes2; ++i)
{
buffer[(index+i) & ringBufferMask] = data2[i];
}
this->writePosition = (index+bytes2) & ringBufferMask;
if (SEMAPHORE_READER)
{
sem_post(&readSemaphore);
}
return true;
} else {
if (writeSpace() <= bytes+sizeof(bytes2)+bytes2) {
return false;
}
size_t index = this->writePosition;
for (size_t i = 0; i < bytes; ++i)
{
buffer[(index+i) & ringBufferMask] = data[i];
}
index = (index+bytes) & ringBufferMask;
for (size_t i = 0; i < sizeof(bytes2); ++i)
{
buffer[(index+i) & ringBufferMask] = ((char*)&bytes2)[i];
}
index = (index+sizeof(bytes2)) & ringBufferMask;
for (size_t i = 0; i < bytes2; ++i)
{
buffer[(index+i) & ringBufferMask] = data2[i];
}
this->writePosition = (index+bytes2) & ringBufferMask;
if (SEMAPHORE_READER)
{
sem_post(&readSemaphore);
}
return true;
}
}
bool read(size_t bytes, uint8_t*data)
{
if (readSpace() < bytes) return false;
+51 -1
View File
@@ -23,7 +23,6 @@
#include "Lv2Log.hpp"
#include "VuUpdate.hpp"
#include "JackHost.hpp"
namespace pipedal
{
@@ -50,6 +49,8 @@ namespace pipedal
OnMidiListen = 16,
AtomOutput = 17,
};
class RealtimeMonitorPortSubscription
@@ -186,6 +187,16 @@ namespace pipedal
}
return true;
}
bool read(size_t size, uint8_t*data)
{
if (!ringBuffer->read(size,data))
{
throw PiPedalStateException("Ringbuffer read failed. Did you forget to check for space?");
}
return true;
}
template <typename T>
void readComplete(T *output)
{
@@ -251,6 +262,24 @@ namespace pipedal
}
}
template <typename T>
void write(RingBufferCommand command, const T &value, size_t dataLength, uint8_t*variableData)
{
// the goal: to atomically write the command and associated data.
CommandBuffer<T> buffer(command, value);
if (!ringBuffer->write(buffer.size(),(uint8_t *)&buffer,dataLength,variableData))
{
Lv2Log::error("No space in audio service ringbuffer.");
return;
}
}
void AtomOutput(uint64_t instanceId, size_t bytes, uint8_t*data)
{
write(RingBufferCommand::AtomOutput,instanceId,bytes,data);
}
void ParameterRequest(RealtimeParameterRequest *pRequest)
{
write(RingBufferCommand::ParameterRequest,pRequest);
@@ -354,4 +383,25 @@ namespace pipedal
}
};
typedef RingBufferReader<true, false> RealtimeRingBufferReader;
typedef RingBufferReader<false, true> HostRingBufferReader;
typedef RingBufferWriter<true, false> HostRingBufferWriter;
// cures a forward-declaration problem.
class RealtimeRingBufferWriter: public RingBufferWriter<false, true>
{
public:
RealtimeRingBufferWriter()
{
}
RealtimeRingBufferWriter(RingBuffer<false,true>*ringBuffer)
: RingBufferWriter<false, true> (ringBuffer)
{
}
};
} //namespace
+3 -2
View File
@@ -274,17 +274,18 @@ namespace pipedal
}
}
}
long instanceId;
uint64_t instanceId;
virtual uint8_t *GetAtomInputBuffer() { return nullptr; }
virtual uint8_t *GetAtomOutputBuffer() { return nullptr; }
virtual void RequestParameter(LV2_URID uridUri) {}
virtual void GatherParameter(RealtimeParameterRequest *pRequest) {}
virtual std::string AtomToJson(uint8_t *pAtom) { return ""; }
virtual std::string GetAtomObjectType(uint8_t*pData) { return "not implemented";}
public:
SplitEffect(
long instanceId,
uint64_t instanceId,
double sampleRate,
const std::vector<float *> &inputs)
: instanceId(instanceId), inputs(inputs), sampleRate(sampleRate)
+1 -1
View File
@@ -26,7 +26,7 @@ namespace pipedal
class VuUpdate
{
public:
long instanceId_ = 0;
uint64_t instanceId_ = 0;
long sampleTime_ = 0;
bool isStereoInput_ = false;
bool isStereoOutput_ = false;