Browse Source

Merge branch 'feature-mediaServer' into develop

Conflicts:
	src/UserInterface/RadioList.cpp
master
Krisjanis Rijnieks 11 years ago
parent
commit
064d729f34
  1. 76
      addon_config.mk
  2. 4
      example/addons.make
  3. BIN
      example/bin/data/sources/videos/test.mov
  4. 15
      example/src/ofApp.cpp
  5. 5
      example/src/ofApp.h
  6. 46
      src/MediaServer/DirectoryWatcher.cpp
  7. 144
      src/MediaServer/DirectoryWatcher.h
  8. 300
      src/MediaServer/MediaServer.cpp
  9. 91
      src/MediaServer/MediaServer.h
  10. 59
      src/Sources/BaseSource.cpp
  11. 36
      src/Sources/BaseSource.h
  12. 39
      src/Sources/ImageSource.cpp
  13. 18
      src/Sources/ImageSource.h
  14. 46
      src/Sources/SourceType.h
  15. 74
      src/Sources/VideoSource.cpp
  16. 48
      src/Sources/VideoSource.h
  17. 121
      src/SourcesEditor.cpp
  18. 40
      src/SourcesEditor.h
  19. 200
      src/SurfaceManager.cpp
  20. 17
      src/SurfaceManager.h
  21. 11
      src/SurfaceManagerGui.cpp
  22. 2
      src/SurfaceManagerGui.h
  23. 10
      src/SurfaceType.h
  24. 42
      src/Surfaces/BaseSurface.cpp
  25. 21
      src/Surfaces/BaseSurface.h
  26. 17
      src/Surfaces/QuadSurface.cpp
  27. 2
      src/Surfaces/QuadSurface.h
  28. 22
      src/Surfaces/TriangleSurface.cpp
  29. 2
      src/Surfaces/TriangleSurface.h
  30. 0
      src/UserInterface/BaseJoint.cpp
  31. 0
      src/UserInterface/BaseJoint.h
  32. 0
      src/UserInterface/CircleJoint.cpp
  33. 0
      src/UserInterface/CircleJoint.h
  34. 0
      src/UserInterface/EditorType.h
  35. 0
      src/UserInterface/GuiMode.h
  36. 0
      src/UserInterface/ProjectionEditor.cpp
  37. 0
      src/UserInterface/ProjectionEditor.h
  38. 52
      src/UserInterface/RadioList.cpp
  39. 12
      src/UserInterface/RadioList.h
  40. 271
      src/UserInterface/SourcesEditor.cpp
  41. 73
      src/UserInterface/SourcesEditor.h
  42. 12
      src/UserInterface/TextureEditor.cpp
  43. 0
      src/UserInterface/TextureEditor.h
  44. 4
      src/ofxPiMapper.h

76
addon_config.mk

@ -0,0 +1,76 @@
# All variables and this file are optional, if they are not present the PG and the
# makefiles will try to parse the correct values from the file system.
#
# Variables that specify exclusions can use % as a wildcard to specify that anything in
# that position will match. A partial path can also be specified to, for example, exclude
# a whole folder from the parsed paths from the file system
#
# Variables can be specified using = or +=
# = will clear the contents of that variable both specified from the file or the ones parsed
# from the file system
# += will add the values to the previous ones in the file or the ones parsed from the file
# system
#
# The PG can be used to detect errors in this file, just create a new project with this addon
# and the PG will write to the console the kind of error and in which line it is
meta:
ADDON_NAME = ofxPiMapper
ADDON_DESCRIPTION = Projection Mapping Addon optimized for the Raspberry Pi
ADDON_AUTHOR = kr15h aspeteRakete
ADDON_TAGS = "Raspberry Pi" "Projection Mapping"
ADDON_URL = http://github.com/kr15h/ofxPiMapper
common:
# dependencies with other addons, a list of them separated by spaces
# or use += in several lines
ADDON_DEPENDENCIES = ofxIO ofxXmlSettings ofxGui
# include search paths, this will be usually parsed from the file system
# but if the addon or addon libraries need special search paths they can be
# specified here separated by spaces or one per line using +=
# ADDON_INCLUDES =
# any special flag that should be passed to the compiler when using this
# addon
# ADDON_CFLAGS =
# any special flag that should be passed to the linker when using this
# addon, also used for system libraries with -lname
# ADDON_LDFLAGS =
# linux only, any library that should be included in the project using
# pkg-config
# ADDON_PKG_CONFIG_LIBRARIES =
# osx/iOS only, any framework that should be included in the project
# ADDON_FRAMEWORKS =
# source files, these will be usually parsed from the file system looking
# in the src folders in libs and the root of the addon. if your addon needs
# to include files in different places or a different set of files per platform
# they can be specified here
# ADDON_SOURCES =
# some addons need resources to be copied to the bin/data folder of the project
# specify here any files that need to be copied, you can use wildcards like * and ?
# ADDON_DATA =
# when parsing the file system looking for libraries exclude this for all or
# a specific platform
# ADDON_LIBS_EXCLUDE =
linux64:
# binary libraries, these will be usually parsed from the file system but some
# libraries need to passed to the linker in a specific order
ADDON_LIBS =
linux:
ADDON_LIBS =
win_cb:
ADDON_LIBS =
linuxarmv6l:
ADDON_LIBS =
linuxarmv7l:
ADDON_LIBS =
android/armeabi:
ADDON_LIBS =

4
example/addons.make

@ -1,3 +1,5 @@
ofxPiMapper
ofxGui
ofxIO
ofxXmlSettings
ofxGui
ofxOMXPlayer

BIN
example/bin/data/sources/videos/test.mov

Binary file not shown.

15
example/src/ofApp.cpp

