diff --git a/include/clients/rt/FluidDataSetWr.hpp b/include/clients/rt/FluidDataSetWr.hpp index ebdc0a4..ab13df0 100644 --- a/include/clients/rt/FluidDataSetWr.hpp +++ b/include/clients/rt/FluidDataSetWr.hpp @@ -20,39 +20,45 @@ namespace fluid { namespace client { -class DataSetWriterClient : public FluidBaseClient, OfflineIn, OfflineOut -{ +class DataSetWriterClient : public FluidBaseClient, OfflineIn, OfflineOut { + enum { kDataSet, kIDPrefix, kIDNumber, kBuffer }; + static constexpr std::initializer_list idNumberDefaults{0, 0}; + public: - FLUID_DECLARE_PARAMS( - DataSetClientRef::makeParam("dataSet", "DataSet ID"), - StringParam("labelPrefix","Label Prefix"), - LongParam("labelOffset", "Label Counter Offset", 0), - BufferParam("buf", "Data Buffer") - ); - - DataSetWriterClient(ParamSetViewType& p) : mParams(p) {} - - template - Result process(FluidContext&) - { - auto dataset = get<0>().get(); - if (auto datasetPtr = dataset.lock()) - { - std::stringstream ss; - ss << get<1>(); - - index labelOffset = get<2>(); - if(labelOffset >= 0) ss << labelOffset + (mCounter++); - - auto buf = get<3>(); - return datasetPtr->addPoint(ss.str(), buf); - } - else - return {Result::Status::kError, "No dataset"}; + FLUID_DECLARE_PARAMS(DataSetClientRef::makeParam("dataSet", "DataSet ID"), + StringParam("idPrefix", "ID Prefix"), + LongArrayParam("idNumber", "ID Counter Offset", + idNumberDefaults), + BufferParam("buf", "Data Buffer")); + + DataSetWriterClient(ParamSetViewType &p) : mParams(p) {} + + template Result process(FluidContext &) { + auto dataset = get().get(); + if (auto datasetPtr = dataset.lock()) { + std::string &idPrefix = get(); + auto &idNumberArr = get(); + if (idNumberArr.size() != 2) + return {Result::Status::kError, "ID number malformed"}; + if (idPrefix.size() == 0 && idNumberArr[0] == 0) + return {Result::Status::kError, "No ID supplied"}; + + mStream.clear(); + mStream.seekp(0); + + mStream << idPrefix; + + if (idNumberArr[0] > 0) + mStream << idNumberArr[1]; + + auto buf = get(); + return datasetPtr->setPoint(mStream.str(), buf); + } else + return {Result::Status::kError, "No DataSet"}; } - - private: - index mCounter{0}; + +private: + std::ostringstream mStream; }; using NRTThreadedDataSetWriter = diff --git a/release-packaging/Classes/FluidDataSetWr.sc b/release-packaging/Classes/FluidDataSetWr.sc index db4f79d..c72c12d 100644 --- a/release-packaging/Classes/FluidDataSetWr.sc +++ b/release-packaging/Classes/FluidDataSetWr.sc @@ -1,10 +1,12 @@ FluidDataSetWr : FluidBufProcessor { - *kr { |dataset,labelPrefix = "", labelOffset = 0,buf, trig=1, blocking = 1| + *kr { |dataset,idPrefix = "", idNumber = 0,buf, trig=1, blocking = 1| var args; - buf ?? {"No input buffer provided".error}; - labelPrefix = labelPrefix !? {[labelPrefix.asString.size] ++ labelPrefix.asString.ascii} ?? {0}; + buf ?? {(this.class.name ++ ": No input buffer provided").error}; + + idNumber = idNumber !? {[2,1,idNumber.asInteger.asUGenInput]} ?? {[2,0,0]}; + idPrefix = idPrefix !? {[idPrefix.asString.size] ++ idPrefix.asString.ascii} ?? {0}; - args = [-1] ++ dataset.asUGenInput ++labelPrefix ++ labelOffset.asInteger.asUGenInput ++buf.asUGenInput ++ trig ++ blocking; + args = [-1] ++ dataset.asUGenInput ++idPrefix ++ idNumber ++ buf.asUGenInput ++ trig ++ blocking; ^FluidProxyUgen.kr(\FluidDataSetWrTrigger,*args); } diff --git a/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp b/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp index e797c52..ad7dcc3 100644 --- a/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp +++ b/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp @@ -4,9 +4,9 @@ categories:: FluidManipulation related:: Classes/FLuidDataSet DESCRIPTION:: -A UGen that adds labelled points to a link::Classes/FluidDataSet:: +A UGen that adds labelled points to a link::Classes/FluidDataSet:: Internally, this calls code::setPoint::, so IDs that already exist will be overwritten, and new IDs will be added. The actual work is done on the server's command queue, rather than the real-thread. -By default the object generates a numerical index that gets used for the point labels. This index starts counting from link::#offset#labelOffset:: and increments each time the Ugen is retriggered with a zero to non-zero transition. The label is then concatenated with the code::labelPrefix:: symbol, which is fixed at instantiation. In this way, one can make custom, incrementing labels, e.g. +By default the object generates a numerical index that gets used for the point labels. This index starts counting from link::#offset#labelOffset:: and increments each time the Ugen is re-triggered with a zero to non-zero transition. The label is then concatenated with the code::idPrefix:: symbol, which is fixed at instantiation. In this way, one can make custom, incrementing labels, e.g. code:: FluidDataSetWr.kr(~somedataset,"my_data",0,~somebuffer,trig) @@ -14,7 +14,7 @@ FluidDataSetWr.kr(~somedataset,"my_data",0,~somebuffer,trig) would add points like code::my_data0, mydata1, mydata2...:: if successively retriggered. -Alternatively, for one shot use you may not want a numerical suffix at all. Setting code::indexLabel:: < 0 will bypass this and use only the labelPrefix. As such, any retriggering will result in a complaint from the link::Classes/FluidDataSet:: that the requested label is already present. +Alternatively, for one shot use you may not want a numerical suffix at all. Setting code::idNumber:: to code:: nil:: will bypass this and use only the code::idPrefix:: string. CLASSMETHODS:: @@ -26,12 +26,12 @@ The equivalent of calling link::Classes/FluidDataSet#-addPoint::, but within a l ARGUMENT:: dataset An instance of link::Classes/FluidDataSet:: or an instance's name. -ARGUMENT:: labelPrefix +ARGUMENT:: idPrefix A string or symbol with a prefix for generated labels -ARGUMENT:: labelOffset +ARGUMENT:: idNumber ANCHOR::offset:: -An integer with the offset to start labeling from. If the UGen is run in a server-side loop (i.e. repeatedly retriggered), the generated labels will count upwards from this offset. If < 0, then no numerical index will be applied to the generated label (i.e. only the labelPrefix is used). +An integer with the offset to start labeling from. If the UGen is run in a server-side loop (i.e. repeatedly re-triggered), the generated labels will count upwards from this offset. If < 0, then no numerical index will be applied to the generated label (i.e. only the labelPrefix is used). ARGUMENT:: buf The link::Classes/Buffer:: containing the data point. @@ -40,6 +40,10 @@ ARGUMENT:: trig A kr trigger signal +ARGUMENT:: blocking + +If 0 then the job will run in its own thread (not reccomended for this object) + EXAMPLES:: code:: @@ -48,13 +52,24 @@ s.reboot; ~ds = FluidDataSet(s); ) +//Write a 100 points whose values increase ( -{ +~ds.clear; +OSCFunc({ + "FluidDataSetWr help: all points written".postln; + ~ds.print +},'/datasetwrdone').oneShot; + +{ |n| var b = LocalBuf.newFrom([0,1,2,3]); - FreeSelfWhenDone.kr(FluidDataSetWr.kr(~ds,"help_data_point",buf:b)); -}.play(s); + var trig = Impulse.kr(ControlRate.ir / 2); + var idx = Stepper.kr(trig,min:0,max:n); + 4.collect{|i| BufWr.kr([(4 * idx) + i],b,i)}; + FluidDataSetWr.kr(~ds,idNumber:idx,buf:b,trig:trig); + SendReply.kr(idx >= n, '/datasetwrdone'); + FreeSelf.kr(idx >= n); + +}.play(s,args:[n:100]); ) -~ds.print; - ::