ofxPubSubOsc というoFのaddonを書いてまして, 最近やっとver0.3.0もリリースしたし, 今更ながら紹介記事を書いてみようと.
もう if(m.getAddress() == "/hoge")
って書きたくない
// int hoge, fuga, piyo;
// receiver.setup(port);
void update() {
...
ofxOscMessage m;
while(receiver.hasWaitingMessages()) {
receiver.getNextMessage(m);
if(m.getAddress() == "/hoge") {
hoge = m.getArgAsInt32(0);
}
else if(m.getAddress() == "/fuga") {
fuga = m.getArgAsInt32(0);
}
else if(m.getAddress() == "/piyo") {
piyo = m.getArgAsInt32(0);
}
...
}
...
}
こんなコード書いてますか?書いてますよね?
ofxPubSubOscを使うと
// int hoge, fuga, piyo;
void setup() {
...
ofxSubScribeOsc(port, "/hoge", hoge);
ofxSubScribeOsc(port, "/fuga", fuga);
ofxSubScribeOsc(port, "/piyo", piyo);
...
}
すっきり.
値が変更されたときに何か処理したい
// int hoge;
ofxOscMessage m;
while(receiver.hasWaitingMessages()) {
receiver.getNextMessage(m);
if(m.getAddress() == "/hoge") {
hoge = m.getArgAsInt32(0);
doHoge(hoge);
}
}
こういうときは無名関数を使って
// int hoge;
ofxSubscribeOsc(port, "/hoge", [=](int val) {
hoge = val;
doHoge(hoge);
});
OSC引数が複数ある場合
// int hoge1;
// std::string hoge2;
// bool hoge3;
if(m.getAddress() == "/hoge") {
hoge1 = m.getArgAsInt32(0);
hoge2 = m.getArgAsString(1);
hoge3 = m.getArgAsBool(2);
}
複数引数にも対応.
// int hoge1;
// std::string hoge2;
// bool hoge3;
ofxSubscribeOsc(port, "/hoge", hoge1, hoge2, hoge3);
std::vector<float>
とか
std::vector<float>
// std::vector<float> xs;
if(m.getAddress() == "/xs") {
xs.resize(m.getNumArgs());
for(std::size_t i = 0; i < xs.size(); i++) {
xs[i] = m.getArgAsFloat(i);
}
}
// std::vector<float> xs;
ofxSubscribeOsc(port, "/xs", xs);
ofVec4f
// ofVec4f v4;
if(m.getAddress() == "/vec") {
for(std::size_t i = 0; i < 4; i++) {
v4[i] = m.getArgAsFloat(i);
}
}
そのまま渡すと
// ofVec4f v4;
ofxSubscribeOsc(port, "/vec", v4);
もっと複雑な使い方
受信時に追加で処理したいときは
// int hoge1;
// std::string hoge2;
// bool hoge3;
ofxSubscribeOsc(port, "/hoge", [=](int x, std::string y, bool z) {
hoge1 = x;
hoge2 = y;
hoge3 = z;
doHogehoge();
});
もっとスマートに
// int hoge1;
// std::string hoge2;
// bool hoge3;
ofxSubscribeOsc(port, "/hoge", hoge1, hoge2, hoge3, [=]{ doHogehoge(); });
前処理もしたい
受信時に追加で処理したいときは
// int hoge1;
// std::string hoge2;
// bool hoge3;
ofxSubscribeOsc(port, "/hoge", [=](int x, std::string y, bool z) {
wilHogeHoge();
hoge1 = x;
hoge2 = y;
hoge3 = z;
doHogehoge();
});
もっとスマートに
// int hoge1;
// std::string hoge2;
// bool hoge3;
ofxSubscribeOsc(port, "/hoge", [=]{ willHogehoge(); }, hoge1, hoge2, hoge3, [=] { doHogehoge(); });
例
こんなコードが
class ofApp : public ofBaseApp {
ofxOscReceiver receiver;
ofVec3f position;
ofColor bgColor;
ofColor fgColor;
public:
void setup() {
receiver.setup(26666);
}
void update() {
while(receiver.hasWaitingMessages()) {
ofxOscMessage m;
receiver.getNextMessage(m);
std::string address = m.getAddress();
if(address == "/position") {
position.x = m.getArgAsFloat(0);
position.y = m.getArgAsFloat(1);
position.z = m.getArgAsFloat(2);
}
else if(address == "/bg_color") {
bgColor.r = m.getArgAsInt32(0);
bgColor.g = m.getArgAsInt32(1);
bgColor.b = m.getArgAsInt32(2);
}
else if(address == "/fg_color") {
fgColor.r = m.getArgAsInt32(0);
fgColor.g = m.getArgAsInt32(1);
fgColor.b = m.getArgAsInt32(2);
}
else if(address == "/bg_auto") {
bool b = m.getArgAsBool(0);
ofSetBackgroundAuto(b);
}
}
}
};
こんな感じに
class ofApp : public ofBaseApp {
ofxOscReceiver receiver;
ofVec3f position;
ofColor bgColor;
ofColor fgColor;
std::uint16_t port{26666};
public:
void setup() {
ofxSubscribeOsc(port, "/position", position);
ofxSubscribeOsc(port, "/bg_color", bgColor);
ofxSubscribeOsc(port, "/fg_color", fgColor);
ofxSubscribeOsc(port, "/bg_auto", ofSetBackgroundAuto);
}
void update() {
}
};
スマートでしょ?
飽きてきた
質問等のコメント付いたら答えます.
気が向いたら次は ofxPublishOsc
について書きます.
といってももっぱら ofxSubscribeOsc
の方がニーズがある気がするので書かないかも.