@@ -1,5 +1,9 @@
|
||||
#include "transition.h"
|
||||
|
||||
#include "project/clip.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
Transition::Transition() {
|
||||
length = 30;
|
||||
link = NULL;
|
||||
@@ -10,3 +14,16 @@ Transition* Transition::copy() {
|
||||
}
|
||||
|
||||
void Transition::process_transition(float) {}
|
||||
|
||||
Transition* create_transition(int transition_id, Clip* c) {
|
||||
if (c->track < 0) {
|
||||
switch (transition_id) {
|
||||
case VIDEO_DISSOLVE_TRANSITION: return new CrossDissolveTransition();
|
||||
}
|
||||
} else {
|
||||
switch (transition_id) {
|
||||
}
|
||||
}
|
||||
qDebug() << "[ERROR] Invalid transition ID";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <QString>
|
||||
|
||||
struct Clip;
|
||||
|
||||
enum VideoTransitions {
|
||||
VIDEO_DISSOLVE_TRANSITION,
|
||||
VIDEO_TRANSITION_COUNT
|
||||
@@ -32,4 +34,6 @@ public:
|
||||
Transition* copy();
|
||||
};
|
||||
|
||||
Transition* create_transition(int transition_id, Clip* c);
|
||||
|
||||
#endif // TRANSITION_H
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define MEDIA_TYPE_FOOTAGE 0
|
||||
#define MEDIA_TYPE_SEQUENCE 1
|
||||
#define MEDIA_TYPE_FOLDER 2
|
||||
#define MEDIA_TYPE_SOLID 3
|
||||
|
||||
struct Sequence;
|
||||
|
||||
|
||||
+13
-7
@@ -1,4 +1,4 @@
|
||||
#include "mainwindow.h"
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include "io/config.h"
|
||||
@@ -273,6 +273,9 @@ void MainWindow::autorecover_interval() {
|
||||
bool MainWindow::save_project_as() {
|
||||
QString fn = QFileDialog::getSaveFileName(this, "Save Project As...", "", OLIVE_FILE_FILTER);
|
||||
if (!fn.isEmpty()) {
|
||||
if (!fn.endsWith(".ove", Qt::CaseInsensitive)) {
|
||||
fn += ".ove";
|
||||
}
|
||||
project_url = fn;
|
||||
panel_project->save_project();
|
||||
return true;
|
||||
@@ -308,12 +311,10 @@ void MainWindow::on_action_Save_Project_triggered()
|
||||
|
||||
void MainWindow::on_action_Open_Project_triggered()
|
||||
{
|
||||
if (can_close_project()) {
|
||||
QString fn = QFileDialog::getOpenFileName(this, "Open Project...", "", OLIVE_FILE_FILTER);
|
||||
if (!fn.isEmpty()) {
|
||||
project_url = fn;
|
||||
panel_project->load_project();
|
||||
}
|
||||
QString fn = QFileDialog::getOpenFileName(this, "Open Project...", "", OLIVE_FILE_FILTER);
|
||||
if (!fn.isEmpty() && can_close_project()) {
|
||||
project_url = fn;
|
||||
panel_project->load_project();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,6 +497,7 @@ void MainWindow::toolMenu_About_To_Be_Shown() {
|
||||
ui->actionEdit_Tool_Selects_Links->setChecked(panel_timeline->edit_tool_selects_links);
|
||||
ui->actionSelecting_Also_Seeks->setChecked(panel_timeline->select_also_seeks);
|
||||
ui->actionSeek_to_the_End_of_Pastes->setChecked(panel_timeline->paste_seeks);
|
||||
ui->actionToggle_Snapping->setChecked(panel_timeline->snapping);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionEdit_Tool_Selects_Links_triggered() {
|
||||
@@ -520,3 +522,7 @@ void MainWindow::on_actionSeek_to_the_End_of_Pastes_triggered()
|
||||
{
|
||||
panel_timeline->paste_seeks = !panel_timeline->paste_seeks;
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAdd_Default_Transition_triggered() {
|
||||
if (panel_timeline->focused()) panel_timeline->add_transition();
|
||||
}
|
||||
|
||||
@@ -135,6 +135,8 @@ private slots:
|
||||
|
||||
void on_actionSeek_to_the_End_of_Pastes_triggered();
|
||||
|
||||
void on_actionAdd_Default_Transition_triggered();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
void setup_layout();
|
||||
|
||||
+17
-2
@@ -24,7 +24,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>653</width>
|
||||
<height>17</height>
|
||||
<height>29</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
@@ -68,6 +68,7 @@
|
||||
<addaction name="actionDeselect_All"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionSplit_at_Playhead"/>
|
||||
<addaction name="actionAdd_Default_Transition"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuWindow">
|
||||
<property name="title">
|
||||
@@ -448,8 +449,14 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToggle_Snapping">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Toggle Snapping</string>
|
||||
<string>Snapping</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Snapping</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>S</string>
|
||||
@@ -556,6 +563,14 @@
|
||||
<string>Seek to the End of Pastes</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAdd_Default_Transition">
|
||||
<property name="text">
|
||||
<string>Add Default Transition</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Shift+D</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
|
||||
@@ -57,7 +57,8 @@ SOURCES += \
|
||||
ui/labelslider.cpp \
|
||||
dialogs/preferencesdialog.cpp \
|
||||
effects/transition.cpp \
|
||||
effects/crossdissolvetransition.cpp
|
||||
effects/crossdissolvetransition.cpp \
|
||||
ui/audiomonitor.cpp
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h \
|
||||
@@ -89,7 +90,8 @@ HEADERS += \
|
||||
io/previewgenerator.h \
|
||||
ui/labelslider.h \
|
||||
dialogs/preferencesdialog.h \
|
||||
effects/transition.h
|
||||
effects/transition.h \
|
||||
ui/audiomonitor.h
|
||||
|
||||
FORMS += \
|
||||
mainwindow.ui \
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.6.2, 2018-07-07T00:03:37. -->
|
||||
<!-- Written by QtCreator 4.6.2, 2018-07-08T11:23:30. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "panels/timeline.h"
|
||||
#include "project/sequence.h"
|
||||
#include "project/effect.h"
|
||||
#include "effects/transition.h"
|
||||
#include "io/previewgenerator.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
@@ -467,6 +468,12 @@ void Project::load_project() {
|
||||
} else if (stream.name() == "track") {
|
||||
stream.readNext();
|
||||
temp_clip->track = stream.text().toInt();
|
||||
} else if (stream.name() == "opening") {
|
||||
stream.readNext();
|
||||
temp_clip->opening_transition = create_transition(stream.text().toInt(), temp_clip);
|
||||
} else if (stream.name() == "closing") {
|
||||
stream.readNext();
|
||||
temp_clip->closing_transition = create_transition(stream.text().toInt(), temp_clip);
|
||||
} else if (stream.name() == "color") {
|
||||
for (int j=0;j<stream.attributes().size();j++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(j);
|
||||
@@ -585,6 +592,12 @@ void Project::save_project() {
|
||||
stream.writeTextElement("in", QString::number(c->timeline_in));
|
||||
stream.writeTextElement("out", QString::number(c->timeline_out));
|
||||
stream.writeTextElement("track", QString::number(c->track));
|
||||
if (c->opening_transition != NULL) {
|
||||
stream.writeTextElement("opening", QString::number(c->opening_transition->id));
|
||||
}
|
||||
if (c->closing_transition != NULL) {
|
||||
stream.writeTextElement("closing", QString::number(c->closing_transition->id));
|
||||
}
|
||||
stream.writeStartElement("color");
|
||||
stream.writeAttribute("r", QString::number(c->color_r));
|
||||
stream.writeAttribute("g", QString::number(c->color_g));
|
||||
|
||||
+30
-8
@@ -12,6 +12,7 @@
|
||||
#include "panels/viewer.h"
|
||||
#include "playback/cacher.h"
|
||||
#include "playback/playback.h"
|
||||
#include "effects/transition.h"
|
||||
#include "ui_viewer.h"
|
||||
|
||||
#include <QTime>
|
||||
@@ -126,6 +127,7 @@ void Timeline::reset_all_audio() {
|
||||
c->audio_buffer_write = 0;
|
||||
}
|
||||
}
|
||||
ui->audio_monitor->reset();
|
||||
clear_audio_ibuffer();
|
||||
}
|
||||
|
||||
@@ -173,6 +175,21 @@ int Timeline::get_track_height_size(bool video) {
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::add_transition() {
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip* c = sequence->get_clip(i);
|
||||
if (c != NULL && is_clip_selected(c)) {
|
||||
if (c->opening_transition == NULL) {
|
||||
c->opening_transition = create_transition(0, c);
|
||||
}
|
||||
if (c->closing_transition == NULL) {
|
||||
c->closing_transition = create_transition(0, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw_all_clips(true);
|
||||
}
|
||||
|
||||
int Timeline::calculate_track_height(int track, int value) {
|
||||
int index = (track < 0) ? qAbs(track + 1) : track;
|
||||
QVector<int>& vector = (track < 0) ? video_track_heights : audio_track_heights;
|
||||
@@ -242,6 +259,7 @@ void Timeline::repaint_timeline() {
|
||||
ui->audio_area->update();
|
||||
if (last_frame != playhead) {
|
||||
panel_viewer->viewer_widget->update();
|
||||
ui->audio_monitor->update();
|
||||
last_frame = playhead;
|
||||
}
|
||||
panel_viewer->update_playhead_timecode();
|
||||
@@ -343,20 +361,24 @@ void Timeline::set_zoom(bool in) {
|
||||
}
|
||||
|
||||
void Timeline::ripple(long ripple_point, long ripple_length) {
|
||||
// ripple all clips around the ripple_point
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip* c = sequence->get_clip(i);
|
||||
if (c != NULL && c->timeline_in >= ripple_point) {
|
||||
c->timeline_in += ripple_length;
|
||||
c->timeline_out += ripple_length;
|
||||
}
|
||||
}
|
||||
for (int i=0;i<selections.size();i++) {
|
||||
Selection& s = selections[i];
|
||||
if (s.in >= ripple_point) {
|
||||
s.in += ripple_length;
|
||||
s.out += ripple_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ripple the selections
|
||||
for (int i=0;i<selections.size();i++) {
|
||||
Selection& s = selections[i];
|
||||
// only ripple the selection if it's within range of the ripple point
|
||||
if (s.old_in >= ripple_point) {
|
||||
s.in += ripple_length;
|
||||
s.out += ripple_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::decheck_tool_buttons(QObject* sender) {
|
||||
|
||||
@@ -74,6 +74,7 @@ public:
|
||||
void update_sequence();
|
||||
void increase_track_height();
|
||||
void decrease_track_height();
|
||||
void add_transition();
|
||||
|
||||
int get_snap_range();
|
||||
int getScreenPointFromFrame(long frame);
|
||||
|
||||
+17
-1
@@ -330,7 +330,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>458</width>
|
||||
<width>408</width>
|
||||
<height>314</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -396,6 +396,16 @@
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="AudioMonitor" name="audio_monitor" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
@@ -412,6 +422,12 @@
|
||||
<header>ui/timelineheader.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>AudioMonitor</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>ui/audiomonitor.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../icons/icons.qrc"/>
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ void clear_audio_ibuffer() {
|
||||
|
||||
int get_buffer_offset_from_frame(long frame) {
|
||||
if (frame >= audio_ibuffer_frame) {
|
||||
return av_samples_get_buffer_size(NULL, av_get_channel_layout_nb_channels(sequence->audio_layout), qFloor(((frame-audio_ibuffer_frame)/sequence->frame_rate)*sequence->audio_frequency), AV_SAMPLE_FMT_S16, 1);
|
||||
return av_samples_get_buffer_size(NULL, av_get_channel_layout_nb_channels(sequence->audio_layout), qRound(((frame-audio_ibuffer_frame)/sequence->frame_rate)*sequence->audio_frequency), AV_SAMPLE_FMT_S16, 1);
|
||||
} else {
|
||||
qDebug() << "[WARNING] get_buffer_offset_from_frame called incorrectly";
|
||||
return 0;
|
||||
|
||||
@@ -189,12 +189,8 @@ long seconds_to_clip_frame(Clip* c, float seconds) {
|
||||
}
|
||||
|
||||
float clip_frame_to_seconds(Clip* c, long clip_frame) {
|
||||
// returns frame number as seconds (decimal)
|
||||
if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
return (double) clip_frame / av_q2d(c->stream->avg_frame_rate);
|
||||
} else {
|
||||
return (double) clip_frame / c->sequence->frame_rate;
|
||||
}
|
||||
// returns frame number in decimal seconds
|
||||
return (float) clip_frame / c->sequence->frame_rate;
|
||||
}
|
||||
|
||||
int retrieve_next_frame(Clip* c, AVFrame* f) {
|
||||
|
||||
+121
-134
@@ -62,7 +62,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
|
||||
bool ignore_infinite_length = false;
|
||||
Media* m = panel_project->get_media_from_tree(items.at(i));
|
||||
long duration = m->get_length_in_frames(sequence->frame_rate);
|
||||
Ghost g = {NULL, entry_point, entry_point + duration};
|
||||
Ghost g = {0, entry_point, entry_point + duration};
|
||||
g.media = m;
|
||||
g.clip_in = 0;
|
||||
for (int j=0;j<m->audio_tracks.size();j++) {
|
||||
@@ -289,7 +289,34 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
bool repaint = false;
|
||||
|
||||
if (panel_timeline->moving_proc) {
|
||||
if (event->modifiers() & Qt::AltModifier) { // if holding alt, duplicate rather than move
|
||||
// if we were RIPPLING, move all the clips
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) {
|
||||
long ripple_length, ripple_point;
|
||||
|
||||
// ripple_length becomes the length/number of frames we trimmed
|
||||
// ripple point becomes the point to ripple (i.e. the point after or before which we move every clip)
|
||||
if (panel_timeline->trim_in) {
|
||||
ripple_length = panel_timeline->ghosts.at(0).old_in - panel_timeline->ghosts.at(0).in;
|
||||
ripple_point = panel_timeline->ghosts.at(0).old_in;
|
||||
} else {
|
||||
// if we're trimming an out-point
|
||||
ripple_length = panel_timeline->ghosts.at(0).old_out - panel_timeline->ghosts.at(0).out;
|
||||
ripple_point = panel_timeline->ghosts.at(0).old_out;
|
||||
}
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
long comp_point;
|
||||
if (panel_timeline->trim_in) {
|
||||
comp_point = panel_timeline->ghosts.at(i).old_in;
|
||||
} else {
|
||||
comp_point = panel_timeline->ghosts.at(i).old_out;
|
||||
}
|
||||
if (ripple_point > comp_point) ripple_point = comp_point;
|
||||
}
|
||||
if (!panel_timeline->trim_in) ripple_length = -ripple_length;
|
||||
panel_timeline->ripple(ripple_point, ripple_length);
|
||||
}
|
||||
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_POINTER && (event->modifiers() & Qt::AltModifier)) { // if holding alt, duplicate rather than move
|
||||
// duplicate clips
|
||||
QVector<Clip*> copy_clips;
|
||||
QVector<int> old_clips;
|
||||
@@ -326,67 +353,43 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
} else {
|
||||
// move clips
|
||||
// TODO can we do this better than 3 consecutive for loops?
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
// step 1 - set clips that are moving to "undeletable" (to avoid step 2 deleting any part of them)
|
||||
sequence->get_clip(panel_timeline->ghosts[i].clip)->undeletable = true;
|
||||
}
|
||||
// step 2 - delete areas
|
||||
QVector<Selection> delete_areas;
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
const Ghost& g = panel_timeline->ghosts.at(i);
|
||||
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_POINTER) {
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_POINTER) {
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
// step 1 - set clips that are moving to "undeletable" (to avoid step 2 deleting any part of them)
|
||||
sequence->get_clip(panel_timeline->ghosts[i].clip)->undeletable = true;
|
||||
}
|
||||
// step 2 - delete areas
|
||||
QVector<Selection> delete_areas;
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
// step 2 - delete anything that exists in area that clip is moving to
|
||||
// note: ripples are non-destructive so this is pointer-tool exclusive
|
||||
const Ghost& g = panel_timeline->ghosts.at(i);
|
||||
Selection s;
|
||||
s.in = g.in;
|
||||
s.out = g.out;
|
||||
s.track = g.track;
|
||||
delete_areas.append(s);
|
||||
}
|
||||
panel_timeline->delete_areas_and_relink(delete_areas);
|
||||
}
|
||||
panel_timeline->delete_areas_and_relink(delete_areas);
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
Ghost& g = panel_timeline->ghosts[i];
|
||||
|
||||
// step 3 - move clips
|
||||
Clip* c = sequence->get_clip(g.clip);
|
||||
c->timeline_in = g.in;
|
||||
c->timeline_out = g.out;
|
||||
c->track = g.track;
|
||||
c->clip_in = g.clip_in;
|
||||
c->timeline_in += (g.in - g.old_in);
|
||||
c->timeline_out += (g.out - g.old_out);
|
||||
c->track += (g.track - g.old_track);
|
||||
c->clip_in += (g.clip_in - g.old_clip_in);
|
||||
}
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
// step 4 - set clips back to deletable
|
||||
sequence->get_clip(panel_timeline->ghosts[i].clip)->undeletable = false;
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_POINTER) {
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
// step 4 - set clips back to deletable
|
||||
sequence->get_clip(panel_timeline->ghosts[i].clip)->undeletable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ripple ops
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) {
|
||||
long ripple_length, ripple_point;
|
||||
if (panel_timeline->trim_in) {
|
||||
ripple_length = panel_timeline->ghosts.at(0).old_in - panel_timeline->ghosts.at(0).in;
|
||||
ripple_point = (ripple_length < 0) ? panel_timeline->ghosts.at(0).old_in : panel_timeline->ghosts.at(0).in;
|
||||
} else {
|
||||
ripple_length = panel_timeline->ghosts.at(0).old_out - panel_timeline->ghosts.at(0).out;
|
||||
ripple_point = (ripple_length < 0) ? panel_timeline->ghosts.at(0).old_out : panel_timeline->ghosts.at(0).out;
|
||||
}
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
long comp_point;
|
||||
if (panel_timeline->trim_in) {
|
||||
comp_point = (ripple_length < 0) ? panel_timeline->ghosts.at(i).old_in : panel_timeline->ghosts.at(i).in;
|
||||
} else {
|
||||
comp_point = (ripple_length < 0) ? panel_timeline->ghosts.at(i).old_out : panel_timeline->ghosts.at(i).out;
|
||||
}
|
||||
if (ripple_point > comp_point) ripple_point = comp_point;
|
||||
}
|
||||
if (panel_timeline->trim_in) {
|
||||
panel_timeline->ripple(ripple_point, ripple_length);
|
||||
} else {
|
||||
panel_timeline->ripple(ripple_point, -ripple_length);
|
||||
}
|
||||
}
|
||||
panel_timeline->redraw_all_clips(true);
|
||||
} else if (panel_timeline->selecting) {
|
||||
// remove duplicate selections
|
||||
@@ -533,6 +536,8 @@ void TimelineWidget::update_ghosts(QPoint& mouse_pos) {
|
||||
Ghost& g = panel_timeline->ghosts[i];
|
||||
Clip* c = sequence->get_clip(g.clip);
|
||||
|
||||
validate_snapping(g, &frame_diff);
|
||||
|
||||
if (panel_timeline->trim_in) {
|
||||
// prevent clip length from being less than 1 frame long
|
||||
validator = g.ghost_length - frame_diff;
|
||||
@@ -546,25 +551,6 @@ void TimelineWidget::update_ghosts(QPoint& mouse_pos) {
|
||||
// prevent clip_in from going below 0
|
||||
validator = g.old_clip_in + frame_diff;
|
||||
if (validator < 0) frame_diff -= validator;
|
||||
}
|
||||
|
||||
// ripple ops
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) {
|
||||
for (int j=0;j<post_clips.size();j++) {
|
||||
// prevent any rippled clip from going below 0
|
||||
Clip* post = post_clips.at(j);
|
||||
validator = post->timeline_in - frame_diff;
|
||||
if (validator < 0) frame_diff += validator;
|
||||
|
||||
// prevent any post-clips colliding with pre-clips
|
||||
for (int k=0;k<pre_clips.size();k++) {
|
||||
Clip* pre = pre_clips.at(k);
|
||||
if (pre->track == post->track) {
|
||||
validator = post->timeline_in - frame_diff - pre->timeline_out;
|
||||
if (validator < 0) frame_diff += validator;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// prevent clip length from being less than 1 frame long
|
||||
@@ -575,26 +561,32 @@ void TimelineWidget::update_ghosts(QPoint& mouse_pos) {
|
||||
// prevent clip length exceeding media length
|
||||
validator = g.ghost_length + frame_diff;
|
||||
if (validator > g.media_length) frame_diff -= validator - g.media_length;
|
||||
}
|
||||
|
||||
// ripple ops
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) {
|
||||
for (int j=0;j<post_clips.size();j++) {
|
||||
Clip* post = post_clips.at(j);
|
||||
|
||||
// prevent any post-clips colliding with pre-clips
|
||||
for (int k=0;k<pre_clips.size();k++) {
|
||||
Clip* pre = pre_clips.at(k);
|
||||
if (pre->track == post->track) {
|
||||
validator = post->timeline_in + frame_diff - pre->timeline_out;
|
||||
if (validator < 0) frame_diff -= validator;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
validate_snapping(g, &frame_diff);
|
||||
// ripple ops
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) {
|
||||
for (int j=0;j<post_clips.size();j++) {
|
||||
// prevent any rippled clip from going below 0
|
||||
Clip* post = post_clips.at(j);
|
||||
validator = post->timeline_in - frame_diff;
|
||||
if (validator < 0) frame_diff += validator;
|
||||
|
||||
// prevent any post-clips colliding with pre-clips
|
||||
for (int k=0;k<pre_clips.size();k++) {
|
||||
Clip* pre = pre_clips.at(k);
|
||||
if (pre != post && pre->track == post->track) {
|
||||
if (panel_timeline->trim_in) {
|
||||
validator = post->timeline_in - frame_diff - pre->timeline_out;
|
||||
if (validator < 0) frame_diff += validator;
|
||||
} else {
|
||||
validator = post->timeline_in + frame_diff - pre->timeline_out;
|
||||
if (validator < 0) frame_diff -= validator;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// resize ghosts
|
||||
@@ -798,62 +790,51 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
|
||||
// ripple edit prep
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) {
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
// get clips before and after ripple point
|
||||
for (int j=0;j<sequence->clip_count();j++) {
|
||||
Clip* cc = sequence->get_clip(j);
|
||||
QVector<Clip*> axis_ghosts;
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
Clip* c = sequence->get_clip(panel_timeline->ghosts.at(i).clip);
|
||||
bool found = false;
|
||||
for (int j=0;j<axis_ghosts.size();j++) {
|
||||
Clip* cc = axis_ghosts.at(j);
|
||||
if (c->track == cc->track &&
|
||||
((panel_timeline->trim_in && c->timeline_in < cc->timeline_in) ||
|
||||
(!panel_timeline->trim_in && c->timeline_out > cc->timeline_out))) {
|
||||
axis_ghosts[j] = c;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
axis_ghosts.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (cc != NULL) {
|
||||
// don't cache any currently selected clips
|
||||
Clip* c = sequence->get_clip(panel_timeline->ghosts.at(i).clip);
|
||||
bool is_selected = false;
|
||||
for (int k=0;k<panel_timeline->ghosts.size();k++) {
|
||||
if (panel_timeline->ghosts.at(k).clip == j) {
|
||||
is_selected = true;
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip* c = sequence->get_clip(i);
|
||||
if (c != NULL && !panel_timeline->is_clip_selected(c)) {
|
||||
for (int j=0;j<axis_ghosts.size();j++) {
|
||||
Clip* axis = axis_ghosts.at(j);
|
||||
long comp_point = (panel_timeline->trim_in) ? axis->timeline_in : axis->timeline_out;
|
||||
bool clip_is_pre = (c->timeline_in < comp_point);
|
||||
QVector<Clip*>& clip_list = clip_is_pre ? pre_clips : post_clips;
|
||||
bool found = false;
|
||||
for (int k=0;k<clip_list.size();k++) {
|
||||
Clip* cached = clip_list.at(k);
|
||||
if (cached->track == c->track) {
|
||||
if (clip_is_pre == (c->timeline_in > cached->timeline_in)) {
|
||||
clip_list[k] = c;
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_selected) {
|
||||
if (cc->timeline_in < c->timeline_in) {
|
||||
// add clip to pre-cache UNLESS there is already a clip on that track closer to the ripple point
|
||||
bool found = false;
|
||||
for (int k=0;k<pre_clips.size();k++) {
|
||||
Clip* ccc = pre_clips.at(k);
|
||||
if (ccc->track == cc->track) {
|
||||
if (ccc->timeline_in < cc->timeline_in) {
|
||||
// clip is closer to ripple point than the one in cache, replace it
|
||||
ccc = cc;
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// no clip from that track in the cache, add it
|
||||
pre_clips.append(cc);
|
||||
}
|
||||
} else {
|
||||
// add clip to post-cache UNLESS there is already a clip on that track closer to the ripple point
|
||||
bool found = false;
|
||||
for (int k=0;k<post_clips.size();k++) {
|
||||
Clip* ccc = post_clips.at(k);
|
||||
if (ccc->track == cc->track) {
|
||||
if (ccc->timeline_in > cc->timeline_in) {
|
||||
// clip is closer to ripple point than the one in cache, replace it
|
||||
ccc = cc;
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// no clip from that track in the cache, add it
|
||||
post_clips.append(cc);
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
clip_list.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// qDebug() << "found" << pre_clips.size() << "pres and" << post_clips.size() << "posts";
|
||||
}
|
||||
|
||||
init_ghosts();
|
||||
@@ -1062,15 +1043,21 @@ void TimelineWidget::redraw_clips() {
|
||||
}
|
||||
if (t != NULL) {
|
||||
int transition_width = panel_timeline->getScreenPointFromFrame(t->length);
|
||||
QRect transition_rect;
|
||||
int transition_height = clip_rect.height() * 0.6;
|
||||
if (transition_height <= TRACK_MIN_HEIGHT) {
|
||||
transition_height = clip_rect.height();
|
||||
}
|
||||
int tr_y = clip_rect.y() + ((clip_rect.height()-transition_height)/2);
|
||||
int tr_x = 0;
|
||||
if (i == 0) {
|
||||
transition_rect = QRect(clip_rect.x(), clip_rect.y(), transition_width, clip_rect.height());
|
||||
tr_x = clip_rect.x();
|
||||
text_rect.setX(text_rect.x()+transition_width);
|
||||
thumb_x += transition_width;
|
||||
} else {
|
||||
transition_rect = QRect(clip_rect.right()-transition_width, clip_rect.y(), transition_width, clip_rect.height());
|
||||
tr_x = clip_rect.right()-transition_width;
|
||||
text_rect.setWidth(text_rect.width()-transition_width);
|
||||
}
|
||||
QRect transition_rect = QRect(tr_x, tr_y, transition_width, transition_height);
|
||||
clip_painter.fillRect(transition_rect, transition_color);
|
||||
QRect transition_text_rect(transition_rect.x() + CLIP_TEXT_PADDING, transition_rect.y() + CLIP_TEXT_PADDING, transition_rect.width() - CLIP_TEXT_PADDING, transition_rect.height() - CLIP_TEXT_PADDING);
|
||||
if (transition_text_rect.width() > MAX_TEXT_WIDTH) {
|
||||
|
||||
+2
-2
@@ -50,8 +50,8 @@ private:
|
||||
bool track_resizing;
|
||||
int track_target;
|
||||
|
||||
QList<Clip*> pre_clips;
|
||||
QList<Clip*> post_clips;
|
||||
QVector<Clip*> pre_clips;
|
||||
QVector<Clip*> post_clips;
|
||||
|
||||
QPixmap clip_pixmap;
|
||||
// QPixmap selection_pixmap;
|
||||
|
||||
+15
-1
@@ -9,6 +9,7 @@
|
||||
#include "playback/playback.h"
|
||||
#include "playback/audio.h"
|
||||
#include "io/media.h"
|
||||
#include "ui_timeline.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
@@ -176,8 +177,21 @@ void ViewerWidget::paintGL() {
|
||||
int adjusted_read_index = audio_ibuffer_read%audio_ibuffer_size;
|
||||
int max_write = audio_ibuffer_size - adjusted_read_index;
|
||||
int actual_write = audio_io_device->write((const char*) audio_ibuffer+adjusted_read_index, max_write);
|
||||
memset(audio_ibuffer+adjusted_read_index, 0, actual_write);
|
||||
audio_ibuffer_read += actual_write;
|
||||
|
||||
// send samples to audio monitor cache
|
||||
if (panel_timeline->ui->audio_monitor->sample_cache_offset == -1) {
|
||||
panel_timeline->ui->audio_monitor->sample_cache_offset = panel_timeline->playhead;
|
||||
}
|
||||
long sample_cache_playhead = panel_timeline->ui->audio_monitor->sample_cache_offset + panel_timeline->ui->audio_monitor->sample_cache.size();
|
||||
int buffer_offset, buffer_offset_adjusted;
|
||||
while ((buffer_offset = get_buffer_offset_from_frame(sample_cache_playhead)) < audio_ibuffer_read) {
|
||||
buffer_offset_adjusted = buffer_offset%audio_ibuffer_size;
|
||||
panel_timeline->ui->audio_monitor->sample_cache.append((qint16) ((audio_ibuffer[buffer_offset_adjusted+1] << 8) | audio_ibuffer[buffer_offset_adjusted]));
|
||||
sample_cache_playhead++;
|
||||
}
|
||||
|
||||
memset(audio_ibuffer+adjusted_read_index, 0, actual_write);
|
||||
if (actual_write == max_write) {
|
||||
// got all the bytes, write again
|
||||
actual_write = audio_io_device->write((const char*) audio_ibuffer, audio_ibuffer_size);
|
||||
|
||||
Reference in New Issue
Block a user