diff --git a/release-packaging/Classes/FluidMessageResponse.sc b/release-packaging/Classes/FluidMessageResponse.sc new file mode 100644 index 0000000..5f3782d --- /dev/null +++ b/release-packaging/Classes/FluidMessageResponse.sc @@ -0,0 +1,32 @@ +FluidMessageResponse : Object +{ + //selectors is an array of functions + //my cunning thought is that those that need extra data (e..g numbers()) can + //use partial applicaiton + *collectArgs{ |selectors,a| + var response = []; + var idx = 0; + selectors.do{ |selector| + var newThings; + # newThings,idx = selector.value(a, idx); + response = response.add(newThings); + }; + ^response + } + + *string{ |a, offset| + var split = a.find([0],offset); + var res; + if(split.isNil) {"ERROR: can't parse string from server".throw}; + ^[a.copyRange(offset,split-1).keep(split).collectAs({|x|x.asInt.asAscii},String), split + 1] + } + + *numbers{ |a, n, offset| + ^[a.copyRange(offset, offset + n),offset + n] + } + + *buffer{ |a,server,offset| + server = server ? Server.default ; + ^[Buffer.cachedBufferAt(server, a[offset]), offset + 1] + } +} \ No newline at end of file diff --git a/release-packaging/Classes/FluidMessageTest.sc b/release-packaging/Classes/FluidMessageTest.sc new file mode 100644 index 0000000..f440d37 --- /dev/null +++ b/release-packaging/Classes/FluidMessageTest.sc @@ -0,0 +1,120 @@ +FluidMessageTest : UGen { + + var server; + + *kr{ |doneAction = 0| + + ^this.multiNew('control', doneAction); + } + + testReturnStrings { |server, nodeID, action| + + server = server ? Server.default; + + server.sendMsg('/u_cmd',nodeID,this.synthIndex,'testReturnStrings'); + + OSCFunc( + { |msg| + var resp =FluidMessageResponse.collectArgs( + 4.collect{string(FluidMessageResponse,_,_)}, msg.drop(3)); + if(action.notNil){action.value(resp);}; + },'/testReturnStrings').oneShot; + + } + + testReturnNumbers{ |server, nodeID, action| + + server = server ? Server.default; + + server.sendMsg('/u_cmd',nodeID,this.synthIndex,'testReturnNumbers'); + + OSCFunc( + { |msg| + var result = FluidMessageResponse.collectArgs( + [numbers(FluidMessageResponse,_,100,_)], msg.drop(3)); + if(action.notNil){action.value(result);}; + },'/testReturnNumbers').oneShot; + } + + testReturnOneString{ |server, nodeID, action| + + server = server ? Server.default; + + server.sendMsg('/u_cmd',nodeID,this.synthIndex,'testReturnOneString'); + + OSCFunc( + { |msg| + var result = FluidMessageResponse.collectArgs( + [string(FluidMessageResponse,_,_)], msg.drop(3)); + if(action.notNil){action.value(result);}; + },'/testReturnOneString').oneShot; + } + + testReturnOneNumber{ |server, nodeID, action| + + server = server ? Server.default; + + server.sendMsg('/u_cmd',nodeID,this.synthIndex,'testReturnOneNumber'); + + OSCFunc( + { |msg| + var result = msg.drop(3); + if(action.notNil){action.value(result);}; + },'/testReturnOneNumber').oneShot; + } + + testAccessBuffer{ |server, nodeID, buf, action| + + server = server ? Server.default; + + server.sendMsg('/u_cmd',nodeID,this.synthIndex,'testAccessBuffer', buf.asUGenInput); + + OSCFunc( + { |msg| + var result = FluidMessageResponse.collectArgs([numbers(FluidMessageResponse,_,1,_)],msg.drop(3)); + if(action.notNil){action.value(result);}; + },'/testAccessBuffer').oneShot; + } + + testPassString{ |server, nodeID, str, a, b, c, d, action| + + server = server ? Server.default; + + server.sendMsg('/u_cmd',nodeID,this.synthIndex,'testPassString', str, a, b, c); + + OSCFunc( + { |msg| + if(action.notNil){action.value;}; + },'/testPassString').oneShot; + } + + + testReturnBuffer{ |server, nodeID, b, action| + + server = server ? Server.default; + + server.sendMsg('/u_cmd',nodeID,this.synthIndex,'testReturnBuffer', b.asUGenInput); + + OSCFunc( + { |msg| + var result = result = FluidMessageResponse.collectArgs([buffer(FluidMessageResponse,_,server,_)],msg.drop(3)); + if(action.notNil){action.value(result);}; + },'/testReturnBuffer').oneShot; + } + + testReturnHetero{ |server, nodeID, action| + + server = server ? Server.default; + + server.sendMsg('/u_cmd',nodeID,this.synthIndex,'testReturnHetero'); + + OSCFunc( + { |msg| + var result = result = FluidMessageResponse.collectArgs([string(FluidMessageResponse,_,_), numbers(FluidMessageResponse,_,2,_)],msg.drop(3)); + if(action.notNil){action.value(result);}; + },'/testReturnHetero').oneShot; + } + + + +} \ No newline at end of file diff --git a/release-packaging/Classes/FluidProviderTest.sc b/release-packaging/Classes/FluidProviderTest.sc new file mode 100644 index 0000000..d9589b2 --- /dev/null +++ b/release-packaging/Classes/FluidProviderTest.sc @@ -0,0 +1,56 @@ +FluidProviderTest : UGen { + +/* var <> server; + var <> nodeID; + + *new{ |server, name| + + + + }*/ + + *kr{ |name| + ^this.multiNew('control',name); + } + + *new1 { |rate, name| + var ascii = name.ascii; + ^super.new1(*[rate, ascii.size].addAll(ascii)); + } + + init { |size...chars| + //Send the number of inputs (size of provider string) as specialIndex, + //so server plugin knows what's going onnode + specialIndex = -1; + inputs = [size].addAll(chars); + } + + addPoint{|server, nodeID, args, action| + this.pr_sendMsg(server, nodeID, 'addPoint',args,action); + } + + updatePoint{|server, nodeID, args, action| + this.pr_sendMsg(server, nodeID, 'updatePoint',args,action); + } + + deletePoint{|server, nodeID, args, action| + this.pr_sendMsg(server,nodeID, 'deletePoint',args,action); + } + + pr_sendMsg { |server, nodeID, msg, args, action,parser| + + server = server ? Server.default; + + server.listSendMsg(['/u_cmd',nodeID.nodeID,this.synthIndex,msg].addAll(args)); + + OSCFunc( + { |msg| + var result = FluidMessageResponse.collectArgs(parser,msg.drop(3)); + if(action.notNil){action.value(result)}{action.value}; + },'/'++msg).oneShot; + } + + + + +} \ No newline at end of file diff --git a/release-packaging/Classes/FluidSubscriberTest.sc b/release-packaging/Classes/FluidSubscriberTest.sc new file mode 100644 index 0000000..8ea6070 --- /dev/null +++ b/release-packaging/Classes/FluidSubscriberTest.sc @@ -0,0 +1,40 @@ +FluidSubscriberTest : UGen { + + var <> providerName; + var <> nodeID; + + *kr { |provider| + ^this.multiNew('control',provider); + } + + *new1 { |rate, provider| + var ascii = provider.ascii; + ^super.new1(*[rate, ascii.size].addAll(ascii)); + } + + init { |size...chars| + //Send the number of inputs (size of provider string) as specialIndex, + //so server plugin knows what's going on + specialIndex = -1; + inputs = [size].addAll(chars); + providerName = chars.collectAs({|x|x.asInt.asAscii}, String); + } + + providerLookup { |server, nodeID, label, action| + this.pr_sendMsg(server, nodeID, 'providerLookup', label, action, + [string(FluidMessageResponse,_,_),numbers(FluidMessageResponse,_,2,_)] ); + } + + pr_sendMsg { |server, nodeID, msg, args, action,parser| + + server = server ? Server.default; + + server.listSendMsg(['/u_cmd',nodeID.nodeID,this.synthIndex,msg].addAll(args)); + + OSCFunc( + { |msg| + var result = FluidMessageResponse.collectArgs(parser,msg.drop(3)); + if(action.notNil){action.value(result)}{action.value}; + },'/'++msg).oneShot; + } +} \ No newline at end of file diff --git a/src/FluidManipulation/CMakeLists.txt b/src/FluidManipulation/CMakeLists.txt new file mode 100644 index 0000000..3693881 --- /dev/null +++ b/src/FluidManipulation/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.3) +get_filename_component(PLUGIN ${CMAKE_CURRENT_LIST_DIR} NAME_WE) +message("Configuring ${PLUGIN}") +set(FILENAME ${PLUGIN}.cpp) + +add_library( + ${PLUGIN} + MODULE + ${FILENAME} +) + +target_include_directories( + ${PLUGIN} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../../include +) + +target_link_libraries( + ${PLUGIN} PRIVATE FLUID_DECOMPOSITION +) + +include(${CMAKE_CURRENT_LIST_DIR}/../../scripts/target_post.cmake) diff --git a/src/FluidManipulation/FluidManipulation.cpp b/src/FluidManipulation/FluidManipulation.cpp new file mode 100644 index 0000000..64738d2 --- /dev/null +++ b/src/FluidManipulation/FluidManipulation.cpp @@ -0,0 +1,14 @@ + +// A tool from the FluCoMa project, funded by the European Research Council (ERC) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899) + +#include +#include + +static InterfaceTable *ft; + +PluginLoad(FluidSTFTUGen) +{ + ft = inTable; + using namespace fluid::client; + makeSCWrapper("FluidAmpSlice", ft); +} diff --git a/src/FluidSubscriberProviderTest/CMakeLists.txt b/src/FluidSubscriberProviderTest/CMakeLists.txt new file mode 100644 index 0000000..3693881 --- /dev/null +++ b/src/FluidSubscriberProviderTest/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.3) +get_filename_component(PLUGIN ${CMAKE_CURRENT_LIST_DIR} NAME_WE) +message("Configuring ${PLUGIN}") +set(FILENAME ${PLUGIN}.cpp) + +add_library( + ${PLUGIN} + MODULE + ${FILENAME} +) + +target_include_directories( + ${PLUGIN} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../../include +) + +target_link_libraries( + ${PLUGIN} PRIVATE FLUID_DECOMPOSITION +) + +include(${CMAKE_CURRENT_LIST_DIR}/../../scripts/target_post.cmake) diff --git a/src/FluidSubscriberProviderTest/FluidSubscriberProviderTest.cpp b/src/FluidSubscriberProviderTest/FluidSubscriberProviderTest.cpp new file mode 100644 index 0000000..224dadf --- /dev/null +++ b/src/FluidSubscriberProviderTest/FluidSubscriberProviderTest.cpp @@ -0,0 +1,17 @@ + +// A tool from the FluCoMa project, funded by the European Research Council (ERC) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899) + +#include +#include +#include + +static InterfaceTable *ft; + +PluginLoad(FluidSTFTUGen) +{ + ft = inTable; + using namespace fluid::client; + makeSCWrapper("FluidProviderTest", ft); + makeSCWrapper("FluidSubscriberTest", ft); + +} diff --git a/tests/TestFluiSubscriberProvider.scd b/tests/TestFluiSubscriberProvider.scd new file mode 100644 index 0000000..b8f1652 --- /dev/null +++ b/tests/TestFluiSubscriberProvider.scd @@ -0,0 +1,12 @@ + +~provider +~subscriber +a = {~subscriber = FluidSubscriberTest.kr(\bollocks)}.play +b = {~provider = FluidProviderTest.kr(\bollocks)}.play +~provider.addPoint(Server.default,b,['foo', 1,2],{'Added'.postln}) +~subscriber.providerLookup(Server.default,a,['foo'],{|msg| msg.postln}) +~provider.updatePoint(Server.default,b,['foo', 3,4],{'Upadted'.postln}) +~subscriber.providerLookup(Server.default,a,['foo'],{|msg| msg.postln}) +~provider.deletePoint(Server.default,b,['foo'],{'Deleted'.postln}) +~subscriber.providerLookup(Server.default,a,['foo'],{|msg| msg.postln}) + diff --git a/tests/TestFluidMessageTest..scd b/tests/TestFluidMessageTest..scd index 63b0218..54f4a14 100644 --- a/tests/TestFluidMessageTest..scd +++ b/tests/TestFluidMessageTest..scd @@ -8,6 +8,9 @@ b = Buffer.read(s,File.realpath(FluidMessageTest.class.filenameSymbol).dirname.w ~messageTest.testAccessBuffer(nil,a.nodeID,b,{|msg| msg.postln}); b.numFrames ~messageTest.testPassString(nil,a.nodeID,'hello, you big lovely server',1,2,3,{'testPassString Done'.postln}); +~messageTest.testReturnBuffer(nil,a.nodeID,b,{|buffer| b.numFrames.postln}); +~messageTest.testReturnHetero(nil,a.nodeID,{|x|x.postln}); +a.free // OSCFunc.trace(true) // OSCFunc.trace(false) \ No newline at end of file