Use (hacky) NRT SendReply for responses

This solves problems wih behaviour w/r/t server sync
nix
Owen Green 5 years ago
parent c0ec922564
commit 9eb2a44a69

@ -99,5 +99,103 @@ namespace client {
(convert(f + offsets[Is], std::get<Is>(t)), 0)...}; (convert(f + offsets[Is], std::get<Is>(t)), 0)...};
} }
}; };
template<typename Packet>
struct ToOSCTypes
{
static index numTags(typename BufferT::type) { return 1; }
template <typename T>
static std::enable_if_t<
std::is_integral<T>::value || std::is_floating_point<T>::value, index>
numTags(T)
{
return 1;
}
static index numTags(std::string)
{
return 1;;
}
template <typename T>
static index numTags(FluidTensor<T, 1> s)
{
return s.size();
}
template <typename... Ts>
static index numTags(std::tuple<Ts...>&&)
{
return std::tuple_size<std::tuple<Ts...>>::value;
};
static void getTag(Packet& p, typename BufferT::type) { p.addtag('i'); }
template <typename T>
static std::enable_if_t<std::is_integral<std::decay_t<T>>::value>
getTag(Packet& p, T&&) { p.addtag('i'); }
template <typename T>
static std::enable_if_t<std::is_floating_point<std::decay_t<T>>::value>
getTag(Packet& p, T&&) { p.addtag('f'); }
static void getTag (Packet& p, std::string) { p.addtag('s'); }
template <typename T>
static void getTag(Packet& p, FluidTensor<T, 1> x)
{
T dummy{};
for (int i = 0; i < x.rows(); i++)
getTag(p, dummy);
}
template <typename... Ts, size_t... Is>
static void getTag(Packet& p, std::tuple<Ts...>&& t)
{
ForEach(t,[&p](auto& x){getTag(p,x);});
}
static void convert(Packet& p, typename BufferT::type buf)
{
p.addi(static_cast<SCBufferAdaptor*>(buf.get())->bufnum());
}
template <typename T>
static std::enable_if_t<std::is_integral<T>::value>
convert(Packet& p, T x)
{
p.addi(x);
}
template <typename T>
static std::enable_if_t<std::is_floating_point<T>::value>
convert(Packet& p, T x)
{
p.addf(x);
}
static void convert(Packet& p, std::string s)
{
p.adds(s.c_str());
}
template <typename T>
static void convert(Packet& p, FluidTensor<T, 1> s)
{
for(auto& x: s) convert(p,x);
}
template <typename... Ts, size_t... Is>
static void convert(Packet& p, std::tuple<Ts...>&& t)
{
ForEach(t,[&p](auto& x){ convert(p,x);});
}
};
} }
} }

