diff --git a/Mixer.cpp b/Mixer.cpp index 75adbc5..eb761b2 100644 --- a/Mixer.cpp +++ b/Mixer.cpp @@ -212,10 +212,20 @@ void Mixer::update() // delete sources which failed update (one by one) Source *failure = session()->failedSource(); if (failure != nullptr) { - MediaSource *failedFile = dynamic_cast(failure); - if (failedFile != nullptr) { - Settings::application.recentImport.remove( failedFile->path() ); + // failed media: remove it from the list of imports + MediaSource *failedMedia = dynamic_cast(failure); + if (failedMedia != nullptr) { + Settings::application.recentImport.remove( failedMedia->path() ); } + // failed Render loopback: replace it with one matching the current session + RenderSource *failedRender = dynamic_cast(failure); + if (failedRender != nullptr) { + RenderSource *fixedRender = new RenderSource; + replaceSource(failedRender, fixedRender); + fixedRender->setSession(session_); + failure = nullptr; // prevent delete (already done in replace) + } + // delete the source deleteSource(failure, false); } @@ -282,7 +292,8 @@ Source * Mixer::createSourceFile(const std::string &path) Source * Mixer::createSourceRender() { // ready to create a source - RenderSource *s = new RenderSource(session_); + RenderSource *s = new RenderSource; + s->setSession(session_); // propose a new name based on session name s->setName(SystemToolkit::base_filename(session_->filename())); @@ -411,6 +422,39 @@ void Mixer::insertSource(Source *s, View::Mode m) } } + +void Mixer::replaceSource(Source *from, Source *to) +{ + if ( from != nullptr && to != nullptr) + { + // rename + renameSource(to, from->name()); + + // remove source Nodes from all views + detach(from); + + // copy all transforms + to->group(View::MIXING)->copyTransform( from->group(View::MIXING) ); + to->group(View::GEOMETRY)->copyTransform( from->group(View::GEOMETRY) ); + to->group(View::LAYER)->copyTransform( from->group(View::LAYER) ); + to->group(View::MIXING)->copyTransform( from->group(View::MIXING) ); + + // TODO copy all filters + + + // add sources Nodes to all views + attach(to); + + // add source + session_->addSource(to); + + // delete source + session_->deleteSource(from); + + } + +} + void Mixer::deleteSource(Source *s, bool withundo) { if ( s != nullptr ) diff --git a/Mixer.h b/Mixer.h index bbf6f8d..bbdab79 100644 --- a/Mixer.h +++ b/Mixer.h @@ -109,6 +109,7 @@ protected: SourceList candidate_sources_; SourceList stash_; void insertSource(Source *s, View::Mode m = View::INVALID); + void replaceSource(Source *from, Source *to); void setCurrentSource(SourceList::iterator it); SourceList::iterator current_source_; diff --git a/Session.cpp b/Session.cpp index dd11458..90869d7 100644 --- a/Session.cpp +++ b/Session.cpp @@ -7,6 +7,7 @@ #include "GarbageVisitor.h" #include "FrameGrabber.h" #include "SessionCreator.h" +#include "SessionSource.h" #include "Log.h" @@ -15,7 +16,7 @@ Session::Session() : failedSource_(nullptr), active_(true), fading_target_(0.f) filename_ = ""; config_[View::RENDERING] = new Group; - config_[View::RENDERING]->scale_ = FrameBuffer::getResolutionFromParameters(Settings::application.render.ratio, Settings::application.render.res); + config_[View::RENDERING]->scale_ = glm::vec3(0.f); config_[View::GEOMETRY] = new Group; config_[View::GEOMETRY]->scale_ = Settings::application.views[View::GEOMETRY].default_scale; @@ -63,11 +64,21 @@ void Session::setActive (bool on) // update all sources void Session::update(float dt) { - failedSource_ = nullptr; + // no update until render view is initialized + if ( render_.frame() == nullptr ) + return; // pre-render of all sources + failedSource_ = nullptr; for( SourceList::iterator it = sources_.begin(); it != sources_.end(); it++){ + // ensure the RenderSource is rendering this session + RenderSource *s = dynamic_cast( *it ); + if ( s!= nullptr ){ + if ( s->session() != this /*|| s->session()->frame()->resolution() != frame()->resolution()*/) + s->setSession(nullptr); // RenderSource will fail and be replaced + } + if ( (*it)->failed() ) { failedSource_ = (*it); } diff --git a/SessionCreator.cpp b/SessionCreator.cpp index 3b70823..6604c1d 100644 --- a/SessionCreator.cpp +++ b/SessionCreator.cpp @@ -85,12 +85,12 @@ void SessionCreator::load(const std::string& filename) // session file seems legit, create a session session_ = new Session; + // load views config (includes resolution of session rendering) + loadConfig( xmlDoc_.FirstChildElement("Views") ); + // ready to read sources SessionLoader::load( xmlDoc_.FirstChildElement("Session") ); - // load optionnal config - loadConfig( xmlDoc_.FirstChildElement("Views") ); - // all good session_->setFilename(filename); } @@ -145,7 +145,7 @@ void SessionLoader::load(XMLElement *sessionNode) load_source = new SessionSource; } else if ( std::string(pType) == "RenderSource") { - load_source = new RenderSource(session_); + load_source = new RenderSource; } else if ( std::string(pType) == "PatternSource") { load_source = new PatternSource; @@ -245,7 +245,7 @@ Source *SessionLoader::cloneOrCreateSource(tinyxml2::XMLElement *sourceNode) load_source = new SessionSource; } else if ( std::string(pType) == "RenderSource") { - load_source = new RenderSource(session_); + load_source = new RenderSource; } else if ( std::string(pType) == "PatternSource") { load_source = new PatternSource; @@ -534,6 +534,11 @@ void SessionLoader::visit (SessionSource& s) } +void SessionLoader::visit (RenderSource& s) +{ + s.setSession( session_ ); +} + void SessionLoader::visit (PatternSource& s) { uint t = xmlCurrent_->UnsignedAttribute("pattern"); diff --git a/SessionCreator.h b/SessionCreator.h index a1233fb..bc504da 100644 --- a/SessionCreator.h +++ b/SessionCreator.h @@ -48,6 +48,7 @@ public: void visit (Source& s) override; void visit (MediaSource& s) override; void visit (SessionSource& s) override; + void visit (RenderSource& s) override; void visit (PatternSource& s) override; void visit (DeviceSource& s) override; void visit (NetworkSource& s) override; diff --git a/SessionSource.cpp b/SessionSource.cpp index ac61a6b..ae4cebf 100644 --- a/SessionSource.cpp +++ b/SessionSource.cpp @@ -95,6 +95,7 @@ Session *SessionSource::detach() // make disabled initialized_ = false; + // ask to delete me failed_ = true; @@ -165,7 +166,7 @@ void SessionSource::init() texturesurface_->setTextureIndex( session_->frame()->texture() ); // create Frame buffer matching size of session - FrameBuffer *renderbuffer = new FrameBuffer( session_->frame()->resolution()); + FrameBuffer *renderbuffer = new FrameBuffer( session_->frame()->resolution() ); // set the renderbuffer of the source and attach rendering nodes attach(renderbuffer); @@ -175,12 +176,13 @@ void SessionSource::init() wait_for_sources_ = true; else { initialized_ = true; - Log::Info("New Session created."); + Log::Info("New Session created %d x %d.", session_->frame()->width(), session()->frame()->height()); } } } - if (initialized_){ + if (initialized_) + { // remove the loading icon Node *loader = overlays_[View::TRANSITION]->back(); overlays_[View::TRANSITION]->detach(loader); @@ -229,7 +231,8 @@ void SessionSource::accept(Visitor& v) } -RenderSource::RenderSource(Session *session) : Source(), session_(session) + +RenderSource::RenderSource() : Source(), session_(nullptr) { // set symbol symbol_ = new Symbol(Symbol::RENDER, glm::vec3(0.75f, 0.75f, 0.01f)); @@ -239,20 +242,20 @@ RenderSource::RenderSource(Session *session) : Source(), session_(session) bool RenderSource::failed() const { - return session_ == nullptr; + return (initialized_ && session_ == nullptr); } uint RenderSource::texture() const { - if (session_ == nullptr) - return Resource::getTextureBlack(); - else + if (session_ && session_->frame()) return session_->frame()->texture(); + else + return Resource::getTextureBlack(); // getTextureTransparent ? } void RenderSource::init() { - if (session_ && session_->frame()->texture() != Resource::getTextureBlack()) { + if (session_ && session_->frame() && session_->frame()->texture() != Resource::getTextureBlack()) { FrameBuffer *fb = session_->frame(); @@ -260,7 +263,7 @@ void RenderSource::init() texturesurface_->setTextureIndex( fb->texture() ); // create Frame buffer matching size of output session - FrameBuffer *renderbuffer = new FrameBuffer( fb->resolution()); + FrameBuffer *renderbuffer = new FrameBuffer( fb->resolution() ); // set the renderbuffer of the source and attach rendering nodes attach(renderbuffer); diff --git a/SessionSource.h b/SessionSource.h index 30202f2..44f33ec 100644 --- a/SessionSource.h +++ b/SessionSource.h @@ -43,13 +43,16 @@ protected: class RenderSource : public Source { public: - RenderSource(Session *session); + RenderSource(); // implementation of source API - bool failed() const override; + bool failed () const override; uint texture() const override; void accept (Visitor& v) override; + inline Session *session () const { return session_; } + inline void setSession (Session *se) { session_ = se; } + glm::ivec2 icon() const override { return glm::ivec2(0, 2); } protected: diff --git a/Source.cpp b/Source.cpp index 020bb23..4364ec0 100644 --- a/Source.cpp +++ b/Source.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -14,6 +15,7 @@ #include "ImageShader.h" #include "ImageProcessingShader.h" #include "SystemToolkit.h" +#include "SessionVisitor.h" #include "Log.h" #include "Mixer.h" @@ -350,6 +352,13 @@ void Source::render() void Source::attach(FrameBuffer *renderbuffer) { + // invalid argument +// if (renderbuffer == nullptr) +// return; + +// // replace renderbuffer_ +// if (renderbuffer_) +// delete renderbuffer_; renderbuffer_ = renderbuffer; // if a symbol is available, add it to overlay @@ -451,9 +460,9 @@ float sin_quad(float x, float y) { } -float Source::depth() +float Source::depth() const { - return groups_[View::RENDERING]->translation_.z; + return group(View::RENDERING)->translation_.z; } void Source::setDepth(float d) @@ -462,7 +471,7 @@ void Source::setDepth(float d) touch(); } -float Source::alpha() +float Source::alpha() const { return blendingShader()->color.a; } @@ -668,6 +677,27 @@ void Source::setMask(FrameBufferImage *img) } +std::string Source::xml(Source *s) +{ + std::string x = ""; + + tinyxml2::XMLDocument xmlDoc; + tinyxml2::XMLElement *selectionNode = xmlDoc.NewElement(APP_NAME); + selectionNode->SetAttribute("size", 1); + xmlDoc.InsertEndChild(selectionNode); + + SessionVisitor sv(&xmlDoc, selectionNode); + s->accept(sv); + + // get compact string + tinyxml2::XMLPrinter xmlPrint(0, true); + xmlDoc.Print( &xmlPrint ); + x = xmlPrint.CStr(); + + return x; +} + + bool Source::hasNode::operator()(const Source* elem) const { if (_n && elem) diff --git a/Source.h b/Source.h index ef98091..5f689ea 100644 --- a/Source.h +++ b/Source.h @@ -97,12 +97,12 @@ public: virtual void update (float dt); // update mode + inline bool active () const { return active_; } virtual void setActive (bool on); - inline bool active () const { return active_; } // lock mode + inline bool locked () const { return locked_; } virtual void setLocked (bool on); - inline bool locked () const { return locked_; } // Workspace typedef enum { @@ -125,15 +125,16 @@ public: virtual void accept (Visitor& v); // operations on mask - void storeMask(FrameBufferImage *img = nullptr); - FrameBufferImage *getMask() const { return maskimage_; } - void setMask(FrameBufferImage *img); + inline FrameBufferImage *getMask () const { return maskimage_; } + void setMask (FrameBufferImage *img); + void storeMask (FrameBufferImage *img = nullptr); - float depth(); - void setDepth(float d); + float depth () const; + void setDepth (float d); + + float alpha () const; + void setAlpha (float a); - float alpha(); - void setAlpha(float a); struct hasNode: public std::unary_function { @@ -165,6 +166,9 @@ public: virtual glm::ivec2 icon () const { return glm::ivec2(12, 11); } + // get the xml description text of a source + static std::string xml(Source *s); + protected: // name std::string name_; diff --git a/View.cpp b/View.cpp index 9ddc490..bc152d5 100644 --- a/View.cpp +++ b/View.cpp @@ -651,8 +651,6 @@ uint MixingView::textureMixingQuadratic() RenderView::RenderView() : View(RENDERING), frame_buffer_(nullptr), fading_overlay_(nullptr) { - // set resolution to settings default - setResolution(); } RenderView::~RenderView() @@ -710,12 +708,14 @@ void RenderView::draw() { static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -SCENE_DEPTH, 1.f); - // draw in frame buffer - glm::mat4 P = glm::scale( projection, glm::vec3(1.f / frame_buffer_->aspectRatio(), 1.f, 1.f)); - frame_buffer_->begin(); - scene.root()->draw(glm::identity(), P); - fading_overlay_->draw(glm::identity(), projection); - frame_buffer_->end(); + if (frame_buffer_) { + // draw in frame buffer + glm::mat4 P = glm::scale( projection, glm::vec3(1.f / frame_buffer_->aspectRatio(), 1.f, 1.f)); + frame_buffer_->begin(); + scene.root()->draw(glm::identity(), P); + fading_overlay_->draw(glm::identity(), projection); + frame_buffer_->end(); + } } GeometryView::GeometryView() : View(GEOMETRY)