Saving, undo and dynamic change of MultiFileSource

This commit is contained in:
Bruno
2021-05-06 23:44:15 +02:00
parent 250df8b651
commit d56700a9d5
5 changed files with 71 additions and 61 deletions

View File

@@ -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();
}

View File

@@ -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_);
}

View File

@@ -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_;
};

View File

@@ -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);
@@ -911,11 +911,21 @@ void SessionLoader::visit (MultiFileSource& s)
s.setSequence( sequence, fps);
}
// same sequence, different framerate
else if ( fps != s.framerate() ) {
else if ( fps != s.framerate() ) {
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);
}
}

View File

@@ -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)