@ -2,6 +2,7 @@
#include "ArgsFromClient.hpp" #include "ArgsFromClient.hpp"
#include "ArgsToClient.hpp" #include "ArgsToClient.hpp"
#include <scsynthsend.h>
namespace fluid { namespace fluid {
namespace client { namespace client {
@ -27,6 +28,7 @@ struct FluidSCMessaging{
ReturnType result; ReturnType result;
std::string name; std::string name;
IndexList argIndices; IndexList argIndices;
void* replyAddr{nullptr};
}; };
@ -123,6 +125,7 @@ struct FluidSCMessaging{
auto msg = new MessageData(); auto msg = new MessageData();
msg->id = args->geti(); msg->id = args->geti();
msg->replyAddr = copyReplyAddress(replyAddr);
///TODO make this step contingent on verbosity or something, in the name of effieciency ///TODO make this step contingent on verbosity or something, in the name of effieciency
bool willContinue = validateMessageArgs(msg, args); bool willContinue = validateMessageArgs(msg, args);
@ -167,7 +170,7 @@ struct FluidSCMessaging{
return true; return true;
}, },
[](World* world, void* data) // RT thread: response [](World* world, void* data) // RT thread: buffer swap (and possible completion messages)
{ {
MessageData* m = static_cast<MessageData*>(data); MessageData* m = static_cast<MessageData*>(data);
MessageData::Descriptor::template forEachArg<typename BufferT::type, MessageData::Descriptor::template forEachArg<typename BufferT::type,
@ -175,19 +178,16 @@ struct FluidSCMessaging{
world); world);
return true; return true;
}, },
nullptr, // NRT Thread: No-op [](World* world, void* data) // NRT Thread: Send reply
[](World* world, void* data) // RT thread: clean up
{ {
MessageData* m = static_cast<MessageData*>(data); MessageData* m = static_cast<MessageData*>(data);
if(m->result.status() != Result::Status::kError) if(m->result.status() != Result::Status::kError)
messageOutput(m->name, m->id, m->result, world); messageOutput(m->name, m->id, m->result, m->replyAddr);
else return false;
},
[](World*, void* data) // RT thread: clean up
{ {
auto ft = getInterfaceTable(); MessageData* m = static_cast<MessageData*>(data);
ft->fSendNodeReply(ft->fGetNode(world,0),-1, m->name.c_str(),0, nullptr);
}
delete m; delete m;
}, },
static_cast<int>(completionMsgSize), completionMsgData); static_cast<int>(completionMsgSize), completionMsgData);
@ -201,61 +201,67 @@ struct FluidSCMessaging{
} }
template <typename T> // call from RT template <typename T> // call from RT
static void messageOutput(const std::string& s, index id, MessageResult<T>& result, World* world) static void messageOutput(const std::string& s, index id, MessageResult<T>& result, void* replyAddr)
{ {
auto ft = getInterfaceTable(); index numTags = ToOSCTypes<small_scpacket>::numTags(static_cast<T>(result));
if(numTags > 2048)
// allocate return values
index numArgs = ToFloatArray::allocSize(static_cast<T>(result));
if(numArgs > 2048)
{ {
std::cout << "ERROR: Message response too big to send (" << asUnsigned(numArgs) * sizeof(float) << " bytes)." << std::endl; std::cout << "ERROR: Message response too big to send (" << asUnsigned(numTags) * sizeof(float) << " bytes)." << std::endl;
return; return;
} }
float* values = new float[asUnsigned(numArgs)]; small_scpacket packet;
packet.adds(s.c_str());
// copy return data packet.maketags(static_cast<int>(numTags) + 2);
ToFloatArray::convert(values, static_cast<T>(result)); packet.addtag(',');
packet.addtag('i');
ToOSCTypes<small_scpacket>::getTag(packet, static_cast<T>(result));
ft->fSendNodeReply(ft->fGetNode(world,0), static_cast<int>(id), s.c_str(), packet.addi(static_cast<int>(id));
static_cast<int>(numArgs), values); ToOSCTypes<small_scpacket>::convert(packet, static_cast<T>(result));
delete[] values; if(replyAddr)
::SendReply(static_cast<ReplyAddress*>(replyAddr),packet.data(),static_cast<int>(packet.size()));
} }
static void messageOutput(const std::string& s,index id, MessageResult<void>&, World* world) static void messageOutput(const std::string& s,index id, MessageResult<void>&, void* replyAddr)
{ {
auto ft = getInterfaceTable(); small_scpacket packet;
ft->fSendNodeReply(ft->fGetNode(world,0), static_cast<int>(id), s.c_str(), 0, nullptr); packet.adds(s.c_str());
packet.maketags(2);
packet.addtag(',');
packet.addtag('i');
packet.addi(static_cast<int>(id));
if(replyAddr)
::SendReply(static_cast<ReplyAddress*>(replyAddr),packet.data(),static_cast<int>(packet.size()));
} }
template <typename... Ts> template <typename... Ts>
static void messageOutput(const std::string& s, index id, MessageResult<std::tuple<Ts...>>& result, World* world) static void messageOutput(const std::string& s, index id, MessageResult<std::tuple<Ts...>>& result, void* replyAddr)
{ {
std::array<index, sizeof...(Ts)> offsets; using T = std::tuple<Ts...>;
index numArgs;
std::tie(offsets, numArgs) = index numTags = ToOSCTypes<small_scpacket>::numTags(static_cast<T>(result));
ToFloatArray::allocSize(static_cast<std::tuple<Ts...>>(result)); if(numTags > 2048)
if(numArgs > 2048)
{ {
std::cout << "ERROR: Message response too big to send (" << asUnsigned(numArgs) * sizeof(float) << " bytes)." << std::endl; std::cout << "ERROR: Message response too big to send (" << asUnsigned(numTags) * sizeof(float) << " bytes)." << std::endl;
return; return;
} }
float* values = new float[asUnsigned(numArgs)]; small_scpacket packet;
ToFloatArray::convert(values, std::tuple<Ts...>(result), offsets, packet.adds(s.c_str());
std::index_sequence_for<Ts...>()); packet.maketags(static_cast<int>(numTags + 3));
packet.addtag(',');
packet.addtag('i');
ToOSCTypes<small_scpacket>::getTag(packet,static_cast<T>(result));
auto ft = getInterfaceTable(); packet.addi(static_cast<int>(id));
ft->fSendNodeReply(ft->fGetNode(world,0), static_cast<int>(id), s.c_str(), ToOSCTypes<small_scpacket>::convert(packet, static_cast<T>(result));
static_cast<int>(numArgs), values);
if(replyAddr)
::SendReply(static_cast<ReplyAddress*>(replyAddr),packet.data(),static_cast<int>(packet.size()));
delete[] values;
} }
}; };
} }