@ -2,6 +2,12 @@
void ofApp::setup() {
bShowInfo = false;
// Pass pointers to our media server instance to both:
// surface manager and it's gui, only then we will be able to
// load surface data from xml settings files
surfaceManager.setMediaServer(&mediaServer);
gui.setMediaServer(&mediaServer);
// check if the surfaces.xml file is there
// if not - load defaultSurfaces.xml
@ -17,7 +23,8 @@ void ofApp::setup() {
// Create FBO
fbo = new ofFbo();
fbo->allocate(500, 500);
setFboAsTexture();
fboSource = new ofx::piMapper::BaseSource(&fbo->getTextureReference());
setFboAsSource();
// Genereate rects
int numRects = 20; // change this to add more or less rects
@ -114,7 +121,7 @@ void ofApp::keyPressed(int key) {
surfaceManager.saveXmlSettings("surfaces.xml");
break;
case 'a':
setFboAsTexture();
setFboAsSource();
break;
case OF_KEY_BACKSPACE:
surfaceManager.removeSelectedSurface();
@ -178,6 +185,6 @@ void ofApp::addSurface() {
surfaceManager.selectSurface(surfaceManager.size() - 1);
}
void ofApp::setFboAsTexture() {
surfaceManager.getSurface(0)->setTexture(&fbo->getTextureReference());
void ofApp::setFboAsSource() {
surfaceManager.getSurface(0)->setSource(fboSource);
}

5
example/src/ofApp.h

@ -2,6 +2,7 @@
#include "ofMain.h"
#include "ofxPiMapper.h"
#include "BaseSource.h"
class ofApp : public ofBaseApp {
public:
@ -15,13 +16,15 @@ class ofApp : public ofBaseApp {
void addRandomSurface();
void addQuadSurface();
void addSurface();
void setFboAsTexture();
void setFboAsSource();
ofImage image;
ofx::piMapper::MediaServer mediaServer;
ofx::piMapper::SurfaceManager surfaceManager;
ofx::piMapper::SurfaceManagerGui gui;
bool bShowInfo;
ofFbo* fbo;
ofx::piMapper::BaseSource* fboSource;
vector<ofRectangle> rects;
vector<float> rectSpeeds;
};

46
src/MediaServer/DirectoryWatcher.cpp

@ -0,0 +1,46 @@
//
// DirectoryWatcher.cpp
// example
//
// Created by felix on 23.09.14.
//
//
#include "DirectoryWatcher.h"
namespace ofx {
namespace piMapper {
DirectoryWatcher::DirectoryWatcher(std::string path, int watcherMediaType) {
mediaType = watcherMediaType;
// Decide what filter we need depending on media type
if (mediaType == SourceType::SOURCE_TYPE_VIDEO) {
filter = new VideoPathFilter();
} else if (mediaType == SourceType::SOURCE_TYPE_IMAGE) {
filter = new ImagePathFilter();
} else {
ofLogFatalError("DirectoryWatcher::DirectoryWatcher", "Unkonwn media type");
std::exit(EXIT_FAILURE);
}
dirWatcher.registerAllEvents(this);
// For some reason the filters are not working,
// we leave just the path here and do the filter logic in the listeners
dirWatcher.addPath(path);
// Initial directory listing. Fill the file paths vector.
IO::DirectoryUtils::list(path, filePaths, true, filter);
}
DirectoryWatcher::~DirectoryWatcher() {
delete filter;
filter = NULL;
}
std::vector<std::string>& DirectoryWatcher::getFilePaths() {
return filePaths;
}
int DirectoryWatcher::getMediaType() {
return mediaType;
}
} // namespace piMapper
} // namespace ofx

144
src/MediaServer/DirectoryWatcher.h

@ -0,0 +1,144 @@
//
// DirectoryWatcher.h
// example
//
// Created by felix on 23.09.14.
//
//
#pragma once
#include "ofMain.h"
#include "ofxIO.h"
#include "SourceType.h"
namespace ofx {
namespace piMapper {
class BasePathFilter : public ofx::IO::AbstractPathFilter {
public:
BasePathFilter() {};
virtual ~BasePathFilter() {};
virtual bool accept(const Poco::Path& path) const {};
};
class VideoPathFilter : public BasePathFilter {
public:
VideoPathFilter() {};
virtual ~VideoPathFilter() {};
bool accept(const Poco::Path& path) const {
return !Poco::File(path).isHidden() &&
(ofIsStringInString(path.toString(), ".mp4") ||
ofIsStringInString(path.toString(), ".h264")||
ofIsStringInString(path.toString(), ".mov") ||
ofIsStringInString(path.toString(), ".avi") ||
ofIsStringInString(path.toString(), ".mpeg"));
}
};
class ImagePathFilter : public BasePathFilter {
public:
ImagePathFilter() {};
virtual ~ImagePathFilter() {};
bool accept(const Poco::Path& path) const {
return !Poco::File(path).isHidden() &&
(ofIsStringInString(path.toString(), ".png") ||
ofIsStringInString(path.toString(), ".jpg") ||
ofIsStringInString(path.toString(), ".jpeg"));
}
};
class DirectoryWatcher {
public:
DirectoryWatcher(std::string path, int watcherMediaType);
~DirectoryWatcher();
// TODO make useful stuff with onDirectoryWatcher*
void onDirectoryWatcherItemAdded(
const ofx::IO::DirectoryWatcherManager::DirectoryEvent& evt) {
string path = evt.item.path();
Poco::Path pocoPath = Poco::Path(path);
if (!filter->accept(pocoPath)) {
return;
}
filePaths.push_back(path);
ofNotifyEvent(onItemAdded, path, this);
}
void onDirectoryWatcherItemRemoved(
const ofx::IO::DirectoryWatcherManager::DirectoryEvent& evt) {
string path = evt.item.path();
Poco::Path pocoPath = Poco::Path(path);
if (!filter->accept(pocoPath)) {
return;
}
// Remove path from vector
for (int i = 0; i < filePaths.size(); i++) {
if (path == filePaths[i]) {
filePaths.erase(filePaths.begin() + i);
break;
}
}
ofNotifyEvent(onItemRemoved, path, this);
}
void onDirectoryWatcherItemModified(
const ofx::IO::DirectoryWatcherManager::DirectoryEvent& evt) {
string path = evt.item.path();
Poco::Path pocoPath = Poco::Path(path);
if (!filter->accept(pocoPath)) {
return;
}
ofNotifyEvent(onItemModified, path, this);
}
void onDirectoryWatcherItemMovedFrom(
const ofx::IO::DirectoryWatcherManager::DirectoryEvent& evt) {
string path = evt.item.path();
Poco::Path pocoPath = Poco::Path(path);
if (!filter->accept(pocoPath)) {
return;
}
ofLogNotice("ofApp::onDirectoryWatcherItemMovedFrom")
<< "Moved From: " << path;
ofNotifyEvent(onItemMovedFrom, path, this);
}
void onDirectoryWatcherItemMovedTo(
const ofx::IO::DirectoryWatcherManager::DirectoryEvent& evt) {
string path = evt.item.path();
Poco::Path pocoPath = Poco::Path(path);
if (!filter->accept(pocoPath)) {
return;
}
ofLogNotice("ofApp::onDirectoryWatcherItemMovedTo")
<< "Moved To: " << path;
ofNotifyEvent(onItemMovedTo, path, this);
}
void onDirectoryWatcherError(const Poco::Exception& exc) {
ofLogError("ofApp::onDirectoryWatcherError")
<< "Error: " << exc.displayText();
}
// Getters
std::vector<std::string>& getFilePaths();
int getMediaType();
// Custom events
ofEvent<string> onItemAdded;
ofEvent<string> onItemRemoved;
ofEvent<string> onItemModified;
ofEvent<string> onItemMovedFrom;
ofEvent<string> onItemMovedTo;
private:
ofx::IO::DirectoryWatcherManager dirWatcher;
BasePathFilter* filter;
std::vector<std::string> filePaths;
int mediaType;
};
}
}

300
src/MediaServer/MediaServer.cpp

@ -0,0 +1,300 @@
//
// MediaServer.cpp
// example
//
// Created by felix on 13.09.14.
//
//
#include "MediaServer.h"
namespace ofx {
namespace piMapper {
MediaServer::MediaServer():
videoWatcher(ofToDataPath(DEFAULT_VIDEOS_DIR, true), SourceType::SOURCE_TYPE_VIDEO),
imageWatcher(ofToDataPath(DEFAULT_IMAGES_DIR, true), SourceType::SOURCE_TYPE_IMAGE) {
addWatcherListeners();
}
MediaServer::~MediaServer() {
removeWatcherListeners();
};
int MediaServer::getNumImages() { return imageWatcher.getFilePaths().size(); }
int MediaServer::getNumVideos() { return videoWatcher.getFilePaths().size(); }
std::vector<std::string>& MediaServer::getImagePaths() {
return imageWatcher.getFilePaths();
}
std::vector<std::string> MediaServer::getImageNames() {
std::vector<std::string> imageNames;
for (int i = 0; i < getNumImages(); i++) {
// Split image path
std::vector<std::string> pathParts = ofSplitString(getImagePaths()[i], "/");
// And get only the last piece
std::string name = pathParts[pathParts.size()-1];
imageNames.push_back(name);
}
return imageNames;
}
std::vector<std::string>& MediaServer::getVideoPaths() {
return videoWatcher.getFilePaths();
}
std::vector<std::string> MediaServer::getVideoNames() {
std::vector<std::string> videoNames;
for (int i = 0; i < getNumVideos(); i++) {
// Split video path
std::vector<std::string> pathParts = ofSplitString(getVideoPaths()[i], "/");
// And get only the last piece
std::string name = pathParts[pathParts.size()-1];
videoNames.push_back(name);
}
return videoNames;
}
BaseSource* MediaServer::loadMedia(string &path, int mediaType) {
// Chose load method depending on type
if (mediaType == SourceType::SOURCE_TYPE_IMAGE) {
return loadImage(path);
} else if (mediaType == SourceType::SOURCE_TYPE_VIDEO) {
return loadVideo(path);
} else {
std::stringstream ss;
ss << "Can not load media of unknown type: " << mediaType;
ofLogFatalError("MediaServer") << ss.str();
std::exit(EXIT_FAILURE);
}
return NULL;
}
BaseSource* MediaServer::loadImage(string& path) {
ImageSource* imageSource = NULL;
// Check if this image is already loaded
bool isImageLoaded = false;
if (loadedSources.count(path)) {
imageSource = static_cast<ImageSource*>(loadedSources[path]);
isImageLoaded = true;
}
// If image is loaded
if (isImageLoaded) {
// Increase reference count of this source
//referenceCount[path]++;
imageSource->referenceCount++;
std::stringstream refss;
refss << "Current reference count for " << path << " = " << imageSource->referenceCount;
ofLogNotice("MediaServer") << refss.str();
// Notify objects registered to onImageLoaded event
std::stringstream ss;
ss << "Image " << path << " already loaded";
ofLogNotice("MediaServer") << ss.str();
ofNotifyEvent(onImageLoaded, path, this);
return imageSource;
}
// Else load fresh
imageSource = new ImageSource();
imageSource->loadImage(path);
loadedSources[path] = imageSource;
// Set reference count of this image path to 1
//referenceCount[path] = 1;
std::stringstream refss;
refss << "Initialized reference count of " << path << " to " << imageSource->referenceCount;
ofLogNotice("MediaServer") << refss.str();
// Notify objects registered to onImageLoaded event
ofNotifyEvent(onImageLoaded, path, this);
return imageSource;
}
void MediaServer::unloadImage(string& path) {
ImageSource* source = static_cast<ImageSource*>(getSourceByPath(path));
ofLogNotice("MediaServer") << "Unload image, current reference count: " << source->referenceCount;
source->referenceCount--;
// Unload only if reference count is less or equal to 0
ofLogNotice("MediaServer") << "New reference count: " << source->referenceCount;
if (source->referenceCount > 0) {
ofLogNotice("MediaServer") << "Not unloading image as it is being referenced elsewhere";
return;
}
// Reference count 0 or less, unload image
std::stringstream ss;
ss << "Removing image " << path;
ofLogNotice("MediaServer") << ss.str();
// Destroy image source
if (loadedSources.count(path)) {
ofLogNotice("MediaServer") << "Source count BEFORE image removal: " << loadedSources.size() << endl;
loadedSources[path]->clear();
std::map<std::string, BaseSource*>::iterator it = loadedSources.find(path);
delete it->second;
loadedSources.erase(it);
ofLogNotice("MediaServer") << "Source count AFTER image removal: " << loadedSources.size() << endl;
ofNotifyEvent(onImageUnloaded, path, this);
return;
}
// Something wrong here, we should be out of the routine by now
std::stringstream failss;
failss << "Failed to remove image source: " << path;
ofLogFatalError("MediaServer") << failss.str();
std::exit(EXIT_FAILURE);
}
BaseSource* MediaServer::loadVideo(string& path) {
VideoSource* videoSource = NULL;
// Check if this video is already loaded
bool isVideoLoaded = false;
if (loadedSources.count(path)) {
videoSource = static_cast<VideoSource*>(loadedSources[path]);
isVideoLoaded = true;
}
// If is loaded
if (isVideoLoaded) {
// Increase reference count of this source
videoSource->referenceCount++;
std::stringstream refss;
refss << "Current reference count for " << path << " = " << videoSource->referenceCount;
ofLogNotice("MediaServer") << refss.str();
// Notify objects registered to onImageLoaded event
std::stringstream ss;
ss << "Video " << path << " already loaded";
ofLogNotice("MediaServer") << ss.str();
ofNotifyEvent(onVideoLoaded, path, this);
return videoSource;
}
// Else load fresh
videoSource = new VideoSource();
videoSource->loadVideo(path);
loadedSources[path] = videoSource;
// Set reference count of this image path to 1
//referenceCount[path] = 1;
std::stringstream refss;
refss << "Initialized reference count of " << path << " to " << videoSource->referenceCount;
ofLogNotice("MediaServer") << refss.str();
ofNotifyEvent(onVideoLoaded, path, this);
return videoSource;
}
void MediaServer::unloadVideo(string& path) {
VideoSource* videoSource = static_cast<VideoSource*>(getSourceByPath(path));
// Decrease reference count of the video
//referenceCount[path]--;
videoSource->referenceCount--;
// Unload only if reference count is less or equal to 0
if (videoSource->referenceCount > 0) {
ofLogNotice("MediaServer") << "Not unloading video as it is being referenced elsewhere";
return;
}
// Reference count 0 or less, let's unload the video
ofLogNotice("MediaServer") << "Removing video " << path;
// Distroy video source
if (loadedSources.count(path)) {
ofLogNotice("MediaServer") << "Source count before video removal: " << loadedSources.size() << endl;
videoSource->clear();
std::map<std::string, BaseSource*>::iterator it = loadedSources.find(path);
delete it->second;
loadedSources.erase(it);
ofLogNotice("MediaServer") << "Source count after video removal: " << loadedSources.size() << endl;
ofNotifyEvent(onVideoUnloaded, path, this);
return;
}
// Something wrong here, we should be out of the routine by now
std::stringstream failss;
failss << "Failed to remove video source: " << path;
ofLogFatalError("MediaServer") << failss.str();
std::exit(EXIT_FAILURE);
}
void MediaServer::unloadMedia(string &path) {
if (loadedSources.count(path)) {
BaseSource* mediaSource = getSourceByPath(path);
if (mediaSource->getType() == SourceType::SOURCE_TYPE_IMAGE) {
unloadImage(path);
} else if (mediaSource->getType() == SourceType::SOURCE_TYPE_VIDEO) {
unloadVideo(path);
} else {
// Oh my god, what to do!? Relax and exit.
ofLogFatalError("MediaServer") << "Attempt to unload media of unknown type";
std::exit(EXIT_FAILURE);
}
} else {
std:stringstream ss;
ss << "Media with path " << path << " is not loaded and thus can't be unloaded";
ofLogFatalError("MediaServer") << ss.str();
std::exit(EXIT_FAILURE);
}
}
// Clear all loaded media
void MediaServer::clear() {
typedef std::map<std::string, BaseSource*>::iterator it_type;
for (it_type i = loadedSources.begin(); i != loadedSources.end(); i++) {
delete i->second;
}
loadedSources.clear();
}
BaseSource* MediaServer::getSourceByPath(std::string& mediaPath) {
if (loadedSources.count(mediaPath)) {
return loadedSources[mediaPath];
}
// Source not found, exit with error
std::stringstream ss;
ss << "Could not find source by path: " << mediaPath;
ofLogFatalError("MediaServer") << ss.str();
std::exit(EXIT_FAILURE);
}
std::string MediaServer::getDefaultImageDir() {
return DEFAULT_IMAGES_DIR;
}
std::string MediaServer::getDefaultVideoDir() {
return DEFAULT_VIDEOS_DIR;
}
std::string MediaServer::getDefaultMediaDir(int sourceType) {
if (sourceType == SourceType::SOURCE_TYPE_IMAGE) {
return getDefaultImageDir();
} else if (sourceType == SourceType::SOURCE_TYPE_VIDEO) {
return getDefaultVideoDir();
} else {
std::stringstream ss;
ss << "Could not get default media dir. Unknown source type: " << sourceType;
ofLogFatalError("MediaServer") << ss.str();
std::exit(EXIT_FAILURE);
}
}
void MediaServer::handleImageAdded(string& path) {
ofNotifyEvent(onImageAdded, path, this);
}
void MediaServer::handleImageRemoved(string& path) {
ofNotifyEvent(onImageRemoved, path, this);
}
void MediaServer::handleVideoAdded(string& path) {
ofNotifyEvent(onVideoAdded, path, this);
}
void MediaServer::handleVideoRemoved(string& path) {
ofNotifyEvent(onVideoRemoved, path, this);
}
void MediaServer::addWatcherListeners() {
ofAddListener(imageWatcher.onItemAdded, this, &MediaServer::handleImageAdded);
ofAddListener(imageWatcher.onItemRemoved, this, &MediaServer::handleImageRemoved);
ofAddListener(videoWatcher.onItemAdded, this, &MediaServer::handleVideoAdded);
ofAddListener(videoWatcher.onItemRemoved, this, &MediaServer::handleVideoRemoved);
}
void MediaServer::removeWatcherListeners() {
ofRemoveListener(imageWatcher.onItemAdded, this, &MediaServer::handleImageAdded);
ofRemoveListener(imageWatcher.onItemRemoved, this, &MediaServer::handleImageRemoved);
ofRemoveListener(videoWatcher.onItemAdded, this, &MediaServer::handleVideoAdded);
ofRemoveListener(videoWatcher.onItemRemoved, this, &MediaServer::handleVideoRemoved);
}
} // namespace piMapper
} // namespace ofx

91
src/MediaServer/MediaServer.h

@ -0,0 +1,91 @@
//
// MediaServer.h
// example
//
// Created by felix on 13.09.14.
//
//
#pragma once
#include "ofMain.h"
#include "DirectoryWatcher.h"
#include "BaseSource.h"
#include "ImageSource.h"
#include "VideoSource.h"
#include "SourceType.h"
#define DEFAULT_IMAGES_DIR "sources/images/"
#define DEFAULT_VIDEOS_DIR "sources/videos/"
namespace ofx {
namespace piMapper {
class MediaServer {
public:
MediaServer();
virtual ~MediaServer();
int getNumVideos();
int getNumImages();
std::vector<std::string>& getVideoPaths();
std::vector<std::string> getVideoNames();
std::vector<std::string>& getImagePaths();
std::vector<std::string> getImageNames();
BaseSource* loadMedia(string& path, int mediaType);
BaseSource* loadImage(string& path);
void unloadImage(string& path);
BaseSource* loadVideo(string& path);
void unloadVideo(string& path);
void unloadMedia(string& path);
void clear(); // Force all loaded source unload
BaseSource* getSourceByPath(std::string& mediaPath);
std::string getDefaultImageDir();
std::string getDefaultVideoDir();
std::string getDefaultMediaDir(int sourceType);
// Custom events
ofEvent<string> onImageAdded;
ofEvent<string> onImageRemoved;
ofEvent<string> onVideoAdded;
ofEvent<string> onVideoRemoved;
ofEvent<string> onImageLoaded;
ofEvent<string> onImageUnloaded;
ofEvent<string> onVideoLoaded;
ofEvent<string> onVideoUnloaded;
private:
// Directory Watchers
ofx::piMapper::DirectoryWatcher videoWatcher;
ofx::piMapper::DirectoryWatcher imageWatcher;
std::map<std::string, BaseSource*> loadedSources;
// imageWatcher event listeners
void handleImageAdded(string& path);
void handleImageRemoved(string& path);
// TODO rest of listeners
/*
void onImageModified();
void onImageMovedFrom();
void onImageMovedTo();
*/
// videoWatcher event listeners
void handleVideoAdded(string& path);
void handleVideoRemoved(string& path);
// TODO rest of listeners
/*
void onVideoModified();
void onVideoMovedFrom();
void onVideoMovedTo();
*/
// Add/remove event listeners.
// Add event listeners to image and video watcher events.
void addWatcherListeners();
// Remove event listeners to image and video watcher events
void removeWatcherListeners();
};
} // namespace piMapper
} // namespace ofx

59
src/Sources/BaseSource.cpp

@ -0,0 +1,59 @@
#include "BaseSource.h"
namespace ofx {
namespace piMapper {
BaseSource::BaseSource() {
//cout << "BaseSource" << endl;
init();
}
BaseSource::BaseSource(ofTexture* newTexture) {
init();
texture = newTexture;
}
BaseSource::~BaseSource() {}
ofTexture* BaseSource::getTexture() {
return texture;
}
std::string& BaseSource::getName() {
return name;
}
bool BaseSource::isLoadable() {
return loadable;
}
bool BaseSource::isLoaded() {
return loaded;
}
int BaseSource::getType() {
return type;
}
std::string& BaseSource::getPath() {
return path;
}
void BaseSource::init() {
texture = NULL;
name = "";
path = "";
loadable = false;
loaded = false;
type = SourceType::SOURCE_TYPE_NONE;
referenceCount = 1; // We have one instance on init
}
void BaseSource::setNameFromPath(std::string& fullPath) {
std::vector<string> pathParts;
//cout << "fullPath: " << fullPath << endl;
pathParts = ofSplitString(fullPath, "/"); // Maybe on win "/" is "\", have to test
//cout << "lastPathPart: " << pathParts[pathParts.size() - 1] << endl;
name = pathParts[pathParts.size() - 1];
}
}
}

36
src/Sources/BaseSource.h

@ -0,0 +1,36 @@
#pragma once
#include "ofMain.h"
#include "SourceType.h"
namespace ofx {
namespace piMapper {
// Use this for adding generative sources to your surfaces
class BaseSource {
public:
BaseSource();
BaseSource(ofTexture* newTexture); // Only one clean way of passing the texture
~BaseSource();
ofTexture* getTexture();
std::string& getName();
bool isLoadable(); // Maybe the loading features shoud go to a derrived class
bool isLoaded(); // as BaseSourceLoadable
int getType();
std::string& getPath();
virtual void clear() {};
int referenceCount;
private:
void init();
protected:
void setNameFromPath(std::string& fullPath);
ofTexture* texture;
std::string name;
std::string path; // This is set only if loadable is true
bool loadable; // If the source can be loaded from disk like image and video
bool loaded; // Is the source loaded?
int type;
};
}
}

39
src/Sources/ImageSource.cpp

@ -0,0 +1,39 @@
#include "ImageSource.h"
namespace ofx {
namespace piMapper {
ImageSource::ImageSource() {
//cout << "ImageSource" << endl;
loadable = true;
loaded = false;
type = SourceType::SOURCE_TYPE_IMAGE;
}
ImageSource::~ImageSource() {}
void ImageSource::loadImage(std::string& filePath) {
path = filePath;
//cout << "loading image: " << filePath << endl;
setNameFromPath(filePath);
//cout << "path: " << path << endl;
image = new ofImage();
if (!image->loadImage(filePath)) {
ofLogWarning("ImageSource") << "Could not load image";
//std::exit(EXIT_FAILURE);
}
texture = &image->getTextureReference();
loaded = true;
}
void ImageSource::clear() {
texture = NULL;
image->clear();
delete image;
image = NULL;
//path = "";
//name = "";
loaded = false;
}
}
}

18
src/Sources/ImageSource.h

@ -0,0 +1,18 @@
#pragma once
#include "BaseSource.h"
namespace ofx {
namespace piMapper {
class ImageSource : public BaseSource {
public:
ImageSource();
~ImageSource();
std::string& getPath();
void loadImage(std::string& filePath);
void clear();
private:
ofImage* image;
};
}
}

46
src/Sources/SourceType.h

@ -0,0 +1,46 @@
#pragma once
#include "ofLog.h"
#define SOURCE_TYPE_NAME_NONE "none"
#define SOURCE_TYPE_NAME_IMAGE "image"
#define SOURCE_TYPE_NAME_VIDEO "video"
namespace ofx {
namespace piMapper {
class SourceType {
public:
enum { SOURCE_TYPE_NONE, SOURCE_TYPE_IMAGE, SOURCE_TYPE_VIDEO };
static std::string GetSourceTypeName(int sourceTypeEnum) {
if (sourceTypeEnum == SOURCE_TYPE_IMAGE) {
return SOURCE_TYPE_NAME_IMAGE;
} else if (sourceTypeEnum == SOURCE_TYPE_VIDEO) {
return SOURCE_TYPE_NAME_VIDEO;
} else if (sourceTypeEnum == SOURCE_TYPE_NONE) {
return SOURCE_TYPE_NAME_NONE;
} else {
std::stringstream ss;
ss << "Invalid source type: " << sourceTypeEnum;
ofLogFatalError("SourceType") << ss.str();
std::exit(EXIT_FAILURE);
}
};
static int GetSourceTypeEnum(std::string sourceTypeName) {
if (sourceTypeName == SOURCE_TYPE_NAME_IMAGE) {
return SOURCE_TYPE_IMAGE;
} else if (sourceTypeName == SOURCE_TYPE_NAME_VIDEO) {
return SOURCE_TYPE_VIDEO;
} else if (sourceTypeName == SOURCE_TYPE_NAME_NONE) {
return SOURCE_TYPE_NONE;
} else {
std::stringstream ss;
ss << "Invalid source type name: " << sourceTypeName;
ofLogFatalError("SourceType") << ss.str();
std::exit(EXIT_FAILURE);
}
}
};
}
}

74
src/Sources/VideoSource.cpp

@ -0,0 +1,74 @@
#include "VideoSource.h"
namespace ofx {
namespace piMapper {
VideoSource::VideoSource() {
//cout << "VideoSource constr" << endl;
loadable = true;
loaded = false;
type = SourceType::SOURCE_TYPE_VIDEO;
#ifdef TARGET_RASPBERRY_PI
omxPlayer = NULL;
#else
videoPlayer = NULL;
#endif
}
VideoSource::~VideoSource() {}
void VideoSource::loadVideo(std::string& filePath) {
path = filePath;
//cout << "loading video: " << filePath << endl;
setNameFromPath(filePath);
#ifdef TARGET_RASPBERRY_PI
// Do things with the OMX player
ofxOMXPlayerSettings settings;
settings.videoPath = filePath;
settings.useHDMIForAudio = true; //default true
settings.enableTexture = true; //default true
settings.enableLooping = true; //default true
settings.enableAudio = false; //default true, save resources by disabling
//settings.doFlipTexture = true; //default false
omxPlayer = new ofxOMXPlayer();
omxPlayer->setup(settings);
texture = &(omxPlayer->getTextureReference());
#else
// regular ofVideoPlayer
videoPlayer = new ofVideoPlayer();
videoPlayer->loadMovie(filePath);
videoPlayer->setLoopState(OF_LOOP_NORMAL);
videoPlayer->play();
texture = &(videoPlayer->getTextureReference());
ofAddListener(ofEvents().update, this, &VideoSource::update);
#endif
loaded = true;
}
void VideoSource::clear() {
texture = NULL;
#ifdef TARGET_RASPBERRY_PI
omxPlayer->close();
delete omxPlayer;
omxPlayer = NULL;
#else
ofRemoveListener(ofEvents().update, this, &VideoSource::update);
videoPlayer->stop();
videoPlayer->close();
delete videoPlayer;
videoPlayer = NULL;
#endif
//path = "";
//name = "";
loaded = false;
}
#ifndef TARGET_RASPBERRY_PI
void VideoSource::update(ofEventArgs &args) {
if (videoPlayer != NULL) {
videoPlayer->update();
}
}
#endif
}
}

48
src/Sources/VideoSource.h

@ -0,0 +1,48 @@
#pragma once
#include "ofMain.h"
#include "BaseSource.h"
#ifdef TARGET_RASPBERRY_PI
/*
Notice that if you get an error like this:
fatal error: libavcodec/opt.h: No such file or directory
Create a file opt.h in addons/ofxOMXPlayer/libs/ffmpeg/libavcodec/
with the following contents:
#ifndef AVCODEC_OPT_H
#define AVCODEC_OPT_H
#include "libavcodec/version.h"
#if FF_API_OPT_H
#include "libavutil/opt.h"
#endif
#endif // AVCODEC_OPT_H
More here: https://github.com/jvcleave/ofxOMXPlayer/issues/34
*/
#include "ofxOMXPlayer.h"
#endif
namespace ofx {
namespace piMapper {
class VideoSource : public BaseSource {
public:
VideoSource();
~VideoSource();
std::string& getPath();
void loadVideo(std::string& path);
void clear();
#ifndef TARGET_RASPBERRY_PI
void update(ofEventArgs& args);
#endif
private:
#ifdef TARGET_RASPBERRY_PI
ofxOMXPlayer* omxPlayer; // Naming different for less confusion
#else
// Go with ofVideoPlayer or
// TODO: High Performance Video player on newer Macs
ofVideoPlayer* videoPlayer;
#endif
};
}
}

121
src/SourcesEditor.cpp

@ -1,121 +0,0 @@
#include "SourcesEditor.h"
namespace ofx {
namespace piMapper {
SourcesEditor::SourcesEditor() {
defImgDir = DEFAULT_IMAGES_DIR;
registerAppEvents();
}
SourcesEditor::~SourcesEditor() {
unregisterAppEvents();
delete gui;
while (images.size()) {
delete images.back();
images.pop_back();
}
}
void SourcesEditor::registerAppEvents() {
ofAddListener(ofEvents().setup, this, &SourcesEditor::setup);
}
void SourcesEditor::unregisterAppEvents() {
ofRemoveListener(ofEvents().setup, this, &SourcesEditor::setup);
}
void SourcesEditor::setup(ofEventArgs& args) {
gui = new RadioList();
// read directory contents
ofDirectory imgDir;
imgDir.listDir(defImgDir);
imgDir.sort();
vector<string> vnames;
for (int i = 0; i < (int)imgDir.size(); i++) {
// images[i].loadImage(imgDir.getPath(i));
vnames.push_back(imgDir.getName(i));
}
gui->setup("Images", vnames);
gui->setPosition(20, 20);
ofAddListener(gui->radioSelectedEvent, this, &SourcesEditor::guiEvent);
}
void SourcesEditor::draw() {
// Don't draw if there is no source selected
if (surfaceManager->getSelectedSurface() == NULL) {
return;
}
gui->draw();
}
void SourcesEditor::loadImage(string name, string path) {
images.push_back(new ofImage());
images.back()->loadImage(path);
imageNames.push_back(name);
ofSendMessage("imageLoaded");
}
void SourcesEditor::disable() { gui->disable(); }
void SourcesEditor::enable() {
// Don't enable if there is no surface selected
if (surfaceManager->getSelectedSurface() == NULL) {
cout << "No surface selected. Not enable()ing source list." << endl;
return;
}
gui->enable();
}
void SourcesEditor::setSurfaceManager(SurfaceManager* newSurfaceManager) {
surfaceManager = newSurfaceManager;
}
void SourcesEditor::selectImageSourceRadioButton(string name) {
if (name == "none") {
gui->unselectAll();
return;
} else {
int i;
for (i = 0; i < gui->size(); i++) {
if (gui->getItemName(i) == name) {
gui->selectItem(i);
return;
}
}
}
}
int SourcesEditor::getLoadedTexCount() { return images.size(); }
ofTexture* SourcesEditor::getTexture(int index) {
if (index >= images.size()) {
throw std::runtime_error("Texture index out of bounds.");
}
return &images[index]->getTextureReference();
}
void SourcesEditor::guiEvent(string& imageName) {
string name = imageName;
if (surfaceManager->getSelectedSurface() == NULL) {
return;
}
stringstream ss;
ss << defImgDir << name;
cout << "attempt to load image: " << ss.str() << endl;
ofTexture* texture = surfaceManager->loadImageSource(name, ss.str());
surfaceManager->getSelectedSurface()->setTexture(texture);
surfaceManager->manageMemory();
}
}
}

40
src/SourcesEditor.h

@ -1,40 +0,0 @@
#pragma once
#include "ofGraphics.h"
#include "ofEvents.h"
#include "SurfaceManager.h"
#include "RadioList.h"
#define DEFAULT_IMAGES_DIR "sources/images/";
namespace ofx {
namespace piMapper {
class SourcesEditor {
public:
SourcesEditor();
~SourcesEditor();
void registerAppEvents();
void unregisterAppEvents();
void setup(ofEventArgs& args);
void draw();
void loadImage(string name, string path);
void disable();
void enable();
void setSurfaceManager(SurfaceManager* newSurfaceManager);
void selectImageSourceRadioButton(string name);
int getLoadedTexCount();
ofTexture* getTexture(int index);
private:
SurfaceManager* surfaceManager;
RadioList* gui;
string defImgDir;
void guiEvent(string& imageName);
vector<ofImage*> images;
vector<string> imageNames;
};
}
}

200
src/SurfaceManager.cpp

@ -2,7 +2,10 @@
namespace ofx {
namespace piMapper {
SurfaceManager::SurfaceManager() {}
SurfaceManager::SurfaceManager() {
// Init variables
mediaServer = NULL;
}
SurfaceManager::~SurfaceManager() { clear(); }
@ -18,19 +21,21 @@ void SurfaceManager::addSurface(int surfaceType) {
} else if (surfaceType == SurfaceType::QUAD_SURFACE) {
surfaces.push_back(new QuadSurface());
} else {
throw std::runtime_error("Attempt to add non-existing surface type.");
ofLogFatalError("SurfaceManager") << "Attempt to add non-existing surface type";
std::exit(EXIT_FAILURE);
}
}
void SurfaceManager::addSurface(int surfaceType, ofTexture* texturePtr) {
void SurfaceManager::addSurface(int surfaceType, BaseSource* newSource) {
if (surfaceType == SurfaceType::TRIANGLE_SURFACE) {
surfaces.push_back(new TriangleSurface());
surfaces.back()->setTexture(texturePtr);
surfaces.back()->setSource(newSource);
} else if (surfaceType == SurfaceType::QUAD_SURFACE) {
surfaces.push_back(new QuadSurface());
surfaces.back()->setTexture(texturePtr);
surfaces.back()->setSource(newSource);
} else {
throw std::runtime_error("Attempt to add non-existing surface type.");
ofLogFatalError("SurfaceManager") << "Attempt to add non-existing surface type";
std::exit(EXIT_FAILURE);
}
}
@ -67,11 +72,12 @@ void SurfaceManager::addSurface(int surfaceType, vector<ofVec2f> vertices,
surfaces.back()->setTexCoord(i, texCoords[i]);
}
} else {
throw std::runtime_error("Attempt to add non-existing surface type.");
ofLogFatalError("SurfaceManager") << "Attempt to add non-existing surface type";
std::exit(EXIT_FAILURE);
}
}
void SurfaceManager::addSurface(int surfaceType, ofTexture* texturePtr,
void SurfaceManager::addSurface(int surfaceType, BaseSource* newSource,
vector<ofVec2f> vertices,
vector<ofVec2f> texCoords) {
if (surfaceType == SurfaceType::TRIANGLE_SURFACE) {
@ -84,7 +90,7 @@ void SurfaceManager::addSurface(int surfaceType, ofTexture* texturePtr,
}
surfaces.push_back(new TriangleSurface());
surfaces.back()->setTexture(texturePtr);
surfaces.back()->setSource(newSource);
for (int i = 0; i < 3; i++) {
surfaces.back()->setVertex(i, vertices[i]);
@ -100,20 +106,22 @@ void SurfaceManager::addSurface(int surfaceType, ofTexture* texturePtr,
}
surfaces.push_back(new QuadSurface());
surfaces.back()->setTexture(texturePtr);
surfaces.back()->setSource(newSource);
for (int i = 0; i < 4; i++) {
surfaces.back()->setVertex(i, vertices[i]);
surfaces.back()->setTexCoord(i, texCoords[i]);
}
} else {
throw std::runtime_error("Attempt to add non-existing surface type.");
ofLogFatalError("SurfaceManager") << "Attempt to add non-existing surface type";
std::exit(EXIT_FAILURE);
}
}
void SurfaceManager::removeSelectedSurface() {
if (selectedSurface == NULL) return;
if (selectedSurface == NULL) {
return;
}
for (int i = 0; i < surfaces.size(); i++) {
if (surfaces[i] == selectedSurface) {
delete surfaces[i];
@ -124,61 +132,23 @@ void SurfaceManager::removeSelectedSurface() {
}
}
void SurfaceManager::manageMemory() {
// check if each of the sources is assigned to a surface or not
for (int i = 0; i < loadedImageSources.size(); i++) {
bool bAssigned = false;
for (int j = 0; j < surfaces.size(); j++) {
if (surfaces[j]->getTexture() ==
&loadedImageSources[i]->getTextureReference()) {
bAssigned = true;
break;
}
}
if (!bAssigned) {
// purge the image source from memory
delete loadedImageSources[i];
loadedImageSources.erase(loadedImageSources.begin() + i);
cout << "Deleting image source: " << loadedImageSourceNames[i] << endl;
loadedImageSourceNames.erase(loadedImageSourceNames.begin() + i);
i--;
}
}
}
void SurfaceManager::clear() {
// delete all extra allocations from the heap
while (surfaces.size()) {
delete surfaces.back();
surfaces.pop_back();
}
while (loadedImageSources.size()) {
delete loadedImageSources.back();
loadedImageSources.pop_back();
}
while (loadedImageSourceNames.size()) {
loadedImageSourceNames.pop_back();
}
}
// String getTypeString(SurfaceType e)
// {
// switch e
// {
// case TRINAGLE_SURFACE: return "TRINAGLE_SURFACE";
// case QUAD_SURFACE: return "QUAD_SURFACE";
// default: throw Exception("Bad MyEnum");
// }
// }
void SurfaceManager::saveXmlSettings(string fileName) {
// Exit if mediaServer not set
if (mediaServer == NULL) {
ofLogFatalError("SurfaceManager") << "Media server not set";
std::exit(EXIT_FAILURE);
}
// We need a fresh copy of the xml settings object
xmlSettings.clear();
// save surfaces
// Save surfaces
xmlSettings.addTag("surfaces");
xmlSettings.pushTag("surfaces");
for (int i = 0; i < surfaces.size(); i++) {
@ -214,37 +184,31 @@ void SurfaceManager::saveXmlSettings(string fileName) {
xmlSettings.popTag(); // texCoord
}
xmlSettings.popTag(); // texCoords
xmlSettings.addTag("source");
xmlSettings.pushTag("source");
xmlSettings.addValue("source-type", "image");
xmlSettings.addValue("source-name", getSurfaceSourceName(surface));
// xmlSettings.addValue("source-path", "/root/etc/image.jpg");
string sourceTypeName = SourceType::GetSourceTypeName(surface->getSource()->getType());
cout << "sourceTypeName: " << sourceTypeName << endl;
xmlSettings.addValue("source-type", sourceTypeName);
xmlSettings.addValue("source-name", surface->getSource()->getName());
xmlSettings.popTag(); // source
// xmlSettings.addTag("type");
// xmlSettings.pushTag("type");
// // surfaceType == SurfaceType::TRIANGLE_SURFACE
// SurfaceType surfaceType = &surface->getType();
// xmlSettings.addValue("surface-type", surfaceType);
// xmlSettings.popTag(); // type
xmlSettings.popTag(); // surface
}
xmlSettings.popTag(); // surfaces
xmlSettings.save(fileName);
}
void SurfaceManager::loadXmlSettings(string fileName) {
// Exit if there is no media server
if (mediaServer == NULL) {
ofLogFatalError("SurfaceManager") << "Media server not set";
std::exit(EXIT_FAILURE);
}
if (!xmlSettings.loadFile(fileName)) {
ofLog(OF_LOG_WARNING, "Could not load XML settings.");
ofLogWarning("SurfaceManager") << "Could not load XML settings";
return;
}
if (!xmlSettings.tagExists("surfaces")) {
ofLog(OF_LOG_WARNING, "XML settings is empty or has wrong markup.");
ofLogWarning("SurfaceManager") << "XML settings is empty or has wrong markup";
return;
}
@ -255,31 +219,27 @@ void SurfaceManager::loadXmlSettings(string fileName) {
xmlSettings.pushTag("surface", i);
// attempt to load surface source
xmlSettings.pushTag("source");
string sourceType = xmlSettings.getValue("source-type", "image");
string sourceName = xmlSettings.getValue("source-name", "none");
ofTexture* sourceTexture = NULL;
if (sourceName != "none") {
stringstream ss;
ss << "sources/images/" << sourceName; // TODO: reuse constants here
sourceTexture = loadImageSource(sourceName, ss.str());
string sourceType = xmlSettings.getValue("source-type", "");
string sourceName = xmlSettings.getValue("source-name", "");
BaseSource* source = NULL;
if (sourceName != "" && sourceName != "none" && sourceType != "") {
// Load source depending on type
int typeEnum = SourceType::GetSourceTypeEnum(sourceType);
// Construct full path
string dir = mediaServer->getDefaultMediaDir(typeEnum);
std::stringstream pathss;
pathss << ofToDataPath(dir, true) << sourceName;
string sourcePath = pathss.str();
// Load media by using full path
source = mediaServer->loadMedia(sourcePath, typeEnum);
}
xmlSettings.popTag(); // source
// // attempt to load surface type
// ofLog(OF_LOG_WARNING, "Attempt to load surface type.");
// xmlSettings.pushTag("type");
// string surfaceType = xmlSettings.getValue("surface-type",
// "TRIANGLE_SURFACE");
// xmlSettings.popTag(); // type
xmlSettings.pushTag("vertices");
vector<ofVec2f> vertices;
int vertexCount = xmlSettings.getNumTags("vertex");
// it's a triangle ?
if (vertexCount == 3) {
ofLog(OF_LOG_NOTICE, "create Triangle");
//ofLog(OF_LOG_NOTICE, "create Triangle");
xmlSettings.pushTag("vertex", 0);
vertices.push_back(ofVec2f(xmlSettings.getValue("x", 0.0f),
xmlSettings.getValue("y", 0.0f)));
@ -320,8 +280,8 @@ void SurfaceManager::loadXmlSettings(string fileName) {
// now we have variables sourceName and sourceTexture
// by checking those we can use one or another addSurface method
if (sourceName != "none" && sourceTexture != NULL) {
addSurface(SurfaceType::TRIANGLE_SURFACE, sourceTexture, vertices,
if (sourceName != "none" && source != NULL) {
addSurface(SurfaceType::TRIANGLE_SURFACE, source, vertices,
texCoords);
} else {
addSurface(SurfaceType::TRIANGLE_SURFACE, vertices, texCoords);
@ -381,8 +341,8 @@ void SurfaceManager::loadXmlSettings(string fileName) {
// now we have variables sourceName and sourceTexture
// by checking those we can use one or another addSurface method
if (sourceName != "none" && sourceTexture != NULL) {
addSurface(SurfaceType::QUAD_SURFACE, sourceTexture, vertices,
if (sourceName != "none" && source != NULL) {
addSurface(SurfaceType::QUAD_SURFACE, source, vertices,
texCoords);
} else {
addSurface(SurfaceType::QUAD_SURFACE, vertices, texCoords);
@ -394,6 +354,10 @@ void SurfaceManager::loadXmlSettings(string fileName) {
xmlSettings.popTag(); // surfaces
}
void SurfaceManager::setMediaServer(MediaServer* newMediaServer) {
mediaServer = newMediaServer;
}
BaseSurface* SurfaceManager::selectSurface(int index) {
if (index >= surfaces.size()) {
@ -406,46 +370,12 @@ BaseSurface* SurfaceManager::selectSurface(int index) {
ofSendMessage("surfaceSelected");
}
BaseSurface* SurfaceManager::getSelectedSurface() { return selectedSurface; }
void SurfaceManager::deselectSurface() { selectedSurface = NULL; }
ofTexture* SurfaceManager::loadImageSource(string name, string path) {
// check if it is loaded
for (int i = 0; i < loadedImageSourceNames.size(); i++) {
if (loadedImageSourceNames[i] == name) {
// this image is already loaded
return &loadedImageSources[i]->getTextureReference();
}
}
// not loaded - load
ofImage* image = new ofImage();
if (!image->loadImage(path)) {
return NULL;
}
loadedImageSources.push_back(image);
loadedImageSourceNames.push_back(name);
return &image->getTextureReference();
BaseSurface* SurfaceManager::getSelectedSurface() {
return selectedSurface;
}
string SurfaceManager::getSelectedSurfaceSourceName() {
if (selectedSurface == NULL) {
return "none";
}
return getSurfaceSourceName(selectedSurface);
}
string SurfaceManager::getSurfaceSourceName(BaseSurface* surface) {
ofTexture* tex = surface->getTexture();
for (int i = 0; i < loadedImageSources.size(); i++) {
if (tex == &loadedImageSources[i]->getTextureReference()) {
return loadedImageSourceNames[i];
}
}
return "none";
void SurfaceManager::deselectSurface() {
selectedSurface = NULL;
}
BaseSurface* SurfaceManager::getSurface(int index) {

17
src/SurfaceManager.h

@ -4,6 +4,9 @@
#include "TriangleSurface.h"
#include "QuadSurface.h"
#include "SurfaceType.h"
#include "MediaServer.h"
#include "BaseSource.h"
#include "SourceType.h"
#include "ofEvents.h"
#include "ofxXmlSettings.h"
@ -19,32 +22,28 @@ class SurfaceManager {
void draw();
void addSurface(int surfaceType);
void addSurface(int surfaceType, ofTexture* texturePtr);
void addSurface(int surfaceType, BaseSource* newSource);
void addSurface(int surfaceType, vector<ofVec2f> vertices,
vector<ofVec2f> texCoords);
void addSurface(int surfaceType, ofTexture* texturePtr,
void addSurface(int surfaceType, BaseSource* newSource,
vector<ofVec2f> vertices, vector<ofVec2f> texCoords);
void removeSelectedSurface();
void manageMemory(); // deletes unasigned sources
void clear();
void saveXmlSettings(string fileName);
void loadXmlSettings(string fileName);
void setMediaServer(MediaServer* newMediaServer);
BaseSurface* getSurface(int index);
int size();
BaseSurface* selectSurface(int index);
BaseSurface* getSelectedSurface();
void deselectSurface();
ofTexture* loadImageSource(string name, string path);
string getSelectedSurfaceSourceName();
string getSurfaceSourceName(BaseSurface* surface);
private:
vector<BaseSurface*> surfaces;
std::vector<BaseSurface*> surfaces;
BaseSurface* selectedSurface;
vector<string> loadedImageSourceNames;
vector<ofImage*> loadedImageSources;
ofxXmlSettings xmlSettings;
MediaServer* mediaServer;
};
}
}

11
src/SurfaceManagerGui.cpp

@ -174,6 +174,13 @@ void SurfaceManagerGui::setSurfaceManager(SurfaceManager* newSurfaceManager) {
sourcesEditor.setSurfaceManager(surfaceManager);
}
// Set external media server so we can access it from wherever we need
void SurfaceManagerGui::setMediaServer(MediaServer* newMediaServer) {
mediaServer = newMediaServer;
// Set the media server of the sources editor here
sourcesEditor.setMediaServer(mediaServer);
}
void SurfaceManagerGui::setMode(int newGuiMode) {
if (newGuiMode != GuiMode::NONE && newGuiMode != GuiMode::TEXTURE_MAPPING &&
newGuiMode != GuiMode::PROJECTION_MAPPING &&
@ -191,8 +198,8 @@ void SurfaceManagerGui::setMode(int newGuiMode) {
if (guiMode == GuiMode::SOURCE_SELECTION) {
sourcesEditor.enable();
string sourceName = surfaceManager->getSelectedSurfaceSourceName();
sourcesEditor.selectImageSourceRadioButton(sourceName);
//string sourceName = surfaceManager->getSelectedSurfaceSourceName();
//sourcesEditor.selectImageSourceRadioButton(sourceName);
} else {
sourcesEditor.disable();
}

2
src/SurfaceManagerGui.h

@ -27,6 +27,7 @@ class SurfaceManagerGui {
void mouseReleased(ofMouseEventArgs& args);
void mouseDragged(ofMouseEventArgs& args);
void setSurfaceManager(SurfaceManager* newSurfaceManager);
void setMediaServer(MediaServer* newMediaServer);
void setMode(int newGuiMode);
void drawSelectedSurfaceHighlight();
void drawSelectedSurfaceTextureHighlight();
@ -35,6 +36,7 @@ class SurfaceManagerGui {
private:
SurfaceManager* surfaceManager;
MediaServer* mediaServer;
TextureEditor textureEditor;
ProjectionEditor projectionEditor;
SourcesEditor sourcesEditor;

10
src/SurfaceType.h

@ -1,9 +1,9 @@
#pragma once
namespace ofx {
namespace piMapper {
struct SurfaceType {
enum { TRIANGLE_SURFACE, QUAD_SURFACE };
};
}
namespace piMapper {
struct SurfaceType {
enum { TRIANGLE_SURFACE, QUAD_SURFACE };
};
}
}

42
src/BaseSurface.cpp → src/Surfaces/BaseSurface.cpp

@ -7,6 +7,12 @@ BaseSurface::BaseSurface() {
ofEnableNormalizedTexCoords();
createDefaultTexture();
}
BaseSurface::~BaseSurface() {
delete defaultSource;
defaultSource = NULL;
defaultTexture.clear();
}
void BaseSurface::createDefaultTexture() {
ofPixels pixels;
@ -38,33 +44,47 @@ void BaseSurface::createDefaultTexture() {
// load pixels into texture
defaultTexture.loadData(pixels);
// Assign default texture to texture pointer
texture = &defaultTexture;
// Create new source to be the default
defaultSource = new BaseSource(&defaultTexture);
source = defaultSource;
}
void BaseSurface::drawTexture(ofVec2f position) {
if (source->getTexture() == NULL) {
ofLogWarning("BaseSurface") << "Source texture empty. Not drawing.";
return;
}
ofMesh texMesh;
texMesh.addVertex(position);
texMesh.addVertex(position + ofVec2f(texture->getWidth(), 0.0f));
texMesh.addVertex(position + ofVec2f(source->getTexture()->getWidth(), 0.0f));
texMesh.addVertex(position +
ofVec2f(texture->getWidth(), texture->getHeight()));
texMesh.addVertex(position + ofVec2f(0.0f, texture->getHeight()));
ofVec2f(source->getTexture()->getWidth(), source->getTexture()->getHeight()));
texMesh.addVertex(position + ofVec2f(0.0f, source->getTexture()->getHeight()));
texMesh.addTriangle(0, 2, 3);
texMesh.addTriangle(0, 1, 2);
texMesh.addTexCoord(ofVec2f(0.0f, 0.0f));
texMesh.addTexCoord(ofVec2f(1.0f, 0.0f));
texMesh.addTexCoord(ofVec2f(1.0f, 1.0f));
texMesh.addTexCoord(ofVec2f(0.0f, 1.0f));
texture->bind();
source->getTexture()->bind();
texMesh.draw();
texture->unbind();
source->getTexture()->unbind();
}
void BaseSurface::setTexture(ofTexture* texturePtr) { texture = texturePtr; }
//void BaseSurface::setTexture(ofTexture* texturePtr) { texture = texturePtr; }
void BaseSurface::setSource(BaseSource* newSource) {
source = newSource;
}
ofTexture* BaseSurface::getTexture() { return texture; }
//ofTexture* BaseSurface::getTexture() { return texture; }
BaseSource* BaseSurface::getSource() {
return source;
}
ofTexture* BaseSurface::getDefaultTexture() { return &defaultTexture; }
//ofTexture* BaseSurface::getDefaultTexture() { return &defaultTexture; }
BaseSource* BaseSurface::getDefaultSource() {
return defaultSource;
}
}
}

21
src/BaseSurface.h → src/Surfaces/BaseSurface.h

@ -2,6 +2,7 @@
#include "ofMain.h"
#include <string>
#include "BaseSource.h"
using namespace std;
@ -10,6 +11,7 @@ namespace piMapper {
class BaseSurface {
public:
BaseSurface();
~BaseSurface();
virtual void setup() {};
virtual void draw() {};
virtual void setVertex(int index, ofVec2f p) {};
@ -24,16 +26,21 @@ class BaseSurface {
// Draws a texture using ofMesh
void drawTexture(ofVec2f position);
void setTexture(ofTexture* texturePtr);
ofTexture* getTexture();
ofTexture* getDefaultTexture();
//void setTexture(ofTexture* texturePtr);
void setSource(BaseSource* newSource);
//ofTexture* getTexture();
//ofTexture* getDefaultTexture();
BaseSource* getSource();
BaseSource* getDefaultSource();
protected:
ofMesh mesh;
ofTexture* texture;
//ofTexture* texture;
ofTexture defaultTexture;
BaseSource* source;
BaseSource* defaultSource;
void createDefaultTexture();
};
}

17
src/QuadSurface.cpp → src/Surfaces/QuadSurface.cpp

@ -22,14 +22,14 @@ void QuadSurface::setup() {
ofVec2f t3 = ofVec2f(ofVec2f(1.0f, 1.0f));
ofVec2f t4 = ofVec2f(ofVec2f(0.0f, 1.0f));
setup(p1, p2, p3, p4, t1, t2, t3, t4, texture);
setup(p1, p2, p3, p4, t1, t2, t3, t4, source);
}
void QuadSurface::setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f p4,
ofVec2f t1, ofVec2f t2, ofVec2f t3, ofVec2f t4,
ofTexture* texturePtr) {
BaseSource* newSource) {
// Assign texture
texture = texturePtr;
source = newSource;
// Clear mesh
mesh.clear();
@ -68,6 +68,11 @@ void QuadSurface::setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f p4,
}
void QuadSurface::draw() {
if (source->getTexture() == NULL) {
ofLogWarning("QuadSurface") << "Source texture empty. Not drawing.";
return;
}
/*if(mesh.haveVertsChanged() || mesh.haveTexCoordsChanged()){
calculate4dTextureCoords();
}*/
@ -75,9 +80,9 @@ void QuadSurface::draw() {
glTexCoordPointer(4, GL_FLOAT, 0, quadTexCoordinates);
glVertexPointer(3, GL_FLOAT, 0, quadVertices);
texture->bind();
source->getTexture()->bind();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, quadIndices);
texture->unbind();
source->getTexture()->unbind();
}
void QuadSurface::setVertex(int index, ofVec2f p) {
@ -154,7 +159,7 @@ ofPolyline QuadSurface::getHitArea() {
ofPolyline QuadSurface::getTextureHitArea() {
ofPolyline line;
vector<ofVec2f>& texCoords = mesh.getTexCoords();
ofVec2f textureSize = ofVec2f(texture->getWidth(), texture->getHeight());
ofVec2f textureSize = ofVec2f(source->getTexture()->getWidth(), source->getTexture()->getHeight());
for (int i = 0; i < texCoords.size(); i++) {
line.addVertex(ofPoint(texCoords[i] * textureSize));
}

2
src/QuadSurface.h → src/Surfaces/QuadSurface.h

@ -14,7 +14,7 @@ class QuadSurface : public BaseSurface {
void setup();
void setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f p4, ofVec2f t1,
ofVec2f t2, ofVec2f t3, ofVec2f t4, ofTexture* texturePtr);
ofVec2f t2, ofVec2f t3, ofVec2f t4, BaseSource* newSource);
void draw();
void setVertex(int index, ofVec2f p);

22
src/TriangleSurface.cpp → src/Surfaces/TriangleSurface.cpp

@ -3,13 +3,10 @@
namespace ofx {
namespace piMapper {
TriangleSurface::TriangleSurface() {
cout << "TriangleSurface constructor." << endl;
setup();
}
TriangleSurface::~TriangleSurface() {
cout << "TriangleSurface destructor." << endl;
}
TriangleSurface::~TriangleSurface() {}
void TriangleSurface::setup() {
// Create 3 points for the triangle
@ -22,13 +19,13 @@ void TriangleSurface::setup() {
ofVec2f t2 = ofVec2f(0, 1.0f);
ofVec2f t3 = ofVec2f(1, 1.0f);
setup(p1, p2, p3, t1, t2, t3, texture);
setup(p1, p2, p3, t1, t2, t3, source);
}
void TriangleSurface::setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f t1,
ofVec2f t2, ofVec2f t3, ofTexture* texturePtr) {
ofVec2f t2, ofVec2f t3, BaseSource* newSource) {
// Assign texture
texture = texturePtr;
source = newSource;
// Clear mesh
mesh.clear();
@ -45,9 +42,14 @@ void TriangleSurface::setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f t1,
}
void TriangleSurface::draw() {
texture->bind();
if (source->getTexture() == NULL) {
ofLogWarning("TriangleSurface") << "Source texture is empty. Not drawing.";
return;
}
source->getTexture()->bind();
mesh.draw();
texture->unbind();
source->getTexture()->unbind();
}
void TriangleSurface::setVertex(int index, ofVec2f p) {
@ -120,7 +122,7 @@ ofPolyline TriangleSurface::getHitArea() {
ofPolyline TriangleSurface::getTextureHitArea() {
ofPolyline line;
vector<ofVec2f>& texCoords = mesh.getTexCoords();
ofVec2f textureSize = ofVec2f(texture->getWidth(), texture->getHeight());
ofVec2f textureSize = ofVec2f(source->getTexture()->getWidth(), source->getTexture()->getHeight());
for (int i = 0; i < texCoords.size(); i++) {
line.addVertex(ofPoint(texCoords[i] * textureSize));
}

2
src/TriangleSurface.h → src/Surfaces/TriangleSurface.h

@ -13,7 +13,7 @@ class TriangleSurface : public BaseSurface {
void setup();
void setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f t1, ofVec2f t2,
ofVec2f t3, ofTexture* texturePtr);
ofVec2f t3, BaseSource* newSource);
void draw();
void setVertex(int index, ofVec2f p);
void setTexCoord(int index, ofVec2f t);

0
src/BaseJoint.cpp → src/UserInterface/BaseJoint.cpp

0
src/BaseJoint.h → src/UserInterface/BaseJoint.h

0
src/CircleJoint.cpp → src/UserInterface/CircleJoint.cpp

0
src/CircleJoint.h → src/UserInterface/CircleJoint.h

0
src/EditorType.h → src/UserInterface/EditorType.h

0
src/GuiMode.h → src/UserInterface/GuiMode.h

0
src/ProjectionEditor.cpp → src/UserInterface/ProjectionEditor.cpp

0
src/ProjectionEditor.h → src/UserInterface/ProjectionEditor.h

52
src/ui/RadioList.cpp → src/UserInterface/RadioList.cpp

@ -7,21 +7,22 @@ RadioList::RadioList() {
storedSelectedItem = 0;
}
RadioList::RadioList(vector<string>& labels) {
RadioList::RadioList(vector<string>& labels, vector<string>& values) {
RadioList();
setup(labels);
setup(labels, values);
}
RadioList::RadioList(string title, vector<string>& labels) {
RadioList::RadioList(string title, vector<string>& labels, vector<string>& values) {
RadioList();
setup(title, labels);
setup(title, labels, values);
}
RadioList::~RadioList() { clear(); }
void RadioList::setup(vector<string>& labels) {
void RadioList::setup(vector<string>& labels, vector<string>& values) {
// Copy incomming labels for later use
storedLabels = labels;
storedValues = values;
// Create toggles with labels from the labels arg
int i;
@ -35,15 +36,13 @@ void RadioList::setup(vector<string>& labels) {
toggle->registerMouseEvents();
#endif
}
cout << "num items: " << guiGroup.getNumControls() << endl;
}
void RadioList::setup(string title, vector<string>& labels) {
void RadioList::setup(string title, vector<string>& labels, vector<string>& values) {
// Store title for later use
storedTitle = title;
guiGroup.setName(title);
setup(labels);
setup(labels, values);
}
void RadioList::draw() { guiGroup.draw(); }
@ -68,11 +67,36 @@ void RadioList::selectItem(int index) {
toggle->removeListener(this, &RadioList::onToggleClicked);
*toggle = true; // Select the specific radio button
toggle->addListener(this, &RadioList::onToggleClicked);
string name = toggle->getName();
ofNotifyEvent(radioSelectedEvent, name, this);
//string name = toggle->getName();
// Throw event with value that is image path instead of name
string value = storedValues[index];
ofNotifyEvent(onRadioSelected, value, this);
storedSelectedItem = index;
}
bool RadioList::selectItemByValue(std::string itemValue) {
if (itemValue == "") {
ofLogNotice("RadioList") << "Item value empty";
return false;
}
unselectAll();
int itemIndex = -1;
for (int i = 0; i < storedValues.size(); i++) {
if (itemValue == storedValues[i]) {
itemIndex = i;
break;
}
}
if (itemIndex >= 0) {
ofxToggle* toggle = static_cast<ofxToggle*>(guiGroup.getControl(itemIndex));
toggle->removeListener(this, &RadioList::onToggleClicked);
*toggle = true; // Select the specific radio button
toggle->addListener(this, &RadioList::onToggleClicked);
return true;
}
ofLogNotice("RadioList") << "Item with value " << itemValue << " not found";
return false;
}
void RadioList::enable() {
if (guiGroup.getNumControls() >= 0) {
@ -80,7 +104,7 @@ void RadioList::enable() {
}
// Rebuild everyting
setup(storedTitle, storedLabels);
setup(storedTitle, storedLabels, storedValues);
// Select the stored selected item without throwing an event
ofxToggle* toggle =
@ -136,7 +160,7 @@ string RadioList::getItemName(int index) {
return toggle->getName();
}
int RadioList::size() { return guiGroup.getNumControls(); }
int RadioList::size() { return storedValues.size(); }
void RadioList::onToggleClicked(bool& toggleValue)
{

12
src/ui/RadioList.h → src/UserInterface/RadioList.h

@ -10,17 +10,18 @@ namespace piMapper {
class RadioList {
public:
RadioList();
RadioList(vector<string> &labels);
RadioList(string title, vector<string> &labels);
RadioList(vector<string>& labels, vector<string>& values);
RadioList(string title, vector<string>& labels, vector<string>& values);
~RadioList();
void setup(vector<string> &labels);
void setup(string title, vector<string> &labels);
void setup(vector<string> &labels, vector<string>& values);
void setup(string title, vector<string>& labels, vector<string>& values);
void draw();
void setTitle(string title);
void setPosition(ofPoint p);
void setPosition(float x, float y);
void selectItem(int index);
bool selectItemByValue(std::string itemValue);
void enable();
void disable();
void clear();
@ -37,10 +38,11 @@ class RadioList {
// Use ofAddListener(RadioListInstance.radioSelectedEvent, listenerClassPtr,
// &listenerClass::listenerMethod)
// to listen to this. Listner method void listenerMethod(string & radioName)
ofEvent<string> radioSelectedEvent;
ofEvent<string> onRadioSelected;
private:
vector<string> storedLabels;
vector<string> storedValues;
string storedTitle;
ofxGuiGroup guiGroup;
int storedSelectedItem;

271
src/UserInterface/SourcesEditor.cpp

@ -0,0 +1,271 @@
#include "SourcesEditor.h"
namespace ofx {
namespace piMapper {
SourcesEditor::SourcesEditor() {
init();
// Create new MediaServer instance,
// we will need to clear this in the deconstr
mediaServer = new MediaServer();
isMediaServerExternal = false;
addMediaServerListeners();
}
SourcesEditor::SourcesEditor(MediaServer* externalMediaServer) {
init();
// Assign external MediaServer instance pointer
mediaServer = externalMediaServer;
isMediaServerExternal = true;
addMediaServerListeners();
}
SourcesEditor::~SourcesEditor() {
unregisterAppEvents();
delete imageSelector;
delete videoSelector;
removeMediaServerListeners();
clearMediaServer();
}
void SourcesEditor::registerAppEvents() {
ofAddListener(ofEvents().setup, this, &SourcesEditor::setup);
}
void SourcesEditor::unregisterAppEvents() {
ofRemoveListener(ofEvents().setup, this, &SourcesEditor::setup);
}
void SourcesEditor::setup(ofEventArgs& args) {
imageSelector = new RadioList();
videoSelector = new RadioList();
// Get media count
int numImages = mediaServer->getNumImages();
int numVideos = mediaServer->getNumVideos();
// Depending on media count, decide what to load and initialize
if (numImages) {
// Get image names from media server
vector<string> imageNames = mediaServer->getImageNames();
imageSelector->setup("Images", imageNames, mediaServer->getImagePaths());
ofAddListener(imageSelector->onRadioSelected, this, &SourcesEditor::handleImageSelected);
}
if (numVideos) {
vector<string> videoNames = mediaServer->getVideoNames();
videoSelector->setup("Videos", videoNames, mediaServer->getVideoPaths());
ofAddListener(videoSelector->onRadioSelected, this, &SourcesEditor::handleVideoSelected);
}
if (numImages) {
imageSelector->setPosition(20, 20);
if (numVideos) {
videoSelector->setPosition(250, 20);
}
} else {
if (numVideos) {
videoSelector->setPosition(20, 20);
}
}
}
void SourcesEditor::draw() {
// Don't draw if there is no source selected
if (surfaceManager->getSelectedSurface() == NULL) {
ofLogNotice("SourcesEditor") << "No surface selected";
return;
}
if (imageSelector->size()) {
imageSelector->draw();
}
if (videoSelector->size()) {
videoSelector->draw();
}
}
void SourcesEditor::disable() {
if (imageSelector->size()) {
imageSelector->disable();
}
if (videoSelector->size()) {
videoSelector->disable();
}
}
void SourcesEditor::enable() {
// Don't enable if there is no surface selected
if (surfaceManager->getSelectedSurface() == NULL) {
ofLogNotice("SourcesEditor") << "No surface selected. Not enabling and not showing source list.";
return;
}
if (imageSelector->size()) {
imageSelector->enable();
}
if (videoSelector->size()) {
videoSelector->enable();
}
BaseSource* source = surfaceManager->getSelectedSurface()->getSource();
selectSourceRadioButton(source->getPath());
}
void SourcesEditor::setSurfaceManager(SurfaceManager* newSurfaceManager) {
surfaceManager = newSurfaceManager;
}
void SourcesEditor::setMediaServer(MediaServer* newMediaServer) {
// If the new media server is not valid
if (newMediaServer == NULL) {
// Log an error and return from the routine
ofLogFatalError("SourcesEditor") << "New media server is NULL";
std::exit(EXIT_FAILURE);
}
// Attempt to clear existing media server and assign new one
clearMediaServer();
//cout << "old ms addr: " << mediaServer << endl;
//cout << "new ms addr: " << newMediaServer << endl;
mediaServer = newMediaServer;
isMediaServerExternal = true;
}
void SourcesEditor::selectSourceRadioButton(std::string& sourcePath) {
if (sourcePath == "") {
ofLogNotice("SourcesEditor") << "Path is empty";
if (imageSelector->size()) {
imageSelector->unselectAll();
}
if (videoSelector->size()) {
videoSelector->unselectAll();
}
return;
} else {
// Check image selector first
bool imageRadioSelected = false;
bool videoRadioSelected = false;
if (imageSelector->size()) {
imageRadioSelected = imageSelector->selectItemByValue(sourcePath);
}
if (videoSelector->size()) {
videoRadioSelected = videoSelector->selectItemByValue(sourcePath);
}
if (imageRadioSelected || videoRadioSelected) {
return;
}
// Log warning if we are still here
ofLogWarning("SourcesEditor") << "Could not find option in any of the source lists";
}
}
void SourcesEditor::init() {
mediaServer = NULL; // Pointers to NULL pointer so we can check later
isMediaServerExternal = false;
registerAppEvents();
}
void SourcesEditor::addMediaServerListeners() {
// Check if the media server is valid
if (mediaServer == NULL) {
ofLogError("SourcesEditor::addMediaServerListeners", "Media server not set");
return;
}
// Add listeners to custom events of the media server
ofAddListener(mediaServer->onImageAdded, this, &SourcesEditor::handleImageAdded);
ofAddListener(mediaServer->onImageRemoved, this, &SourcesEditor::handleImageRemoved);
ofAddListener(mediaServer->onVideoAdded, this, &SourcesEditor::handleVideoAdded);
ofAddListener(mediaServer->onVideoRemoved, this, &SourcesEditor::handleVideoRemoved);
ofAddListener(mediaServer->onImageLoaded, this, &SourcesEditor::handleImageLoaded);
ofAddListener(mediaServer->onImageUnloaded, this, &SourcesEditor::handleImageUnloaded);
}
void SourcesEditor::removeMediaServerListeners() {
// Check if the media server is valid
if (mediaServer == NULL) {
ofLogError("SourcesEditor::addMediaServerListeners", "Media server not set");
return;
}
// Remove listeners to custom events of the media server
ofRemoveListener(mediaServer->onImageAdded, this, &SourcesEditor::handleImageAdded);
ofRemoveListener(mediaServer->onImageRemoved, this, &SourcesEditor::handleImageRemoved);
ofRemoveListener(mediaServer->onVideoAdded, this, &SourcesEditor::handleVideoAdded);
ofRemoveListener(mediaServer->onVideoRemoved, this, &SourcesEditor::handleVideoRemoved);
ofRemoveListener(mediaServer->onImageLoaded, this, &SourcesEditor::handleImageLoaded);
ofRemoveListener(mediaServer->onImageUnloaded, this, &SourcesEditor::handleImageUnloaded);
}
void SourcesEditor::handleImageSelected(string& imagePath) {
// Unselect video item if any selected
videoSelector->unselectAll();
BaseSurface* surface = surfaceManager->getSelectedSurface();
if (surface == NULL) {
ofLogNotice("SourcesEditor") << "No surface selected";
return;
}
// Unload old media
BaseSource* source = surface->getSource();
if (source->isLoadable()) {
mediaServer->unloadMedia(source->getPath());
}
// Load new image
surface->setSource(mediaServer->loadImage(imagePath));
}
void SourcesEditor::handleVideoSelected(string& videoPath) {
// Unselect image item if any selected
imageSelector->unselectAll();
BaseSurface* surface = surfaceManager->getSelectedSurface();
if (surface == NULL) {
ofLogNotice("SourcesEditor") << "No surface selected";
return;
}
// Unload old media
BaseSource* source = surface->getSource();
if (source->isLoadable()) {
mediaServer->unloadMedia(source->getPath());
}
// Load new video
surface->setSource(mediaServer->loadVideo(videoPath));
}
void SourcesEditor::clearMediaServer() {
// If mediaServer is local, clear it
if (!isMediaServerExternal) {
// Clear all loaded sources
mediaServer->clear();
// Destroy the pointer and set it to NULL pointer
delete mediaServer;
mediaServer = NULL;
}
}
void SourcesEditor::handleImageAdded(string& path) {
cout << "image added: " << path << endl;
}
void SourcesEditor::handleImageRemoved(string& path) {
cout << "image removed: " << path << endl;
}
void SourcesEditor::handleVideoAdded(string& path) {
cout << "video added: " << path << endl;
}
void SourcesEditor::handleVideoRemoved(string& path) {
cout << "video removed: " << path << endl;
}
void SourcesEditor::handleImageLoaded(string& path) {
cout << "Image loaded: " << path << endl;
// Test image unload
// mediaServer->unloadImage(path);
//BaseSource* source = mediaServer->getSourceByPath(path);
//surfaceManager->getSelectedSurface()->setSource(source);
}
void SourcesEditor::handleImageUnloaded(string& path) {
cout << "Image unloaded: " << path << endl;
}
}
}

73
src/UserInterface/SourcesEditor.h

@ -0,0 +1,73 @@
#pragma once
#include "ofGraphics.h"
#include "ofEvents.h"
#include "SurfaceManager.h"
#include "RadioList.h"
#include "MediaServer.h"
namespace ofx {
namespace piMapper {
class SourcesEditor {
public:
// Default contructor that initializes media server locally,
// thus requiring to delete the media server from memory on deconstr
SourcesEditor();
// Alternative constructor that allows to assign external media server
SourcesEditor(MediaServer* externalMediaServer);
~SourcesEditor();
void registerAppEvents();
void unregisterAppEvents();
void setup(ofEventArgs& args);
void draw();
void loadImage(string name, string path);
void disable();
void enable();
void setSurfaceManager(SurfaceManager* newSurfaceManager);
// Sets external MediaServer
void setMediaServer(MediaServer* newMediaServer);
//void selectImageSourceRadioButton(string name);
void selectSourceRadioButton(std::string& sourcePath);
int getLoadedTexCount();
ofTexture* getTexture(int index);
private:
MediaServer* mediaServer;
SurfaceManager* surfaceManager;
RadioList* imageSelector;
RadioList* videoSelector;
// Is the media server pointer local or from somewhere else?
// We use this to determine if we are allowed to clear media server locally.
bool isMediaServerExternal;
// Init handles variable initialization in all constructors
void init();
// Methods for adding and removing listeners to the media server
void addMediaServerListeners();
void removeMediaServerListeners();
// Handles GUI event, whenever someone has clicked on a radio button
void handleImageSelected(string& imagePath);
void handleVideoSelected(string& videoPath);
// Careful clearing of the media server,
// clears only if the media server has been initialized locally
void clearMediaServer();
// MediaServer event handlers
void handleImageAdded(string& path);
void handleImageRemoved(string& path);
void handleVideoAdded(string& path);
void handleVideoRemoved(string& path);
void handleImageLoaded(string& path);
void handleImageUnloaded(string& path);
};
}
}

12
src/TextureEditor.cpp → src/UserInterface/TextureEditor.cpp

@ -45,8 +45,8 @@ void TextureEditor::update(ofEventArgs& args) {
if (surface == NULL) return;
// update surface if one of the joints is being dragged
ofVec2f textureSize = ofVec2f(surface->getTexture()->getWidth(),
surface->getTexture()->getHeight());
ofVec2f textureSize = ofVec2f(surface->getSource()->getTexture()->getWidth(),
surface->getSource()->getTexture()->getHeight());
// Get selected joint index
int selectedJointIndex = 0;
@ -138,8 +138,8 @@ void TextureEditor::createJoints() {
if (surface == NULL) return;
clearJoints();
vector<ofVec2f>& texCoords = surface->getTexCoords();
ofVec2f textureSize = ofVec2f(surface->getTexture()->getWidth(),
surface->getTexture()->getHeight());
ofVec2f textureSize = ofVec2f(surface->getSource()->getTexture()->getWidth(),
surface->getSource()->getTexture()->getHeight());
for (int i = 0; i < texCoords.size(); i++) {
joints.push_back(new CircleJoint());
@ -163,8 +163,8 @@ void TextureEditor::unselectAllJoints() {
void TextureEditor::moveTexCoords(ofVec2f by) {
if (surface == NULL) return;
vector<ofVec2f>& texCoords = surface->getTexCoords();
ofVec2f textureSize = ofVec2f(surface->getTexture()->getWidth(),
surface->getTexture()->getHeight());
ofVec2f textureSize = ofVec2f(surface->getSource()->getTexture()->getWidth(),
surface->getSource()->getTexture()->getHeight());
for (int i = 0; i < texCoords.size(); i++) {
joints[i]->position += by;
texCoords[i] = joints[i]->position / textureSize;

0
src/TextureEditor.h → src/UserInterface/TextureEditor.h

4
src/ofxPiMapper.h

@ -1,4 +1,6 @@
#pragma once
#include "SurfaceManager.h"
#include "SurfaceManagerGui.h"
#include "SurfaceManagerGui.h"
#include "MediaServer.h"
Loading…
Cancel
Save