44 changed files with 1552 additions and 380 deletions
@ -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 = |
@ -1,3 +1,5 @@ |
|||||
ofxPiMapper |
ofxPiMapper |
||||
ofxGui |
ofxIO |
||||
ofxXmlSettings |
ofxXmlSettings |
||||
|
ofxGui |
||||
|
ofxOMXPlayer |
||||
|
Binary file not shown.
@ -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
|
@ -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; |
||||
|
}; |
||||
|
} |
||||
|
} |
@ -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
|
@ -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
|
@ -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]; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -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; |
||||
|
}; |
||||
|
} |
||||
|
} |
@ -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; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
@ -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; |
||||
|
}; |
||||
|
} |
||||
|
} |
@ -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); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
} |
@ -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 |
||||
|
} |
||||
|
} |
@ -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 |
||||
|
}; |
||||
|
} |
||||
|
} |
@ -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(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -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; |
|
||||
}; |
|
||||
} |
|
||||
} |
|
@ -1,9 +1,9 @@ |
|||||
#pragma once |
#pragma once |
||||
|
|
||||
namespace ofx { |
namespace ofx { |
||||
namespace piMapper { |
namespace piMapper { |
||||
struct SurfaceType { |
struct SurfaceType { |
||||
enum { TRIANGLE_SURFACE, QUAD_SURFACE }; |
enum { TRIANGLE_SURFACE, QUAD_SURFACE }; |
||||
}; |
}; |
||||
} |
} |
||||
} |
} |
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -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); |
||||
|
}; |
||||
|
} |
||||
|
} |
@ -1,4 +1,6 @@ |
|||||
#pragma once |
#pragma once |
||||
|
|
||||
#include "SurfaceManager.h" |
#include "SurfaceManager.h" |
||||
#include "SurfaceManagerGui.h" |
#include "SurfaceManagerGui.h" |
||||
|
|
||||
|
#include "MediaServer.h" |
Loading…
Reference in new issue