mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-05 15:30:00 +01:00
Add timeline flag management functionality
This commit is contained in:
Binary file not shown.
@@ -926,6 +926,18 @@ void SessionLoader::visit(MediaPlayer &n)
|
||||
fadingselement->QueryUnsignedAttribute("mode", &mode);
|
||||
n.setTimelineFadingMode((MediaPlayer::FadingMode) mode);
|
||||
}
|
||||
XMLElement *flagselement = timelineelement->FirstChildElement("Flags");
|
||||
if (flagselement) {
|
||||
XMLElement* flag = flagselement->FirstChildElement("Interval");
|
||||
for( ; flag ; flag = flag->NextSiblingElement())
|
||||
{
|
||||
uint64_t a = GST_CLOCK_TIME_NONE;
|
||||
uint64_t b = GST_CLOCK_TIME_NONE;
|
||||
flag->QueryUnsigned64Attribute("begin", &a);
|
||||
flag->QueryUnsigned64Attribute("end", &b);
|
||||
tl.addFlag( TimeInterval( (GstClockTime) a, (GstClockTime) b ) );
|
||||
}
|
||||
}
|
||||
n.setTimeline(tl);
|
||||
}
|
||||
|
||||
|
||||
@@ -469,6 +469,18 @@ void SessionVisitor::visit(MediaPlayer &n)
|
||||
XMLElement *array = XMLElementEncodeArray(xmlDoc_, n.timeline()->fadingArray(), MAX_TIMELINE_ARRAY * sizeof(float));
|
||||
fadingelement->InsertEndChild(array);
|
||||
timelineelement->InsertEndChild(fadingelement);
|
||||
|
||||
// flags in timeline
|
||||
XMLElement *flagselement = xmlDoc_->NewElement("Flags");
|
||||
TimeIntervalSet flags = n.timeline()->flags();
|
||||
for( auto it = flags.begin(); it!= flags.end(); ++it) {
|
||||
XMLElement *f = xmlDoc_->NewElement("Interval");
|
||||
f->SetAttribute("begin", (uint64_t) (*it).begin);
|
||||
f->SetAttribute("end", (uint64_t) (*it).end);
|
||||
flagselement->InsertEndChild(f);
|
||||
}
|
||||
timelineelement->InsertEndChild(flagselement);
|
||||
|
||||
newelement->InsertEndChild(timelineelement);
|
||||
fadingelement->SetAttribute("mode", (uint) n.timelineFadingMode());
|
||||
}
|
||||
|
||||
@@ -521,7 +521,7 @@ void Settings::Load(const std::string &filename)
|
||||
widgetsNode->QueryIntAttribute("inputs_view", &application.widget.inputs_view);
|
||||
widgetsNode->QueryBoolAttribute("media_player", &application.widget.media_player);
|
||||
widgetsNode->QueryIntAttribute("media_player_view", &application.widget.media_player_view);
|
||||
widgetsNode->QueryBoolAttribute("timeline_editmode", &application.widget.media_player_timeline_editmode);
|
||||
widgetsNode->QueryIntAttribute("timeline_editmode", &application.widget.media_player_timeline_editmode);
|
||||
widgetsNode->QueryFloatAttribute("media_player_slider", &application.widget.media_player_slider);
|
||||
widgetsNode->QueryBoolAttribute("shader_editor", &application.widget.shader_editor);
|
||||
widgetsNode->QueryIntAttribute("shader_editor_view", &application.widget.shader_editor_view);
|
||||
|
||||
@@ -23,7 +23,7 @@ struct WidgetsConfig
|
||||
int preview_view;
|
||||
bool media_player;
|
||||
int media_player_view;
|
||||
bool media_player_timeline_editmode;
|
||||
int media_player_timeline_editmode;
|
||||
float media_player_slider;
|
||||
bool timer;
|
||||
int timer_view;
|
||||
@@ -46,7 +46,7 @@ struct WidgetsConfig
|
||||
preview_view = -1;
|
||||
media_player = false;
|
||||
media_player_view = -1;
|
||||
media_player_timeline_editmode = false;
|
||||
media_player_timeline_editmode = 0;
|
||||
media_player_slider = 0.f;
|
||||
toolbox = false;
|
||||
help = false;
|
||||
|
||||
@@ -57,7 +57,9 @@ typedef struct payload
|
||||
FADE_OUT_IN,
|
||||
CUT,
|
||||
CUT_MERGE,
|
||||
CUT_ERASE
|
||||
CUT_ERASE,
|
||||
FLAG_ADD,
|
||||
FLAG_REMOVE
|
||||
};
|
||||
Action action;
|
||||
guint64 drop_time;
|
||||
@@ -464,6 +466,7 @@ void SourceControlWindow::Render()
|
||||
mediaplayer_timeline_zoom_ = 1.f;
|
||||
mediaplayer_active_->timeline()->clearFading();
|
||||
mediaplayer_active_->timeline()->clearGaps();
|
||||
mediaplayer_active_->timeline()->clearFlags();
|
||||
mediaplayer_active_->setVideoEffect("");
|
||||
std::ostringstream oss;
|
||||
oss << SystemToolkit::base_filename( mediaplayer_active_->filename() );
|
||||
@@ -566,7 +569,7 @@ void DrawTimeScale(const char* label, guint64 duration, double width_ratio)
|
||||
|
||||
bool EditTimeline(const char *label,
|
||||
Timeline *tl,
|
||||
bool edit_histogram,
|
||||
int edit_mode,
|
||||
bool *released,
|
||||
const ImVec2 size)
|
||||
{
|
||||
@@ -575,11 +578,13 @@ bool EditTimeline(const char *label,
|
||||
const guint64 begin = tl->begin();
|
||||
const guint64 end = tl->end();
|
||||
|
||||
bool cursor_dot = !edit_histogram;
|
||||
bool cursor_dot = edit_mode == 1;
|
||||
bool cursor_flag = false;
|
||||
Timeline _tl;
|
||||
bool array_changed = false;
|
||||
float *lines_array = tl->fadingArray();
|
||||
float *histogram_array = tl->gapsArray();
|
||||
float *gaps_array = tl->gapsArray();
|
||||
float *flags_array = tl->flagsArray();
|
||||
|
||||
// get window
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
@@ -629,6 +634,7 @@ bool EditTimeline(const char *label,
|
||||
size_t index = CLAMP( (int) floor(static_cast<double>(MAX_TIMELINE_ARRAY) * x), 0, MAX_TIMELINE_ARRAY);
|
||||
char cursor_text[64];
|
||||
guint64 time = begin + (index * end) / static_cast<guint64>(MAX_TIMELINE_ARRAY);
|
||||
static guint64 removed_flag_time = 0;
|
||||
|
||||
// enter edit if widget is active
|
||||
if (ImGui::GetActiveID() == id) {
|
||||
@@ -649,31 +655,55 @@ bool EditTimeline(const char *label,
|
||||
const size_t left = MIN(previous_index, index);
|
||||
const size_t right = MAX(previous_index, index);
|
||||
|
||||
if (edit_histogram){
|
||||
if (edit_mode == 0) {
|
||||
static float target_value = values_min;
|
||||
|
||||
// toggle value histo
|
||||
if (!active) {
|
||||
target_value = histogram_array[index] > 0.f ? 0.f : 1.f;
|
||||
target_value = gaps_array[index] > 0.f ? 0.f : 1.f;
|
||||
active = true;
|
||||
}
|
||||
|
||||
for (size_t i = left; i < right; ++i)
|
||||
histogram_array[i] = target_value;
|
||||
gaps_array[i] = target_value;
|
||||
}
|
||||
else {
|
||||
else if (edit_mode == 1) {
|
||||
const float target_value = values_max - val;
|
||||
|
||||
for (size_t i = left; i < right; ++i)
|
||||
lines_array[i] = target_value;
|
||||
|
||||
}
|
||||
else if (edit_mode == 2) {
|
||||
if (!active) {
|
||||
// remove flag on mouse press
|
||||
if ( tl->isFlagged(time) ) {
|
||||
removed_flag_time = time;
|
||||
tl->removeFlagAt(time);
|
||||
}
|
||||
// add flag on mouse release
|
||||
else
|
||||
active = true;
|
||||
}
|
||||
else if (! tl->isFlagged(time) ) {
|
||||
cursor_flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
previous_index = index;
|
||||
array_changed = true;
|
||||
}
|
||||
// release active widget on mouse release
|
||||
else {
|
||||
// add flag on mouse release
|
||||
if (edit_mode == 2 && active) {
|
||||
// exception: if flag was removed at same time, do not add it back
|
||||
if ( removed_flag_time != time ) {
|
||||
tl->addFlag(time);
|
||||
}
|
||||
removed_flag_time = 0;
|
||||
}
|
||||
|
||||
active = false;
|
||||
ImGui::ClearActiveID();
|
||||
previous_index = UINT32_MAX;
|
||||
@@ -699,17 +729,17 @@ bool EditTimeline(const char *label,
|
||||
case TimelinePayload::CUT:
|
||||
_tl = *tl;
|
||||
_tl.cut(time, (bool) pl->argument);
|
||||
histogram_array = _tl.gapsArray();
|
||||
gaps_array = _tl.gapsArray();
|
||||
break;
|
||||
case TimelinePayload::CUT_MERGE:
|
||||
_tl = *tl;
|
||||
_tl.mergeGapstAt(time);
|
||||
histogram_array = _tl.gapsArray();
|
||||
gaps_array = _tl.gapsArray();
|
||||
break;
|
||||
case TimelinePayload::CUT_ERASE:
|
||||
_tl = *tl;
|
||||
_tl.removeGaptAt(time);
|
||||
histogram_array = _tl.gapsArray();
|
||||
gaps_array = _tl.gapsArray();
|
||||
break;
|
||||
case TimelinePayload::FADE_IN:
|
||||
_tl = *tl;
|
||||
@@ -731,6 +761,16 @@ bool EditTimeline(const char *label,
|
||||
_tl.fadeInOutRange(time, pl->timing, false, (Timeline::FadingCurve) pl->argument);
|
||||
lines_array = _tl.fadingArray();
|
||||
break;
|
||||
case TimelinePayload::FLAG_ADD:
|
||||
_tl = *tl;
|
||||
_tl.addFlag(time);
|
||||
flags_array = _tl.flagsArray();
|
||||
break;
|
||||
case TimelinePayload::FLAG_REMOVE:
|
||||
_tl = *tl;
|
||||
_tl.removeFlagAt(time);
|
||||
flags_array = _tl.flagsArray();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -745,16 +785,21 @@ bool EditTimeline(const char *label,
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
else {
|
||||
if ( edit_mode == 2 && tl->isFlagged(time) ) {
|
||||
cursor_flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
// back to draw
|
||||
ImGui::SetCursorScreenPos(canvas_pos);
|
||||
|
||||
// plot histogram (with frame)
|
||||
// plot gaps (with frame)
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, bg_color);
|
||||
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, style.Colors[ImGuiCol_ModalWindowDimBg]); // a dark color
|
||||
char buf[128];
|
||||
snprintf(buf, 128, "##Histo%s", label);
|
||||
ImGui::PlotHistogram(buf, histogram_array, MAX_TIMELINE_ARRAY, 0, NULL, values_min, values_max, size);
|
||||
ImGui::PlotHistogram(buf, gaps_array, MAX_TIMELINE_ARRAY, 0, NULL, values_min, values_max, size);
|
||||
ImGui::PopStyleColor(2);
|
||||
|
||||
// back to draw
|
||||
@@ -766,6 +811,15 @@ bool EditTimeline(const char *label,
|
||||
ImGui::PlotLines(buf, lines_array, MAX_TIMELINE_ARRAY, 0, NULL, values_min, values_max, size);
|
||||
ImGui::PopStyleColor(1);
|
||||
|
||||
// back to draw
|
||||
ImGui::SetCursorScreenPos(canvas_pos);
|
||||
|
||||
// plot flags (transparent background)
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0,0,0,0));
|
||||
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, style.Colors[ImGuiCol_TabActive]); // cursor color
|
||||
snprintf(buf, 128, "##Flags%s", label);
|
||||
ImGui::PlotHistogram(buf, flags_array, MAX_TIMELINE_ARRAY, 0, NULL, values_min, values_max, size);
|
||||
ImGui::PopStyleColor(2);
|
||||
|
||||
// draw the cursor
|
||||
if (hovered) {
|
||||
@@ -785,6 +839,11 @@ bool EditTimeline(const char *label,
|
||||
cursor_pos = cursor_pos + mouse_pos_in_canvas;
|
||||
window->DrawList->AddCircleFilled( cursor_pos, 3.f, cur_color, 8);
|
||||
}
|
||||
else if (cursor_flag) {
|
||||
cursor_pos = cursor_pos + ImVec2(mouse_pos_in_canvas.x, 12.f);
|
||||
window->DrawList->AddLine( cursor_pos, cursor_pos + ImVec2(0.f, size.y - 8.f), cur_color);
|
||||
_drawIcon(cursor_pos - ImVec2(2.f, 1.f), 12, 6, true, window);
|
||||
}
|
||||
else {
|
||||
cursor_pos = cursor_pos + ImVec2(mouse_pos_in_canvas.x, 4.f);
|
||||
window->DrawList->AddLine( cursor_pos, cursor_pos + ImVec2(0.f, size.y - 8.f), cur_color);
|
||||
@@ -1850,6 +1909,8 @@ void DragButtonIcon(int i, int j, const char *tooltip, TimelinePayload payload)
|
||||
void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
||||
{
|
||||
static bool show_overlay_info = false;
|
||||
static std::vector< std::pair<int,int> > editmode_icon = { {8, 3}, {7, 4}, {12, 6} };
|
||||
static std::vector< std::string > editmode_tooltip = { "Cutting tool", "Fading tool", "Flag tool" };
|
||||
|
||||
mediaplayer_active_ = ms->mediaplayer();
|
||||
|
||||
@@ -1999,10 +2060,12 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
||||
else if (released)
|
||||
{
|
||||
tl->refresh();
|
||||
if (Settings::application.widget.media_player_timeline_editmode)
|
||||
if (Settings::application.widget.media_player_timeline_editmode == 0)
|
||||
oss << ": Timeline cut";
|
||||
else
|
||||
else if (Settings::application.widget.media_player_timeline_editmode == 1)
|
||||
oss << ": Timeline fading";
|
||||
else
|
||||
oss << ": Timeline flags";
|
||||
Action::manager().store(oss.str());
|
||||
}
|
||||
// custom timeline slider
|
||||
@@ -2022,8 +2085,8 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
||||
if (mediaplayer_edit_panel_ && ImGuiToolkit::IconButton(10, 0, "Close panel"))
|
||||
mediaplayer_edit_panel_ = false;
|
||||
ImGui::SetCursorScreenPos(bottom + ImVec2(1.f, 0.5f * timeline_height_));
|
||||
const char *tooltip[2] = {"Fading tool", "Cutting tool"};
|
||||
ImGuiToolkit::IconToggle(7,4,8,3, &Settings::application.widget.media_player_timeline_editmode, tooltip);
|
||||
// select timeline editmode; cut, fade, flag
|
||||
ImGuiToolkit::IconMultistate(editmode_icon, &Settings::application.widget.media_player_timeline_editmode, editmode_tooltip );
|
||||
|
||||
// zoom slider
|
||||
ImGui::SetCursorScreenPos(bottom + ImVec2(0.f, timeline_height_));
|
||||
@@ -2220,7 +2283,7 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
||||
/// PANEL FOR CUT TIMELINE MODE
|
||||
///
|
||||
ImGui::Spacing();
|
||||
if (Settings::application.widget.media_player_timeline_editmode) {
|
||||
if (Settings::application.widget.media_player_timeline_editmode == 0) {
|
||||
|
||||
// PANEL WITH LARGE FONTS
|
||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE);
|
||||
@@ -2308,9 +2371,9 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
||||
ImGui::PopFont();
|
||||
}
|
||||
///
|
||||
/// FADING
|
||||
/// PANEL FOR FADING
|
||||
///
|
||||
else {
|
||||
else if (Settings::application.widget.media_player_timeline_editmode == 1) {
|
||||
// Icons for Drag & Drop
|
||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE);
|
||||
|
||||
@@ -2398,6 +2461,9 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
||||
DragButtonIcon(17, 10, "Drop in timeline to insert\nSmooth fade in & out",
|
||||
TimelinePayload(TimelinePayload::FADE_IN_OUT, d*GST_MSECOND, Timeline::FADING_SMOOTH));
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
///
|
||||
/// DURATION SLIDER
|
||||
@@ -2467,6 +2533,28 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
||||
// end icons
|
||||
ImGui::PopFont();
|
||||
}
|
||||
///
|
||||
/// PANEL FOR FLAGS
|
||||
///
|
||||
else if (Settings::application.widget.media_player_timeline_editmode == 2) {
|
||||
|
||||
// PANEL WITH LARGE FONTS
|
||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE);
|
||||
|
||||
///
|
||||
/// CUT LEFT OF CURSOR
|
||||
///
|
||||
DragButtonIcon(12, 6, "Drop in timeline to\nAdd flag",
|
||||
TimelinePayload(TimelinePayload::FLAG_ADD, 0, 1) );
|
||||
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
|
||||
DragButtonIcon(6, 0, "Drop in timeline to\nDelete flag",
|
||||
TimelinePayload(TimelinePayload::FLAG_REMOVE, 0, 1) );
|
||||
|
||||
// end icons
|
||||
ImGui::PopFont();
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
114
src/Timeline.cpp
114
src/Timeline.cpp
@@ -86,6 +86,9 @@ Timeline& Timeline::operator = (const Timeline& b)
|
||||
memcpy( this->gapsArray_, b.gapsArray_, MAX_TIMELINE_ARRAY * sizeof(float));
|
||||
memcpy( this->fadingArray_, b.fadingArray_, MAX_TIMELINE_ARRAY * sizeof(float));
|
||||
this->fading_array_changed_ = true;
|
||||
this->flags_ = b.flags_;
|
||||
this->flags_array_need_update_ = b.flags_array_need_update_;
|
||||
memcpy( this->flagsArray_, b.flagsArray_, MAX_TIMELINE_ARRAY * sizeof(float));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -100,6 +103,7 @@ void Timeline::reset()
|
||||
|
||||
clearGaps();
|
||||
clearFading();
|
||||
clearFlags();
|
||||
}
|
||||
|
||||
bool Timeline::is_valid() const
|
||||
@@ -175,6 +179,7 @@ void Timeline::update()
|
||||
void Timeline::refresh()
|
||||
{
|
||||
fillArrayFromGaps(gapsArray_, MAX_TIMELINE_ARRAY);
|
||||
fillArrayFromFlags(flagsArray_, MAX_TIMELINE_ARRAY);
|
||||
}
|
||||
|
||||
bool Timeline::gapAt(const GstClockTime t) const
|
||||
@@ -511,8 +516,7 @@ void Timeline::clearGaps()
|
||||
{
|
||||
gaps_.clear();
|
||||
|
||||
for(int i=0;i<MAX_TIMELINE_ARRAY;++i)
|
||||
gapsArray_[i] = 0.f;
|
||||
memcpy(gapsArray_, empty_zeros, MAX_TIMELINE_ARRAY * sizeof(float));
|
||||
|
||||
gaps_array_need_update_ = true;
|
||||
}
|
||||
@@ -942,3 +946,109 @@ void Timeline::fillArrayFromGaps(float *array, size_t array_size)
|
||||
// array[i] = gapAt(t, gap) ? 1.f : 0.f;
|
||||
// }
|
||||
}
|
||||
|
||||
#define FLAG_MARGIN 100
|
||||
|
||||
float *Timeline::flagsArray()
|
||||
{
|
||||
if (flags_array_need_update_) {
|
||||
fillArrayFromFlags(flagsArray_, MAX_TIMELINE_ARRAY);
|
||||
}
|
||||
return flagsArray_;
|
||||
}
|
||||
|
||||
bool Timeline::addFlag(GstClockTime t)
|
||||
{
|
||||
if (t > timing_.begin + (step_ * 2)
|
||||
&& t < timing_.end - (step_ * 2)
|
||||
&& !isFlagged(t)) {
|
||||
|
||||
// compute nearest frame time
|
||||
GstClockTime t_frame = ( (t - timing_.begin) / step_ ) * step_ + timing_.begin + step_;
|
||||
|
||||
// Flag interval centered on t_frame
|
||||
TimeInterval f(t_frame - step_ - FLAG_MARGIN, t_frame + step_ + FLAG_MARGIN);
|
||||
|
||||
flags_array_need_update_ = true;
|
||||
return flags_.insert(f).second;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Timeline::addFlag(TimeInterval s)
|
||||
{
|
||||
if ( s.is_valid() ) {
|
||||
flags_array_need_update_ = true;
|
||||
return flags_.insert(s).second;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Timeline::removeFlagAt(GstClockTime t)
|
||||
{
|
||||
if (flags_.empty())
|
||||
return false;
|
||||
|
||||
TimeIntervalSet::const_iterator f = std::find_if(flags_.begin(), flags_.end(), includesTime(t));
|
||||
|
||||
if ( f != flags_.end() ) {
|
||||
flags_.erase(f);
|
||||
flags_array_need_update_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Timeline::isFlagged(GstClockTime t) const
|
||||
{
|
||||
TimeIntervalSet::const_iterator f = std::find_if(flags_.begin(), flags_.end(), includesTime(t));
|
||||
return ( f != flags_.end() );
|
||||
}
|
||||
|
||||
|
||||
GstClockTime Timeline::getFlagAt(GstClockTime t) const
|
||||
{
|
||||
TimeIntervalSet::const_iterator f = std::find_if(flags_.begin(), flags_.end(), includesTime(t));
|
||||
|
||||
if ( f != flags_.end() ) {
|
||||
return ( (*f).begin + step_ + FLAG_MARGIN);
|
||||
}
|
||||
|
||||
return GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
|
||||
void Timeline::clearFlags()
|
||||
{
|
||||
flags_.clear();
|
||||
memcpy(flagsArray_, empty_zeros, MAX_TIMELINE_ARRAY * sizeof(float));
|
||||
|
||||
flags_array_need_update_ = true;
|
||||
}
|
||||
|
||||
void Timeline::fillArrayFromFlags(float *array, size_t array_size)
|
||||
{
|
||||
// fill the array from flags list
|
||||
if (array != nullptr && array_size > 0 && timing_.is_valid()) {
|
||||
|
||||
// clear with static array
|
||||
memcpy(flagsArray_, empty_zeros, MAX_TIMELINE_ARRAY * sizeof(float));
|
||||
|
||||
// for each flag
|
||||
GstClockTime d = timing_.duration();
|
||||
for (auto it = flags_.begin(); it != flags_.end(); ++it)
|
||||
{
|
||||
size_t e = ( ( (*it).begin + step_ + FLAG_MARGIN ) * array_size ) / d ;
|
||||
|
||||
// fill with 1 where there is a flag
|
||||
flagsArray_[e-1] = 1.f;
|
||||
flagsArray_[ e ] = 1.f;
|
||||
flagsArray_[e+1] = 1.f;
|
||||
}
|
||||
|
||||
// done !
|
||||
flags_array_need_update_ = false;
|
||||
}
|
||||
}
|
||||
@@ -137,6 +137,17 @@ public:
|
||||
bool gapAt(const GstClockTime t) const;
|
||||
bool getGapAt(const GstClockTime t, TimeInterval &gap) const;
|
||||
|
||||
// Manipulation of flags
|
||||
inline TimeIntervalSet flags() const { return flags_; };
|
||||
inline size_t numFlags() const { return flags_.size(); };
|
||||
float *flagsArray();
|
||||
bool addFlag(GstClockTime t);
|
||||
bool addFlag(TimeInterval s);
|
||||
bool removeFlagAt(GstClockTime t);
|
||||
bool isFlagged(GstClockTime t) const;
|
||||
GstClockTime getFlagAt(GstClockTime t) const;
|
||||
void clearFlags();
|
||||
|
||||
// inverse of gaps: sections of play areas
|
||||
TimeIntervalSet sections() const;
|
||||
GstClockTime sectionsDuration() const;
|
||||
@@ -190,6 +201,11 @@ private:
|
||||
float fadingArray_[MAX_TIMELINE_ARRAY];
|
||||
bool fading_array_changed_, fading_array_allones_;
|
||||
|
||||
TimeIntervalSet flags_;
|
||||
float flagsArray_[MAX_TIMELINE_ARRAY];
|
||||
bool flags_array_need_update_;
|
||||
// synchronize data structures
|
||||
void fillArrayFromFlags(float *array, size_t array_size);
|
||||
};
|
||||
|
||||
#endif // TIMELINE_H
|
||||
|
||||
Reference in New Issue
Block a user