@ -10,6 +10,7 @@
#include <clients/common/FluidBaseClient.hpp> #include <clients/common/FluidBaseClient.hpp>
#include <SC_PlugIn.hpp> #include <SC_PlugIn.hpp>
#include <SC_ReplyImpl.hpp> #include <SC_ReplyImpl.hpp>
#include <scsynthsend.h>
#include <map> #include <map>
namespace fluid { namespace fluid {
@ -96,7 +97,7 @@ namespace impl {
struct NRTCommand struct NRTCommand
{ {
NRTCommand(World*, sc_msg_iter* args, bool consumeID = true) NRTCommand(World*, sc_msg_iter* args, void* replyAddr, bool consumeID = true)
{ {
auto count = args->count; auto count = args->count;
auto pos = args->rdpos; auto pos = args->rdpos;
@ -108,34 +109,51 @@ namespace impl {
args->count = count; args->count = count;
args->rdpos = pos; args->rdpos = pos;
} }
if(replyAddr)
mReplyAddress = copyReplyAddress(replyAddr);
}
~NRTCommand()
{
if(mReplyAddress) deleteReplyAddress(mReplyAddress);
} }
NRTCommand(){} NRTCommand(){}
explicit NRTCommand(index id):mID{id}{} explicit NRTCommand(index id):mID{id}{}
bool stage2(World*) { std::cout << "Nope\n"; return true; } //nrt bool stage2(World*) { return true; } //nrt
bool stage3(World*) { return true; } //rt bool stage3(World*) { return true; } //rt
bool stage4(World*) { return true; } //nrt bool stage4(World*) { return false; } //nrt
void cleanup(World*) {} //rt void cleanup(World*) {} //rt
void sendReply(World* world, const char* name,bool success) void sendReply(const char* name,bool success)
{ {
if(mID < 0) return; if(mReplyAddress)
auto ft = getInterfaceTable(); {
auto root = ft->fGetNode(world,0); std::string slash{"/"};
float res[2] = {static_cast<float>(success),static_cast<float>(mID)}; small_scpacket packet;
std::string slashname = std::string{'/'} + name; packet.adds((slash+name).c_str());
ft->fSendNodeReply(root,0, slashname.c_str(), 2, res); packet.maketags(3);
packet.addtag(',');
packet.addtag('i');
packet.addtag('i');
packet.addi(success);
packet.addi(static_cast<int>(mID));
::SendReply(static_cast<ReplyAddress*>(mReplyAddress),packet.data(), static_cast<int>(packet.size()));
}
} }
// protected: // protected:
index mID; index mID;
void* mReplyAddress{nullptr};
}; };
struct CommandNew : public NRTCommand struct CommandNew : public NRTCommand
{ {
CommandNew(World* world, sc_msg_iter* args) CommandNew(World* world, sc_msg_iter* args,void* replyAddr)
: NRTCommand{world,args, !IsNamedShared_v<Client>}, : NRTCommand{world,args, replyAddr, !IsNamedShared_v<Client>},
mParams{Client::getParameterDescriptors()} mParams{Client::getParameterDescriptors()}
{ {
mParams.template setParameterValuesRT<ParamsFromOSC>(nullptr, world, *args); mParams.template setParameterValuesRT<ParamsFromOSC>(nullptr, world, *args);
@ -168,13 +186,10 @@ namespace impl {
auto ptr = get(NRTCommand::mID).lock(); auto ptr = get(NRTCommand::mID).lock();
ptr->mClient.setParams(ptr->mParams); ptr->mClient.setParams(ptr->mParams);
} }
return mResult;
}
bool stage3(World* w) NRTCommand::sendReply(name(),mResult);
{
NRTCommand::sendReply(w, name(), mResult); return mResult;
return true;
} }
private: private:
@ -218,14 +233,10 @@ namespace impl {
{ {
CancelCheck<IsRTQueryModel>()(NRTCommand::mID); CancelCheck<IsRTQueryModel>()(NRTCommand::mID);
remove(NRTCommand::mID); remove(NRTCommand::mID);
NRTCommand::sendReply(name(), true);
return true; return true;
} }
bool stage3(World* w)
{
NRTCommand::sendReply(w, name(), true);
return true;
}
}; };
@ -235,7 +246,7 @@ namespace impl {
CommandAsyncComplete(World*, index id, void* replyAddress) CommandAsyncComplete(World*, index id, void* replyAddress)
{ {
NRTCommand::mID = id; NRTCommand::mID = id;
mReplyAddress = replyAddress; NRTCommand::mReplyAddress = replyAddress;
} }
static const char* name() { return CommandProcess::name(); } static const char* name() { return CommandProcess::name(); }
@ -243,7 +254,7 @@ namespace impl {
bool stage2(World* world) bool stage2(World* world)
{ {
std::cout << "In Async completion\n"; // std::cout << "In Async completion\n";
if(auto ptr = get(NRTCommand::mID).lock()) if(auto ptr = get(NRTCommand::mID).lock())
{ {
Result r; Result r;
@ -278,7 +289,6 @@ namespace impl {
{ {
auto& params = ptr->mParams; auto& params = ptr->mParams;
params.template forEachParamType<BufferT, AssignBuffer>(world); params.template forEachParamType<BufferT, AssignBuffer>(world);
//NRTCommand::sendReply(world, name(), true);
return true; return true;
} }
return false; return false;
@ -289,29 +299,28 @@ namespace impl {
if(auto ptr = get(NRTCommand::mID).lock()) if(auto ptr = get(NRTCommand::mID).lock())
{ {
ptr->mParams.template forEachParamType<BufferT, impl::CleanUpBuffer>(); ptr->mParams.template forEachParamType<BufferT, impl::CleanUpBuffer>();
if(NRTCommand::mID >= 0 && NRTCommand::mReplyAddress)
{
NRTCommand::sendReply(name(),mSuccess);
}
return true; return true;
} }
return false; return false;
} }
void cleanup(World* world) { void cleanup(World*) {
if(auto ptr = get(NRTCommand::mID).lock() && NRTCommand::mID >= 0) if(NRTCommand::mReplyAddress)
NRTCommand::sendReply(world, name(), mSuccess); deleteReplyAddress(NRTCommand::mReplyAddress);
if(mReplyAddress)
{
ReplyAddress* r = static_cast<ReplyAddress*>(mReplyAddress);
delete r;
}
} //rt } //rt
bool mSuccess; bool mSuccess;
void* mReplyAddress{nullptr};
}; };
static void doProcessCallback(World* world, index id,size_t completionMsgSize,char* completionMessage,void* replyAddress) static void doProcessCallback(World* world, index id,size_t completionMsgSize,char* completionMessage,void* replyAddress)
{ {
std::cout << "In callback\n"; // std::cout << "In callback\n";
auto ft = getInterfaceTable(); auto ft = getInterfaceTable();
struct Context{ struct Context{
@ -325,7 +334,7 @@ namespace impl {
Context* c = new Context{world,id,completionMsgSize,completionMessage,replyAddress}; Context* c = new Context{world,id,completionMsgSize,completionMessage,replyAddress};
auto runCompletion = [](FifoMsg* msg){ auto runCompletion = [](FifoMsg* msg){
std::cout << "In FIFOMsg\n"; // std::cout << "In FIFOMsg\n";
Context* c = static_cast<Context*>(msg->mData); Context* c = static_cast<Context*>(msg->mData);
World* world = c->mWorld; World* world = c->mWorld;
index id = c->mID; index id = c->mID;
@ -348,7 +357,7 @@ namespace impl {
struct CommandProcess: public NRTCommand struct CommandProcess: public NRTCommand
{ {
CommandProcess(World* world, sc_msg_iter* args): NRTCommand{world, args} CommandProcess(World* world, sc_msg_iter* args, void* replyAddr): NRTCommand{world, args, replyAddr}
{ {
auto& ar = *args; auto& ar = *args;
@ -391,7 +400,7 @@ namespace impl {
index id = NRTCommand::mID; index id = NRTCommand::mID;
size_t completionMsgSize = mCompletionMsgSize; size_t completionMsgSize = mCompletionMsgSize;
char* completionMessage = mCompletionMessage; char* completionMessage = mCompletionMessage;
void* replyAddress = copyReplyAddress(mReplyAddr); void* replyAddress = copyReplyAddress(NRTCommand::mReplyAddress);
auto callback = [world,id,completionMsgSize,completionMessage,replyAddress](){ auto callback = [world,id,completionMsgSize,completionMessage,replyAddress](){
doProcessCallback(world,id,completionMsgSize,completionMessage,replyAddress); doProcessCallback(world,id,completionMsgSize,completionMessage,replyAddress);
@ -425,7 +434,7 @@ namespace impl {
// NRTCommand::sendReply(world, name(), mResult.ok()); // NRTCommand::sendReply(world, name(), mResult.ok());
return true; return true;
} }
std::cout << "Ohno\n"; // std::cout << "Ohno\n";
return false; return false;
} }
@ -435,31 +444,25 @@ namespace impl {
if(auto ptr = get(NRTCommand::mID).lock()) if(auto ptr = get(NRTCommand::mID).lock())
{ {
ptr->mParams.template forEachParamType<BufferT, impl::CleanUpBuffer>(); ptr->mParams.template forEachParamType<BufferT, impl::CleanUpBuffer>();
if(NRTCommand::mID >= 0 && mSynchronous)
NRTCommand::sendReply(name(), mResult.ok());
return true; return true;
} }
return false; return false;
} }
void cleanup(World* world) {
if(auto ptr = get(NRTCommand::mID).lock() && NRTCommand::mID >= 0 && mSynchronous)
NRTCommand::sendReply(world, name(), mResult.ok());
if(mReplyAddr)
deleteReplyAddress(mReplyAddr);
// getInterfaceTable()->fRTFree(world,mReplyAddr);
} //rt
bool synchronous() bool synchronous()
{ {
return mSynchronous; return mSynchronous;
} }
void addCompletionMessage(size_t size, char* message, void* addr) void addCompletionMessage(size_t size, char* message)//, void* addr)
{ {
mCompletionMsgSize = size; mCompletionMsgSize = size;
mCompletionMessage = message; mCompletionMessage = message;
mReplyAddr = copyReplyAddress(addr);
// ReplyAddress* rr = static_cast<ReplyAddress*>(addr);
// if(addr)mReplyAddr = *rr;
} }
// private: // private:
@ -467,17 +470,16 @@ namespace impl {
bool mSynchronous; bool mSynchronous;
size_t mCompletionMsgSize{0}; size_t mCompletionMsgSize{0};
char* mCompletionMessage{nullptr}; char* mCompletionMessage{nullptr};
void* mReplyAddr{nullptr};
// sc_msg_iter* mOSCData;
}; };
struct CommandProcessNew: public NRTCommand struct CommandProcessNew: public NRTCommand
{ {
CommandProcessNew(World* world, sc_msg_iter* args) CommandProcessNew(World* world, sc_msg_iter* args,void* replyAddr)
: mNew{world,args}, : mNew{world, args, replyAddr},
mProcess{mNew.mID,false} mProcess{mNew.mID,false}
{ {
mProcess.mSynchronous = args->geti(); mProcess.mSynchronous = args->geti();
mProcess.mReplyAddress = mNew.mReplyAddress;
} }
CommandProcessNew(index id, World* world, FloatControlsIter& args, Unit* x) CommandProcessNew(index id, World* world, FloatControlsIter& args, Unit* x)
@ -501,13 +503,14 @@ namespace impl {
return mProcess.stage3(world); return mProcess.stage3(world);
} }
bool stage4(World* world) //rt bool stage4(World* world) //nrt
{ {
return mProcess.stage4(world); return mProcess.stage4(world);
} }
void cleanup(World* world) void cleanup(World* world)
{ {
mProcess.mReplyAddress = nullptr;
mProcess.cleanup(world); mProcess.cleanup(world);
} }
@ -516,9 +519,9 @@ namespace impl {
return mProcess.synchronous(); return mProcess.synchronous();
} }
void addCompletionMessage(size_t size, char* message,void* addr) void addCompletionMessage(size_t size, char* message)
{ {
mProcess.addCompletionMessage(size, message,addr); mProcess.addCompletionMessage(size, message);
} }
private: private:
@ -529,7 +532,8 @@ namespace impl {
struct CommandCancel: public NRTCommand struct CommandCancel: public NRTCommand
{ {
CommandCancel(World* world, sc_msg_iter* args): NRTCommand{world, args} CommandCancel(World* world, sc_msg_iter* args, void* replyAddr)
: NRTCommand{world, args, replyAddr}
{} {}
static const char* name() static const char* name()
@ -555,8 +559,8 @@ namespace impl {
struct CommandSetParams: public NRTCommand struct CommandSetParams: public NRTCommand
{ {
CommandSetParams(World* world, sc_msg_iter* args) CommandSetParams(World* world, sc_msg_iter* args, void* replyAddr)
: NRTCommand{world, args} : NRTCommand{world, args, replyAddr}
{ {
auto& ar = *args; auto& ar = *args;
if(auto ptr = get(NRTCommand::mID).lock()) if(auto ptr = get(NRTCommand::mID).lock())
@ -564,7 +568,6 @@ namespace impl {
ptr->mParams.template setParameterValuesRT<ParamsFromOSC>(nullptr, world, ar); ptr->mParams.template setParameterValuesRT<ParamsFromOSC>(nullptr, world, ar);
Result result = validateParameters(ptr->mParams); Result result = validateParameters(ptr->mParams);
ptr->mClient.setParams(ptr->mParams); ptr->mClient.setParams(ptr->mParams);
NRTCommand::sendReply(world, name(), result.ok());
} else printNotFound(NRTCommand::mID); } else printNotFound(NRTCommand::mID);
} }
@ -602,7 +605,7 @@ namespace impl {
{ {
if(!cmd->synchronous()) if(!cmd->synchronous())
{ {
cmd->addCompletionMessage(completionMsgSize,completionMsgData,replyAddr); cmd->addCompletionMessage(completionMsgSize,completionMsgData);
return runAsyncCommand<CommandProcess>(world, cmd, replyAddr, 0, nullptr); return runAsyncCommand<CommandProcess>(world, cmd, replyAddr, 0, nullptr);
} }
else return runAsyncCommand<CommandProcess>(world, cmd, replyAddr, completionMsgSize, completionMsgData); else return runAsyncCommand<CommandProcess>(world, cmd, replyAddr, completionMsgSize, completionMsgData);
@ -613,7 +616,7 @@ namespace impl {
{ {
if(!cmd->synchronous()) if(!cmd->synchronous())
{ {
cmd->addCompletionMessage(completionMsgSize,completionMsgData,replyAddr); cmd->addCompletionMessage(completionMsgSize,completionMsgData);
return runAsyncCommand<CommandProcessNew>(world, cmd, replyAddr, 0, nullptr); return runAsyncCommand<CommandProcessNew>(world, cmd, replyAddr, 0, nullptr);
} }
else return runAsyncCommand<CommandProcessNew>(world, cmd, replyAddr, completionMsgSize, completionMsgData); else return runAsyncCommand<CommandProcessNew>(world, cmd, replyAddr, completionMsgSize, completionMsgData);
@ -629,7 +632,7 @@ namespace impl {
auto ft = getInterfaceTable(); auto ft = getInterfaceTable();
void* space = ft->fRTAlloc(world,sizeof(Command)); void* space = ft->fRTAlloc(world,sizeof(Command));
Command* cmd = new (space) Command(world, args); Command* cmd = new (space) Command(world, args, replyAddr);
//This is brittle, but can't think of something better offhand //This is brittle, but can't think of something better offhand
//This is the only place we can check for a completion message at the end of the OSC packet //This is the only place we can check for a completion message at the end of the OSC packet
//beause it has to be passed on to DoAsynhronousCommand at this point. However, detecting correctly //beause it has to be passed on to DoAsynhronousCommand at this point. However, detecting correctly
@ -840,7 +843,7 @@ namespace impl {
struct DefineCommandIf<true, CommandType> struct DefineCommandIf<true, CommandType>
{ {
void operator()() { void operator()() {
std::cout << CommandType::name() << std::endl; // std::cout << CommandType::name() << std::endl;
defineNRTCommand<CommandType>(); defineNRTCommand<CommandType>();
} }
}; };
@ -873,7 +876,6 @@ namespace impl {
DefineCommandIf<!IsRTQueryModel, CommandCancel>()(); DefineCommandIf<!IsRTQueryModel, CommandCancel>()();
DefineCommandIf<IsModel,CommandSetParams>()(); DefineCommandIf<IsModel,CommandSetParams>()();
// DefineCommandIf<IsRTQueryModel,CommandGetParams>()();
defineNRTCommand<CommandFree>(); defineNRTCommand<CommandFree>();
RegisterUnitIf<!IsRTQueryModel,NRTProgressUnit>()(ft); RegisterUnitIf<!IsRTQueryModel,NRTProgressUnit>()(ft);

@ -17,15 +17,12 @@ FluidMessageResponse : Object
} }
*string{ |a, offset| *string{ |a, offset|
var split = a.find([0],offset); ^[a]
var res;
if(split.isNil) {"ERROR: can't parse string from server".throw};
^[[a.copyRange(offset,split-1).keep(split).collectAs({|x|x.asInteger.asAscii},String)], split + 1]
} }
*strings {|a,offset| *strings {|a,offset|
//TODO add an n argument as with numbers() to make this less omnivorous //TODO add an n argument as with numbers() to make this less omnivorous
^[a.drop(offset).drop(-1).collectAs({|x|x.asInteger.asAscii},String).split(0.asAscii)] ^[a.drop(offset)];
} }
*numbers{ |a, n, offset| *numbers{ |a, n, offset|

@ -199,20 +199,15 @@ FluidDataObject : FluidServerObject
if(serverCaches[this].includesKey(server,\messageResponder).not) if(serverCaches[this].includesKey(server,\messageResponder).not)
{ {
serverCaches[this].put(server,\messageResponder,OSCFunc.new({|m| serverCaches[this].put(server,\messageResponder,OSCFunc.new({|m|
var id = m[2].asInteger; var id = m[1].asInteger;
var method; var method;
// "I'm in the maccydees".postln;
serverCaches[this].at(server,id) !? { |p| serverCaches[this].at(server,id) !? { |p|
// "I'm in the burger king".postln ;
// m.postln;
method = m[0].asString.findRegexp("/"++this.name++"/(.*)")[1][1].asSymbol; method = m[0].asString.findRegexp("/"++this.name++"/(.*)")[1][1].asSymbol;
/* p.postln;
p.actions[method].postln;*/
p.actions[method] !? {|a| p.actions[method] !? {|a|
//two items: parser and action //two items: parser and action
var parser = a[0]; var parser = a[0];
var action = a[1]; var action = a[1];
var result = FluidMessageResponse.collectArgs(parser,m[3..]); var result = FluidMessageResponse.collectArgs(parser,m[2..]);
action.value(result); action.value(result);
} }
} }

Loading…
Cancel
Save