This implements an OSC client to a DataNetwork, so that an external SuperCollider client can also be part of the network.
This class is a subclass of SWDataNetwork, so the methods used in that class can be used in this class as well. In some cases methods have an additional argument, which only need to be set, when called internally, so the user interface is the same as when using SWDataNetwork. Access to nodes, slots and their data is just the same as for a local network.
There are some additional methods to send out OSC messages, or for internal use.
A DataNode, or a node, is a collection of data streams which somehow belong together.
For example, this can be representing:
An expected Node is a DataNode that is prepared to be added to the network, but may not be present yet.
A DataSlot, or a slot, is one datastream. So corresponding to the examples of nodes above a slot would represent:
A client: the programming environment of one collaborator hooked up to the network. E.g. Joe, using PureData, or Marije, using SuperCollider, or Vincent, using Processing, or Brett, using Max/MSP.
Subscription: a client can subscribe to a node to receive its data, or subscribe to a single slot of a node. These are called the client's subscriptions.
Setter: a client can provide data to the network by creating a DataNode. The client then becomes the "setter" of the node. Other clients can not set data to the same node.
// create a network client: y = SWDataNetworkClient.new( "192.168.0.104", "myname" ); /* The first argument is the IP address of the datanetwork host, this address is shown in the basic GUI on the host in the lower right corner. The second argument "myname" is the name by which you (as a client) will be identified in the network, and should be unique among all clients (all collaborators in the project). It is used to remember your subscriptions and "setters" when you reconnect to the host, e.g. when you restart supercollider (recompile the library) and re-execute the code. The client will find the port of the host automatically, and register. If the host goes down, the client will search for the host, and react to an announce message from the host to reconnect. The client will automatically unregister, if you recompile the language, or quit SuperCollider. */ //------------ Querying: /* You can make queries about which nodes and which slots are present in the network. After you are registered, you will automatically receive info messages on any new nodes and slots */ // query which nodes are present; this sends a message to the host: y.queryNodes; // the result will print out a lot of informational messages. // to see which nodes are present (local check, // not sending a message to the host): y.nodes; // query which nodes are expected, this sends a message to the host: y.queryExpected; // to see which nodes are expected (local check, not sending // a message to the host: y.expectedNodes; // query which slots are present, this sends a message to the host: y.querySlots; // query which other clients are present (sending message to host): y.queryClients; // query to which nodes you are subscribed (sending message to host): y.querySubscriptions; // query of which nodes you are the setter (sending message to host): y.querySetters; // perform all of the queries (sending message to host): y.queryAll; //------------ Subscribing to a node: // subscribe to node 101, by number: y.subscribeNode( 101 ); // subscribe to node 102 by passing in an instance of SWDataNode as an argument: y.subscribeNode( y.nodes[102] ); // a lot of the interaction with the DataNetwork can also be // done through a graphical user interface: y.makeGui; // -------- working with the data node: // get a reference to a DataNode in a variable: a = y.nodes[102]; // if the node has a label, you acces it by its label: a = y[\minibee102]; // access the values of all slots of the node: a.value; ( SynthDef(\swexample,{ |out=0,amp=0.1,freq=400| Out.ar( out, SinOsc.ar( freq, 0, amp ) ); }).send(s) ) // use it at synth instantiation: b = Synth.new( \swexample, [\amp,a.value ] ); // set it again: b.set( \amp, a.value ); // free the synth b.free; // instead of setting it manually each time, you can assign // an action to the data node to do this automatically: b = Synth.new( \swexample, [\amp,a.value ] ); a.action= { |data| b.set( \amp, data )}; // another method is to put the data automatically on a bus, // and grab the data from there: // reset the action: a.action = {}; // create a bus: a.createBus(s); // map the amplitude of b to the bus: b.map( \amp, a.bus ); b.free; // alternatively, you can use In.kr in your synthdef to read // from the bus: ( SynthDef(\swexampleBus,{ |out=0,ampbus=0,freq=400| Out.ar( out, SinOsc.ar( freq, 0, In.kr( ampbus, 1 ) ) ); }).send(s) ) b = Synth.new( \swexampleBus, [\ampbus,a.bus ] ); b.free; // -------- working with a single slot of a data node: // DataNodes can have multiple channels of data, so the above // approach is mostly useful for multichannel control of data. // You can also work with a single slot of a node, and control a synth: // get a reference to a DataSlot in a variable: a = y.nodes[102].slots[0]; // if the slot has a label, you acces it by its label: a = y[\minibee102_slot0]; // access the value of the slot: a.value; ( SynthDef(\swexample,{ |out=0,amp=0.1,freq=400| Out.ar( out, SinOsc.ar( freq, 0, amp ) ); }).send(s) ) // use it at synth instantiation: b = Synth.new( \swexample, [\amp,a.value ] ); // set it again: b.set( \amp, a.value ); // free the synth b.free; // instead of setting it manually each time, you can assign // an action to the data node to do this automatically: b = Synth.new( \swexample, [\amp,a.value ] ); a.action= { |data| b.set( \amp, data )}; // another method is to put the data automatically on a bus, // and grab the data from there: // reset the action: a.action = {}; // create a bus: a.createBus(s); // map the amplitude of b to the bus: b.map( \amp, a.bus ); b.free; // alternatively, you can use In.kr in your synthdef: ( SynthDef(\swexampleBus,{ |out=0,ampbus=0,freq=400| Out.ar( out, SinOsc.ar( freq, 0, In.kr( ampbus, 1 ) ) ); }).send(s) ) b = Synth.new( \swexampleBus, [\ampbus,a.bus ] ); b.free;