SEVERAL bug fixes
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
#include "mediapropertiesdialog.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
#include <QDialogButtonBox>
|
||||
|
||||
#include "io/media.h"
|
||||
#include "panels/project.h"
|
||||
|
||||
MediaPropertiesDialog::MediaPropertiesDialog(QWidget *parent) {
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
|
||||
QGridLayout* grid = new QGridLayout();
|
||||
setLayout(grid);
|
||||
|
||||
interlacing_box = new QComboBox();
|
||||
interlacing_box->addItem(get_interlacing_name(VIDEO_PROGRESSIVE), VIDEO_PROGRESSIVE);
|
||||
interlacing_box->addItem(get_interlacing_name(VIDEO_TOP_FIELD_FIRST), VIDEO_TOP_FIELD_FIRST);
|
||||
interlacing_box->addItem(get_interlacing_name(VIDEO_BOTTOM_FIELD_FIRST), VIDEO_BOTTOM_FIELD_FIRST);
|
||||
|
||||
grid->addWidget(new QLabel("Interlacing:"), 0, 0);
|
||||
grid->addWidget(interlacing_box, 0, 1);
|
||||
|
||||
grid->addWidget(new QLabel("Name:"), 1, 0);
|
||||
grid->addWidget(new QLineEdit("h"), 1, 1);
|
||||
|
||||
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
buttons->setCenterButtons(true);
|
||||
grid->addWidget(buttons, 2, 0, 1, 2);
|
||||
|
||||
connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef MEDIAPROPERTIESDIALOG_H
|
||||
#define MEDIAPROPERTIESDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class QComboBox;
|
||||
|
||||
class MediaPropertiesDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MediaPropertiesDialog(QWidget *parent = 0);
|
||||
private:
|
||||
QComboBox* interlacing_box;
|
||||
};
|
||||
|
||||
#endif // MEDIAPROPERTIESDIALOG_H
|
||||
@@ -15,6 +15,7 @@ extern "C" {
|
||||
|
||||
NewSequenceDialog::NewSequenceDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
existing_sequence(NULL),
|
||||
ui(new Ui::NewSequenceDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
@@ -51,20 +52,44 @@ void NewSequenceDialog::set_sequence_name(const QString& s) {
|
||||
ui->lineEdit->setText(s);
|
||||
}
|
||||
|
||||
void NewSequenceDialog::on_buttonBox_accepted()
|
||||
{
|
||||
Sequence* s = new Sequence();
|
||||
void NewSequenceDialog::showEvent(QShowEvent *) {
|
||||
if (existing_sequence != NULL) {
|
||||
ui->width_numeric->setValue(existing_sequence->width);
|
||||
ui->height_numeric->setValue(existing_sequence->height);
|
||||
int comp_rate = qRound(existing_sequence->frame_rate*100);
|
||||
for (int i=0;i<ui->frame_rate_combobox->count();i++) {
|
||||
if (qRound(ui->frame_rate_combobox->itemData(i).toDouble()*100) == comp_rate) {
|
||||
ui->frame_rate_combobox->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ui->lineEdit->setText(existing_sequence->name);
|
||||
for (int i=0;i<ui->audio_frequency_combobox->count();i++) {
|
||||
if (ui->audio_frequency_combobox->itemData(i) == existing_sequence->audio_frequency) {
|
||||
ui->audio_frequency_combobox->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NewSequenceDialog::on_buttonBox_accepted() {
|
||||
Sequence* s = (existing_sequence != NULL) ? existing_sequence : new Sequence();
|
||||
|
||||
s->name = ui->lineEdit->text();
|
||||
s->width = ui->width_numeric->value();
|
||||
s->height = ui->height_numeric->value();
|
||||
s->frame_rate = ui->frame_rate_combobox->currentData().toDouble();
|
||||
s->frame_rate = ui->frame_rate_combobox->currentData().toDouble();
|
||||
s->audio_frequency = ui->audio_frequency_combobox->currentData().toInt();
|
||||
s->audio_layout = AV_CH_LAYOUT_STEREO;
|
||||
|
||||
ComboAction* ca = new ComboAction();
|
||||
panel_project->new_sequence(ca, s, true, NULL);
|
||||
undo_stack.push(ca);
|
||||
if (existing_sequence == NULL) {
|
||||
ComboAction* ca = new ComboAction();
|
||||
panel_project->new_sequence(ca, s, true, NULL);
|
||||
undo_stack.push(ca);
|
||||
} else {
|
||||
// TODO make editing undoable
|
||||
}
|
||||
}
|
||||
|
||||
void NewSequenceDialog::on_comboBox_currentIndexChanged(int index)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <QDialog>
|
||||
|
||||
class Project;
|
||||
struct Sequence;
|
||||
|
||||
namespace Ui {
|
||||
class NewSequenceDialog;
|
||||
@@ -16,8 +17,12 @@ class NewSequenceDialog : public QDialog
|
||||
public:
|
||||
explicit NewSequenceDialog(QWidget *parent = 0);
|
||||
~NewSequenceDialog();
|
||||
Sequence* existing_sequence;
|
||||
void set_sequence_name(const QString& s);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *);
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_accepted();
|
||||
|
||||
|
||||
@@ -320,7 +320,8 @@ void set_speed(ComboAction* ca, Clip* c, double speed, bool ripple, long& ep, lo
|
||||
for (int j=0;j<e->row_count();j++) {
|
||||
EffectRow* r = e->row(j);
|
||||
for (int k=0;k<r->keyframe_times.size();k++) {
|
||||
long new_pos = r->keyframe_times.at(k) / speed;
|
||||
long new_pos = r->keyframe_times.at(k) * c->speed / speed;
|
||||
qDebug() << "old key" << r->keyframe_times.at(k) << "new key" << new_pos;
|
||||
KeyframeMove* km = new KeyframeMove();
|
||||
km->movement = new_pos - r->keyframe_times.at(k);
|
||||
km->rows.append(r);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "audionoiseeffect.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QtMath>
|
||||
|
||||
AudioNoiseEffect::AudioNoiseEffect(Clip* c) : Effect(c, EFFECT_TYPE_AUDIO, AUDIO_NOISE_EFFECT) {
|
||||
amount_val = add_row("Amount:")->add_field(EFFECT_FIELD_DOUBLE);
|
||||
@@ -26,11 +27,12 @@ void AudioNoiseEffect::process_audio(double timecode_start, double timecode_end,
|
||||
qint16 right_noise_sample = rand();
|
||||
|
||||
// set noise volume
|
||||
left_noise_sample *= amount_val->get_double_value(timecode)*0.01;
|
||||
right_noise_sample *= amount_val->get_double_value(timecode)*0.01;
|
||||
double vol = qSqrt(amount_val->get_double_value(timecode, true)*0.01);
|
||||
left_noise_sample *= vol;
|
||||
right_noise_sample *= vol;
|
||||
|
||||
// mix with source audio
|
||||
if (mix_val->get_bool_value(timecode)) {
|
||||
if (mix_val->get_bool_value(timecode, true)) {
|
||||
qint16 left_sample = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF));
|
||||
qint16 right_sample = (qint16) (((samples[i+3] & 0xFF) << 8) | (samples[i+2] & 0xFF));
|
||||
left_noise_sample = mix_audio_sample(left_noise_sample, left_sample);
|
||||
|
||||
@@ -23,17 +23,16 @@ PanEffect::PanEffect(Clip* c) : Effect(c, EFFECT_TYPE_AUDIO, AUDIO_PAN_EFFECT) {
|
||||
void PanEffect::process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int) {
|
||||
double interval = (timecode_end - timecode_start)/nb_bytes;
|
||||
for (int i=0;i<nb_bytes;i+=4) {
|
||||
double pval = pan_val->get_double_value(timecode_start+(interval*i));
|
||||
double pval = qSqrt(pan_val->get_double_value(timecode_start+(interval*i), true)*0.01);
|
||||
qint16 left_sample = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF));
|
||||
qint16 right_sample = (qint16) (((samples[i+3] & 0xFF) << 8) | (samples[i+2] & 0xFF));
|
||||
|
||||
double val = qPow(pval*0.01, 3);
|
||||
if (val < 0) {
|
||||
if (pval < 0) {
|
||||
// affect right channel
|
||||
right_sample *= (1-std::abs(val));
|
||||
right_sample *= (1-std::abs(pval));
|
||||
} else {
|
||||
// affect left channel
|
||||
left_sample *= (1-val);
|
||||
left_sample *= (1-pval);
|
||||
}
|
||||
|
||||
samples[i+3] = (quint8) (right_sample >> 8);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "project/clip.h"
|
||||
#include "project/sequence.h"
|
||||
|
||||
ToneEffect::ToneEffect(Clip* c) : Effect(c, EFFECT_TYPE_AUDIO, AUDIO_TONE_EFFECT), sinX(0) {
|
||||
ToneEffect::ToneEffect(Clip* c) : Effect(c, EFFECT_TYPE_AUDIO, AUDIO_TONE_EFFECT), sinX(INT_MIN) {
|
||||
type_val = add_row("Type:")->add_field(EFFECT_FIELD_COMBO);
|
||||
type_val->add_combo_item("Sine", TONE_TYPE_SINE);
|
||||
|
||||
@@ -34,12 +34,12 @@ void ToneEffect::process_audio(double timecode_start, double timecode_end, quint
|
||||
for (int i=0;i<nb_bytes;i+=4) {
|
||||
double timecode = timecode_start+(interval*i);
|
||||
|
||||
qint16 left_tone_sample = qSin((2*M_PI*sinX*freq_val->get_double_value(timecode))/parent_clip->sequence->audio_frequency)*(amount_val->get_double_value(timecode)*0.01)*INT16_MAX;
|
||||
qint16 left_tone_sample = qSin((2*M_PI*sinX*freq_val->get_double_value(timecode, true))/parent_clip->sequence->audio_frequency)*qSqrt((amount_val->get_double_value(timecode, true)*0.01))*INT16_MAX;
|
||||
qint16 right_tone_sample = left_tone_sample;
|
||||
|
||||
|
||||
// mix with source audio
|
||||
if (mix_val->get_bool_value(timecode)) {
|
||||
if (mix_val->get_bool_value(timecode, true)) {
|
||||
qint16 left_sample = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF));
|
||||
qint16 right_sample = (qint16) (((samples[i+3] & 0xFF) << 8) | (samples[i+2] & 0xFF));
|
||||
left_tone_sample = mix_audio_sample(left_tone_sample, left_sample);
|
||||
@@ -54,7 +54,7 @@ void ToneEffect::process_audio(double timecode_start, double timecode_end, quint
|
||||
int presin = sinX;
|
||||
sinX++;
|
||||
if (sinX < presin) {
|
||||
qDebug() << "overflowed";
|
||||
qDebug() << "[WARNING] Tone effect overflowed";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,9 @@ void VolumeEffect::process_audio(double timecode_start, double timecode_end, qui
|
||||
// qDebug() << timecode_start << timecode_end;
|
||||
double interval = (timecode_end-timecode_start)/nb_bytes;
|
||||
for (int i=0;i<nb_bytes;i+=2) {
|
||||
double vol_val = volume_val->get_double_value(timecode_start+(interval*i));
|
||||
// qDebug() << timecode_start+(interval*i);
|
||||
double vol_val = qSqrt(volume_val->get_double_value(timecode_start+(interval*i), true)*0.01);
|
||||
qint32 samp = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF));
|
||||
double val = qPow(vol_val*0.01, 3);
|
||||
samp *= val;
|
||||
samp *= vol_val;
|
||||
if (samp > INT16_MAX) {
|
||||
samp = INT16_MAX;
|
||||
} else if (samp < INT16_MIN) {
|
||||
|
||||
+58
-17
@@ -699,7 +699,7 @@ QVariant EffectField::get_current_data() {
|
||||
switch (type) {
|
||||
case EFFECT_FIELD_DOUBLE: return static_cast<LabelSlider*>(ui_element)->value(); break;
|
||||
case EFFECT_FIELD_COLOR: return static_cast<ColorButton*>(ui_element)->get_color(); break;
|
||||
case EFFECT_FIELD_STRING: return static_cast<TextEditEx*>(ui_element)->toPlainText(); break;
|
||||
case EFFECT_FIELD_STRING: return static_cast<TextEditEx*>(ui_element)->getPlainTextEx(); break;
|
||||
case EFFECT_FIELD_BOOL: return static_cast<QCheckBox*>(ui_element)->isChecked(); break;
|
||||
case EFFECT_FIELD_COMBO: return static_cast<ComboBoxEx*>(ui_element)->currentIndex(); break;
|
||||
case EFFECT_FIELD_FONT: return static_cast<FontCombobox*>(ui_element)->currentText(); break;
|
||||
@@ -765,8 +765,12 @@ void EffectField::get_keyframe_data(double timecode, int &before, int &after, do
|
||||
}
|
||||
}
|
||||
|
||||
void EffectField::validate_keyframe_data(double timecode) {
|
||||
if (parent_row->isKeyframing() && keyframe_data.size() > 0) {
|
||||
bool EffectField::hasKeyframes() {
|
||||
return (parent_row->isKeyframing() && keyframe_data.size() > 0);
|
||||
}
|
||||
|
||||
QVariant EffectField::validate_keyframe_data(double timecode, bool async) {
|
||||
if (hasKeyframes()) {
|
||||
int before_keyframe;
|
||||
int after_keyframe;
|
||||
double progress;
|
||||
@@ -784,7 +788,10 @@ void EffectField::validate_keyframe_data(double timecode) {
|
||||
double after_dbl = keyframe_data.at(after_keyframe).toDouble();
|
||||
value = double_lerp(before_dbl, after_dbl, progress);
|
||||
}
|
||||
static_cast<LabelSlider*>(ui_element)->set_value(value, false);
|
||||
if (async) {
|
||||
return value;
|
||||
}
|
||||
static_cast<LabelSlider*>(ui_element)->set_value(value, false);
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_COLOR:
|
||||
@@ -797,23 +804,39 @@ void EffectField::validate_keyframe_data(double timecode) {
|
||||
QColor after_data = keyframe_data.at(after_keyframe).value<QColor>();
|
||||
value = QColor(lerp(before_data.red(), after_data.red(), progress), lerp(before_data.green(), after_data.green(), progress), lerp(before_data.blue(), after_data.blue(), progress));
|
||||
}
|
||||
return static_cast<ColorButton*>(ui_element)->set_color(value);
|
||||
if (async) {
|
||||
return value;
|
||||
}
|
||||
static_cast<ColorButton*>(ui_element)->set_color(value);
|
||||
}
|
||||
break;
|
||||
case EFFECT_FIELD_STRING:
|
||||
if (async) {
|
||||
return before_data;
|
||||
}
|
||||
static_cast<TextEditEx*>(ui_element)->setPlainTextEx(before_data.toString());
|
||||
break;
|
||||
case EFFECT_FIELD_BOOL:
|
||||
static_cast<QCheckBox*>(ui_element)->setChecked(before_data.toBool());
|
||||
if (async) {
|
||||
return before_data;
|
||||
}
|
||||
static_cast<QCheckBox*>(ui_element)->setChecked(before_data.toBool());
|
||||
break;
|
||||
case EFFECT_FIELD_COMBO:
|
||||
static_cast<ComboBoxEx*>(ui_element)->setCurrentIndexEx(before_data.toInt());
|
||||
if (async) {
|
||||
return before_data;
|
||||
}
|
||||
static_cast<ComboBoxEx*>(ui_element)->setCurrentIndexEx(before_data.toInt());
|
||||
break;
|
||||
case EFFECT_FIELD_FONT:
|
||||
static_cast<FontCombobox*>(ui_element)->setCurrentTextEx(before_data.toString());
|
||||
if (async) {
|
||||
return before_data;
|
||||
}
|
||||
static_cast<FontCombobox*>(ui_element)->setCurrentTextEx(before_data.toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void EffectField::uiElementChange() {
|
||||
@@ -835,9 +858,12 @@ void EffectField::set_enabled(bool e) {
|
||||
ui_element->setEnabled(e);
|
||||
}
|
||||
|
||||
double EffectField::get_double_value(double timecode) {
|
||||
double EffectField::get_double_value(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).toDouble();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<LabelSlider*>(ui_element)->value();
|
||||
return static_cast<LabelSlider*>(ui_element)->value();
|
||||
}
|
||||
|
||||
void EffectField::set_double_value(double v) {
|
||||
@@ -860,7 +886,10 @@ void EffectField::add_combo_item(const QString& name, const QVariant& data) {
|
||||
static_cast<ComboBoxEx*>(ui_element)->addItem(name, data);
|
||||
}
|
||||
|
||||
int EffectField::get_combo_index(double timecode) {
|
||||
int EffectField::get_combo_index(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).toInt();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<ComboBoxEx*>(ui_element)->currentIndex();
|
||||
}
|
||||
@@ -883,7 +912,10 @@ void EffectField::set_combo_string(const QString& s) {
|
||||
static_cast<ComboBoxEx*>(ui_element)->setCurrentTextEx(s);
|
||||
}
|
||||
|
||||
bool EffectField::get_bool_value(double timecode) {
|
||||
bool EffectField::get_bool_value(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).toBool();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<QCheckBox*>(ui_element)->isChecked();
|
||||
}
|
||||
@@ -892,16 +924,22 @@ void EffectField::set_bool_value(bool b) {
|
||||
return static_cast<QCheckBox*>(ui_element)->setChecked(b);
|
||||
}
|
||||
|
||||
const QString EffectField::get_string_value(double timecode) {
|
||||
const QString EffectField::get_string_value(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).toString();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<TextEditEx*>(ui_element)->toPlainText();
|
||||
return static_cast<TextEditEx*>(ui_element)->getPlainTextEx();
|
||||
}
|
||||
|
||||
void EffectField::set_string_value(const QString& s) {
|
||||
static_cast<TextEditEx*>(ui_element)->setPlainTextEx(s);
|
||||
}
|
||||
|
||||
const QString EffectField::get_font_name(double timecode) {
|
||||
const QString EffectField::get_font_name(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).toString();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<FontCombobox*>(ui_element)->currentText();
|
||||
}
|
||||
@@ -910,7 +948,10 @@ void EffectField::set_font_name(const QString& s) {
|
||||
static_cast<FontCombobox*>(ui_element)->setCurrentText(s);
|
||||
}
|
||||
|
||||
QColor EffectField::get_color_value(double timecode) {
|
||||
QColor EffectField::get_color_value(double timecode, bool async) {
|
||||
if (async && hasKeyframes()) {
|
||||
return validate_keyframe_data(timecode, true).value<QColor>();
|
||||
}
|
||||
validate_keyframe_data(timecode);
|
||||
return static_cast<ColorButton*>(ui_element)->get_color();
|
||||
}
|
||||
|
||||
+8
-9
@@ -99,33 +99,31 @@ public:
|
||||
long timecodeToFrame(double timecode);
|
||||
void set_current_data(const QVariant&);
|
||||
void get_keyframe_data(double timecode, int& before, int& after, double& d);
|
||||
void validate_keyframe_data(double timecode);
|
||||
// QVariant get_keyframe_data(long p);
|
||||
// bool is_keyframed(long p);
|
||||
QVariant validate_keyframe_data(double timecode, bool async = false);
|
||||
|
||||
double get_double_value(double timecode);
|
||||
double get_double_value(double timecode, bool async = false);
|
||||
void set_double_value(double v);
|
||||
void set_double_default_value(double v);
|
||||
void set_double_minimum_value(double v);
|
||||
void set_double_maximum_value(double v);
|
||||
|
||||
const QString get_string_value(double timecode);
|
||||
const QString get_string_value(double timecode, bool async = false);
|
||||
void set_string_value(const QString &s);
|
||||
|
||||
void add_combo_item(const QString& name, const QVariant &data);
|
||||
int get_combo_index(double timecode);
|
||||
int get_combo_index(double timecode, bool async = false);
|
||||
const QVariant get_combo_data(double timecode);
|
||||
const QString get_combo_string(double timecode);
|
||||
void set_combo_index(int index);
|
||||
void set_combo_string(const QString& s);
|
||||
|
||||
bool get_bool_value(double timecode);
|
||||
bool get_bool_value(double timecode, bool async = false);
|
||||
void set_bool_value(bool b);
|
||||
|
||||
const QString get_font_name(double timecode);
|
||||
const QString get_font_name(double timecode, bool async = false);
|
||||
void set_font_name(const QString& s);
|
||||
|
||||
QColor get_color_value(double timecode);
|
||||
QColor get_color_value(double timecode, bool async = false);
|
||||
void set_color_value(QColor color);
|
||||
|
||||
QWidget* get_ui_element();
|
||||
@@ -133,6 +131,7 @@ public:
|
||||
QVector<QVariant> keyframe_data;
|
||||
QWidget* ui_element;
|
||||
private:
|
||||
bool hasKeyframes();
|
||||
private slots:
|
||||
void uiElementChange();
|
||||
signals:
|
||||
|
||||
+61
-4
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "media.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "panels/project.h"
|
||||
#include "io/config.h"
|
||||
|
||||
#include <QPainter>
|
||||
@@ -301,19 +302,20 @@ void PreviewGenerator::run() {
|
||||
char* filename = new char[ba.size()+1];
|
||||
strcpy(filename, ba.data());
|
||||
|
||||
QString errorStr;
|
||||
bool error = false;
|
||||
int errCode = avformat_open_input(&fmt_ctx, filename, NULL, NULL);
|
||||
if(errCode != 0) {
|
||||
char err[1024];
|
||||
av_strerror(errCode, err, 1024);
|
||||
item->setToolTip(0, "Could not open file - " + QString(err));
|
||||
errorStr = "Could not open file - " + QString(err);
|
||||
error = true;
|
||||
} else {
|
||||
errCode = avformat_find_stream_info(fmt_ctx, NULL);
|
||||
if (errCode < 0) {
|
||||
char err[1024];
|
||||
av_strerror(errCode, err, 1024);
|
||||
item->setToolTip(0, "Could not find stream information - " + QString(err));
|
||||
errorStr = "Could not find stream information - " + QString(err);
|
||||
error = true;
|
||||
} else {
|
||||
av_dump_format(fmt_ctx, 0, filename, 0);
|
||||
@@ -321,12 +323,67 @@ void PreviewGenerator::run() {
|
||||
generate_waveform();
|
||||
}
|
||||
avformat_close_input(&fmt_ctx);
|
||||
}
|
||||
}
|
||||
QString tooltip = "Name: " + media->name + "\nFilename: " + media->url + "\n";
|
||||
if (error) {
|
||||
tooltip += errorStr;
|
||||
emit set_icon(ICON_TYPE_ERROR, replace);
|
||||
} else {
|
||||
item->setToolTip(0, QString());
|
||||
// tooltip += "Video Tracks: " + QString::number(media->video_tracks.size()) + "\nAudio Tracks: " + QString::number(media->audio_tracks.size()) + "\n";
|
||||
|
||||
if (media->video_tracks.size() > 0) {
|
||||
tooltip += "Video Dimensions: ";
|
||||
for (int i=0;i<media->video_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += QString::number(media->video_tracks.at(i)->video_width) + "x" + QString::number(media->video_tracks.at(i)->video_height);
|
||||
}
|
||||
tooltip += "\n";
|
||||
|
||||
tooltip += "Frame Rate: ";
|
||||
for (int i=0;i<media->video_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += QString::number(media->video_tracks.at(i)->video_frame_rate);
|
||||
if (media->video_tracks.at(i)->video_interlacing != VIDEO_PROGRESSIVE) {
|
||||
tooltip += " fields (" + QString::number(media->video_tracks.at(i)->video_frame_rate*0.5) + " frames)";
|
||||
}
|
||||
}
|
||||
tooltip += "\n";
|
||||
|
||||
tooltip += "Interlacing: ";
|
||||
for (int i=0;i<media->video_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += get_interlacing_name(media->video_tracks.at(i)->video_interlacing);
|
||||
}
|
||||
tooltip += "\n";
|
||||
}
|
||||
|
||||
if (media->audio_tracks.size() > 0) {
|
||||
tooltip += "Audio Frequency: ";
|
||||
for (int i=0;i<media->audio_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += QString::number(media->audio_tracks.at(i)->audio_frequency);
|
||||
}
|
||||
tooltip += "\n";
|
||||
|
||||
tooltip += "Audio Channels: ";
|
||||
for (int i=0;i<media->audio_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += get_channel_layout_name(media->audio_tracks.at(i)->audio_channels, media->audio_tracks.at(i)->audio_layout);
|
||||
}
|
||||
// tooltip += "\n";
|
||||
}
|
||||
}
|
||||
item->setToolTip(0, tooltip);
|
||||
delete [] filename;
|
||||
media->preview_gen = NULL;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,8 @@ SOURCES += \
|
||||
dialogs/demonotice.cpp \
|
||||
effects/audio/toneeffect.cpp \
|
||||
project/marker.cpp \
|
||||
dialogs/speeddialog.cpp
|
||||
dialogs/speeddialog.cpp \
|
||||
dialogs/mediapropertiesdialog.cpp
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h \
|
||||
@@ -141,7 +142,8 @@ HEADERS += \
|
||||
project/marker.h \
|
||||
project/selection.h \
|
||||
dialogs/speeddialog.h \
|
||||
dialogs/speeddialog.h
|
||||
dialogs/speeddialog.h \
|
||||
dialogs/mediapropertiesdialog.h
|
||||
|
||||
FORMS += \
|
||||
mainwindow.ui \
|
||||
|
||||
+65
-2
@@ -18,6 +18,8 @@
|
||||
#include "playback/cacher.h"
|
||||
#include "dialogs/replaceclipmediadialog.h"
|
||||
#include "panels/effectcontrols.h"
|
||||
#include "dialogs/newsequencedialog.h"
|
||||
#include "dialogs/mediapropertiesdialog.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QString>
|
||||
@@ -28,6 +30,7 @@
|
||||
#include <QDropEvent>
|
||||
#include <QMimeData>
|
||||
#include <QPushButton>
|
||||
#include <QInputDialog>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
@@ -140,6 +143,39 @@ void Project::replace_clip_media() {
|
||||
}
|
||||
}
|
||||
|
||||
void Project::open_properties() {
|
||||
if (ui->treeWidget->selectedItems().size() == 1) {
|
||||
QTreeWidgetItem* item = ui->treeWidget->selectedItems().at(0);
|
||||
switch (get_type_from_tree(item)) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
{
|
||||
MediaPropertiesDialog mpd(this);
|
||||
mpd.exec();
|
||||
}
|
||||
break;
|
||||
case MEDIA_TYPE_SEQUENCE:
|
||||
{
|
||||
NewSequenceDialog nsd(this);
|
||||
Sequence* s = get_sequence_from_tree(item);
|
||||
nsd.existing_sequence = s;
|
||||
if (nsd.exec() == QDialog::Accepted) {
|
||||
set_sequence_of_tree(item, s);
|
||||
panel_timeline->repaint_timeline(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
// fall back to renaming
|
||||
QString new_name = QInputDialog::getText(this, "Rename '" + item->text(0) + "'", "Enter new name:");
|
||||
if (!new_name.isEmpty()) {
|
||||
item->setText(0, new_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Project::new_sequence(ComboAction *ca, Sequence *s, bool open, QTreeWidgetItem* parent) {
|
||||
QTreeWidgetItem* item = new_item();
|
||||
item->setText(0, s->name);
|
||||
@@ -521,9 +557,27 @@ Sequence* get_sequence_from_tree(QTreeWidgetItem* item) {
|
||||
return reinterpret_cast<Sequence*>(item->data(0, Qt::UserRole + 2).value<quintptr>());
|
||||
}
|
||||
|
||||
void set_sequence_of_tree(QTreeWidgetItem* item, Sequence* sequence) {
|
||||
QString get_channel_layout_name(int channels, int layout) {
|
||||
switch (channels) {
|
||||
case 0: return "Invalid"; break;
|
||||
case 1: return "Mono"; break;
|
||||
case 2: return "Stereo"; break;
|
||||
default: {
|
||||
char buf[50];
|
||||
av_get_channel_layout_string(buf, sizeof(buf), channels, layout);
|
||||
return QString(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_sequence_of_tree(QTreeWidgetItem* item, Sequence* s) {
|
||||
item->setData(0, Qt::UserRole + 1, MEDIA_TYPE_SEQUENCE);
|
||||
item->setData(0, Qt::UserRole + 2, QVariant::fromValue(reinterpret_cast<quintptr>(sequence)));
|
||||
item->setData(0, Qt::UserRole + 2, QVariant::fromValue(reinterpret_cast<quintptr>(s)));
|
||||
item->setToolTip(0, "Name: " + s->name
|
||||
+ "\nVideo Dimensions: " + QString::number(s->width) + "x" + QString::number(s->height)
|
||||
+ "\nFrame Rate: " + QString::number(s->frame_rate)
|
||||
+ "\nAudio Frequency: " + QString::number(s->audio_frequency)
|
||||
+ "\nAudio Layout: " + get_channel_layout_name(av_get_channel_layout_nb_channels(s->audio_layout), s->audio_layout));
|
||||
}
|
||||
|
||||
int get_type_from_tree(QTreeWidgetItem* item) {
|
||||
@@ -1294,3 +1348,12 @@ void MediaThrobber::stop(int icon_type, bool replace) {
|
||||
panel_project->source_table->viewport()->update();
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
QString get_interlacing_name(int interlacing) {
|
||||
switch (interlacing) {
|
||||
case VIDEO_PROGRESSIVE: return "None (Progressive)";
|
||||
case VIDEO_TOP_FIELD_FIRST: return "Top Field First";
|
||||
case VIDEO_BOTTOM_FIELD_FIRST: return "Bottom Field First";
|
||||
default: return "Invalid";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@ Sequence* get_sequence_from_tree(QTreeWidgetItem* item);
|
||||
void set_sequence_of_tree(QTreeWidgetItem* item, Sequence* sequence);
|
||||
void set_item_to_folder(QTreeWidgetItem* item);
|
||||
|
||||
QString get_channel_layout_name(int channels, int layout);
|
||||
QString get_interlacing_name(int interlacing);
|
||||
|
||||
class Project : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -70,6 +73,7 @@ public slots:
|
||||
void delete_clips_using_selected_media();
|
||||
void replace_selected_file();
|
||||
void replace_clip_media();
|
||||
void open_properties();
|
||||
private:
|
||||
Ui::Project *ui;
|
||||
QTreeWidgetItem* new_item();
|
||||
|
||||
+2
-2
@@ -260,7 +260,7 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
// apply any audio effects to the data
|
||||
if (nb_bytes == INT_MAX) nb_bytes = frame->nb_samples * av_get_bytes_per_sample(static_cast<AVSampleFormat>(frame->format)) * frame->channels;
|
||||
if (new_frame) {
|
||||
apply_audio_effects(c, bytes_to_seconds(c->audio_buffer_write, 2, sequence->audio_frequency) + audio_ibuffer_timecode, frame, nb_bytes);
|
||||
apply_audio_effects(c, bytes_to_seconds(c->audio_buffer_write, 2, sequence->audio_frequency) + audio_ibuffer_timecode + ((double) (c->clip_in - c->timeline_in)/sequence->frame_rate), frame, nb_bytes);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -431,7 +431,7 @@ void reset_cache(Clip* c, long target_frame) {
|
||||
|
||||
// seeks to nearest keyframe (target_frame represents internal clip frame)
|
||||
int64_t seek_ts = qRound(clip_frame_to_seconds(c, target_frame) / timebase);
|
||||
av_seek_frame(c->formatCtx, ms->file_index, seek_ts - (av_q2d(av_inv_q(c->stream->time_base))), AVSEEK_FLAG_BACKWARD);
|
||||
av_seek_frame(c->formatCtx, ms->file_index, seek_ts/* - (av_q2d(av_inv_q(c->stream->time_base)))*/, AVSEEK_FLAG_BACKWARD);
|
||||
|
||||
// play up to the frame we actually want
|
||||
int ret;
|
||||
|
||||
+22
-20
@@ -109,7 +109,7 @@ bool get_clip_frame(Clip* c, long playhead) {
|
||||
// do we need to update the texture?
|
||||
MediaStream* ms = static_cast<Media*>(c->media)->get_stream_from_file_index(c->track < 0, c->media_stream);
|
||||
|
||||
long sequence_clip_time = playhead - c->timeline_in + c->clip_in;
|
||||
long sequence_clip_time = qMax(0L, playhead - c->timeline_in + c->clip_in);
|
||||
|
||||
if (c->reverse && !ms->infinite_length) {
|
||||
sequence_clip_time = c->getMaximumLength() - sequence_clip_time - 1;
|
||||
@@ -117,7 +117,7 @@ bool get_clip_frame(Clip* c, long playhead) {
|
||||
|
||||
double rate = c->getMediaFrameRate();
|
||||
if (c->skip_type == SKIP_TYPE_DISCARD) rate *= c->speed;
|
||||
long clip_time = qMax(0L, refactor_frame_number(sequence_clip_time, c->sequence->frame_rate, rate));
|
||||
long clip_time = refactor_frame_number(sequence_clip_time, c->sequence->frame_rate, rate);
|
||||
|
||||
AVFrame* current_frame = NULL;
|
||||
bool no_frame = false;
|
||||
@@ -206,25 +206,27 @@ bool get_clip_frame(Clip* c, long playhead) {
|
||||
}
|
||||
}
|
||||
|
||||
if (current_frame != NULL) {
|
||||
// set up opengl texture
|
||||
if (c->texture == NULL) {
|
||||
c->texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
|
||||
c->texture->setSize(current_frame->width, current_frame->height);
|
||||
c->texture->setFormat(QOpenGLTexture::RGBA8_UNorm);
|
||||
c->texture->setMipLevels(c->texture->maximumMipLevels());
|
||||
c->texture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear);
|
||||
c->texture->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
|
||||
}
|
||||
if (playhead >= c->timeline_in) {
|
||||
if (current_frame != NULL) {
|
||||
// set up opengl texture
|
||||
if (c->texture == NULL) {
|
||||
c->texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
|
||||
c->texture->setSize(current_frame->width, current_frame->height);
|
||||
c->texture->setFormat(QOpenGLTexture::RGBA8_UNorm);
|
||||
c->texture->setMipLevels(c->texture->maximumMipLevels());
|
||||
c->texture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear);
|
||||
c->texture->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
|
||||
}
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, current_frame->linesize[0]/4);
|
||||
c->texture->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, current_frame->data[0]);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
c->texture_frame = clip_time;
|
||||
return true;
|
||||
} else {
|
||||
texture_failed = true;
|
||||
qDebug() << "[ERROR] Failed to retrieve frame from cache (R:" << clip_time << "| A:" << c->cache_A.offset << "-" << c->cache_A.offset+c->cache_size-1 << "| B:" << c->cache_B.offset << "-" << c->cache_B.offset+c->cache_size-1 << "| WA:" << c->cache_A.written << "| WB:" << c->cache_B.written << ")";
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, current_frame->linesize[0]/4);
|
||||
c->texture->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, current_frame->data[0]);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
c->texture_frame = clip_time;
|
||||
return true;
|
||||
} else {
|
||||
texture_failed = true;
|
||||
qDebug() << "[ERROR] Failed to retrieve frame from cache (R:" << clip_time << "| A:" << c->cache_A.offset << "-" << c->cache_A.offset+c->cache_size-1 << "| B:" << c->cache_B.offset << "-" << c->cache_B.offset+c->cache_size-1 << "| WA:" << c->cache_A.written << "| WB:" << c->cache_B.written << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
+25
-23
@@ -178,33 +178,35 @@ long Clip::getLength() {
|
||||
}
|
||||
|
||||
void Clip::recalculateMaxLength() {
|
||||
double fr = this->sequence->frame_rate;
|
||||
if (sequence != NULL) {
|
||||
double fr = this->sequence->frame_rate;
|
||||
|
||||
fr /= speed;
|
||||
fr /= speed;
|
||||
|
||||
switch (media_type) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
{
|
||||
Media* m = static_cast<Media*>(media);
|
||||
MediaStream* ms = m->get_stream_from_file_index(track < 0, media_stream);
|
||||
if (ms != NULL && ms->infinite_length) {
|
||||
switch (media_type) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
{
|
||||
Media* m = static_cast<Media*>(media);
|
||||
MediaStream* ms = m->get_stream_from_file_index(track < 0, media_stream);
|
||||
if (ms != NULL && ms->infinite_length) {
|
||||
calculated_length = LONG_MAX;
|
||||
} else {
|
||||
calculated_length = m->get_length_in_frames(fr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MEDIA_TYPE_SEQUENCE:
|
||||
{
|
||||
Sequence* s = static_cast<Sequence*>(media);
|
||||
calculated_length = refactor_frame_number(s->getEndFrame(), s->frame_rate, fr);
|
||||
}
|
||||
break;
|
||||
/*case MEDIA_TYPE_SOLID:
|
||||
case MEDIA_TYPE_TONE:*/
|
||||
default:
|
||||
calculated_length = LONG_MAX;
|
||||
} else {
|
||||
calculated_length = m->get_length_in_frames(fr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MEDIA_TYPE_SEQUENCE:
|
||||
{
|
||||
Sequence* s = static_cast<Sequence*>(media);
|
||||
calculated_length = refactor_frame_number(s->getEndFrame(), s->frame_rate, fr);
|
||||
}
|
||||
break;
|
||||
/*case MEDIA_TYPE_SOLID:
|
||||
case MEDIA_TYPE_TONE:*/
|
||||
default:
|
||||
calculated_length = LONG_MAX;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-3
@@ -8,7 +8,6 @@
|
||||
#include "project/selection.h"
|
||||
|
||||
struct Sequence {
|
||||
public:
|
||||
Sequence();
|
||||
~Sequence();
|
||||
Sequence* copy();
|
||||
@@ -31,8 +30,7 @@ public:
|
||||
int save_id;
|
||||
|
||||
QVector<Marker> markers;
|
||||
QVector<Clip*> clips;
|
||||
private:
|
||||
QVector<Clip*> clips;
|
||||
};
|
||||
|
||||
// static variable for the currently active sequence
|
||||
|
||||
+7
-3
@@ -352,8 +352,10 @@ DeleteMediaCommand::DeleteMediaCommand(QTreeWidgetItem* i) :
|
||||
{}
|
||||
|
||||
DeleteMediaCommand::~DeleteMediaCommand() {
|
||||
panel_project->delete_media(item);
|
||||
delete item;
|
||||
if (done) {
|
||||
panel_project->delete_media(item);
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteMediaCommand::undo() {
|
||||
@@ -364,6 +366,7 @@ void DeleteMediaCommand::undo() {
|
||||
}
|
||||
|
||||
mainWindow->setWindowModified(old_project_changed);
|
||||
done = false;
|
||||
}
|
||||
|
||||
void DeleteMediaCommand::redo() {
|
||||
@@ -373,9 +376,10 @@ void DeleteMediaCommand::redo() {
|
||||
panel_project->source_table->takeTopLevelItem(panel_project->source_table->indexOfTopLevelItem(item));
|
||||
} else {
|
||||
parent->removeChild(item);
|
||||
}
|
||||
}
|
||||
|
||||
mainWindow->setWindowModified(true);
|
||||
done = true;
|
||||
}
|
||||
|
||||
RippleCommand::RippleCommand(Sequence *s, long ipoint, long ilength) :
|
||||
|
||||
@@ -193,6 +193,7 @@ private:
|
||||
QTreeWidgetItem* item;
|
||||
QTreeWidgetItem* parent;
|
||||
bool old_project_changed;
|
||||
bool done;
|
||||
};
|
||||
|
||||
class RippleCommand : public QUndoCommand {
|
||||
|
||||
+15
-8
@@ -81,6 +81,10 @@ void KeyframeView::paintEvent(QPaintEvent*) {
|
||||
visible_out = effects_out;
|
||||
|
||||
int max_width = getScreenPointFromFrame(panel_effect_controls->zoom, visible_out - visible_in);
|
||||
qDebug() << max_width << width();
|
||||
if (max_width < width()) {
|
||||
p.fillRect(QRect(max_width, 0, width(), height()), QColor(0, 0, 0, 64));
|
||||
}
|
||||
panel_effect_controls->ui->horizontalScrollBar->setMaximum(qMax(max_width - width(), 0));
|
||||
header->set_visible_in(effects_in);
|
||||
|
||||
@@ -152,11 +156,13 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) {
|
||||
int row_index = -1;
|
||||
int keyframe_index = -1;
|
||||
long frame_diff = 0;
|
||||
long frame_min = getFrameFromScreenPoint(panel_effect_controls->zoom, event->x()-KEYFRAME_SIZE);
|
||||
drag_frame_start = getFrameFromScreenPoint(panel_effect_controls->zoom, event->x());
|
||||
long frame_max = getFrameFromScreenPoint(panel_effect_controls->zoom, event->x()+KEYFRAME_SIZE);
|
||||
int mouse_x = event->x() + x_scroll;
|
||||
int mouse_y = event->y();
|
||||
long frame_min = getFrameFromScreenPoint(panel_effect_controls->zoom, mouse_x-KEYFRAME_SIZE);
|
||||
drag_frame_start = getFrameFromScreenPoint(panel_effect_controls->zoom, mouse_x);
|
||||
long frame_max = getFrameFromScreenPoint(panel_effect_controls->zoom, mouse_x+KEYFRAME_SIZE);
|
||||
for (int i=0;i<rowY.size();i++) {
|
||||
if (event->y() > rowY.at(i)-KEYFRAME_SIZE-KEYFRAME_SIZE && event->y() < rowY.at(i)+KEYFRAME_SIZE+KEYFRAME_SIZE) {
|
||||
if (mouse_y > rowY.at(i)-KEYFRAME_SIZE-KEYFRAME_SIZE && mouse_y < rowY.at(i)+KEYFRAME_SIZE+KEYFRAME_SIZE) {
|
||||
EffectRow* row = rows.at(i);
|
||||
for (int j=0;j<row->keyframe_times.size();j++) {
|
||||
long eval_keyframe_time = row->keyframe_times.at(j)-row->parent_effect->parent_clip->clip_in+(row->parent_effect->parent_clip->timeline_in-visible_in);
|
||||
@@ -199,9 +205,10 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) {
|
||||
|
||||
void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
|
||||
if (mousedown) {
|
||||
int mouse_x = event->x() + x_scroll;
|
||||
if (keys_selected) {
|
||||
// move keyframes
|
||||
frame_diff = getFrameFromScreenPoint(panel_effect_controls->zoom, event->x()) - drag_frame_start;
|
||||
frame_diff = getFrameFromScreenPoint(panel_effect_controls->zoom, mouse_x) - drag_frame_start;
|
||||
|
||||
// snapping to playhead
|
||||
if (panel_timeline->snapping) {
|
||||
@@ -210,7 +217,7 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
|
||||
Clip* c = row->parent_effect->parent_clip;
|
||||
long key_time = row->keyframe_times.at(selected_keyframes.at(i)) + frame_diff - c->clip_in + c->timeline_in;
|
||||
long key_eval = key_time;
|
||||
if (panel_timeline->snap_to_timeline(&key_eval, true, true, true)) {
|
||||
if (panel_timeline->snap_to_point(sequence->playhead, &key_eval)) {
|
||||
frame_diff += (key_eval - key_time);
|
||||
break;
|
||||
}
|
||||
@@ -245,8 +252,8 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
|
||||
int min_row = qMin(rect_select_y, event->y())-KEYFRAME_SIZE;
|
||||
int max_row = qMax(rect_select_y, event->y())+KEYFRAME_SIZE;
|
||||
|
||||
long frame_start = getFrameFromScreenPoint(panel_effect_controls->zoom, rect_select_x);
|
||||
long frame_end = getFrameFromScreenPoint(panel_effect_controls->zoom, event->x());
|
||||
long frame_start = getFrameFromScreenPoint(panel_effect_controls->zoom, rect_select_x+x_scroll);
|
||||
long frame_end = getFrameFromScreenPoint(panel_effect_controls->zoom, mouse_x);
|
||||
long min_frame = qMin(frame_start, frame_end)-KEYFRAME_SIZE;
|
||||
long max_frame = qMax(frame_start, frame_end)+KEYFRAME_SIZE;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <QMouseEvent>
|
||||
#include <QInputDialog>
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
|
||||
LabelSlider::LabelSlider(QWidget* parent) : QLabel(parent) {
|
||||
decimal_places = 1;
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ public:
|
||||
bool is_set();
|
||||
double get_drag_start_value();
|
||||
bool is_dragging();
|
||||
virtual QString valueToString(double v);
|
||||
QString valueToString(double v);
|
||||
double getPreviousValue();
|
||||
int decimal_places;
|
||||
protected:
|
||||
|
||||
+8
-3
@@ -24,10 +24,10 @@ SourceTable::SourceTable(QWidget* parent) : QTreeWidget(parent) {
|
||||
connect(&rename_timer, SIGNAL(timeout()), this, SLOT(rename_interval()));
|
||||
connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(item_click(QTreeWidgetItem*,int)));
|
||||
connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(item_renamed(QTreeWidgetItem*)));
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu(const QPoint&)));
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu()));
|
||||
}
|
||||
|
||||
void SourceTable::show_context_menu(const QPoint& pos) {
|
||||
void SourceTable::show_context_menu() {
|
||||
QMenu menu(this);
|
||||
|
||||
if (selectedItems().size() == 0) {
|
||||
@@ -75,9 +75,14 @@ void SourceTable::show_context_menu(const QPoint& pos) {
|
||||
// delete media
|
||||
QAction* delete_action = menu.addAction("Delete");
|
||||
connect(delete_action, SIGNAL(triggered(bool)), panel_project, SLOT(delete_selected_media()));
|
||||
|
||||
if (selectedItems().size() == 1) {
|
||||
QAction* properties_action = menu.addAction("Properties...");
|
||||
connect(properties_action, SIGNAL(triggered(bool)), panel_project, SLOT(open_properties()));
|
||||
}
|
||||
}
|
||||
|
||||
menu.exec(mapToGlobal(pos));
|
||||
menu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void SourceTable::item_renamed(QTreeWidgetItem* item) {
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ private slots:
|
||||
void item_click(QTreeWidgetItem* item, int column);
|
||||
void stop_rename_timer();
|
||||
void item_renamed(QTreeWidgetItem *item);
|
||||
void show_context_menu(const QPoint& pos);
|
||||
void show_context_menu();
|
||||
};
|
||||
|
||||
#endif // SOURCETABLE_H
|
||||
|
||||
+22
-13
@@ -5,22 +5,17 @@
|
||||
TextEditEx::TextEditEx(QWidget *parent) : QTextEdit(parent) {
|
||||
setUndoRedoEnabled(false);
|
||||
connect(this, SIGNAL(textChanged()), this, SLOT(updateInternals()));
|
||||
connect(this, SIGNAL(updateSelf()), this, SLOT(updateText()));
|
||||
}
|
||||
|
||||
void TextEditEx::setPlainTextEx(const QString &text) {
|
||||
blockSignals(true);
|
||||
const QString& TextEditEx::getPlainTextEx() {
|
||||
return text;
|
||||
}
|
||||
|
||||
int pos = textCursor().position();
|
||||
|
||||
setPlainText(text);
|
||||
|
||||
QTextCursor newCursor(document());
|
||||
newCursor.setPosition(pos);
|
||||
setTextCursor(newCursor);
|
||||
|
||||
updateInternals();
|
||||
|
||||
blockSignals(false);
|
||||
void TextEditEx::setPlainTextEx(const QString &t) {
|
||||
previousText = text;
|
||||
text = t;
|
||||
emit updateSelf();
|
||||
}
|
||||
|
||||
const QString &TextEditEx::getPreviousValue() {
|
||||
@@ -31,3 +26,17 @@ void TextEditEx::updateInternals() {
|
||||
previousText = text;
|
||||
text = toPlainText();
|
||||
}
|
||||
|
||||
void TextEditEx::updateText() {
|
||||
blockSignals(true);
|
||||
|
||||
int pos = textCursor().position();
|
||||
|
||||
setPlainText(text);
|
||||
|
||||
QTextCursor newCursor(document());
|
||||
newCursor.setPosition(pos);
|
||||
setTextCursor(newCursor);
|
||||
|
||||
blockSignals(false);
|
||||
}
|
||||
|
||||
@@ -9,8 +9,12 @@ public:
|
||||
TextEditEx(QWidget* parent = 0);
|
||||
void setPlainTextEx(const QString &text);
|
||||
const QString& getPreviousValue();
|
||||
const QString& getPlainTextEx();
|
||||
signals:
|
||||
void updateSelf();
|
||||
private slots:
|
||||
void updateInternals();
|
||||
void updateText();
|
||||
private:
|
||||
QString previousText;
|
||||
QString text;
|
||||
|
||||
@@ -1947,7 +1947,7 @@ void TimelineWidget::paintEvent(QPaintEvent*) {
|
||||
for (int i=0;i<2;i++) {
|
||||
Transition* t = (i == 0) ? clip->opening_transition : clip->closing_transition;
|
||||
if (t != NULL) {
|
||||
int transition_width = panel_timeline->getTimelineScreenPointFromFrame(t->length);
|
||||
int transition_width = getScreenPointFromFrame(panel_timeline->zoom, t->length);
|
||||
int transition_height = clip_rect.height();
|
||||
int tr_y = clip_rect.y();
|
||||
int tr_x = 0;
|
||||
|
||||
+28
-13
@@ -85,7 +85,7 @@ void ViewerWidget::drawTitleSafeArea() {
|
||||
glLoadIdentity();
|
||||
glOrtho(-halfWidth, halfWidth, halfHeight, -halfHeight, -1, 1);
|
||||
|
||||
glColor4f(0.5, 0.5, 0.5, 1.0);
|
||||
glColor4f(0.66f, 0.66f, 0.66f, 1.0f);
|
||||
glBegin(GL_LINES);
|
||||
|
||||
// action safe rectangle
|
||||
@@ -378,6 +378,8 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
|
||||
glVertex2f(coords.vertexBottomLeftX, coords.vertexBottomLeftY); // bottom left
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
if (nest != NULL) {
|
||||
nest->fbo[0]->release();
|
||||
if (default_fbo != NULL) default_fbo->bind();
|
||||
@@ -386,19 +388,32 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
|
||||
|
||||
glPopMatrix();
|
||||
} else {
|
||||
switch (c->media_type) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
case MEDIA_TYPE_TONE:
|
||||
if (render_audio
|
||||
&& c->lock.tryLock()) {
|
||||
// clip is not caching, start caching audio
|
||||
cache_clip(c, playhead, false, false, c->audio_reset, nest);
|
||||
c->lock.unlock();
|
||||
if (render_audio) {
|
||||
switch (c->media_type) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
case MEDIA_TYPE_TONE:
|
||||
if (c->lock.tryLock()) {
|
||||
// clip is not caching, start caching audio
|
||||
cache_clip(c, playhead, false, false, c->audio_reset, nest);
|
||||
c->lock.unlock();
|
||||
}
|
||||
break;
|
||||
case MEDIA_TYPE_SEQUENCE:
|
||||
compose_sequence(c, render_audio);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// visually update all the keyframe values
|
||||
double ts = (playhead - c->timeline_in + c->clip_in)/sequence->frame_rate;
|
||||
for (int i=0;i<c->effects.size();i++) {
|
||||
Effect* e = c->effects.at(i);
|
||||
for (int j=0;j<e->row_count();j++) {
|
||||
EffectRow* r = e->row(j);
|
||||
for (int k=0;k<r->fieldCount();k++) {
|
||||
r->field(k)->validate_keyframe_data(ts);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MEDIA_TYPE_SEQUENCE:
|
||||
compose_sequence(c, render_audio);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user