several improvements
This commit is contained in:
@@ -90,6 +90,10 @@ void NewSequenceDialog::on_buttonBox_accepted() {
|
||||
panel_project->new_sequence(ca, s, true, NULL);
|
||||
undo_stack.push(ca);
|
||||
} else {
|
||||
ComboAction* ca = new ComboAction();
|
||||
|
||||
double multiplier = ui->frame_rate_combobox->currentData().toDouble() / existing_sequence->frame_rate;
|
||||
|
||||
EditSequenceCommand* esc = new EditSequenceCommand(existing_item, existing_sequence);
|
||||
esc->name = ui->lineEdit->text();
|
||||
esc->width = ui->width_numeric->value();
|
||||
@@ -97,7 +101,16 @@ void NewSequenceDialog::on_buttonBox_accepted() {
|
||||
esc->frame_rate = ui->frame_rate_combobox->currentData().toDouble();
|
||||
esc->audio_frequency = ui->audio_frequency_combobox->currentData().toInt();
|
||||
esc->audio_layout = AV_CH_LAYOUT_STEREO;
|
||||
undo_stack.push(esc);
|
||||
ca->append(esc);
|
||||
|
||||
for (int i=0;i<existing_sequence->clips.size();i++) {
|
||||
Clip* c = existing_sequence->clips.at(i);
|
||||
if (c != NULL) {
|
||||
c->refactor_frame_rate(ca, multiplier, true);
|
||||
}
|
||||
}
|
||||
|
||||
undo_stack.push(ca);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-15
@@ -315,21 +315,8 @@ void set_speed(ComboAction* ca, Clip* c, double speed, bool ripple, long& ep, lo
|
||||
ep = qMin(ep, c->timeline_out);
|
||||
lr = qMax(lr, proposed_out - c->timeline_out);
|
||||
ca->append(new MoveClipAction(c, c->timeline_in, proposed_out, c->clip_in * multiplier, c->track));
|
||||
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->keyframe_times.size();k++) {
|
||||
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);
|
||||
km->keyframes.append(k);
|
||||
ca->append(km);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c->refactor_frame_rate(ca, multiplier, false);
|
||||
|
||||
Selection sel;
|
||||
sel.in = c->timeline_in;
|
||||
|
||||
@@ -116,6 +116,7 @@ Effect::Effect(Clip* c, int t, int i) :
|
||||
ui = new QWidget();
|
||||
|
||||
ui_layout = new QGridLayout();
|
||||
ui_layout->setSpacing(4);
|
||||
ui->setLayout(ui_layout);
|
||||
container->setContents(ui);
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
@@ -41,5 +41,7 @@
|
||||
<file>add-button.png</file>
|
||||
<file>add-button-disabled.png</file>
|
||||
<file>clock.png</file>
|
||||
<file>sequence.png</file>
|
||||
<file>folder.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
+7
-4
@@ -56,6 +56,7 @@ void MainWindow::setup_layout() {
|
||||
|
||||
addDockWidget(Qt::TopDockWidgetArea, panel_project);
|
||||
addDockWidget(Qt::TopDockWidgetArea, panel_effect_controls);
|
||||
tabifyDockWidget(panel_effect_controls, panel_footage_viewer);
|
||||
addDockWidget(Qt::TopDockWidgetArea, panel_sequence_viewer);
|
||||
addDockWidget(Qt::BottomDockWidgetArea, panel_timeline);
|
||||
|
||||
@@ -103,6 +104,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
panel_project = new Project(this);
|
||||
panel_effect_controls = new EffectControls(this);
|
||||
panel_sequence_viewer = new Viewer(this);
|
||||
panel_footage_viewer = new Viewer(this);
|
||||
panel_timeline = new Timeline(this);
|
||||
|
||||
setup_layout();
|
||||
@@ -174,8 +176,9 @@ MainWindow::~MainWindow() {
|
||||
|
||||
delete panel_project;
|
||||
delete panel_effect_controls;
|
||||
delete panel_timeline;
|
||||
delete panel_sequence_viewer;
|
||||
delete panel_timeline;
|
||||
delete panel_footage_viewer;
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Import_triggered()
|
||||
@@ -698,16 +701,16 @@ void MainWindow::on_actionRipple_to_Out_Point_triggered()
|
||||
|
||||
void MainWindow::on_actionSet_In_Point_triggered()
|
||||
{
|
||||
if (panel_timeline->focused()) panel_timeline->set_in_point();
|
||||
if (panel_timeline->focused() || panel_sequence_viewer->hasFocus()) panel_timeline->set_in_point();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSet_Out_Point_triggered()
|
||||
{
|
||||
if (panel_timeline->focused()) panel_timeline->set_out_point();
|
||||
if (panel_timeline->focused() || panel_sequence_viewer->hasFocus()) panel_timeline->set_out_point();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionClear_In_Out_triggered() {
|
||||
if (panel_timeline->focused() && sequence->using_workarea) {
|
||||
if ((panel_timeline->focused() || panel_sequence_viewer->hasFocus()) && sequence->using_workarea) {
|
||||
undo_stack.push(new SetTimelineInOutCommand(sequence, false, 0, 0));
|
||||
panel_timeline->repaint_timeline(false);
|
||||
}
|
||||
|
||||
@@ -59,11 +59,7 @@ bool EffectControls::keyframe_focus() {
|
||||
}
|
||||
|
||||
void EffectControls::set_zoom(bool in) {
|
||||
if (in) {
|
||||
zoom *= 2;
|
||||
} else {
|
||||
zoom *= 0.5;
|
||||
}
|
||||
zoom *= (in) ? 2 : 0.5;
|
||||
update_keyframes();
|
||||
}
|
||||
|
||||
@@ -94,7 +90,7 @@ void EffectControls::menu_select(QAction* q) {
|
||||
}
|
||||
|
||||
void EffectControls::update_keyframes() {
|
||||
if (ui->headers->isVisible()) ui->headers->update_zoom(zoom);
|
||||
ui->headers->update_zoom(zoom);
|
||||
ui->keyframeView->update();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,4 +3,5 @@
|
||||
Project* panel_project = 0;
|
||||
EffectControls* panel_effect_controls = 0;
|
||||
Viewer* panel_sequence_viewer = 0;
|
||||
Viewer* panel_footage_viewer = 0;
|
||||
Timeline* panel_timeline = 0;
|
||||
|
||||
@@ -9,6 +9,7 @@ class Timeline;
|
||||
extern Project* panel_project;
|
||||
extern EffectControls* panel_effect_controls;
|
||||
extern Viewer* panel_sequence_viewer;
|
||||
extern Viewer* panel_footage_viewer;
|
||||
extern Timeline* panel_timeline;
|
||||
|
||||
#endif // PANELS_H
|
||||
|
||||
+8
-2
@@ -165,9 +165,13 @@ void Project::open_properties() {
|
||||
default:
|
||||
{
|
||||
// fall back to renaming
|
||||
QString new_name = QInputDialog::getText(this, "Rename '" + item->text(0) + "'", "Enter new name:");
|
||||
QString new_name = QInputDialog::getText(this, "Rename '" + item->text(0) + "'", "Enter new name:", QLineEdit::Normal, item->text(0));
|
||||
if (!new_name.isEmpty()) {
|
||||
item->setText(0, new_name);
|
||||
MediaRename* mr = new MediaRename();
|
||||
mr->from = item->text(0);
|
||||
mr->item = item;
|
||||
mr->to = new_name;
|
||||
undo_stack.push(mr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -220,6 +224,7 @@ QTreeWidgetItem* Project::new_folder(QString name) {
|
||||
QTreeWidgetItem* item = new_item();
|
||||
item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
|
||||
item->setText(0, (name.isEmpty()) ? "New Folder" : name);
|
||||
item->setIcon(0, QIcon(":/icons/folder.png"));
|
||||
set_item_to_folder(item);
|
||||
return item;
|
||||
}
|
||||
@@ -576,6 +581,7 @@ void set_sequence_of_tree(QTreeWidgetItem* item, Sequence* s) {
|
||||
+ "\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));
|
||||
item->setIcon(0, QIcon(":/icons/sequence.png"));
|
||||
}
|
||||
|
||||
int get_type_from_tree(QTreeWidgetItem* item) {
|
||||
|
||||
+10
-1
@@ -307,7 +307,9 @@ void Timeline::repaint_timeline(bool changed) {
|
||||
panel_effect_controls->update_keyframes();
|
||||
|
||||
if (sequence != NULL) {
|
||||
panel_timeline->ui->horizontalScrollBar->setMaximum(qMax(0, getScreenPointFromFrame(panel_timeline->zoom, sequence->getEndFrame()) + 100 - ui->editAreas->width()));
|
||||
long sequenceEndFrame = sequence->getEndFrame();
|
||||
|
||||
panel_timeline->ui->horizontalScrollBar->setMaximum(qMax(0, getScreenPointFromFrame(panel_timeline->zoom, sequenceEndFrame) + 100 - ui->editAreas->width()));
|
||||
|
||||
if (last_frame != sequence->playhead) {
|
||||
panel_sequence_viewer->viewer_widget->update();
|
||||
@@ -324,6 +326,13 @@ void Timeline::repaint_timeline(bool changed) {
|
||||
}
|
||||
|
||||
panel_sequence_viewer->update_playhead_timecode(sequence->playhead);
|
||||
|
||||
|
||||
if (sequenceEndFrame > 0) {
|
||||
panel_sequence_viewer->ui->headers->update_zoom((double) panel_sequence_viewer->ui->headers->width() / (double) sequenceEndFrame);
|
||||
} else {
|
||||
panel_sequence_viewer->ui->headers->update_zoom(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-5
@@ -22,6 +22,7 @@ Viewer::Viewer(QWidget *parent) :
|
||||
ui(new Ui::Viewer)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->headers->show_text(false);
|
||||
ui->glViewerPane->child = ui->openGLWidget;
|
||||
viewer_widget = ui->openGLWidget;
|
||||
update_media(MEDIA_TYPE_SEQUENCE, NULL);
|
||||
@@ -111,11 +112,7 @@ void Viewer::update_playhead_timecode(long p) {
|
||||
}
|
||||
|
||||
void Viewer::update_end_timecode() {
|
||||
if (sequence == NULL) {
|
||||
ui->endTimecode->setText(frame_to_timecode(0, config.timecode_view, 30));
|
||||
} else {
|
||||
ui->endTimecode->setText(frame_to_timecode(sequence->getEndFrame(), config.timecode_view, sequence->frame_rate));
|
||||
}
|
||||
ui->endTimecode->setText((sequence == NULL) ? frame_to_timecode(0, config.timecode_view, 30) : frame_to_timecode(sequence->getEndFrame(), config.timecode_view, sequence->frame_rate));
|
||||
}
|
||||
|
||||
void Viewer::update_media(int type, void* media) {
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="ViewerContainer" name="glViewerPane" native="true">
|
||||
<property name="sizePolicy">
|
||||
@@ -58,6 +61,9 @@
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="TimelineHeader" name="headers" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="playbackControls" native="true">
|
||||
<property name="sizePolicy">
|
||||
@@ -233,6 +239,12 @@
|
||||
<extends>QLabel</extends>
|
||||
<header>ui/labelslider.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>TimelineHeader</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>ui/timelineheader.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../icons/icons.qrc"/>
|
||||
|
||||
+38
-5
@@ -26,6 +26,9 @@ extern "C" {
|
||||
#include <QtMath>
|
||||
#include <math.h>
|
||||
|
||||
// temp debug shit
|
||||
//#define AUDIOWARNINGS
|
||||
|
||||
int dest_format = AV_PIX_FMT_RGBA;
|
||||
|
||||
double bytes_to_seconds(int nb_bytes, int nb_channels, int sample_rate) {
|
||||
@@ -97,9 +100,11 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
avcodec_flush_buffers(c->codecCtx);
|
||||
int64_t backtrack_seek = qMax(c->rev_target - static_cast<int64_t>(av_q2d(av_inv_q(c->stream->time_base))), static_cast<int64_t>(0));
|
||||
av_seek_frame(c->formatCtx, c->stream->index, backtrack_seek, AVSEEK_FLAG_BACKWARD);
|
||||
#ifdef AUDIOWARNINGS
|
||||
if (backtrack_seek == 0) {
|
||||
qDebug() << "backtracked to 0";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
do {
|
||||
@@ -120,7 +125,9 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
if (!c->reverse) {
|
||||
c->reached_end = true;
|
||||
} else {
|
||||
#ifdef AUDIOWARNINGS
|
||||
qDebug() << "reached EOF";
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
qDebug() << "[WARNING] Raw audio frame data could not be retrieved." << ret;
|
||||
@@ -136,7 +143,9 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
c->reached_end = true;
|
||||
break;
|
||||
} else {
|
||||
#ifdef AUDIOWARNINGS
|
||||
qDebug() << "reached EOF";
|
||||
#endif
|
||||
if (!c->reverse) break;
|
||||
}
|
||||
}
|
||||
@@ -146,19 +155,25 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
AVFrame* rev_frame = c->cache_A.frames[1];
|
||||
if (ret != AVERROR_EOF) {
|
||||
if (loop == 2) {
|
||||
#ifdef AUDIOWARNINGS
|
||||
qDebug() << "starting rev_frame";
|
||||
#endif
|
||||
rev_frame->nb_samples = 0;
|
||||
rev_frame->pts = c->frame->pkt_pts;
|
||||
}
|
||||
int offset = rev_frame->nb_samples * av_get_bytes_per_sample(static_cast<AVSampleFormat>(rev_frame->format)) * rev_frame->channels;
|
||||
#ifdef AUDIOWARNINGS
|
||||
qDebug() << "offset 1:" << offset;
|
||||
qDebug() << "retrieved samples:" << frame->nb_samples << "size:" << (frame->nb_samples * av_get_bytes_per_sample(static_cast<AVSampleFormat>(frame->format)) * frame->channels);
|
||||
#endif
|
||||
memcpy(
|
||||
rev_frame->data[0]+offset,
|
||||
frame->data[0],
|
||||
(frame->nb_samples * av_get_bytes_per_sample(static_cast<AVSampleFormat>(frame->format)) * frame->channels)
|
||||
);
|
||||
#ifdef AUDIOWARNINGS
|
||||
qDebug() << "pts:" << c->frame->pts << "dur:" << c->frame->pkt_duration << "rev_target:" << c->rev_target << "offset:" << offset << "limit:" << rev_frame->linesize[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
rev_frame->nb_samples += frame->nb_samples;
|
||||
@@ -173,9 +188,13 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
rev_frame->nb_samples -= cutoff;
|
||||
}*/
|
||||
|
||||
#ifdef AUDIOWARNINGS
|
||||
qDebug() << "pre cutoff deets::: rev_frame.pts:" << rev_frame->pts << "rev_frame.nb_samples" << rev_frame->nb_samples << "rev_target:" << c->rev_target;
|
||||
#endif
|
||||
rev_frame->nb_samples = qRound(static_cast<double>(c->rev_target - rev_frame->pts) / c->stream->codecpar->sample_rate * sequence->audio_frequency);
|
||||
#ifdef AUDIOWARNINGS
|
||||
qDebug() << "post cutoff deets::" << rev_frame->nb_samples;
|
||||
#endif
|
||||
|
||||
int frame_size = rev_frame->nb_samples * rev_frame->channels * av_get_bytes_per_sample(static_cast<AVSampleFormat>(rev_frame->format));
|
||||
int half_frame_size = frame_size >> 1;
|
||||
@@ -203,7 +222,9 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
|
||||
loop++;
|
||||
|
||||
#ifdef AUDIOWARNINGS
|
||||
qDebug() << "loop" << loop;
|
||||
#endif
|
||||
} else {
|
||||
frame->pts = c->frame->pts;
|
||||
break;
|
||||
@@ -228,15 +249,19 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
// get precise sample offset for the elected clip_in from this audio frame
|
||||
double target_sts = playhead_to_seconds(c, c->audio_target_frame);
|
||||
double frame_sts = (frame->pts * timebase);
|
||||
int nb_samples = qRound((target_sts - frame_sts)*c->sequence->audio_frequency);
|
||||
qDebug() << "fsts:" << frame_sts << "tsts:" << target_sts << "nbs:" << nb_samples << "nbb:" << nb_bytes << "rev_targetToSec:" << (c->rev_target * timebase);
|
||||
int nb_samples = qRound((target_sts - frame_sts)*c->sequence->audio_frequency);
|
||||
c->frame_sample_index = nb_samples * 4;
|
||||
#ifdef AUDIOWARNINGS
|
||||
qDebug() << "fsts:" << frame_sts << "tsts:" << target_sts << "nbs:" << nb_samples << "nbb:" << nb_bytes << "rev_targetToSec:" << (c->rev_target * timebase);
|
||||
qDebug() << "fsi-calc:" << c->frame_sample_index;
|
||||
#endif
|
||||
if (c->reverse) c->frame_sample_index = nb_bytes - c->frame_sample_index;
|
||||
c->audio_just_reset = false;
|
||||
}
|
||||
|
||||
#ifdef AUDIOWARNINGS
|
||||
qDebug() << "fsi-post-post:" << c->frame_sample_index;
|
||||
#endif
|
||||
|
||||
if (c->audio_buffer_write == 0) c->audio_buffer_write = get_buffer_offset_from_frame(qMax(timeline_in, c->audio_target_frame));
|
||||
|
||||
@@ -255,7 +280,9 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
|
||||
if (c->reverse) frame = c->cache_A.frames[1];
|
||||
|
||||
#ifdef AUDIOWARNINGS
|
||||
qDebug() << "j" << c->frame_sample_index << nb_bytes;
|
||||
#endif
|
||||
|
||||
// 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;
|
||||
@@ -290,7 +317,6 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
if (frame->nb_samples == 0) {
|
||||
break;
|
||||
} else {
|
||||
qDebug() << "re:" << c->reached_end;
|
||||
long buffer_timeline_out = get_buffer_offset_from_frame(timeline_out);
|
||||
audio_write_lock.lock();
|
||||
while (c->frame_sample_index < nb_bytes
|
||||
@@ -308,7 +334,9 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
c->audio_buffer_write+=2;
|
||||
c->frame_sample_index+=2;
|
||||
}
|
||||
#ifdef AUDIOWARNINGS
|
||||
if (c->audio_buffer_write >= buffer_timeline_out) qDebug() << "timeline out at fsi" << c->frame_sample_index << "of frame ts" << c->frame->pts;
|
||||
#endif
|
||||
audio_write_lock.unlock();
|
||||
|
||||
if (c->frame_sample_index == nb_bytes) {
|
||||
@@ -318,7 +346,7 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
break;
|
||||
}
|
||||
|
||||
qDebug() << "ended" << c->frame_sample_index << nb_bytes;
|
||||
// qDebug() << "ended" << c->frame_sample_index << nb_bytes;
|
||||
}
|
||||
if (c->reached_end) {
|
||||
frame->nb_samples = 0;
|
||||
@@ -386,6 +414,8 @@ void cache_video_worker(Clip* c, long playhead, ClipCache* cache) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
qDebug() << "retrieved PTS:" << cache->frames[i]->pts << c->stream->time_base.num << "/" << c->stream->time_base.den;
|
||||
|
||||
cache->written = true;
|
||||
i++;
|
||||
cache->write_count = i;
|
||||
@@ -412,6 +442,7 @@ void reset_cache(Clip* c, long target_frame) {
|
||||
switch (c->media_type) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
{
|
||||
c->reached_end = false;
|
||||
MediaStream* ms = static_cast<Media*>(c->media)->get_stream_from_file_index(c->track < 0, c->media_stream);
|
||||
if (!ms->infinite_length) {
|
||||
// flush ffmpeg codecs
|
||||
@@ -445,7 +476,7 @@ void reset_cache(Clip* c, long target_frame) {
|
||||
av_frame_unref(temp);
|
||||
av_frame_free(&temp);
|
||||
} else {
|
||||
av_seek_frame(c->formatCtx, ms->file_index, 0, AVSEEK_FLAG_BACKWARD);
|
||||
av_seek_frame(c->formatCtx, ms->file_index, c->stream->start_time, AVSEEK_FLAG_BACKWARD);
|
||||
}
|
||||
} else if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
// seek (target_frame represents timeline timecode in frames, not clip timecode)
|
||||
@@ -453,7 +484,9 @@ void reset_cache(Clip* c, long target_frame) {
|
||||
if (c->reverse) {
|
||||
c->rev_target = timestamp;
|
||||
timestamp -= av_q2d(av_inv_q(c->stream->time_base));
|
||||
#ifdef AUDIOWARNINGS
|
||||
qDebug() << "seeking to" << timestamp << "(originally" << c->rev_target << ")";
|
||||
#endif
|
||||
}
|
||||
av_seek_frame(c->formatCtx, ms->file_index, timestamp, AVSEEK_FLAG_BACKWARD);
|
||||
c->audio_target_frame = target_frame;
|
||||
|
||||
+12
-2
@@ -9,6 +9,7 @@
|
||||
#include "panels/timeline.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "effects/effect.h"
|
||||
#include "panels/effectcontrols.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
@@ -281,8 +282,16 @@ int retrieve_next_frame(Clip* c, AVFrame* f) {
|
||||
return send_ret;
|
||||
}
|
||||
} else {
|
||||
if (read_ret != AVERROR_EOF) qDebug() << "[ERROR] Could not read frame." << read_ret;
|
||||
return read_ret; // skips trying to find a frame at all
|
||||
if (read_ret == AVERROR_EOF) {
|
||||
int send_ret = avcodec_send_packet(c->codecCtx, NULL);
|
||||
if (send_ret < 0) {
|
||||
qDebug() << "[ERROR] Failed to send packet to decoder." << send_ret;
|
||||
return send_ret;
|
||||
}
|
||||
} else {
|
||||
qDebug() << "[ERROR] Could not read frame." << read_ret;
|
||||
return read_ret; // skips trying to find a frame at all
|
||||
}
|
||||
}
|
||||
}
|
||||
if (receive_ret < 0) {
|
||||
@@ -302,6 +311,7 @@ bool is_clip_active(Clip* c, long playhead) {
|
||||
|
||||
void set_sequence(Sequence* s) {
|
||||
closeActiveClips(sequence, true);
|
||||
panel_effect_controls->clear_effects(true);
|
||||
sequence = s;
|
||||
panel_timeline->update_sequence();
|
||||
panel_sequence_viewer->update_media(MEDIA_TYPE_SEQUENCE, sequence);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "panels/project.h"
|
||||
#include "project/sequence.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
@@ -259,3 +260,28 @@ int Clip::getHeight() {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Clip::refactor_frame_rate(ComboAction* ca, double multiplier, bool change_timeline_points) {
|
||||
if (change_timeline_points) {
|
||||
ca->append(new MoveClipAction(this,
|
||||
qRound((double) timeline_in * multiplier),
|
||||
qRound((double) timeline_out * multiplier),
|
||||
qRound((double) clip_in * multiplier),
|
||||
track));
|
||||
}
|
||||
|
||||
for (int i=0;i<effects.size();i++) {
|
||||
Effect* e = effects.at(i);
|
||||
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) * multiplier;
|
||||
KeyframeMove* km = new KeyframeMove();
|
||||
km->movement = new_pos - r->keyframe_times.at(k);
|
||||
km->rows.append(r);
|
||||
km->keyframes.append(k);
|
||||
ca->append(km);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ class Cacher;
|
||||
class Effect;
|
||||
class Transition;
|
||||
class QOpenGLFramebufferObject;
|
||||
class ComboAction;
|
||||
struct Sequence;
|
||||
struct Media;
|
||||
struct MediaStream;
|
||||
@@ -78,6 +79,7 @@ struct Clip
|
||||
bool reverse;
|
||||
long calculated_length;
|
||||
int skip_type;
|
||||
void refactor_frame_rate(ComboAction* ca, double multiplier, bool change_timeline_points);
|
||||
|
||||
// other variables (should be "duplicated" in copy())
|
||||
QList<Effect*> effects;
|
||||
|
||||
@@ -1572,6 +1572,9 @@ void EditSequenceCommand::redo() {
|
||||
}
|
||||
|
||||
void EditSequenceCommand::update() {
|
||||
// update name
|
||||
item->setText(0, seq->name);
|
||||
|
||||
// update tooltip
|
||||
set_sequence_of_tree(item, seq);
|
||||
|
||||
|
||||
@@ -150,7 +150,6 @@ void KeyframeView::draw_keyframe(QPainter &p, int x, int y, bool darker) {
|
||||
p.setPen(QColor(0, 0, 0));
|
||||
p.setBrush(QColor(color, color, color));
|
||||
p.drawPolygon(points, KEYFRAME_POINT_COUNT);
|
||||
qDebug() << "drew key at" << x << y;
|
||||
}
|
||||
|
||||
void KeyframeView::mousePressEvent(QMouseEvent *event) {
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ double LabelSlider::value() {
|
||||
}
|
||||
|
||||
void LabelSlider::set_default_value(double v) {
|
||||
if (internal_value == default_value) set = false; // TODO: CONTROVERSIAL - may be undesirable behaviour
|
||||
// if (internal_value == default_value) set = false; TODO: CONTROVERSIAL - disabled bc may lead undesirable behaviour
|
||||
|
||||
default_value = v;
|
||||
if (!set) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "panels/panels.h"
|
||||
#include "playback/playback.h"
|
||||
#include "project/undo.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QDragEnterEvent>
|
||||
#include <QMimeData>
|
||||
@@ -33,6 +34,9 @@ void SourceTable::show_context_menu() {
|
||||
if (selectedItems().size() == 0) {
|
||||
QAction* import_action = menu.addAction("Import...");
|
||||
connect(import_action, SIGNAL(triggered(bool)), panel_project, SLOT(import_dialog()));
|
||||
|
||||
QAction* new_folder_action = menu.addAction("New Folder...");
|
||||
connect(new_folder_action, SIGNAL(triggered(bool)), mainWindow, SLOT(on_actionFolder_triggered()));
|
||||
} else {
|
||||
if (selectedItems().size() == 1) {
|
||||
// replace footage
|
||||
|
||||
+26
-14
@@ -30,10 +30,11 @@ TimelineHeader::TimelineHeader(QWidget *parent) :
|
||||
dragging_markers(false),
|
||||
scroll(0)
|
||||
{
|
||||
height_actual = fm.height();
|
||||
setCursor(Qt::ArrowCursor);
|
||||
setMouseTracking(true);
|
||||
setFixedHeight(fm.height()*2);
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
show_text(true);
|
||||
}
|
||||
|
||||
void TimelineHeader::set_scroll(int s) {
|
||||
@@ -85,6 +86,16 @@ void TimelineHeader::set_out_point(long new_out) {
|
||||
panel_timeline->repaint_timeline(false);
|
||||
}
|
||||
|
||||
void TimelineHeader::show_text(bool enable) {
|
||||
text_enabled = enable;
|
||||
if (enable) {
|
||||
setFixedHeight(height_actual*2);
|
||||
} else {
|
||||
setFixedHeight(height_actual);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void TimelineHeader::mousePressEvent(QMouseEvent* event) {
|
||||
if (resizing_workarea) {
|
||||
sequence_end = sequence->getEndFrame();
|
||||
@@ -137,7 +148,7 @@ void TimelineHeader::mouseMoveEvent(QMouseEvent* event) {
|
||||
if (dragging) {
|
||||
if (resizing_workarea) {
|
||||
long frame = getHeaderFrameFromScreenPoint(event->pos().x());
|
||||
panel_timeline->snap_to_timeline(&frame, true, true, false);
|
||||
if (snapping) panel_timeline->snap_to_timeline(&frame, true, true, false);
|
||||
|
||||
if (resizing_workarea_in) {
|
||||
temp_workarea_in = qMax(qMin(temp_workarea_out-1, frame), 0L);
|
||||
@@ -152,7 +163,7 @@ void TimelineHeader::mouseMoveEvent(QMouseEvent* event) {
|
||||
// snap markers
|
||||
for (int i=0;i<selected_markers.size();i++) {
|
||||
long fm = selected_marker_original_times.at(i) + frame_movement;
|
||||
if (panel_timeline->snap_to_timeline(&fm, true, false, true)) {
|
||||
if (snapping && panel_timeline->snap_to_timeline(&fm, true, false, true)) {
|
||||
frame_movement = fm - selected_marker_original_times.at(i);
|
||||
break;
|
||||
}
|
||||
@@ -179,7 +190,7 @@ void TimelineHeader::mouseMoveEvent(QMouseEvent* event) {
|
||||
} else {
|
||||
resizing_workarea = false;
|
||||
unsetCursor();
|
||||
if (sequence->using_workarea) {
|
||||
if (sequence != NULL && sequence->using_workarea) {
|
||||
long min_frame = getHeaderFrameFromScreenPoint(event->pos().x() - CLICK_RANGE) - 1;
|
||||
long max_frame = getHeaderFrameFromScreenPoint(event->pos().x() + CLICK_RANGE) + 1;
|
||||
if (sequence->workarea_in > min_frame && sequence->workarea_in < max_frame) {
|
||||
@@ -198,7 +209,7 @@ void TimelineHeader::mouseMoveEvent(QMouseEvent* event) {
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineHeader::mouseReleaseEvent(QMouseEvent* event) {
|
||||
void TimelineHeader::mouseReleaseEvent(QMouseEvent*) {
|
||||
dragging = false;
|
||||
if (resizing_workarea) {
|
||||
undo_stack.push(new SetTimelineInOutCommand(sequence, true, temp_workarea_in, temp_workarea_out));
|
||||
@@ -248,9 +259,9 @@ void TimelineHeader::delete_markers() {
|
||||
}
|
||||
|
||||
void TimelineHeader::paintEvent(QPaintEvent*) {
|
||||
if (sequence != NULL) {
|
||||
if (sequence != NULL && zoom > 0) {
|
||||
QPainter p(this);
|
||||
int yoff = height()/2;
|
||||
int yoff = (text_enabled) ? height()/2 : 0;
|
||||
|
||||
double interval = sequence->frame_rate;
|
||||
int textWidth = 0;
|
||||
@@ -278,14 +289,15 @@ void TimelineHeader::paintEvent(QPaintEvent*) {
|
||||
if (lineX > width()) break;
|
||||
if (next_lineX > 0 && lineX > lastLineX+LINE_MIN_PADDING) {
|
||||
// draw text
|
||||
if (lineX-textWidth > lastTextBoundary) {
|
||||
if (text_enabled && lineX-textWidth > lastTextBoundary) {
|
||||
p.setPen(Qt::white);
|
||||
QString timecode = frame_to_timecode(frame + in_visible, config.timecode_view, sequence->frame_rate);
|
||||
textWidth = fm.width(timecode)>>1;
|
||||
if (lineX + textWidth > 0) {
|
||||
int text_x = qMax(lineX-textWidth, 0);
|
||||
lastTextBoundary = text_x+textWidth+textWidth;
|
||||
p.drawText(QRect(text_x, 0, lastTextBoundary, yoff), timecode);
|
||||
int fullTextWidth = fm.width(timecode);
|
||||
textWidth = fullTextWidth>>1;
|
||||
int text_x = lineX-textWidth;
|
||||
lastTextBoundary = lineX+textWidth;
|
||||
if (lastTextBoundary >= 0) {
|
||||
p.drawText(QRect(text_x, 0, fullTextWidth, yoff), timecode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,5 +363,5 @@ void TimelineHeader::paintEvent(QPaintEvent*) {
|
||||
path.lineTo(in_x+PLAYHEAD_SIZE, yoff);
|
||||
path.lineTo(start);
|
||||
p.fillPath(path, Qt::red);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ public:
|
||||
|
||||
bool snapping;
|
||||
|
||||
void show_text(bool enable);
|
||||
|
||||
void update_zoom(double z);
|
||||
|
||||
void delete_markers();
|
||||
@@ -57,6 +59,9 @@ private:
|
||||
|
||||
int scroll;
|
||||
|
||||
int height_actual;
|
||||
bool text_enabled;
|
||||
|
||||
signals:
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user