From 39a76bd5c3b838fd6a9c3807bcd5a8def7a345aa Mon Sep 17 00:00:00 2001 From: Peter Eszlari Date: Tue, 8 Jan 2019 02:57:22 +0100 Subject: [PATCH 1/7] linux/appdata: 1600x900 screenshot --- packaging/linux/org.olivevideoeditor.Olive.appdata.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/linux/org.olivevideoeditor.Olive.appdata.xml b/packaging/linux/org.olivevideoeditor.Olive.appdata.xml index 703ce1de1..62fa50e1b 100644 --- a/packaging/linux/org.olivevideoeditor.Olive.appdata.xml +++ b/packaging/linux/org.olivevideoeditor.Olive.appdata.xml @@ -17,7 +17,7 @@ https://www.patreon.com/olivevideoeditor https://github.com/olive-editor/olive/issues - https://olivevideoeditor.org/img/screenshot.jpg + https://olivevideoeditor.org/img/screenshot.1600.jpg From 21af8fad0c62c081a70d5a08e1378f2096af44c8 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 8 Jan 2019 17:00:47 +1100 Subject: [PATCH 2/7] fixed #272 --- project/effect.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/project/effect.cpp b/project/effect.cpp index 3b5baef6a..74f901388 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -466,6 +466,7 @@ void Effect::copy_field_keyframes(Effect* e) { EffectField* field = row->field(j); EffectField* copy_field = copy_row->field(j); copy_field->keyframes = field->keyframes; + copy_field->set_current_data(field->get_current_data()); } } } From d43cb42f02f966fdaf2dfddda70153b133f7df5a Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 8 Jan 2019 17:13:07 +1100 Subject: [PATCH 3/7] fixed a linking issue and undo crash --- panels/timeline.cpp | 7 +++---- project/undo.cpp | 2 ++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/panels/timeline.cpp b/panels/timeline.cpp index 3ba55d0ef..a84211137 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -1391,14 +1391,13 @@ void Timeline::toggle_links() { for (int i=0;iclips.size();i++) { Clip* c = sequence->clips.at(i); if (c != NULL && is_clip_selected(c, true)) { - command->clips.append(i); + if (!command->clips.contains(i)) command->clips.append(i); + if (c->linked.size() > 0) { command->link = false; // prioritize unlinking for (int j=0;jlinked.size();j++) { // add links to the command - if (!command->clips.contains(c->linked.at(j))) { - command->clips.append(c->linked.at(j)); - } + if (!command->clips.contains(c->linked.at(j))) command->clips.append(c->linked.at(j)); } } } diff --git a/project/undo.cpp b/project/undo.cpp index a169d9d7f..be8932c47 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -489,6 +489,7 @@ AddClipCommand::~AddClipCommand() { } void AddClipCommand::undo() { + panel_effect_controls->clear_effects(true); for (int i=0;iclips.last(); panel_timeline->deselect_area(c->timeline_in, c->timeline_out, c->track); @@ -539,6 +540,7 @@ void LinkCommand::undo() { void LinkCommand::redo() { old_links.clear(); for (int i=0;iclips.at(clips.at(i)); if (link) { for (int j=0;j Date: Tue, 8 Jan 2019 22:36:18 +1100 Subject: [PATCH 4/7] added autoscrolling when seeking the timeline --- panels/timeline.cpp | 13 +++++++++++++ panels/timeline.h | 2 ++ panels/viewer.cpp | 1 + 3 files changed, 16 insertions(+) diff --git a/panels/timeline.cpp b/panels/timeline.cpp index a84211137..d1ab37705 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -475,6 +475,19 @@ void Timeline::select_all() { } } +void Timeline::scroll_to_frame(long frame) { + if (sequence != NULL) { + int screen_point = getTimelineScreenPointFromFrame(frame); + int min_x = timeline_area->width()*0.1; + int max_x = timeline_area->width()*0.9; + if (screen_point < min_x) { + horizontalScrollBar->setValue(getScreenPointFromFrame(zoom, frame) - min_x); + } else if (screen_point > max_x) { + horizontalScrollBar->setValue(getScreenPointFromFrame(zoom, frame) - max_x); + } + } +} + void Timeline::resizeEvent(QResizeEvent *event) { if (sequence != NULL) set_sb_max(); } diff --git a/panels/timeline.h b/panels/timeline.h index 278aacbb3..7714df242 100644 --- a/panels/timeline.h +++ b/panels/timeline.h @@ -203,6 +203,8 @@ public: QPushButton* toolTransitionButton; QPushButton* snappingButton; + void scroll_to_frame(long frame); + void resizeEvent(QResizeEvent *event); public slots: void repaint_timeline(); diff --git a/panels/viewer.cpp b/panels/viewer.cpp index 397364e13..8ee03decf 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -237,6 +237,7 @@ bool frame_rate_is_droppable(float rate) { void Viewer::seek(long p) { pause(); seq->playhead = p; + if (main_sequence) panel_timeline->scroll_to_frame(p); update_parents(); reset_all_audio(); audio_scrub = true; From d3b02f3f53d7b34698705ca9a4b7d8e9724f1cc9 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 8 Jan 2019 22:47:02 +1100 Subject: [PATCH 5/7] added autoscrolling to keyframe view seek --- panels/effectcontrols.cpp | 4 + panels/effectcontrols.h | 1 + panels/panels.cpp | 175 ++++++++++++++++++++------------------ panels/panels.h | 2 + panels/timeline.cpp | 11 +-- panels/viewer.cpp | 6 +- 6 files changed, 107 insertions(+), 92 deletions(-) diff --git a/panels/effectcontrols.cpp b/panels/effectcontrols.cpp index de1726900..fc64d0083 100644 --- a/panels/effectcontrols.cpp +++ b/panels/effectcontrols.cpp @@ -145,6 +145,10 @@ void EffectControls::copy(bool del) { } } +void EffectControls::scroll_to_frame(long frame) { + scroll_to_frame_internal(horizontalScrollBar, frame, zoom, keyframeView->width()); +} + void EffectControls::show_effect_menu(int type, int subtype) { effect_menu_type = type; effect_menu_subtype = subtype; diff --git a/panels/effectcontrols.h b/panels/effectcontrols.h index 564b4f0a8..afb9a7e26 100644 --- a/panels/effectcontrols.h +++ b/panels/effectcontrols.h @@ -42,6 +42,7 @@ public: void delete_selected_keyframes(); void copy(bool del); bool multiple; + void scroll_to_frame(long frame); QVector selected_clips; diff --git a/panels/panels.cpp b/panels/panels.cpp index 35bed658a..e1f57e94d 100644 --- a/panels/panels.cpp +++ b/panels/panels.cpp @@ -11,6 +11,8 @@ #include "grapheditor.h" #include "debug.h" +#include + Project* panel_project = 0; EffectControls* panel_effect_controls = 0; Viewer* panel_sequence_viewer = 0; @@ -27,43 +29,43 @@ void update_effect_controls() { int vclip = -1; int aclip = -1; QVector selected_clips; - int mode = TA_NO_TRANSITION; + int mode = TA_NO_TRANSITION; if (sequence != NULL) { for (int i=0;iclips.size();i++) { Clip* clip = sequence->clips.at(i); - if (clip != NULL) { - for (int j=0;jselections.size();j++) { - const Selection& s = sequence->selections.at(j); - bool add = true; - if (clip->timeline_in >= s.in && clip->timeline_out <= s.out && clip->track == s.track) { - mode = TA_NO_TRANSITION; - } else if (selection_contains_transition(s, clip, TA_OPENING_TRANSITION)) { - mode = TA_OPENING_TRANSITION; - } else if (selection_contains_transition(s, clip, TA_CLOSING_TRANSITION)) { - mode = TA_CLOSING_TRANSITION; - } else { - add = false; - } + if (clip != NULL) { + for (int j=0;jselections.size();j++) { + const Selection& s = sequence->selections.at(j); + bool add = true; + if (clip->timeline_in >= s.in && clip->timeline_out <= s.out && clip->track == s.track) { + mode = TA_NO_TRANSITION; + } else if (selection_contains_transition(s, clip, TA_OPENING_TRANSITION)) { + mode = TA_OPENING_TRANSITION; + } else if (selection_contains_transition(s, clip, TA_CLOSING_TRANSITION)) { + mode = TA_CLOSING_TRANSITION; + } else { + add = false; + } - if (add) { - if (clip->track < 0 && vclip == -1) { - vclip = i; - } else if (clip->track >= 0 && aclip == -1) { - aclip = i; - } else { - vclip = -2; - aclip = -2; + if (add) { + if (clip->track < 0 && vclip == -1) { + vclip = i; + } else if (clip->track >= 0 && aclip == -1) { + aclip = i; + } else { + vclip = -2; + aclip = -2; multiple = true; multiple = true; - break; - } - } - } + break; + } + } + } } } if (!multiple) { - // check if aclip is linked to vclip + // check if aclip is linked to vclip if (vclip >= 0) selected_clips.append(vclip); if (aclip >= 0) selected_clips.append(aclip); if (vclip >= 0 && aclip >= 0) { @@ -84,7 +86,7 @@ void update_effect_controls() { } } - bool same = (selected_clips.size() == panel_effect_controls->selected_clips.size()); + bool same = (selected_clips.size() == panel_effect_controls->selected_clips.size()); if (same) { for (int i=0;iselected_clips.at(i)) { @@ -101,9 +103,9 @@ void update_effect_controls() { } void update_ui(bool modified) { - if (modified) { - update_effect_controls(); - } + if (modified) { + update_effect_controls(); + } panel_effect_controls->update_keyframes(); panel_timeline->repaint_timeline(); panel_sequence_viewer->update_viewer(); @@ -111,61 +113,72 @@ void update_ui(bool modified) { } QDockWidget *get_focused_panel() { - QDockWidget* w = NULL; - if (config.hover_focus) { - if (panel_project->underMouse()) { - w = panel_project; - } else if (panel_effect_controls->underMouse()) { - w = panel_effect_controls; - } else if (panel_sequence_viewer->underMouse()) { - w = panel_sequence_viewer; - } else if (panel_footage_viewer->underMouse()) { - w = panel_footage_viewer; - } else if (panel_timeline->underMouse()) { - w = panel_timeline; - } - } - if (w == NULL) { - if (panel_project->is_focused()) { - w = panel_project; + QDockWidget* w = NULL; + if (config.hover_focus) { + if (panel_project->underMouse()) { + w = panel_project; + } else if (panel_effect_controls->underMouse()) { + w = panel_effect_controls; + } else if (panel_sequence_viewer->underMouse()) { + w = panel_sequence_viewer; + } else if (panel_footage_viewer->underMouse()) { + w = panel_footage_viewer; + } else if (panel_timeline->underMouse()) { + w = panel_timeline; + } + } + if (w == NULL) { + if (panel_project->is_focused()) { + w = panel_project; } else if (panel_effect_controls->keyframe_focus() || panel_effect_controls->is_focused()) { - w = panel_effect_controls; - } else if (panel_sequence_viewer->is_focused()) { - w = panel_sequence_viewer; - } else if (panel_footage_viewer->is_focused()) { - w = panel_footage_viewer; - } else if (panel_timeline->focused()) { - w = panel_timeline; - } - } - return w; + w = panel_effect_controls; + } else if (panel_sequence_viewer->is_focused()) { + w = panel_sequence_viewer; + } else if (panel_footage_viewer->is_focused()) { + w = panel_footage_viewer; + } else if (panel_timeline->focused()) { + w = panel_timeline; + } + } + return w; } void alloc_panels(QWidget* parent) { - // TODO maybe replace these with non-pointers later on? - panel_sequence_viewer = new Viewer(parent); - panel_sequence_viewer->setObjectName("seq_viewer"); - panel_footage_viewer = new Viewer(parent); - panel_footage_viewer->setObjectName("footage_viewer"); - panel_project = new Project(parent); - panel_project->setObjectName("proj_root"); - panel_effect_controls = new EffectControls(parent); - panel_effect_controls->setObjectName("fx_controls"); - panel_timeline = new Timeline(parent); - panel_timeline->setObjectName("timeline"); - panel_graph_editor = new GraphEditor(parent); - panel_graph_editor->setObjectName("graph_editor"); + // TODO maybe replace these with non-pointers later on? + panel_sequence_viewer = new Viewer(parent); + panel_sequence_viewer->setObjectName("seq_viewer"); + panel_footage_viewer = new Viewer(parent); + panel_footage_viewer->setObjectName("footage_viewer"); + panel_project = new Project(parent); + panel_project->setObjectName("proj_root"); + panel_effect_controls = new EffectControls(parent); + panel_effect_controls->setObjectName("fx_controls"); + panel_timeline = new Timeline(parent); + panel_timeline->setObjectName("timeline"); + panel_graph_editor = new GraphEditor(parent); + panel_graph_editor->setObjectName("graph_editor"); } void free_panels() { - delete panel_sequence_viewer; - panel_sequence_viewer = NULL; - delete panel_footage_viewer; - panel_footage_viewer = NULL; - delete panel_project; - panel_project = NULL; - delete panel_effect_controls; - panel_effect_controls = NULL; - delete panel_timeline; - panel_timeline = NULL; + delete panel_sequence_viewer; + panel_sequence_viewer = NULL; + delete panel_footage_viewer; + panel_footage_viewer = NULL; + delete panel_project; + panel_project = NULL; + delete panel_effect_controls; + panel_effect_controls = NULL; + delete panel_timeline; + panel_timeline = NULL; +} + +void scroll_to_frame_internal(QScrollBar* bar, long frame, double zoom, int area_width) { + int screen_point = getScreenPointFromFrame(zoom, frame) - bar->value(); + int min_x = area_width*0.1; + int max_x = area_width-min_x; + if (screen_point < min_x) { + bar->setValue(getScreenPointFromFrame(zoom, frame) - min_x); + } else if (screen_point > max_x) { + bar->setValue(getScreenPointFromFrame(zoom, frame) - max_x); + } } diff --git a/panels/panels.h b/panels/panels.h index 691736b82..2434d1daa 100644 --- a/panels/panels.h +++ b/panels/panels.h @@ -9,6 +9,7 @@ class GraphEditor; class QWidget; class QDockWidget; +class QScrollBar; extern Project* panel_project; extern EffectControls* panel_effect_controls; @@ -21,5 +22,6 @@ void update_ui(bool modified); QDockWidget* get_focused_panel(); void alloc_panels(QWidget *parent); void free_panels(); +void scroll_to_frame_internal(QScrollBar* bar, long frame, double zoom, int area_width); #endif // PANELS_H diff --git a/panels/timeline.cpp b/panels/timeline.cpp index d1ab37705..b450f7e61 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -476,16 +476,7 @@ void Timeline::select_all() { } void Timeline::scroll_to_frame(long frame) { - if (sequence != NULL) { - int screen_point = getTimelineScreenPointFromFrame(frame); - int min_x = timeline_area->width()*0.1; - int max_x = timeline_area->width()*0.9; - if (screen_point < min_x) { - horizontalScrollBar->setValue(getScreenPointFromFrame(zoom, frame) - min_x); - } else if (screen_point > max_x) { - horizontalScrollBar->setValue(getScreenPointFromFrame(zoom, frame) - max_x); - } - } + scroll_to_frame_internal(horizontalScrollBar, frame, zoom, timeline_area->width()); } void Timeline::resizeEvent(QResizeEvent *event) { diff --git a/panels/viewer.cpp b/panels/viewer.cpp index 8ee03decf..af1522dc7 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -3,6 +3,7 @@ #include "playback/audio.h" #include "timeline.h" #include "panels/project.h" +#include "panels/effectcontrols.h" #include "project/sequence.h" #include "project/clip.h" #include "panels/panels.h" @@ -237,7 +238,10 @@ bool frame_rate_is_droppable(float rate) { void Viewer::seek(long p) { pause(); seq->playhead = p; - if (main_sequence) panel_timeline->scroll_to_frame(p); + if (main_sequence) { + panel_timeline->scroll_to_frame(p); + panel_effect_controls->scroll_to_frame(p); + } update_parents(); reset_all_audio(); audio_scrub = true; From 607d36115a86265f8bf934250a79aeaa0795733c Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Wed, 9 Jan 2019 00:13:39 +1100 Subject: [PATCH 6/7] fixed #274 --- ui/keyframeview.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/keyframeview.cpp b/ui/keyframeview.cpp index 4a53bd118..812e34878 100644 --- a/ui/keyframeview.cpp +++ b/ui/keyframeview.cpp @@ -199,7 +199,9 @@ void KeyframeView::set_y_scroll(int s) { } void KeyframeView::resize_move(double d) { - header->update_zoom(header->get_zoom()*d); + panel_effect_controls->zoom *= d; + header->update_zoom(panel_effect_controls->zoom); + update(); } void KeyframeView::mousePressEvent(QMouseEvent *event) { From 6b1bb620c1549dea825b7875363e607207653c50 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Wed, 9 Jan 2019 10:05:43 +1100 Subject: [PATCH 7/7] added fill left/right effect --- effects/internal/fillleftrighteffect.cpp | 24 ++++++++++++++++++ effects/internal/fillleftrighteffect.h | 14 +++++++++++ effects/internal/volumeeffect.cpp | 31 +++++++++++++++++------- olive.pro | 6 +++-- project/effect.cpp | 8 +++++- project/effect.h | 2 +- 6 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 effects/internal/fillleftrighteffect.cpp create mode 100644 effects/internal/fillleftrighteffect.h diff --git a/effects/internal/fillleftrighteffect.cpp b/effects/internal/fillleftrighteffect.cpp new file mode 100644 index 000000000..d21765e60 --- /dev/null +++ b/effects/internal/fillleftrighteffect.cpp @@ -0,0 +1,24 @@ +#include "fillleftrighteffect.h" + +#define FILL_TYPE_LEFT 0 +#define FILL_TYPE_RIGHT 1 + +FillLeftRightEffect::FillLeftRightEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { + EffectRow* type_row = add_row("Type"); + fill_type = type_row->add_field(EFFECT_FIELD_COMBO, "type"); + fill_type->add_combo_item("Fill Left with Right", FILL_TYPE_LEFT); + fill_type->add_combo_item("Fill Right with Left", FILL_TYPE_RIGHT); +} + +void FillLeftRightEffect::process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int) { + double interval = (timecode_end-timecode_start)/nb_bytes; + for (int i=0;iget_combo_data(timecode_start+(interval*i)) == FILL_TYPE_LEFT) { + samples[i+1] = samples[i+3]; + samples[i] = samples[i+2]; + } else { + samples[i+3] = samples[i+1]; + samples[i+2] = samples[i]; + } + } +} diff --git a/effects/internal/fillleftrighteffect.h b/effects/internal/fillleftrighteffect.h new file mode 100644 index 000000000..3b3390d2e --- /dev/null +++ b/effects/internal/fillleftrighteffect.h @@ -0,0 +1,14 @@ +#ifndef FILLLEFTRIGHTEFFECT_H +#define FILLLEFTRIGHTEFFECT_H + +#include "project/effect.h" + +class FillLeftRightEffect : public Effect { +public: + FillLeftRightEffect(Clip* c, const EffectMeta* em); + void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); +private: + EffectField* fill_type; +}; + +#endif // FILLLEFTRIGHTEFFECT_H diff --git a/effects/internal/volumeeffect.cpp b/effects/internal/volumeeffect.cpp index b7b18017b..48a329c16 100644 --- a/effects/internal/volumeeffect.cpp +++ b/effects/internal/volumeeffect.cpp @@ -19,17 +19,30 @@ VolumeEffect::VolumeEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { void VolumeEffect::process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int) { double interval = (timecode_end-timecode_start)/nb_bytes; - for (int i=0;iget_double_value(timecode_start+(interval*i), true)*0.01); - qint32 samp = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF)); - samp *= vol_val; - if (samp > INT16_MAX) { - samp = INT16_MAX; - } else if (samp < INT16_MIN) { - samp = INT16_MIN; + + qint32 right_samp = (qint16) (((samples[i+3] & 0xFF) << 8) | (samples[i+2] & 0xFF)); + qint32 left_samp = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF)); + + left_samp *= vol_val; + right_samp *= vol_val; + + if (left_samp > INT16_MAX) { + left_samp = INT16_MAX; + } else if (left_samp < INT16_MIN) { + left_samp = INT16_MIN; } - samples[i+1] = (quint8) (samp >> 8); - samples[i] = (quint8) samp; + if (right_samp > INT16_MAX) { + right_samp = INT16_MAX; + } else if (right_samp < INT16_MIN) { + right_samp = INT16_MIN; + } + + samples[i+3] = (quint8) (right_samp >> 8); + samples[i+2] = (quint8) right_samp; + samples[i+1] = (quint8) (left_samp >> 8); + samples[i] = (quint8) left_samp; } } diff --git a/olive.pro b/olive.pro index 28e268fbe..40185c471 100644 --- a/olive.pro +++ b/olive.pro @@ -117,7 +117,8 @@ SOURCES += \ ui/clickablelabel.cpp \ project/keyframe.cpp \ ui/rectangleselect.cpp \ - dialogs/actionsearch.cpp + dialogs/actionsearch.cpp \ + effects/internal/fillleftrighteffect.cpp HEADERS += \ mainwindow.h \ @@ -204,7 +205,8 @@ HEADERS += \ ui/clickablelabel.h \ project/keyframe.h \ ui/rectangleselect.h \ - dialogs/actionsearch.h + dialogs/actionsearch.h \ + effects/internal/fillleftrighteffect.h FORMS += diff --git a/project/effect.cpp b/project/effect.cpp index 74f901388..6315ade00 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -28,6 +28,7 @@ #include "effects/internal/paneffect.h" #include "effects/internal/shakeeffect.h" #include "effects/internal/cornerpineffect.h" +#include "effects/internal/fillleftrighteffect.h" #include #include @@ -60,6 +61,7 @@ Effect* create_effect(Clip* c, const EffectMeta* em) { case EFFECT_INTERNAL_TONE: return new ToneEffect(c, em); case EFFECT_INTERNAL_SHAKE: return new ShakeEffect(c, em); case EFFECT_INTERNAL_CORNERPIN: return new CornerPinEffect(c, em); + case EFFECT_INTERNAL_FILLLEFTRIGHT: return new FillLeftRightEffect(c, em); } } else { dout << "[ERROR] Invalid effect data"; @@ -100,6 +102,10 @@ void load_internal_effects() { em.internal = EFFECT_INTERNAL_NOISE; effects.append(em); + em.name = "Fill Left/Right"; + em.internal = EFFECT_INTERNAL_FILLLEFTRIGHT; + effects.append(em); + em.subtype = EFFECT_TYPE_VIDEO; em.name = "Transform"; @@ -447,7 +453,7 @@ Effect::~Effect() { close(); } - delete container; + //delete container; for (int i=0;i