Skip to content

Commit

Permalink
add ofxOscPublisher
Browse files Browse the repository at this point in the history
  • Loading branch information
2bbb committed May 11, 2015
1 parent 3d733e7 commit 1ad3de7
Show file tree
Hide file tree
Showing 3 changed files with 314 additions and 4 deletions.
32 changes: 28 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# ofxOscSubscriber
# ofxPubSubOsc

subscribe OSC message.
publish/subscribe OSC message.

## How to use?
## API

* template \<typename T\> ofxSubscribeOSC(int _port_, const string &_address_, T &value);
### ofxSubscribeOsc

* template \<typename T\> ofxSubscribeOsc(int _port_, const string &_address_, T &value);

bind value to OSC message has _address_ incoming from _port_.

Expand All @@ -17,8 +19,30 @@ unbind OSC message has _address_ incoming from _port_.

unbind all OSC messages incoming from _port_.

### ofxPublishOsc

* template \<typename T\> ofxPublishOsc(const string &_ip_, int _port_, const string &_address_, T &_value_);
* template \<typename T\> ofxPublishOsc(const string &_ip_, int _port_, const string &_address_, T (*_getter_)());
* template \<typename T, typename U\> ofxPublishOsc(const string &_ip_, int _port_, const string &_address_, U \*_that_, T (U::*_getter_)());

publish _value_ / _getter()_ / _that.*getter()_ to OSC message has _address_ to _ip:port_.


* ofxUnpublishOSC(int _port_, const string &_address_);

unpublish OSC message has _address_ is send to _ip:port_.

* ofxUnpublishOSC(int _port_);

unpublish all OSC messages is send to _ip:port_.

## Update history

### 2015/05/11 ver 0.02 release

* rename from ofxOscSubscriber
* add ofxOscPublisher

### 2015/05/09 ver 0.01 release

## License
Expand Down
275 changes: 275 additions & 0 deletions src/ofxOscPublisher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
//
// ofxOscPublisher.h
//
// Created by ISHII 2bit on 2015/05/11.
//
//

#pragma once

#include "ofMain.h"
#include "ofxOsc.h"

