diff --git a/example_remote-server/Makefile b/example_remote-server/Makefile new file mode 100644 index 0000000..8d8e4c0 --- /dev/null +++ b/example_remote-server/Makefile @@ -0,0 +1,13 @@ +# Attempt to load a config.make file. +# If none is found, project defaults in config.project.make will be used. +ifneq ($(wildcard config.make),) + include config.make +endif + +# make sure the the OF_ROOT location is defined +ifndef OF_ROOT + OF_ROOT=$(realpath ../../..) +endif + +# call the project makefile! +include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk diff --git a/example_remote-server/addons.make b/example_remote-server/addons.make new file mode 100644 index 0000000..8e7845c --- /dev/null +++ b/example_remote-server/addons.make @@ -0,0 +1,6 @@ +ofxGui +ofxJSON +ofxNetwork +ofxOpenCv +ofxPiMapper +ofxXmlSettings diff --git a/example_remote-server/bin/data/ofxpimapper.xml b/example_remote-server/bin/data/ofxpimapper.xml new file mode 100644 index 0000000..a11fe2e --- /dev/null +++ b/example_remote-server/bin/data/ofxpimapper.xml @@ -0,0 +1,36 @@ + + + + + 640.000000000 + 50.000000000 + + + 1230.000000000 + 750.000000000 + + + 50.000000000 + 750.000000000 + + + + + 0.500000000 + 0.000000000 + + + 1.000000000 + 1.000000000 + + + 0.000000000 + 1.000000000 + + + + video + gene-nsynthesis-loop-b.mp4 + + + diff --git a/example_remote-server/bin/data/sources/videos/gene-nsynthesis-loop-b.mp4 b/example_remote-server/bin/data/sources/videos/gene-nsynthesis-loop-b.mp4 new file mode 100644 index 0000000..eba3582 --- /dev/null +++ b/example_remote-server/bin/data/sources/videos/gene-nsynthesis-loop-b.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2da7b85225116bee7e1ae5275f58cca7684c2a5d013b97bdd46955c2c418a812 +size 2045077 diff --git a/example_remote-server/config.make b/example_remote-server/config.make new file mode 100644 index 0000000..df10f64 --- /dev/null +++ b/example_remote-server/config.make @@ -0,0 +1,142 @@ +################################################################################ +# CONFIGURE PROJECT MAKEFILE (optional) +# This file is where we make project specific configurations. +################################################################################ + +################################################################################ +# OF ROOT +# The location of your root openFrameworks installation +# (default) OF_ROOT = ../../.. +################################################################################ +# OF_ROOT = ../../.. + +################################################################################ +# PROJECT ROOT +# The location of the project - a starting place for searching for files +# (default) PROJECT_ROOT = . (this directory) +# +################################################################################ +# PROJECT_ROOT = . + +################################################################################ +# PROJECT SPECIFIC CHECKS +# This is a project defined section to create internal makefile flags to +# conditionally enable or disable the addition of various features within +# this makefile. For instance, if you want to make changes based on whether +# GTK is installed, one might test that here and create a variable to check. +################################################################################ +# None + +################################################################################ +# PROJECT EXTERNAL SOURCE PATHS +# These are fully qualified paths that are not within the PROJECT_ROOT folder. +# Like source folders in the PROJECT_ROOT, these paths are subject to +# exlclusion via the PROJECT_EXLCUSIONS list. +# +# (default) PROJECT_EXTERNAL_SOURCE_PATHS = (blank) +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_EXTERNAL_SOURCE_PATHS = + +################################################################################ +# PROJECT EXCLUSIONS +# These makefiles assume that all folders in your current project directory +# and any listed in the PROJECT_EXTERNAL_SOURCH_PATHS are are valid locations +# to look for source code. The any folders or files that match any of the +# items in the PROJECT_EXCLUSIONS list below will be ignored. +# +# Each item in the PROJECT_EXCLUSIONS list will be treated as a complete +# string unless teh user adds a wildcard (%) operator to match subdirectories. +# GNU make only allows one wildcard for matching. The second wildcard (%) is +# treated literally. +# +# (default) PROJECT_EXCLUSIONS = (blank) +# +# Will automatically exclude the following: +# +# $(PROJECT_ROOT)/bin% +# $(PROJECT_ROOT)/obj% +# $(PROJECT_ROOT)/%.xcodeproj +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_EXCLUSIONS = + +################################################################################ +# PROJECT LINKER FLAGS +# These flags will be sent to the linker when compiling the executable. +# +# (default) PROJECT_LDFLAGS = -Wl,-rpath=./libs +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ + +# Currently, shared libraries that are needed are copied to the +# $(PROJECT_ROOT)/bin/libs directory. The following LDFLAGS tell the linker to +# add a runtime path to search for those shared libraries, since they aren't +# incorporated directly into the final executable application binary. +# TODO: should this be a default setting? +# PROJECT_LDFLAGS=-Wl,-rpath=./libs + +################################################################################ +# PROJECT DEFINES +# Create a space-delimited list of DEFINES. The list will be converted into +# CFLAGS with the "-D" flag later in the makefile. +# +# (default) PROJECT_DEFINES = (blank) +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_DEFINES = + +################################################################################ +# PROJECT CFLAGS +# This is a list of fully qualified CFLAGS required when compiling for this +# project. These CFLAGS will be used IN ADDITION TO the PLATFORM_CFLAGS +# defined in your platform specific core configuration files. These flags are +# presented to the compiler BEFORE the PROJECT_OPTIMIZATION_CFLAGS below. +# +# (default) PROJECT_CFLAGS = (blank) +# +# Note: Before adding PROJECT_CFLAGS, note that the PLATFORM_CFLAGS defined in +# your platform specific configuration file will be applied by default and +# further flags here may not be needed. +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_CFLAGS = + +################################################################################ +# PROJECT OPTIMIZATION CFLAGS +# These are lists of CFLAGS that are target-specific. While any flags could +# be conditionally added, they are usually limited to optimization flags. +# These flags are added BEFORE the PROJECT_CFLAGS. +# +# PROJECT_OPTIMIZATION_CFLAGS_RELEASE flags are only applied to RELEASE targets. +# +# (default) PROJECT_OPTIMIZATION_CFLAGS_RELEASE = (blank) +# +# PROJECT_OPTIMIZATION_CFLAGS_DEBUG flags are only applied to DEBUG targets. +# +# (default) PROJECT_OPTIMIZATION_CFLAGS_DEBUG = (blank) +# +# Note: Before adding PROJECT_OPTIMIZATION_CFLAGS, please note that the +# PLATFORM_OPTIMIZATION_CFLAGS defined in your platform specific configuration +# file will be applied by default and further optimization flags here may not +# be needed. +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_OPTIMIZATION_CFLAGS_RELEASE = +# PROJECT_OPTIMIZATION_CFLAGS_DEBUG = + +################################################################################ +# PROJECT COMPILERS +# Custom compilers can be set for CC and CXX +# (default) PROJECT_CXX = (blank) +# (default) PROJECT_CC = (blank) +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_CXX = +# PROJECT_CC = diff --git a/example_remote-server/src/TCPServer.cpp b/example_remote-server/src/TCPServer.cpp new file mode 100644 index 0000000..e3c5127 --- /dev/null +++ b/example_remote-server/src/TCPServer.cpp @@ -0,0 +1,93 @@ +#include "TCPServer.h" + +shared_ptr TCPServer::_instance = 0; + +shared_ptr TCPServer::instance(){ + if(_instance == 0){ + _instance = shared_ptr(new TCPServer); + } + return _instance; +} + +TCPServer::TCPServer(){ + std::cout << "TCPServer initialized" << std::endl; +} + +void TCPServer::setup(int port){ + _tcpServer.setup(port); +} + +void TCPServer::update(){ + int numClients = _tcpServer.getLastID(); + for(auto i = 0; i < numClients; ++i){ + if(_tcpServer.isClientConnected(i)){ + + // Notify application when new client connects + if(!_tcpConnections[i]){ + ofxJSONElement json; + json["ip"] = _tcpServer.getClientIP(i); + json["port"] = _tcpServer.getClientPort(i); + json["id"] = i; + json["event"] = "connected"; + + ofMessage message(json.getRawString()); + ofSendMessage(message); + + _tcpConnections[i] = true; + } + + // Receive messages + string rx = _tcpServer.receive(i); + if(rx.length() > 0){ + ofxJSONElement json; + bool ok = json.parse(rx); + + if(!ok){ + json["ip"] = _tcpServer.getClientIP(i); + json["port"] = _tcpServer.getClientPort(i); + json["id"] = i; + json["event"] = "received"; + json["data"] = rx; + } + + ofMessage message(json.getRawString()); + ofSendMessage(message); + } + }else{ + + // Notify application when client disconnects + if(_tcpConnections[i]){ + ofxJSONElement json; + json["ip"] = _tcpServer.getClientIP(i); + json["port"] = _tcpServer.getClientPort(i); + json["id"] = i; + json["event"] = "disconnected"; + + ofMessage message(json.getRawString()); + ofSendMessage(message); + + _tcpConnections[i] = false; + } + } + } +} + +void TCPServer::draw(){ + int numClients = _tcpServer.getLastID(); + int clientsConnected = 0; + for(auto i = 0; i < numClients; ++i){ + if(_tcpServer.isClientConnected(i)){ + ofSetColor(0, 255, 0); + ofPushMatrix(); + ofTranslate(10, 10); + ofDrawRectangle(clientsConnected * 20, 0, 10, 10); + ofPopMatrix(); + clientsConnected++; + } + } +} + +void TCPServer::send(int clientID, std::string message){ + _tcpServer.send(clientID, message); +} + diff --git a/example_remote-server/src/TCPServer.h b/example_remote-server/src/TCPServer.h new file mode 100644 index 0000000..a6be1c2 --- /dev/null +++ b/example_remote-server/src/TCPServer.h @@ -0,0 +1,23 @@ +#pragma once + +#include "ofMain.h" +#include "ofxNetwork.h" +#include "ofxJSONElement.h" + +class TCPServer { +public: + static shared_ptr instance(); + + void setup(int port); + void update(); + void draw(); + + void send(int clientID, std::string message); + +private: + TCPServer(); + static shared_ptr _instance; + + ofxTCPServer _tcpServer; + std::map _tcpConnections; +}; diff --git a/example_remote-server/src/main.cpp b/example_remote-server/src/main.cpp new file mode 100644 index 0000000..c696d20 --- /dev/null +++ b/example_remote-server/src/main.cpp @@ -0,0 +1,7 @@ +#include "ofMain.h" +#include "ofApp.h" + +int main(){ + ofSetupOpenGL(1280, 800, OF_WINDOW); + ofRunApp(new ofApp()); +} diff --git a/example_remote-server/src/ofApp.cpp b/example_remote-server/src/ofApp.cpp new file mode 100644 index 0000000..7532328 --- /dev/null +++ b/example_remote-server/src/ofApp.cpp @@ -0,0 +1,84 @@ +#include "ofApp.h" + +void ofApp::setup(){ + ofBackground(0); + mapper.setup(); + TCPServer::instance()->setup(9999); + +#ifdef TARGET_RASPBERRY_PI + ofSetFullscreen(true); +#endif +} + +void ofApp::update(){ + mapper.update(); + TCPServer::instance()->update(); +} + +void ofApp::draw(){ + mapper.draw(); + TCPServer::instance()->draw(); +} + +// Here is where we process messages received from TCPServer instance +void ofApp::gotMessage(ofMessage m){ + std::cout << m.message << std::endl; + + ofxJSONElement json; + bool ok = json.parse(m.message); + if(ok){ + if(json["event"].asString() == "connected"){ + // Save Mapper composition and get config as string + std::cout << "Sending mapper config" << std::endl; + mapper.saveProject(); + + ofFile file; + file.open(ofToDataPath("ofxpimapper.xml"), ofFile::ReadOnly, false); + ofBuffer buff = file.readToBuffer(); + string text = buff.getText(); + + TCPServer::instance()->send(json["id"].asInt(), text); + } + + if(json["event"].asString() == "keyPressed"){ + mapper.keyPressed(json["key"].asInt()); + } + + if(json["event"].asString() == "keyReleased"){ + mapper.keyReleased(json["key"].asInt()); + } + + if(json["event"].asString() == "mousePressed"){ + mapper.mousePressed(json["x"].asInt(), json["y"].asInt(), json["button"].asInt()); + } + + if(json["event"].asString() == "mouseReleased"){ + mapper.mouseReleased(json["x"].asInt(), json["y"].asInt(), json["button"].asInt()); + } + + if(json["event"].asString() == "mouseDragged"){ + mapper.mouseDragged(json["x"].asInt(), json["y"].asInt(), json["button"].asInt()); + } + } +} + +void ofApp::keyPressed(int key){ + mapper.keyPressed(key); +} + +void ofApp::keyReleased(int key){ + mapper.keyReleased(key); +} + +void ofApp::mousePressed(int x, int y, int button){ + mapper.mousePressed(x, y, button); +} + +void ofApp::mouseReleased(int x, int y, int button){ + mapper.mouseReleased(x, y, button); +} + +void ofApp::mouseDragged(int x, int y, int button){ + mapper.mouseDragged(x, y, button); +} + diff --git a/example_remote-server/src/ofApp.h b/example_remote-server/src/ofApp.h new file mode 100644 index 0000000..6c95a21 --- /dev/null +++ b/example_remote-server/src/ofApp.h @@ -0,0 +1,23 @@ +#pragma once + +#include "ofMain.h" +#include "TCPServer.h" +#include "ofxPiMapper.h" +#include "ofxJSONElement.h" + +class ofApp : public ofBaseApp{ +public: + void setup(); + void update(); + void draw(); + + void gotMessage(ofMessage m); + + void keyPressed(int key); + void keyReleased(int key); + void mousePressed(int x, int y, int button); + void mouseReleased(int x, int y, int button); + void mouseDragged(int x, int y, int button); + + ofxPiMapper mapper; +};