mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-13 19:29:58 +01:00
New Session class to contain the list of sources. Loading and Saving of
session files in XML. Verified deletion of Nodes, Groups and Sources.
This commit is contained in:
224
Mixer.cpp
224
Mixer.cpp
@@ -1,19 +1,32 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include <tinyxml2.h>
|
||||
#include "tinyxml2Toolkit.h"
|
||||
using namespace tinyxml2;
|
||||
|
||||
#include "defines.h"
|
||||
#include "Log.h"
|
||||
#include "View.h"
|
||||
#include "Primitives.h"
|
||||
#include "Mesh.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "Mixer.h"
|
||||
#include "Settings.h"
|
||||
#include "SystemToolkit.h"
|
||||
#include "ImageProcessingShader.h"
|
||||
#include "SessionVisitor.h"
|
||||
#include "SessionCreator.h"
|
||||
|
||||
Mixer::Mixer()
|
||||
#include "MediaPlayer.h"
|
||||
|
||||
#include "Mixer.h"
|
||||
|
||||
Mixer::Mixer() : session_(nullptr), current_view_(nullptr)
|
||||
{
|
||||
setCurrentView( (View::Mode) Settings::application.current_view );
|
||||
// this initializes with a new empty session
|
||||
newSession();
|
||||
|
||||
current_source_ = Source::end();
|
||||
update_time_ = GST_CLOCK_TIME_NONE;
|
||||
// this initializes with the current view
|
||||
setCurrentView( (View::Mode) Settings::application.current_view );
|
||||
}
|
||||
|
||||
|
||||
@@ -26,13 +39,10 @@ void Mixer::update()
|
||||
float dt = static_cast<float>( GST_TIME_AS_MSECONDS(current_time - update_time_) ) * 0.001f;
|
||||
update_time_ = current_time;
|
||||
|
||||
// render of all sources
|
||||
for( SourceList::iterator it = Source::begin(); it != Source::end(); it++){
|
||||
(*it)->render( it == current_source_ );
|
||||
}
|
||||
// update session and associted sources
|
||||
session_->update(dt);
|
||||
|
||||
// recursive update of ALL views
|
||||
render_.update(dt);
|
||||
// update views
|
||||
mixing_.update(dt);
|
||||
geometry_.update(dt);
|
||||
// TODO other views
|
||||
@@ -40,12 +50,8 @@ void Mixer::update()
|
||||
|
||||
}
|
||||
|
||||
// draw render view and current view
|
||||
void Mixer::draw()
|
||||
{
|
||||
// always draw render view
|
||||
render_.draw();
|
||||
|
||||
// draw the current view in the window
|
||||
current_view_->draw();
|
||||
}
|
||||
@@ -54,44 +60,89 @@ void Mixer::draw()
|
||||
void Mixer::createSourceMedia(std::string uri)
|
||||
{
|
||||
// create source
|
||||
MediaSource *m = new MediaSource("s", uri);
|
||||
MediaSource *m = new MediaSource();
|
||||
m->setURI(uri);
|
||||
|
||||
// add Nodes to ALL views
|
||||
//
|
||||
// Render Node
|
||||
render_.scene.root()->addChild(m->group(View::RENDERING));
|
||||
// propose a new name based on uri
|
||||
renameSource(m, SystemToolkit::base_filename(uri));
|
||||
|
||||
// add to mixer
|
||||
insertSource(m);
|
||||
}
|
||||
|
||||
void Mixer::insertSource(Source *s)
|
||||
{
|
||||
// Add source to Session and set it as current
|
||||
setCurrentSource( session_->addSource(s) );
|
||||
|
||||
// add sources Nodes to ALL views
|
||||
// Mixing Node
|
||||
mixing_.scene.root()->addChild(m->group(View::MIXING));
|
||||
mixing_.scene.root()->addChild(s->group(View::MIXING));
|
||||
// Geometry Node
|
||||
geometry_.scene.root()->addChild(m->group(View::GEOMETRY));
|
||||
geometry_.scene.root()->addChild(s->group(View::GEOMETRY));
|
||||
|
||||
// set source as current
|
||||
current_source_ = Source::begin();
|
||||
}
|
||||
|
||||
void Mixer::renameSource(Source *s, const std::string &newname)
|
||||
{
|
||||
// tentative new name
|
||||
std::string tentativename = newname;
|
||||
|
||||
// refuse to rename to an empty name
|
||||
if ( newname.empty() )
|
||||
tentativename = "source";
|
||||
|
||||
// trivial case : same name as current
|
||||
if ( tentativename == s->name() )
|
||||
return;
|
||||
|
||||
// search for a source of the name 'tentativename'
|
||||
std::string basename = tentativename;
|
||||
int count = 1;
|
||||
while ( std::find_if(session_->begin(), session_->end(), hasName(tentativename)) != session_->end() ) {
|
||||
tentativename = basename + std::to_string(++count);
|
||||
}
|
||||
|
||||
// ok to rename
|
||||
s->setName(tentativename);
|
||||
}
|
||||
|
||||
void Mixer::setCurrentSource(SourceList::iterator it)
|
||||
{
|
||||
unsetCurrentSource();
|
||||
if ( it != session_->end() ) {
|
||||
current_source_ = it;
|
||||
(*current_source_)->setOverlayVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
void Mixer::setCurrentSource(Node *node)
|
||||
{
|
||||
current_source_ = Source::find(node);
|
||||
setCurrentSource( session_->find(node) );
|
||||
}
|
||||
|
||||
void Mixer::setCurrentSource(std::string namesource)
|
||||
{
|
||||
current_source_ = Source::find(namesource);
|
||||
setCurrentSource( session_->find(namesource) );
|
||||
}
|
||||
|
||||
void Mixer::setCurrentSource(Source *s)
|
||||
{
|
||||
current_source_ = Source::find(s);
|
||||
setCurrentSource( session_->find(s) );
|
||||
}
|
||||
|
||||
void Mixer::unsetCurrentSource()
|
||||
{
|
||||
current_source_ = Source::end();
|
||||
// discard overlay for previously current source
|
||||
if ( current_source_ != session_->end() )
|
||||
(*current_source_)->setOverlayVisible(false);
|
||||
// deselect current source
|
||||
current_source_ = session_->end();
|
||||
}
|
||||
|
||||
Source *Mixer::currentSource()
|
||||
{
|
||||
if ( current_source_ == Source::end() )
|
||||
if ( current_source_ == session_->end() )
|
||||
return nullptr;
|
||||
else {
|
||||
return *(current_source_);
|
||||
@@ -117,8 +168,6 @@ void Mixer::setCurrentView(View::Mode m)
|
||||
View *Mixer::getView(View::Mode m)
|
||||
{
|
||||
switch (m) {
|
||||
case View::RENDERING:
|
||||
return &render_;
|
||||
case View::GEOMETRY:
|
||||
return &geometry_;
|
||||
case View::MIXING:
|
||||
@@ -132,3 +181,116 @@ View *Mixer::currentView()
|
||||
{
|
||||
return current_view_;
|
||||
}
|
||||
|
||||
|
||||
void Mixer::save(const std::string& filename)
|
||||
{
|
||||
XMLDocument xmlDoc;
|
||||
|
||||
XMLElement *version = xmlDoc.NewElement(APP_NAME);
|
||||
version->SetAttribute("major", XML_VERSION_MAJOR);
|
||||
version->SetAttribute("minor", XML_VERSION_MINOR);
|
||||
xmlDoc.InsertEndChild(version);
|
||||
|
||||
// block: list of sources
|
||||
XMLElement *session = xmlDoc.NewElement("Session");
|
||||
xmlDoc.InsertEndChild(session);
|
||||
SourceList::iterator iter;
|
||||
for (iter = session_->begin(); iter != session_->end(); iter++)
|
||||
{
|
||||
SessionVisitor sv(&xmlDoc, session);
|
||||
(*iter)->accept(sv);
|
||||
}
|
||||
|
||||
// block: config of views
|
||||
XMLElement *views = xmlDoc.NewElement("Views");
|
||||
xmlDoc.InsertEndChild(views);
|
||||
{
|
||||
XMLElement *mixing = xmlDoc.NewElement( "Mixing" );
|
||||
mixing->InsertEndChild( SessionVisitor::NodeToXML(*mixing_.scene.root(), &xmlDoc));
|
||||
views->InsertEndChild(mixing);
|
||||
|
||||
XMLElement *geometry = xmlDoc.NewElement( "Geometry" );
|
||||
geometry->InsertEndChild( SessionVisitor::NodeToXML(*geometry_.scene.root(), &xmlDoc));
|
||||
views->InsertEndChild(geometry);
|
||||
}
|
||||
|
||||
// save file
|
||||
XMLSaveDoc(&xmlDoc, filename);
|
||||
}
|
||||
|
||||
bool Mixer::open(const std::string& filename)
|
||||
{
|
||||
XMLDocument xmlDoc;
|
||||
XMLError eResult = xmlDoc.LoadFile(filename.c_str());
|
||||
if (XMLResultError(eResult))
|
||||
return false;
|
||||
|
||||
XMLElement *version = xmlDoc.FirstChildElement(APP_NAME);
|
||||
if (version == nullptr) {
|
||||
Log::Warning("Not a %s session file: %s", APP_NAME, filename.c_str());
|
||||
return false;
|
||||
}
|
||||
int version_major = -1, version_minor = -1;
|
||||
version->QueryIntAttribute("major", &version_major); // TODO incompatible if major is different?
|
||||
version->QueryIntAttribute("minor", &version_minor);
|
||||
if (version_major != XML_VERSION_MAJOR || version_minor != XML_VERSION_MINOR){
|
||||
Log::Warning("%s is in an older versions of session file format. Data might be lost.", filename.c_str());
|
||||
}
|
||||
|
||||
// ok, ready to read sources
|
||||
SessionCreator creator( xmlDoc.FirstChildElement("Session") );
|
||||
Session *new_session = creator.session();
|
||||
|
||||
// if all good, change to new session
|
||||
if (new_session) {
|
||||
|
||||
// validate new session
|
||||
newSession( new_session );
|
||||
|
||||
// insert nodes of sources into views
|
||||
SourceList::iterator iter;
|
||||
for (iter = new_session->begin(); iter != new_session->end(); iter++)
|
||||
{
|
||||
mixing_.scene.root()->addChild( (*iter)->group(View::MIXING) );
|
||||
geometry_.scene.root()->addChild( (*iter)->group(View::GEOMETRY) );
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
Log::Warning("Session file %s not loaded.", filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// config of view settings (optionnal)
|
||||
XMLElement *views = xmlDoc.FirstChildElement("Views");
|
||||
if (views != nullptr) {
|
||||
// ok, ready to read views
|
||||
SessionCreator::XMLToNode( views->FirstChildElement("Mixing"), *mixing_.scene.root());
|
||||
SessionCreator::XMLToNode( views->FirstChildElement("Geometry"), *geometry_.scene.root());
|
||||
}
|
||||
|
||||
Log::Info("Session file %s loaded. %d source(s) created.", filename.c_str(), session_->numSource());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Mixer::newSession(Session *newsession)
|
||||
{
|
||||
// TODO : remove roots of scenes for views? done in session
|
||||
// delete session : delete all sources
|
||||
if (session_)
|
||||
delete session_;
|
||||
|
||||
// validate new session
|
||||
if (newsession)
|
||||
session_ = newsession;
|
||||
else
|
||||
session_ = new Session;
|
||||
|
||||
// no current source
|
||||
current_source_ = session_->end();
|
||||
|
||||
// reset timer
|
||||
update_time_ = GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user