massive rewrite of project data system

This commit is contained in:
itsmattkc
2018-12-13 14:29:09 +11:00
parent 6c3197aac6
commit ac1cb9d14f
44 changed files with 2562 additions and 2158 deletions
+75 -65
View File
@@ -1,7 +1,7 @@
#include "sourcetable.h"
#include "panels/project.h"
#include "io/media.h"
#include "project/footage.h"
#include "panels/timeline.h"
#include "panels/viewer.h"
#include "panels/panels.h"
@@ -10,6 +10,8 @@
#include "project/sequence.h"
#include "mainwindow.h"
#include "io/config.h"
#include "project/media.h"
#include "debug.h"
#include <QDragEnterEvent>
#include <QMimeData>
@@ -22,16 +24,16 @@
#include <QDir>
#include <QProcess>
SourceTable::SourceTable(QWidget* parent) : QTreeWidget(parent) {
SourceTable::SourceTable(QWidget* parent) : QTreeView(parent) {
editing_item = NULL;
setSortingEnabled(true);
sortByColumn(0, Qt::AscendingOrder);
rename_timer.setInterval(1000);
setContextMenuPolicy(Qt::CustomContextMenu);
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()));
connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(item_click(const QModelIndex&)));
//connect(this, SIGNAL(itemChanged(Media*,int)), this, SLOT(item_renamed(Media*)));
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu()));
}
void SourceTable::show_context_menu() {
@@ -43,10 +45,14 @@ void SourceTable::show_context_menu() {
QAction* new_folder_action = menu.addAction("New Folder...");
connect(new_folder_action, SIGNAL(triggered(bool)), mainWindow, SLOT(on_actionFolder_triggered()));
if (selectedItems().size() > 0) {
if (selectedItems().size() == 1) {
QModelIndexList selected_items = selectionModel()->selectedRows();
if (selected_items.size() > 0) {
Media* m = static_cast<Media*>(selected_items.at(0).internalPointer());
if (selected_items.size() == 1) {
// replace footage
int type = get_type_from_tree(selectedItems().at(0));
int type = m->get_type();
if (type == MEDIA_TYPE_FOOTAGE) {
QAction* replace_action = menu.addAction("Replace/Relink Media");
connect(replace_action, SIGNAL(triggered(bool)), panel_project, SLOT(replace_selected_file()));
@@ -69,11 +75,11 @@ void SourceTable::show_context_menu() {
// duplicate item
bool all_sequences = true;
bool all_footage = true;
for (int i=0;i<selectedItems().size();i++) {
if (get_type_from_tree(selectedItems().at(i)) != MEDIA_TYPE_SEQUENCE) {
for (int i=0;i<selected_items.size();i++) {
if (m->get_type() != MEDIA_TYPE_SEQUENCE) {
all_sequences = false;
}
if (get_type_from_tree(selectedItems().at(i)) != MEDIA_TYPE_FOOTAGE) {
if (m->get_type() != MEDIA_TYPE_FOOTAGE) {
all_footage = false;
}
}
@@ -99,7 +105,7 @@ void SourceTable::show_context_menu() {
QAction* delete_action = menu.addAction("Delete");
connect(delete_action, SIGNAL(triggered(bool)), panel_project, SLOT(delete_selected_media()));
if (selectedItems().size() == 1) {
if (selected_items.size() == 1) {
QAction* properties_action = menu.addAction("Properties...");
connect(properties_action, SIGNAL(triggered(bool)), panel_project, SLOT(open_properties()));
}
@@ -109,20 +115,19 @@ void SourceTable::show_context_menu() {
}
void SourceTable::create_seq_from_selected() {
if (!selectedItems().isEmpty()) {
QVector<void*> media_list;
QVector<int> type_list;
for (int i=0;i<selectedItems().size();i++) {
QTreeWidgetItem* item = selectedItems().at(i);
media_list.append(get_media_from_tree(item));
type_list.append(get_type_from_tree(item));
QModelIndexList selected_items = selectionModel()->selectedRows();
if (!selected_items.isEmpty()) {
QVector<Media*> media_list;
for (int i=0;i<selected_items.size();i++) {
media_list.append(static_cast<Media*>(selected_items.at(i).internalPointer()));
}
ComboAction* ca = new ComboAction();
Sequence* s = create_sequence_from_media(media_list, type_list);
Sequence* s = create_sequence_from_media(media_list);
// add clips to it
panel_timeline->create_ghosts_from_media(s, 0, media_list, type_list);
panel_timeline->create_ghosts_from_media(s, 0, media_list);
panel_timeline->add_clips_from_ghosts(ca, s);
panel_project->new_sequence(ca, s, true, NULL);
@@ -131,7 +136,8 @@ void SourceTable::create_seq_from_selected() {
}
void SourceTable::reveal_in_browser() {
Media* m = get_footage_from_tree(selectedItems().at(0));
QModelIndexList selected_items = selectionModel()->selectedRows();
Footage* m = static_cast<Footage*>(selected_items.at(0).internalPointer());
#if defined(Q_OS_WIN)
QStringList args;
@@ -153,12 +159,9 @@ void SourceTable::reveal_in_browser() {
#endif
}
void SourceTable::item_renamed(QTreeWidgetItem* item) {
void SourceTable::item_renamed(Media* item) {
if (editing_item == item) {
MediaRename* mr = new MediaRename();
mr->from = editing_item_name;
mr->item = editing_item;
mr->to = editing_item->text(0);
MediaRename* mr = new MediaRename(item, "idk");
undo_stack.push(mr);
editing_item = NULL;
}
@@ -171,37 +174,41 @@ void SourceTable::stop_rename_timer() {
void SourceTable::rename_interval() {
stop_rename_timer();
if (hasFocus() && editing_item != NULL) {
editing_item_name = editing_item->text(0);
editItem(editing_item, 0);
edit(editing_index);
//editItem(editing_item, 0);
}
}
void SourceTable::item_click(QTreeWidgetItem* item, int column) {
if (column == 0 && selectedItems().size() == 1) {
if (editing_item == item) {
void SourceTable::item_click(const QModelIndex& index) {
if (selectionModel()->selectedRows().size() == 1 && index.column() == 0) {
Media* m = static_cast<Media*>(index.internalPointer());
if (editing_item == m) {
rename_timer.start();
} else {
editing_item = m;
editing_index = index;
}
editing_item = item;
}
}
void SourceTable::mousePressEvent(QMouseEvent* event) {
stop_rename_timer();
QTreeWidget::mousePressEvent(event);
QTreeView::mousePressEvent(event);
}
void SourceTable::mouseDoubleClickEvent(QMouseEvent* ) {
void SourceTable::mouseDoubleClickEvent(QMouseEvent* e) {
stop_rename_timer();
if (selectedItems().count() == 0) {
QModelIndexList selected_items = selectionModel()->selectedRows();
if (selected_items.size() == 0) {
panel_project->import_dialog();
} else if (selectedItems().count() == 1) {
QTreeWidgetItem* item = selectedItems().at(0);
switch (get_type_from_tree(item)) {
} else if (selected_items.size() == 1) {
Media* item = static_cast<Media*>(selected_items.at(0).internalPointer());
switch (item->get_type()) {
case MEDIA_TYPE_FOOTAGE:
panel_footage_viewer->set_media(get_type_from_tree(item), get_media_from_tree(item));
panel_footage_viewer->set_media(item);
panel_footage_viewer->setFocus();
break;
case MEDIA_TYPE_SEQUENCE:
undo_stack.push(new ChangeSequenceAction(get_sequence_from_tree(item)));
undo_stack.push(new ChangeSequenceAction(item->to_sequence()));
break;
}
}
@@ -211,7 +218,7 @@ void SourceTable::dragEnterEvent(QDragEnterEvent *event) {
if (event->mimeData()->hasUrls()) {
event->acceptProposedAction();
} else {
QTreeWidget::dragEnterEvent(event);
QTreeView::dragEnterEvent(event);
}
}
@@ -219,13 +226,14 @@ void SourceTable::dragMoveEvent(QDragMoveEvent *event) {
if (event->mimeData()->hasUrls()) {
event->acceptProposedAction();
} else {
QTreeWidget::dragMoveEvent(event);
QTreeView::dragMoveEvent(event);
}
}
void SourceTable::dropEvent(QDropEvent* event) {
const QMimeData* mimeData = event->mimeData();
QTreeWidgetItem* drop_item = itemAt(event->pos());
const QModelIndex& drop_item = indexAt(event->pos());
Media* m = static_cast<Media*>(drop_item.internalPointer());
if (mimeData->hasUrls()) {
// drag files in from outside
QList<QUrl> urls = mimeData->urls();
@@ -236,25 +244,25 @@ void SourceTable::dropEvent(QDropEvent* event) {
}
bool replace = false;
if (urls.size() == 1
&& drop_item != NULL
&& get_type_from_tree(drop_item) == MEDIA_TYPE_FOOTAGE
&& drop_item.isValid()
&& m->get_type() == MEDIA_TYPE_FOOTAGE
&& !QFileInfo(paths.at(0)).isDir()
&& config.drop_on_media_to_replace
&& QMessageBox::question(this, "Replace Media", "You dropped a file onto '" + drop_item->text(0) + "'. Would you like to replace it with the dropped file?", QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) {
&& QMessageBox::question(this, "Replace Media", "You dropped a file onto '" + m->get_name() + "'. Would you like to replace it with the dropped file?", QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) {
replace = true;
panel_project->replace_media(drop_item, paths.at(0));
panel_project->replace_media(m, paths.at(0));
}
if (!replace) {
QTreeWidgetItem* parent = NULL;
if (drop_item != NULL) {
if (get_type_from_tree(drop_item) == MEDIA_TYPE_FOLDER) {
parent = drop_item;
QModelIndex parent;
if (drop_item.isValid()) {
if (m->get_type() == MEDIA_TYPE_FOLDER) {
parent = drop_item;
} else {
parent = drop_item->parent();
parent = drop_item.parent();
}
}
if (parent != NULL) parent->setExpanded(true);
panel_project->process_file_list(false, paths, parent, NULL);
if (parent.isValid()) setExpanded(parent, true);
panel_project->process_file_list(false, paths, static_cast<Media*>(parent.internalPointer()), NULL);
}
}
event->acceptProposedAction();
@@ -263,24 +271,26 @@ void SourceTable::dropEvent(QDropEvent* event) {
// dragging files within project
// if we dragged to the root OR dragged to a folder
if (drop_item == NULL || (drop_item != NULL && get_type_from_tree(drop_item) == MEDIA_TYPE_FOLDER)) {
QVector<QTreeWidgetItem*> move_items;
QList<QTreeWidgetItem*> selected_items = selectedItems();
if (!drop_item.isValid() || (drop_item.isValid() && m->get_type() == MEDIA_TYPE_FOLDER)) {
QVector<Media*> move_items;
QModelIndexList selected_items = selectionModel()->selectedRows();
for (int i=0;i<selected_items.size();i++) {
QTreeWidgetItem* s = selected_items.at(i);
if (s->parent() != drop_item && s != drop_item) {
const QModelIndex& item = selected_items.at(i);
const QModelIndex& parent = item.parent();
Media* s = static_cast<Media*>(item.internalPointer());
if (parent != drop_item && item != drop_item) {
bool ignore = false;
if (s->parent() != NULL) {
if (parent.isValid()) {
// if child belongs to a selected parent, assume the user is just moving the parent and ignore the child
QTreeWidgetItem* par = s->parent();
while (par != NULL && !ignore) {
QModelIndex par = parent;
while (par.isValid() && !ignore) {
for (int j=0;j<selected_items.size();j++) {
if (par == selected_items.at(j)) {
ignore = true;
break;
}
}
par = par->parent();
par = par.parent();
}
}
if (!ignore) {
@@ -290,7 +300,7 @@ void SourceTable::dropEvent(QDropEvent* event) {
}
if (move_items.size() > 0) {
MediaMove* mm = new MediaMove(this);
mm->to = drop_item;
mm->to = m;
mm->items = move_items;
undo_stack.push(mm);
}
+7 -6
View File
@@ -1,13 +1,14 @@
#ifndef SOURCETABLE_H
#define SOURCETABLE_H
#include <QTreeWidget>
#include <QTreeView>
#include <QTimer>
#include <QUndoCommand>
class Project;
class Media;
class SourceTable : public QTreeWidget
class SourceTable : public QTreeView
{
Q_OBJECT
public:
@@ -20,13 +21,13 @@ protected:
void dropEvent(QDropEvent *event);
private:
QTimer rename_timer;
QTreeWidgetItem* editing_item;
QString editing_item_name;
Media* editing_item;
QModelIndex editing_index;
private slots:
void rename_interval();
void item_click(QTreeWidgetItem* item, int column);
void item_click(const QModelIndex& index);
void stop_rename_timer();
void item_renamed(QTreeWidgetItem *item);
void item_renamed(Media *item);
void show_context_menu();
void create_seq_from_selected();
void reveal_in_browser();
+32 -40
View File
@@ -8,7 +8,7 @@
#include "project/clip.h"
#include "panels/project.h"
#include "panels/timeline.h"
#include "io/media.h"
#include "project/footage.h"
#include "ui/sourcetable.h"
#include "panels/effectcontrols.h"
#include "panels/viewer.h"
@@ -16,6 +16,7 @@
#include "ui_timeline.h"
#include "mainwindow.h"
#include "ui/viewerwidget.h"
#include "project/media.h"
#include "debug.h"
#include "project/effect.h"
@@ -238,17 +239,14 @@ bool same_sign(int a, int b) {
void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
bool import_init = false;
QVector<void*> media_list;
QVector<int> type_list;
QVector<Media*> media_list;
panel_timeline->importing_files = false;
if (event->source() == panel_project->source_table) {
QList<QTreeWidgetItem*> items = panel_project->source_table->selectedItems();
media_list.resize(items.size());
type_list.resize(items.size());
for (int i=0;i<items.size();i++) {
type_list[i] = get_type_from_tree(items.at(i));
media_list[i] = get_media_from_tree(items.at(i));
QModelIndexList items = panel_project->source_table->selectionModel()->selectedRows();
media_list.resize(items.size());
for (int i=0;i<items.size();i++) {
media_list[i] = static_cast<Media*>(items.at(i).internalPointer());
}
import_init = true;
}
@@ -256,13 +254,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
if (event->source() == panel_footage_viewer->viewer_widget) {
Sequence* proposed_seq = panel_footage_viewer->seq;
if (proposed_seq != sequence) { // don't allow nesting the same sequence
if (proposed_seq->wrapper_sequence) {
type_list.append(MEDIA_TYPE_FOOTAGE);
media_list.append(proposed_seq->clips.at(0)->media);
} else {
type_list.append(MEDIA_TYPE_SEQUENCE);
media_list.append(proposed_seq);
}
media_list.append(panel_footage_viewer->media);
import_init = true;
}
}
@@ -281,12 +273,12 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
for (int i=0;i<panel_project->last_imported_media.size();i++) {
// waits for media to have a duration
// TODO would be much nicer if this was multithreaded
panel_project->last_imported_media.at(i)->ready_lock.lock();
panel_project->last_imported_media.at(i)->ready_lock.unlock();
Footage* f = panel_project->last_imported_media.at(i)->to_footage();
f->ready_lock.lock();
f->ready_lock.unlock();
if (panel_project->last_imported_media.at(i)->ready) {
media_list.append(panel_project->last_imported_media.at(i));
type_list.append(MEDIA_TYPE_FOOTAGE);
if (f->ready) {
media_list.append(panel_project->last_imported_media.at(i));
}
}
@@ -309,7 +301,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
// if no sequence, we're going to create a new one using the clips as a reference
entry_point = 0;
self_created_sequence = create_sequence_from_media(media_list, type_list);
self_created_sequence = create_sequence_from_media(media_list);
seq = self_created_sequence;
} else {
entry_point = panel_timeline->getTimelineFrameFromScreenPoint(event->pos().x());
@@ -317,7 +309,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
panel_timeline->drag_track_start = (bottom_align) ? -1 : 0;
}
panel_timeline->create_ghosts_from_media(seq, entry_point, media_list, type_list);
panel_timeline->create_ghosts_from_media(seq, entry_point, media_list);
panel_timeline->importing = true;
}
@@ -773,7 +765,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
if (c->track < 0) {
// default video effects (before custom effects)
c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_TRANSFORM, EFFECT_TYPE_EFFECT)));
c->media_type = MEDIA_TYPE_SOLID;
//c->media_type = MEDIA_TYPE_SOLID;
}
switch (panel_timeline->creating_object) {
@@ -807,7 +799,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
// default audio effects (after custom effects)
c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_VOLUME, EFFECT_TYPE_EFFECT)));
c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_PAN, EFFECT_TYPE_EFFECT)));
c->media_type = MEDIA_TYPE_TONE;
//c->media_type = MEDIA_TYPE_TONE;
}
push_undo = true;
@@ -1227,17 +1219,17 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) {
Clip* c = NULL;
if (g.clip != -1) c = sequence->clips.at(g.clip);
MediaStream* ms = NULL;
if (g.clip != -1 && c->media_type == MEDIA_TYPE_FOOTAGE) {
ms = static_cast<Media*>(c->media)->get_stream_from_file_index(c->track < 0, c->media_stream);
FootageStream* ms = NULL;
if (g.clip != -1 && c->media->get_type() == MEDIA_TYPE_FOOTAGE) {
ms = c->media->to_footage()->get_stream_from_file_index(c->track < 0, c->media_stream);
}
// validate ghosts for trimming
if (panel_timeline->creating) {
// i feel like we might need something here but we haven't so far?
} else if (panel_timeline->tool == TIMELINE_TOOL_SLIP) {
if (c->media_type == MEDIA_TYPE_SEQUENCE
|| (c->media_type == MEDIA_TYPE_FOOTAGE && !static_cast<Media*>(c->media)->get_stream_from_file_index(c->track < 0, c->media_stream)->infinite_length)) {
if (c->media->get_type() == MEDIA_TYPE_SEQUENCE
|| (ms != NULL && !ms->infinite_length)) {
// prevent slip moving a clip below 0 clip_in
validator = g.old_clip_in - frame_diff;
if (validator < 0) frame_diff += validator;
@@ -1257,7 +1249,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) {
if (validator < 0) frame_diff -= validator;
// prevent clip_in from going below 0
if (c->media_type == MEDIA_TYPE_SEQUENCE
if (c->media->get_type() == MEDIA_TYPE_SEQUENCE
|| (ms != NULL && !ms->infinite_length)) {
validator = g.old_clip_in + frame_diff;
if (validator < 0) frame_diff -= validator;
@@ -1268,7 +1260,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) {
if (validator < 1) frame_diff += (1 - validator);
// prevent clip length exceeding media length
if (c->media_type == MEDIA_TYPE_SEQUENCE
if (c->media->get_type() == MEDIA_TYPE_SEQUENCE
|| (ms != NULL && !ms->infinite_length)) {
validator = g.old_clip_in + g.ghost_length + frame_diff;
if (validator > g.media_length) frame_diff -= validator - g.media_length;
@@ -1349,14 +1341,14 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) {
if (validator > 0) frame_diff -= validator;
} else {
// prevent clip_in from going below 0
if (c->media_type == MEDIA_TYPE_SEQUENCE
if (c->media->get_type() == MEDIA_TYPE_SEQUENCE
|| (ms != NULL && !ms->infinite_length)) {
validator = g.old_clip_in + frame_diff;
if (validator < 0) frame_diff -= validator;
}
// prevent clip length exceeding media length
if (c->media_type == MEDIA_TYPE_SEQUENCE
if (c->media->get_type() == MEDIA_TYPE_SEQUENCE
|| (ms != NULL && !ms->infinite_length)) {
validator = g.old_clip_in + g.ghost_length + frame_diff;
if (validator > g.media_length) frame_diff -= validator - g.media_length;
@@ -2049,7 +2041,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
g.in = g.old_in = g.out = g.old_out = (panel_timeline->transition_tool_type == TA_OPENING_TRANSITION) ? c->timeline_in : c->timeline_out;
g.track = c->track;
g.clip = panel_timeline->transition_tool_pre_clip;
g.media_type = panel_timeline->transition_tool_type;
g.media_stream = panel_timeline->transition_tool_type;
g.trimming = false;
panel_timeline->ghosts.append(g);
@@ -2097,7 +2089,7 @@ int color_brightness(int r, int g, int b) {
return (0.2126*r + 0.7152*g + 0.0722*b);
}
void draw_waveform(Clip* clip, MediaStream* ms, long media_length, QPainter *p, const QRect& clip_rect, int waveform_start, int waveform_limit, double zoom) {
void draw_waveform(Clip* clip, FootageStream* ms, long media_length, QPainter *p, const QRect& clip_rect, int waveform_start, int waveform_limit, double zoom) {
int divider = ms->audio_channels*2;
int channel_height = clip_rect.height()/ms->audio_channels;
@@ -2225,11 +2217,11 @@ void TimelineWidget::paintEvent(QPaintEvent*) {
int thumb_x = clip_rect.x() + 1;
if (clip->media_type == MEDIA_TYPE_FOOTAGE) {
if (clip->media != NULL && clip->media->get_type() == MEDIA_TYPE_FOOTAGE) {
bool draw_checkerboard = false;
QRect checkerboard_rect(clip_rect);
Media* m = static_cast<Media*>(clip->media);
MediaStream* ms = m->get_stream_from_file_index(clip->track < 0, clip->media_stream);
Footage* m = clip->media->to_footage();
FootageStream* ms = m->get_stream_from_file_index(clip->track < 0, clip->media_stream);
if (ms == NULL) {
draw_checkerboard = true;
} else if (ms->preview_done) {
@@ -2641,5 +2633,5 @@ void TimelineWidget::setScroll(int s) {
}
void TimelineWidget::reveal_media() {
panel_project->reveal_media(rc_reveal_media);
panel_project->reveal_media(rc_reveal_media);
}
+2 -2
View File
@@ -13,7 +13,7 @@
struct Sequence;
struct Clip;
struct MediaStream;
struct FootageStream;
class Timeline;
class TimelineAction;
class QScrollBar;
@@ -21,7 +21,7 @@ class SetSelectionsCommand;
class QPainter;
bool same_sign(int a, int b);
void draw_waveform(Clip* clip, MediaStream* ms, long media_length, QPainter* p, const QRect& clip_rect, int waveform_start, int waveform_limit, double zoom);
void draw_waveform(Clip* clip, FootageStream* ms, long media_length, QPainter* p, const QRect& clip_rect, int waveform_start, int waveform_limit, double zoom);
class TimelineWidget : public QWidget {
Q_OBJECT
+58 -62
View File
@@ -10,7 +10,7 @@
#include "project/transition.h"
#include "playback/playback.h"
#include "playback/audio.h"
#include "io/media.h"
#include "project/footage.h"
#include "ui_timeline.h"
#include "playback/cacher.h"
#include "io/config.h"
@@ -18,6 +18,7 @@
#include "io/math.h"
#include "ui/collapsiblewidget.h"
#include "project/undo.h"
#include "project/media.h"
#include <QPainter>
#include <QAudioOutput>
@@ -126,7 +127,7 @@ void ViewerWidget::initializeGL() {
connect(context(), SIGNAL(aboutToBeDestroyed()), this, SLOT(delete_function()), Qt::DirectConnection);
retry_timer.start();
retry_timer.start();
}
//void ViewerWidget::resizeGL(int w, int h)
@@ -378,7 +379,7 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
if (!nests.isEmpty()) {
for (int i=0;i<nests.size();i++) {
s = static_cast<Sequence*>(nests.at(i)->media);
s = nests.at(i)->media->to_sequence();
playhead += nests.at(i)->clip_in - nests.at(i)->get_timeline_in_with_transition();
playhead = refactor_frame_number(playhead, nests.at(i)->sequence->frame_rate, s->frame_rate);
}
@@ -402,13 +403,11 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
if (!(!nests.isEmpty() && !same_sign(c->track, nests.last()->track))) {
bool clip_is_active = false;
switch (c->media_type) {
case MEDIA_TYPE_FOOTAGE:
{
Media* m = static_cast<Media*>(c->media);
if (c->media != NULL && c->media->get_type() == MEDIA_TYPE_FOOTAGE) {
Footage* m = c->media->to_footage();
if (!m->invalid && !(c->track >= 0 && !is_audio_device_set())) {
if (m->ready) {
MediaStream* ms = m->get_stream_from_file_index(c->track < 0, c->media_stream);
FootageStream* ms = m->get_stream_from_file_index(c->track < 0, c->media_stream);
if (ms != NULL && is_clip_active(c, playhead)) {
// if thread is already working, we don't want to touch this,
// but we also don't want to hang the UI thread
@@ -421,23 +420,18 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
close_clip(c);
}
} else {
dout << "[WARNING] Media was not ready, retrying...";
//dout << "[WARNING] Media '" + m->name + "' was not ready, retrying...";
texture_failed = true;
}
}
}
break;
case MEDIA_TYPE_SEQUENCE:
case MEDIA_TYPE_SOLID:
case MEDIA_TYPE_TONE:
if (is_clip_active(c, playhead)) {
if (!c->open) open_clip(c, !rendering);
clip_is_active = true;
} else if (c->open) {
close_clip(c);
}
break;
}
} else {
if (is_clip_active(c, playhead)) {
if (!c->open) open_clip(c, !rendering);
clip_is_active = true;
} else if (c->open) {
close_clip(c);
}
}
if (clip_is_active) {
bool added = false;
for (int j=0;j<current_clips.size();j++) {
@@ -469,7 +463,7 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
Clip* c = current_clips.at(i);
if (c->media_type == MEDIA_TYPE_FOOTAGE && !c->finished_opening) {
if (c->media != NULL && c->media->get_type() == MEDIA_TYPE_FOOTAGE && !c->finished_opening) {
dout << "[WARNING] Tried to display clip" << i << "but it's closed";
texture_failed = true;
} else {
@@ -478,23 +472,28 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
int video_width = c->getWidth();
int video_height = c->getHeight();
if (c->media_type == MEDIA_TYPE_FOOTAGE) {
// set up opengl texture
if (c->texture == NULL) {
c->texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
c->texture->setSize(c->stream->codecpar->width, c->stream->codecpar->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);
}
get_clip_frame(c, playhead);
textureID = c->texture->textureId();
} else if (c->media_type == MEDIA_TYPE_SEQUENCE) {
textureID = -1;
}
if (c->media != NULL) {
switch (c->media->get_type()) {
case MEDIA_TYPE_FOOTAGE:
// set up opengl texture
if (c->texture == NULL) {
c->texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
c->texture->setSize(c->stream->codecpar->width, c->stream->codecpar->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);
}
get_clip_frame(c, playhead);
textureID = c->texture->textureId();
break;
case MEDIA_TYPE_SEQUENCE:
textureID = -1;
break;
}
}
if (textureID == 0 && c->media_type != MEDIA_TYPE_SOLID) {
if (textureID == 0 && c->media != NULL) {
dout << "[WARNING] Texture hasn't been created yet";
texture_failed = true;
} else if (playhead >= c->get_timeline_in_with_transition()) {
@@ -519,21 +518,22 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
glViewport(0, 0, video_width, video_height);
// for nested sequences
if (c->media_type == MEDIA_TYPE_SEQUENCE) {
nests.append(c);
textureID = compose_sequence(nests, render_audio);
nests.removeLast();
fbo_switcher = true;
}
GLuint composite_texture;
GLuint composite_texture;
if (c->media_type == MEDIA_TYPE_SOLID) {
if (c->media == NULL) {
c->fbo[fbo_switcher]->bind();
glClear(GL_COLOR_BUFFER_BIT);
c->fbo[fbo_switcher]->release();
composite_texture = c->fbo[fbo_switcher]->texture();
} else {
// for nested sequences
if (c->media->get_type()== MEDIA_TYPE_SEQUENCE) {
nests.append(c);
textureID = compose_sequence(nests, render_audio);
nests.removeLast();
fbo_switcher = true;
}
composite_texture = draw_clip(c->fbo[fbo_switcher], textureID, true);
}
@@ -686,21 +686,17 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
}
} else {
if (render_audio || (config.enable_audio_scrubbing && audio_scrub)) {
switch (c->media_type) {
case MEDIA_TYPE_FOOTAGE:
case MEDIA_TYPE_TONE:
if (c->lock.tryLock()) {
if (c->media != NULL && c->media->get_type() == MEDIA_TYPE_SEQUENCE) {
nests.append(c);
compose_sequence(nests, render_audio);
nests.removeLast();
} else {
if (c->lock.tryLock()) {
// clip is not caching, start caching audio
cache_clip(c, playhead, c->audio_reset, !render_audio, nests);
c->lock.unlock();
}
break;
case MEDIA_TYPE_SEQUENCE:
nests.append(c);
compose_sequence(nests, render_audio);
nests.removeLast();
break;
}
cache_clip(c, playhead, c->audio_reset, !render_audio, nests);
c->lock.unlock();
}
}
}
// visually update all the keyframe values
+2 -2
View File
@@ -12,7 +12,7 @@
class Viewer;
struct Clip;
struct MediaStream;
struct FootageStream;
class QOpenGLFramebufferObject;
class Effect;
class EffectGizmo;
@@ -32,7 +32,7 @@ public:
bool waveform;
Clip* waveform_clip;
MediaStream* waveform_ms;
FootageStream* waveform_ms;
bool force_quit;
public slots: