It depends whether youâre okay with waiting for an answer from the server, or if you need the answer synchronously, Right Now.
// asynchronous way
(
~checkNodeID = { |id, timeout = 0.2|
var okResp, failResp;
var cond = CondVar.new;
var answer;
okResp = OSCFunc({ |msg|
answer = true;
cond.signalOne;
}, '/n_info', s.addr, argTemplate: [id]);
failResp = OSCFunc({ |msg|
if(msg[2].asString.contains(id.asString)) {
answer = false;
cond.signalOne;
};
}, '/fail', s.addr, argTemplate: ['/n_query']);
s.sendMsg(\n_query, id);
cond.waitFor(timeout, { answer.notNil });
okResp.free;
failResp.free;
answer
};
)
fork { ~checkNodeID.(1000).postln };
~checkNodeID
can be called only within a Routine. Thereâs no way around that. If youâre going to ask the server, then you have to wait for the answer. The Routine waits for the answer.
Note also that the server will post ânode not foundâ if the node isnât there. I tried to turn that off, but then it doesnât send the âfailâ message either â so youâre stuck with it. (This goes back to a general point⌠often a question like this is phrased in terms of âhow do I ask the server xyz?â but quite often, this ends up being impractical.)
If thatâs not acceptable, then the only other way is to mirror the ID on/off states in the client, all the time.
(
var activeNodes = IdentitySet.new;
OSCdef(\onResp, { |msg|
activeNodes.add(msg[1]);
}, '/n_go', s.addr); // here it's bound to a specific server though
OSCdef(\offResp, { |msg|
activeNodes.remove(msg[1]);
}, '/n_end', s.addr);
~checkNodeID = { |id|
activeNodes.includes(id)
};
)
This function, you can call in any context.
hjh