ofxPiMapper fixed for C++17 & oF 12.0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

394 lines
13 KiB

//
// 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();
}
int MediaServer::getNumFboSources(){
return fboSources.size();
}
vector <string> & MediaServer::getImagePaths(){
return imageWatcher.getFilePaths();
}
vector <string> MediaServer::getImageNames(){
vector <string> imageNames;
for(int i = 0; i < getNumImages(); i++){
// Split image path
vector <string> pathParts = ofSplitString(getImagePaths()[i], "/");
// And get only the last piece
string name = pathParts[pathParts.size() - 1];
imageNames.push_back(name);
}
return imageNames;
}
vector <string> MediaServer::getFboSourceNames(){
vector <string> fboSourceNames;
for(int i = 0; i < fboSources.size(); i++){
fboSourceNames.push_back(fboSources[i]->getName());
}
return fboSourceNames;
}
vector <string> & MediaServer::getVideoPaths(){
return videoWatcher.getFilePaths();
}
vector <string> MediaServer::getVideoNames(){
vector <string> videoNames;
for(int i = 0; i < getNumVideos(); i++){
// Split video path
vector <string> pathParts = ofSplitString(getVideoPaths()[i], "/");
// And get only the last piece
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 if(mediaType == SourceType::SOURCE_TYPE_FBO){
return loadFboSource(path);
}else{
stringstream ss;
ss << "Can not load media of unknown type: " << mediaType;
ofLogFatalError("MediaServer") << ss.str();
exit(EXIT_FAILURE);
}
return 0;
}
BaseSource * MediaServer::loadImage(string & path){
ImageSource * imageSource = 0;
// 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++;
stringstream refss;
refss << "Current reference count for " << path << " = " << imageSource->referenceCount;
ofLogNotice("MediaServer") << refss.str();
// Notify objects registered to onImageLoaded event
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;
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
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();
map <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
stringstream failss;
failss << "Failed to remove image source: " << path;
ofLogFatalError("MediaServer") << failss.str();
exit(EXIT_FAILURE);
}
BaseSource * MediaServer::loadVideo(string & path){
VideoSource * videoSource = 0;
// 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++;
stringstream refss;
refss << "Current reference count for " << path << " = " << videoSource->referenceCount;
ofLogNotice("MediaServer") << refss.str();
// Notify objects registered to onImageLoaded event
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;
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();
map <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
stringstream failss;
failss << "Failed to remove video source: " << path;
ofLogFatalError("MediaServer") << failss.str();
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 if(mediaSource->getType() == SourceType::SOURCE_TYPE_FBO){
unloadFboSource(path);
}else{
// Oh my god, what to do!? Relax and exit.
ofLogFatalError("MediaServer") << "Attempt to unload media of unknown type";
exit(EXIT_FAILURE);
}
}else{
ofLogNotice("MediaServer") << "Nothing to unload";
}
}
// Clear all loaded media
void MediaServer::clear(){
typedef map <string, BaseSource *>::iterator it_type;
for(it_type i = loadedSources.begin(); i != loadedSources.end(); i++){
// Do not delete FBO source pointers as they are (and should be) initialized elsewhere
if(i->second->getType() != SourceType::SOURCE_TYPE_FBO){
delete i->second;
}
}
loadedSources.clear();
}
// TODO: getLoadedSourceByPath
BaseSource * MediaServer::getSourceByPath(string & mediaPath){
if(loadedSources.count(mediaPath)){
return loadedSources[mediaPath];
}
// Source not found, exit with error
stringstream ss;
ss << "Could not find source by path: " << mediaPath;
ofLogFatalError("MediaServer") << ss.str();
exit(EXIT_FAILURE);
}
string MediaServer::getDefaultImageDir(){
return DEFAULT_IMAGES_DIR;
}
string MediaServer::getDefaultVideoDir(){
return DEFAULT_VIDEOS_DIR;
}
string MediaServer::getDefaultMediaDir(int sourceType){
if(sourceType == SourceType::SOURCE_TYPE_IMAGE){
return getDefaultImageDir();
}else if(sourceType == SourceType::SOURCE_TYPE_VIDEO){
return getDefaultVideoDir();
}else{
stringstream ss;
ss << "Could not get default media dir. Unknown source type: " << sourceType;
ofLogFatalError("MediaServer") << ss.str();
exit(EXIT_FAILURE);
}
}
void MediaServer::addFboSource(ofx::piMapper::FboSource & fboSource){
ofLogNotice("MediaServer") << "Attempting to add FBO source with name " << fboSource.getName();
// FBO source has to be with unique name
for(int i = 0; i < fboSources.size(); i++){
if(fboSources[i]->getName() == fboSource.getName()){
ofLogWarning("MediaServer") << "Attempt to add FBO source with duplicate name";
ofExit(EXIT_FAILURE); // Here we definitely need to fail to avoid confusion
}
}
ofLogNotice("MediaServer") << "Source new, adding";
fboSources.push_back(&fboSource);
} // addFboSource
BaseSource * MediaServer::loadFboSource(string & fboSourceName){
ofLogNotice("MediaServer") << "Attempting to load FBO source with name " << fboSourceName;
// Search for FBO source name in our storage
FboSource * source = 0;
for(int i = 0; i < fboSources.size(); i++){
if(fboSources[i]->getName() == fboSourceName){
source = fboSources[i];
break;
}
}
// Panic if not in storage
if(source == 0){
ofLogError("MediaServer") << "Attempt to load non existing FBO source: " << fboSourceName;
ofExit(EXIT_FAILURE);
}
// Check if it is loaded/activated
if(loadedSources.count(fboSourceName)){
// Is loaded, increase reference count and return existing
loadedSources[fboSourceName]->referenceCount++;
ofLogNotice("MediaServer") << "Current " << fboSourceName << "reference count: " << loadedSources[fboSourceName]->referenceCount;
return loadedSources[fboSourceName];
}
// else
// Not loaded, add to loaded sources and activate
// source var should be set by now
source->addAppListeners();
source->referenceCount = 1;
ofLogNotice("MediaServer") << "Current " << fboSourceName << " reference count: " << source->referenceCount;
loadedSources[fboSourceName] = source;
return loadedSources[fboSourceName];
} // loadFboSource
void MediaServer::unloadFboSource(string & fboSourceName){
ofLogNotice("MediaServer") << "Attempt to unload FBO source " << fboSourceName;
// Check if loaded at all
if(!loadedSources.count(fboSourceName)){
ofLogWarning("MediaServer") << "FBO source not loaded";
return;
}
// TODO: remove static cast, make the sources handle reference counting,
// enabling and disabling by themselves
FboSource * source = static_cast <FboSource *>(loadedSources[fboSourceName]);
// else decrease reference count
source->referenceCount--;
ofLogNotice("MediaServer") << "Current " << fboSourceName << "reference count: " << loadedSources[fboSourceName]->referenceCount;
// If no references left, disable
if(source->referenceCount <= 0){
ofLogNotice("MediaServer") << fboSourceName << " reference count <= 0, removing from loaded sources";
source->referenceCount = 0;
source->removeAppListeners();
map <string, BaseSource *>::iterator it = loadedSources.find(fboSourceName);
loadedSources.erase(it);
ofLogNotice("MediaServer") << "Source count after FBO source removal: " << loadedSources.size() << endl;
ofNotifyEvent(onFboSourceUnloaded, fboSourceName, this);
}
} // unloadFboSource
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