namespace ofx {
namespace {
template <typename T>
struct add_reference_if_non_arithmetic {
typedef T& type;
};

#define define_add_reference_if_non_arithmetic(T) \
template <> \
struct add_reference_if_non_arithmetic<T> { \
typedef T type; \
};
define_add_reference_if_non_arithmetic(bool);
define_add_reference_if_non_arithmetic(short);
define_add_reference_if_non_arithmetic(unsigned short);
define_add_reference_if_non_arithmetic(int);
define_add_reference_if_non_arithmetic(unsigned int);
define_add_reference_if_non_arithmetic(long);
define_add_reference_if_non_arithmetic(unsigned long);
define_add_reference_if_non_arithmetic(float);
define_add_reference_if_non_arithmetic(double);
#undef define_add_reference_if_non_arithmetic
#define TypeRef(T) typename add_reference_if_non_arithmetic<T>::type
}
class OscPublisher {
struct AbstractParameter {
virtual void send(ofxOscSender &sender, const string &address) {}
};

struct SetImplementation {
protected:
#define define_set_int(type) inline void set(ofxOscMessage &m, type v) const { m.addIntArg(v); }
define_set_int(bool);
define_set_int(short);
define_set_int(unsigned short);
define_set_int(int);
define_set_int(unsigned int);
#undef define_set_int
#define define_set_int64(type) inline void set(ofxOscMessage &m, type v) const { m.addInt64Arg(v); }
define_set_int64(long);
define_set_int64(unsigned long);
#undef define_set_int64
#define define_set_float(type) inline void set(ofxOscMessage &m, type v) const { m.addFloatArg(v); }
define_set_float(float);
define_set_float(double);
#undef define_set_float
inline void set(ofxOscMessage &m, const string &v) const { m.addStringArg(v); }
template <typename PixType>
inline void set(ofxOscMessage &m, const ofColor_<PixType> &v) const { setVec<4>(m, v); }
inline void set(ofxOscMessage &m, const ofVec2f &v) const { setVec<2>(m, v); }
inline void set(ofxOscMessage &m, const ofVec3f &v) const { setVec<3>(m, v); }
inline void set(ofxOscMessage &m, const ofVec4f &v) const { setVec<4>(m, v); }

template <size_t n, typename T>
inline void setVec(ofxOscMessage &m, const T &v) const {
for(int i = 0; i < n; i++) { set(m, v[i]); }
}

inline void set(ofxOscMessage &m, const ofRectangle &v) const {
set(m, v.x);
set(m, v.y);
set(m, v.width);
set(m, v.height);
}

template <typename U, size_t size>
inline void set(ofxOscMessage &m, const U v[size]) const {
for(int i = 0; i < size; i++) { set(m, v[i]); }
}

template <typename U>
inline void set(ofxOscMessage &m, const vector<U> &v) const {
for(int i = 0; i < v.size(); i++) { set(m, v[i]); }
}
};

template <typename T, bool isCheckValue>
struct Parameter : AbstractParameter, SetImplementation {
Parameter(T &t) : t(t) {}
virtual void send(ofxOscSender &sender, const string &address) {
ofxOscMessage m;
m.setAddress(address);
set(m, get());
sender.sendMessage(m);
}

protected:
virtual TypeRef(T) get() { return t; }
T &t;
};

template <typename T>
struct Parameter<T, true> : AbstractParameter, SetImplementation {
Parameter(T &t) : t(t), old(t) {}
virtual void send(ofxOscSender &sender, const string &address) {
if(!isChanged()) return;
ofxOscMessage m;
m.setAddress(address);
set(m, get());
sender.sendMessage(m);
}

protected:
inline bool isChanged() {
if(old != get()) {
old = get();
return true;
} else {
return false;
}
}

virtual TypeRef(T) get() { return t; }
protected:
T &t;
T old;
};

template <typename T, bool isCheckValue>
struct GetterFunctionParameter : Parameter<T, isCheckValue> {
typedef T (*GetterFunction)();
GetterFunctionParameter(GetterFunction getter) : Parameter<T, isCheckValue>(dummy), getter(getter) {}

protected:
virtual TypeRef(T) get() { return getter(); }
private:
GetterFunction getter;
T dummy;
};

template <typename T, typename U, bool isCheckValue>
struct GetterParameter : Parameter<T, isCheckValue> {
typedef T (U::*Getter)();
GetterParameter(U *that, Getter getter) : getter(getter), that(*that) {}
GetterParameter(U &that, Getter getter) : getter(getter), that(that) {}

protected:
virtual TypeRef(T) get() { return that.*getter(); }
private:
Getter getter;
U &that;
};

typedef shared_ptr<AbstractParameter> ParameterRef;
typedef shared_ptr<ofxOscSender> OscSenderRef;
typedef pair<string, int> SenderKey;
typedef map<string, ParameterRef> Targets;
typedef map<SenderKey, pair<OscSenderRef, Targets> > TargetsMap;

public:
static OscPublisher &getSharedInstance() {
return *(sharedInstance ?: sharedInstance = new OscPublisher);
}

inline void publish(const string &ip, int port, const string &address, ParameterRef ref) {
SenderKey key(ip, port);
if(!isPublished(key)) {
ofxOscSender *sender = new ofxOscSender;
sender->setup(ip, port);
targetsMap.insert(make_pair(key, make_pair(OscSenderRef(sender), Targets())));
}
targetsMap[key].second.insert(make_pair(address, ref));
}

template <typename T>
void publish(const string &ip, int port, const string &address, const T &value, bool whenValueIsChanged = false) {
ParameterRef p;
if(whenValueIsChanged) p = ParameterRef(new Parameter<T, true>(value));
else p = ParameterRef(new Parameter<T, false>(value));
publish(ip, port, address, p);
}

template <typename T>
void publish(const string &ip, int port, const string &address, T (*getter)(), bool whenValueIsChanged = false) {
ParameterRef p;
if(whenValueIsChanged) p = ParameterRef(new GetterFunctionParameter<T, true>(getter));
else p = ParameterRef(new GetterFunctionParameter<T, false>(getter));
publish(ip, port, address, p);
}

template <typename T, typename U>
void publish(const string &ip, int port, const string &address, U *that, T (U::*getter)(), bool whenValueIsChanged = false) {
ParameterRef p;
if(whenValueIsChanged) p = ParameterRef(new GetterParameter<T, U, true>(that, getter));
else p = ParameterRef(new GetterParameter<T, U, false>(that, getter));
publish(ip, port, address, p);
}

template <typename T, typename U>
void publish(const string &ip, int port, const string &address, U &that, T (U::*getter)(), bool whenValueIsChanged = false) {
ParameterRef p;
if(whenValueIsChanged) p = ParameterRef(new GetterParameter<T, U, true>(that, getter));
else p = ParameterRef(new GetterParameter<T, U, false>(that, getter));
publish(ip, port, address, p);
}

void unsubscribe(const string &ip, int port, const string &address) {
SenderKey key(ip, port);
if(targetsMap.find(key) == targetsMap.end()) return;
targetsMap[key].second.erase(address);
}

void unsubscribe(const string &ip, int port) {
SenderKey key(ip, port);
targetsMap.erase(key);
}

inline bool isPublished(const string &ip, int port) const {
return isPublished(SenderKey(ip, port));
}

inline bool isPublished(const SenderKey &key) const {
return targetsMap.find(key) != targetsMap.end();
}

inline bool isPublished(const string &ip, int port, const string &address) const {
SenderKey key(ip, port);
return isPublished(key) && (targetsMap.at(key).second.find(address) != targetsMap.at(key).second.end());
}

private:
void update(ofEventArgs &args) {
for(TargetsMap::iterator _ = targetsMap.begin(); _ != targetsMap.end(); _++) {
Targets &targets = _->second.second;
ofxOscSender *sender = _->second.first.get();
for(Targets::iterator it = targets.begin(); it != targets.end(); it++) {
it->second->send(*sender, it->first);
}
}
}
OscPublisher() {
ofAddListener(ofEvents().update, this, &OscPublisher::update, OF_EVENT_ORDER_BEFORE_APP);
}
virtual ~OscPublisher() {
ofRemoveListener(ofEvents().update, this, &OscPublisher::update, OF_EVENT_ORDER_BEFORE_APP);
}
TargetsMap targetsMap;
static OscPublisher *sharedInstance;
};
OscPublisher *OscPublisher::sharedInstance = NULL;
};

