rewrite nearly complete

This commit is contained in:
itsmattkc
2019-04-03 01:38:01 +11:00
parent 8989333e99
commit 2d4714547b
102 changed files with 3213 additions and 2892 deletions
-83
View File
@@ -1,83 +0,0 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "clipboard.h"
#include "timeline/clip.h"
#include "effects/effect.h"
#include "effects/transition.h"
Clipboard::Clipboard() :
type_(CLIPBOARD_TYPE_CLIP)
{
}
void Clipboard::Append(VoidPtr obj)
{
clipboard_.append(obj);
}
void Clipboard::Clear()
{
clipboard_.clear();
clipboard_transitions_.clear();
}
int Clipboard::Count()
{
return clipboard_.size();
}
VoidPtr Clipboard::Get(int i)
{
return clipboard_.at(i);
}
bool Clipboard::IsEmpty()
{
return clipboard_.isEmpty();
}
Clipboard::Type Clipboard::type()
{
return type_;
}
bool Clipboard::DeleteClipsWithMedia(ComboAction *ca, Media *m)
{
if (type_ != CLIPBOARD_TYPE_CLIP) {
return false;
}
int delete_count = 0;
for (int i=0;i<clipboard_.size();i++) {
Clip* c = std::static_pointer_cast<Clip>(clipboard_.at(i)).get();
if (c->media() == m) {
ca->append(new RemoveClipsFromClipboard(i-delete_count));
delete_count++;
}
}
return (delete_count > 0);
}
Clipboard olive::clipboard;
-59
View File
@@ -1,59 +0,0 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef CLIPBOARD_H
#define CLIPBOARD_H
#include <QVector>
#include "effects/transition.h"
using VoidPtr = std::shared_ptr<void>;
class Clipboard {
public:
enum Type {
CLIPBOARD_TYPE_CLIP,
CLIPBOARD_TYPE_EFFECT
};
Clipboard();
void Append(VoidPtr obj);
void Clear();
int Count();
VoidPtr Get(int i);
void SetType(Type type);
bool IsEmpty();
Type type();
bool DeleteClipsWithMedia(ComboAction* ca, Media* m);
private:
Type type_;
QVector<TransitionPtr> clipboard_transitions_;
QVector<VoidPtr> clipboard_;
};
namespace olive {
extern Clipboard clipboard;
}
#endif // CLIPBOARD_H
+24 -1
View File
@@ -23,6 +23,7 @@
#include <QDebug>
#include <QtMath>
#include <QPainter>
#include <QCoreApplication>
#include <OpenColorIO/OpenColorIO.h>
namespace OCIO = OCIO_NAMESPACE::v1;
@@ -114,7 +115,7 @@ QString Footage::Colorspace()
return guess_colorspace;
}
return olive::CurrentConfig.ocio_default_input_colorspace;
return olive::config.ocio_default_input_colorspace;
}
void Footage::SetColorspace(const QString &cs)
@@ -154,3 +155,25 @@ FootageStream* Footage::get_stream_from_file_index(bool video, int index) {
}
return nullptr;
}
QString Footage::get_interlacing_name(int interlacing) {
switch (interlacing) {
case VIDEO_PROGRESSIVE: return QCoreApplication::translate("InterlacingName", "None (Progressive)");
case VIDEO_TOP_FIELD_FIRST: return QCoreApplication::translate("InterlacingName", "Top Field First");
case VIDEO_BOTTOM_FIELD_FIRST: return QCoreApplication::translate("InterlacingName", "Bottom Field First");
default: return QCoreApplication::translate("InterlacingName", "Invalid");
}
}
QString Footage::get_channel_layout_name(int channels, uint64_t layout) {
switch (channels) {
case 0: return QCoreApplication::translate("ChannelLayoutName", "Invalid");
case 1: return QCoreApplication::translate("ChannelLayoutName", "Mono");
case 2: return QCoreApplication::translate("ChannelLayoutName", "Stereo");
default: {
char buf[50];
av_get_channel_layout_string(buf, sizeof(buf), channels, layout);
return QString(buf);
}
}
}
+16 -10
View File
@@ -27,6 +27,7 @@
#include "global/config.h"
#include "rendering/renderfunctions.h"
#include "project/previewgenerator.h"
#include "project/projectfunctions.h"
#include "effects/internal/voideffect.h"
#include "global/debug.h"
#include "effects/effectloaders.h"
@@ -82,8 +83,10 @@ void LoadThread::load_effect(QXmlStreamReader& stream, Clip* c) {
// Find the clip with the ID referenced in the transition
int clip_id = attr.value().toInt();
for (int i=0;i<c->sequence->clips.size();i++) {
Clip* test_clip = c->sequence->clips.at(i).get();
QVector<Clip*> sequence_clips = c->track()->sequence()->GetAllClips();
for (int i=0;i<sequence_clips.size();i++) {
Clip* test_clip = sequence_clips.at(i);
if (test_clip->load_id == clip_id) {
sharing_clip = test_clip;
break;
@@ -262,7 +265,7 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
switch (type) {
case MEDIA_TYPE_FOLDER:
{
MediaPtr folder = panel_project->create_folder_internal(nullptr);
MediaPtr folder = olive::project::CreateFolder(nullptr);
folder->temp_id2 = 0;
for (int j=0;j<stream.attributes().size();j++) {
const QXmlStreamAttribute& attr = stream.attributes().at(j);
@@ -440,7 +443,9 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
int media_id = -1;
int stream_id = -1;
ClipPtr c = std::make_shared<Clip>(s.get());
Track* t;
ClipPtr c = std::make_shared<Clip>(t);
//ClipPtr c = std::make_shared<Clip>(s.get());
QColor clip_color;
ClipSpeed speed_info = c->speed();
@@ -459,8 +464,6 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
c->set_timeline_in(attr.value().toLong());
} else if (attr.name() == "out") {
c->set_timeline_out(attr.value().toLong());
} else if (attr.name() == "track") {
c->set_track(attr.value().toInt());
} else if (attr.name() == "r") {
clip_color.setRed(attr.value().toInt());
} else if (attr.name() == "g") {
@@ -518,7 +521,8 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
for (int k=0;k<stream.attributes().size();k++) {
const QXmlStreamAttribute& link_attr = stream.attributes().at(k);
if (link_attr.name() == "id") {
c->linked.append(link_attr.value().toInt());
// FIXME reimplement this
//c->linked.append(link_attr.value().toInt());
break;
}
}
@@ -546,11 +550,12 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
}
if (cancelled_) return false;
s->clips.append(c);
//s->clips.append(c);
}
}
if (cancelled_) return false;
/*
// correct links, clip IDs, transitions
for (int i=0;i<s->clips.size();i++) {
// correct links
@@ -585,6 +590,7 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
MediaPtr m = panel_project->create_sequence_internal(nullptr, s, false, parent);
loaded_sequences.append(m.get());
*/
}
break;
}
@@ -780,11 +786,11 @@ void LoadThread::success_func() {
olive::Global->update_project_filename(orig_filename);
} else {
panel_project->add_recent_project(filename_);
olive::Global->add_recent_project(filename_);
}
olive::Global->set_modified(autorecovery_);
if (open_seq != nullptr) {
olive::Global->set_sequence(open_seq);
Timeline::OpenSequence(open_seq);
}
}
+6 -28
View File
@@ -39,28 +39,6 @@ extern "C" {
#include "global/debug.h"
#include "global/timing.h"
QString get_interlacing_name(int interlacing) {
switch (interlacing) {
case VIDEO_PROGRESSIVE: return QCoreApplication::translate("InterlacingName", "None (Progressive)");
case VIDEO_TOP_FIELD_FIRST: return QCoreApplication::translate("InterlacingName", "Top Field First");
case VIDEO_BOTTOM_FIELD_FIRST: return QCoreApplication::translate("InterlacingName", "Bottom Field First");
default: return QCoreApplication::translate("InterlacingName", "Invalid");
}
}
QString get_channel_layout_name(int channels, uint64_t layout) {
switch (channels) {
case 0: return QCoreApplication::translate("ChannelLayoutName", "Invalid");
case 1: return QCoreApplication::translate("ChannelLayoutName", "Mono");
case 2: return QCoreApplication::translate("ChannelLayoutName", "Stereo");
default: {
char buf[50];
av_get_channel_layout_string(buf, sizeof(buf), channels, layout);
return QString(buf);
}
}
}
Media::Media() :
root(false),
type(-1),
@@ -172,7 +150,7 @@ void Media::update_tooltip(const QString& error) {
if (i > 0) {
tooltip += ", ";
}
tooltip += get_interlacing_name(f->video_tracks.at(i).video_interlacing);
tooltip += Footage::get_interlacing_name(f->video_tracks.at(i).video_interlacing);
}
}
@@ -193,7 +171,7 @@ void Media::update_tooltip(const QString& error) {
if (i > 0) {
tooltip += ", ";
}
tooltip += get_channel_layout_name(f->audio_tracks.at(i).audio_channels, f->audio_tracks.at(i).audio_layout);
tooltip += Footage::get_channel_layout_name(f->audio_tracks.at(i).audio_channels, f->audio_tracks.at(i).audio_layout);
}
// tooltip += "\n";
}
@@ -216,7 +194,7 @@ void Media::update_tooltip(const QString& error) {
QString::number(s->height),
QString::number(s->frame_rate),
QString::number(s->audio_frequency),
get_channel_layout_name(av_get_channel_layout_nb_channels(s->audio_layout), s->audio_layout)
Footage::get_channel_layout_name(av_get_channel_layout_nb_channels(s->audio_layout), s->audio_layout)
);
}
break;
@@ -288,7 +266,7 @@ bool Media::setData(int col, const QVariant &value) {
if (col == 0) {
QString n = value.toString();
if (!n.isEmpty() && get_name() != n) {
olive::UndoStack.push(new MediaRename(this, value.toString()));
olive::undo_stack.push(new MediaRename(this, value.toString()));
return true;
}
}
@@ -310,7 +288,7 @@ int Media::columnCount() const {
QString Media::GetStringDuration() {
if (get_type() == MEDIA_TYPE_SEQUENCE) {
Sequence* s = to_sequence().get();
return frame_to_timecode(s->GetEndFrame(), olive::CurrentConfig.timecode_view, s->frame_rate);
return frame_to_timecode(s->GetEndFrame(), olive::config.timecode_view, s->frame_rate);
}
if (get_type() == MEDIA_TYPE_FOOTAGE) {
Footage* f = to_footage();
@@ -320,7 +298,7 @@ QString Media::GetStringDuration() {
r = f->video_tracks.at(0).video_frame_rate * f->speed;
long len = f->get_length_in_frames(r);
if (len > 0) return frame_to_timecode(len, olive::CurrentConfig.timecode_view, r);
if (len > 0) return frame_to_timecode(len, olive::config.timecode_view, r);
}
return QString();
}
+7 -6
View File
@@ -218,8 +218,9 @@ void PreviewGenerator::finalize_media() {
media_->update_tooltip();
}
if (olive::ActiveSequence != nullptr) {
olive::ActiveSequence->RefreshClips(media_);
QVector<Media*> all_sequences = olive::project_model.GetAllSequences();
for (int i=0;i<all_sequences.size();i++) {
all_sequences.at(i)->to_sequence()->RefreshClipsUsingMedia(media_);
}
}
}
@@ -258,8 +259,8 @@ void PreviewGenerator::generate_waveform() {
// we only generate previews for video and audio
// and only if the thumbnail and waveform sizes are > 0
if ((fmt_ctx_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && olive::CurrentConfig.thumbnail_resolution > 0)
|| (fmt_ctx_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && olive::CurrentConfig.waveform_resolution > 0)) {
if ((fmt_ctx_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && olive::config.thumbnail_resolution > 0)
|| (fmt_ctx_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && olive::config.waveform_resolution > 0)) {
AVCodec* codec = avcodec_find_decoder(fmt_ctx_->streams[i]->codecpar->codec_id);
if (codec != nullptr) {
@@ -332,7 +333,7 @@ void PreviewGenerator::generate_waveform() {
if (s != nullptr) {
if (fmt_ctx_->streams[packet->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
if (!s->preview_done) {
int dstH = olive::CurrentConfig.thumbnail_resolution;
int dstH = olive::config.thumbnail_resolution;
int dstW = qRound(dstH * (float(temp_frame->width)/float(temp_frame->height)));
sws_ctx = sws_getContext(
@@ -401,7 +402,7 @@ void PreviewGenerator::generate_waveform() {
// `config.waveform_resolution` determines how many samples per second are stored in waveform.
// `sample_rate` is samples per second, so `interval` is how many samples are averaged in
// each "point" of the waveform
int interval = qFloor((temp_frame->sample_rate/olive::CurrentConfig.waveform_resolution)/4)*4;
int interval = qFloor((temp_frame->sample_rate/olive::config.waveform_resolution)/4)*4;
// get the amount of bytes in an audio sample
int sample_size = av_get_bytes_per_sample(static_cast<AVSampleFormat>(swr_frame->format));
+5 -5
View File
@@ -21,11 +21,11 @@ SequencePtr olive::project::CreateSequenceFromMedia(QVector<olive::timeline::Med
s->name = olive::project_model.GetNextSequenceName();
// Retrieve default Sequence settings from Config
s->width = olive::CurrentConfig.default_sequence_width;
s->height = olive::CurrentConfig.default_sequence_height;
s->frame_rate = olive::CurrentConfig.default_sequence_framerate;
s->audio_frequency = olive::CurrentConfig.default_sequence_audio_frequency;
s->audio_layout = olive::CurrentConfig.default_sequence_audio_channel_layout;
s->width = olive::config.default_sequence_width;
s->height = olive::config.default_sequence_height;
s->frame_rate = olive::config.default_sequence_framerate;
s->audio_frequency = olive::config.default_sequence_audio_frequency;
s->audio_layout = olive::config.default_sequence_audio_channel_layout;
bool got_video_values = false;
bool got_audio_values = false;
+21 -13
View File
@@ -20,11 +20,18 @@
#include "projectmodel.h"
#include <QMessageBox>
#include "panels/panels.h"
#include "panels/viewer.h"
#include "ui/viewerwidget.h"
#include "ui/mainwindow.h"
#include "project/media.h"
#include "global/debug.h"
#include "global/config.h"
#include "global/global.h"
#include "projectfunctions.h"
#include "previewgenerator.h"
ProjectModel olive::project_model;
@@ -297,18 +304,14 @@ MediaPtr ProjectModel::CreateSequence(ComboAction *ca, SequencePtr s, bool open,
ca->append(new AddMediaCommand(item, parent));
if (open) {
ca->append(new ChangeSequenceAction(s));
}
} else {
appendChild(parent, item);
if (open) {
olive::Global->set_sequence(s);
}
}
if (open) {
Timeline::OpenSequence(s);
}
return item;
@@ -404,7 +407,7 @@ void ProjectModel::process_file_list(QStringList& files, bool recursive, MediaPt
bool imported = false;
// retrieve the array of image formats from the user's configuration
QStringList image_sequence_formats = olive::CurrentConfig.img_seq_formats.split("|");
QStringList image_sequence_formats = olive::config.img_seq_formats.split("|");
// a cache of image sequence formatted URLS to assist the user in importing image sequences
QVector<QString> image_sequence_urls;
@@ -422,8 +425,8 @@ void ProjectModel::process_file_list(QStringList& files, bool recursive, MediaPt
// If this file is a directory, we'll recursively call this function again to process the directory's contents
if (QFileInfo(files.at(i)).isDir()) {
QString folder_name = get_file_name_from_path(files.at(i));
MediaPtr folder = CreateFolder(folder_name);
QString folder_name = QFileInfo(files.at(i)).fileName();
MediaPtr folder = olive::project::CreateFolder(folder_name);
QDir directory(files.at(i));
directory.setFilter(QDir::NoDotAndDotDot | QDir::AllEntries);
@@ -452,7 +455,7 @@ void ProjectModel::process_file_list(QStringList& files, bool recursive, MediaPt
if (file.endsWith(".ove", Qt::CaseInsensitive)) {
// This file is an Olive project file. Ask the user if they really want to import it.
if (QMessageBox::question(this,
if (QMessageBox::question(olive::MainWindow,
tr("Import a Project"),
tr("\"%1\" is an Olive project file. It will merge with this project. "
"Do you wish to continue?").arg(file),
@@ -556,7 +559,7 @@ void ProjectModel::process_file_list(QStringList& files, bool recursive, MediaPt
image_sequence_urls.append(new_filename);
// This does look like an image sequence, let's ask the user if it'll indeed be an image sequence
if (QMessageBox::question(this,
if (QMessageBox::question(olive::MainWindow,
tr("Image sequence detected"),
tr("The file '%1' appears to be part of an image sequence. "
"Would you like to import it as such?").arg(file),
@@ -640,7 +643,7 @@ void ProjectModel::process_file_list(QStringList& files, bool recursive, MediaPt
}
if (create_undo_action) {
if (imported) {
olive::UndoStack.push(ca);
olive::undo_stack.push(ca);
for (int i=0;i<last_imported_media.size();i++) {
// generate waveform/thumbnail in another thread
@@ -651,3 +654,8 @@ void ProjectModel::process_file_list(QStringList& files, bool recursive, MediaPt
}
}
}
QVector<Media *> ProjectModel::GetLastImportedMedia()
{
return last_imported_media;
}
+4 -2
View File
@@ -9,11 +9,12 @@
#include "global/config.h"
#include "projectmodel.h"
/*
void RecursiveSave() {
}
void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, const QModelIndex& parent) {
void save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, const QModelIndex& parent) {
for (int i=0;i<olive::project_model.rowCount(parent);i++) {
const QModelIndex& item = olive::project_model.index(i, 0, parent);
Media* m = olive::project_model.getItem(item);
@@ -57,6 +58,7 @@ void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only,
}
}
}
*/
void olive::Save(bool autorecovery)
{
@@ -91,7 +93,7 @@ void olive::Save(bool autorecovery)
file.close();
if (!autorecovery) {
add_recent_project(olive::ActiveProjectFilename);
olive::Global->add_recent_project(olive::ActiveProjectFilename);
olive::Global->set_modified(false);
}
}
+14 -14
View File
@@ -68,12 +68,11 @@ void SourcesCommon::create_seq_from_selected() {
ComboAction* ca = new ComboAction();
SequencePtr s = olive::project::CreateSequenceFromMedia(media_list);
// add clips to it
panel_timeline->create_ghosts_from_media(s.get(), 0, media_list);
panel_timeline->add_clips_from_ghosts(ca, s.get());
// add clips to it
s->AddClipsFromGhosts(ca, olive::timeline::CreateGhostsFromMedia(s.get(), 0, media_list));
olive::project_model.CreateSequence(ca, s, true, nullptr);
olive::UndoStack.push(ca);
olive::undo_stack.push(ca);
}
}
@@ -245,14 +244,14 @@ void SourcesCommon::replace_media(MediaPtr item, QString filename)
{
if (filename.isEmpty()) {
filename = QFileDialog::getOpenFileName(
this,
olive::MainWindow,
tr("Replace '%1'").arg(item->get_name()),
"",
tr("All Files") + " (*)");
}
if (!filename.isEmpty()) {
ReplaceMediaCommand* rmc = new ReplaceMediaCommand(item, filename);
olive::UndoStack.push(rmc);
olive::undo_stack.push(rmc);
}
}
@@ -276,7 +275,7 @@ void SourcesCommon::mouseDoubleClickEvent(const QModelIndexList& selected_items)
} else if (selected_items.size() == 1) {
Media* media = project_parent->item_to_media(selected_items.at(0));
if (media->get_type() == MEDIA_TYPE_SEQUENCE) {
olive::UndoStack.push(new ChangeSequenceAction(media->to_sequence()));
Timeline::OpenSequence(media->to_sequence());
} else {
OpenSelectedMediaInMediaViewer(project_parent->item_to_media(selected_items.at(0)));
}
@@ -302,7 +301,7 @@ void SourcesCommon::dropEvent(QWidget* parent,
&& drop_item.isValid()
&& m->get_type() == MEDIA_TYPE_FOOTAGE
&& !QFileInfo(paths.at(0)).isDir()
&& olive::CurrentConfig.drop_on_media_to_replace
&& olive::config.drop_on_media_to_replace
&& QMessageBox::question(
parent,
tr("Replace Media"),
@@ -320,7 +319,7 @@ void SourcesCommon::dropEvent(QWidget* parent,
parent = drop_item.parent();
}
}
olive::project_model.process_file_list(paths, false, nullptr, panel_project->item_to_media(parent));
olive::project_model.process_file_list(paths, false, nullptr, project_parent->item_to_media(parent));
}
}
event->acceptProposedAction();
@@ -359,7 +358,7 @@ void SourcesCommon::dropEvent(QWidget* parent,
MediaMove* mm = new MediaMove();
mm->to = m.get();
mm->items = move_items;
olive::UndoStack.push(mm);
olive::undo_stack.push(mm);
}
}
}
@@ -403,7 +402,7 @@ void SourcesCommon::rename_interval() {
void SourcesCommon::item_renamed(Media* item) {
if (editing_item == item) {
MediaRename* mr = new MediaRename(item, "idk");
olive::UndoStack.push(mr);
olive::undo_stack.push(mr);
editing_item = nullptr;
}
}
@@ -447,9 +446,10 @@ void SourcesCommon::clear_proxies_from_selected() {
f->proxy_path.clear();
}
if (olive::ActiveSequence != nullptr) {
QVector<Media*> all_sequences = olive::project_model.GetAllSequences();
for (int i=0;i<all_sequences.size();i++) {
// close all clips so we can delete any proxies requested to be deleted
olive::ActiveSequence->Close();
all_sequences.at(i)->to_sequence()->Close();
}
// delete proxies requested to be deleted
@@ -457,7 +457,7 @@ void SourcesCommon::clear_proxies_from_selected() {
QFile::remove(delete_list.at(i));
}
if (olive::ActiveSequence != nullptr) {
if (panel_sequence_viewer->seq != nullptr) {
// update viewer (will re-open active clips with original media)
panel_sequence_viewer->viewer_widget()->frame_update();
}