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:
brunoherbelin
2020-06-21 00:52:59 +02:00
parent 10d0a8c04b
commit 8684d6f2c2
15 changed files with 1055 additions and 495 deletions

View File

@@ -37,7 +37,8 @@ void DrawVisitor::visit(Group &n)
// traverse children // traverse children
glm::mat4 mv = modelview_; glm::mat4 mv = modelview_;
for (NodeSet::iterator node = n.begin(); !done_ && node != n.end(); node++) { for (NodeSet::iterator node = n.begin(); !done_ && node != n.end(); node++) {
(*node)->accept(*this); if ( (*node)->visible_ )
(*node)->accept(*this);
modelview_ = mv; modelview_ = mv;
} }
} }

View File

@@ -40,6 +40,7 @@ MediaPlayer::MediaPlayer(string name) : id_(name)
seekable_ = false; seekable_ = false;
isimage_ = false; isimage_ = false;
interlaced_ = false; interlaced_ = false;
enabled_ = true;
need_loop_ = false; need_loop_ = false;
v_frame_is_full_ = false; v_frame_is_full_ = false;
rate_ = 1.0; rate_ = 1.0;
@@ -271,10 +272,37 @@ GstClockTime MediaPlayer::position()
return pos - start_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) void MediaPlayer::play(bool on)
{ {
// cannot play an image // cannot play an image
if (isimage_) if (!enabled_ || isimage_)
return; return;
// request state // request state
@@ -299,7 +327,7 @@ void MediaPlayer::play(bool on)
// all ready, apply state change immediately // all ready, apply state change immediately
GstStateChangeReturn ret = gst_element_set_state (pipeline_, desired_state_); GstStateChangeReturn ret = gst_element_set_state (pipeline_, desired_state_);
if (ret == GST_STATE_CHANGE_FAILURE) { 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; failed_ = true;
} }
#ifdef MEDIA_PLAYER_DEBUG #ifdef MEDIA_PLAYER_DEBUG
@@ -317,7 +345,7 @@ void MediaPlayer::play(bool on)
bool MediaPlayer::isPlaying(bool testpipeline) const bool MediaPlayer::isPlaying(bool testpipeline) const
{ {
// image cannot play // image cannot play
if (isimage_) if (!enabled_ || isimage_)
return false; return false;
// if not ready yet, answer with requested state // if not ready yet, answer with requested state
@@ -328,8 +356,6 @@ bool MediaPlayer::isPlaying(bool testpipeline) const
GstState state; GstState state;
gst_element_get_state (pipeline_, &state, NULL, GST_CLOCK_TIME_NONE); gst_element_get_state (pipeline_, &state, NULL, GST_CLOCK_TIME_NONE);
return state == GST_STATE_PLAYING; return state == GST_STATE_PLAYING;
// return desired_state == GST_STATE_PLAYING;
} }
@@ -345,7 +371,7 @@ void MediaPlayer::setLoop(MediaPlayer::LoopMode mode)
void MediaPlayer::rewind() void MediaPlayer::rewind()
{ {
if (!seekable_) if (!enabled_ || !seekable_)
return; return;
if (rate_ > 0.0) if (rate_ > 0.0)
@@ -360,7 +386,7 @@ void MediaPlayer::rewind()
void MediaPlayer::seekNextFrame() void MediaPlayer::seekNextFrame()
{ {
// useful only when Paused // useful only when Paused
if (isPlaying()) if (!enabled_ || isPlaying())
return; return;
if ( loop_ != LOOP_NONE) { if ( loop_ != LOOP_NONE) {
@@ -376,7 +402,7 @@ void MediaPlayer::seekNextFrame()
void MediaPlayer::seekTo(GstClockTime pos) void MediaPlayer::seekTo(GstClockTime pos)
{ {
if (!seekable_) if (!enabled_ || !seekable_)
return; return;
// apply seek // apply seek
@@ -387,7 +413,7 @@ void MediaPlayer::seekTo(GstClockTime pos)
void MediaPlayer::fastForward() void MediaPlayer::fastForward()
{ {
if (!seekable_) if (!enabled_ || !seekable_)
return; return;
double step = SIGN(rate_) * 0.01 * static_cast<double>(duration_); double step = SIGN(rate_) * 0.01 * static_cast<double>(duration_);
@@ -459,6 +485,9 @@ void MediaPlayer::update()
discoverer_ = nullptr; discoverer_ = nullptr;
} }
if (!enabled_)
return;
// apply texture // apply texture
if (v_frame_is_full_) { if (v_frame_is_full_) {
// first occurence; create texture // first occurence; create texture

View File

@@ -119,6 +119,11 @@ public:
* Must be called in update loop * Must be called in update loop
* */ * */
void update(); void update();
void enable(bool on);
bool isEnabled() const;
/** /**
* Pause / Play * Pause / Play
* Can play backward if play speed is negative * Can play backward if play speed is negative
@@ -256,6 +261,7 @@ private:
bool seekable_; bool seekable_;
bool isimage_; bool isimage_;
bool interlaced_; bool interlaced_;
bool enabled_;
void execute_open(); void execute_open();
void execute_loop_command(); void execute_loop_command();

View File

@@ -11,7 +11,7 @@
#include "Visitor.h" #include "Visitor.h"
#include "Log.h" #include "Log.h"
MediaSource::MediaSource() : Source(), path_("") MediaSource::MediaSource() : Source(), path_(""), media_playing_(true)
{ {
// create media player // create media player
mediaplayer_ = new MediaPlayer; mediaplayer_ = new MediaPlayer;
@@ -35,7 +35,7 @@ void MediaSource::setPath(const std::string &p)
{ {
path_ = p; path_ = p;
mediaplayer_->open(path_); mediaplayer_->open(path_);
mediaplayer_->play(true); mediaplayer_->play(media_playing_);
Log::Notify("Opening %s", p.c_str()); 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() void MediaSource::render()
{ {
if (!initialized_) if (!initialized_)
init(); init();
else { else {
// update video
mediaplayer_->update();
// render the media player into frame buffer // 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); static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f);

View File

@@ -10,6 +10,8 @@ public:
~MediaSource(); ~MediaSource();
// implementation of source API // implementation of source API
void update (float dt) override;
void setActive (bool on) override;
void render() override; void render() override;
bool failed() const override; bool failed() const override;
uint texture() const override; uint texture() const override;
@@ -27,6 +29,7 @@ protected:
Surface *mediasurface_; Surface *mediasurface_;
std::string path_; std::string path_;
MediaPlayer *mediaplayer_; MediaPlayer *mediaplayer_;
bool media_playing_;
}; };
#endif // MEDIASOURCE_H #endif // MEDIASOURCE_H

View File

@@ -26,7 +26,7 @@ void Selection::remove(Source *s)
SourceList::iterator it = find(s); SourceList::iterator it = find(s);
if (it != selection_.end()) { if (it != selection_.end()) {
selection_.erase(it); 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) void Selection::remove(SourceList l)
{ {
for(auto it = l.begin(); it != l.end(); it++) 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 // generate new set as difference of current selection and give list
SourceList result; SourceList result;
@@ -95,7 +95,7 @@ void Selection::remove(SourceList l)
void Selection::clear() void Selection::clear()
{ {
for(auto it = selection_.begin(); it != selection_.end(); it++) for(auto it = selection_.begin(); it != selection_.end(); it++)
(*it)->setMode(Source::NORMAL); (*it)->setMode(Source::VISIBLE);
selection_.clear(); selection_.clear();
} }

View File

@@ -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() void SessionSource::render()
{ {
if (!initialized_) if (!initialized_)
init(); init();
else { 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 // render the sesion into frame buffer
static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f); static glm::mat4 projection = glm::ortho(-1.f, 1.f, 1.f, -1.f, -1.f, 1.f);
renderbuffer_->begin(); renderbuffer_->begin();

View File

@@ -11,6 +11,7 @@ public:
~SessionSource(); ~SessionSource();
// implementation of source API // implementation of source API
void update (float dt) override;
void render() override; void render() override;
bool failed() const override; bool failed() const override;
uint texture() const override; uint texture() const override;

View File

@@ -15,12 +15,13 @@
#include "ImageShader.h" #include "ImageShader.h"
#include "ImageProcessingShader.h" #include "ImageProcessingShader.h"
#include "Log.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_, "__"); sprintf(initials_, "__");
name_ = "Source"; name_ = "Source";
mode_ = Source::HIDDEN; mode_ = Source::UNINITIALIZED;
// create groups and overlays for each view // create groups and overlays for each view
@@ -168,20 +169,23 @@ Source::Mode Source::mode() const
void Source::setMode(Source::Mode m) void Source::setMode(Source::Mode m)
{ {
mode_ = m; // make visible on first time
if ( mode_ == Source::UNINITIALIZED ) {
for (auto g = groups_.begin(); g != groups_.end(); g++)
(*g).second->visible_ = true;
}
bool visible = mode_ != Source::HIDDEN; // choose frame if selected
for (auto g = groups_.begin(); g != groups_.end(); g++) uint index_frame = m == Source::SELECTED ? 1 : 0;
(*g).second->visible_ = visible;
uint index_frame = mode_ == Source::NORMAL ? 0 : 1;
for (auto f = frames_.begin(); f != frames_.end(); f++) for (auto f = frames_.begin(); f != frames_.end(); f++)
(*f).second->setActive(index_frame); (*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++) for (auto o = overlays_.begin(); o != overlays_.end(); o++)
(*o).second->visible_ = current; (*o).second->visible_ = current;
mode_ = m;
} }
// test update callback // test update callback
@@ -228,8 +232,23 @@ void Source::attach(FrameBuffer *renderbuffer)
// groups_[View::GEOMETRY]->update_callbacks_.push_front(fix_ar); // groups_[View::GEOMETRY]->update_callbacks_.push_front(fix_ar);
// make the source visible // make the source visible
if ( mode_ == HIDDEN ) if ( mode_ == UNINITIALIZED )
setMode(NORMAL); 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) 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 ); float alpha = 1.0 - CLAMP( ( dist.x * dist.x ) + ( dist.y * dist.y ), 0.f, 1.f );
blendingshader_->color.a = alpha; blendingshader_->color.a = alpha;
// CHANGE update status based on limbo
setActive( glm::length(dist) < 1.3f );
// MODIFY geometry based on GEOMETRY node // MODIFY geometry based on GEOMETRY node
groups_[View::RENDERING]->translation_ = groups_[View::GEOMETRY]->translation_; groups_[View::RENDERING]->translation_ = groups_[View::GEOMETRY]->translation_;
groups_[View::RENDERING]->rotation_ = groups_[View::GEOMETRY]->rotation_; 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() void CloneSource::render()
{ {
if (!initialized_) if (!initialized_)

View File

@@ -38,42 +38,47 @@ public:
// manipulate name of source // manipulate name of source
void setName (const std::string &name); void setName (const std::string &name);
inline std::string name () const { return name_; } inline std::string name () const { return name_; }
inline const char *initials() const { return initials_; } inline const char *initials () const { return initials_; }
// cloning mechanism // cloning mechanism
virtual CloneSource *clone(); virtual CloneSource *clone ();
// Display mode // Display mode
typedef enum { typedef enum {
HIDDEN = 0, UNINITIALIZED = 0,
NORMAL = 1, VISIBLE = 1,
SELECTED = 2, SELECTED = 2,
CURRENT = 3 CURRENT = 3
} Mode; } Mode;
Mode mode() const; Mode mode () const;
void setMode(Mode m); void setMode (Mode m);
// get handle on the nodes used to manipulate the source in a view // 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 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 Node *groupNode (View::Mode m) const { return static_cast<Node*>(groups_.at(m)); }
// tests if a given node is part of the source // 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 // 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 // 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 // every Source has a frame buffer from the renderbuffer
virtual FrameBuffer *frame() const; virtual FrameBuffer *frame () const;
// touch to request update // 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) // 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 // accept all kind of visitors
virtual void accept (Visitor& v); virtual void accept (Visitor& v);
@@ -143,6 +148,7 @@ protected:
Handles *handle_[4]; Handles *handle_[4];
// update // update
bool active_;
bool need_update_; bool need_update_;
float dt_; float dt_;
Group *stored_status_; Group *stored_status_;
@@ -161,6 +167,7 @@ public:
~CloneSource(); ~CloneSource();
// implementation of source API // implementation of source API
void setActive (bool on) override;
void render() override; void render() override;
uint texture() const override { return origin_->texture(); } uint texture() const override { return origin_->texture(); }
bool failed() const override { return origin_ == nullptr; } bool failed() const override { return origin_ == nullptr; }

View File

@@ -795,7 +795,7 @@ void UserInterface::RenderMediaPlayer()
} }
ImGui::SetCursorScreenPos(draw_pos); 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)) if (ImGui::Button(ICON_FA_FAST_BACKWARD))
mp->rewind(); mp->rewind();

View File

@@ -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 // read default settings
if ( Settings::application.views[mode_].name.empty() ) { if ( Settings::application.views[mode_].name.empty() ) {
@@ -162,7 +162,12 @@ MixingView::MixingView() : View(MIXING)
scene.bg()->attach(disk); scene.bg()->attach(disk);
Mesh *circle = new Mesh("mesh/circle.ply"); 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); scene.bg()->attach(circle);
} }

2
View.h
View File

@@ -89,9 +89,11 @@ public:
Cursor grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2>) override; Cursor grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2>) override;
void setAlpha (Source *s); void setAlpha (Source *s);
inline float limboScale() { return limbo_scale_; }
private: private:
uint textureMixingQuadratic(); uint textureMixingQuadratic();
float limbo_scale_;
}; };
class RenderView : public View class RenderView : public View

View File

@@ -57,6 +57,7 @@
#define COLOR_DEFAULT_SOURCE 0.8f, 0.8f, 0.8f #define COLOR_DEFAULT_SOURCE 0.8f, 0.8f, 0.8f
#define COLOR_HIGHLIGHT_SOURCE 1.f, 1.f, 1.f #define COLOR_HIGHLIGHT_SOURCE 1.f, 1.f, 1.f
#define COLOR_FRAME 0.8f, 0.f, 0.8f #define COLOR_FRAME 0.8f, 0.f, 0.8f
#define COLOR_LIMBO_CIRCLE 0.7f, 0.7f, 0.7f
// from glmixer // from glmixer
#define TEXTURE_REQUIRED_MAXIMUM 2048 #define TEXTURE_REQUIRED_MAXIMUM 2048
@@ -84,7 +85,7 @@
#define COLOR_CIRCLE_MOVE 230, 30, 230 #define COLOR_CIRCLE_MOVE 230, 30, 230
#define COLOR_DRAWINGS 180, 180, 180 #define COLOR_DRAWINGS 180, 180, 180
#define COLOR_LIMBO 35, 35, 35 #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_FADING 25, 25, 25
#define COLOR_FLASHING 250, 250, 250 #define COLOR_FLASHING 250, 250, 250
#define COLOR_FRAME_MOVE 230, 30, 230 #define COLOR_FRAME_MOVE 230, 30, 230

File diff suppressed because it is too large Load Diff