Add fdNRTBase: Base class for Non Real-Time SC commands

nix
Owen Green 7 years ago
parent 41ed298279
commit f4a9560e9c

@ -1,14 +1,19 @@
//Can I reallocate buffers on the server? Yes I can.
#pragma once
#include "data/FluidTensor.hpp"
#include "clients/common/FluidParams.hpp"
#include "SC_PlugIn.h"
#include <boost/align/aligned_alloc.hpp>
#include <vector>
#include "data/FluidTensor.hpp"
static InterfaceTable *ft;
//static InterfaceTable *ft;
namespace fluid {
namespace sc{
using ViewType = fluid::FluidTensorView<float, 2>;
/**
A descendent of SndBuf that will populate itself
from the NRT mirror buffers given a world and a bufnum
@ -16,14 +21,17 @@ namespace sc{
struct NRTBuf: public SndBuf
{
NRTBuf(SndBuf& b):SndBuf(b){}
NRTBuf(World* world,size_t bufnum):
NRTBuf(World* world,long bufnum):
NRTBuf(*World_GetNRTBuf(world,bufnum))
{}
{
this->samplerate = world->mFullRate.mSampleRate;
}
};
/**
A combination of SndBuf and FluidTensorView, for simple transfer of data
A combination of SndBuf and parameter::BufferAdaptor (which, in turn, exposes FluidTensorView<float,2>), for simple transfer of data
Given a World* and a buffer number, this will populate its SndBuf stuff
from the NRT mirror buffers, and create a FluidTensorView wrapper of
@ -33,136 +41,173 @@ namespace sc{
and SC notified of the update. (In the context of SequencedCommands, in which this is meant
to be used, this would happen at Stage3() on the real-time thread)
nSamps = rows
nChans = columns
**/
class SCBufferView: public NRTBuf,ViewType
class SCBufferView: public NRTBuf, public parameter::BufferAdaptor
{
public:
SCBufferView() = delete;
SCBufferView(SCBufferView&) = delete;
SCBufferView operator=(SCBufferView&) = delete;
SCBufferView(size_t bufnum,World* world):
SCBufferView(long bufnum,World* world):
NRTBuf(world,bufnum),
ViewType({0,{static_cast<size_t>(frames),
static_cast<size_t>(channels)}},NRTBuf::data),
BufferAdaptor({0,{static_cast<size_t>(frames),static_cast<size_t>(channels)}},NRTBuf::data),
mBufnum(bufnum), mWorld(world)
{}
void assignToRT()
~SCBufferView() = default;
void assignToRT(World* rtWorld)
{
SndBuf* rtBuf = World_GetBuf(mWorld,mBufnum);
SndBuf* rtBuf = World_GetBuf(rtWorld,mBufnum);
*rtBuf = static_cast<SndBuf>(*this);
mWorld->mSndBufUpdates[mBufnum].writes++;
rtWorld->mSndBufUpdates[mBufnum].writes++;
}
//No locks in (vanilla) SC, so no-ops for these
void acquire() override {}
void release() override {}
private:
size_t mBufnum;
World * mWorld;
};
//Validity is based on whether this buffer is within the range the server knows about
bool valid() const override {
return (mBufnum >=0 && mBufnum < mWorld->mNumSndBufs);
}
class NRTCommandBase{
void resize(size_t frames, size_t channels, size_t rank) override {
SndBuf* thisThing = static_cast<SndBuf*>(this);
template <typename T>
using AsyncFn = bool (T::*)();
float* oldData = thisThing->data;
template <typename T>
using AsyncCleanup = void (T::*) ();
mWorld->ft->fBufAlloc(this, channels * rank, frames, this->samplerate);
template<typename T, AsyncFn<T> F>
static bool call(World*,void* x)
{
return (static_cast<T*>(x)->*F)();
}
FluidTensorView<float,2> v= FluidTensorView<float,2>(NRTBuf::data,0,static_cast<size_t>(frames),static_cast<size_t>(channels * rank));
template<typename T, AsyncCleanup<T> F>
static void call(World*, void* x)
{
(static_cast<T*>(x)->*F)();
}
static_cast<FluidTensorView<float,2>&>(*this) = std::move(v);
if(oldData)
boost::alignment::aligned_free(oldData);
template<typename T, AsyncFn<T> Stage2, AsyncFn<T> Stage3, AsyncFn<T> Stage4, AsyncCleanup<T> Cleanup>
void cmd(std::string name)
}
protected:
bool equal(BufferAdaptor* rhs) const override
{
SCBufferView* x = dynamic_cast<SCBufferView*>(rhs);
if(x)
{
(*ft->fDoAsynchronousCommand)( mWorld, mReplyAddr,name.c_str(),this,
call<T,Stage2>, call<T,Stage3>, call<T,Stage4>,call<T,Cleanup>,
mCompletionMsgSize,mCompletionMsgData);
return mBufnum == x->mBufnum;
}
return false;
}
long mBufnum;
World* mWorld;
};
class NRTCommandBase{
using param_type = fluid::parameter::Instance;
public:
NRTCommandBase() = delete;
NRTCommandBase(NRTCommandBase&) = delete;
NRTCommandBase& operator=(NRTCommandBase&) = delete;
NRTCommandBase(World *inWorld, void* inUserData, struct sc_msg_iter *args, void *replyAddr):
mWorld(inWorld),mReplyAddr(replyAddr){}
NRTCommandBase(std::vector<param_type> params,
void* inUserData):
// mWorld(inWorld),mReplyAddr(replyAddr), mCompletionMsgData(completionMsgData), mCompletionMsgSize(completionMsgSize),
mParams(params)
{}
~NRTCommandBase() = default;
virtual ~NRTCommandBase() = default;
template <typename T> using AsyncFn = bool (T::*)(World* w);
template <typename T> using AsyncCleanup = void (T::*)();
/**Override these**/
virtual bool process() { return true; } //NRT
virtual bool post_processing() { return true; } //RT
virtual bool post_complete() { return true; } //NRT
void cleanup() {}
template <typename T, AsyncFn<T> F>
static bool call(World* w,void* x){return (static_cast<T*>(x)->*F)(w);}
/**Probably not this though**/
void runCommand(std::string name)
template<typename T>
static void call(World*, void* x){delete static_cast<T*>(x);}
template<typename T, AsyncFn<T> Stage2, AsyncFn<T> Stage3, AsyncFn<T> Stage4>
void cmd(World* world, std::string name, void* replyAddr, char* completionMsgData, size_t completionMsgSize)
{
cmd<NRTCommandBase, &NRTCommandBase::process, &NRTCommandBase::post_processing, &NRTCommandBase::post_complete, &NRTCommandBase::cleanup> (name);
(world->ft->fDoAsynchronousCommand)(world, replyAddr,name.c_str(),this,
call<T,Stage2>, call<T,Stage3>, call<T,Stage4>,call<T>,
completionMsgSize,completionMsgData);
}
private:
protected:
World * mWorld;
// World * mWorld;
// InterfaceTable *ft;
long bufNUm;
void* mReplyAddr;
const char* cmdName;
void *cmdData;
size_t mCompletionMsgSize;
char* mCompletionMsgData;
size_t mCompletionMsgSize;
std::vector<param_type> mParams;
};
void handleCompletionMessage(struct sc_msg_iter *args)
//This wraps a class instance in a function call to pass to SC
template<typename NRT_Plug>
void command(World *inWorld, void* inUserData, struct sc_msg_iter *args, void *replyAddr)
{
//Iterate over parameter descriptions associated with this client object, fill with data from language side
std::vector<parameter::Instance> params = NRT_Plug::client_type::newParameterSet();
for (auto&& p: params)
{
switch(p.getDescriptor().getType())
{
case parameter::Type::Buffer:
{
long bufNum = static_cast<long>(args->geti());
if(bufNum >= 0){
SCBufferView* buf = new SCBufferView(bufNum,inWorld);
p.setBuffer(buf);
}
break;
}
case parameter::Type::Long:
{
mCompletionMsgSize = args->getbsize();
mCompletionMsgData = 0;
if(mCompletionMsgSize)
p.setLong(static_cast<long>(args->geti()));
break;
}
case parameter::Type::Float:
{
p.setFloat(args->getf());
break;
}
default:
{
p.setLong(static_cast<long>(args->geti()));
}
}
}
//Deal with the completion message at the end, if any
size_t completionMsgSize = args->getbsize();
char* completionMsgData = 0;
if(completionMsgSize)
{
//allocate string
mCompletionMsgData = (char*)RTAlloc(mWorld,mCompletionMsgSize);
args->getb(mCompletionMsgData,mCompletionMsgSize);
completionMsgData = (char*)inWorld->ft->fRTAlloc(inWorld,completionMsgSize);
args->getb(completionMsgData,completionMsgSize);
}
//Make a new pointer for our plugin, and set it going
NRT_Plug* cmd = new NRT_Plug(params, inUserData);
cmd->runCommand(inWorld, replyAddr, completionMsgData, completionMsgSize);
}
};
} //namespace supercollider
} //namespace sc
}//namespace fluid
template<typename NRT_Plug>
void command(World *inWorld, void* inUserData, struct sc_msg_iter *args, void *replyAddr)
{
NRT_Plug cmd(inWorld, inUserData, args, replyAddr);
cmd.runCommand("AysncCommand");
}
template <typename NRT_Plug>
template <typename NRT_Plug,typename NRT_Client>
void registerCommand(InterfaceTable* ft, const char* name)
{
//(World *inWorld, void* inUserData, struct sc_msg_iter *args, void *replyAddr);
PlugInCmdFunc cmd = command<NRT_Plug>;
PlugInCmdFunc cmd = fluid::sc::command<NRT_Plug>;
(*ft->fDefinePlugInCmd)(name,cmd,nullptr);
}
//PluginLoad(BufferFunTime) {
//
// using fluid::sc::NRTCommandBase;
//
// registerCommand<NRTCommandBase>(inTable, "ASyncBufMatch");
//
//// ft = inTable;
//// //BufGen version: all in the NRT thread
////// DefineBufGen("BufMatch", BufferMatch);
//// //ASync version: swaps between NRT and RT threads
//// DefinePlugInCmd("AsyncBufMatch", ASyncBufferFun_Main, nullptr);
////
//}

Loading…
Cancel
Save