You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
5.2 KiB
C++
169 lines
5.2 KiB
C++
//Can I reallocate buffers on the server? Yes I can.
|
|
#include "SC_PlugIn.h"
|
|
#include <vector>
|
|
#include "data/FluidTensor.hpp"
|
|
|
|
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
|
|
**/
|
|
struct NRTBuf: public SndBuf
|
|
{
|
|
NRTBuf(SndBuf& b):SndBuf(b){}
|
|
|
|
NRTBuf(World* world,size_t bufnum):
|
|
NRTBuf(*World_GetNRTBuf(world,bufnum))
|
|
{}
|
|
};
|
|
|
|
/**
|
|
A combination of SndBuf and FluidTensorView, 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
|
|
appropriate dimensions.
|
|
|
|
The SndBuf can then be 'transferred' back to the RT buffers once we're done with it,
|
|
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)
|
|
|
|
**/
|
|
class SCBufferView: public NRTBuf,ViewType
|
|
{
|
|
public:
|
|
SCBufferView() = delete;
|
|
SCBufferView(SCBufferView&) = delete;
|
|
SCBufferView operator=(SCBufferView&) = delete;
|
|
|
|
SCBufferView(size_t bufnum,World* world):
|
|
NRTBuf(world,bufnum),
|
|
ViewType({0,{static_cast<size_t>(frames),
|
|
static_cast<size_t>(channels)}},NRTBuf::data),
|
|
mBufnum(bufnum), mWorld(world)
|
|
{}
|
|
|
|
void assignToRT()
|
|
{
|
|
SndBuf* rtBuf = World_GetBuf(mWorld,mBufnum);
|
|
*rtBuf = static_cast<SndBuf>(*this);
|
|
mWorld->mSndBufUpdates[mBufnum].writes++;
|
|
}
|
|
|
|
private:
|
|
size_t mBufnum;
|
|
World * mWorld;
|
|
};
|
|
|
|
class NRTCommandBase{
|
|
|
|
|
|
template <typename T>
|
|
using AsyncFn = bool (T::*)();
|
|
|
|
template <typename T>
|
|
using AsyncCleanup = void (T::*) ();
|
|
|
|
template<typename T, AsyncFn<T> F>
|
|
static bool call(World*,void* x)
|
|
{
|
|
return (static_cast<T*>(x)->*F)();
|
|
}
|
|
|
|
template<typename T, AsyncCleanup<T> F>
|
|
static void call(World*, void* x)
|
|
{
|
|
(static_cast<T*>(x)->*F)();
|
|
}
|
|
|
|
template<typename T, AsyncFn<T> Stage2, AsyncFn<T> Stage3, AsyncFn<T> Stage4, AsyncCleanup<T> Cleanup>
|
|
void cmd(std::string name)
|
|
{
|
|
(*ft->fDoAsynchronousCommand)( mWorld, mReplyAddr,name.c_str(),this,
|
|
call<T,Stage2>, call<T,Stage3>, call<T,Stage4>,call<T,Cleanup>,
|
|
mCompletionMsgSize,mCompletionMsgData);
|
|
}
|
|
|
|
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){}
|
|
|
|
virtual ~NRTCommandBase() = default;
|
|
|
|
/**Override these**/
|
|
virtual bool process() { return true; } //NRT
|
|
virtual bool post_processing() { return true; } //RT
|
|
virtual bool post_complete() { return true; } //NRT
|
|
void cleanup() {}
|
|
|
|
/**Probably not this though**/
|
|
void runCommand(std::string name)
|
|
{
|
|
cmd<NRTCommandBase, &NRTCommandBase::process, &NRTCommandBase::post_processing, &NRTCommandBase::post_complete, &NRTCommandBase::cleanup> (name);
|
|
}
|
|
private:
|
|
protected:
|
|
World * mWorld;
|
|
void* mReplyAddr;
|
|
const char* cmdName;
|
|
void *cmdData;
|
|
size_t mCompletionMsgSize;
|
|
char* mCompletionMsgData;
|
|
|
|
void handleCompletionMessage(struct sc_msg_iter *args)
|
|
{
|
|
mCompletionMsgSize = args->getbsize();
|
|
mCompletionMsgData = 0;
|
|
if(mCompletionMsgSize)
|
|
{
|
|
//allocate string
|
|
mCompletionMsgData = (char*)RTAlloc(mWorld,mCompletionMsgSize);
|
|
args->getb(mCompletionMsgData,mCompletionMsgSize);
|
|
}
|
|
}
|
|
};
|
|
} //namespace supercollider
|
|
}//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>
|
|
void registerCommand(InterfaceTable* ft, const char* name)
|
|
{
|
|
//(World *inWorld, void* inUserData, struct sc_msg_iter *args, void *replyAddr);
|
|
PlugInCmdFunc cmd = 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);
|
|
////
|
|
//}
|
|
|