mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 10:19:59 +01:00
Source creation by origin: File, software and hardware. Separate source
classes for Media and Session sources. Update of file dialog accordingly.
This commit is contained in:
@@ -209,6 +209,7 @@ set(VMIX_SRCS
|
||||
View.cpp
|
||||
Source.cpp
|
||||
Session.cpp
|
||||
SessionSource.cpp
|
||||
SessionVisitor.cpp
|
||||
GarbageVisitor.cpp
|
||||
SessionCreator.cpp
|
||||
@@ -218,6 +219,7 @@ set(VMIX_SRCS
|
||||
Resource.cpp
|
||||
FileDialog.cpp
|
||||
MediaPlayer.cpp
|
||||
MediaSource.cpp
|
||||
FrameBuffer.cpp
|
||||
RenderingManager.cpp
|
||||
UserInterfaceManager.cpp
|
||||
|
||||
155
MediaSource.cpp
Normal file
155
MediaSource.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include "MediaSource.h"
|
||||
|
||||
#include "defines.h"
|
||||
#include "ImageShader.h"
|
||||
#include "ImageProcessingShader.h"
|
||||
#include "Resource.h"
|
||||
#include "Primitives.h"
|
||||
#include "MediaPlayer.h"
|
||||
#include "Visitor.h"
|
||||
#include "Log.h"
|
||||
|
||||
MediaSource::MediaSource() : Source(), path_("")
|
||||
{
|
||||
// create media player
|
||||
mediaplayer_ = new MediaPlayer;
|
||||
|
||||
// create media surface:
|
||||
// - textured with original texture from media player
|
||||
// - crop & repeat UV can be managed here
|
||||
// - additional custom shader can be associated
|
||||
mediasurface_ = new Surface(rendershader_);
|
||||
|
||||
}
|
||||
|
||||
MediaSource::~MediaSource()
|
||||
{
|
||||
// TODO delete media surface with visitor
|
||||
delete mediasurface_;
|
||||
|
||||
delete mediaplayer_;
|
||||
// TODO verify that all surfaces and node is deleted in Source destructor
|
||||
}
|
||||
|
||||
void MediaSource::setPath(const std::string &p)
|
||||
{
|
||||
path_ = p;
|
||||
mediaplayer_->open(path_);
|
||||
mediaplayer_->play(true);
|
||||
|
||||
Log::Notify("Opening %s", p.c_str());
|
||||
}
|
||||
|
||||
std::string MediaSource::path() const
|
||||
{
|
||||
return path_;
|
||||
}
|
||||
|
||||
MediaPlayer *MediaSource::mediaplayer() const
|
||||
{
|
||||
return mediaplayer_;
|
||||
}
|
||||
|
||||
bool MediaSource::failed() const
|
||||
{
|
||||
return mediaplayer_->failed();
|
||||
}
|
||||
|
||||
void MediaSource::init()
|
||||
{
|
||||
if ( mediaplayer_->isOpen() ) {
|
||||
|
||||
// update video
|
||||
mediaplayer_->update();
|
||||
|
||||
// once the texture of media player is created
|
||||
if (mediaplayer_->texture() != Resource::getTextureBlack()) {
|
||||
|
||||
// get the texture index from media player, apply it to the media surface
|
||||
mediasurface_->setTextureIndex( mediaplayer_->texture() );
|
||||
|
||||
// create Frame buffer matching size of media player
|
||||
float height = float(mediaplayer()->width()) / mediaplayer()->aspectRatio();
|
||||
renderbuffer_ = new FrameBuffer(mediaplayer()->width(), (uint)height);
|
||||
|
||||
// create the surfaces to draw the frame buffer in the views
|
||||
// TODO Provide the source custom effect shader
|
||||
rendersurface_ = new FrameBufferSurface(renderbuffer_, blendingshader_);
|
||||
groups_[View::RENDERING]->attach(rendersurface_);
|
||||
groups_[View::GEOMETRY]->attach(rendersurface_);
|
||||
groups_[View::MIXING]->attach(rendersurface_);
|
||||
groups_[View::LAYER]->attach(rendersurface_);
|
||||
|
||||
// for mixing view, add another surface to overlay (for stippled view in transparency)
|
||||
Surface *surfacemix = new FrameBufferSurface(renderbuffer_);
|
||||
ImageShader *is = static_cast<ImageShader *>(surfacemix->shader());
|
||||
if (is) is->stipple = 1.0;
|
||||
groups_[View::MIXING]->attach(surfacemix);
|
||||
groups_[View::LAYER]->attach(surfacemix);
|
||||
if (mediaplayer_->duration() == GST_CLOCK_TIME_NONE)
|
||||
overlays_[View::MIXING]->attach( new Mesh("mesh/icon_image.ply") );
|
||||
else
|
||||
overlays_[View::MIXING]->attach( new Mesh("mesh/icon_video.ply") );
|
||||
|
||||
// scale all mixing nodes to match aspect ratio of the media
|
||||
for (NodeSet::iterator node = groups_[View::MIXING]->begin();
|
||||
node != groups_[View::MIXING]->end(); node++) {
|
||||
(*node)->scale_.x = mediaplayer_->aspectRatio();
|
||||
}
|
||||
for (NodeSet::iterator node = groups_[View::GEOMETRY]->begin();
|
||||
node != groups_[View::GEOMETRY]->end(); node++) {
|
||||
(*node)->scale_.x = mediaplayer_->aspectRatio();
|
||||
}
|
||||
for (NodeSet::iterator node = groups_[View::LAYER]->begin();
|
||||
node != groups_[View::LAYER]->end(); node++) {
|
||||
(*node)->scale_.x = mediaplayer_->aspectRatio();
|
||||
}
|
||||
|
||||
// done init once and for all
|
||||
initialized_ = true;
|
||||
// make visible
|
||||
groups_[View::RENDERING]->visible_ = true;
|
||||
groups_[View::MIXING]->visible_ = true;
|
||||
groups_[View::GEOMETRY]->visible_ = true;
|
||||
groups_[View::LAYER]->visible_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MediaSource::render()
|
||||
{
|
||||
if (!initialized_)
|
||||
init();
|
||||
else {
|
||||
// update video
|
||||
mediaplayer_->update();
|
||||
|
||||
// render the media player into frame buffer
|
||||
static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f);
|
||||
renderbuffer_->begin();
|
||||
mediasurface_->draw(glm::identity<glm::mat4>(), projection);
|
||||
renderbuffer_->end();
|
||||
}
|
||||
}
|
||||
|
||||
FrameBuffer *MediaSource::frame() const
|
||||
{
|
||||
if (initialized_ && renderbuffer_)
|
||||
{
|
||||
return renderbuffer_;
|
||||
}
|
||||
else {
|
||||
static FrameBuffer *black = new FrameBuffer(640,480);
|
||||
return black;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MediaSource::accept(Visitor& v)
|
||||
{
|
||||
Source::accept(v);
|
||||
v.visit(*this);
|
||||
}
|
||||
32
MediaSource.h
Normal file
32
MediaSource.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef MEDIASOURCE_H
|
||||
#define MEDIASOURCE_H
|
||||
|
||||
#include "Source.h"
|
||||
|
||||
class MediaSource : public Source
|
||||
{
|
||||
public:
|
||||
MediaSource();
|
||||
~MediaSource();
|
||||
|
||||
// implementation of source API
|
||||
FrameBuffer *frame() const override;
|
||||
void render() override;
|
||||
void accept (Visitor& v) override;
|
||||
bool failed() const override;
|
||||
|
||||
// Media specific interface
|
||||
void setPath(const std::string &p);
|
||||
std::string path() const;
|
||||
MediaPlayer *mediaplayer() const;
|
||||
|
||||
protected:
|
||||
|
||||
void init() override;
|
||||
|
||||
Surface *mediasurface_;
|
||||
std::string path_;
|
||||
MediaPlayer *mediaplayer_;
|
||||
};
|
||||
|
||||
#endif // MEDIASOURCE_H
|
||||
97
Mixer.cpp
97
Mixer.cpp
@@ -1,52 +1,54 @@
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
|
||||
#include <tinyxml2.h>
|
||||
#include "tinyxml2Toolkit.h"
|
||||
using namespace tinyxml2;
|
||||
|
||||
#include "defines.h"
|
||||
#include "Settings.h"
|
||||
#include "Log.h"
|
||||
#include "View.h"
|
||||
#include "Primitives.h"
|
||||
#include "Mesh.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "Settings.h"
|
||||
#include "SystemToolkit.h"
|
||||
#include "ImageProcessingShader.h"
|
||||
#include "GarbageVisitor.h"
|
||||
//#include "GarbageVisitor.h"
|
||||
#include "SessionVisitor.h"
|
||||
#include "SessionCreator.h"
|
||||
#include "MediaPlayer.h"
|
||||
#include "SessionSource.h"
|
||||
#include "MediaSource.h"
|
||||
|
||||
#include "Mixer.h"
|
||||
|
||||
// static objects for multithreaded session loading
|
||||
static std::atomic<bool> sessionThreadActive_ = false;
|
||||
static std::string sessionThreadFilename_ = "";
|
||||
|
||||
static std::atomic<bool> sessionLoadFinished_ = false;
|
||||
|
||||
static void loadSession(const std::string& filename, Session *session)
|
||||
{
|
||||
sessionThreadActive_ = true;
|
||||
sessionLoadFinished_ = false;
|
||||
sessionThreadFilename_ = "";
|
||||
while (sessionThreadActive_)
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds(50));
|
||||
sessionThreadActive_ = true;
|
||||
sessionLoadFinished_ = false;
|
||||
sessionThreadFilename_ = "";
|
||||
|
||||
// actual loading of xml file
|
||||
SessionCreator creator( session );
|
||||
// actual loading of xml file
|
||||
SessionCreator creator( session );
|
||||
|
||||
if (!creator.load(filename)) {
|
||||
// error loading
|
||||
Log::Notify("Failed to load Session file %s.", filename.c_str());
|
||||
}
|
||||
else {
|
||||
// loaded ok
|
||||
Log::Notify("Session %s loaded. %d source(s) created.", filename.c_str(), session->numSource());
|
||||
}
|
||||
if (!creator.load(filename)) {
|
||||
// error loading
|
||||
Log::Warning("Failed to load Session file %s.", filename.c_str());
|
||||
}
|
||||
else {
|
||||
// loaded ok
|
||||
Log::Notify("Session %s loaded. %d source(s) created.", filename.c_str(), session->numSource());
|
||||
}
|
||||
|
||||
sessionThreadFilename_ = filename;
|
||||
sessionLoadFinished_ = true;
|
||||
sessionThreadActive_ = false;
|
||||
sessionThreadFilename_ = filename;
|
||||
sessionLoadFinished_ = true;
|
||||
sessionThreadActive_ = false;
|
||||
}
|
||||
|
||||
// static objects for multithreaded session saving
|
||||
@@ -54,6 +56,8 @@ static std::atomic<bool> sessionSaveFinished_ = false;
|
||||
static void saveSession(const std::string& filename, Session *session)
|
||||
{
|
||||
// reset
|
||||
while (sessionThreadActive_)
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds(50));
|
||||
sessionThreadActive_ = true;
|
||||
sessionSaveFinished_ = false;
|
||||
sessionThreadFilename_ = "";
|
||||
@@ -175,22 +179,44 @@ void Mixer::draw()
|
||||
}
|
||||
|
||||
// manangement of sources
|
||||
void Mixer::createSourceMedia(std::string path)
|
||||
void Mixer::createSourceFile(std::string path)
|
||||
{
|
||||
// create source
|
||||
MediaSource *m = new MediaSource();
|
||||
m->setPath(path);
|
||||
// sanity check
|
||||
if ( !SystemToolkit::file_exists( path ) ) {
|
||||
Log::Notify("File %s does not exist.", path);
|
||||
return;
|
||||
}
|
||||
// ready to create a source
|
||||
Source *s = nullptr;
|
||||
|
||||
// test type of file by extension
|
||||
std::string ext = SystemToolkit::extension_filename(path);
|
||||
if ( ext == "vmx" )
|
||||
{
|
||||
// create a session source
|
||||
SessionSource *ss = new SessionSource();
|
||||
ss->setPath(path);
|
||||
s = ss;
|
||||
}
|
||||
else {
|
||||
// (try to) create media source by default
|
||||
MediaSource *ms = new MediaSource();
|
||||
ms->setPath(path);
|
||||
s = ms;
|
||||
}
|
||||
|
||||
// remember in recent media
|
||||
Settings::application.recentMedia.push(path);
|
||||
Settings::application.recentImport.push(path);
|
||||
Settings::application.recentImport.path = SystemToolkit::path_filename(path);
|
||||
|
||||
// propose a new name based on uri
|
||||
renameSource(m, SystemToolkit::base_filename(path));
|
||||
renameSource(s, SystemToolkit::base_filename(path));
|
||||
|
||||
// add to mixer
|
||||
insertSource(m);
|
||||
insertSource(s);
|
||||
}
|
||||
|
||||
|
||||
void Mixer::insertSource(Source *s)
|
||||
{
|
||||
// Add source to Session and set it as current
|
||||
@@ -353,18 +379,12 @@ View *Mixer::currentView()
|
||||
|
||||
void Mixer::save()
|
||||
{
|
||||
if (sessionThreadActive_)
|
||||
return;
|
||||
|
||||
if (!sessionFilename_.empty())
|
||||
saveas(sessionFilename_);
|
||||
}
|
||||
|
||||
void Mixer::saveas(const std::string& filename)
|
||||
{
|
||||
if (sessionThreadActive_)
|
||||
return;
|
||||
|
||||
// optional copy of views config
|
||||
session_->config(View::MIXING)->copyTransform( mixing_.scene.root() );
|
||||
session_->config(View::GEOMETRY)->copyTransform( geometry_.scene.root() );
|
||||
@@ -376,9 +396,6 @@ void Mixer::saveas(const std::string& filename)
|
||||
|
||||
void Mixer::open(const std::string& filename)
|
||||
{
|
||||
if (sessionThreadActive_)
|
||||
return;
|
||||
|
||||
if (back_session_)
|
||||
delete back_session_;
|
||||
|
||||
|
||||
4
Mixer.h
4
Mixer.h
@@ -1,7 +1,6 @@
|
||||
#ifndef MIXER_H
|
||||
#define MIXER_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
// GStreamer
|
||||
#include <gst/gst.h>
|
||||
@@ -11,6 +10,7 @@
|
||||
#include "Session.h"
|
||||
#include "Source.h"
|
||||
|
||||
|
||||
class Mixer
|
||||
{
|
||||
// Private Constructor
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
void draw();
|
||||
|
||||
// manangement of sources
|
||||
void createSourceMedia(std::string path);
|
||||
void createSourceFile(std::string path);
|
||||
|
||||
void deleteSource(Source *s);
|
||||
void deleteCurrentSource();
|
||||
|
||||
@@ -438,18 +438,8 @@ void Rendering::FileDropped(GLFWwindow *, int path_count, const char* paths[])
|
||||
std::string filename(paths[i]);
|
||||
if (filename.empty())
|
||||
break;
|
||||
std::string ext = SystemToolkit::extension_filename(filename);
|
||||
// Log::Info("Dropped file %s %s\n", filename.c_str(), ext.c_str());
|
||||
if ( ext == "vmx" )
|
||||
{
|
||||
// try to load a session
|
||||
Mixer::manager().open(filename);
|
||||
}
|
||||
else {
|
||||
// try to create a media source
|
||||
Mixer::manager().createSourceMedia( filename );
|
||||
}
|
||||
|
||||
// try to create a source
|
||||
Mixer::manager().createSourceFile( filename );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "Primitives.h"
|
||||
#include "Mesh.h"
|
||||
#include "Source.h"
|
||||
#include "MediaSource.h"
|
||||
#include "Session.h"
|
||||
#include "ImageShader.h"
|
||||
#include "ImageProcessingShader.h"
|
||||
|
||||
176
SessionSource.cpp
Normal file
176
SessionSource.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#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"
|
||||
|
||||
|
||||
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)) {
|
||||
// error loading
|
||||
Log::Notify("Failed to load Session file %s.", filename.c_str());
|
||||
source->loadFailed_ = true;
|
||||
}
|
||||
|
||||
source->loadFinished_ = true;
|
||||
}
|
||||
|
||||
SessionSource::SessionSource() : Source(), path_("")
|
||||
{
|
||||
loadFailed_ = false;
|
||||
loadFinished_ = 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()
|
||||
{
|
||||
// TODO delete media surface with visitor
|
||||
delete sessionsurface_;
|
||||
|
||||
// TODO close and delete session
|
||||
delete session_;
|
||||
}
|
||||
|
||||
void SessionSource::setPath(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());
|
||||
}
|
||||
|
||||
std::string SessionSource::path() const
|
||||
{
|
||||
return path_;
|
||||
}
|
||||
|
||||
Session *SessionSource::session() const
|
||||
{
|
||||
return session_;
|
||||
}
|
||||
|
||||
bool SessionSource::failed() const
|
||||
{
|
||||
return loadFailed_;
|
||||
}
|
||||
|
||||
void SessionSource::init()
|
||||
{
|
||||
if ( loadFinished_ && !loadFailed_ ) {
|
||||
loadFinished_ = false;
|
||||
|
||||
// set resolution
|
||||
session_->setResolution( session_->config(View::RENDERING)->scale_ );
|
||||
|
||||
// get the texture index from media player, apply it to the media surface
|
||||
sessionsurface_->setTextureIndex( session_->frame()->texture() );
|
||||
|
||||
// create Frame buffer matching size of media player
|
||||
renderbuffer_ = new FrameBuffer(session_->frame()->resolution());
|
||||
|
||||
// create the surfaces to draw the frame buffer in the views
|
||||
rendersurface_ = new FrameBufferSurface(renderbuffer_, blendingshader_);
|
||||
groups_[View::RENDERING]->attach(rendersurface_);
|
||||
groups_[View::GEOMETRY]->attach(rendersurface_);
|
||||
groups_[View::MIXING]->attach(rendersurface_);
|
||||
groups_[View::LAYER]->attach(rendersurface_);
|
||||
|
||||
// for mixing view, add another surface to overlay (for stippled view in transparency)
|
||||
Surface *surfacemix = new FrameBufferSurface(renderbuffer_);
|
||||
ImageShader *is = static_cast<ImageShader *>(surfacemix->shader());
|
||||
if (is) is->stipple = 1.0;
|
||||
groups_[View::MIXING]->attach(surfacemix);
|
||||
groups_[View::LAYER]->attach(surfacemix);
|
||||
// TODO icon session
|
||||
// overlays_[View::MIXING]->attach( new Mesh("mesh/icon_video.ply") );
|
||||
|
||||
// scale all mixing nodes to match aspect ratio of the media
|
||||
for (NodeSet::iterator node = groups_[View::MIXING]->begin();
|
||||
node != groups_[View::MIXING]->end(); node++) {
|
||||
(*node)->scale_.x = session_->frame()->aspectRatio();
|
||||
}
|
||||
for (NodeSet::iterator node = groups_[View::GEOMETRY]->begin();
|
||||
node != groups_[View::GEOMETRY]->end(); node++) {
|
||||
(*node)->scale_.x = session_->frame()->aspectRatio();
|
||||
}
|
||||
for (NodeSet::iterator node = groups_[View::LAYER]->begin();
|
||||
node != groups_[View::LAYER]->end(); node++) {
|
||||
(*node)->scale_.x = session_->frame()->aspectRatio();
|
||||
}
|
||||
|
||||
// done init once and for all
|
||||
initialized_ = true;
|
||||
|
||||
// make visible
|
||||
groups_[View::RENDERING]->visible_ = true;
|
||||
groups_[View::MIXING]->visible_ = true;
|
||||
groups_[View::GEOMETRY]->visible_ = true;
|
||||
groups_[View::LAYER]->visible_ = true;
|
||||
|
||||
Log::Info("Source Session %s loading %d sources.", path_.c_str(), session_->numSource());
|
||||
}
|
||||
}
|
||||
|
||||
void SessionSource::render()
|
||||
{
|
||||
if (!initialized_)
|
||||
init();
|
||||
else {
|
||||
// update session
|
||||
session_->update(dt_);
|
||||
|
||||
sessionsurface_->setTextureIndex( session_->frame()->texture() );
|
||||
|
||||
// render the media player 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<glm::mat4>(), projection);
|
||||
renderbuffer_->end();
|
||||
}
|
||||
}
|
||||
|
||||
FrameBuffer *SessionSource::frame() const
|
||||
{
|
||||
if (initialized_ && renderbuffer_)
|
||||
{
|
||||
return renderbuffer_;
|
||||
}
|
||||
else {
|
||||
static FrameBuffer *black = new FrameBuffer(640,480);
|
||||
return black;
|
||||
}
|
||||
}
|
||||
|
||||
void SessionSource::accept(Visitor& v)
|
||||
{
|
||||
Source::accept(v);
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
36
SessionSource.h
Normal file
36
SessionSource.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef SESSIONSOURCE_H
|
||||
#define SESSIONSOURCE_H
|
||||
|
||||
#include <atomic>
|
||||
#include "Source.h"
|
||||
|
||||
class SessionSource : public Source
|
||||
{
|
||||
public:
|
||||
SessionSource();
|
||||
~SessionSource();
|
||||
|
||||
// implementation of source API
|
||||
FrameBuffer *frame() const override;
|
||||
void render() override;
|
||||
void accept (Visitor& v) override;
|
||||
bool failed() const override;
|
||||
|
||||
// Media specific interface
|
||||
void setPath(const std::string &p);
|
||||
std::string path() const;
|
||||
Session *session() const;
|
||||
|
||||
protected:
|
||||
|
||||
void init() override;
|
||||
static void loadSession(const std::string& filename, SessionSource *source);
|
||||
|
||||
Surface *sessionsurface_;
|
||||
std::string path_;
|
||||
Session *session_;
|
||||
|
||||
std::atomic<bool> loadFailed_;
|
||||
std::atomic<bool> loadFinished_;
|
||||
};
|
||||
#endif // SESSIONSOURCE_H
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Primitives.h"
|
||||
#include "Mesh.h"
|
||||
#include "Source.h"
|
||||
#include "MediaSource.h"
|
||||
#include "ImageShader.h"
|
||||
#include "ImageProcessingShader.h"
|
||||
#include "MediaPlayer.h"
|
||||
|
||||
24
Settings.cpp
24
Settings.cpp
@@ -108,10 +108,10 @@ void Settings::Save()
|
||||
};
|
||||
recent->InsertEndChild(recentsession);
|
||||
|
||||
XMLElement *recentmedia = xmlDoc.NewElement( "Media" );
|
||||
recentmedia->SetAttribute("path", application.recentMedia.path.c_str());
|
||||
for(auto it = application.recentMedia.filenames.begin();
|
||||
it != application.recentMedia.filenames.end(); it++) {
|
||||
XMLElement *recentmedia = xmlDoc.NewElement( "Import" );
|
||||
recentmedia->SetAttribute("path", application.recentImport.path.c_str());
|
||||
for(auto it = application.recentImport.filenames.begin();
|
||||
it != application.recentImport.filenames.end(); it++) {
|
||||
|
||||
XMLElement *fileNode = xmlDoc.NewElement("path");
|
||||
XMLText *text = xmlDoc.NewText( (*it).c_str() );
|
||||
@@ -245,21 +245,21 @@ void Settings::Load()
|
||||
}
|
||||
}
|
||||
// recent media uri
|
||||
XMLElement * pMedia = pElement->FirstChildElement("Media");
|
||||
if (pMedia)
|
||||
XMLElement * pImport = pElement->FirstChildElement("Import");
|
||||
if (pImport)
|
||||
{
|
||||
const char *path_ = pMedia->Attribute("path");
|
||||
const char *path_ = pImport->Attribute("path");
|
||||
if (path_)
|
||||
application.recentMedia.path = std::string(path_);
|
||||
application.recentImport.path = std::string(path_);
|
||||
else
|
||||
application.recentMedia.path = SystemToolkit::home_path();
|
||||
application.recentMedia.filenames.clear();
|
||||
XMLElement* path = pMedia->FirstChildElement("path");
|
||||
application.recentImport.path = SystemToolkit::home_path();
|
||||
application.recentImport.filenames.clear();
|
||||
XMLElement* path = pImport->FirstChildElement("path");
|
||||
for( ; path ; path = path->NextSiblingElement())
|
||||
{
|
||||
const char *p = path->GetText();
|
||||
if (p)
|
||||
application.recentMedia.push( std::string (p) );
|
||||
application.recentImport.push( std::string (p) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ struct Application
|
||||
|
||||
// recent files histories
|
||||
History recentSessions;
|
||||
History recentMedia;
|
||||
History recentImport;
|
||||
|
||||
Application() : name(APP_NAME){
|
||||
scale = 1.f;
|
||||
|
||||
216
Source.cpp
216
Source.cpp
@@ -6,14 +6,11 @@
|
||||
|
||||
#include "defines.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "ImageShader.h"
|
||||
#include "ImageProcessingShader.h"
|
||||
#include "Resource.h"
|
||||
#include "Primitives.h"
|
||||
#include "Mesh.h"
|
||||
#include "MediaPlayer.h"
|
||||
#include "SearchVisitor.h"
|
||||
|
||||
#include "ImageShader.h"
|
||||
#include "ImageProcessingShader.h"
|
||||
#include "Log.h"
|
||||
|
||||
Source::Source() : initialized_(false), need_update_(true)
|
||||
@@ -32,13 +29,18 @@ Source::Source() : initialized_(false), need_update_(true)
|
||||
groups_[View::MIXING]->visible_ = false;
|
||||
Frame *frame = new Frame(Frame::ROUND_THIN);
|
||||
frame->translation_.z = 0.1;
|
||||
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 0.9f);
|
||||
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 0.7f);
|
||||
groups_[View::MIXING]->attach(frame);
|
||||
groups_[View::MIXING]->scale_ = glm::vec3(0.15f, 0.15f, 1.f);
|
||||
groups_[View::MIXING]->translation_ = glm::vec3(-1.f, 1.f, 0.f);
|
||||
|
||||
overlays_[View::MIXING] = new Group;
|
||||
overlays_[View::MIXING]->translation_.z = 0.1;
|
||||
overlays_[View::MIXING]->visible_ = false;
|
||||
frame = new Frame(Frame::ROUND_LARGE);
|
||||
frame->translation_.z = 0.1;
|
||||
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 1.f);
|
||||
overlays_[View::MIXING]->attach(frame);
|
||||
groups_[View::MIXING]->attach(overlays_[View::MIXING]);
|
||||
|
||||
// default geometry nodes
|
||||
@@ -46,12 +48,31 @@ Source::Source() : initialized_(false), need_update_(true)
|
||||
groups_[View::GEOMETRY]->visible_ = false;
|
||||
frame = new Frame(Frame::SHARP_THIN);
|
||||
frame->translation_.z = 0.1;
|
||||
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 0.9f);
|
||||
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 0.7f);
|
||||
groups_[View::GEOMETRY]->attach(frame);
|
||||
|
||||
overlays_[View::GEOMETRY] = new Group;
|
||||
overlays_[View::GEOMETRY]->translation_.z = 0.15;
|
||||
overlays_[View::GEOMETRY]->visible_ = false;
|
||||
frame = new Frame(Frame::SHARP_LARGE);
|
||||
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 1.f);
|
||||
overlays_[View::GEOMETRY]->attach(frame);
|
||||
resize_handle_ = new Handles(Handles::RESIZE);
|
||||
resize_handle_->color = glm::vec4( COLOR_DEFAULT_SOURCE, 1.f);
|
||||
resize_handle_->translation_.z = 0.1;
|
||||
overlays_[View::GEOMETRY]->attach(resize_handle_);
|
||||
resize_H_handle_ = new Handles(Handles::RESIZE_H);
|
||||
resize_H_handle_->color = glm::vec4( COLOR_DEFAULT_SOURCE, 1.f);
|
||||
resize_H_handle_->translation_.z = 0.1;
|
||||
overlays_[View::GEOMETRY]->attach(resize_H_handle_);
|
||||
resize_V_handle_ = new Handles(Handles::RESIZE_V);
|
||||
resize_V_handle_->color = glm::vec4( COLOR_DEFAULT_SOURCE, 1.f);
|
||||
resize_V_handle_->translation_.z = 0.1;
|
||||
overlays_[View::GEOMETRY]->attach(resize_V_handle_);
|
||||
rotate_handle_ = new Handles(Handles::ROTATE);
|
||||
rotate_handle_->color = glm::vec4( COLOR_DEFAULT_SOURCE, 1.f);
|
||||
rotate_handle_->translation_.z = 0.1;
|
||||
overlays_[View::GEOMETRY]->attach(rotate_handle_);
|
||||
groups_[View::GEOMETRY]->attach(overlays_[View::GEOMETRY]);
|
||||
|
||||
// default mixing nodes
|
||||
@@ -59,7 +80,7 @@ Source::Source() : initialized_(false), need_update_(true)
|
||||
groups_[View::LAYER]->visible_ = false;
|
||||
frame = new Frame(Frame::ROUND_SHADOW);
|
||||
frame->translation_.z = 0.1;
|
||||
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 0.9f);
|
||||
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 0.8f);
|
||||
groups_[View::LAYER]->attach(frame);
|
||||
|
||||
overlays_[View::LAYER] = new Group;
|
||||
@@ -72,10 +93,6 @@ Source::Source() : initialized_(false), need_update_(true)
|
||||
rendershader_ = new ImageProcessingShader;
|
||||
renderbuffer_ = nullptr;
|
||||
rendersurface_ = nullptr;
|
||||
resize_handle_ = nullptr;
|
||||
resize_H_handle_ = nullptr;
|
||||
resize_V_handle_ = nullptr;
|
||||
rotate_handle_ = nullptr;
|
||||
}
|
||||
|
||||
Source::~Source()
|
||||
@@ -117,6 +134,10 @@ void Source::setOverlayVisible(bool on)
|
||||
|
||||
void Source::update(float dt)
|
||||
{
|
||||
// keep delta-t
|
||||
dt_ = dt;
|
||||
|
||||
// update nodes if needed
|
||||
if (need_update_)
|
||||
{
|
||||
// ADJUST alpha based on MIXING node
|
||||
@@ -173,175 +194,4 @@ bool hasNode::operator()(const Source* elem) const
|
||||
return false;
|
||||
}
|
||||
|
||||
MediaSource::MediaSource() : Source(), path_("")
|
||||
{
|
||||
// create media player
|
||||
mediaplayer_ = new MediaPlayer;
|
||||
|
||||
// create media surface:
|
||||
// - textured with original texture from media player
|
||||
// - crop & repeat UV can be managed here
|
||||
// - additional custom shader can be associated
|
||||
mediasurface_ = new Surface(rendershader_);
|
||||
|
||||
// extra overlay for mixing view
|
||||
Frame *frame = new Frame(Frame::ROUND_LARGE);
|
||||
frame->translation_.z = 0.1;
|
||||
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 1.f);
|
||||
overlays_[View::MIXING]->attach(frame);
|
||||
|
||||
// extra overlays for geometry view
|
||||
frame = new Frame(Frame::SHARP_LARGE);
|
||||
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 1.f);
|
||||
overlays_[View::GEOMETRY]->attach(frame);
|
||||
resize_handle_ = new Handles(Handles::RESIZE);
|
||||
resize_handle_->color = glm::vec4( COLOR_DEFAULT_SOURCE, 1.f);
|
||||
resize_handle_->translation_.z = 0.1;
|
||||
overlays_[View::GEOMETRY]->attach(resize_handle_);
|
||||
resize_H_handle_ = new Handles(Handles::RESIZE_H);
|
||||
resize_H_handle_->color = glm::vec4( COLOR_DEFAULT_SOURCE, 1.f);
|
||||
resize_H_handle_->translation_.z = 0.1;
|
||||
overlays_[View::GEOMETRY]->attach(resize_H_handle_);
|
||||
resize_V_handle_ = new Handles(Handles::RESIZE_V);
|
||||
resize_V_handle_->color = glm::vec4( COLOR_DEFAULT_SOURCE, 1.f);
|
||||
resize_V_handle_->translation_.z = 0.1;
|
||||
overlays_[View::GEOMETRY]->attach(resize_V_handle_);
|
||||
rotate_handle_ = new Handles(Handles::ROTATE);
|
||||
rotate_handle_->color = glm::vec4( COLOR_DEFAULT_SOURCE, 1.f);
|
||||
rotate_handle_->translation_.z = 0.1;
|
||||
overlays_[View::GEOMETRY]->attach(rotate_handle_);
|
||||
|
||||
}
|
||||
|
||||
MediaSource::~MediaSource()
|
||||
{
|
||||
// TODO delete media surface with visitor
|
||||
delete mediasurface_;
|
||||
|
||||
delete mediaplayer_;
|
||||
// TODO verify that all surfaces and node is deleted in Source destructor
|
||||
}
|
||||
|
||||
void MediaSource::setPath(const std::string &p)
|
||||
{
|
||||
path_ = p;
|
||||
mediaplayer_->open(path_);
|
||||
mediaplayer_->play(true);
|
||||
|
||||
Log::Notify("Opening %s", p.c_str());
|
||||
}
|
||||
|
||||
std::string MediaSource::path() const
|
||||
{
|
||||
return path_;
|
||||
}
|
||||
|
||||
MediaPlayer *MediaSource::mediaplayer() const
|
||||
{
|
||||
return mediaplayer_;
|
||||
}
|
||||
|
||||
bool MediaSource::failed() const
|
||||
{
|
||||
return mediaplayer_->failed();
|
||||
}
|
||||
|
||||
void MediaSource::init()
|
||||
{
|
||||
if ( mediaplayer_->isOpen() ) {
|
||||
|
||||
// update video
|
||||
mediaplayer_->update();
|
||||
|
||||
// once the texture of media player is created
|
||||
if (mediaplayer_->texture() != Resource::getTextureBlack()) {
|
||||
|
||||
// get the texture index from media player, apply it to the media surface
|
||||
mediasurface_->setTextureIndex( mediaplayer_->texture() );
|
||||
|
||||
// create Frame buffer matching size of media player
|
||||
float height = float(mediaplayer()->width()) / mediaplayer()->aspectRatio();
|
||||
renderbuffer_ = new FrameBuffer(mediaplayer()->width(), (uint)height);
|
||||
|
||||
// // setup shader resolution for texture 0
|
||||
// rendershader_->iChannelResolution[0] = glm::vec3(mediaplayer()->width(), mediaplayer()->height(), 0.f);
|
||||
|
||||
// create the surfaces to draw the frame buffer in the views
|
||||
// TODO Provide the source custom effect shader
|
||||
rendersurface_ = new FrameBufferSurface(renderbuffer_, blendingshader_);
|
||||
groups_[View::RENDERING]->attach(rendersurface_);
|
||||
groups_[View::GEOMETRY]->attach(rendersurface_);
|
||||
groups_[View::MIXING]->attach(rendersurface_);
|
||||
groups_[View::LAYER]->attach(rendersurface_);
|
||||
|
||||
// for mixing view, add another surface to overlay (for stippled view in transparency)
|
||||
Surface *surfacemix = new FrameBufferSurface(renderbuffer_);
|
||||
ImageShader *is = static_cast<ImageShader *>(surfacemix->shader());
|
||||
if (is) is->stipple = 1.0;
|
||||
groups_[View::MIXING]->attach(surfacemix);
|
||||
groups_[View::LAYER]->attach(surfacemix);
|
||||
if (mediaplayer_->duration() == GST_CLOCK_TIME_NONE)
|
||||
overlays_[View::MIXING]->attach( new Mesh("mesh/icon_image.ply") );
|
||||
else
|
||||
overlays_[View::MIXING]->attach( new Mesh("mesh/icon_video.ply") );
|
||||
|
||||
// scale all mixing nodes to match aspect ratio of the media
|
||||
for (NodeSet::iterator node = groups_[View::MIXING]->begin();
|
||||
node != groups_[View::MIXING]->end(); node++) {
|
||||
(*node)->scale_.x = mediaplayer_->aspectRatio();
|
||||
}
|
||||
for (NodeSet::iterator node = groups_[View::GEOMETRY]->begin();
|
||||
node != groups_[View::GEOMETRY]->end(); node++) {
|
||||
(*node)->scale_.x = mediaplayer_->aspectRatio();
|
||||
}
|
||||
for (NodeSet::iterator node = groups_[View::LAYER]->begin();
|
||||
node != groups_[View::LAYER]->end(); node++) {
|
||||
(*node)->scale_.x = mediaplayer_->aspectRatio();
|
||||
}
|
||||
|
||||
// done init once and for all
|
||||
initialized_ = true;
|
||||
// make visible
|
||||
groups_[View::RENDERING]->visible_ = true;
|
||||
groups_[View::MIXING]->visible_ = true;
|
||||
groups_[View::GEOMETRY]->visible_ = true;
|
||||
groups_[View::LAYER]->visible_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MediaSource::render()
|
||||
{
|
||||
if (!initialized_)
|
||||
init();
|
||||
else {
|
||||
// update video
|
||||
mediaplayer_->update();
|
||||
|
||||
// render the media player into frame buffer
|
||||
static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f);
|
||||
renderbuffer_->begin();
|
||||
mediasurface_->draw(glm::identity<glm::mat4>(), projection);
|
||||
renderbuffer_->end();
|
||||
}
|
||||
}
|
||||
|
||||
FrameBuffer *MediaSource::frame() const
|
||||
{
|
||||
if (initialized_ && renderbuffer_)
|
||||
{
|
||||
return renderbuffer_;
|
||||
}
|
||||
else {
|
||||
static FrameBuffer *black = new FrameBuffer(640,480);
|
||||
return black;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MediaSource::accept(Visitor& v)
|
||||
{
|
||||
Source::accept(v);
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
35
Source.h
35
Source.h
@@ -14,6 +14,7 @@ class FrameBuffer;
|
||||
class FrameBufferSurface;
|
||||
class MediaPlayer;
|
||||
class Surface;
|
||||
class Session;
|
||||
class Frame;
|
||||
|
||||
class Source
|
||||
@@ -43,12 +44,12 @@ public:
|
||||
// a Source has a shader to control mixing effects
|
||||
inline ImageShader *blendingShader() const { return blendingshader_; }
|
||||
|
||||
// a Source shall be updated before displayed (Mixing, Geometry and Layer)
|
||||
void update (float dt);
|
||||
|
||||
// touch to request update
|
||||
inline void touch() { need_update_ = true; }
|
||||
|
||||
// a Source shall be updated before displayed (Mixing, Geometry and Layer)
|
||||
void update (float dt);
|
||||
|
||||
// accept all kind of visitors
|
||||
virtual void accept (Visitor& v);
|
||||
|
||||
@@ -95,6 +96,7 @@ protected:
|
||||
|
||||
// update need
|
||||
bool need_update_;
|
||||
float dt_;
|
||||
};
|
||||
|
||||
// TODO SourceSet sorted by shader
|
||||
@@ -122,32 +124,5 @@ private:
|
||||
Node *_n;
|
||||
};
|
||||
|
||||
class MediaSource : public Source
|
||||
{
|
||||
public:
|
||||
MediaSource();
|
||||
~MediaSource();
|
||||
|
||||
// implementation of source API
|
||||
FrameBuffer *frame() const override;
|
||||
void render() override;
|
||||
void accept (Visitor& v) override;
|
||||
bool failed() const override;
|
||||
|
||||
// Media specific interface
|
||||
void setPath(const std::string &p);
|
||||
std::string path() const;
|
||||
MediaPlayer *mediaplayer() const;
|
||||
|
||||
protected:
|
||||
|
||||
void init() override;
|
||||
|
||||
Surface *mediasurface_;
|
||||
std::string path_;
|
||||
MediaPlayer *mediaplayer_;
|
||||
};
|
||||
|
||||
// TODO dedicated source .cpp .h files for MediaSource
|
||||
|
||||
#endif // SOURCE_H
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "Mixer.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "MediaPlayer.h"
|
||||
#include "MediaSource.h"
|
||||
#include "PickingVisitor.h"
|
||||
#include "ImageShader.h"
|
||||
#include "ImageProcessingShader.h"
|
||||
@@ -58,14 +59,14 @@ void ShowAbout(bool* p_open);
|
||||
|
||||
// static objects for multithreaded file dialog
|
||||
static std::atomic<bool> FileDialogPending_ = false;
|
||||
static std::atomic<bool> FileDialogLoadFinished_ = false;
|
||||
static std::atomic<bool> FileDialogSaveFinished_ = false;
|
||||
static std::string FileDialogFilename_ = "";
|
||||
static std::atomic<bool> SessionFileDialogLoadFinished_ = false;
|
||||
static std::atomic<bool> SessionFileDialogSaveFinished_ = false;
|
||||
static std::string SessionFileDialogFilename_ = "";
|
||||
|
||||
static void FileDialogOpen(std::string path)
|
||||
static void SessionFileDialogOpen(std::string path)
|
||||
{
|
||||
FileDialogPending_ = true;
|
||||
FileDialogLoadFinished_ = false;
|
||||
SessionFileDialogLoadFinished_ = false;
|
||||
|
||||
char const * open_file_name;
|
||||
char const * open_pattern[1] = { "*.vmx" };
|
||||
@@ -73,17 +74,17 @@ static void FileDialogOpen(std::string path)
|
||||
open_file_name = tinyfd_openFileDialog( "Open a session file", path.c_str(), 1, open_pattern, "vimix session", 0);
|
||||
|
||||
if (!open_file_name)
|
||||
FileDialogFilename_ = "";
|
||||
SessionFileDialogFilename_ = "";
|
||||
else
|
||||
FileDialogFilename_ = std::string( open_file_name );
|
||||
SessionFileDialogFilename_ = std::string( open_file_name );
|
||||
|
||||
FileDialogLoadFinished_ = true;
|
||||
SessionFileDialogLoadFinished_ = true;
|
||||
}
|
||||
|
||||
static void FileDialogSave(std::string path)
|
||||
static void SessionFileDialogSave(std::string path)
|
||||
{
|
||||
FileDialogPending_ = true;
|
||||
FileDialogSaveFinished_ = false;
|
||||
SessionFileDialogSaveFinished_ = false;
|
||||
|
||||
char const * save_file_name;
|
||||
char const * save_pattern[1] = { "*.vmx" };
|
||||
@@ -91,37 +92,32 @@ static void FileDialogSave(std::string path)
|
||||
save_file_name = tinyfd_saveFileDialog( "Save a session file", path.c_str(), 1, save_pattern, "vimix session");
|
||||
|
||||
if (!save_file_name)
|
||||
FileDialogFilename_ = "";
|
||||
SessionFileDialogFilename_ = "";
|
||||
else
|
||||
{
|
||||
FileDialogFilename_ = std::string( save_file_name );
|
||||
SessionFileDialogFilename_ = std::string( save_file_name );
|
||||
// check extension
|
||||
std::string extension = FileDialogFilename_.substr(FileDialogFilename_.find_last_of(".") + 1);
|
||||
std::string extension = SessionFileDialogFilename_.substr(SessionFileDialogFilename_.find_last_of(".") + 1);
|
||||
if (extension != "vmx")
|
||||
FileDialogFilename_ += ".vmx";
|
||||
SessionFileDialogFilename_ += ".vmx";
|
||||
}
|
||||
|
||||
FileDialogSaveFinished_ = true;
|
||||
SessionFileDialogSaveFinished_ = true;
|
||||
}
|
||||
|
||||
static std::atomic<bool> MediaDialogFinished_ = false;
|
||||
static std::string MediaDialogUri_ = "";
|
||||
static void MediaDialogOpen(std::string path)
|
||||
static void ImportFileDialogOpen(char *filename, const std::string &path)
|
||||
{
|
||||
FileDialogPending_ = true;
|
||||
MediaDialogFinished_ = false;
|
||||
if (FileDialogPending_)
|
||||
return;
|
||||
FileDialogPending_ = true;
|
||||
|
||||
char const * open_file_name;
|
||||
char const * open_pattern[15] = { "*.mp4", "*.mpg", "*.avi", "*.mov", "*.mkv", "*.webm", "*.mod", "*.wmv", "*.mxf", "*.ogg", "*.flv", "*.asf", "*.jpg", "*.png", "*.gif" };
|
||||
char const * open_pattern[17] = { "*vmx", "*.mp4", "*.mpg", "*.avi", "*.mov", "*.mkv", "*.webm", "*.mod", "*.wmv", "*.mxf", "*.ogg", "*.flv", "*.asf", "*.jpg", "*.png", "*.gif", "*.svg" };
|
||||
char const * open_file_name;
|
||||
|
||||
open_file_name = tinyfd_openFileDialog( "Open a Media file", path.c_str(), 15, open_pattern, "Video or image", 0);
|
||||
open_file_name = tinyfd_openFileDialog( "Import a file", path.c_str(), 17, open_pattern, "All supported formats", 0);
|
||||
sprintf(filename, "%s", open_file_name);
|
||||
|
||||
if (!open_file_name)
|
||||
MediaDialogUri_ = "";
|
||||
else
|
||||
MediaDialogUri_ = std::string( open_file_name );
|
||||
|
||||
MediaDialogFinished_ = true;
|
||||
FileDialogPending_ = false;
|
||||
}
|
||||
|
||||
UserInterface::UserInterface()
|
||||
@@ -211,7 +207,7 @@ void UserInterface::handleKeyboard()
|
||||
}
|
||||
else if (ImGui::IsKeyPressed( GLFW_KEY_O )) {
|
||||
// Open session
|
||||
std::thread (FileDialogOpen, Settings::application.recentSessions.path).detach();
|
||||
std::thread (SessionFileDialogOpen, Settings::application.recentSessions.path).detach();
|
||||
navigator.hidePannel();
|
||||
}
|
||||
else if (ImGui::IsKeyPressed( GLFW_KEY_S )) {
|
||||
@@ -378,37 +374,29 @@ void UserInterface::NewFrame()
|
||||
handleMouse();
|
||||
|
||||
// handle FileDialog
|
||||
if (FileDialogLoadFinished_) {
|
||||
FileDialogLoadFinished_ = false;
|
||||
if (SessionFileDialogLoadFinished_) {
|
||||
SessionFileDialogLoadFinished_ = false;
|
||||
FileDialogPending_ = false;
|
||||
if (!FileDialogFilename_.empty()) {
|
||||
Mixer::manager().open(FileDialogFilename_);
|
||||
Settings::application.recentSessions.path = SystemToolkit::path_filename(FileDialogFilename_);
|
||||
if (!SessionFileDialogFilename_.empty()) {
|
||||
Mixer::manager().open(SessionFileDialogFilename_);
|
||||
Settings::application.recentSessions.path = SystemToolkit::path_filename(SessionFileDialogFilename_);
|
||||
}
|
||||
}
|
||||
if (FileDialogSaveFinished_) {
|
||||
FileDialogSaveFinished_ = false;
|
||||
if (SessionFileDialogSaveFinished_) {
|
||||
SessionFileDialogSaveFinished_ = false;
|
||||
FileDialogPending_ = false;
|
||||
if (!FileDialogFilename_.empty()) {
|
||||
Mixer::manager().saveas(FileDialogFilename_);
|
||||
Settings::application.recentSessions.path = SystemToolkit::path_filename(FileDialogFilename_);
|
||||
}
|
||||
}
|
||||
if (MediaDialogFinished_) {
|
||||
MediaDialogFinished_ = false;
|
||||
FileDialogPending_ = false;
|
||||
if (!MediaDialogUri_.empty()) {
|
||||
navigator.setMediaUri(MediaDialogUri_);
|
||||
Settings::application.recentMedia.path = SystemToolkit::path_filename(MediaDialogUri_);
|
||||
if (!SessionFileDialogFilename_.empty()) {
|
||||
Mixer::manager().saveas(SessionFileDialogFilename_);
|
||||
Settings::application.recentSessions.path = SystemToolkit::path_filename(SessionFileDialogFilename_);
|
||||
}
|
||||
}
|
||||
|
||||
// overlay when disabled
|
||||
// overlay to ensure file dialog is modal
|
||||
if (FileDialogPending_){
|
||||
ImGui::OpenPopup("Busy");
|
||||
if (ImGui::BeginPopupModal("Busy", NULL, ImGuiWindowFlags_AlwaysAutoResize))
|
||||
{
|
||||
ImGui::Text("Close dialog to resume...");
|
||||
ImGui::Text("Close file dialog box to resume.");
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
@@ -480,7 +468,7 @@ void UserInterface::showMenuFile()
|
||||
{
|
||||
if (ImGui::MenuItem( ICON_FA_FILE_UPLOAD " Open", "Ctrl+O")) {
|
||||
// launch file dialog to open a session file
|
||||
std::thread (FileDialogOpen, Settings::application.recentSessions.path).detach();
|
||||
std::thread (SessionFileDialogOpen, Settings::application.recentSessions.path).detach();
|
||||
navigator.hidePannel();
|
||||
}
|
||||
if (ImGui::MenuItem( ICON_FA_FILE_DOWNLOAD " Save", "Ctrl+S")) {
|
||||
@@ -488,7 +476,7 @@ void UserInterface::showMenuFile()
|
||||
navigator.hidePannel();
|
||||
}
|
||||
if (ImGui::MenuItem( ICON_FA_FOLDER_OPEN " Save as")) {
|
||||
std::thread (FileDialogSave, Settings::application.recentSessions.path).detach();
|
||||
std::thread (SessionFileDialogSave, Settings::application.recentSessions.path).detach();
|
||||
navigator.hidePannel();
|
||||
}
|
||||
|
||||
@@ -1061,10 +1049,6 @@ void Navigator::RenderSourcePannel(Source *s)
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void Navigator::setMediaUri(std::string path)
|
||||
{
|
||||
sprintf(media_path_, "%s", path.c_str());
|
||||
}
|
||||
|
||||
void Navigator::RenderNewPannel()
|
||||
{
|
||||
@@ -1082,55 +1066,61 @@ void Navigator::RenderNewPannel()
|
||||
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
static int new_source_type = 0;
|
||||
ImGui::Combo("Type", &new_source_type, "Media\0Render\0Clone\0");
|
||||
ImGui::Combo("Origin", &new_source_type, "File\0Software\0Hardware\0");
|
||||
|
||||
// Media Source creation
|
||||
if (new_source_type == 0) {
|
||||
// helper
|
||||
ImGui::SetCursorPosX(pannel_width - 30 + IMGUI_RIGHT_ALIGN);
|
||||
ImGuiToolkit::HelpMarker("A Media source displays an image or a video file.");
|
||||
// browse folder
|
||||
ImGuiToolkit::HelpMarker("Create a source from a file:\n- Video (*.mpg, *mov, *.avi, etc.)\n- Image (*.jpg, *.png, etc.)\n- Vector graphics (*.svg)\n- vimix session (*.vmx)\n\nEquivalent to dropping the file in the workspace.");
|
||||
|
||||
// filename of the media to open
|
||||
static char filename[2048];
|
||||
|
||||
// browse for a filename
|
||||
if (ImGuiToolkit::ButtonIcon(2, 5)) {
|
||||
std::thread (MediaDialogOpen, Settings::application.recentMedia.path).detach();
|
||||
std::thread (ImportFileDialogOpen, filename, Settings::application.recentImport.path).detach();
|
||||
}
|
||||
// combo recent
|
||||
// combo of recent media filenames
|
||||
ImGui::SameLine(0, 10);
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
if (ImGui::BeginCombo("##RecentMedia", "Select recent"))
|
||||
if (ImGui::BeginCombo("##RecentImport", "Select recent"))
|
||||
{
|
||||
std::for_each(Settings::application.recentMedia.filenames.begin(),
|
||||
Settings::application.recentMedia.filenames.end(), [](std::string& path) {
|
||||
std::for_each(Settings::application.recentImport.filenames.begin(),
|
||||
Settings::application.recentImport.filenames.end(), [](std::string& path) {
|
||||
int right = MIN( 40, path.size());
|
||||
if (ImGui::Selectable( path.substr( path.size() - right ).c_str() )) {
|
||||
UserInterface::manager().navigator.setMediaUri(path);
|
||||
sprintf(filename, "%s", path.c_str());
|
||||
}
|
||||
});
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
// uri text entry
|
||||
// filename text entry - [Return] to validate
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
if (ImGui::InputText("Path", media_path_, IM_ARRAYSIZE(media_path_), ImGuiInputTextFlags_EnterReturnsTrue) ) {
|
||||
Mixer::manager().createSourceMedia(media_path_);
|
||||
if (ImGui::InputText("Path", filename, IM_ARRAYSIZE(filename), ImGuiInputTextFlags_EnterReturnsTrue) ) {
|
||||
Mixer::manager().createSourceFile( std::string(filename) );
|
||||
selected_button[NAV_NEW] = false;
|
||||
}
|
||||
|
||||
// Validate button
|
||||
// or press Validate button
|
||||
ImGui::Text(" ");
|
||||
if ( ImGui::Button("Create !", ImVec2(pannel_width - padding_width, 0)) ) {
|
||||
|
||||
if ( SystemToolkit::file_exists(media_path_) ) {
|
||||
Mixer::manager().createSourceMedia(media_path_);
|
||||
selected_button[NAV_NEW] = false;
|
||||
}
|
||||
Mixer::manager().createSourceFile( std::string(filename) );
|
||||
selected_button[NAV_NEW] = false;
|
||||
}
|
||||
}
|
||||
// Render Source creator
|
||||
else if (new_source_type == 1){
|
||||
|
||||
// helper
|
||||
ImGui::SetCursorPosX(pannel_width - 30 + IMGUI_RIGHT_ALIGN);
|
||||
ImGuiToolkit::HelpMarker("A Render source replicates the rendering of the output.");
|
||||
ImGuiToolkit::HelpMarker("Create a source from a software algorithm or from vimix objects.");
|
||||
|
||||
}
|
||||
// Hardware
|
||||
else {
|
||||
// helper
|
||||
ImGui::SetCursorPosX(pannel_width - 30 + IMGUI_RIGHT_ALIGN);
|
||||
ImGuiToolkit::HelpMarker("A Clone source duplicates the content of another source.");
|
||||
ImGuiToolkit::HelpMarker("Create a source capturing images from an external hardware.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,8 +33,6 @@ class Navigator
|
||||
void RenderNewPannel();
|
||||
void RenderMainPannel();
|
||||
|
||||
char media_path_[1024];
|
||||
|
||||
public:
|
||||
Navigator();
|
||||
|
||||
@@ -43,7 +41,6 @@ public:
|
||||
void showPannelSource(int index);
|
||||
void Render();
|
||||
|
||||
void setMediaUri(std::string path);
|
||||
};
|
||||
|
||||
class ToolBox
|
||||
|
||||
1
View.cpp
1
View.cpp
@@ -304,6 +304,7 @@ void GeometryView::grab (glm::vec2 from, glm::vec2 to, Source *s, std::pair<Node
|
||||
S_resize.y = S_resize.x;
|
||||
sourceNode->scale_ = start_scale * S_resize;
|
||||
|
||||
Log::Info(" resize ( %.1f, %.1f ) ", S_resize.x, S_resize.y);
|
||||
// glm::vec3 factor = S_resize * glm::vec3(0.5f, 0.5f, 1.f);
|
||||
//// glm::vec3 factor = S_resize * glm::vec3(1.f, 1.f, 1.f);
|
||||
//// factor *= glm::sign( glm::vec3(pick.second, 1.f) );
|
||||
|
||||
Reference in New Issue
Block a user