From e83d87d6bad3dd075bac6cf7ec62fdd558576a17 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Mon, 4 Feb 2019 01:34:51 +1100 Subject: [PATCH] attached clip markers to footage markers --- io/loadthread.cpp | 60 +++++++++++++++++++++++++-------------- panels/project.cpp | 21 ++++++++++---- project/clip.cpp | 4 +-- project/footage.h | 9 ++++++ project/media.cpp | 15 +++++++++- project/media.h | 5 ++++ project/projectfilter.cpp | 9 +++--- 7 files changed, 88 insertions(+), 35 deletions(-) diff --git a/io/loadthread.cpp b/io/loadthread.cpp index ff44fffd1..7f4911be4 100644 --- a/io/loadthread.cpp +++ b/io/loadthread.cpp @@ -185,34 +185,34 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) { int folder = 0; Media* item = new Media(0); - Footage* m = new Footage(); + Footage* f = new Footage(); - m->using_inout = false; + f->using_inout = false; for (int j=0;jsave_id = attr.value().toInt(); + f->save_id = attr.value().toInt(); } else if (attr.name() == "folder") { folder = attr.value().toInt(); } else if (attr.name() == "name") { - m->name = attr.value().toString(); + f->name = attr.value().toString(); } else if (attr.name() == "url") { - m->url = attr.value().toString(); + f->url = attr.value().toString(); - if (!QFileInfo::exists(m->url)) { // if path is not absolute - QString proj_dir_test = proj_dir.absoluteFilePath(m->url); - QString internal_proj_dir_test = internal_proj_dir.absoluteFilePath(m->url); + if (!QFileInfo::exists(f->url)) { // if path is not absolute + QString proj_dir_test = proj_dir.absoluteFilePath(f->url); + QString internal_proj_dir_test = internal_proj_dir.absoluteFilePath(f->url); if (QFileInfo::exists(proj_dir_test)) { // if path is relative to the project's current dir - m->url = proj_dir_test; + f->url = proj_dir_test; qInfo() << "Matched" << attr.value().toString() << "relative to project's current directory"; } else if (QFileInfo::exists(internal_proj_dir_test)) { // if path is relative to the last directory the project was saved in - m->url = internal_proj_dir_test; + f->url = internal_proj_dir_test; qInfo() << "Matched" << attr.value().toString() << "relative to project's internal directory"; - } else if (m->url.contains('%')) { + } else if (f->url.contains('%')) { // hack for image sequences (qt won't be able to find the URL with %, but ffmpeg may) - m->url = internal_proj_dir_test; + f->url = internal_proj_dir_test; qInfo() << "Guess image sequence" << attr.value().toString() << "path to project's internal directory"; } else { qInfo() << "Failed to match" << attr.value().toString() << "to file"; @@ -221,25 +221,41 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) { qInfo() << "Matched" << attr.value().toString() << "with absolute path"; } } else if (attr.name() == "duration") { - m->length = attr.value().toLongLong(); + f->length = attr.value().toLongLong(); } else if (attr.name() == "using_inout") { - m->using_inout = (attr.value() == "1"); + f->using_inout = (attr.value() == "1"); } else if (attr.name() == "in") { - m->in = attr.value().toLong(); + f->in = attr.value().toLong(); } else if (attr.name() == "out") { - m->out = attr.value().toLong(); + f->out = attr.value().toLong(); } else if (attr.name() == "speed") { - m->speed = attr.value().toDouble(); + f->speed = attr.value().toDouble(); } else if (attr.name() == "alphapremul") { - m->alpha_is_premultiplied = (attr.value() == "1"); + f->alpha_is_premultiplied = (attr.value() == "1"); } else if (attr.name() == "proxy") { - m->proxy = (attr.value() == "1"); + f->proxy = (attr.value() == "1"); } else if (attr.name() == "proxypath") { - m->proxy_path = attr.value().toString(); + f->proxy_path = attr.value().toString(); } - } + } - item->set_footage(m); + while (!cancelled && !(stream.name() == child_search && stream.isEndElement()) && !stream.atEnd()) { + read_next_start_element(stream); + if (stream.name() == "marker" && stream.isStartElement()) { + Marker m; + for (int j=0;jmarkers.append(m); + } + } + + item->set_footage(f); if (folder == 0) { project_model.appendChild(nullptr, item); diff --git a/panels/project.cpp b/panels/project.cpp index f8c740829..725cd6152 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -970,6 +970,7 @@ void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, stream.writeAttribute("proxy", QString::number(f->proxy)); stream.writeAttribute("proxypath", f->proxy_path); + // save video stream metadata for (int j=0;jvideo_tracks.size();j++) { const FootageStream& ms = f->video_tracks.at(j); stream.writeStartElement("video"); @@ -978,8 +979,10 @@ void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, stream.writeAttribute("height", QString::number(ms.video_height)); stream.writeAttribute("framerate", QString::number(ms.video_frame_rate, 'f', 10)); stream.writeAttribute("infinite", QString::number(ms.infinite_length)); - stream.writeEndElement(); + stream.writeEndElement(); // video } + + // save audio stream metadata for (int j=0;jaudio_tracks.size();j++) { const FootageStream& ms = f->audio_tracks.at(j); stream.writeStartElement("audio"); @@ -987,9 +990,15 @@ void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, stream.writeAttribute("channels", QString::number(ms.audio_channels)); stream.writeAttribute("layout", QString::number(ms.audio_layout)); stream.writeAttribute("frequency", QString::number(ms.audio_frequency)); - stream.writeEndElement(); + stream.writeEndElement(); // audio } - stream.writeEndElement(); + + // save footage markers + for (int j=0;jmarkers.size();j++) { + save_marker(stream, f->markers.at(j)); + } + + stream.writeEndElement(); // footage media_id++; } else if (type == MEDIA_TYPE_SEQUENCE) { Sequence* s = m->to_sequence(); @@ -1062,8 +1071,8 @@ void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, } // save markers - // unnecessary for nested sequences since sequences have their own marker saving - if (c->media == nullptr || c->media->get_type() != MEDIA_TYPE_SEQUENCE) { + // only necessary for null media clips, since media has its own markers + if (c->media == nullptr) { for (int k=0;kget_markers().size();k++) { save_marker(stream, c->get_markers().at(k)); } @@ -1087,7 +1096,7 @@ void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, stream.writeEndElement(); // clip } } - for (int j=0;jmarkers.size();j++) { + for (int j=0;jmarkers.size();j++) { save_marker(stream, s->markers.at(j)); } stream.writeEndElement(); diff --git a/project/clip.cpp b/project/clip.cpp index 5516f124d..faafc8fb4 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -151,8 +151,8 @@ void Clip::queue_remove_earliest() { } QVector &Clip::get_markers() { - if (media != nullptr && media->get_type() == MEDIA_TYPE_SEQUENCE) { - return media->to_sequence()->markers; + if (media != nullptr) { + return media->get_markers(); } return markers; } diff --git a/project/footage.h b/project/footage.h index 749c3bf86..e42fc65f8 100644 --- a/project/footage.h +++ b/project/footage.h @@ -9,6 +9,8 @@ #include #include +#include "project/marker.h" + enum VideoInterlacingMode { VIDEO_PROGRESSIVE, VIDEO_TOP_FIELD_FIRST, @@ -45,6 +47,7 @@ struct Footage { Footage(); ~Footage(); + // footage metadata QString url; QString name; int64_t length; @@ -60,13 +63,19 @@ struct Footage { bool proxy; QString proxy_path; + // thumbnail/waveform generation PreviewGenerator* preview_gen; QMutex ready_lock; + // in/out points bool using_inout; long in; long out; + // markers + QVector markers; + + // functions long get_length_in_frames(double frame_rate); FootageStream *get_stream_from_file_index(bool video, int index); void reset(); diff --git a/project/media.cpp b/project/media.cpp index 92141ef7e..77b9f0c72 100644 --- a/project/media.cpp +++ b/project/media.cpp @@ -329,5 +329,18 @@ Media *Media::parentItem() { } void Media::removeChild(int i) { - children.removeAt(i); + children.removeAt(i); +} + +QVector &Media::get_markers() { + // returns the marker array from the internal object + // + // NOTE: if this media object is not footage or a sequence, the result is + // undefined - most likely a crash + + if (get_type() == MEDIA_TYPE_FOOTAGE) { + return to_footage()->markers; + } else { + return to_sequence()->markers; + } } diff --git a/project/media.h b/project/media.h index 3c04de933..b917d7495 100644 --- a/project/media.h +++ b/project/media.h @@ -4,6 +4,8 @@ #include #include +#include "project/marker.h" + #define MEDIA_TYPE_FOOTAGE 0 #define MEDIA_TYPE_SEQUENCE 1 #define MEDIA_TYPE_FOLDER 2 @@ -46,6 +48,9 @@ public: Media *parentItem(); void removeChild(int i); + // get markers from internal object + QVector& get_markers(); + bool root; int temp_id; int temp_id2; diff --git a/project/projectfilter.cpp b/project/projectfilter.cpp index 8b084b141..f6a4e58d6 100644 --- a/project/projectfilter.cpp +++ b/project/projectfilter.cpp @@ -41,10 +41,11 @@ bool ProjectFilter::filterAcceptsRow(int source_row, const QModelIndex &source_p // search markers if media is a sequene bool marker_contains_search = false; - if (media->get_type() == MEDIA_TYPE_SEQUENCE) { - Sequence* s = media->to_sequence(); - for (int i=0;imarkers.size();i++) { - if (s->markers.at(i).name.contains(search_filter, Qt::CaseInsensitive)) { + if (media->get_type() == MEDIA_TYPE_SEQUENCE + || media->get_type() == MEDIA_TYPE_FOOTAGE) { + QVector& markers = media->get_markers(); + for (int i=0;i