diff --git a/dialogs/clippropertiesdialog.cpp b/dialogs/clippropertiesdialog.cpp new file mode 100644 index 000000000..9d204db02 --- /dev/null +++ b/dialogs/clippropertiesdialog.cpp @@ -0,0 +1,118 @@ +#include "clippropertiesdialog.h" + +#include +#include +#include + +#include "panels/panels.h" +#include "project/undo.h" + +ClipPropertiesDialog::ClipPropertiesDialog(QWidget *parent, QVector clips) : + QDialog(parent) +{ + setWindowTitle((clips.size() == 1) ? + tr("\"%1\" Properties").arg(clips.at(0)->name()) : + tr("Multiple Clip Properties")); + + clips_ = clips; + + QGridLayout* layout = new QGridLayout(this); + + int row = 0; + + // Clip Name field + layout->addWidget(new QLabel(tr("Name:")), row, 0); + + clip_name_field_ = new QLineEdit(); + + layout->addWidget(clip_name_field_, row, 1); + + row++; + + // Clip Duration field + layout->addWidget(new QLabel(tr("Duration:")), row, 0); + + duration_field_ = new LabelSlider(); + duration_field_->set_display_type(LABELSLIDER_FRAMENUMBER); + duration_field_->set_minimum_value(1); + layout->addWidget(duration_field_, row, 1); + + row++; + + // Dialog buttons (OK and Cancel) + QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + buttons->setCenterButtons(true); + layout->addWidget(buttons, row, 0, 1, 2); + + connect(buttons, SIGNAL(accepted()), this, SLOT(accept())); + connect(buttons, SIGNAL(rejected()), this, SLOT(reject())); + + // analyze list of clips for default values + + bool all_clips_have_same_name = true; + bool all_clips_have_same_duration = true; + + for (int i=1;iname() != clips.at(i)->name()) { + all_clips_have_same_name = false; + } + if (clips.at(i-1)->length() != clips.at(i)->length()) { + all_clips_have_same_duration = false; + } + } + + Clip* first_clip = clips_.first(); + + if (all_clips_have_same_name) { + // if there's only one clip selected, set all defaults to that clip's properties + clip_name_field_->setText(first_clip->name()); + } else { + // if there are multiple clips, use different properties + clip_name_field_->setPlaceholderText(tr("(multiple)")); + } + + // it's assumed all the clips come from the same sequence + duration_field_->set_frame_rate(first_clip->sequence->frame_rate); + + if (all_clips_have_same_duration) { + duration_field_->set_default_value(first_clip->length()); + duration_field_->set_value(first_clip->length(), false); + duration_field_->set_maximum_value(first_clip->media_length()); + } else { + duration_field_->set_default_value(qSNaN()); + duration_field_->set_value(qSNaN(), false); + } +} + +void ClipPropertiesDialog::accept() +{ + const QString& clip_name = clip_name_field_->text(); + double clip_duration = duration_field_->value(); + + ComboAction* ca = new ComboAction(); + + for (int i=0;iappend(new RenameClipCommand(clip, clip_name)); + } + + if (!qIsNaN(clip_duration)) { + clip->move(ca, + clip->timeline_in(), + clip->timeline_in() + qRound(clip_duration), + clip->clip_in(), + clip->track()); + } + } + + if (ca->hasActions()) { + olive::UndoStack.push(ca); + update_ui(false); + } else { + delete ca; + } + + QDialog::accept(); +} diff --git a/dialogs/clippropertiesdialog.h b/dialogs/clippropertiesdialog.h new file mode 100644 index 000000000..12b631b3f --- /dev/null +++ b/dialogs/clippropertiesdialog.h @@ -0,0 +1,23 @@ +#ifndef CLIPPROPERTIESDIALOG_H +#define CLIPPROPERTIESDIALOG_H + +#include +#include + +#include "project/clip.h" +#include "ui/labelslider.h" + +class ClipPropertiesDialog : public QDialog { + Q_OBJECT +public: + ClipPropertiesDialog(QWidget* parent, QVector clips); +protected: + virtual void accept() override; +private: + QVector clips_; + + QLineEdit* clip_name_field_; + LabelSlider* duration_field_; +}; + +#endif // CLIPPROPERTIESDIALOG_H diff --git a/dialogs/speeddialog.cpp b/dialogs/speeddialog.cpp index 0b5e505dc..5b0035115 100644 --- a/dialogs/speeddialog.cpp +++ b/dialogs/speeddialog.cpp @@ -35,9 +35,11 @@ #include "project/effect.h" #include "project/media.h" -SpeedDialog::SpeedDialog(QWidget *parent) : QDialog(parent) { +SpeedDialog::SpeedDialog(QWidget *parent, QVector clips) : QDialog(parent) { setWindowTitle(tr("Speed/Duration")); + clips_ = clips; + QVBoxLayout* main_layout = new QVBoxLayout(this); QGridLayout* grid = new QGridLayout(); @@ -93,8 +95,8 @@ void SpeedDialog::run() { default_length = -1; current_length = -1; - for (int i=0;iisEnabled() && c->track() < 0) { @@ -220,8 +222,8 @@ void SpeedDialog::duration_update() { bool got_fr = false; double fr_val = qSNaN(); - for (int i=0;ilength() * c->speed().value); @@ -263,8 +265,8 @@ void SpeedDialog::frame_rate_update() { long len_val = -1; // analyze video clips - for (int i=0;itrack() >= 0) { long new_clip_len = (qIsNaN(old_pc_val) || qIsNaN(pc_val)) ? c->length() : ((c->length() * c->speed().value) / pc_val); @@ -311,7 +313,7 @@ void SpeedDialog::frame_rate_update() { duration->set_value((len_val == -1) ? qSNaN() : len_val, false); } -void set_speed(ComboAction* ca, ClipPtr c, double speed, bool ripple, long& ep, long& lr) { +void set_speed(ComboAction* ca, Clip* c, double speed, bool ripple, long& ep, long& lr) { panel_timeline->deselect_area(c->timeline_in(), c->timeline_out(), c->track()); long proposed_out = c->timeline_out(); @@ -330,7 +332,7 @@ void set_speed(ComboAction* ca, ClipPtr c, double speed, bool ripple, long& ep, } ep = qMin(ep, c->timeline_out()); lr = qMax(lr, proposed_out - c->timeline_out()); - move_clip(ca, c, c->timeline_in(), proposed_out, qRound(c->clip_in() * multiplier), c->track()); + c->move(ca, c->timeline_in(), proposed_out, qRound(c->clip_in() * multiplier), c->track()); c->refactor_frame_rate(ca, multiplier, false); @@ -358,8 +360,8 @@ void SpeedDialog::accept() { long earliest_point = LONG_MAX; long longest_ripple = LONG_MIN; - for (int i=0;iIsOpen()) { @@ -376,7 +378,7 @@ void SpeedDialog::accept() { // set reverse setting if the user made a selection if (reverse->checkState() != Qt::PartiallyChecked && c->reversed() != reverse->isChecked()) { long new_clip_in = (c->media_length() - (c->length() + c->clip_in())); - move_clip(ca, c, c->timeline_in(), c->timeline_out(), new_clip_in, c->track()); + c->move(ca, c->timeline_in(), c->timeline_out(), new_clip_in, c->track()); c->set_clip_in(new_clip_in); reversed_action->AddSetting(c, reverse->isChecked()); } @@ -386,8 +388,8 @@ void SpeedDialog::accept() { if (!qIsNaN(percent->value())) { // if we have a percentage value, use that on all the clips - for (int i=0;ivalue(), ripple->isChecked(), earliest_point, longest_ripple); } @@ -395,15 +397,13 @@ void SpeedDialog::accept() { // if the user changed the speed by changing the frame rate, bool can_change_all = true; - double cached_speed; + double cached_speed = clips_.first()->speed().value; double cached_fr = qSNaN(); // see if we can use the frame rate to change all the speeds - for (int i=0;ispeed().value; - } else if (!qFuzzyCompare(cached_speed, c->speed().value)) { + for (int i=0;i 0 && !qFuzzyCompare(cached_speed, c->speed().value)) { can_change_all = false; } if (c->track() < 0) { @@ -417,8 +417,8 @@ void SpeedDialog::accept() { } // make changes - for (int i=0;itrack() < 0) { set_speed(ca, c, frame_rate->value() / c->media_frame_rate(), ripple->isChecked(), earliest_point, longest_ripple); } else if (can_change_all) { @@ -427,14 +427,14 @@ void SpeedDialog::accept() { } } else if (!qIsNaN(duration->value())) { // simply set duration - for (int i=0;ilength() * c->speed().value) / duration->value(), ripple->isChecked(), earliest_point, longest_ripple); } } if (ripple->isChecked()) { - ripple_clips(ca, clips.at(0)->sequence, earliest_point, longest_ripple); + ripple_clips(ca, clips_.at(0)->sequence, earliest_point, longest_ripple); } sel_command->new_data = olive::ActiveSequence->selections; diff --git a/dialogs/speeddialog.h b/dialogs/speeddialog.h index 9f355377a..26bb0ab9c 100644 --- a/dialogs/speeddialog.h +++ b/dialogs/speeddialog.h @@ -29,31 +29,32 @@ class SpeedDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - SpeedDialog(QWidget* parent = 0); - QVector clips; + SpeedDialog(QWidget* parent, QVector clips); - void run(); + void run(); private slots: - void percent_update(); - void duration_update(); - void frame_rate_update(); - void accept(); + void percent_update(); + void duration_update(); + void frame_rate_update(); + void accept(); private: - LabelSlider* percent; - LabelSlider* duration; - LabelSlider* frame_rate; + QVector clips_; - QCheckBox* reverse; - QCheckBox* maintain_pitch; - QCheckBox* ripple; + LabelSlider* percent; + LabelSlider* duration; + LabelSlider* frame_rate; - double default_frame_rate; - double current_frame_rate; - double current_percent; - long default_length; - long current_length; + QCheckBox* reverse; + QCheckBox* maintain_pitch; + QCheckBox* ripple; + + double default_frame_rate; + double current_frame_rate; + double current_percent; + long default_length; + long current_length; }; #endif // SPEEDDIALOG_H diff --git a/effects/internal/audionoiseeffect.cpp b/effects/internal/audionoiseeffect.cpp index 00afe04c8..d43fd5545 100644 --- a/effects/internal/audionoiseeffect.cpp +++ b/effects/internal/audionoiseeffect.cpp @@ -23,7 +23,7 @@ #include #include -AudioNoiseEffect::AudioNoiseEffect(ClipPtr c, const EffectMeta *em) : Effect(c, em) { +AudioNoiseEffect::AudioNoiseEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { amount_val = add_row(tr("Amount"))->add_field(EFFECT_FIELD_DOUBLE, "amount"); amount_val->set_double_minimum_value(0); amount_val->set_double_maximum_value(100); diff --git a/effects/internal/audionoiseeffect.h b/effects/internal/audionoiseeffect.h index ea0e47dcb..2906499c9 100644 --- a/effects/internal/audionoiseeffect.h +++ b/effects/internal/audionoiseeffect.h @@ -26,7 +26,7 @@ class AudioNoiseEffect : public Effect { Q_OBJECT public: - AudioNoiseEffect(ClipPtr c, const EffectMeta* em); + AudioNoiseEffect(Clip* c, const EffectMeta* em); void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); EffectField* amount_val; diff --git a/effects/internal/cornerpineffect.cpp b/effects/internal/cornerpineffect.cpp index baf8194ef..d00ecd571 100644 --- a/effects/internal/cornerpineffect.cpp +++ b/effects/internal/cornerpineffect.cpp @@ -24,7 +24,7 @@ #include "project/clip.h" #include "debug.h" -CornerPinEffect::CornerPinEffect(ClipPtr c, const EffectMeta *em) : Effect(c, em) { +CornerPinEffect::CornerPinEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { enable_coords = true; enable_shader = true; diff --git a/effects/internal/cornerpineffect.h b/effects/internal/cornerpineffect.h index 711571b96..b1591246d 100644 --- a/effects/internal/cornerpineffect.h +++ b/effects/internal/cornerpineffect.h @@ -26,7 +26,7 @@ class CornerPinEffect : public Effect { Q_OBJECT public: - CornerPinEffect(ClipPtr c, const EffectMeta* em); + CornerPinEffect(Clip* c, const EffectMeta* em); void process_coords(double timecode, GLTextureCoords& coords, int data); void process_shader(double timecode, GLTextureCoords& coords, int iterations); void gizmo_draw(double timecode, GLTextureCoords& coords); diff --git a/effects/internal/crossdissolvetransition.cpp b/effects/internal/crossdissolvetransition.cpp index a9d3fae35..ba495346d 100644 --- a/effects/internal/crossdissolvetransition.cpp +++ b/effects/internal/crossdissolvetransition.cpp @@ -22,7 +22,7 @@ #include -CrossDissolveTransition::CrossDissolveTransition(ClipPtr c, ClipPtr s, const EffectMeta* em) : Transition(c, s, em) { +CrossDissolveTransition::CrossDissolveTransition(Clip* c, Clip* s, const EffectMeta* em) : Transition(c, s, em) { enable_coords = true; // add_row("Smooth")->add_field(EFFECT_FIELD_BOOL, "smooth"); diff --git a/effects/internal/crossdissolvetransition.h b/effects/internal/crossdissolvetransition.h index 427b3e18b..2b11b7c7e 100644 --- a/effects/internal/crossdissolvetransition.h +++ b/effects/internal/crossdissolvetransition.h @@ -25,7 +25,7 @@ class CrossDissolveTransition : public Transition { public: - CrossDissolveTransition(ClipPtr c, ClipPtr s, const EffectMeta* em); + CrossDissolveTransition(Clip *c, Clip *s, const EffectMeta* em); void process_coords(double timecode, GLTextureCoords &, int data); }; diff --git a/effects/internal/cubetransition.cpp b/effects/internal/cubetransition.cpp index 74b79d780..829ad820d 100644 --- a/effects/internal/cubetransition.cpp +++ b/effects/internal/cubetransition.cpp @@ -22,7 +22,7 @@ #include "debug.h" -CubeTransition::CubeTransition(ClipPtr c, ClipPtr s, const EffectMeta* em) : Transition(c, s, em) { +CubeTransition::CubeTransition(Clip* c, Clip* s, const EffectMeta* em) : Transition(c, s, em) { enable_coords = true; } diff --git a/effects/internal/cubetransition.h b/effects/internal/cubetransition.h index 05f23b306..82519ad03 100644 --- a/effects/internal/cubetransition.h +++ b/effects/internal/cubetransition.h @@ -25,7 +25,7 @@ class CubeTransition : public Transition { public: - CubeTransition(ClipPtr c, ClipPtr s, const EffectMeta* em); + CubeTransition(Clip* c, Clip* s, const EffectMeta* em); void process_coords(double timecode, GLTextureCoords &, int data); }; diff --git a/effects/internal/exponentialfadetransition.cpp b/effects/internal/exponentialfadetransition.cpp index e82c0275d..ca7c367ca 100644 --- a/effects/internal/exponentialfadetransition.cpp +++ b/effects/internal/exponentialfadetransition.cpp @@ -22,7 +22,7 @@ #include -ExponentialFadeTransition::ExponentialFadeTransition(ClipPtr c, ClipPtr s, const EffectMeta* em) : Transition(c, s, em) {} +ExponentialFadeTransition::ExponentialFadeTransition(Clip* c, Clip* s, const EffectMeta* em) : Transition(c, s, em) {} void ExponentialFadeTransition::process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int type) { double interval = (timecode_end-timecode_start)/nb_bytes; diff --git a/effects/internal/exponentialfadetransition.h b/effects/internal/exponentialfadetransition.h index 1fcca50bb..36ec7f6f1 100644 --- a/effects/internal/exponentialfadetransition.h +++ b/effects/internal/exponentialfadetransition.h @@ -25,7 +25,7 @@ class ExponentialFadeTransition : public Transition { public: - ExponentialFadeTransition(ClipPtr c, ClipPtr s, const EffectMeta* em); + ExponentialFadeTransition(Clip* c, Clip* s, const EffectMeta* em); void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); }; diff --git a/effects/internal/fillleftrighteffect.cpp b/effects/internal/fillleftrighteffect.cpp index 8d0326042..e6e687839 100644 --- a/effects/internal/fillleftrighteffect.cpp +++ b/effects/internal/fillleftrighteffect.cpp @@ -23,7 +23,7 @@ #define FILL_TYPE_LEFT 0 #define FILL_TYPE_RIGHT 1 -FillLeftRightEffect::FillLeftRightEffect(ClipPtr c, const EffectMeta *em) : Effect(c, em) { +FillLeftRightEffect::FillLeftRightEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { EffectRow* type_row = add_row(tr("Type")); fill_type = type_row->add_field(EFFECT_FIELD_COMBO, "type"); fill_type->add_combo_item(tr("Fill Left with Right"), FILL_TYPE_LEFT); diff --git a/effects/internal/fillleftrighteffect.h b/effects/internal/fillleftrighteffect.h index d37f0d3e2..198f44dcb 100644 --- a/effects/internal/fillleftrighteffect.h +++ b/effects/internal/fillleftrighteffect.h @@ -26,7 +26,7 @@ class FillLeftRightEffect : public Effect { Q_OBJECT public: - FillLeftRightEffect(ClipPtr c, const EffectMeta* em); + 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; diff --git a/effects/internal/frei0reffect.cpp b/effects/internal/frei0reffect.cpp index 71085154c..223cd0cce 100644 --- a/effects/internal/frei0reffect.cpp +++ b/effects/internal/frei0reffect.cpp @@ -37,7 +37,7 @@ typedef void (*f0rGetPluginInfo)(f0r_plugin_info_t* info); typedef void (*f0rSetParamValue) (f0r_instance_t instance, f0r_param_t param, int param_index); -Frei0rEffect::Frei0rEffect(ClipPtr c, const EffectMeta *em) : +Frei0rEffect::Frei0rEffect(Clip* c, const EffectMeta *em) : Effect(c, em), open(false) { diff --git a/effects/internal/frei0reffect.h b/effects/internal/frei0reffect.h index b197fff5a..b6428a8b9 100644 --- a/effects/internal/frei0reffect.h +++ b/effects/internal/frei0reffect.h @@ -35,7 +35,7 @@ typedef void (*f0rGetParamInfo)(f0r_param_info_t * info, class Frei0rEffect : public Effect { Q_OBJECT public: - Frei0rEffect(ClipPtr c, const EffectMeta* em); + Frei0rEffect(Clip* c, const EffectMeta* em); ~Frei0rEffect(); virtual void process_image(double timecode, uint8_t* input, uint8_t* output, int size); diff --git a/effects/internal/linearfadetransition.cpp b/effects/internal/linearfadetransition.cpp index c8e65c95f..0c3917928 100644 --- a/effects/internal/linearfadetransition.cpp +++ b/effects/internal/linearfadetransition.cpp @@ -20,7 +20,7 @@ #include "linearfadetransition.h" -LinearFadeTransition::LinearFadeTransition(ClipPtr c, ClipPtr s, const EffectMeta* em) : Transition(c, s, em) {} +LinearFadeTransition::LinearFadeTransition(Clip* c, Clip* s, const EffectMeta* em) : Transition(c, s, em) {} void LinearFadeTransition::process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int type) { double interval = (timecode_end-timecode_start)/nb_bytes; diff --git a/effects/internal/linearfadetransition.h b/effects/internal/linearfadetransition.h index b4d2bbae3..f3716753a 100644 --- a/effects/internal/linearfadetransition.h +++ b/effects/internal/linearfadetransition.h @@ -25,7 +25,7 @@ class LinearFadeTransition : public Transition { public: - LinearFadeTransition(ClipPtr c, ClipPtr s, const EffectMeta* em); + LinearFadeTransition(Clip* c, Clip* s, const EffectMeta* em); void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); }; diff --git a/effects/internal/logarithmicfadetransition.cpp b/effects/internal/logarithmicfadetransition.cpp index d4af9d860..e4b3bd664 100644 --- a/effects/internal/logarithmicfadetransition.cpp +++ b/effects/internal/logarithmicfadetransition.cpp @@ -22,7 +22,7 @@ #include -LogarithmicFadeTransition::LogarithmicFadeTransition(ClipPtr c, ClipPtr s, const EffectMeta* em) : Transition(c, s, em) {} +LogarithmicFadeTransition::LogarithmicFadeTransition(Clip* c, Clip* s, const EffectMeta* em) : Transition(c, s, em) {} void LogarithmicFadeTransition::process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int type) { double interval = (timecode_end-timecode_start)/nb_bytes; diff --git a/effects/internal/logarithmicfadetransition.h b/effects/internal/logarithmicfadetransition.h index 66ac0014a..a476351d1 100644 --- a/effects/internal/logarithmicfadetransition.h +++ b/effects/internal/logarithmicfadetransition.h @@ -25,7 +25,7 @@ class LogarithmicFadeTransition : public Transition { public: - LogarithmicFadeTransition(ClipPtr c, ClipPtr s, const EffectMeta* em); + LogarithmicFadeTransition(Clip* c, Clip* s, const EffectMeta* em); void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); }; diff --git a/effects/internal/paneffect.cpp b/effects/internal/paneffect.cpp index d3318838e..babb0b01b 100644 --- a/effects/internal/paneffect.cpp +++ b/effects/internal/paneffect.cpp @@ -28,7 +28,7 @@ #include "ui/labelslider.h" #include "ui/collapsiblewidget.h" -PanEffect::PanEffect(ClipPtr c, const EffectMeta *em) : Effect(c, em) { +PanEffect::PanEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { EffectRow* pan_row = add_row(tr("Pan")); pan_val = pan_row->add_field(EFFECT_FIELD_DOUBLE, "pan"); pan_val->set_double_minimum_value(-100); diff --git a/effects/internal/paneffect.h b/effects/internal/paneffect.h index 8ac4c3903..7640c48be 100644 --- a/effects/internal/paneffect.h +++ b/effects/internal/paneffect.h @@ -26,7 +26,7 @@ class PanEffect : public Effect { Q_OBJECT public: - PanEffect(ClipPtr c, const EffectMeta* em); + PanEffect(Clip* c, const EffectMeta* em); void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); EffectField* pan_val; diff --git a/effects/internal/shakeeffect.cpp b/effects/internal/shakeeffect.cpp index 275eabeea..89bb39ecb 100644 --- a/effects/internal/shakeeffect.cpp +++ b/effects/internal/shakeeffect.cpp @@ -33,7 +33,7 @@ #include "debug.h" -ShakeEffect::ShakeEffect(ClipPtr c, const EffectMeta *em) : Effect(c, em) { +ShakeEffect::ShakeEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { enable_coords = true; EffectRow* intensity_row = add_row(tr("Intensity")); diff --git a/effects/internal/shakeeffect.h b/effects/internal/shakeeffect.h index b162ab3bf..634868a3d 100644 --- a/effects/internal/shakeeffect.h +++ b/effects/internal/shakeeffect.h @@ -28,7 +28,7 @@ class ShakeEffect : public Effect { Q_OBJECT public: - ShakeEffect(ClipPtr c, const EffectMeta* em); + ShakeEffect(Clip* c, const EffectMeta* em); void process_coords(double timecode, GLTextureCoords& coords, int data); EffectField* intensity_val; diff --git a/effects/internal/solideffect.cpp b/effects/internal/solideffect.cpp index cf09eee63..a3077852b 100644 --- a/effects/internal/solideffect.cpp +++ b/effects/internal/solideffect.cpp @@ -38,7 +38,7 @@ #define SMPTE_STRIP_COUNT 3 #define SMPTE_LOWER_BARS 4 -SolidEffect::SolidEffect(ClipPtr c, const EffectMeta* em) : Effect(c, em) { +SolidEffect::SolidEffect(Clip* c, const EffectMeta* em) : Effect(c, em) { enable_superimpose = true; solid_type = add_row(tr("Type"))->add_field(EFFECT_FIELD_COMBO, "type"); diff --git a/effects/internal/solideffect.h b/effects/internal/solideffect.h index 66ad89a58..9175e02e6 100644 --- a/effects/internal/solideffect.h +++ b/effects/internal/solideffect.h @@ -28,7 +28,7 @@ class SolidEffect : public Effect { Q_OBJECT public: - SolidEffect(ClipPtr c, const EffectMeta *em); + SolidEffect(Clip* c, const EffectMeta *em); void redraw(double timecode); private slots: void ui_update(int); diff --git a/effects/internal/texteffect.cpp b/effects/internal/texteffect.cpp index 6c80632cb..897d98d79 100644 --- a/effects/internal/texteffect.cpp +++ b/effects/internal/texteffect.cpp @@ -44,7 +44,7 @@ #include "io/config.h" #include "mainwindow.h" -TextEffect::TextEffect(ClipPtr c, const EffectMeta* em) : +TextEffect::TextEffect(Clip* c, const EffectMeta* em) : Effect(c, em) { enable_superimpose = true; diff --git a/effects/internal/texteffect.h b/effects/internal/texteffect.h index 5a0c7fcc2..d73b60de0 100644 --- a/effects/internal/texteffect.h +++ b/effects/internal/texteffect.h @@ -29,7 +29,7 @@ class TextEffect : public Effect { Q_OBJECT public: - TextEffect(ClipPtr c, const EffectMeta *em); + TextEffect(Clip* c, const EffectMeta *em); void redraw(double timecode); EffectField* text_val; diff --git a/effects/internal/timecodeeffect.cpp b/effects/internal/timecodeeffect.cpp index a3666e85b..b01e202d5 100644 --- a/effects/internal/timecodeeffect.cpp +++ b/effects/internal/timecodeeffect.cpp @@ -43,7 +43,7 @@ #include "ui/fontcombobox.h" #include "io/config.h" -TimecodeEffect::TimecodeEffect(ClipPtr c, const EffectMeta* em) : +TimecodeEffect::TimecodeEffect(Clip* c, const EffectMeta* em) : Effect(c, em) { enable_always_update = true; diff --git a/effects/internal/timecodeeffect.h b/effects/internal/timecodeeffect.h index 8cae99a8b..2caeb3276 100644 --- a/effects/internal/timecodeeffect.h +++ b/effects/internal/timecodeeffect.h @@ -29,7 +29,7 @@ class TimecodeEffect : public Effect { Q_OBJECT public: - TimecodeEffect(ClipPtr c, const EffectMeta *em); + TimecodeEffect(Clip* c, const EffectMeta *em); void redraw(double timecode); EffectField * scale_val; EffectField * color_val; diff --git a/effects/internal/toneeffect.cpp b/effects/internal/toneeffect.cpp index 112a700e4..777c3e878 100644 --- a/effects/internal/toneeffect.cpp +++ b/effects/internal/toneeffect.cpp @@ -28,7 +28,7 @@ #include "project/sequence.h" #include "debug.h" -ToneEffect::ToneEffect(ClipPtr c, const EffectMeta *em) : Effect(c, em), sinX(INT_MIN) { +ToneEffect::ToneEffect(Clip* c, const EffectMeta *em) : Effect(c, em), sinX(INT_MIN) { type_val = add_row(tr("Type"))->add_field(EFFECT_FIELD_COMBO, "type"); type_val->add_combo_item("Sine", TONE_TYPE_SINE); diff --git a/effects/internal/toneeffect.h b/effects/internal/toneeffect.h index ec4e17622..2007ac70e 100644 --- a/effects/internal/toneeffect.h +++ b/effects/internal/toneeffect.h @@ -26,7 +26,7 @@ class ToneEffect : public Effect { Q_OBJECT public: - ToneEffect(ClipPtr c, const EffectMeta* em); + ToneEffect(Clip* c, const EffectMeta* em); void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); EffectField* type_val; diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index 458d03e31..07dd08d3f 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -43,7 +43,7 @@ #include "panels/viewer.h" #include "ui/viewerwidget.h" -TransformEffect::TransformEffect(ClipPtr c, const EffectMeta* em) : Effect(c, em) { +TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) { enable_coords = true; EffectRow* position_row = add_row(tr("Position")); diff --git a/effects/internal/transformeffect.h b/effects/internal/transformeffect.h index 969f76fc6..f815659ed 100644 --- a/effects/internal/transformeffect.h +++ b/effects/internal/transformeffect.h @@ -26,7 +26,7 @@ class TransformEffect : public Effect { Q_OBJECT public: - TransformEffect(ClipPtr c, const EffectMeta* em); + TransformEffect(Clip* c, const EffectMeta* em); void refresh(); void process_coords(double timecode, GLTextureCoords& coords, int data); diff --git a/effects/internal/voideffect.cpp b/effects/internal/voideffect.cpp index 8a898d772..de7aaa293 100644 --- a/effects/internal/voideffect.cpp +++ b/effects/internal/voideffect.cpp @@ -27,7 +27,7 @@ #include "ui/collapsiblewidget.h" #include "debug.h" -VoidEffect::VoidEffect(ClipPtr c, const QString& n) : Effect(c, nullptr) { +VoidEffect::VoidEffect(Clip* c, const QString& n) : Effect(c, nullptr) { name = n; QString display_name; if (n.isEmpty()) { @@ -43,7 +43,7 @@ VoidEffect::VoidEffect(ClipPtr c, const QString& n) : Effect(c, nullptr) { meta = &void_meta; } -EffectPtr VoidEffect::copy(ClipPtr c) { +EffectPtr VoidEffect::copy(Clip* c) { EffectPtr copy(new VoidEffect(c, name)); copy->set_enabled(is_enabled()); copy_field_keyframes(copy); diff --git a/effects/internal/voideffect.h b/effects/internal/voideffect.h index b30dd9a59..210b8bed0 100644 --- a/effects/internal/voideffect.h +++ b/effects/internal/voideffect.h @@ -32,9 +32,9 @@ class VoidEffect : public Effect { Q_OBJECT public: - VoidEffect(ClipPtr c, const QString& n); + VoidEffect(Clip* c, const QString& n); - virtual EffectPtr copy(ClipPtr c) override; + virtual EffectPtr copy(Clip* c) override; virtual void load(QXmlStreamReader &stream) override; virtual void save(QXmlStreamWriter &stream) override; private: diff --git a/effects/internal/volumeeffect.cpp b/effects/internal/volumeeffect.cpp index 17caa6e36..23cf1a45f 100644 --- a/effects/internal/volumeeffect.cpp +++ b/effects/internal/volumeeffect.cpp @@ -28,7 +28,7 @@ #include "ui/labelslider.h" #include "ui/collapsiblewidget.h" -VolumeEffect::VolumeEffect(ClipPtr c, const EffectMeta *em) : Effect(c, em) { +VolumeEffect::VolumeEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { EffectRow* volume_row = add_row(tr("Volume")); volume_val = volume_row->add_field(EFFECT_FIELD_DOUBLE, "volume"); diff --git a/effects/internal/volumeeffect.h b/effects/internal/volumeeffect.h index c1e67b667..6d143f5af 100644 --- a/effects/internal/volumeeffect.h +++ b/effects/internal/volumeeffect.h @@ -26,7 +26,7 @@ class VolumeEffect : public Effect { Q_OBJECT public: - VolumeEffect(ClipPtr c, const EffectMeta* em); + VolumeEffect(Clip* c, const EffectMeta* em); void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); EffectField* volume_val; diff --git a/effects/internal/vsthost.cpp b/effects/internal/vsthost.cpp index 686d22662..110c31312 100644 --- a/effects/internal/vsthost.cpp +++ b/effects/internal/vsthost.cpp @@ -256,7 +256,7 @@ void VSTHost::processAudio(long numFrames) { plugin->processReplacing(plugin, inputs, outputs, numFrames); } -VSTHost::VSTHost(ClipPtr c, const EffectMeta *em) : Effect(c, em) { +VSTHost::VSTHost(Clip* c, const EffectMeta *em) : Effect(c, em) { plugin = nullptr; inputs = new float* [CHANNEL_COUNT]; diff --git a/effects/internal/vsthost.h b/effects/internal/vsthost.h index 4bcd6e818..cd2d2ae48 100644 --- a/effects/internal/vsthost.h +++ b/effects/internal/vsthost.h @@ -37,7 +37,7 @@ typedef intptr_t (*dispatcherFuncPtr)(AEffect *effect, int32_t opCode, int32_t i class VSTHost : public Effect { Q_OBJECT public: - VSTHost(ClipPtr c, const EffectMeta* em); + VSTHost(Clip* c, const EffectMeta* em); ~VSTHost(); void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); diff --git a/io/loadthread.cpp b/io/loadthread.cpp index b6e96123e..8ee232bcd 100644 --- a/io/loadthread.cpp +++ b/io/loadthread.cpp @@ -41,11 +41,14 @@ LoadThread::LoadThread(bool a) : autorecovery(a), cancelled(false) { connect(this, SIGNAL(finished()), this, SLOT(deleteLater())); connect(this, SIGNAL(success()), this, SLOT(success_func())); connect(this, SIGNAL(error()), this, SLOT(error_func())); - connect(this, SIGNAL(start_create_effect_ui(QXmlStreamReader*, ClipPtr, int, const QString*, const EffectMeta*, long, bool)), this, SLOT(create_effect_ui(QXmlStreamReader*, ClipPtr, int, const QString*, const EffectMeta*, long, bool))); + connect(this, + SIGNAL(start_create_effect_ui(QXmlStreamReader*, Clip*, int, const QString*, const EffectMeta*, long, bool)), + this, + SLOT(create_effect_ui(QXmlStreamReader*, Clip*, int, const QString*, const EffectMeta*, long, bool))); connect(this, SIGNAL(start_question(const QString&, const QString &, int)), this, SLOT(question_func(const QString &, const QString &, int))); } -void LoadThread::load_effect(QXmlStreamReader& stream, ClipPtr c) { +void LoadThread::load_effect(QXmlStreamReader& stream, Clip* c) { QString tag = stream.name().toString(); // variables to store effect metadata in @@ -68,7 +71,7 @@ void LoadThread::load_effect(QXmlStreamReader& stream, ClipPtr c) { } else if (attr.name() == "shared") { // if a transition has this tag, it's sharing a transition with another clip so we don't have to do any processing - ClipPtr sharing_clip = c->sequence->clips.at(attr.value().toInt()); + Clip* sharing_clip = c->sequence->clips.at(attr.value().toInt()).get(); if (tag == "opening") { c->opening_transition = (sharing_clip->closing_transition); @@ -376,7 +379,8 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) { } else if (stream.name() == "clip" && stream.isStartElement()) { int media_type = -1; int media_id, stream_id; - ClipPtr c(new Clip(s)); + + ClipPtr c = std::make_shared(s); QColor clip_color; ClipSpeed speed_info = c->speed(); @@ -465,7 +469,7 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) { && (stream.name() == "effect" || stream.name() == "opening" || stream.name() == "closing")) { - load_effect(stream, c); + load_effect(stream, c.get()); } else if (stream.name() == "marker" && stream.isStartElement()) { Marker m; for (int j=0;jclips.size();i++) { // correct links - ClipPtr correct_clip = s->clips.at(i); + Clip* correct_clip = s->clips.at(i).get(); for (int j=0;jlinked.size();j++) { bool found = false; for (int k=0;kclips.size();k++) { @@ -727,7 +731,7 @@ void LoadThread::success_func() { void LoadThread::create_effect_ui( QXmlStreamReader* stream, - ClipPtr c, + Clip* c, int type, const QString* effect_name, const EffectMeta* meta, diff --git a/io/loadthread.h b/io/loadthread.h index a9d562137..28d9e00fb 100644 --- a/io/loadthread.h +++ b/io/loadthread.h @@ -41,18 +41,30 @@ signals: void start_question(const QString &title, const QString &text, int buttons); void success(); void error(); - void start_create_effect_ui(QXmlStreamReader* stream, ClipPtr c, int type, const QString *effect_name, const EffectMeta* meta, long effect_length, bool effect_enabled); + void start_create_effect_ui(QXmlStreamReader* stream, + Clip* c, + int type, + const QString *effect_name, + const EffectMeta* meta, + long effect_length, + bool effect_enabled); void report_progress(int p); private slots: void question_func(const QString &title, const QString &text, int buttons); void error_func(); void success_func(); - void create_effect_ui(QXmlStreamReader* stream, ClipPtr c, int type, const QString *effect_name, const EffectMeta* meta, long effect_length, bool effect_enabled); + void create_effect_ui(QXmlStreamReader* stream, + Clip* c, + int type, + const QString *effect_name, + const EffectMeta* meta, + long effect_length, + bool effect_enabled); private: bool autorecovery; bool load_worker(QFile& f, QXmlStreamReader& stream, int type); - void load_effect(QXmlStreamReader& stream, ClipPtr c); + void load_effect(QXmlStreamReader& stream, Clip* c); void read_next(QXmlStreamReader& stream); void read_next_start_element(QXmlStreamReader& stream); diff --git a/main.cpp b/main.cpp index b6a25d844..759892d2c 100644 --- a/main.cpp +++ b/main.cpp @@ -25,6 +25,7 @@ #include "oliveglobal.h" #include "ui/mediaiconservice.h" +#include "panels/timeline.h" #include "io/config.h" @@ -126,6 +127,9 @@ int main(int argc, char *argv[]) { MainWindow w(nullptr); + // multiply track height constants by the current DPI scale + olive::timeline::MultiplyTrackSizesByDPI(); + // connect main window's first paint to global's init finished function QObject::connect(&w, SIGNAL(finished_first_paint()), olive::Global.get(), SLOT(finished_initialize())); diff --git a/olive.pro b/olive.pro index a103ea85a..95066c9b0 100644 --- a/olive.pro +++ b/olive.pro @@ -158,7 +158,8 @@ SOURCES += \ rendering/renderthread.cpp \ rendering/cacher.cpp \ rendering/clipqueue.cpp \ - rendering/audio.cpp + rendering/audio.cpp \ + dialogs/clippropertiesdialog.cpp HEADERS += \ mainwindow.h \ @@ -268,7 +269,8 @@ HEADERS += \ rendering/renderthread.h \ rendering/clipqueue.h \ rendering/cacher.h \ - rendering/audio.h + rendering/audio.h \ + dialogs/clippropertiesdialog.h FORMS += diff --git a/oliveglobal.cpp b/oliveglobal.cpp index fb4f0a8e3..9e875fdb6 100644 --- a/oliveglobal.cpp +++ b/oliveglobal.cpp @@ -357,14 +357,20 @@ void OliveGlobal::open_debug_log() { void OliveGlobal::open_speed_dialog() { if (olive::ActiveSequence != nullptr) { - SpeedDialog s(olive::MainWindow); + + QVector selected_clips; + for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); + Clip* c = olive::ActiveSequence->clips.at(i).get(); if (c != nullptr && is_clip_selected(c, true)) { - s.clips.append(c); + selected_clips.append(c); } } - if (s.clips.size() > 0) s.run(); + + if (selected_clips.size() > 0) { + SpeedDialog s(olive::MainWindow, selected_clips); + s.exec(); + } } } diff --git a/panels/effectcontrols.cpp b/panels/effectcontrols.cpp index eb948afea..b6aa690e3 100644 --- a/panels/effectcontrols.cpp +++ b/panels/effectcontrols.cpp @@ -100,7 +100,7 @@ void EffectControls::set_zoom(bool in) { void EffectControls::menu_select(QAction* q) { ComboAction* ca = new ComboAction(); for (int i=0;iclips.at(selected_clips.at(i)); + Clip* c = olive::ActiveSequence->clips.at(selected_clips.at(i)).get(); if ((c->track() < 0) == (effect_menu_subtype == EFFECT_TYPE_VIDEO)) { const EffectMeta* meta = reinterpret_cast(q->data().value()); if (effect_menu_type == EFFECT_TYPE_TRANSITION) { @@ -148,7 +148,7 @@ void EffectControls::copy(bool del) { ComboAction* ca = new ComboAction(); EffectDeleteCommand* del_com = (del) ? new EffectDeleteCommand() : nullptr; for (int i=0;iclips.at(selected_clips.at(i)); + Clip* c = olive::ActiveSequence->clips.at(selected_clips.at(i)).get(); for (int j=0;jeffects.size();j++) { EffectPtr effect = c->effects.at(j); if (effect->container->selected) { @@ -566,7 +566,7 @@ void EffectControls::delete_effects() { if (mode == kTransitionNone) { EffectDeleteCommand* command = new EffectDeleteCommand(); for (int i=0;iclips.at(selected_clips.at(i)); + Clip* c = olive::ActiveSequence->clips.at(selected_clips.at(i)).get(); for (int j=0;jeffects.size();j++) { EffectPtr effect = c->effects.at(j); if (effect->container->selected) { diff --git a/panels/panels.cpp b/panels/panels.cpp index 08f1c3427..1d87a8c2f 100644 --- a/panels/panels.cpp +++ b/panels/panels.cpp @@ -50,7 +50,7 @@ void update_effect_controls() { int mode = kTransitionNone; if (olive::ActiveSequence != nullptr) { for (int i=0;iclips.size();i++) { - ClipPtr clip = olive::ActiveSequence->clips.at(i); + Clip* clip = olive::ActiveSequence->clips.at(i).get(); if (clip != nullptr) { for (int j=0;jselections.size();j++) { const Selection& s = olive::ActiveSequence->selections.at(j); diff --git a/panels/timeline.cpp b/panels/timeline.cpp index 3ee07a16e..bef7ffd3b 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -54,6 +54,10 @@ #include #include +int olive::timeline::kTrackDefaultHeight = 40; +int olive::timeline::kTrackMinHeight = 30; +int olive::timeline::kTrackHeightIncrement = 10; + Timeline::Timeline(QWidget *parent) : Panel(parent), cursor_frame(0), @@ -301,7 +305,7 @@ void Timeline::add_clips_from_ghosts(ComboAction* ca, SequencePtr s) { earliest_point = qMin(earliest_point, g.in); - ClipPtr c = ClipPtr(new Clip(s)); + ClipPtr c = std::make_shared(s); c->set_media(g.media, g.media_stream); c->set_timeline_in(g.in); c->set_timeline_out(g.out); @@ -345,11 +349,11 @@ void Timeline::add_clips_from_ghosts(ComboAction* ca, SequencePtr s) { if (olive::CurrentConfig.add_default_effects_to_clips) { if (c->track() < 0) { // add default video effects - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TRANSFORM, EFFECT_TYPE_EFFECT))); + c->effects.append(create_effect(c.get(), get_internal_meta(EFFECT_INTERNAL_TRANSFORM, EFFECT_TYPE_EFFECT))); } else { // add default audio effects - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_VOLUME, EFFECT_TYPE_EFFECT))); - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_PAN, EFFECT_TYPE_EFFECT))); + c->effects.append(create_effect(c.get(), get_internal_meta(EFFECT_INTERNAL_VOLUME, EFFECT_TYPE_EFFECT))); + c->effects.append(create_effect(c.get(), get_internal_meta(EFFECT_INTERNAL_PAN, EFFECT_TYPE_EFFECT))); } } } @@ -366,7 +370,7 @@ void Timeline::add_transition() { bool adding = false; for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); + Clip* c = olive::ActiveSequence->clips.at(i).get(); if (c != nullptr && is_clip_selected(c, true)) { int transition_to_add = (c->track() < 0) ? TRANSITION_INTERNAL_CROSSDISSOLVE : TRANSITION_INTERNAL_LINEARFADE; if (c->opening_transition == nullptr) { @@ -404,7 +408,7 @@ void Timeline::nest() { // get selected clips for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); + Clip* c = olive::ActiveSequence->clips.at(i).get(); if (c != nullptr && is_clip_selected(c, true)) { selected_clips.append(i); earliest_point = qMin(c->timeline_in(), earliest_point); @@ -658,7 +662,7 @@ void Timeline::toggle_enable_on_selected_clips() { bool push_undo = false; for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); + Clip* c = olive::ActiveSequence->clips.at(i).get(); if (c != nullptr && is_clip_selected(c, true)) { set_action->AddSetting(c, !c->enabled()); push_undo = true; @@ -824,7 +828,7 @@ void Timeline::DecreaseTrackHeight() { repaint_timeline(); } -bool is_clip_selected(ClipPtr clip, bool containing) { +bool is_clip_selected(Clip *clip, bool containing) { for (int i=0;isequence->selections.size();i++) { const Selection& s = clip->sequence->selections.at(i); if (clip->track() == s.track && ((clip->timeline_in() >= s.in && clip->timeline_out() <= s.out && containing) || @@ -845,7 +849,7 @@ ClipPtr Timeline::split_clip(ComboAction* ca, bool transitions, int p, long fram } ClipPtr Timeline::split_clip(ComboAction* ca, bool transitions, int p, long frame, long post_in) { - ClipPtr pre = olive::ActiveSequence->clips.at(p); + Clip* pre = olive::ActiveSequence->clips.at(p).get(); if (pre != nullptr) { if (pre->timeline_in() < frame && pre->timeline_out() > frame) { @@ -858,7 +862,7 @@ ClipPtr Timeline::split_clip(ComboAction* ca, bool transitions, int p, long fram post->set_timeline_in(post_in); post->set_clip_in(pre->clip_in() + (post->timeline_in() - pre->timeline_in())); - move_clip(ca, pre, pre->timeline_in(), frame, pre->clip_in(), pre->track(), false); + pre->move(ca, pre->timeline_in(), frame, pre->clip_in(), pre->track(), false); if (transitions) { @@ -925,7 +929,7 @@ bool Timeline::split_clip_and_relink(ComboAction *ca, int clip, long frame, bool split_cache.append(clip); - ClipPtr c = olive::ActiveSequence->clips.at(clip); + Clip* c = olive::ActiveSequence->clips.at(clip).get(); if (c != nullptr) { QVector pre_clips; QVector post_clips; @@ -947,7 +951,7 @@ bool Timeline::split_clip_and_relink(ComboAction *ca, int clip, long frame, bool for (int i=0;ilinked.size();i++) { int l = c->linked.at(i); if (!split_cache.contains(l)) { - ClipPtr link = olive::ActiveSequence->clips.at(l); + Clip* link = olive::ActiveSequence->clips.at(l).get(); if ((original_clip_is_selected && is_clip_selected(link, true)) || !original_clip_is_selected) { split_cache.append(l); ClipPtr s = split_clip(ca, true, l, frame); @@ -998,7 +1002,7 @@ void Timeline::clean_up_selections(QVector& areas) { } } -bool selection_contains_transition(const Selection& s, ClipPtr c, int type) { +bool selection_contains_transition(const Selection& s, Clip* c, int type) { if (type == kTransitionOpening) { return c->opening_transition != nullptr && s.out == c->timeline_in() + c->opening_transition->get_true_length() @@ -1022,7 +1026,7 @@ void Timeline::delete_areas_and_relink(ComboAction* ca, QVector& area for (int i=0;iclips.size();j++) { - ClipPtr c = olive::ActiveSequence->clips.at(j); + Clip* c = olive::ActiveSequence->clips.at(j).get(); if (c != nullptr && c->track() == s.track && !c->undeletable) { if (selection_contains_transition(s, c, kTransitionOpening)) { // delete opening transition @@ -1043,7 +1047,7 @@ void Timeline::delete_areas_and_relink(ComboAction* ca, QVector& area post_clips.append(post); } else if (c->timeline_in() < s.in && c->timeline_out() > s.in) { // only out point is in deletion area - move_clip(ca, c, c->timeline_in(), s.in, c->clip_in(), c->track()); + c->move(ca, c->timeline_in(), s.in, c->clip_in(), c->track()); if (c->closing_transition != nullptr) { if (s.in < c->timeline_out() - c->closing_transition->get_true_length()) { @@ -1054,7 +1058,7 @@ void Timeline::delete_areas_and_relink(ComboAction* ca, QVector& area } } else if (c->timeline_in() < s.out && c->timeline_out() > s.out) { // only in point is in deletion area - move_clip(ca, c, s.out, c->timeline_out(), c->clip_in() + (s.out - c->timeline_in()), c->track()); + c->move(ca, s.out, c->timeline_out(), c->clip_in() + (s.out - c->timeline_in()), c->track()); if (c->opening_transition != nullptr) { if (s.out > c->timeline_in() + c->opening_transition->get_true_length()) { @@ -1236,7 +1240,7 @@ void Timeline::paste(bool insert) { bool ask_conflict = true; for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); + Clip* c = olive::ActiveSequence->clips.at(i).get(); if (c != nullptr && is_clip_selected(c, true)) { for (int j=0;j(clipboard.at(j)); @@ -1405,7 +1409,9 @@ void Timeline::edit_to_point_internal(bool in, bool ripple) { update_ui(true); - if (seek != olive::ActiveSequence->playhead && ripple) panel_sequence_viewer->seek(seek); + if (seek != olive::ActiveSequence->playhead && ripple) { + panel_sequence_viewer->seek(seek); + } } else { delete ca; } @@ -1484,7 +1490,7 @@ void Timeline::split_at_playhead() { QVector pre_clips; QVector post_clips; for (int j=0;jclips.size();j++) { - ClipPtr clip = olive::ActiveSequence->clips.at(j); + Clip* clip = olive::ActiveSequence->clips.at(j).get(); if (clip != nullptr && is_clip_selected(clip, true)) { ClipPtr s = split_clip(ca, true, j, olive::ActiveSequence->playhead); if (s != nullptr) { @@ -1626,7 +1632,7 @@ void Timeline::set_marker() { bool clip_mode = false; for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); + Clip* c = olive::ActiveSequence->clips.at(i).get(); if (c != nullptr && is_clip_selected(c, true)) { @@ -1681,7 +1687,7 @@ void Timeline::toggle_links() { LinkCommand* command = new LinkCommand(); command->s = olive::ActiveSequence; for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); + Clip* c = olive::ActiveSequence->clips.at(i).get(); if (c != nullptr && is_clip_selected(c, true)) { if (!command->clips.contains(i)) command->clips.append(i); @@ -2034,38 +2040,6 @@ void Timeline::setup_ui() { setWidget(dockWidgetContents); } -void move_clip(ComboAction* ca, ClipPtr c, long iin, long iout, long iclip_in, int itrack, bool verify_transitions, bool relative) { - ca->append(new MoveClipAction(c, iin, iout, iclip_in, itrack, relative)); - - if (verify_transitions) { - - // if this is a shared transition, and the corresponding clip will be moved away somehow - if (c->opening_transition != nullptr - && c->opening_transition->secondary_clip != nullptr - && c->opening_transition->secondary_clip->timeline_out() != iin) { - // separate transition - ca->append(new SetPointer(reinterpret_cast(&c->opening_transition->secondary_clip), nullptr)); - ca->append(new AddTransitionCommand(nullptr, - c->opening_transition->secondary_clip, - c->opening_transition, - nullptr, - 0)); - } - - if (c->closing_transition != nullptr - && c->closing_transition->secondary_clip != nullptr - && c->closing_transition->parent_clip->timeline_in() != iout) { - // separate transition - ca->append(new SetPointer(reinterpret_cast(&c->closing_transition->secondary_clip), nullptr)); - ca->append(new AddTransitionCommand(nullptr, - c, - c->closing_transition, - nullptr, - 0)); - } - } -} - void Timeline::set_tool() { QPushButton* button = static_cast(sender()); decheck_tool_buttons(button); @@ -2083,3 +2057,12 @@ void Timeline::set_tool() { timeline_area->setCursor(Qt::ArrowCursor); } } + +void olive::timeline::MultiplyTrackSizesByDPI() +{ + qDebug() << QApplication::desktop()->devicePixelRatio(); + + kTrackDefaultHeight *= QApplication::desktop()->devicePixelRatio(); + kTrackMinHeight *= QApplication::desktop()->devicePixelRatio(); + kTrackHeightIncrement *= QApplication::desktop()->devicePixelRatio(); +} diff --git a/panels/timeline.h b/panels/timeline.h index 5a8a7a1bb..1408bc7cb 100644 --- a/panels/timeline.h +++ b/panels/timeline.h @@ -50,11 +50,31 @@ enum TrimType { TRIM_OUT }; -bool is_clip_selected(ClipPtr clip, bool containing); +namespace olive { + namespace timeline { + const int kGhostThickness = 2; + const int kClipTextPadding = 3; + + /** + * @brief Set default track sizes + * + * Olive has a few default constants used for adjusting track heights in the Timeline. For HiDPI, it makes + * sense to multiply these by the current DPI scale. It uses a variable from QApplication to do this multiplication, + * which means the QApplication instance needs to be instantiated before these are calculated. Therefore, call this + * function ONCE after QApplication is created to multiply the track heights correctly. + */ + void MultiplyTrackSizesByDPI(); + + extern int kTrackDefaultHeight; + extern int kTrackMinHeight; + extern int kTrackHeightIncrement; + } +} + +bool is_clip_selected(Clip* clip, bool containing); int getScreenPointFromFrame(double zoom, long frame); long getFrameFromScreenPoint(double zoom, int x); -bool selection_contains_transition(const Selection& s, ClipPtr c, int type); -void move_clip(ComboAction *ca, ClipPtr c, long iin, long iout, long iclip_in, int itrack, bool verify_transitions = true, bool relative = false); +bool selection_contains_transition(const Selection& s, Clip *c, int type); void ripple_clips(ComboAction *ca, SequencePtr s, long point, long length, const QVector& ignore = QVector()); struct Ghost { diff --git a/panels/viewer.cpp b/panels/viewer.cpp index a188221db..f4c268c25 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -448,7 +448,7 @@ void Viewer::pause() { panel_project->process_file_list(file_list); // add it to the sequence - ClipPtr c = ClipPtr(new Clip(seq)); + ClipPtr c = std::make_shared(seq); Media* m = panel_project->last_imported_media.at(0); FootagePtr f = m->to_footage(); @@ -745,7 +745,7 @@ void Viewer::set_media(Media* m) { seq->height = video_stream.video_height; if (video_stream.video_frame_rate > 0 && !video_stream.infinite_length) seq->frame_rate = video_stream.video_frame_rate * footage->speed; - ClipPtr c = ClipPtr(new Clip(seq)); + ClipPtr c = std::make_shared(seq); c->set_media(media, video_stream.file_index); c->set_timeline_in(0); c->set_timeline_out(footage->get_length_in_frames(seq->frame_rate)); @@ -765,7 +765,7 @@ void Viewer::set_media(Media* m) { const FootageStream& audio_stream = footage->audio_tracks.at(0); seq->audio_frequency = audio_stream.audio_frequency; - ClipPtr c = ClipPtr(new Clip(seq)); + ClipPtr c = std::make_shared(seq); c->set_media(media, audio_stream.file_index); c->set_timeline_in(0); c->set_timeline_out(footage->get_length_in_frames(seq->frame_rate)); diff --git a/project/clip.cpp b/project/clip.cpp index fcd00860f..9e5b1b8b1 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -40,7 +40,7 @@ const int kRGBAComponentCount = 4; Clip::Clip(SequencePtr s) : sequence(s), - cacher(ClipPtr(this)) + cacher(this) { enabled_ = true; clip_in_ = 0; @@ -63,7 +63,7 @@ Clip::Clip(SequencePtr s) : } ClipPtr Clip::copy(SequencePtr s) { - ClipPtr copy(new Clip(s)); + ClipPtr copy = std::make_shared(s); copy->set_enabled(enabled()); copy->set_name(name()); @@ -78,7 +78,7 @@ ClipPtr Clip::copy(SequencePtr s) { copy->set_reversed(reversed()); for (int i=0;ieffects.append(effects.at(i)->copy(copy)); + copy->effects.append(effects.at(i)->copy(copy.get())); } copy->set_cached_frame_rate((this->sequence == nullptr) ? cached_frame_rate() : this->sequence->frame_rate); @@ -153,6 +153,39 @@ void Clip::set_enabled(bool e) enabled_ = e; } +void Clip::move(ComboAction* ca, long iin, long iout, long iclip_in, int itrack, bool verify_transitions, bool relative) +{ + ca->append(new MoveClipAction(this, iin, iout, iclip_in, itrack, relative)); + + if (verify_transitions) { + + // if this is a shared transition, and the corresponding clip will be moved away somehow + if (opening_transition != nullptr + && opening_transition->secondary_clip != nullptr + && opening_transition->secondary_clip->timeline_out() != iin) { + // separate transition + ca->append(new SetPointer(reinterpret_cast(&opening_transition->secondary_clip), nullptr)); + ca->append(new AddTransitionCommand(nullptr, + opening_transition->secondary_clip, + opening_transition, + nullptr, + 0)); + } + + if (closing_transition != nullptr + && closing_transition->secondary_clip != nullptr + && closing_transition->parent_clip->timeline_in() != iout) { + // separate transition + ca->append(new SetPointer(reinterpret_cast(&closing_transition->secondary_clip), nullptr)); + ca->append(new AddTransitionCommand(nullptr, + this, + closing_transition, + nullptr, + 0)); + } + } +} + void Clip::reset() { texture = nullptr; } @@ -395,11 +428,11 @@ int Clip::media_height() { void Clip::refactor_frame_rate(ComboAction* ca, double multiplier, bool change_timeline_points) { if (change_timeline_points) { - move_clip(ca, ClipPtr(this), - qRound(double(timeline_in_) * multiplier), - qRound(double(timeline_out_) * multiplier), - qRound(double(clip_in_) * multiplier), - track_); + this->move(ca, + qRound(double(timeline_in_) * multiplier), + qRound(double(timeline_out_) * multiplier), + qRound(double(clip_in_) * multiplier), + track_); } // move keyframes @@ -485,7 +518,7 @@ bool Clip::IsOpen() return open_; } -void Clip::Cache(long playhead, bool scrubbing, QVector& nests, int playback_speed) { +void Clip::Cache(long playhead, bool scrubbing, QVector& nests, int playback_speed) { // qint64 time = QDateTime::currentMSecsSinceEpoch(); cacher.Cache(playhead, scrubbing, nests, playback_speed); @@ -542,7 +575,7 @@ bool Clip::Retrieve() memcpy(data_buffer_1, frame->data[0], frame_size); } - e->process_image(get_timecode(ClipPtr(this), cacher_frame), + e->process_image(get_timecode(this, cacher_frame), using_db_1 ? data_buffer_1 : data_buffer_2, using_db_1 ? data_buffer_2 : data_buffer_1, frame_size diff --git a/project/clip.h b/project/clip.h index ac7a0038a..db2bf6c11 100644 --- a/project/clip.h +++ b/project/clip.h @@ -53,7 +53,7 @@ using ClipPtr = std::shared_ptr; class Sequence; using SequencePtr = std::shared_ptr; -class Clip { +class Clip : public std::enable_shared_from_this { public: Clip(SequencePtr s); ~Clip(); @@ -77,6 +77,14 @@ public: bool enabled(); void set_enabled(bool e); + void move(ComboAction* ca, + long iin, + long iout, + long iclip_in, + int itrack, + bool verify_transitions = true, + bool relative = false); + long clip_in(bool with_transition = false); void set_clip_in(long c); @@ -126,7 +134,7 @@ public: // playback functions void Open(); - void Cache(long playhead, bool scrubbing, QVector &nests, int playback_speed); + void Cache(long playhead, bool scrubbing, QVector &nests, int playback_speed); bool Retrieve(); void Close(bool wait); bool IsOpen(); diff --git a/project/comboaction.cpp b/project/comboaction.cpp index 825c28262..e0d9be038 100644 --- a/project/comboaction.cpp +++ b/project/comboaction.cpp @@ -31,5 +31,10 @@ void ComboAction::append(QUndoCommand* u) { } void ComboAction::appendPost(QUndoCommand* u) { - post_commands.append(u); + post_commands.append(u); +} + +bool ComboAction::hasActions() +{ + return commands.size() > 0; } diff --git a/project/comboaction.h b/project/comboaction.h index 7d3edbf65..083e82b6d 100644 --- a/project/comboaction.h +++ b/project/comboaction.h @@ -73,6 +73,14 @@ public: * The PostAction to add */ void appendPost(QUndoCommand* u); + + /** + * @brief Returns whether actions have been appended or not + * + * @return **TRUE** if actions have been appended, **FALSE** if not. + */ + bool hasActions(); + private: /** * @brief Internal array of QUndoCommand objects diff --git a/project/effect.cpp b/project/effect.cpp index 9f565fca8..4fba79c72 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -69,7 +69,7 @@ QVector effects; -EffectPtr create_effect(ClipPtr c, const EffectMeta* em) { +EffectPtr create_effect(Clip* c, const EffectMeta* em) { if (em->internal >= 0 && em->internal < EFFECT_INTERNAL_COUNT) { // must be an internal effect switch (em->internal) { @@ -112,7 +112,7 @@ const EffectMeta* get_internal_meta(int internal_id, int type) { return nullptr; } -Effect::Effect(ClipPtr c, const EffectMeta *em) : +Effect::Effect(Clip* c, const EffectMeta *em) : parent_clip(c), meta(em), enable_shader(false), @@ -854,7 +854,7 @@ void Effect::setIterations(int i) { void Effect::process_image(double, uint8_t *, uint8_t *, int){} -EffectPtr Effect::copy(ClipPtr c) { +EffectPtr Effect::copy(Clip *c) { EffectPtr copy = create_effect(c, meta); copy->set_enabled(is_enabled()); copy_field_keyframes(copy); diff --git a/project/effect.h b/project/effect.h index 0b83b7f3b..6c7fffe24 100644 --- a/project/effect.h +++ b/project/effect.h @@ -49,114 +49,114 @@ class Effect; using EffectPtr = std::shared_ptr; struct EffectMeta { - QString name; - QString category; - QString filename; - QString path; - QString tooltip; - int internal; - int type; - int subtype; + QString name; + QString category; + QString filename; + QString path; + QString tooltip; + int internal; + int type; + int subtype; }; extern QVector effects; double log_volume(double linear); -EffectPtr create_effect(ClipPtr c, const EffectMeta *em); +EffectPtr create_effect(Clip *c, const EffectMeta *em); const EffectMeta* get_internal_meta(int internal_id, int type); enum EffectType { - EFFECT_TYPE_INVALID, - EFFECT_TYPE_VIDEO, - EFFECT_TYPE_AUDIO, - EFFECT_TYPE_EFFECT, - EFFECT_TYPE_TRANSITION + EFFECT_TYPE_INVALID, + EFFECT_TYPE_VIDEO, + EFFECT_TYPE_AUDIO, + EFFECT_TYPE_EFFECT, + EFFECT_TYPE_TRANSITION }; enum EffectKeyframeType { - EFFECT_KEYFRAME_LINEAR, - EFFECT_KEYFRAME_BEZIER, - EFFECT_KEYFRAME_HOLD + EFFECT_KEYFRAME_LINEAR, + EFFECT_KEYFRAME_BEZIER, + EFFECT_KEYFRAME_HOLD }; enum EffectInternal { - EFFECT_INTERNAL_TRANSFORM, - EFFECT_INTERNAL_TEXT, - EFFECT_INTERNAL_SOLID, - EFFECT_INTERNAL_NOISE, - EFFECT_INTERNAL_VOLUME, - EFFECT_INTERNAL_PAN, - EFFECT_INTERNAL_TONE, - EFFECT_INTERNAL_SHAKE, - EFFECT_INTERNAL_TIMECODE, - EFFECT_INTERNAL_MASK, - EFFECT_INTERNAL_FILLLEFTRIGHT, - EFFECT_INTERNAL_VST, - EFFECT_INTERNAL_CORNERPIN, - EFFECT_INTERNAL_FREI0R, - EFFECT_INTERNAL_COUNT + EFFECT_INTERNAL_TRANSFORM, + EFFECT_INTERNAL_TEXT, + EFFECT_INTERNAL_SOLID, + EFFECT_INTERNAL_NOISE, + EFFECT_INTERNAL_VOLUME, + EFFECT_INTERNAL_PAN, + EFFECT_INTERNAL_TONE, + EFFECT_INTERNAL_SHAKE, + EFFECT_INTERNAL_TIMECODE, + EFFECT_INTERNAL_MASK, + EFFECT_INTERNAL_FILLLEFTRIGHT, + EFFECT_INTERNAL_VST, + EFFECT_INTERNAL_CORNERPIN, + EFFECT_INTERNAL_FREI0R, + EFFECT_INTERNAL_COUNT }; enum EffectBlendMode { - BLEND_MODE_ADD, - BLEND_MODE_AVERAGE, - BLEND_MODE_COLORBURN, - BLEND_MODE_COLORDODGE, - BLEND_MODE_DARKEN, - BLEND_MODE_DIFFERENCE, - BLEND_MODE_EXCLUSION, - BLEND_MODE_GLOW, - BLEND_MODE_HARDLIGHT, - BLEND_MODE_HARDMIX, - BLEND_MODE_LIGHTEN, - BLEND_MODE_LINEARBURN, - BLEND_MODE_LINEARDODGE, - BLEND_MODE_LINEARLIGHT, - BLEND_MODE_MULTIPLY, - BLEND_MODE_NEGATION, - BLEND_MODE_NORMAL, - BLEND_MODE_OVERLAY, - BLEND_MODE_PHOENIX, - BLEND_MODE_PINLIGHT, - BLEND_MODE_REFLECT, - BLEND_MODE_SCREEN, - BLEND_MODE_SOFTLIGHT, - BLEND_MODE_SUBSTRACT, - BLEND_MODE_SUBTRACT, - BLEND_MODE_VIVIDLIGHT, - BLEND_MODE_COUNT + BLEND_MODE_ADD, + BLEND_MODE_AVERAGE, + BLEND_MODE_COLORBURN, + BLEND_MODE_COLORDODGE, + BLEND_MODE_DARKEN, + BLEND_MODE_DIFFERENCE, + BLEND_MODE_EXCLUSION, + BLEND_MODE_GLOW, + BLEND_MODE_HARDLIGHT, + BLEND_MODE_HARDMIX, + BLEND_MODE_LIGHTEN, + BLEND_MODE_LINEARBURN, + BLEND_MODE_LINEARDODGE, + BLEND_MODE_LINEARLIGHT, + BLEND_MODE_MULTIPLY, + BLEND_MODE_NEGATION, + BLEND_MODE_NORMAL, + BLEND_MODE_OVERLAY, + BLEND_MODE_PHOENIX, + BLEND_MODE_PINLIGHT, + BLEND_MODE_REFLECT, + BLEND_MODE_SCREEN, + BLEND_MODE_SOFTLIGHT, + BLEND_MODE_SUBSTRACT, + BLEND_MODE_SUBTRACT, + BLEND_MODE_VIVIDLIGHT, + BLEND_MODE_COUNT }; struct GLTextureCoords { - int grid_size; + int grid_size; - int vertexTopLeftX; - int vertexTopLeftY; - int vertexTopLeftZ; - int vertexTopRightX; - int vertexTopRightY; - int vertexTopRightZ; - int vertexBottomLeftX; - int vertexBottomLeftY; - int vertexBottomLeftZ; - int vertexBottomRightX; - int vertexBottomRightY; - int vertexBottomRightZ; + int vertexTopLeftX; + int vertexTopLeftY; + int vertexTopLeftZ; + int vertexTopRightX; + int vertexTopRightY; + int vertexTopRightZ; + int vertexBottomLeftX; + int vertexBottomLeftY; + int vertexBottomLeftZ; + int vertexBottomRightX; + int vertexBottomRightY; + int vertexBottomRightZ; - float textureTopLeftX; - float textureTopLeftY; - float textureTopLeftQ; - float textureTopRightX; - float textureTopRightY; - float textureTopRightQ; - float textureBottomRightX; - float textureBottomRightY; - float textureBottomRightQ; - float textureBottomLeftX; - float textureBottomLeftY; - float textureBottomLeftQ; + float textureTopLeftX; + float textureTopLeftY; + float textureTopLeftQ; + float textureTopRightX; + float textureTopRightY; + float textureTopRightQ; + float textureBottomRightX; + float textureBottomRightY; + float textureBottomRightQ; + float textureBottomLeftX; + float textureBottomLeftY; + float textureBottomLeftQ; - int blendmode; - float opacity; + int blendmode; + float opacity; }; const EffectMeta* get_meta_from_name(const QString& input); @@ -168,114 +168,114 @@ qint16 mix_audio_sample(qint16 a, qint16 b); #include "effectgizmo.h" class Effect : public QObject { - Q_OBJECT + Q_OBJECT public: - Effect(ClipPtr c, const EffectMeta* em); - ~Effect(); - ClipPtr parent_clip; - const EffectMeta* meta; - int id; - QString name; - CollapsibleWidget* container; + Effect(Clip *c, const EffectMeta* em); + ~Effect(); + Clip* parent_clip; + const EffectMeta* meta; + int id; + QString name; + CollapsibleWidget* container; - EffectRow* add_row(const QString &name, bool savable = true, bool keyframable = true); - EffectRow* row(int i); - int row_count(); + EffectRow* add_row(const QString &name, bool savable = true, bool keyframable = true); + EffectRow* row(int i); + int row_count(); - EffectGizmo* add_gizmo(int type); - EffectGizmo* gizmo(int i); - int gizmo_count(); + EffectGizmo* add_gizmo(int type); + EffectGizmo* gizmo(int i); + int gizmo_count(); - bool is_enabled(); - void set_enabled(bool b); + bool is_enabled(); + void set_enabled(bool b); - virtual void refresh(); + virtual void refresh(); - virtual EffectPtr copy(ClipPtr c); - void copy_field_keyframes(EffectPtr e); + virtual EffectPtr copy(Clip* c); + void copy_field_keyframes(EffectPtr e); - virtual void load(QXmlStreamReader& stream); - virtual void custom_load(QXmlStreamReader& stream); - virtual void save(QXmlStreamWriter& stream); + virtual void load(QXmlStreamReader& stream); + virtual void custom_load(QXmlStreamReader& stream); + virtual void save(QXmlStreamWriter& stream); - void load_from_string(const QByteArray &s); - QByteArray save_to_string(); + void load_from_string(const QByteArray &s); + QByteArray save_to_string(); - // glsl handling - bool is_open(); - void open(); - void close(); - bool is_glsl_linked(); - virtual void startEffect(); - virtual void endEffect(); + // glsl handling + bool is_open(); + void open(); + void close(); + bool is_glsl_linked(); + virtual void startEffect(); + virtual void endEffect(); - bool enable_shader; - bool enable_coords; - bool enable_superimpose; - bool enable_image; + bool enable_shader; + bool enable_coords; + bool enable_superimpose; + bool enable_image; - int getIterations(); - void setIterations(int i); + int getIterations(); + void setIterations(int i); - const char* ffmpeg_filter; + const char* ffmpeg_filter; - virtual void process_image(double timecode, uint8_t* input, uint8_t* output, int size); - virtual void process_shader(double timecode, GLTextureCoords&, int iteration); - virtual void process_coords(double timecode, GLTextureCoords& coords, int data); - virtual GLuint process_superimpose(double timecode); - virtual void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); + virtual void process_image(double timecode, uint8_t* input, uint8_t* output, int size); + virtual void process_shader(double timecode, GLTextureCoords&, int iteration); + virtual void process_coords(double timecode, GLTextureCoords& coords, int data); + virtual GLuint process_superimpose(double timecode); + virtual void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); - virtual void gizmo_draw(double timecode, GLTextureCoords& coords); - void gizmo_move(EffectGizmo* sender, int x_movement, int y_movement, double timecode, bool done); - void gizmo_world_to_screen(); - bool are_gizmos_enabled(); + virtual void gizmo_draw(double timecode, GLTextureCoords& coords); + void gizmo_move(EffectGizmo* sender, int x_movement, int y_movement, double timecode, bool done); + void gizmo_world_to_screen(); + bool are_gizmos_enabled(); public slots: - void field_changed(); + void field_changed(); private slots: - void show_context_menu(const QPoint&); - void delete_self(); - void move_up(); - void move_down(); - void save_to_file(); - void load_from_file(); + void show_context_menu(const QPoint&); + void delete_self(); + void move_up(); + void move_down(); + void save_to_file(); + void load_from_file(); protected: - // glsl effect - QOpenGLShaderProgram* glslProgram; - QString vertPath; - QString fragPath; + // glsl effect + QOpenGLShaderProgram* glslProgram; + QString vertPath; + QString fragPath; - // superimpose effect - QImage img; - QOpenGLTexture* texture; + // superimpose effect + QImage img; + QOpenGLTexture* texture; - // enable effect to update constantly - bool enable_always_update; + // enable effect to update constantly + bool enable_always_update; private: - // superimpose effect - QString script; + // superimpose effect + QString script; - bool isOpen; - QVector rows; - QVector gizmos; - QGridLayout* ui_layout; - QWidget* ui; - bool bound; - int iterations; + bool isOpen; + QVector rows; + QVector gizmos; + QGridLayout* ui_layout; + QWidget* ui; + bool bound; + int iterations; - // superimpose functions - virtual void redraw(double timecode); - bool valueHasChanged(double timecode); - QVector cachedValues; - void delete_texture(); - int get_index_in_clip(); - void validate_meta_path(); + // superimpose functions + virtual void redraw(double timecode); + bool valueHasChanged(double timecode); + QVector cachedValues; + void delete_texture(); + int get_index_in_clip(); + void validate_meta_path(); }; class EffectInit : public QThread { public: - EffectInit(); + EffectInit(); protected: - void run(); + void run(); }; #endif // EFFECT_H diff --git a/project/effectrow.cpp b/project/effectrow.cpp index 2401b5d45..11ef3f23f 100644 --- a/project/effectrow.cpp +++ b/project/effectrow.cpp @@ -116,7 +116,7 @@ void EffectRow::set_keyframe_enabled(bool enabled) { void EffectRow::goto_previous_key() { long key = LONG_MIN; - ClipPtr c = parent_effect->parent_clip; + Clip* c = parent_effect->parent_clip; for (int i=0;ikeyframes.size();j++) { @@ -132,7 +132,7 @@ void EffectRow::goto_previous_key() { void EffectRow::toggle_key() { QVector key_fields; QVector key_field_index; - ClipPtr c = parent_effect->parent_clip; + Clip* c = parent_effect->parent_clip; for (int j=0;jkeyframes.size();i++) { @@ -159,7 +159,7 @@ void EffectRow::toggle_key() { void EffectRow::goto_next_key() { long key = LONG_MAX; - ClipPtr c = parent_effect->parent_clip; + Clip* c = parent_effect->parent_clip; for (int i=0;ikeyframes.size();j++) { diff --git a/project/transition.cpp b/project/transition.cpp index a34097ea0..1940429cc 100644 --- a/project/transition.cpp +++ b/project/transition.cpp @@ -41,7 +41,7 @@ #include #include -Transition::Transition(ClipPtr c, ClipPtr s, const EffectMeta* em) : +Transition::Transition(Clip *c, Clip *s, const EffectMeta* em) : Effect(c, em), secondary_clip(s), length(30) { @@ -55,7 +55,7 @@ Transition::Transition(ClipPtr c, ClipPtr s, const EffectMeta* em) : length_ui_ele->set_frame_rate(parent_clip->sequence == nullptr ? parent_clip->cached_frame_rate() : parent_clip->sequence->frame_rate); } -TransitionPtr Transition::copy(ClipPtr c, ClipPtr s) { +TransitionPtr Transition::copy(Clip *c, Clip *s) { return create_transition(c, s, meta, length); } @@ -80,7 +80,7 @@ long Transition::get_length() { return length; } -ClipPtr Transition::get_opened_clip() { +Clip* Transition::get_opened_clip() { if (parent_clip->opening_transition.get() == this) { return parent_clip; } else if (secondary_clip != nullptr && secondary_clip->opening_transition.get() == this) { @@ -89,7 +89,7 @@ ClipPtr Transition::get_opened_clip() { return nullptr; } -ClipPtr Transition::get_closed_clip() { +Clip* Transition::get_closed_clip() { if (parent_clip->closing_transition.get() == this) { return parent_clip; } else if (secondary_clip != nullptr && secondary_clip->closing_transition.get() == this) { @@ -103,7 +103,7 @@ void Transition::set_length_from_slider() { update_ui(false); } -TransitionPtr get_transition_from_meta(ClipPtr c, ClipPtr s, const EffectMeta* em) { +TransitionPtr get_transition_from_meta(Clip* c, Clip* s, const EffectMeta* em) { if (!em->filename.isEmpty()) { // load effect from file return TransitionPtr(new Transition(c, s, em)); @@ -126,7 +126,7 @@ TransitionPtr get_transition_from_meta(ClipPtr c, ClipPtr s, const EffectMeta* e return nullptr; } -TransitionPtr create_transition(ClipPtr c, ClipPtr s, const EffectMeta* em, long length) { +TransitionPtr create_transition(Clip* c, Clip* s, const EffectMeta* em, long length) { TransitionPtr t(get_transition_from_meta(c, s, em)); if (t != nullptr) { if (length > 0) { diff --git a/project/transition.h b/project/transition.h index ec6352398..6da299a91 100644 --- a/project/transition.h +++ b/project/transition.h @@ -41,16 +41,16 @@ enum TransitionInternal { class Transition; using TransitionPtr = std::shared_ptr; -TransitionPtr get_transition_from_meta(ClipPtr c, ClipPtr s, const EffectMeta* em); +TransitionPtr get_transition_from_meta(Clip *c, Clip *s, const EffectMeta* em); -TransitionPtr create_transition(ClipPtr c, ClipPtr s, const EffectMeta* em, long length = 0); +TransitionPtr create_transition(Clip* c, Clip* s, const EffectMeta* em, long length = 0); class Transition : public Effect { Q_OBJECT public: - Transition(ClipPtr c, ClipPtr s, const EffectMeta* em); - virtual TransitionPtr copy(ClipPtr c, ClipPtr s); - ClipPtr secondary_clip; + Transition(Clip* c, Clip* s, const EffectMeta* em); + virtual TransitionPtr copy(Clip* c, Clip* s); + Clip* secondary_clip; virtual void save(QXmlStreamWriter& stream) override; @@ -58,8 +58,8 @@ public: long get_true_length(); long get_length(); - ClipPtr get_opened_clip(); - ClipPtr get_closed_clip(); + Clip* get_opened_clip(); + Clip* get_closed_clip(); private slots: void set_length_from_slider(); private: diff --git a/project/undo.cpp b/project/undo.cpp index efcd57569..9a7e1f2e9 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -50,7 +50,7 @@ QUndoStack olive::UndoStack; -MoveClipAction::MoveClipAction(ClipPtr c, long iin, long iout, long iclip_in, int itrack, bool irelative) { +MoveClipAction::MoveClipAction(Clip *c, long iin, long iout, long iclip_in, int itrack, bool irelative) { clip = c; old_in = c->timeline_in(); @@ -192,7 +192,7 @@ void SetTimelineInOutCommand::doRedo() { } } -AddEffectCommand::AddEffectCommand(ClipPtr c, EffectPtr e, const EffectMeta *m, int insert_pos) { +AddEffectCommand::AddEffectCommand(Clip* c, EffectPtr e, const EffectMeta *m, int insert_pos) { clip = c; ref = e; meta = m; @@ -222,8 +222,8 @@ void AddEffectCommand::doRedo() { done = true; } -AddTransitionCommand::AddTransitionCommand(ClipPtr iopen, - ClipPtr iclose, +AddTransitionCommand::AddTransitionCommand(Clip* iopen, + Clip* iclose, TransitionPtr copy, const EffectMeta *itransition, int ilength) { @@ -247,8 +247,8 @@ void AddTransitionCommand::doUndo() { void AddTransitionCommand::doRedo() { // convert open/close clips to primary/secondary for transition object - ClipPtr primary = open_; - ClipPtr secondary = close_; + Clip* primary = open_; + Clip* secondary = close_; if (primary == nullptr) { primary = secondary; secondary = nullptr; @@ -596,7 +596,7 @@ EffectDeleteCommand::~EffectDeleteCommand() {} void EffectDeleteCommand::doUndo() { for (int i=0;ieffects.insert(fx.at(i), deleted_objects.at(i)); } panel_effect_controls->reload_clips(); @@ -607,7 +607,7 @@ void EffectDeleteCommand::doUndo() { void EffectDeleteCommand::doRedo() { deleted_objects.clear(); for (int i=0;ieffects.at(fx_id); e->close(); @@ -689,7 +689,7 @@ void EffectFieldUndo::doRedo() { SetClipProperty::SetClipProperty(SetClipPropertyType type) : type_(type) {} -void SetClipProperty::AddSetting(ClipPtr c, bool setting) +void SetClipProperty::AddSetting(Clip* c, bool setting) { clips_.append(c); setting_.append(setting); @@ -829,7 +829,7 @@ void DeleteMarkerAction::doRedo() { sorted = true; } -SetSpeedAction::SetSpeedAction(ClipPtr c, double speed) { +SetSpeedAction::SetSpeedAction(Clip* c, double speed) { clip = c; old_speed = c->speed().value; new_speed = speed; @@ -1005,20 +1005,19 @@ void RemoveClipsFromClipboard::doRedo() { done = true; } -RenameClipCommand::RenameClipCommand() {} +RenameClipCommand::RenameClipCommand(Clip *clip, QString new_name) +{ + clip_ = clip; + old_name_ = clip_->name(); + new_name_ = new_name; +} void RenameClipCommand::doUndo() { - for (int i=0;iset_name(old_names.at(i)); - } + clip_->set_name(old_name_); } void RenameClipCommand::doRedo() { - old_names.resize(clips.size()); - for (int i=0;iname(); - clips.at(i)->set_name(new_name); - } + clip_->set_name(new_name_); } SetPointer::SetPointer(void **pointer, void *data) { @@ -1062,7 +1061,7 @@ void RippleAction::doRedo() { ClipPtr c = s->clips.at(i); if (c != nullptr) { if (c->timeline_in() >= point) { - move_clip(ca, c, length, length, 0, 0, true, true); + c->move(ca, length, length, 0, 0, true, true); } } } diff --git a/project/undo.h b/project/undo.h index 16507b148..029d3445f 100644 --- a/project/undo.h +++ b/project/undo.h @@ -63,11 +63,11 @@ private: class MoveClipAction : public OliveAction { public: - MoveClipAction(ClipPtr c, long iin, long iout, long iclip_in, int itrack, bool irelative); + MoveClipAction(Clip* c, long iin, long iout, long iclip_in, int itrack, bool irelative); virtual void doUndo() override; virtual void doRedo() override; private: - ClipPtr clip; + Clip* clip; long old_in; long old_out; @@ -125,11 +125,11 @@ private: class AddEffectCommand : public OliveAction { public: - AddEffectCommand(ClipPtr c, EffectPtr e, const EffectMeta* m, int insert_pos = -1); + AddEffectCommand(Clip* c, EffectPtr e, const EffectMeta* m, int insert_pos = -1); virtual void doUndo() override; virtual void doRedo() override; private: - ClipPtr clip; + Clip* clip; const EffectMeta* meta; EffectPtr ref; int pos; @@ -138,12 +138,12 @@ private: class AddTransitionCommand : public OliveAction { public: - AddTransitionCommand(ClipPtr iopen, ClipPtr iclose, TransitionPtr copy, const EffectMeta* itransition, int ilength); + AddTransitionCommand(Clip* iopen, Clip* iclose, TransitionPtr copy, const EffectMeta* itransition, int ilength); virtual void doUndo() override; virtual void doRedo() override; private: - ClipPtr open_; - ClipPtr close_; + Clip* open_; + Clip* close_; TransitionPtr transition_to_copy_; const EffectMeta* transition_meta_; int length_; @@ -170,8 +170,8 @@ public: virtual void doRedo() override; private: TransitionPtr transition_ref_; - ClipPtr opened_clip_; - ClipPtr closed_clip_; + Clip* opened_clip_; + Clip* closed_clip_; }; class SetTimelineInOutCommand : public OliveAction { @@ -295,7 +295,7 @@ public: virtual ~EffectDeleteCommand() override; virtual void doUndo() override; virtual void doRedo() override; - QVector clips; + QVector clips; QVector fx; private: bool done; @@ -374,10 +374,10 @@ public: SetClipProperty(SetClipPropertyType type); virtual void doUndo() override; virtual void doRedo() override; - void AddSetting(ClipPtr c, bool setting); + void AddSetting(Clip *c, bool setting); private: SetClipPropertyType type_; - QVector clips_; + QVector clips_; QVector setting_; QVector old_setting_; void MainLoop(bool undo); @@ -421,11 +421,11 @@ private: class SetSpeedAction : public OliveAction { public: - SetSpeedAction(ClipPtr c, double speed); + SetSpeedAction(Clip* c, double speed); virtual void doUndo() override; virtual void doRedo() override; private: - ClipPtr clip; + Clip* clip; double old_speed; double new_speed; }; @@ -542,7 +542,7 @@ public: MoveEffectCommand(); virtual void doUndo() override; virtual void doRedo() override; - ClipPtr clip; + Clip* clip; int from; int to; }; @@ -561,13 +561,13 @@ private: class RenameClipCommand : public OliveAction { public: - RenameClipCommand(); - QVector clips; - QString new_name; + RenameClipCommand(Clip* clip, QString new_name); virtual void doUndo() override; virtual void doRedo() override; private: - QVector old_names; + QString old_name_; + QString new_name_; + Clip* clip_; }; class SetPointer : public OliveAction { diff --git a/rendering/cacher.cpp b/rendering/cacher.cpp index 8081dc228..2c4055372 100644 --- a/rendering/cacher.cpp +++ b/rendering/cacher.cpp @@ -42,7 +42,7 @@ double bytes_to_seconds(int nb_bytes, int nb_channels, int sample_rate) { return (double(nb_bytes >> 1) / nb_channels / sample_rate); } -void apply_audio_effects(ClipPtr clip, double timecode_start, AVFrame* frame, int nb_bytes, QVector nests) { +void apply_audio_effects(Clip* clip, double timecode_start, AVFrame* frame, int nb_bytes, QVector nests) { // perform all audio effects double timecode_end; timecode_end = timecode_start + bytes_to_seconds(nb_bytes, frame->channels, frame->sample_rate); @@ -78,7 +78,7 @@ void apply_audio_effects(ClipPtr clip, double timecode_start, AVFrame* frame, in } if (!nests.isEmpty()) { - ClipPtr next_nest = nests.last(); + Clip* next_nest = nests.last(); nests.removeLast(); apply_audio_effects(next_nest, timecode_start + (double(clip->timeline_in(true)-clip->clip_in(true))/clip->sequence->frame_rate), @@ -735,7 +735,7 @@ void Cacher::WakeMainThread() main_thread_lock_.unlock(); } -Cacher::Cacher(ClipPtr c) : clip(c) {} +Cacher::Cacher(Clip* c) : clip(c) {} void Cacher::OpenWorker() { qint64 time_start = QDateTime::currentMSecsSinceEpoch(); @@ -1048,7 +1048,7 @@ void Cacher::Open() start((clip->track() < 0) ? QThread::HighPriority : QThread::TimeCriticalPriority); } -void Cacher::Cache(long playhead, bool scrubbing, QVector& nests, int playback_speed) +void Cacher::Cache(long playhead, bool scrubbing, QVector& nests, int playback_speed) { if (clip->media_stream()->infinite_length && queue.size() > 0) { retrieved_frame = queue.at(0); diff --git a/rendering/cacher.h b/rendering/cacher.h index 4b9848335..e8d100852 100644 --- a/rendering/cacher.h +++ b/rendering/cacher.h @@ -42,7 +42,6 @@ extern "C" { #include "rendering/clipqueue.h" class Clip; -using ClipPtr = std::shared_ptr; /** * @brief The Cacher class @@ -106,7 +105,7 @@ public: * * @param c */ - Cacher(ClipPtr c); + Cacher(Clip* c); /** * @brief The main QThread loop @@ -158,7 +157,7 @@ public: * * The current playback speed (controlled by Shuttle Left/Stop/Right) */ - void Cache(long playhead, bool scrubbing, QVector& nests, int playback_speed); + void Cache(long playhead, bool scrubbing, QVector& nests, int playback_speed); /** * @brief Retrieve frame requested by Cache() @@ -257,7 +256,7 @@ private: /** * @brief Reference to the parent clip. Set in the constructor and never changed during this object's lifetime. */ - ClipPtr clip; + Clip* clip; /** * @brief Frame queue @@ -327,7 +326,7 @@ private: /** * @brief Current nested Sequence hierarchy set by Cache() */ - QVector nests_; + QVector nests_; /** * @brief Signal cache to continue operation after one cycle rather than wait for another signal diff --git a/rendering/renderfunctions.cpp b/rendering/renderfunctions.cpp index 9ccb3d827..f62112913 100644 --- a/rendering/renderfunctions.cpp +++ b/rendering/renderfunctions.cpp @@ -106,7 +106,7 @@ GLuint draw_clip(QOpenGLFramebufferObject* fbo, GLuint texture, bool clear) { return fbo->texture(); } -void process_effect(ClipPtr c, +void process_effect(Clip* c, EffectPtr e, double timecode, GLTextureCoords& coords, @@ -178,12 +178,12 @@ GLuint compose_sequence(ComposeSequenceParams ¶ms) { int audio_track_count = 0; - QVector current_clips; + QVector current_clips; // loop through clips, find currently active, and sort by track for (int i=0;iclips.size();i++) { - ClipPtr c = s->clips.at(i); + Clip* c = s->clips.at(i).get(); if (c != nullptr) { @@ -284,7 +284,7 @@ GLuint compose_sequence(ComposeSequenceParams ¶ms) { // loop through current clips for (int i=0;isequence->frame_rate; } -long playhead_to_clip_frame(ClipPtr c, long playhead) { +long playhead_to_clip_frame(Clip* c, long playhead) { return (qMax(0L, playhead - c->timeline_in(true)) + c->clip_in(true)); } -double playhead_to_clip_seconds(ClipPtr c, long playhead) { +double playhead_to_clip_seconds(Clip* c, long playhead) { // returns time in seconds long clip_frame = playhead_to_clip_frame(c, playhead); @@ -707,18 +707,18 @@ double playhead_to_clip_seconds(ClipPtr c, long playhead) { return secs; } -int64_t seconds_to_timestamp(ClipPtr c, double seconds) { +int64_t seconds_to_timestamp(Clip *c, double seconds) { return qRound64(seconds * av_q2d(av_inv_q(c->time_base()))); } -int64_t playhead_to_timestamp(ClipPtr c, long playhead) { +int64_t playhead_to_timestamp(Clip* c, long playhead) { return seconds_to_timestamp(c, playhead_to_clip_seconds(c, playhead)); } void close_active_clips(SequencePtr s) { if (s != nullptr) { for (int i=0;iclips.size();i++) { - ClipPtr c = s->clips.at(i); + Clip* c = s->clips.at(i).get(); if (c != nullptr) { c->Close(true); } diff --git a/rendering/renderfunctions.h b/rendering/renderfunctions.h index f733c560a..411191e95 100644 --- a/rendering/renderfunctions.h +++ b/rendering/renderfunctions.h @@ -67,7 +67,7 @@ struct ComposeSequenceParams { * Should be left empty. This array gets passed around compose_sequence() as it calls itself recursively to * handle nested sequences. */ - QVector nests; + QVector nests; /** * @brief Set compose mode to video or audio @@ -307,7 +307,7 @@ long rescale_frame_number(long framenumber, double source_frame_rate, double tar * * Timecode in seconds */ -double get_timecode(ClipPtr c, long playhead); +double get_timecode(Clip *c, long playhead); /** * @brief Convert playhead frame number to a clip frame number @@ -327,7 +327,7 @@ double get_timecode(ClipPtr c, long playhead); * * The curren frame number of the clip at `playhead` */ -long playhead_to_clip_frame(ClipPtr c, long playhead); +long playhead_to_clip_frame(Clip* c, long playhead); /** * @brief Converts the playhead to clip seconds @@ -348,7 +348,7 @@ long playhead_to_clip_frame(ClipPtr c, long playhead); * * Clip time in seconds */ -double playhead_to_clip_seconds(ClipPtr c, long playhead); +double playhead_to_clip_seconds(Clip *c, long playhead); /** * @brief Convert seconds to FFmpeg timestamp @@ -368,7 +368,7 @@ double playhead_to_clip_seconds(ClipPtr c, long playhead); * * An FFmpeg-compatible timestamp in AVStream->time_base units. */ -int64_t seconds_to_timestamp(ClipPtr c, double seconds); +int64_t seconds_to_timestamp(Clip* c, double seconds); /** * @brief Convert Timeline playhead to FFmpeg timestamp @@ -388,7 +388,7 @@ int64_t seconds_to_timestamp(ClipPtr c, double seconds); * * An FFmpeg-compatible timestamp in AVStream->time_base units. */ -int64_t playhead_to_timestamp(ClipPtr c, long playhead); +int64_t playhead_to_timestamp(Clip *c, long playhead); /** * @brief Close all open clips in a Sequence diff --git a/ui/keyframeview.cpp b/ui/keyframeview.cpp index 0ecfbbe84..fcca08c26 100644 --- a/ui/keyframeview.cpp +++ b/ui/keyframeview.cpp @@ -376,7 +376,7 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) { if (panel_timeline->snapping) { for (int i=0;iparent_row->parent_effect->parent_clip; + Clip* c = field->parent_row->parent_effect->parent_clip; long key_time = old_key_vals.at(i) + frame_diff - c->clip_in() + c->timeline_in(); long key_eval = key_time; if (panel_timeline->snap_to_point(olive::ActiveSequence->playhead, &key_eval)) { diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 2641f96dc..59b853e4b 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -38,6 +38,7 @@ #include "ui/cursors.h" #include "ui/menuhelper.h" #include "ui/focusfilter.h" +#include "dialogs/clippropertiesdialog.h" #include "debug.h" #include "project/effect.h" @@ -100,9 +101,9 @@ void TimelineWidget::show_context_menu(const QPoint& pos) { menu.addSeparator(); // collect all the selected clips - QVector selected_clips; + QVector selected_clips; for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); + Clip* c = olive::ActiveSequence->clips.at(i).get(); if (c != nullptr && is_clip_selected(c, true)) { selected_clips.append(c); } @@ -175,8 +176,7 @@ void TimelineWidget::show_context_menu(const QPoint& pos) { connect(revealInProjectAction, SIGNAL(triggered(bool)), this, SLOT(reveal_media())); } - QAction* rename = menu.addAction(tr("R&ename")); - connect(rename, SIGNAL(triggered(bool)), this, SLOT(rename_clip())); + menu.addAction(tr("Properties"), this, SLOT(show_clip_properties())); } menu.exec(mapToGlobal(pos)); @@ -188,7 +188,7 @@ void TimelineWidget::toggle_autoscale() { bool added_clip = false; for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); + Clip* c = olive::ActiveSequence->clips.at(i).get(); if (c != nullptr && is_clip_selected(c, true)) { action->AddSetting(c, !c->autoscaled()); added_clip = true; @@ -219,32 +219,6 @@ void TimelineWidget::tooltip_timer_timeout() { tooltip_timer.stop(); } -void TimelineWidget::rename_clip() { - QVector selected_clips; - for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); - if (c != nullptr && is_clip_selected(c, true)) { - selected_clips.append(c); - } - } - if (selected_clips.size() > 0) { - QString s = QInputDialog::getText(this, - (selected_clips.size() == 1) ? tr("Rename '%1'").arg(selected_clips.at(0)->name()) - : tr("Rename multiple clips"), - tr("Enter a new name for this clip:"), - QLineEdit::Normal, - selected_clips.at(0)->name() - ); - if (!s.isEmpty()) { - RenameClipCommand* rcc = new RenameClipCommand(); - rcc->new_name = s; - rcc->clips = selected_clips; - olive::UndoStack.push(rcc); - update_ui(true); - } - } -} - void TimelineWidget::open_sequence_properties() { QList sequence_items; QList all_top_level_items; @@ -262,6 +236,24 @@ void TimelineWidget::open_sequence_properties() { QMessageBox::critical(this, tr("Error"), tr("Couldn't locate media wrapper for sequence.")); } +void TimelineWidget::show_clip_properties() +{ + // get list of selected clips + QVector selected_clips; + for (int i=0;iclips.size();i++) { + Clip* c = olive::ActiveSequence->clips.at(i).get(); + if (c != nullptr && is_clip_selected(c, true)) { + selected_clips.append(c); + } + } + + // if clips are selected, open the clip properties dialog + if (selected_clips.size() > 0) { + ClipPropertiesDialog cpd(this, selected_clips); + cpd.exec(); + } +} + bool same_sign(int a, int b) { return (a < 0) == (b < 0); } @@ -669,7 +661,7 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) { // check if we're currently hovering over a clip or not if (hovered_clip >= 0) { - ClipPtr clip = olive::ActiveSequence->clips.at(hovered_clip); + Clip* clip = olive::ActiveSequence->clips.at(hovered_clip).get(); if (is_clip_selected(clip, true)) { @@ -771,7 +763,7 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) { for (int i=0;ilinked.size();i++) { - ClipPtr link = olive::ActiveSequence->clips.at(clip->linked.at(i)); + Clip* link = olive::ActiveSequence->clips.at(clip->linked.at(i)).get(); // check if the clip is already selected if (!is_clip_selected(link, true)) { @@ -854,7 +846,7 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) { } void make_room_for_transition(ComboAction* ca, - ClipPtr c, + Clip* c, int type, long transition_start, long transition_end, @@ -895,7 +887,7 @@ void make_room_for_transition(ComboAction* ca, } } -void VerifyTransitionsAfterCreating(ComboAction* ca, ClipPtr open, ClipPtr close, long transition_start, long transition_end) { +void VerifyTransitionsAfterCreating(ComboAction* ca, Clip* open, Clip* close, long transition_start, long transition_end) { // in case the user made the transition larger than the clips, we're going to delete everything under // the transition ghost and extend the clips to the transition's coordinates as necessary @@ -939,7 +931,7 @@ void VerifyTransitionsAfterCreating(ComboAction* ca, ClipPtr open, ClipPtr close // loop through both kinds of transition for (int t=kTransitionOpening;t<=kTransitionClosing;t++) { - ClipPtr clip_ref = (t == kTransitionOpening) ? open : close; + Clip* clip_ref = (t == kTransitionOpening) ? open : close; // if we have an opening transition: if (clip_ref != nullptr) { @@ -975,12 +967,11 @@ void VerifyTransitionsAfterCreating(ComboAction* ca, ClipPtr open, ClipPtr close - move_clip(ca, - clip_ref, - new_in, - new_out, - clip_ref->clip_in() - (clip_ref->timeline_in() - new_in), - clip_ref->track()); + clip_ref->move(ca, + new_in, + new_out, + clip_ref->clip_in() - (clip_ref->timeline_in() - new_in), + clip_ref->track()); } } } @@ -1006,7 +997,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { panel_sequence_viewer->cue_recording(qMin(g.in, g.out), qMax(g.in, g.out), g.track); panel_timeline->creating = false; } else if (g.in != g.out) { - ClipPtr c = ClipPtr(new Clip(olive::ActiveSequence)); + ClipPtr c = std::make_shared(olive::ActiveSequence); c->set_media(nullptr, 0); c->set_timeline_in(qMin(g.in, g.out)); c->set_timeline_out(qMax(g.in, g.out)); @@ -1032,40 +1023,40 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { if (c->track() < 0 && olive::CurrentConfig.add_default_effects_to_clips) { // default video effects (before custom effects) - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TRANSFORM, EFFECT_TYPE_EFFECT))); + c->effects.append(create_effect(c.get(), get_internal_meta(EFFECT_INTERNAL_TRANSFORM, EFFECT_TYPE_EFFECT))); } switch (panel_timeline->creating_object) { case ADD_OBJ_TITLE: c->set_name(tr("Title")); - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TEXT, EFFECT_TYPE_EFFECT))); + c->effects.append(create_effect(c.get(), get_internal_meta(EFFECT_INTERNAL_TEXT, EFFECT_TYPE_EFFECT))); break; case ADD_OBJ_SOLID: c->set_name(tr("Solid Color")); - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_SOLID, EFFECT_TYPE_EFFECT))); + c->effects.append(create_effect(c.get(), get_internal_meta(EFFECT_INTERNAL_SOLID, EFFECT_TYPE_EFFECT))); break; case ADD_OBJ_BARS: { c->set_name(tr("Bars")); - EffectPtr e = create_effect(c, get_internal_meta(EFFECT_INTERNAL_SOLID, EFFECT_TYPE_EFFECT)); + EffectPtr e = create_effect(c.get(), get_internal_meta(EFFECT_INTERNAL_SOLID, EFFECT_TYPE_EFFECT)); e->row(0)->field(0)->set_combo_index(1); c->effects.append(e); } break; case ADD_OBJ_TONE: c->set_name(tr("Tone")); - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TONE, EFFECT_TYPE_EFFECT))); + c->effects.append(create_effect(c.get(), get_internal_meta(EFFECT_INTERNAL_TONE, EFFECT_TYPE_EFFECT))); break; case ADD_OBJ_NOISE: c->set_name(tr("Noise")); - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_NOISE, EFFECT_TYPE_EFFECT))); + c->effects.append(create_effect(c.get(), get_internal_meta(EFFECT_INTERNAL_NOISE, EFFECT_TYPE_EFFECT))); break; } if (c->track() >= 0 && olive::CurrentConfig.add_default_effects_to_clips) { // default audio effects (after custom effects) - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_VOLUME, EFFECT_TYPE_EFFECT))); - c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_PAN, EFFECT_TYPE_EFFECT))); + c->effects.append(create_effect(c.get(), get_internal_meta(EFFECT_INTERNAL_VOLUME, EFFECT_TYPE_EFFECT))); + c->effects.append(create_effect(c.get(), get_internal_meta(EFFECT_INTERNAL_PAN, EFFECT_TYPE_EFFECT))); } push_undo = true; @@ -1250,13 +1241,13 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { for (int i=0;ighosts.size();i++) { Ghost& g = panel_timeline->ghosts[i]; - ClipPtr c = olive::ActiveSequence->clips.at(g.clip); + Clip* c = olive::ActiveSequence->clips.at(g.clip).get(); if (g.transition == nullptr) { // if this was a clip rather than a transition - move_clip(ca, c, (g.in - g.old_in), (g.out - g.old_out), (g.clip_in - g.old_clip_in), (g.track - g.old_track), false, true); + c->move(ca, (g.in - g.old_in), (g.out - g.old_out), (g.clip_in - g.old_clip_in), (g.track - g.old_track), false, true); } else { @@ -1290,8 +1281,8 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { timeline_in_movement = g.in - g.transition->secondary_clip->timeline_in(); } - move_clip(ca, g.transition->parent_clip, movement, timeline_out_movement, movement, 0, false, true); - move_clip(ca, g.transition->secondary_clip, timeline_in_movement, movement, timeline_in_movement, 0, false, true); + g.transition->parent_clip->move(ca, movement, timeline_out_movement, movement, 0, false, true); + g.transition->secondary_clip->move(ca, timeline_in_movement, movement, timeline_in_movement, 0, false, true); make_room_for_transition(ca, g.transition->parent_clip, kTransitionOpening, g.in, g.out, false); make_room_for_transition(ca, g.transition->secondary_clip, kTransitionClosing, g.in, g.out, false); @@ -1309,7 +1300,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { timeline_out_movement = g.out - g.transition->parent_clip->timeline_out(); } - move_clip(ca, c, (g.in - g.old_in), timeline_out_movement, (g.clip_in - g.old_clip_in), 0, false, true); + c->move(ca, (g.in - g.old_in), timeline_out_movement, (g.clip_in - g.old_clip_in), 0, false, true); clip_length -= (g.in - g.old_in); } @@ -1326,7 +1317,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { } // if transition is going to make the clip bigger, make the clip bigger - move_clip(ca, c, timeline_in_movement, (g.out - g.old_out), timeline_in_movement, 0, false, true); + c->move(ca, timeline_in_movement, (g.out - g.old_out), timeline_in_movement, 0, false, true); clip_length += (g.out - g.old_out); } @@ -1378,13 +1369,13 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { // for a shared transition, the secondary_clip will always be the closing transition side and // the parent_clip will always be the opening transition side - ClipPtr search_clip = (t == kTransitionOpening) + Clip* search_clip = (t == kTransitionOpening) ? transition->secondary_clip : transition->parent_clip; for (int j=0;jghosts.size();j++) { const Ghost& other_clip_ghost = panel_timeline->ghosts.at(j); - if (olive::ActiveSequence->clips.at(other_clip_ghost.clip) == search_clip) { + if (olive::ActiveSequence->clips.at(other_clip_ghost.clip).get() == search_clip) { // we found the other clip in the current ghosts/selections @@ -1464,12 +1455,12 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { long transition_end = qMax(g.in, g.out); // get clip references from tool's cached data - ClipPtr open = (panel_timeline->transition_tool_open_clip > -1) - ? olive::ActiveSequence->clips.at(panel_timeline->transition_tool_open_clip) + Clip* open = (panel_timeline->transition_tool_open_clip > -1) + ? olive::ActiveSequence->clips.at(panel_timeline->transition_tool_open_clip).get() : nullptr; - ClipPtr close = (panel_timeline->transition_tool_close_clip > -1) - ? olive::ActiveSequence->clips.at(panel_timeline->transition_tool_close_clip) + Clip* close = (panel_timeline->transition_tool_close_clip > -1) + ? olive::ActiveSequence->clips.at(panel_timeline->transition_tool_close_clip).get() : nullptr; @@ -1585,7 +1576,7 @@ void TimelineWidget::init_ghosts() { } } -void validate_transitions(ClipPtr c, int transition_type, long& frame_diff) { +void validate_transitions(Clip* c, int transition_type, long& frame_diff) { long validator; if (transition_type == kTransitionOpening) { @@ -1676,8 +1667,10 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { long temp_frame_diff = frame_diff; // cache to see if we change it (thus cancelling any snap) for (int i=0;ighosts.size();i++) { const Ghost& g = panel_timeline->ghosts.at(i); - ClipPtr c = nullptr; - if (g.clip != -1) c = olive::ActiveSequence->clips.at(g.clip); + Clip* c = nullptr; + if (g.clip != -1) { + c = olive::ActiveSequence->clips.at(g.clip).get(); + } const FootageStream* ms = nullptr; if (g.clip != -1 && c->media() != nullptr && c->media()->get_type() == MEDIA_TYPE_FOOTAGE) { @@ -1731,8 +1724,8 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { // prevent dual transition from going below 0 on the primary or media length on the secondary if (g.transition != nullptr && g.transition->secondary_clip != nullptr) { - ClipPtr otc = g.transition->parent_clip; - ClipPtr ctc = g.transition->secondary_clip; + Clip* otc = g.transition->parent_clip; + Clip* ctc = g.transition->secondary_clip; if (g.trim_type == TRIM_IN) { frame_diff -= g.transition->get_true_length(); @@ -1833,12 +1826,15 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) { || panel_timeline->transition_tool_close_clip == -1) { validate_transitions(c, g.media_stream, frame_diff); } else { - ClipPtr otc = olive::ActiveSequence->clips.at(panel_timeline->transition_tool_open_clip); // open transition clip - ClipPtr ctc = olive::ActiveSequence->clips.at(panel_timeline->transition_tool_close_clip); // close transition clip + // open transition clip + Clip* otc = olive::ActiveSequence->clips.at(panel_timeline->transition_tool_open_clip).get(); + + // close transition clip + Clip* ctc = olive::ActiveSequence->clips.at(panel_timeline->transition_tool_close_clip).get(); if (g.media_stream == kTransitionClosing) { // swap - ClipPtr temp = otc; + Clip* temp = otc; otc = ctc; ctc = temp; } @@ -2066,7 +2062,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { // find which clips are selected for (int j=0;jclips.size();j++) { - ClipPtr c = olive::ActiveSequence->clips.at(j); + Clip* c = olive::ActiveSequence->clips.at(j).get(); if (c != nullptr && is_clip_selected(c, false)) { @@ -2157,7 +2153,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { // loop through clips for any currently selected for (int i=0;iclips.size();i++) { - ClipPtr c = olive::ActiveSequence->clips.at(i); + Clip* c = olive::ActiveSequence->clips.at(i).get(); if (c != nullptr) { Ghost g; diff --git a/ui/timelinewidget.h b/ui/timelinewidget.h index 68983c1ac..00fce1c4d 100644 --- a/ui/timelinewidget.h +++ b/ui/timelinewidget.h @@ -37,17 +37,6 @@ class Timeline; -namespace olive { - namespace timeline { - const int kGhostThickness = 2; - const int kClipTextPadding = 3; - - const int kTrackDefaultHeight = 40/* * QApplication::desktop()->devicePixelRatio()*/; - const int kTrackMinHeight = 30; - const int kTrackHeightIncrement = 10; - } -} - struct TimelineTrackHeight { int index; int height; @@ -118,8 +107,8 @@ private slots: void show_context_menu(const QPoint& pos); void toggle_autoscale(); void tooltip_timer_timeout(); - void rename_clip(); void open_sequence_properties(); + void show_clip_properties(); }; #endif // TIMELINEWIDGET_H