basic save support added

This commit is contained in:
itsmattkc
2018-06-10 00:14:29 -07:00
parent 1f8f3b0800
commit 94fae972cf
14 changed files with 196 additions and 25 deletions
+3
View File
@@ -3,6 +3,7 @@
#include "project/effect.h"
#include <QXmlStreamWriter>
class QSpinBox;
class QCheckBox;
@@ -52,6 +53,7 @@ public:
VolumeEffect(Clip* c);
void process_audio(uint8_t* samples, int nb_bytes);
Effect* copy();
void save(QXmlStreamWriter* stream);
QSpinBox* volume_val;
};
@@ -61,6 +63,7 @@ public:
PanEffect(Clip* c);
void process_audio(uint8_t* samples, int nb_bytes);
Effect* copy();
void save(QXmlStreamWriter* stream);
QSpinBox* pan_val;
};
+6 -5
View File
@@ -7,12 +7,9 @@
#include "ui/collapsiblewidget.h"
PanEffect::PanEffect(Clip* c) : Effect(c) {
container = new CollapsibleWidget();
container->setText(audio_effect_names[AUDIO_PAN_EFFECT]);
setup_effect(EFFECT_TYPE_AUDIO, AUDIO_PAN_EFFECT);
ui = new QWidget();
QGridLayout* ui_layout = new QGridLayout();
QGridLayout* ui_layout = new QGridLayout();
ui_layout->addWidget(new QLabel("Pan:"), 0, 0);
pan_val = new QSpinBox();
@@ -34,6 +31,10 @@ Effect* PanEffect::copy() {
return p;
}
void PanEffect::save(QXmlStreamWriter *stream) {
stream->writeTextElement("pan", QString::number(pan_val->value()));
}
void PanEffect::process_audio(uint8_t *samples, int nb_bytes) {
for (int i=0;i<nb_bytes;i+=4) {
int16_t left_sample = (int16_t) ((samples[i+1] << 8) | samples[i]);
+1 -4
View File
@@ -14,10 +14,7 @@
#include "io/media.h"
TransformEffect::TransformEffect(Clip* c) : Effect(c) {
container = new CollapsibleWidget();
container->setText(video_effect_names[VIDEO_TRANSFORM_EFFECT]);
ui = new QWidget();
setup_effect(EFFECT_TYPE_VIDEO, VIDEO_TRANSFORM_EFFECT);
QGridLayout* ui_layout = new QGridLayout();
+5 -4
View File
@@ -7,10 +7,7 @@
#include "ui/collapsiblewidget.h"
VolumeEffect::VolumeEffect(Clip* c) : Effect(c) {
container = new CollapsibleWidget();
container->setText(audio_effect_names[AUDIO_VOLUME_EFFECT]);
ui = new QWidget();
setup_effect(EFFECT_TYPE_AUDIO, AUDIO_VOLUME_EFFECT);
QGridLayout* ui_layout = new QGridLayout();
@@ -34,6 +31,10 @@ Effect* VolumeEffect::copy() {
return v;
}
void VolumeEffect::save(QXmlStreamWriter *stream) {
stream->writeTextElement("volume", QString::number(volume_val->value()));
}
void VolumeEffect::process_audio(uint8_t *samples, int nb_bytes) {
for (int i=0;i<nb_bytes;i+=2) {
int16_t full_sample = (int16_t) ((samples[i+1] << 8) | samples[i]);
+1
View File
@@ -24,6 +24,7 @@ struct Media
QVector<MediaStream> video_tracks;
QVector<MediaStream> audio_tracks;
Sequence* sequence;
int save_id;
long get_length_in_frames(float frame_rate);
};
+5
View File
@@ -203,3 +203,8 @@ void MainWindow::on_action_Paste_triggered()
panel_timeline->paste();
}
}
void MainWindow::on_action_Save_Project_triggered()
{
panel_project->save_project();
}
+2
View File
@@ -63,6 +63,8 @@ private slots:
void on_action_Paste_triggered();
void on_action_Save_Project_triggered();
private:
Ui::MainWindow *ui;
void setup_layout();
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.6.1, 2018-06-08T22:09:27. -->
<!-- Written by QtCreator 4.6.1, 2018-06-10T00:00:44. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
+136 -2
View File
@@ -2,15 +2,22 @@
#include "ui_project.h"
#include "io/media.h"
#include "panels/panels.h"
#include "panels/timeline.h"
#include "panels/viewer.h"
#include <QFileDialog>
#include <QString>
#include <QVariant>
#include <QDebug>
#include <QCharRef>
#include <QMessageBox>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include "panels/timeline.h"
#include "project/sequence.h"
#include "project/effect.h"
extern "C" {
#include <libavformat/avformat.h>
@@ -58,7 +65,7 @@ void Project::new_sequence(Sequence *s) {
QTreeWidgetItem* item = new QTreeWidgetItem();
item->setText(0, s->name);
item->setData(0, Qt::UserRole + 1, QVariant::fromValue(reinterpret_cast<quintptr>(m)));
set_media_of_tree(item, m);
ui->treeWidget->addTopLevelItem(item);
source_table = ui->treeWidget;
@@ -153,7 +160,7 @@ void Project::import_dialog() {
}
item->setText(0, m->name);
item->setText(1, QString::number(m->length));
item->setData(0, Qt::UserRole + 1, QVariant::fromValue(reinterpret_cast<quintptr>(m)));
set_media_of_tree(item, m);
ui->treeWidget->addTopLevelItem(item);
}
@@ -162,3 +169,130 @@ void Project::import_dialog() {
delete [] filename;
}
}
Media* Project::get_media_from_tree(QTreeWidgetItem* item) {
return reinterpret_cast<Media*>(item->data(0, Qt::UserRole + 1).value<quintptr>());
}
void Project::set_media_of_tree(QTreeWidgetItem* item, Media* media) {
item->setData(0, Qt::UserRole + 1, QVariant::fromValue(reinterpret_cast<quintptr>(media)));
}
void Project::remove_item(int i) {
Media* m = get_media_from_tree(ui->treeWidget->topLevelItem(i));
if (m->is_sequence) {
delete m->sequence;
}
delete m;
ui->treeWidget->takeTopLevelItem(i);
}
void Project::clear() {
int len = ui->treeWidget->topLevelItemCount();
for (int i=0;i<len;i++) {
remove_item(i);
}
}
void Project::set_sequence(Sequence* s) {
panel_timeline->set_sequence(s);
panel_viewer->set_sequence(s);
}
void Project::load_project() {
// clear existing project
set_sequence(NULL);
clear();
QFile file("C:/Users/Matt/Desktop/test.xml");
if (!file.open(QIODevice::ReadOnly/* | QIODevice::Text*/)) {
qDebug() << "[ERROR] Could not open file";
return;
}
QXmlStreamReader stream(&file);
while (!stream.atEnd()) {
stream.readNext();
}
if (stream.hasError()) {
qDebug() << "[ERROR] Error parsing XML." << stream.error();
}
}
void Project::save_project() {
QFile file("C:/Users/Matt/Desktop/test.xml");
if (!file.open(QIODevice::WriteOnly/* | QIODevice::Text*/)) {
qDebug() << "[ERROR] Could not open file";
return;
}
QXmlStreamWriter stream(&file);
stream.setAutoFormatting(true);
stream.writeStartDocument();
int len = ui->treeWidget->topLevelItemCount();
stream.writeStartElement("media");
for (int i=0;i<len;i++) {
Media* m = get_media_from_tree(ui->treeWidget->topLevelItem(i));
if (!m->is_sequence) {
m->save_id = i;
stream.writeStartElement("footage");
stream.writeAttribute("id", QString::number(m->save_id));
stream.writeTextElement("name", m->name);
stream.writeTextElement("url", m->url);
stream.writeEndElement();
}
}
stream.writeEndElement();
stream.writeStartElement("timeline");
for (int i=0;i<len;i++) {
Media* m = get_media_from_tree(ui->treeWidget->topLevelItem(i));
if (m->is_sequence) {
Sequence* s = m->sequence;
stream.writeStartElement("sequence");
stream.writeTextElement("name", s->name);
stream.writeTextElement("width", QString::number(s->width));
stream.writeTextElement("height", QString::number(s->height));
stream.writeTextElement("framerate", QString::number(s->frame_rate));
stream.writeTextElement("afreq", QString::number(s->audio_frequency));
stream.writeTextElement("alayout", QString::number(s->audio_layout));
stream.writeStartElement("clips");
for (int i=0;i<s->clip_count();i++) {
Clip* c = s->get_clip(i);
stream.writeStartElement("clip");
stream.writeTextElement("name", c->name);
stream.writeTextElement("clipin", QString::number(c->clip_in));
stream.writeTextElement("in", QString::number(c->timeline_in));
stream.writeTextElement("out", QString::number(c->timeline_out));
stream.writeTextElement("track", QString::number(c->track));
stream.writeStartElement("color");
stream.writeAttribute("r", QString::number(c->color_r));
stream.writeAttribute("g", QString::number(c->color_g));
stream.writeAttribute("b", QString::number(c->color_b));
stream.writeEndElement();
stream.writeTextElement("media", QString::number(c->media->save_id));
stream.writeTextElement("stream", QString::number(c->media_stream->file_index));
stream.writeStartElement("effects");
for (int j=0;j<c->effects.size();j++) {
stream.writeStartElement("effect");
Effect* e = c->effects.at(j);
stream.writeAttribute("id", QString::number(e->id));
e->save(&stream);
stream.writeEndElement();
}
stream.writeEndElement();
stream.writeEndElement();
}
stream.writeEndElement();
}
}
stream.writeEndElement();
stream.writeEndDocument();
file.close();
}
+10
View File
@@ -9,6 +9,7 @@ struct Sequence;
class Timeline;
class Viewer;
class SourceTable;
class QTreeWidgetItem;
namespace Ui {
class Project;
@@ -21,9 +22,18 @@ class Project : public QDockWidget
public:
explicit Project(QWidget *parent = 0);
~Project();
void clear();
void import_dialog();
void set_sequence(Sequence* s);
void new_sequence(Sequence* s);
QString get_next_sequence_name();
void remove_item(int i);
void load_project();
void save_project();
Media* get_media_from_tree(QTreeWidgetItem* item);
void set_media_of_tree(QTreeWidgetItem* item, Media* media);
SourceTable* source_table;
+16 -6
View File
@@ -3,6 +3,8 @@
#include "panels/panels.h"
#include "panels/viewer.h"
#include "ui/viewerwidget.h"
#include "ui/collapsiblewidget.h"
#include "effects/effects.h"
Effect::Effect(Clip* c) : parent_clip(c)
{
@@ -10,16 +12,24 @@ Effect::Effect(Clip* c) : parent_clip(c)
type = EFFECT_TYPE_INVALID;
}
void Effect::setup_effect(int t, int i) {
type = t;
id = i;
container = new CollapsibleWidget();
if (type == EFFECT_TYPE_VIDEO) {
container->setText(video_effect_names[i]);
} else if (type == EFFECT_TYPE_AUDIO) {
container->setText(audio_effect_names[i]);
}
ui = new QWidget();
}
void Effect::field_changed() {
panel_viewer->viewer_widget->update();
}
Effect* Effect::copy() {
Effect* e = new Effect(parent_clip);
name = e->name;
type = e->type;
return e;
}
Effect* Effect::copy() {return NULL;}
void Effect::save(QXmlStreamWriter *stream) {}
void Effect::process_gl(int*, int*) {}
void Effect::process_audio(uint8_t*, int) {}
+6
View File
@@ -7,6 +7,7 @@ class QWidget;
class CollapsibleWidget;
struct Clip;
class QXmlStreamWriter;
enum EffectTypes { EFFECT_TYPE_INVALID, EFFECT_TYPE_VIDEO, EFFECT_TYPE_AUDIO };
@@ -16,18 +17,23 @@ class Effect : public QObject
public:
Effect(Clip* c); // default constructor
int type;
int id;
QString name;
CollapsibleWidget* container;
QWidget* ui;
Clip* parent_clip;
virtual Effect* copy();
virtual void save(QXmlStreamWriter* stream);
virtual void process_gl(int* anchor_x, int* anchor_y);
virtual void process_audio(uint8_t* samples, int nb_bytes);
public slots:
void field_changed();
protected:
void setup_effect(int t, int i);
};
#endif // EFFECT_H
+1 -2
View File
@@ -19,8 +19,7 @@ void SourceTable::mouseDoubleClickEvent(QMouseEvent* )
} else if (selectedItems().count() == 1) {
Media* m = reinterpret_cast<Media*>(selectedItems().at(0)->data(0, Qt::UserRole + 1).value<quintptr>());
if (m->is_sequence) {
panel_timeline->set_sequence(m->sequence);
panel_viewer->set_sequence(m->sequence);
panel_project->set_sequence(m->sequence);
}
}
}
+3 -1
View File
@@ -47,7 +47,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
panel_timeline->drag_track_start = (bottom_align) ? -1 : 0;
for (int i=0;i<items.size();i++) {
bool ignore_infinite_length = false;
Media* m = reinterpret_cast<Media*>(items.at(i)->data(0, Qt::UserRole + 1).value<quintptr>());
Media* m = panel_project->get_media_from_tree(items.at(i));
long duration = m->get_length_in_frames(panel_timeline->sequence->frame_rate);
Ghost g = {NULL, entry_point, entry_point + duration};
g.media = m;
@@ -544,6 +544,8 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
panel_timeline->cursor_frame > panel_timeline->playhead-limit-1 &&
panel_timeline->cursor_frame < panel_timeline->playhead+limit+1) {
panel_timeline->cursor_frame = panel_timeline->playhead;
panel_timeline->snapped = true;
panel_timeline->snap_point = panel_timeline->playhead;
} else {
panel_timeline->snap_to_clip(&panel_timeline->cursor_frame);
}