diff --git a/src/MediaServer/DirectoryWatcher.h b/src/MediaServer/DirectoryWatcher.h index 8df11bb..cbc53db 100644 --- a/src/MediaServer/DirectoryWatcher.h +++ b/src/MediaServer/DirectoryWatcher.h @@ -28,9 +28,18 @@ class VideoPathFilter : public BasePathFilter { virtual ~VideoPathFilter() {}; bool accept(const Poco::Path& path) const { +#ifdef TARGET_RASPBERRY_PI return !Poco::File(path).isHidden() && (ofIsStringInString(path.toString(), ".mp4") || ofIsStringInString(path.toString(), ".h264")); +#else + 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")); +#endif } }; diff --git a/src/MediaServer/MediaServer.cpp b/src/MediaServer/MediaServer.cpp index 4d1e7cb..6d16ce1 100644 --- a/src/MediaServer/MediaServer.cpp +++ b/src/MediaServer/MediaServer.cpp @@ -28,9 +28,6 @@ namespace piMapper { std::vector& MediaServer::getImagePaths() { return imageWatcher.getFilePaths(); } - std::vector& MediaServer::getVideoPaths() { - return videoWatcher.getFilePaths(); - } std::vector MediaServer::getImageNames() { std::vector imageNames; @@ -44,6 +41,25 @@ namespace piMapper { return imageNames; } + std::vector& MediaServer::getVideoPaths() { + return videoWatcher.getFilePaths(); + } + + std::vector MediaServer::getVideoNames() { + cout << "nuVideos: " << getNumVideos() << endl; + std::vector videoNames; + for (int i = 0; i < getNumVideos(); i++) { + // Split video path + std::vector 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) { @@ -97,13 +113,11 @@ namespace piMapper { } void MediaServer::unloadImage(string& path) { - ImageSource* source = static_cast(getSourceByPath(path)); - // Decrease reference count of the image - //referenceCount[path]--; + ofLogNotice("MediaServer") << "Unload image, current reference count: " << source->referenceCount; source->referenceCount--; // Unload only if reference count is less or equal to 0 - cout << "referenceCount: " << source->referenceCount << endl; + ofLogNotice("MediaServer") << "New reference count: " << source->referenceCount; if (source->referenceCount > 0) { ofLogNotice("MediaServer") << "Not unloading image as it is being referenced elsewhere"; return; @@ -114,9 +128,12 @@ namespace piMapper { ofLogNotice("MediaServer") << ss.str(); // Destroy image source if (loadedSources.count(path)) { - //loadedSources[path]->clear(); - delete loadedSources[path]; - loadedSources.erase(path); + ofLogNotice("MediaServer") << "Source count BEFORE image removal: " << loadedSources.size() << endl; + loadedSources[path]->clear(); + std::map::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; } @@ -139,7 +156,6 @@ namespace piMapper { // If is loaded if (isVideoLoaded) { // Increase reference count of this source - //referenceCount[path]++; videoSource->referenceCount++; std::stringstream refss; refss << "Current reference count for " << path << " = " << videoSource->referenceCount; @@ -175,14 +191,15 @@ namespace piMapper { return; } // Reference count 0 or less, let's unload the video - std::stringstream ss; - ss << "Removing video " << path; - ofLogNotice("MediaServer") << ss.str(); + ofLogNotice("MediaServer") << "Removing video " << path; // Distroy video source if (loadedSources.count(path)) { - loadedSources[path]->clear(); - delete loadedSources[path]; - loadedSources.erase(path); + ofLogNotice("MediaServer") << "Source count before video removal: " << loadedSources.size() << endl; + videoSource->clear(); + std::map::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; } @@ -223,7 +240,6 @@ namespace piMapper { } BaseSource* MediaServer::getSourceByPath(std::string& mediaPath) { - cout << "num loaded sources: " << loadedSources.size() << endl; if (loadedSources.count(mediaPath)) { return loadedSources[mediaPath]; } diff --git a/src/MediaServer/MediaServer.h b/src/MediaServer/MediaServer.h index 8cb3bfd..3e700e1 100644 --- a/src/MediaServer/MediaServer.h +++ b/src/MediaServer/MediaServer.h @@ -28,9 +28,10 @@ class MediaServer { int getNumVideos(); int getNumImages(); - std::vector& getVideoPaths(); - std::vector& getImagePaths(); - std::vector getImageNames(); + std::vector& getVideoPaths(); + std::vector getVideoNames(); + std::vector& getImagePaths(); + std::vector getImageNames(); BaseSource* loadMedia(string& path, int mediaType); BaseSource* loadImage(string& path); diff --git a/src/Sources/BaseSource.cpp b/src/Sources/BaseSource.cpp index 66f7691..29ceda6 100644 --- a/src/Sources/BaseSource.cpp +++ b/src/Sources/BaseSource.cpp @@ -12,6 +12,10 @@ namespace ofx { texture = newTexture; } + BaseSource::~BaseSource() { + cout << "BaseSource destr" << endl; + } + ofTexture* BaseSource::getTexture() { return texture; } diff --git a/src/Sources/BaseSource.h b/src/Sources/BaseSource.h index 4970c5e..fb5e567 100644 --- a/src/Sources/BaseSource.h +++ b/src/Sources/BaseSource.h @@ -10,6 +10,7 @@ namespace ofx { 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 diff --git a/src/Sources/ImageSource.cpp b/src/Sources/ImageSource.cpp index 8042baf..5c4388a 100644 --- a/src/Sources/ImageSource.cpp +++ b/src/Sources/ImageSource.cpp @@ -9,9 +9,7 @@ namespace ofx { type = SourceType::SOURCE_TYPE_IMAGE; } - ImageSource::~ImageSource() { - clear(); - } + ImageSource::~ImageSource() {} void ImageSource::loadImage(std::string& filePath) { path = filePath; @@ -32,8 +30,8 @@ namespace ofx { image->clear(); delete image; image = NULL; - path = ""; - name = ""; + //path = ""; + //name = ""; loaded = false; } diff --git a/src/Sources/VideoSource.cpp b/src/Sources/VideoSource.cpp index 1c3fcb4..1e72847 100644 --- a/src/Sources/VideoSource.cpp +++ b/src/Sources/VideoSource.cpp @@ -3,14 +3,14 @@ namespace ofx { namespace piMapper { VideoSource::VideoSource() { + cout << "VideoSource constr" << endl; loadable = true; loaded = false; type = SourceType::SOURCE_TYPE_VIDEO; + videoPlayer = NULL; } - VideoSource::~VideoSource() { - clear(); - } + VideoSource::~VideoSource() {} void VideoSource::loadVideo(std::string& filePath) { path = filePath; @@ -47,8 +47,8 @@ namespace ofx { delete videoPlayer; videoPlayer = NULL; #endif - path = ""; - name = ""; + //path = ""; + //name = ""; loaded = false; } @@ -59,7 +59,9 @@ namespace ofx { // probably needs updating as well // #else - videoPlayer->update(); + if (videoPlayer != NULL) { + videoPlayer->update(); + } #endif } } diff --git a/src/SourcesEditor.cpp b/src/SourcesEditor.cpp index 1d3d0fc..fc6e788 100644 --- a/src/SourcesEditor.cpp +++ b/src/SourcesEditor.cpp @@ -4,42 +4,15 @@ 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; - - cout << "numImages: " << mediaServer->getNumImages() << endl; - /* - cout << "list: " << endl; - for (int i = 0; i < mediaServer->getNumImages(); i++) { - cout << mediaServer->getImagePaths()[i] << endl; - } - */ - - cout << "numVideos: " << mediaServer->getNumVideos() << endl; - /* - cout << "list: " << endl; - for (int i = 0; i < mediaServer->getNumVideos(); i++) { - cout << mediaServer->getImagePaths()[i] << endl; - } - */ - addMediaServerListeners(); - - // Test media server onImageLoaded event - /* - if (mediaServer->getNumImages()) { - mediaServer->loadImage(mediaServer->getImagePaths()[0]); - } - */ - } SourcesEditor::SourcesEditor(MediaServer* externalMediaServer) { init(); - // Assign external MediaServer instance pointer mediaServer = externalMediaServer; isMediaServerExternal = true; @@ -48,12 +21,8 @@ namespace piMapper { SourcesEditor::~SourcesEditor() { unregisterAppEvents(); - delete gui; - while (images.size()) { - delete images.back(); - images.pop_back(); - } - + delete imageSelector; + delete videoSelector; removeMediaServerListeners(); clearMediaServer(); } @@ -67,40 +36,48 @@ namespace piMapper { } void SourcesEditor::setup(ofEventArgs& args) { - gui = new RadioList(); + imageSelector = new RadioList(); + videoSelector = new RadioList(); // Get image names from media server - vector vnames = mediaServer->getImageNames(); - gui->setup("Images", vnames, mediaServer->getImagePaths()); - gui->setPosition(20, 20); - // Add radio selected event listener so we can load sources - ofAddListener(gui->onRadioSelected, this, &SourcesEditor::handleRadioSelected); + vector imageNames = mediaServer->getImageNames(); + imageSelector->setup("Images", imageNames, mediaServer->getImagePaths()); + imageSelector->setPosition(20, 20); + ofAddListener(imageSelector->onRadioSelected, this, &SourcesEditor::handleImageSelected); + vector videoNames = mediaServer->getVideoNames(); + cout << "list video names: " << endl; + for (int i = 0; i < videoNames.size(); i++) { + cout << videoNames[i] << endl; + } + videoSelector->setup("Videos", videoNames, mediaServer->getVideoPaths()); + videoSelector->setPosition(250, 20); + ofAddListener(videoSelector->onRadioSelected, this, &SourcesEditor::handleVideoSelected); } void SourcesEditor::draw() { // Don't draw if there is no source selected if (surfaceManager->getSelectedSurface() == NULL) { + ofLogNotice("SourcesEditor") << "No surface selected"; return; } - gui->draw(); + imageSelector->draw(); + videoSelector->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() { + imageSelector->disable(); + videoSelector->disable(); } - 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; + ofLogNotice("SourcesEditor") << "No surface selected. Not enabling and not showing source list."; return; } - - gui->enable(); + imageSelector->enable(); + videoSelector->enable(); + BaseSource* source = surfaceManager->getSelectedSurface()->getSource(); + selectSourceRadioButton(source->getPath()); } void SourcesEditor::setSurfaceManager(SurfaceManager* newSurfaceManager) { @@ -122,35 +99,27 @@ namespace piMapper { isMediaServerExternal = true; } - void SourcesEditor::selectImageSourceRadioButton(string name) { - if (name == "none") { - gui->unselectAll(); + void SourcesEditor::selectSourceRadioButton(std::string& sourcePath) { + if (sourcePath == "") { + ofLogNotice("SourcesEditor") << "Path is empty"; + imageSelector->unselectAll(); + videoSelector->unselectAll(); return; } else { - int i; - for (i = 0; i < gui->size(); i++) { - if (gui->getItemName(i) == name) { - gui->selectItem(i); - return; - } + // Check image selector first + bool imageRadioSelected = imageSelector->selectItemByValue(sourcePath); + bool 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"; } } - - 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::init() { mediaServer = NULL; // Pointers to NULL pointer so we can check later isMediaServerExternal = false; - defImgDir = DEFAULT_IMAGES_DIR; registerAppEvents(); } @@ -160,7 +129,6 @@ namespace piMapper { 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); @@ -177,7 +145,6 @@ namespace piMapper { 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); @@ -187,16 +154,38 @@ namespace piMapper { ofRemoveListener(mediaServer->onImageUnloaded, this, &SourcesEditor::handleImageUnloaded); } - void SourcesEditor::handleRadioSelected(string& sourcePath) { + 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()); } - surface->setSource(mediaServer->loadImage(sourcePath)); + // Load new video + surface->setSource(mediaServer->loadVideo(videoPath)); } void SourcesEditor::clearMediaServer() { @@ -232,8 +221,8 @@ namespace piMapper { // Test image unload // mediaServer->unloadImage(path); - BaseSource* source = mediaServer->getSourceByPath(path); - surfaceManager->getSelectedSurface()->setSource(source); + //BaseSource* source = mediaServer->getSourceByPath(path); + //surfaceManager->getSelectedSurface()->setSource(source); } void SourcesEditor::handleImageUnloaded(string& path) { diff --git a/src/SourcesEditor.h b/src/SourcesEditor.h index 0e814ec..e0edecc 100644 --- a/src/SourcesEditor.h +++ b/src/SourcesEditor.h @@ -30,7 +30,8 @@ class SourcesEditor { // Sets external MediaServer void setMediaServer(MediaServer* newMediaServer); - void selectImageSourceRadioButton(string name); + //void selectImageSourceRadioButton(string name); + void selectSourceRadioButton(std::string& sourcePath); int getLoadedTexCount(); ofTexture* getTexture(int index); @@ -38,10 +39,8 @@ class SourcesEditor { private: MediaServer* mediaServer; SurfaceManager* surfaceManager; - RadioList* gui; - string defImgDir; - vector images; - vector imageNames; + 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. @@ -55,7 +54,8 @@ class SourcesEditor { void removeMediaServerListeners(); // Handles GUI event, whenever someone has clicked on a radio button - void handleRadioSelected(string& sourcePath); + void handleImageSelected(string& imagePath); + void handleVideoSelected(string& videoPath); // Careful clearing of the media server, // clears only if the media server has been initialized locally diff --git a/src/ui/RadioList.cpp b/src/ui/RadioList.cpp index b6ef444..804943b 100644 --- a/src/ui/RadioList.cpp +++ b/src/ui/RadioList.cpp @@ -72,6 +72,30 @@ void RadioList::selectItem(int index) { ofNotifyEvent(onRadioSelected, value, this); storedSelectedItem = index; } + + bool RadioList::selectItemByValue(std::string itemValue) { + if (itemValue == "") { + ofLogNotice("RadioList") << "Item value empty"; + return false; + } + unselectAll(); + int itemIndex = -1; + for (int i = 0; i < storedValues.size(); i++) { + if (itemValue == storedValues[i]) { + itemIndex = i; + break; + } + } + if (itemIndex >= 0) { + ofxToggle* toggle = static_cast(guiGroup.getControl(itemIndex)); + toggle->removeListener(this, &RadioList::onToggleClicked); + *toggle = true; // Select the specific radio button + toggle->addListener(this, &RadioList::onToggleClicked); + return true; + } + ofLogNotice("RadioList") << "Item with value " << itemValue << " not found"; + return false; + } void RadioList::enable() { if (guiGroup.getNumControls() >= 0) { diff --git a/src/ui/RadioList.h b/src/ui/RadioList.h index 2926f2a..c0e1daf 100644 --- a/src/ui/RadioList.h +++ b/src/ui/RadioList.h @@ -21,6 +21,7 @@ class RadioList { void setPosition(ofPoint p); void setPosition(float x, float y); void selectItem(int index); + bool selectItemByValue(std::string itemValue); void enable(); void disable(); void clear();