mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-12 10:49:59 +01:00
Implementation of the limbo area in Mixing view, to change update mode
of source (active or not) and suspend mediaplayer (enabled or not).
This commit is contained in:
@@ -37,6 +37,7 @@ void DrawVisitor::visit(Group &n)
|
||||
// traverse children
|
||||
glm::mat4 mv = modelview_;
|
||||
for (NodeSet::iterator node = n.begin(); !done_ && node != n.end(); node++) {
|
||||
if ( (*node)->visible_ )
|
||||
(*node)->accept(*this);
|
||||
modelview_ = mv;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ MediaPlayer::MediaPlayer(string name) : id_(name)
|
||||
seekable_ = false;
|
||||
isimage_ = false;
|
||||
interlaced_ = false;
|
||||
enabled_ = true;
|
||||
need_loop_ = false;
|
||||
v_frame_is_full_ = false;
|
||||
rate_ = 1.0;
|
||||
@@ -271,10 +272,37 @@ GstClockTime MediaPlayer::position()
|
||||
return pos - start_position_;
|
||||
}
|
||||
|
||||
void MediaPlayer::enable(bool on)
|
||||
{
|
||||
if ( enabled_ != on ) {
|
||||
|
||||
enabled_ = on;
|
||||
|
||||
GstState requested_state = GST_STATE_PAUSED;
|
||||
|
||||
if (enabled_) {
|
||||
requested_state = desired_state_;
|
||||
}
|
||||
|
||||
// apply state change
|
||||
GstStateChangeReturn ret = gst_element_set_state (pipeline_, requested_state);
|
||||
if (ret == GST_STATE_CHANGE_FAILURE) {
|
||||
Log::Warning("MediaPlayer %s Failed to enable", gst_element_get_name(pipeline_));
|
||||
failed_ = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool MediaPlayer::isEnabled() const
|
||||
{
|
||||
return enabled_;
|
||||
}
|
||||
|
||||
void MediaPlayer::play(bool on)
|
||||
{
|
||||
// cannot play an image
|
||||
if (isimage_)
|
||||
if (!enabled_ || isimage_)
|
||||
return;
|
||||
|
||||
// request state
|
||||
@@ -299,7 +327,7 @@ void MediaPlayer::play(bool on)
|
||||
// all ready, apply state change immediately
|
||||
GstStateChangeReturn ret = gst_element_set_state (pipeline_, desired_state_);
|
||||
if (ret == GST_STATE_CHANGE_FAILURE) {
|
||||
Log::Warning("MediaPlayer %s Failed to start", gst_element_get_name(pipeline_));
|
||||
Log::Warning("MediaPlayer %s Failed to play", gst_element_get_name(pipeline_));
|
||||
failed_ = true;
|
||||
}
|
||||
#ifdef MEDIA_PLAYER_DEBUG
|
||||
@@ -317,7 +345,7 @@ void MediaPlayer::play(bool on)
|
||||
bool MediaPlayer::isPlaying(bool testpipeline) const
|
||||
{
|
||||
// image cannot play
|
||||
if (isimage_)
|
||||
if (!enabled_ || isimage_)
|
||||
return false;
|
||||
|
||||
// if not ready yet, answer with requested state
|
||||
@@ -328,8 +356,6 @@ bool MediaPlayer::isPlaying(bool testpipeline) const
|
||||
GstState state;
|
||||
gst_element_get_state (pipeline_, &state, NULL, GST_CLOCK_TIME_NONE);
|
||||
return state == GST_STATE_PLAYING;
|
||||
|
||||
// return desired_state == GST_STATE_PLAYING;
|
||||
}
|
||||
|
||||
|
||||
@@ -345,7 +371,7 @@ void MediaPlayer::setLoop(MediaPlayer::LoopMode mode)
|
||||
|
||||
void MediaPlayer::rewind()
|
||||
{
|
||||
if (!seekable_)
|
||||
if (!enabled_ || !seekable_)
|
||||
return;
|
||||
|
||||
if (rate_ > 0.0)
|
||||
@@ -360,7 +386,7 @@ void MediaPlayer::rewind()
|
||||
void MediaPlayer::seekNextFrame()
|
||||
{
|
||||
// useful only when Paused
|
||||
if (isPlaying())
|
||||
if (!enabled_ || isPlaying())
|
||||
return;
|
||||
|
||||
if ( loop_ != LOOP_NONE) {
|
||||
@@ -376,7 +402,7 @@ void MediaPlayer::seekNextFrame()
|
||||
|
||||
void MediaPlayer::seekTo(GstClockTime pos)
|
||||
{
|
||||
if (!seekable_)
|
||||
if (!enabled_ || !seekable_)
|
||||
return;
|
||||
|
||||
// apply seek
|
||||
@@ -387,7 +413,7 @@ void MediaPlayer::seekTo(GstClockTime pos)
|
||||
|
||||
void MediaPlayer::fastForward()
|
||||
{
|
||||
if (!seekable_)
|
||||
if (!enabled_ || !seekable_)
|
||||
return;
|
||||
|
||||
double step = SIGN(rate_) * 0.01 * static_cast<double>(duration_);
|
||||
@@ -459,6 +485,9 @@ void MediaPlayer::update()
|
||||
discoverer_ = nullptr;
|
||||
}
|
||||
|
||||
if (!enabled_)
|
||||
return;
|
||||
|
||||
// apply texture
|
||||
if (v_frame_is_full_) {
|
||||
// first occurence; create texture
|
||||
|
||||
@@ -119,6 +119,11 @@ public:
|
||||
* Must be called in update loop
|
||||
* */
|
||||
void update();
|
||||
|
||||
void enable(bool on);
|
||||
|
||||
bool isEnabled() const;
|
||||
|
||||
/**
|
||||
* Pause / Play
|
||||
* Can play backward if play speed is negative
|
||||
@@ -256,6 +261,7 @@ private:
|
||||
bool seekable_;
|
||||
bool isimage_;
|
||||
bool interlaced_;
|
||||
bool enabled_;
|
||||
|
||||
void execute_open();
|
||||
void execute_loop_command();
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "Visitor.h"
|
||||
#include "Log.h"
|
||||
|
||||
MediaSource::MediaSource() : Source(), path_("")
|
||||
MediaSource::MediaSource() : Source(), path_(""), media_playing_(true)
|
||||
{
|
||||
// create media player
|
||||
mediaplayer_ = new MediaPlayer;
|
||||
@@ -35,7 +35,7 @@ void MediaSource::setPath(const std::string &p)
|
||||
{
|
||||
path_ = p;
|
||||
mediaplayer_->open(path_);
|
||||
mediaplayer_->play(true);
|
||||
mediaplayer_->play(media_playing_);
|
||||
|
||||
Log::Notify("Opening %s", p.c_str());
|
||||
}
|
||||
@@ -98,13 +98,30 @@ void MediaSource::init()
|
||||
|
||||
}
|
||||
|
||||
void MediaSource::setActive (bool on)
|
||||
{
|
||||
bool was_active = active_;
|
||||
|
||||
Source::setActive(on);
|
||||
|
||||
if ( active_ != was_active ) {
|
||||
mediaplayer()->enable(active_);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaSource::update(float dt)
|
||||
{
|
||||
// update video
|
||||
mediaplayer_->update();
|
||||
|
||||
Source::update(dt);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -10,6 +10,8 @@ public:
|
||||
~MediaSource();
|
||||
|
||||
// implementation of source API
|
||||
void update (float dt) override;
|
||||
void setActive (bool on) override;
|
||||
void render() override;
|
||||
bool failed() const override;
|
||||
uint texture() const override;
|
||||
@@ -27,6 +29,7 @@ protected:
|
||||
Surface *mediasurface_;
|
||||
std::string path_;
|
||||
MediaPlayer *mediaplayer_;
|
||||
bool media_playing_;
|
||||
};
|
||||
|
||||
#endif // MEDIASOURCE_H
|
||||
|
||||
@@ -26,7 +26,7 @@ void Selection::remove(Source *s)
|
||||
SourceList::iterator it = find(s);
|
||||
if (it != selection_.end()) {
|
||||
selection_.erase(it);
|
||||
s->setMode(Source::NORMAL);
|
||||
s->setMode(Source::VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ void Selection::add(SourceList l)
|
||||
void Selection::remove(SourceList l)
|
||||
{
|
||||
for(auto it = l.begin(); it != l.end(); it++)
|
||||
(*it)->setMode(Source::NORMAL);
|
||||
(*it)->setMode(Source::VISIBLE);
|
||||
|
||||
// generate new set as difference of current selection and give list
|
||||
SourceList result;
|
||||
@@ -95,7 +95,7 @@ void Selection::remove(SourceList l)
|
||||
void Selection::clear()
|
||||
{
|
||||
for(auto it = selection_.begin(); it != selection_.end(); it++)
|
||||
(*it)->setMode(Source::NORMAL);
|
||||
(*it)->setMode(Source::VISIBLE);
|
||||
|
||||
selection_.clear();
|
||||
}
|
||||
|
||||
@@ -131,18 +131,25 @@ void SessionSource::init()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SessionSource::update(float dt)
|
||||
{
|
||||
// delete a source which failed
|
||||
if (session()->failedSource() != nullptr)
|
||||
session()->deleteSource(session()->failedSource());
|
||||
|
||||
// update video
|
||||
if (active_)
|
||||
session_->update(dt);
|
||||
|
||||
Source::update(dt);
|
||||
}
|
||||
|
||||
void SessionSource::render()
|
||||
{
|
||||
if (!initialized_)
|
||||
init();
|
||||
else {
|
||||
// update session
|
||||
session_->update(dt_);
|
||||
|
||||
// delete a source which failed
|
||||
if (session()->failedSource() != nullptr)
|
||||
session()->deleteSource(session()->failedSource());
|
||||
|
||||
// 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();
|
||||
|
||||
@@ -11,6 +11,7 @@ public:
|
||||
~SessionSource();
|
||||
|
||||
// implementation of source API
|
||||
void update (float dt) override;
|
||||
void render() override;
|
||||
bool failed() const override;
|
||||
uint texture() const override;
|
||||
|
||||
53
Source.cpp
53
Source.cpp
@@ -15,12 +15,13 @@
|
||||
#include "ImageShader.h"
|
||||
#include "ImageProcessingShader.h"
|
||||
#include "Log.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
Source::Source() : initialized_(false), need_update_(true)
|
||||
Source::Source() : initialized_(false), active_(true), need_update_(true)
|
||||
{
|
||||
sprintf(initials_, "__");
|
||||
name_ = "Source";
|
||||
mode_ = Source::HIDDEN;
|
||||
mode_ = Source::UNINITIALIZED;
|
||||
|
||||
// create groups and overlays for each view
|
||||
|
||||
@@ -168,20 +169,23 @@ Source::Mode Source::mode() const
|
||||
|
||||
void Source::setMode(Source::Mode m)
|
||||
{
|
||||
mode_ = m;
|
||||
|
||||
bool visible = mode_ != Source::HIDDEN;
|
||||
// make visible on first time
|
||||
if ( mode_ == Source::UNINITIALIZED ) {
|
||||
for (auto g = groups_.begin(); g != groups_.end(); g++)
|
||||
(*g).second->visible_ = visible;
|
||||
(*g).second->visible_ = true;
|
||||
}
|
||||
|
||||
uint index_frame = mode_ == Source::NORMAL ? 0 : 1;
|
||||
// choose frame if selected
|
||||
uint index_frame = m == Source::SELECTED ? 1 : 0;
|
||||
for (auto f = frames_.begin(); f != frames_.end(); f++)
|
||||
(*f).second->setActive(index_frame);
|
||||
|
||||
bool current = mode_ == Source::CURRENT;
|
||||
// show overlay if current
|
||||
bool current = m == Source::CURRENT;
|
||||
for (auto o = overlays_.begin(); o != overlays_.end(); o++)
|
||||
(*o).second->visible_ = current;
|
||||
|
||||
mode_ = m;
|
||||
}
|
||||
|
||||
// test update callback
|
||||
@@ -228,8 +232,23 @@ void Source::attach(FrameBuffer *renderbuffer)
|
||||
// groups_[View::GEOMETRY]->update_callbacks_.push_front(fix_ar);
|
||||
|
||||
// make the source visible
|
||||
if ( mode_ == HIDDEN )
|
||||
setMode(NORMAL);
|
||||
if ( mode_ == UNINITIALIZED )
|
||||
setMode(VISIBLE);
|
||||
}
|
||||
|
||||
void Source::setActive (bool on)
|
||||
{
|
||||
active_ = on;
|
||||
|
||||
for(auto clone = clones_.begin(); clone != clones_.end(); clone++) {
|
||||
if ( (*clone)->active() )
|
||||
active_ = true;
|
||||
}
|
||||
|
||||
groups_[View::RENDERING]->visible_ = active_;
|
||||
groups_[View::GEOMETRY]->visible_ = active_;
|
||||
groups_[View::LAYER]->visible_ = active_;
|
||||
|
||||
}
|
||||
|
||||
void Source::update(float dt)
|
||||
@@ -246,6 +265,9 @@ void Source::update(float dt)
|
||||
float alpha = 1.0 - CLAMP( ( dist.x * dist.x ) + ( dist.y * dist.y ), 0.f, 1.f );
|
||||
blendingshader_->color.a = alpha;
|
||||
|
||||
// CHANGE update status based on limbo
|
||||
setActive( glm::length(dist) < 1.3f );
|
||||
|
||||
// MODIFY geometry based on GEOMETRY node
|
||||
groups_[View::RENDERING]->translation_ = groups_[View::GEOMETRY]->translation_;
|
||||
groups_[View::RENDERING]->rotation_ = groups_[View::GEOMETRY]->rotation_;
|
||||
@@ -359,6 +381,17 @@ void CloneSource::init()
|
||||
}
|
||||
}
|
||||
|
||||
void CloneSource::setActive (bool on)
|
||||
{
|
||||
active_ = on;
|
||||
|
||||
groups_[View::RENDERING]->visible_ = active_;
|
||||
groups_[View::GEOMETRY]->visible_ = active_;
|
||||
groups_[View::LAYER]->visible_ = active_;
|
||||
|
||||
origin_->touch();
|
||||
}
|
||||
|
||||
void CloneSource::render()
|
||||
{
|
||||
if (!initialized_)
|
||||
|
||||
35
Source.h
35
Source.h
@@ -38,42 +38,47 @@ public:
|
||||
// manipulate name of source
|
||||
void setName (const std::string &name);
|
||||
inline std::string name () const { return name_; }
|
||||
inline const char *initials() const { return initials_; }
|
||||
inline const char *initials () const { return initials_; }
|
||||
|
||||
// cloning mechanism
|
||||
virtual CloneSource *clone();
|
||||
virtual CloneSource *clone ();
|
||||
|
||||
// Display mode
|
||||
typedef enum {
|
||||
HIDDEN = 0,
|
||||
NORMAL = 1,
|
||||
UNINITIALIZED = 0,
|
||||
VISIBLE = 1,
|
||||
SELECTED = 2,
|
||||
CURRENT = 3
|
||||
} Mode;
|
||||
Mode mode() const;
|
||||
void setMode(Mode m);
|
||||
Mode mode () const;
|
||||
void setMode (Mode m);
|
||||
|
||||
|
||||
// get handle on the nodes used to manipulate the source in a view
|
||||
inline Group *group(View::Mode m) const { return groups_.at(m); }
|
||||
inline Node *groupNode(View::Mode m) const { return static_cast<Node*>(groups_.at(m)); }
|
||||
inline Group *group (View::Mode m) const { return groups_.at(m); }
|
||||
inline Node *groupNode (View::Mode m) const { return static_cast<Node*>(groups_.at(m)); }
|
||||
|
||||
// tests if a given node is part of the source
|
||||
bool contains(Node *node) const;
|
||||
bool contains (Node *node) const;
|
||||
|
||||
// a Source has a shader to control image processing effects
|
||||
inline ImageProcessingShader *processingShader() const { return rendershader_; }
|
||||
inline ImageProcessingShader *processingShader () const { return rendershader_; }
|
||||
|
||||
// a Source has a shader to control mixing effects
|
||||
inline ImageShader *blendingShader() const { return blendingshader_; }
|
||||
inline ImageShader *blendingShader () const { return blendingshader_; }
|
||||
|
||||
// every Source has a frame buffer from the renderbuffer
|
||||
virtual FrameBuffer *frame() const;
|
||||
virtual FrameBuffer *frame () const;
|
||||
|
||||
// touch to request update
|
||||
inline void touch() { need_update_ = true; }
|
||||
inline void touch () { need_update_ = true; }
|
||||
|
||||
// a Source shall be updated before displayed (Mixing, Geometry and Layer)
|
||||
void update (float dt);
|
||||
virtual void update (float dt);
|
||||
|
||||
// update mode
|
||||
virtual void setActive (bool on);
|
||||
inline bool active () { return active_; }
|
||||
|
||||
// accept all kind of visitors
|
||||
virtual void accept (Visitor& v);
|
||||
@@ -143,6 +148,7 @@ protected:
|
||||
Handles *handle_[4];
|
||||
|
||||
// update
|
||||
bool active_;
|
||||
bool need_update_;
|
||||
float dt_;
|
||||
Group *stored_status_;
|
||||
@@ -161,6 +167,7 @@ public:
|
||||
~CloneSource();
|
||||
|
||||
// implementation of source API
|
||||
void setActive (bool on) override;
|
||||
void render() override;
|
||||
uint texture() const override { return origin_->texture(); }
|
||||
bool failed() const override { return origin_ == nullptr; }
|
||||
|
||||
@@ -795,7 +795,7 @@ void UserInterface::RenderMediaPlayer()
|
||||
}
|
||||
ImGui::SetCursorScreenPos(draw_pos);
|
||||
|
||||
if (mp->duration() != GST_CLOCK_TIME_NONE) {
|
||||
if ( mp->isEnabled() && mp->duration() != GST_CLOCK_TIME_NONE) {
|
||||
|
||||
if (ImGui::Button(ICON_FA_FAST_BACKWARD))
|
||||
mp->rewind();
|
||||
|
||||
9
View.cpp
9
View.cpp
@@ -145,7 +145,7 @@ void View::select(glm::vec2 A, glm::vec2 B)
|
||||
}
|
||||
|
||||
|
||||
MixingView::MixingView() : View(MIXING)
|
||||
MixingView::MixingView() : View(MIXING), limbo_scale_(1.3f)
|
||||
{
|
||||
// read default settings
|
||||
if ( Settings::application.views[mode_].name.empty() ) {
|
||||
@@ -162,7 +162,12 @@ MixingView::MixingView() : View(MIXING)
|
||||
scene.bg()->attach(disk);
|
||||
|
||||
Mesh *circle = new Mesh("mesh/circle.ply");
|
||||
circle->shader()->color = glm::vec4( COLOR_FRAME, 1.f );
|
||||
circle->shader()->color = glm::vec4( COLOR_FRAME, 0.9f );
|
||||
scene.bg()->attach(circle);
|
||||
|
||||
circle = new Mesh("mesh/circle.ply");
|
||||
circle->scale_ = glm::vec3(limbo_scale_, limbo_scale_, 1.f);
|
||||
circle->shader()->color = glm::vec4( COLOR_LIMBO_CIRCLE, 0.6f );
|
||||
scene.bg()->attach(circle);
|
||||
}
|
||||
|
||||
|
||||
2
View.h
2
View.h
@@ -89,9 +89,11 @@ public:
|
||||
Cursor grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2>) override;
|
||||
|
||||
void setAlpha (Source *s);
|
||||
inline float limboScale() { return limbo_scale_; }
|
||||
|
||||
private:
|
||||
uint textureMixingQuadratic();
|
||||
float limbo_scale_;
|
||||
};
|
||||
|
||||
class RenderView : public View
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#define COLOR_DEFAULT_SOURCE 0.8f, 0.8f, 0.8f
|
||||
#define COLOR_HIGHLIGHT_SOURCE 1.f, 1.f, 1.f
|
||||
#define COLOR_FRAME 0.8f, 0.f, 0.8f
|
||||
#define COLOR_LIMBO_CIRCLE 0.7f, 0.7f, 0.7f
|
||||
|
||||
// from glmixer
|
||||
#define TEXTURE_REQUIRED_MAXIMUM 2048
|
||||
@@ -84,7 +85,7 @@
|
||||
#define COLOR_CIRCLE_MOVE 230, 30, 230
|
||||
#define COLOR_DRAWINGS 180, 180, 180
|
||||
#define COLOR_LIMBO 35, 35, 35
|
||||
#define COLOR_LIMBO_CIRCLE 210, 160, 210
|
||||
//#define COLOR_LIMBO_CIRCLE 210, 160, 210
|
||||
#define COLOR_FADING 25, 25, 25
|
||||
#define COLOR_FLASHING 250, 250, 250
|
||||
#define COLOR_FRAME_MOVE 230, 30, 230
|
||||
|
||||
1332
rsc/mesh/circle.ply
1332
rsc/mesh/circle.ply
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user