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.
 
 

443 lines
15 KiB

#include "MediaServer.h"
namespace ofx {
namespace piMapper {
// relative pathss as default, absolute Paths for RASPI
#ifdef TARGET_RASPBERRY_PI
bool absolutePathSwitch = true;
#else
bool absolutePathSwitch = false;
#endif
MediaServer::MediaServer() :
piVideoWatcher(PI_IMAGES_DIR, SourceType::SOURCE_TYPE_VIDEO),
usb0VideoWatcher(USB0_VIDEOS_DIR, SourceType::SOURCE_TYPE_VIDEO),
usb1VideoWatcher(USB1_VIDEOS_DIR, SourceType::SOURCE_TYPE_VIDEO),
usb2VideoWatcher(USB2_VIDEOS_DIR, SourceType::SOURCE_TYPE_VIDEO),
usb3VideoWatcher(USB3_VIDEOS_DIR, SourceType::SOURCE_TYPE_VIDEO),
piImageWatcher(PI_IMAGES_DIR, SourceType::SOURCE_TYPE_IMAGE),
usb0ImageWatcher(USB0_IMAGES_DIR, SourceType::SOURCE_TYPE_IMAGE),
usb1ImageWatcher(USB1_IMAGES_DIR, SourceType::SOURCE_TYPE_IMAGE),
usb2ImageWatcher(USB2_IMAGES_DIR, SourceType::SOURCE_TYPE_IMAGE),
usb3ImageWatcher(USB3_IMAGES_DIR, SourceType::SOURCE_TYPE_IMAGE),
imageWatcher(ofToDataPath(DEFAULT_IMAGES_DIR, absolutePathSwitch), SourceType::SOURCE_TYPE_IMAGE),
videoWatcher(ofToDataPath(DEFAULT_VIDEOS_DIR, absolutePathSwitch), SourceType::SOURCE_TYPE_VIDEO)
{
// By initialising all above we also copy files from external media
// to the ofxPiMapper storage.
imageWatcher.beginWatch();
// imageWatcher = DirectoryWatcher(
// ofToDataPath(DEFAULT_IMAGES_DIR, true),
// SourceType::SOURCE_TYPE_IMAGE);
// imageWatcher.beginWatch();
//
// videoWatcher = DirectoryWatcher(
// ofToDataPath(DEFAULT_VIDEOS_DIR, true),
// SourceType::SOURCE_TYPE_VIDEO);
}
void MediaServer::setup(){
// We could setup sources here, but the sources are
// set up while adding them to media server. For now
// This method is here just to keep things consistent.
}
void MediaServer::update(){
for(int i = 0; i < fboSources.size(); ++i){
if (fboSources[i]->isActive() || fboSources[i]->runsInBackground()) fboSources[i]->updateFbo();
}
}
void MediaServer::draw(){
for(int i = 0; i < fboSources.size(); ++i){
if (fboSources[i]->isActive() || fboSources[i]->runsInBackground()) fboSources[i]->drawFbo();
}
}
void MediaServer::restart() {
typedef map <std::string, BaseSource *>::iterator it_type;
for(it_type i = loadedSources.begin(); i != loadedSources.end(); i++){
if(i->second->getType() == SourceType::SOURCE_TYPE_VIDEO){
static_cast <VideoSource *>(i->second)->restart();
}
}
}
void MediaServer::pause() {
typedef map <std::string, BaseSource *>::iterator it_type;
for(it_type i = loadedSources.begin(); i != loadedSources.end(); i++){
if(i->second->getType() == SourceType::SOURCE_TYPE_VIDEO){
static_cast <VideoSource *>(i->second)->pause();
}
}
}
void MediaServer::resume() {
typedef map <std::string, BaseSource *>::iterator it_type;
for(it_type i = loadedSources.begin(); i != loadedSources.end(); i++){
if(i->second->getType() == SourceType::SOURCE_TYPE_VIDEO){
static_cast <VideoSource *>(i->second)->resume();
}
}
}
int MediaServer::getNumImages(){
return imageWatcher.getFilePaths().size();
}
int MediaServer::getNumVideos(){
return videoWatcher.getFilePaths().size();
}
int MediaServer::getNumFboSources(){
return fboSources.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::getFboSourceNames(){
std::vector<std::string> fboSourceNames;
for(int i = 0; i < fboSources.size(); i++){
fboSourceNames.push_back(fboSources[i]->getName());
}
return fboSourceNames;
}
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(std::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{
std::stringstream ss;
ss << "Can not load media of unknown type: " << mediaType;
ofLogFatalError("MediaServer") << ss.str();
std::exit(EXIT_FAILURE);
}
return 0;
}
BaseSource * MediaServer::loadImage(std::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++;
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(std::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() << std::endl;
loadedSources[path]->clear();
map <std::string, BaseSource *>::iterator it = loadedSources.find(path);
delete it->second;
loadedSources.erase(it);
ofLogNotice("MediaServer") << "Source count AFTER image removal: " << loadedSources.size() << std::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(std::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++;
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(std::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() << std::endl;
videoSource->clear();
map <std::string, BaseSource *>::iterator it = loadedSources.find(path);
delete it->second;
loadedSources.erase(it);
ofLogNotice("MediaServer")
<< "Source count after video removal: "
<< loadedSources.size() << std::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(std::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";
std::exit(EXIT_FAILURE);
}
}else{
ofLogNotice("MediaServer") << "Nothing to unload";
}
}
// Clear all loaded media
void MediaServer::clear(){
typedef map <std::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(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::addFboSource(ofx::piMapper::FboSource & fboSource){
addFboSource(&fboSource);
}
void MediaServer::addFboSource(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
std::exit(EXIT_FAILURE); // In case the openFrameworks function fails
}
}
ofLogNotice("MediaServer") << "Source new, adding";
fboSources.push_back(fboSource);
// It is important to run the setup of the FBO
// source from outside as we can see here.
fboSource->setup();
}
BaseSource * MediaServer::loadFboSource(std::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;
source->setActive(true);
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;
source->setActive(true);
return loadedSources[fboSourceName];
} // loadFboSource
void MediaServer::unloadFboSource(std::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->setActive(false);
//source->removeAppListeners();
map <std::string, BaseSource *>::iterator it = loadedSources.find(fboSourceName);
loadedSources.erase(it);
ofLogNotice("MediaServer") << "Source count after FBO source removal: " << loadedSources.size() << std::endl;
ofNotifyEvent(onFboSourceUnloaded, fboSourceName, this);
}
} // unloadFboSource
} // namespace piMapper
} // namespace ofx