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 |
|||
ofxGui |
|||
ofxIO |
|||
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 |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
struct SurfaceType { |
|||
enum { TRIANGLE_SURFACE, QUAD_SURFACE }; |
|||
}; |
|||
} |
|||
namespace piMapper { |
|||
struct SurfaceType { |
|||
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 |
|||
|
|||
#include "SurfaceManager.h" |
|||
#include "SurfaceManagerGui.h" |
|||
#include "SurfaceManagerGui.h" |
|||
|
|||
#include "MediaServer.h" |
Loading…
Reference in new issue