diff --git a/icons/icons.qrc b/icons/icons.qrc
index 3fc0faaf0..3bbbc0ea9 100644
--- a/icons/icons.qrc
+++ b/icons/icons.qrc
@@ -30,5 +30,11 @@
slide.png
slide-disabled.png
throbber.png
+ magnet.png
+ magnet-disabled.png
+ zoomin.png
+ zoomin-disabled.png
+ zoomout.png
+ zoomout-disabled.png
diff --git a/icons/magnet-disabled.png b/icons/magnet-disabled.png
new file mode 100644
index 000000000..4f19588b2
Binary files /dev/null and b/icons/magnet-disabled.png differ
diff --git a/icons/magnet.png b/icons/magnet.png
new file mode 100644
index 000000000..d5fbf13a3
Binary files /dev/null and b/icons/magnet.png differ
diff --git a/icons/zoomin-disabled.png b/icons/zoomin-disabled.png
new file mode 100644
index 000000000..ad008a3f5
Binary files /dev/null and b/icons/zoomin-disabled.png differ
diff --git a/icons/zoomin.png b/icons/zoomin.png
new file mode 100644
index 000000000..cc49cdebf
Binary files /dev/null and b/icons/zoomin.png differ
diff --git a/icons/zoomout-disabled.png b/icons/zoomout-disabled.png
new file mode 100644
index 000000000..a2b254cda
Binary files /dev/null and b/icons/zoomout-disabled.png differ
diff --git a/icons/zoomout.png b/icons/zoomout.png
new file mode 100644
index 000000000..60a07a488
Binary files /dev/null and b/icons/zoomout.png differ
diff --git a/main.cpp b/main.cpp
index 61fc82cca..0634f98c9 100644
--- a/main.cpp
+++ b/main.cpp
@@ -12,7 +12,7 @@ int main(int argc, char *argv[])
// QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true);
- QApplication a(argc, argv);
+ QApplication a(argc, argv);
MainWindow w;
w.show();
diff --git a/mainwindow.cpp b/mainwindow.cpp
index c5f4d7df3..53e6ce745 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -323,7 +323,15 @@ bool MainWindow::save_project() {
bool MainWindow::can_close_project() {
if (project_changed) {
- int r = QMessageBox::question(this, "Unsaved Project", "This project has changed since it was last saved. Would you like to save it before closing?", QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel, QMessageBox::Yes);
+ QMessageBox* m = new QMessageBox(
+ QMessageBox::Question,
+ "Unsaved Project",
+ "This project has changed since it was last saved. Would you like to save it before closing?",
+ QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel,
+ this
+ );
+ m->setWindowModality(Qt::WindowModal);
+ int r = m->exec();
if (r == QMessageBox::Yes) {
return save_project();
} else if (r == QMessageBox::Cancel) {
@@ -426,6 +434,10 @@ void MainWindow::on_actionCrash_triggered()
// intentionally tries to crash the program - mostly used for debugging
Timeline* temp = NULL;
temp->snapped = true;
+ int* kek;
+ kek[5] = 69;
+ kek[99999] = 420;
+ delete temp;
}
}
diff --git a/olive.pro b/olive.pro
index 5b70bd5c5..682d07435 100644
--- a/olive.pro
+++ b/olive.pro
@@ -8,7 +8,7 @@ QT += core gui multimedia opengl
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-TARGET = olive
+TARGET = Olive
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
@@ -123,6 +123,7 @@ win32 {
}
mac {
+ LIBS += -L/usr/local/lib -lavutil -lavformat -lavcodec -lswscale -lswresample
INCLUDEPATH = /usr/local/include
}
diff --git a/panels/timeline.cpp b/panels/timeline.cpp
index ee53c4cac..9c7b3d03d 100644
--- a/panels/timeline.cpp
+++ b/panels/timeline.cpp
@@ -53,7 +53,8 @@ Timeline::Timeline(QWidget *parent) :
ui->video_area->bottom_align = true;
- ui->splitter->setOpaqueResize(false);
+ ui->video_area->container = ui->videoScrollArea;
+ ui->audio_area->container = ui->audioScrollArea;
tool_buttons.append(ui->toolArrowButton);
tool_buttons.append(ui->toolEditButton);
diff --git a/panels/timeline.ui b/panels/timeline.ui
index f486cb108..9df286d0c 100644
--- a/panels/timeline.ui
+++ b/panels/timeline.ui
@@ -6,8 +6,8 @@
0
0
- 523
- 376
+ 901
+ 592
@@ -62,18 +62,6 @@
-
-
-
- 0
- 0
-
-
-
-
- 40
- 16777215
-
-
Pointer Tool (V)
@@ -85,12 +73,6 @@
:/icons/arrow.png
:/icons/arrow-disabled.png:/icons/arrow.png
-
-
- 20
- 20
-
-
true
@@ -98,12 +80,6 @@
-
-
-
- 40
- 16777215
-
-
Edit Tool (X)
@@ -115,12 +91,6 @@
:/icons/beam.png
:/icons/beam-disabled.png:/icons/beam.png
-
-
- 20
- 20
-
-
true
@@ -128,12 +98,6 @@
-
-
-
- 40
- 16777215
-
-
Ripple Tool (B)
@@ -145,12 +109,6 @@
:/icons/ripple.png
:/icons/ripple-disabled.png:/icons/ripple.png
-
-
- 20
- 20
-
-
true
@@ -158,12 +116,6 @@
-
-
-
- 40
- 16777215
-
-
Rolling Tool (N)
@@ -175,12 +127,6 @@
:/icons/rolling.png
:/icons/rolling-disabled.png:/icons/rolling.png
-
-
- 20
- 20
-
-
true
@@ -188,12 +134,6 @@
-
-
-
- 40
- 16777215
-
-
Razor Tool (C)
@@ -205,12 +145,6 @@
:/icons/razor.png
:/icons/razor-disabled.png:/icons/razor.png
-
-
- 20
- 20
-
-
true
@@ -218,12 +152,6 @@
-
-
-
- 40
- 16777215
-
-
Slip Tool (Y)
@@ -236,12 +164,6 @@
:/icons/slip-disabled.png
-
-
- 20
- 20
-
-
true
@@ -249,12 +171,6 @@
-
-
-
- 40
- 16777215
-
-
Slide Tool (U)
@@ -267,12 +183,6 @@
:/icons/slide-disabled.png
-
-
- 20
- 20
-
-
true
@@ -280,14 +190,14 @@
-
-
-
- 40
- 16777215
-
-
- S
+
+
+
+
+ :/icons/magnet.png
+ :/icons/magnet-disabled.png
+
true
@@ -299,33 +209,33 @@
-
-
-
- 40
- 16777215
-
-
Zoom In (=)
- +
+
+
+
+
+ :/icons/zoomin.png
+ :/icons/zoomin-disabled.png
+
-
-
-
- 40
- 16777215
-
-
Zoom Out (-)
- -
+
+
+
+
+ :/icons/zoomout.png
+ :/icons/zoomout-disabled.png
+
@@ -348,7 +258,7 @@
-
- Qt::ScrollBarAlwaysOn
+ Qt::ScrollBarAlwaysOff
Qt::ScrollBarAlwaysOn
@@ -361,11 +271,11 @@
0
0
- 408
- 327
+ 819
+ 551
-
+
0
@@ -399,27 +309,101 @@
Qt::Vertical
-
-
-
- 0
- 0
-
+
+
+ QFrame::NoFrame
-
- Qt::ClickFocus
+
+ Qt::ScrollBarAlwaysOn
+
+ Qt::ScrollBarAlwaysOff
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 802
+ 266
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Qt::ClickFocus
+
+
+
+
+
-
-
-
- 0
- 0
-
+
+
+ QFrame::NoFrame
-
- Qt::ClickFocus
+
+ Qt::ScrollBarAlwaysOn
+
+ Qt::ScrollBarAlwaysOff
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 802
+ 265
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ Qt::ClickFocus
+
+
+
+
+
diff --git a/panels/viewer.ui b/panels/viewer.ui
index 7a748347c..f850d20c7 100644
--- a/panels/viewer.ui
+++ b/panels/viewer.ui
@@ -104,183 +104,48 @@
true
-
-
- 0
- 0
-
-
-
-
- 36
- 0
-
-
-
-
- 16777215
- 16777215
-
-
-
-
-
:/icons/prev.png
:/icons/prev-disabled.png:/icons/prev.png
-
-
- 14
- 14
-
-
-
-
-
- 0
- 0
-
-
-
-
- 36
- 0
-
-
-
-
- 16777215
- 16777215
-
-
-
-
-
:/icons/rew.png
:/icons/rew-disabled.png:/icons/rew.png
-
-
- 14
- 14
-
-
-
-
-
- 0
- 0
-
-
-
-
- 36
- 0
-
-
-
-
- 16777215
- 16777215
-
-
-
-
-
:/icons/play.png
:/icons/play-disabled.png:/icons/play.png
-
-
- 14
- 14
-
-
-
-
-
- 0
- 0
-
-
-
-
- 36
- 0
-
-
-
-
- 16777215
- 16777215
-
-
-
-
-
:/icons/ff.png
:/icons/ff-disabled.png
-
-
- 14
- 14
-
-
-
-
-
- 0
- 0
-
-
-
-
- 36
- 0
-
-
-
-
- 16777215
- 16777215
-
-
-
-
-
:/icons/next.png
:/icons/next-disabled.png:/icons/next.png
-
-
- 14
- 14
-
-
-
diff --git a/playback/cacher.cpp b/playback/cacher.cpp
index d7e62a524..4ac960e83 100644
--- a/playback/cacher.cpp
+++ b/playback/cacher.cpp
@@ -180,21 +180,22 @@ void reset_cache(Clip* c, long target_frame) {
if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
// seeks to nearest keyframe (target_frame represents internal clip frame)
- av_seek_frame(c->formatCtx, ms->file_index, clip_frame_to_seconds(c, target_frame) / timebase, AVSEEK_FLAG_BACKWARD);
+
+ av_seek_frame(c->formatCtx, ms->file_index, (int64_t) qFloor(clip_frame_to_seconds(c, target_frame) / timebase), AVSEEK_FLAG_BACKWARD);
+ qDebug() << target_frame;
// play up to the frame we actually want
long retrieved_frame = 0;
AVFrame* temp = av_frame_alloc();
- do {
+ do {
retrieve_next_frame(c, temp);
if (retrieved_frame == 0) {
- if (target_frame != 0) {
- retrieved_frame = floor(temp->pts * timebase * av_q2d(av_guess_frame_rate(c->formatCtx, c->stream, temp)));
- }
+ if (target_frame != 0) retrieved_frame = floor(temp->pts * timebase * av_q2d(av_guess_frame_rate(c->formatCtx, c->stream, temp)));
} else {
retrieved_frame++;
}
} while (retrieved_frame < target_frame);
+
av_frame_free(&temp);
} else if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
// seek (target_frame represents timeline timecode in frames, not clip timecode)
diff --git a/playback/playback.cpp b/playback/playback.cpp
index 7097deaf4..578e6099c 100644
--- a/playback/playback.cpp
+++ b/playback/playback.cpp
@@ -75,7 +75,7 @@ void cache_clip(Clip* clip, long playhead, bool write_A, bool write_B, bool rese
void get_clip_frame(Clip* c, long playhead) {
if (c->open) {
- long clip_time = seconds_to_clip_frame(c, playhead_to_seconds(c, playhead));
+ long clip_time = refactor_frame_number(playhead - c->timeline_in + c->clip_in, c->sequence->frame_rate, av_q2d(av_guess_frame_rate(c->formatCtx, c->stream, c->frame)));
// do we need to update the texture?
MediaStream* ms = static_cast(c->media)->get_stream_from_file_index(c->media_stream);
@@ -139,15 +139,8 @@ void get_clip_frame(Clip* c, long playhead) {
bool write_A = (!using_cache_A && !c->cache_A.unread);
bool write_B = (!using_cache_B && !c->cache_B.unread);
if (write_A || write_B) {
- long playhead;
- if (cache_needs_reset) {
- // if we have no cache and need to seek, start us at the current playhead...
- playhead = clip_time;
- } else {
- // ...otherwise start at the end of the current cache
- playhead = cache_offset + c->cache_size;
- }
- cache_clip(c, playhead, write_A, write_B, cache_needs_reset, NULL);
+ // if we have no cache and need to seek, start us at the current playhead, otherwise start at the end of the current cache
+ cache_clip(c, (cache_needs_reset) ? clip_time : cache_offset + c->cache_size, write_A, write_B, cache_needs_reset, NULL);
}
c->lock.unlock();
}
@@ -175,12 +168,12 @@ void get_clip_frame(Clip* c, long playhead) {
}
}
-float playhead_to_seconds(Clip* c, long playhead) {
+double playhead_to_seconds(Clip* c, long playhead) {
// returns time in seconds
return (qMax((long) 0, playhead - c->timeline_in) + c->clip_in)/c->sequence->frame_rate;
}
-long seconds_to_clip_frame(Clip* c, float seconds) {
+long seconds_to_clip_frame(Clip* c, double seconds) {
// returns time as frame number (according to clip's frame rate)
if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
return floor(seconds*av_q2d(av_guess_frame_rate(c->formatCtx, c->stream, c->frame)));
@@ -190,9 +183,9 @@ long seconds_to_clip_frame(Clip* c, float seconds) {
}
}
-float clip_frame_to_seconds(Clip* c, long clip_frame) {
+double clip_frame_to_seconds(Clip* c, long clip_frame) {
// returns frame number in decimal seconds
- return (float) clip_frame / c->sequence->frame_rate;
+ return (double) clip_frame / av_q2d(av_guess_frame_rate(c->formatCtx, c->stream, c->frame));
}
int retrieve_next_frame(Clip* c, AVFrame* f) {
diff --git a/playback/playback.h b/playback/playback.h
index 25aa87c37..5acc5f359 100644
--- a/playback/playback.h
+++ b/playback/playback.h
@@ -19,9 +19,9 @@ void cache_video_worker(Clip* c, long playhead, ClipCache* cache);
void handle_media(Sequence* sequence, long playhead, bool multithreaded);
void reset_cache(Clip* c, long target_frame);
void get_clip_frame(Clip* c, long playhead);
-float playhead_to_seconds(Clip* c, long playhead);
-long seconds_to_clip_frame(Clip* c, float seconds);
-float clip_frame_to_seconds(Clip* c, long clip_frame);
+double playhead_to_seconds(Clip* c, long playhead);
+long seconds_to_clip_frame(Clip* c, double seconds);
+double clip_frame_to_seconds(Clip* c, long clip_frame);
int retrieve_next_frame(Clip* c, AVFrame* f);
void retrieve_next_frame_raw_data(Clip* c, AVFrame* output);
bool is_clip_active(Clip* c, long playhead);
diff --git a/project/clip.cpp b/project/clip.cpp
index 6d6721984..65bea6ae2 100644
--- a/project/clip.cpp
+++ b/project/clip.cpp
@@ -91,7 +91,7 @@ void Clip::reset_audio() {
audio_reset = true;
frame_sample_index = 0;
audio_buffer_write = 0;
- reached_end = false;
+ reached_end = false;
break;
case MEDIA_TYPE_SEQUENCE:
{
diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp
index 616146789..8c4381b82 100644
--- a/ui/timelinewidget.cpp
+++ b/ui/timelinewidget.cpp
@@ -1349,27 +1349,44 @@ int color_brightness(int r, int g, int b) {
void TimelineWidget::redraw_clips() {
// Draw clips
if (sequence != NULL) {
- int panel_width = panel_timeline->getScreenPointFromFrame(sequence->getEndFrame()) + 100;
+ // get widget width and height
+ int video_track_limit = 0;
+ int audio_track_limit = 0;
+ long end_frame = 0;
+ for (int i=0;iclip_count();i++) {
+ Clip* clip = sequence->get_clip(i);
+ if (clip != NULL) {
+ end_frame = qMax(end_frame, clip->timeline_out);
+ video_track_limit = qMin(video_track_limit, clip->track);
+ audio_track_limit = qMax(audio_track_limit, clip->track);
+ }
+ }
+ int panel_width = panel_timeline->getScreenPointFromFrame(end_frame) + 100;
+ int panel_height = 0;
+ if (bottom_align) {
+ for (int i=-1;i>=video_track_limit;i--) {
+ panel_height += panel_timeline->calculate_track_height(i, -1);
+ }
+ } else {
+ for (int i=0;i<=audio_track_limit;i++) {
+ panel_height += panel_timeline->calculate_track_height(i, -1);
+ }
+ }
- if (minimumWidth() != panel_width || clip_pixmap.height() != height()) {
+ if (minimumWidth() != panel_width || /*clip_pixmap.height() != height() || */panel_height != minimumHeight()) {
setMinimumWidth(panel_width);
- clip_pixmap = QPixmap(qMax(width(), panel_width), height());
+ container->setMinimumWidth(panel_width);
+ setMinimumHeight(panel_height);
+ clip_pixmap = QPixmap(qMax(width(), panel_width), qMax(height(), panel_height));
}
clip_pixmap.fill(Qt::transparent);
QPainter clip_painter(&clip_pixmap);
- int video_track_limit = 0;
- int audio_track_limit = 0;
+
QColor transition_color(255, 0, 0, 16);
for (int i=0;iclip_count();i++) {
Clip* clip = sequence->get_clip(i);
- if (clip != NULL && is_track_visible(clip->track)) {
- if (clip->track < 0 && clip->track < video_track_limit) { // video clip
- video_track_limit = clip->track;
- } else if (clip->track > audio_track_limit) {
- audio_track_limit = clip->track;
- }
-
+ if (clip != NULL && is_track_visible(clip->track)) {
QRect clip_rect(panel_timeline->getScreenPointFromFrame(clip->timeline_in), getScreenPointFromTrack(clip->track), clip->getLength() * panel_timeline->zoom, panel_timeline->calculate_track_height(clip->track, -1));
clip_painter.fillRect(clip_rect, QColor(clip->color_r, clip->color_g, clip->color_b));
@@ -1378,13 +1395,8 @@ void TimelineWidget::redraw_clips() {
QRect text_rect(clip_rect.left() + CLIP_TEXT_PADDING, clip_rect.top() + CLIP_TEXT_PADDING, clip_rect.width() - CLIP_TEXT_PADDING - 1, clip_rect.height() - CLIP_TEXT_PADDING - 1);
// draw clip transitions
- for (char i=0;i<2;i++) {
- Transition* t;
- if (i == 0) {
- t = clip->opening_transition;
- } else {
- t = clip->closing_transition;
- }
+ 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->getScreenPointFromFrame(t->length);
int transition_height = clip_rect.height() * 0.6;
@@ -1522,9 +1534,8 @@ void TimelineWidget::redraw_clips() {
}
} else {
// only draw lines for audio tracks
- for (int i=0;icalculate_track_height(i, -1);
+ for (int i=0;icalculate_track_height(i, -1);
clip_painter.drawLine(0, line_y, rect().width(), line_y);
}
}
diff --git a/ui/timelinewidget.h b/ui/timelinewidget.h
index debc9506f..ed56c0faa 100644
--- a/ui/timelinewidget.h
+++ b/ui/timelinewidget.h
@@ -19,11 +19,13 @@ class TimelineAction;
class TimelineWidget : public QWidget {
Q_OBJECT
public:
- explicit TimelineWidget(QWidget *parent = 0);
+ explicit TimelineWidget(QWidget *parent = 0);
bool bottom_align;
void redraw_clips();
+
+ QWidget* container;
protected:
void paintEvent(QPaintEvent*);
void resizeEvent(QResizeEvent*);
@@ -60,8 +62,7 @@ private:
int predicted_video_height;
double predicted_new_frame_rate;
int predicted_audio_freq;
- int predicted_audio_layout;
-
+ int predicted_audio_layout;
signals:
public slots:
diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp
index b69881fae..8058a96e5 100644
--- a/ui/viewerwidget.cpp
+++ b/ui/viewerwidget.cpp
@@ -89,12 +89,10 @@ void ViewerWidget::paintEvent(QPaintEvent *e) {
void ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
Sequence* s = sequence;
- long playhead = panel_timeline->playhead;
+ long playhead = panel_timeline->playhead;
+
if (nest != NULL) {
s = static_cast(nest->media);
-
-// qDebug() << "nested sequence was null:" << (s == NULL);
-
playhead += nest->clip_in - nest->timeline_in;
playhead = refactor_frame_number(playhead, sequence->frame_rate, s->frame_rate);
}