#include #include #include #include "SessionSource.h" #include "defines.h" #include "Log.h" #include "FrameBuffer.h" #include "ImageShader.h" #include "ImageProcessingShader.h" #include "Resource.h" #include "Primitives.h" #include "Mesh.h" #include "SearchVisitor.h" #include "Session.h" #include "SessionCreator.h" #include "Mixer.h" void SessionSource::loadSession(const std::string& filename, SessionSource *source) { source->loadFinished_ = false; // actual loading of xml file SessionCreator creator( source->session_ ); if (creator.load(filename)) { // all ok, validate session filename source->session_->setFilename(filename); } else { // error loading Log::Notify("Failed to load Session file %s.", filename.c_str()); source->loadFailed_ = true; } // end thread source->loadFinished_ = true; } SessionSource::SessionSource() : Source(), path_("") { // specific node for transition view groups_[View::TRANSITION]->visible_ = false; groups_[View::TRANSITION]->scale_ = glm::vec3(0.1f, 0.1f, 1.f); groups_[View::TRANSITION]->translation_ = glm::vec3(-1.f, 0.f, 0.f); frames_[View::TRANSITION] = new Switch; Frame *frame = new Frame(Frame::ROUND, Frame::THIN, Frame::DROP); frame->translation_.z = 0.1; frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 0.9f); frames_[View::TRANSITION]->attach(frame); frame = new Frame(Frame::ROUND, Frame::LARGE, Frame::DROP); frame->translation_.z = 0.01; frame->color = glm::vec4( COLOR_TRANSITION_SOURCE, 1.f); frames_[View::TRANSITION]->attach(frame); groups_[View::TRANSITION]->attach(frames_[View::TRANSITION]); overlays_[View::TRANSITION] = new Group; overlays_[View::TRANSITION]->translation_.z = 0.1; overlays_[View::TRANSITION]->visible_ = false; Symbol *center = new Symbol(Symbol::GENERIC, glm::vec3(0.f, -1.05f, 0.1f)); overlays_[View::TRANSITION]->attach(center); groups_[View::TRANSITION]->attach(overlays_[View::TRANSITION]); loadFailed_ = false; loadFinished_ = false; wait_for_sources_ = false; session_ = new Session; // create surface: // - textured with original texture from session // - crop & repeat UV can be managed here // - additional custom shader can be associated sessionsurface_ = new Surface(rendershader_); } SessionSource::~SessionSource() { // delete surface delete sessionsurface_; // delete session if (session_) delete session_; } void SessionSource::load(const std::string &p) { path_ = p; // launch a thread to load the session std::thread ( SessionSource::loadSession, path_, this).detach(); Log::Notify("Opening %s", p.c_str()); } Session *SessionSource::detach() { // remember pointer to give away Session *giveaway = session_; // work on a new session session_ = new Session; // make disabled initialized_ = false; loadFailed_ = true; return giveaway; } bool SessionSource::failed() const { return loadFailed_; } uint SessionSource::texture() const { if (session_ == nullptr) return Resource::getTextureBlack(); return session_->frame()->texture(); } void SessionSource::init() { if (session_ == nullptr) return; if (wait_for_sources_) { // force update of of all sources active_ = true; touch(); // check that every source is ready.. bool ready = true; for (SourceList::iterator iter = session_->begin(); iter != session_->end(); iter++) { // interrupt if any source is NOT ready if ( !(*iter)->ready() ){ ready = false; break; } } // if all sources are ready, done with initialization! if (ready) { // done init wait_for_sources_ = false; initialized_ = true; Log::Info("Source Session %s loaded %d sources.", path_.c_str(), session_->numSource()); } } if ( loadFinished_ && !loadFailed_ && session_ != nullptr) { loadFinished_ = false; // set resolution session_->setResolution( session_->config(View::RENDERING)->scale_ ); // deep update once to draw framebuffer View::need_deep_update_ = true; session_->update(dt_); // get the texture index from framebuffer of session, apply it to the surface sessionsurface_->setTextureIndex( session_->frame()->texture() ); // create Frame buffer matching size of session FrameBuffer *renderbuffer = new FrameBuffer( session_->frame()->resolution()); // set the renderbuffer of the source and attach rendering nodes attach(renderbuffer); // icon in mixing view overlays_[View::MIXING]->attach( new Symbol(Symbol::SESSION, glm::vec3(0.8f, 0.8f, 0.01f)) ); overlays_[View::LAYER]->attach( new Symbol(Symbol::SESSION, glm::vec3(0.8f, 0.8f, 0.01f)) ); // wait for all sources to init wait_for_sources_ = true; } } void SessionSource::setActive (bool on) { Source::setActive(on); // change status of session (recursive change of internal sources) if (session_ != nullptr) session_->setActive(active_); } void SessionSource::update(float dt) { if (session_ == nullptr) loadFailed_ = true; // update content if (active_) session_->update(dt); // delete a source which failed if (session_->failedSource() != nullptr) { session_->deleteSource(session_->failedSource()); // fail session if all sources failed if ( session_->numSource() < 1) loadFailed_ = true; } Source::update(dt); } void SessionSource::render() { if (!initialized_) init(); else { // render the sesion into frame buffer static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f); renderbuffer_->begin(); sessionsurface_->draw(glm::identity(), projection); renderbuffer_->end(); } } void SessionSource::accept(Visitor& v) { Source::accept(v); v.visit(*this); } RenderSource::RenderSource(Session *session) : Source(), session_(session) { // create surface: sessionsurface_ = new Surface(rendershader_); } RenderSource::~RenderSource() { // delete surface delete sessionsurface_; } bool RenderSource::failed() const { return session_ == nullptr; } uint RenderSource::texture() const { if (session_ == nullptr) return Resource::getTextureBlack(); else return session_->frame()->texture(); } void RenderSource::init() { if (session_ == nullptr) return; if (session_ && session_->frame()->texture() != Resource::getTextureBlack()) { FrameBuffer *fb = session_->frame(); // get the texture index from framebuffer of view, apply it to the surface sessionsurface_->setTextureIndex( fb->texture() ); // create Frame buffer matching size of output session FrameBuffer *renderbuffer = new FrameBuffer( fb->resolution()); // set the renderbuffer of the source and attach rendering nodes attach(renderbuffer); // icon in mixing view overlays_[View::MIXING]->attach( new Symbol(Symbol::RENDER, glm::vec3(0.8f, 0.8f, 0.01f)) ); overlays_[View::LAYER]->attach( new Symbol(Symbol::RENDER, glm::vec3(0.8f, 0.8f, 0.01f)) ); // done init initialized_ = true; Log::Info("Source Render linked to session (%d x %d).", int(fb->resolution().x), int(fb->resolution().y) ); } } void RenderSource::render() { if (!initialized_) init(); else { // render the view into frame buffer static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f); renderbuffer_->begin(); sessionsurface_->draw(glm::identity(), projection); renderbuffer_->end(); } } void RenderSource::accept(Visitor& v) { Source::accept(v); v.visit(*this); }