#include "ofxOscSender.h"
#include "ofUtils.h"
#include "ofParameterGroup.h"
#include "UdpSocket.h"
using namespace std;
ofxOscSender::~ofxOscSender() {
clear();
}
ofxOscSender::ofxOscSender(const ofxOscSender & mom){
copy(mom);
}
ofxOscSender& ofxOscSender::operator=(const ofxOscSender & mom){
return copy(mom);
}
ofxOscSender& ofxOscSender::copy(const ofxOscSender& other){
if(this == &other) return *this;
settings = other.settings;
if(other.sendSocket){
setup(settings);
}
return *this;
}
bool ofxOscSender::setup(const std::string &host, int port){
settings.host = host;
settings.port = port;
return setup(settings);
}
bool ofxOscSender::setup(const ofxOscSenderSettings &settings){
if(osc::UdpSocket::GetUdpBufferSize() == 0){
osc::UdpSocket::SetUdpBufferSize(65535);
}
this->settings = settings;
if(settings.host == "") {
ofLogError("ofxOscSender") << "couldn't create sender to empty host";
return false;
}
osc::UdpTransmitSocket *socket = nullptr;
try{
osc::IpEndpointName name = osc::IpEndpointName(settings.host.c_str(), settings.port);
if (!name.address){
ofLogError("ofxOscSender") << "bad host? " << settings.host;
return false;
}
socket = new osc::UdpTransmitSocket(name, settings.broadcast);
sendSocket.reset(socket);
}
catch(std::exception &e){
string what = e.what();
if(!what.empty() && what.back() == '\n') {
what = what.substr(0, what.size()-1);
}
ofLogError("ofxOscSender") << "couldn't create sender to "
<< settings.host << " on port "
<< settings.port << ": " << what;
if(socket != nullptr){
delete socket;
socket = nullptr;
}
sendSocket.reset();
return false;
}
return true;
}
void ofxOscSender::clear(){
sendSocket.reset();
}
void ofxOscSender::sendBundle(const ofxOscBundle &bundle){
if(!sendSocket){
ofLogError("ofxOscSender") << "trying to send with empty socket";
return;
}
static const int OUTPUT_BUFFER_SIZE = 327680;
char buffer[OUTPUT_BUFFER_SIZE];
osc::OutboundPacketStream p(buffer, OUTPUT_BUFFER_SIZE);
appendBundle(bundle, p);
sendSocket->Send(p.Data(), p.Size());
}
void ofxOscSender::sendMessage(const ofxOscMessage &message, bool wrapInBundle){
if(!sendSocket){
ofLogError("ofxOscSender") << "trying to send with empty socket";
return;
}
static const int OUTPUT_BUFFER_SIZE = 327680;
char buffer[OUTPUT_BUFFER_SIZE];
osc::OutboundPacketStream p(buffer, OUTPUT_BUFFER_SIZE);
if(wrapInBundle) {
p << osc::BeginBundleImmediate;
}
appendMessage(message, p);
if(wrapInBundle) {
p << osc::EndBundle;
}
sendSocket->Send(p.Data(), p.Size());
}
void ofxOscSender::sendParameter(const ofAbstractParameter ¶meter){
if(!parameter.isSerializable()) return;
if(parameter.type() == typeid(ofParameterGroup).name()){
std::string address = "/";
const std::vector<std::string> hierarchy = parameter.getGroupHierarchyNames();
for(int i = 0; i < (int)hierarchy.size()-1; i++){
address += hierarchy[i] + "/";
}
ofxOscBundle bundle;
appendParameter(bundle, parameter, address);
sendBundle(bundle);
}
else{
std::string address = "";
const std::vector<std::string> hierarchy = parameter.getGroupHierarchyNames();
for(int i = 0; i < (int)hierarchy.size()-1; i++){
address += "/" + hierarchy[i];
}
if(address.length()) {
address += "/";
}
ofxOscMessage msg;
appendParameter(msg, parameter, address);
sendMessage(msg, false);
}
}
std::string ofxOscSender::getHost() const{
return settings.host;
}
int ofxOscSender::getPort() const{
return settings.port;
}
const ofxOscSenderSettings &ofxOscSender::getSettings() const {
return settings;
}
void ofxOscSender::appendBundle(const ofxOscBundle &bundle, osc::OutboundPacketStream &p){
p << osc::BeginBundleImmediate;
for(int i = 0; i < bundle.getBundleCount(); i++){
appendBundle(bundle.getBundleAt(i), p);
}
for(int i = 0; i < bundle.getMessageCount(); i++){
appendMessage(bundle.getMessageAt(i), p);
}
p << osc::EndBundle;
}
void ofxOscSender::appendMessage(const ofxOscMessage &message, osc::OutboundPacketStream &p){
p << osc::BeginMessage(message.getAddress().c_str());
for(size_t i = 0; i < message.getNumArgs(); ++i) {
switch(message.getArgType(i)){
case OFXOSC_TYPE_INT32:
p << message.getArgAsInt32(i);
break;
case OFXOSC_TYPE_INT64:
p << (osc::int64)message.getArgAsInt64(i);
break;
case OFXOSC_TYPE_FLOAT:
p << message.getArgAsFloat(i);
break;
case OFXOSC_TYPE_DOUBLE:
p << message.getArgAsDouble(i);
break;
case OFXOSC_TYPE_STRING:
p << message.getArgAsString(i).c_str();
break;
case OFXOSC_TYPE_SYMBOL:
p << osc::Symbol(message.getArgAsString(i).c_str());
break;
case OFXOSC_TYPE_CHAR:
p << message.getArgAsChar(i);
break;
case OFXOSC_TYPE_MIDI_MESSAGE:
p << osc::MidiMessage(message.getArgAsMidiMessage(i));
break;
case OFXOSC_TYPE_TRUE: case OFXOSC_TYPE_FALSE:
p << message.getArgAsBool(i);
break;
case OFXOSC_TYPE_NONE:
p << osc::NilType();
break;
case OFXOSC_TYPE_TRIGGER:
p << osc::InfinitumType();
break;
case OFXOSC_TYPE_TIMETAG:
p << osc::TimeTag(message.getArgAsTimetag(i));
break;
case OFXOSC_TYPE_RGBA_COLOR:
p << osc::RgbaColor(message.getArgAsRgbaColor(i));
break;
case OFXOSC_TYPE_BLOB: {
ofBuffer buff = message.getArgAsBlob(i);
p << osc::Blob(buff.getData(), (unsigned long)buff.size());
break;
}
default:
ofLogError("ofxOscSender") << "appendMessage(): bad argument type "
<< message.getArgType(i) << " '" << (char) message.getArgType(i) << "'";
break;
}
}
p << osc::EndMessage;
}
void ofxOscSender::appendParameter(ofxOscBundle &_bundle, const ofAbstractParameter ¶meter, const std::string &address){
if(parameter.type() == typeid(ofParameterGroup).name()){
ofxOscBundle bundle;
const ofParameterGroup &group = static_cast<const ofParameterGroup &>(parameter);
for(std::size_t i = 0; i < group.size(); i++){
const ofAbstractParameter & p = group[i];
if(p.isSerializable()){
appendParameter(bundle, p, address+group.getEscapedName()+"/");
}
}
_bundle.addBundle(bundle);
}
else{
if(parameter.isSerializable()){
ofxOscMessage msg;
appendParameter(msg, parameter, address);
_bundle.addMessage(msg);
}
}
}
void ofxOscSender::appendParameter(ofxOscMessage &msg, const ofAbstractParameter ¶meter, const std::string &address){
msg.setAddress(address+parameter.getEscapedName());
if(parameter.type() == typeid(ofParameter<int>).name()){
msg.addIntArg(parameter.cast<int>());
}
else if(parameter.type() == typeid(ofParameter<float>).name()){
msg.addFloatArg(parameter.cast<float>());
}
else if(parameter.type() == typeid(ofParameter<double>).name()){
msg.addDoubleArg(parameter.cast<double>());
}
else if(parameter.type() == typeid(ofParameter<bool>).name()){
msg.addBoolArg(parameter.cast<bool>());
}
else{
msg.addStringArg(parameter.toString());
}
}
std::ostream& operator<<(std::ostream &os, const ofxOscSender &sender) {
os << sender.getHost() << " " << sender.getPort();
return os;
}
Comments