typedef ofx::OscPublisher ofxOscPublisher;

template <typename T>
void ofxPublishOsc(const string &ip, int port, const string &address, const T &value, bool whenValueIsChanged = false) {
ofxOscPublisher::getSharedInstance().publish(ip, port, address, value, whenValueIsChanged);
}

template <typename T>
void ofxPublishOsc(const string &ip, int port, const string &address, T (*getter)(), bool whenValueIsChanged = false) {
ofxOscPublisher::getSharedInstance().publish(ip, port, address, getter, whenValueIsChanged);
}

template <typename T, typename U>
void ofxPublishOsc(const string &ip, int port, const string &address, U *that, T (U::*getter)(), bool whenValueIsChanged = false) {
ofxOscPublisher::getSharedInstance().publish(ip, port, address, that, getter, whenValueIsChanged);
}

template <typename T, typename U>
void ofxPublishOsc(const string &ip, int port, const string &address, U &that, T (U::*getter)(), bool whenValueIsChanged = false) {
ofxOscPublisher::getSharedInstance().publish(ip, port, address, that, getter, whenValueIsChanged);
}
11 changes: 11 additions & 0 deletions src/ofxPubSubOsc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//
// ofxPubSubOsc.h
//
// Created by ISHII 2bit on 2015/05/11.
//
//

#pragma once

#include "ofxOscPublisher.h"
#include "ofxOscSubscriber.h"

0 comments on commit 1ad3de7

Please sign in to comment.