mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-15 12:20:01 +01:00
Saving, undo and dynamic change of MultiFileSource
This commit is contained in:
@@ -709,7 +709,6 @@ void ImGuiVisitor::visit (NetworkSource& s)
|
||||
s.setConnection(s.connection());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -718,33 +717,43 @@ void ImGuiVisitor::visit (MultiFileSource& s)
|
||||
ImGuiToolkit::Icon(s.icon().x, s.icon().y);
|
||||
ImGui::SameLine(0, 10);
|
||||
ImGui::Text("Images sequence");
|
||||
static int64_t id = s.id();
|
||||
|
||||
// information text
|
||||
std::ostringstream msg;
|
||||
msg << "Sequence of " << s.sequence().max - s.sequence().min << " ";
|
||||
msg << "Sequence of " << s.sequence().max - s.sequence().min + 1 << " ";
|
||||
msg << s.sequence().codec << " images";
|
||||
// msg << "named " << SystemToolkit::base_filename( s.sequence().location );
|
||||
// msg << " in range [" << s.sequence().min << " - " << s.sequence().max << "]";
|
||||
ImGui::Text("%s", msg.str().c_str());
|
||||
|
||||
// change range
|
||||
glm::ivec2 range = s.range();
|
||||
static int _begin = -1;
|
||||
if (_begin < 0 || id != s.id())
|
||||
_begin = s.begin();
|
||||
static int _end = -1;
|
||||
if (_end < 0 || id != s.id())
|
||||
_end = s.end();
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
if ( ImGui::DragIntRange2("Range", &range.x, &range.y, 1, s.sequence().min, s.sequence().max) ){
|
||||
s.setRange( range );
|
||||
ImGui::DragIntRange2("Range", &_begin, &_end, 1, s.sequence().min, s.sequence().max);
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()){
|
||||
s.setRange( _begin, _end );
|
||||
std::ostringstream oss;
|
||||
oss << s.name() << ": Range " << _begin << "-" << _end;
|
||||
Action::manager().store(oss.str());
|
||||
_begin = _end = -1;
|
||||
}
|
||||
|
||||
// change framerate
|
||||
int _fps = s.framerate();
|
||||
static int _fps_changed = -1;
|
||||
static int _fps = -1;
|
||||
if (_fps < 0 || id != s.id())
|
||||
_fps = s.framerate();
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
if ( ImGui::SliderInt("Framerate", &_fps, 1, 30, "%d fps") ) {
|
||||
_fps_changed = _fps;
|
||||
}
|
||||
// only call for setFramerate after mouse release to avoid repeating call to re-open the stream
|
||||
else if (_fps_changed > 0 && ImGui::IsMouseReleased(ImGuiMouseButton_Left)){
|
||||
s.setFramerate(_fps_changed);
|
||||
_fps_changed = -1;
|
||||
ImGui::SliderInt("Framerate", &_fps, 1, 30, "%d fps");
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()){
|
||||
s.setFramerate(_fps);
|
||||
std::ostringstream oss;
|
||||
oss << s.name() << ": Framerate " << _fps << " fps";
|
||||
Action::manager().store(oss.str());
|
||||
_fps = -1;
|
||||
}
|
||||
|
||||
// offer to open file browser at location
|
||||
@@ -755,4 +764,5 @@ void ImGuiVisitor::visit (MultiFileSource& s)
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("Folder");
|
||||
|
||||
id = s.id();
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ MultiFile::MultiFile() : Stream(), src_(nullptr)
|
||||
|
||||
}
|
||||
|
||||
void MultiFile::open(const MultiFileSequence &sequence, uint framerate )
|
||||
void MultiFile::open (const MultiFileSequence &sequence, uint framerate )
|
||||
{
|
||||
if (sequence.location.empty())
|
||||
return;
|
||||
@@ -95,8 +95,7 @@ void MultiFile::open(const MultiFileSequence &sequence, uint framerate )
|
||||
gstreamer_pipeline << sequence.codec;
|
||||
gstreamer_pipeline << ",framerate=(fraction)";
|
||||
gstreamer_pipeline << framerate;
|
||||
gstreamer_pipeline << "/1\" loop=";
|
||||
gstreamer_pipeline << sequence.loop;
|
||||
gstreamer_pipeline << "/1\" loop=1";
|
||||
gstreamer_pipeline << " start-index=";
|
||||
gstreamer_pipeline << sequence.min;
|
||||
gstreamer_pipeline << " stop-index=";
|
||||
@@ -106,28 +105,23 @@ void MultiFile::open(const MultiFileSequence &sequence, uint framerate )
|
||||
// (private) open stream
|
||||
Stream::open(gstreamer_pipeline.str(), sequence.width, sequence.height);
|
||||
|
||||
// keep multifile source for dynamic properties change
|
||||
src_ = gst_bin_get_by_name (GST_BIN (pipeline_), "src");
|
||||
|
||||
}
|
||||
|
||||
void MultiFile::setLoop (int on)
|
||||
{
|
||||
if (src_) {
|
||||
g_object_set (src_, "loop", on, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiFile::setRange (int begin, int end)
|
||||
void MultiFile::setProperties (int begin, int end, int loop)
|
||||
{
|
||||
if (src_) {
|
||||
g_object_set (src_, "start-index", MAX(begin, 0), NULL);
|
||||
g_object_set (src_, "stop-index", MAX(end, 0), NULL);
|
||||
g_object_set (src_, "loop", MIN(loop, 1), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
MultiFileSource::MultiFileSource(uint64_t id) : StreamSource(id), framerate_(0), range_(glm::ivec2(0))
|
||||
MultiFileSource::MultiFileSource (uint64_t id) : StreamSource(id), framerate_(0), begin_(-1), end_(INT_MAX), loop_(1)
|
||||
{
|
||||
// create stream
|
||||
stream_ = static_cast<Stream *>( new MultiFile );
|
||||
@@ -154,8 +148,8 @@ void MultiFileSource::setSequence (const MultiFileSequence &sequence, uint frame
|
||||
multifile()->open( sequence_, framerate_ );
|
||||
stream_->play(true);
|
||||
|
||||
// init range
|
||||
range_ = glm::ivec2(sequence_.min, sequence_.max);
|
||||
// validate range and apply loop_
|
||||
setRange(begin_, end_);
|
||||
|
||||
// will be ready after init and one frame rendered
|
||||
ready_ = false;
|
||||
@@ -172,30 +166,30 @@ void MultiFileSource::setFramerate (uint framerate)
|
||||
void MultiFileSource::setLoop (bool on)
|
||||
{
|
||||
if (multifile()) {
|
||||
sequence_.loop = on ? 1 : 0;
|
||||
multifile()->setLoop( sequence_.loop );
|
||||
loop_ = on ? 1 : 0;
|
||||
multifile()->setProperties (begin_, end_, loop_);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiFileSource::setRange (glm::ivec2 range)
|
||||
void MultiFileSource::setRange (int begin, int end)
|
||||
{
|
||||
range_.x = glm::clamp( range.x, sequence_.min, sequence_.max );
|
||||
range_.y = glm::clamp( range.y, sequence_.min, sequence_.max );
|
||||
range_.x = glm::min( range_.x, range_.y );
|
||||
range_.y = glm::max( range_.x, range_.y );
|
||||
begin_ = glm::clamp( begin, sequence_.min, sequence_.max );
|
||||
end_ = glm::clamp( end , sequence_.min, sequence_.max );
|
||||
begin_ = glm::min( begin_, end_ );
|
||||
end_ = glm::max( begin_, end_ );
|
||||
|
||||
if (multifile())
|
||||
multifile()->setRange( range_.x, range_.y );
|
||||
multifile()->setProperties (begin_, end_, loop_);
|
||||
}
|
||||
|
||||
void MultiFileSource::accept(Visitor& v)
|
||||
void MultiFileSource::accept (Visitor& v)
|
||||
{
|
||||
Source::accept(v);
|
||||
if (!failed())
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
MultiFile *MultiFileSource::multifile() const
|
||||
MultiFile *MultiFileSource::multifile () const
|
||||
{
|
||||
return dynamic_cast<MultiFile *>(stream_);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ struct MultiFileSequence {
|
||||
uint height;
|
||||
int min;
|
||||
int max;
|
||||
int begin;
|
||||
int end;
|
||||
int loop;
|
||||
|
||||
MultiFileSequence ();
|
||||
@@ -28,8 +30,8 @@ public:
|
||||
MultiFile ();
|
||||
void open (const MultiFileSequence &sequence, uint framerate = 30);
|
||||
|
||||
void setRange(int begin, int end);
|
||||
void setLoop (int on);
|
||||
// dynamic change of gstreamer multifile source properties
|
||||
void setProperties(int begin, int end, int loop);
|
||||
|
||||
protected:
|
||||
GstElement *src_ ;
|
||||
@@ -57,17 +59,19 @@ public:
|
||||
inline uint framerate () const { return framerate_; }
|
||||
|
||||
void setLoop (bool on);
|
||||
inline bool loop () const { return sequence_.loop; }
|
||||
inline bool loop () const { return loop_ > 0 ? true : false; }
|
||||
|
||||
void setRange (glm::ivec2 range);
|
||||
glm::ivec2 range () const { return range_; }
|
||||
void setRange (int begin, int end);
|
||||
inline int begin() const { return begin_; }
|
||||
inline int end () const { return end_; }
|
||||
|
||||
MultiFile *multifile () const;
|
||||
|
||||
private:
|
||||
MultiFileSequence sequence_;
|
||||
uint framerate_;
|
||||
glm::ivec2 range_;
|
||||
int begin_, end_, loop_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -897,12 +897,12 @@ void SessionLoader::visit (MultiFileSource& s)
|
||||
sequence.location = std::string ( seq->GetText() );
|
||||
seq->QueryIntAttribute("min", &sequence.min);
|
||||
seq->QueryIntAttribute("max", &sequence.max);
|
||||
seq->QueryIntAttribute("loop", &sequence.loop);
|
||||
seq->QueryUnsignedAttribute("width", &sequence.width);
|
||||
seq->QueryUnsignedAttribute("height", &sequence.height);
|
||||
const char *codec = seq->Attribute("codec");
|
||||
if (codec)
|
||||
sequence.codec = std::string(codec);
|
||||
|
||||
uint fps = 0;
|
||||
seq->QueryUnsignedAttribute("fps", &fps);
|
||||
|
||||
@@ -915,7 +915,17 @@ void SessionLoader::visit (MultiFileSource& s)
|
||||
s.setFramerate( fps );
|
||||
}
|
||||
|
||||
int begin = -1;
|
||||
seq->QueryIntAttribute("begin", &begin);
|
||||
int end = INT_MAX;
|
||||
seq->QueryIntAttribute("end", &end);
|
||||
if ( begin != s.begin() || end != s.end() )
|
||||
s.setRange(begin, end);
|
||||
|
||||
bool loop = true;
|
||||
seq->QueryBoolAttribute("loop", &loop);
|
||||
if ( loop != s.loop() )
|
||||
s.setLoop(loop);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -599,10 +599,14 @@ void SessionVisitor::visit (MultiFileSource& s)
|
||||
xmlCurrent_->SetAttribute("type", "MultiFileSource");
|
||||
|
||||
XMLElement *sequence = xmlDoc_->NewElement("Sequence");
|
||||
// play properties
|
||||
sequence->SetAttribute("fps", s.framerate());
|
||||
sequence->SetAttribute("begin", s.begin());
|
||||
sequence->SetAttribute("end", s.end());
|
||||
sequence->SetAttribute("loop", s.loop());
|
||||
// file sequence description
|
||||
sequence->SetAttribute("min", s.sequence().min);
|
||||
sequence->SetAttribute("max", s.sequence().max);
|
||||
sequence->SetAttribute("loop", s.sequence().loop);
|
||||
sequence->SetAttribute("width", s.sequence().width);
|
||||
sequence->SetAttribute("height", s.sequence().height);
|
||||
sequence->SetAttribute("codec", s.sequence().codec.c_str());
|
||||
@@ -610,18 +614,6 @@ void SessionVisitor::visit (MultiFileSource& s)
|
||||
sequence->InsertEndChild( location );
|
||||
|
||||
xmlCurrent_->InsertEndChild(sequence);
|
||||
|
||||
// XMLElement *sequence = xmlDoc_->NewElement("Sequence");
|
||||
// sequence->SetAttribute("fps", s.fps());
|
||||
|
||||
// std::list<std::string> list = s.sequence ();
|
||||
// for (auto it = list.cbegin(); it != list.cend(); ++it) {
|
||||
// XMLElement *f = xmlDoc_->NewElement("file");
|
||||
// XMLText *filename = xmlDoc_->NewText( it->c_str() );
|
||||
// f->InsertEndChild( filename );
|
||||
// sequence->InsertEndChild(f);
|
||||
// }
|
||||
// xmlCurrent_->InsertEndChild(sequence);
|
||||
}
|
||||
|
||||
std::string SessionVisitor::getClipboard(const SourceList &list)
|
||||
|
||||
Reference in New Issue
Block a user