finished new/load/save
This commit is contained in:
@@ -75,6 +75,11 @@ ExportDialog::ExportDialog(QWidget *parent) :
|
||||
ui->formatCombobox->addItem(format_strings[i]);
|
||||
}
|
||||
ui->formatCombobox->setCurrentIndex(FORMAT_MPEG4);
|
||||
|
||||
ui->widthSpinbox->setValue(sequence->width);
|
||||
ui->heightSpinbox->setValue(sequence->height);
|
||||
ui->samplingRateSpinbox->setValue(sequence->audio_frequency);
|
||||
ui->framerateSpinbox->setValue(sequence->frame_rate);
|
||||
}
|
||||
|
||||
ExportDialog::~ExportDialog()
|
||||
@@ -442,13 +447,6 @@ void ExportDialog::on_pushButton_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
void ExportDialog::set_defaults(Sequence* s) {
|
||||
ui->widthSpinbox->setValue(s->width);
|
||||
ui->heightSpinbox->setValue(s->height);
|
||||
ui->samplingRateSpinbox->setValue(s->audio_frequency);
|
||||
ui->framerateSpinbox->setValue(s->frame_rate);
|
||||
}
|
||||
|
||||
void ExportDialog::update_progress_bar(int value) {
|
||||
ui->progressBar->setValue(value);
|
||||
}
|
||||
|
||||
@@ -15,9 +15,7 @@ class ExportDialog : public QDialog
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ExportDialog(QWidget *parent = 0);
|
||||
~ExportDialog();
|
||||
|
||||
void set_defaults(Sequence* s);
|
||||
~ExportDialog();
|
||||
|
||||
private slots:
|
||||
void on_formatCombobox_currentIndexChanged(int index);
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
VolumeEffect(Clip* c);
|
||||
void process_audio(uint8_t* samples, int nb_bytes);
|
||||
Effect* copy();
|
||||
void load(QXmlStreamReader* stream);
|
||||
void save(QXmlStreamWriter* stream);
|
||||
|
||||
QSpinBox* volume_val;
|
||||
@@ -63,6 +64,7 @@ public:
|
||||
PanEffect(Clip* c);
|
||||
void process_audio(uint8_t* samples, int nb_bytes);
|
||||
Effect* copy();
|
||||
void load(QXmlStreamReader* stream);
|
||||
void save(QXmlStreamWriter* stream);
|
||||
|
||||
QSpinBox* pan_val;
|
||||
|
||||
@@ -31,6 +31,16 @@ Effect* PanEffect::copy() {
|
||||
return p;
|
||||
}
|
||||
|
||||
void PanEffect::load(QXmlStreamReader *stream) {
|
||||
while (!(stream->isEndElement() && stream->name() == "effect") && !stream->atEnd()) {
|
||||
stream->readNext();
|
||||
if (stream->isStartElement() && stream->name() == "pan") {
|
||||
stream->readNext();
|
||||
pan_val->setValue(stream->text().toInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PanEffect::save(QXmlStreamWriter *stream) {
|
||||
stream->writeTextElement("pan", QString::number(pan_val->value()));
|
||||
}
|
||||
|
||||
@@ -31,6 +31,16 @@ Effect* VolumeEffect::copy() {
|
||||
return v;
|
||||
}
|
||||
|
||||
void VolumeEffect::load(QXmlStreamReader *stream) {
|
||||
while (!(stream->isEndElement() && stream->name() == "effect") && !stream->atEnd()) {
|
||||
stream->readNext();
|
||||
if (stream->isStartElement() && stream->name() == "volume") {
|
||||
stream->readNext();
|
||||
volume_val->setValue(stream->text().toInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VolumeEffect::save(QXmlStreamWriter *stream) {
|
||||
stream->writeTextElement("volume", QString::number(volume_val->value()));
|
||||
}
|
||||
|
||||
@@ -49,8 +49,6 @@ bool encode(AVFormatContext* fmt_ctx, AVCodecContext* codec_ctx, AVFrame* frame,
|
||||
void ExportThread::run() {
|
||||
av_log_set_level(AV_LOG_DEBUG);
|
||||
|
||||
Sequence* sequence = panel_timeline->sequence;
|
||||
|
||||
// TODO make customizable
|
||||
long start = 0;
|
||||
long end = sequence->getEndFrame();
|
||||
|
||||
+59
-2
@@ -15,6 +15,10 @@
|
||||
|
||||
#include <QDebug>
|
||||
#include <QStyleFactory>
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
|
||||
#define OLIVE_FILE_FILTER "Olive Project (*.ove)"
|
||||
|
||||
void MainWindow::setup_layout() {
|
||||
panel_project = new Project(this);
|
||||
@@ -133,7 +137,6 @@ void MainWindow::on_actionTimeline_Track_Lines_toggled(bool e)
|
||||
void MainWindow::on_actionExport_triggered()
|
||||
{
|
||||
ExportDialog e(this);
|
||||
if (panel_timeline->sequence != NULL) e.set_defaults(panel_timeline->sequence);
|
||||
e.exec();
|
||||
}
|
||||
|
||||
@@ -204,7 +207,61 @@ void MainWindow::on_action_Paste_triggered()
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::save_project_as() {
|
||||
QString fn = QFileDialog::getSaveFileName(this, "Save Project As...", "", OLIVE_FILE_FILTER);
|
||||
if (!fn.isEmpty()) {
|
||||
project_url = fn;
|
||||
panel_project->save_project();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MainWindow::save_project() {
|
||||
if (project_url.isEmpty()) {
|
||||
return save_project_as();
|
||||
} else {
|
||||
panel_project->save_project();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::can_close_project() {
|
||||
if (project_changed) {
|
||||
int r = QMessageBox::question(this, "Unsaved Project", "This project has changed since it was last saved. Would you like to save it before closing?", QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel, QMessageBox::Yes);
|
||||
if (r == QMessageBox::Yes) {
|
||||
return save_project();
|
||||
} else if (r == QMessageBox::Cancel) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Save_Project_triggered()
|
||||
{
|
||||
panel_project->save_project();
|
||||
save_project();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionProject_triggered()
|
||||
{
|
||||
if (can_close_project()) {
|
||||
panel_project->new_project();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSave_Project_As_triggered()
|
||||
{
|
||||
save_project_as();
|
||||
}
|
||||
|
||||
@@ -65,9 +65,18 @@ private slots:
|
||||
|
||||
void on_action_Save_Project_triggered();
|
||||
|
||||
void on_action_Open_Project_triggered();
|
||||
|
||||
void on_actionProject_triggered();
|
||||
|
||||
void on_actionSave_Project_As_triggered();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
void setup_layout();
|
||||
bool save_project_as();
|
||||
bool save_project();
|
||||
bool can_close_project();
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.6.1, 2018-06-10T00:00:44. -->
|
||||
<!-- Written by QtCreator 4.6.1, 2018-06-10T11:24:49. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
|
||||
+259
-71
@@ -5,6 +5,8 @@
|
||||
#include "panels/panels.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "playback/playback.h"
|
||||
#include "effects/effects.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QString>
|
||||
@@ -24,6 +26,9 @@ extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
bool project_changed = false;
|
||||
QString project_url = "";
|
||||
|
||||
Project::Project(QWidget *parent) :
|
||||
QDockWidget(parent),
|
||||
ui(new Ui::Project)
|
||||
@@ -69,13 +74,80 @@ void Project::new_sequence(Sequence *s) {
|
||||
|
||||
ui->treeWidget->addTopLevelItem(item);
|
||||
source_table = ui->treeWidget;
|
||||
|
||||
project_changed = true;
|
||||
}
|
||||
|
||||
Media* Project::import_file(QString file) {
|
||||
QByteArray ba = file.toLatin1();
|
||||
char* filename = new char[ba.size()+1];
|
||||
strcpy(filename, ba.data());
|
||||
|
||||
Media* m = NULL;
|
||||
AVFormatContext* pFormatCtx = NULL;
|
||||
int errCode = avformat_open_input(&pFormatCtx, filename, NULL, NULL);
|
||||
if(errCode != 0) {
|
||||
char err[1024];
|
||||
av_strerror(errCode, err, 1024);
|
||||
qDebug() << "[ERROR] Could not open" << filename << "-" << err;
|
||||
} else {
|
||||
errCode = avformat_find_stream_info(pFormatCtx, NULL);
|
||||
if (errCode < 0) {
|
||||
char err[1024];
|
||||
av_strerror(errCode, err, 1024);
|
||||
fprintf(stderr, "[ERROR] Could not find stream information. %s\n", err);
|
||||
} else {
|
||||
av_dump_format(pFormatCtx, 0, filename, 0);
|
||||
|
||||
m = new Media();
|
||||
m->is_sequence = false;
|
||||
m->url = file;
|
||||
|
||||
// detect video/audio streams in file
|
||||
for (int i=0;i<(int)pFormatCtx->nb_streams;i++) {
|
||||
// Find the decoder for the video stream
|
||||
if (avcodec_find_decoder(pFormatCtx->streams[i]->codecpar->codec_id) == NULL) {
|
||||
qDebug() << "[ERROR] Unsupported codec in stream %d.\n";
|
||||
} else {
|
||||
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
qDebug() << "[WARNING] INFINITE_LENGTH calculation is inaccurate in this build\n";
|
||||
// TODO BETTER infinite length calculator
|
||||
bool infinite_length = (pFormatCtx->streams[i]->nb_frames == 0);
|
||||
// bool infinite_length = false;
|
||||
|
||||
m->video_tracks.append({i, pFormatCtx->streams[i]->codecpar->width, pFormatCtx->streams[i]->codecpar->height, infinite_length});
|
||||
} else if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
m->audio_tracks.append({i, 0, 0, false});
|
||||
}
|
||||
}
|
||||
}
|
||||
m->name = file.mid(file.lastIndexOf('/')+1);
|
||||
m->length = pFormatCtx->duration;
|
||||
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
if (m->video_tracks.size() == 0) {
|
||||
item->setIcon(0, QIcon(":/icons/audiosource.png"));
|
||||
} else {
|
||||
item->setIcon(0, QIcon(":/icons/videosource.png"));
|
||||
}
|
||||
item->setText(0, m->name);
|
||||
item->setText(1, QString::number(m->length));
|
||||
set_media_of_tree(item, m);
|
||||
|
||||
ui->treeWidget->addTopLevelItem(item);
|
||||
|
||||
project_changed = true;
|
||||
}
|
||||
}
|
||||
avformat_close_input(&pFormatCtx);
|
||||
delete [] filename;
|
||||
return m;
|
||||
}
|
||||
|
||||
void Project::import_dialog() {
|
||||
QStringList files = QFileDialog::getOpenFileNames(this, "Import media...", "", "All Files (*.*)");
|
||||
for (int i=0;i<files.count();i++) {
|
||||
QString file(files.at(i));
|
||||
char* filename = NULL;
|
||||
|
||||
// heuristic to determine whether file is part of an image sequence
|
||||
int lastcharindex = file.lastIndexOf(".")-1;
|
||||
@@ -108,65 +180,7 @@ void Project::import_dialog() {
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray ba = file.toLatin1();
|
||||
filename = new char[ba.size()+1];
|
||||
strcpy(filename, ba.data());
|
||||
|
||||
AVFormatContext* pFormatCtx = NULL;
|
||||
int errCode = avformat_open_input(&pFormatCtx, filename, NULL, NULL);
|
||||
if(errCode != 0) {
|
||||
char err[1024];
|
||||
av_strerror(errCode, err, 1024);
|
||||
qDebug() << "[ERROR] Could not open" << filename << "-" << err;
|
||||
} else {
|
||||
errCode = avformat_find_stream_info(pFormatCtx, NULL);
|
||||
if (errCode < 0) {
|
||||
char err[1024];
|
||||
av_strerror(errCode, err, 1024);
|
||||
fprintf(stderr, "[ERROR] Could not find stream information. %s\n", err);
|
||||
} else {
|
||||
av_dump_format(pFormatCtx, 0, filename, 0);
|
||||
|
||||
Media* m = new Media();
|
||||
m->is_sequence = false;
|
||||
m->url = file;
|
||||
|
||||
// detect video/audio streams in file
|
||||
for (int i=0;i<(int)pFormatCtx->nb_streams;i++) {
|
||||
// Find the decoder for the video stream
|
||||
if (avcodec_find_decoder(pFormatCtx->streams[i]->codecpar->codec_id) == NULL) {
|
||||
qDebug() << "[ERROR] Unsupported codec in stream %d.\n";
|
||||
} else {
|
||||
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
qDebug() << "[WARNING] INFINITE_LENGTH calculation is inaccurate in this build\n";
|
||||
// TODO BETTER infinite length calculator
|
||||
bool infinite_length = (pFormatCtx->streams[i]->nb_frames == 0);
|
||||
// bool infinite_length = false;
|
||||
|
||||
m->video_tracks.append({i, pFormatCtx->streams[i]->codecpar->width, pFormatCtx->streams[i]->codecpar->height, infinite_length});
|
||||
} else if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
m->audio_tracks.append({i, 0, 0, false});
|
||||
}
|
||||
}
|
||||
}
|
||||
m->name = files.at(i).mid(files.at(i).lastIndexOf('/')+1);
|
||||
m->length = pFormatCtx->duration;
|
||||
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
if (m->video_tracks.size() == 0) {
|
||||
item->setIcon(0, QIcon(":/icons/audiosource.png"));
|
||||
} else {
|
||||
item->setIcon(0, QIcon(":/icons/videosource.png"));
|
||||
}
|
||||
item->setText(0, m->name);
|
||||
item->setText(1, QString::number(m->length));
|
||||
set_media_of_tree(item, m);
|
||||
|
||||
ui->treeWidget->addTopLevelItem(item);
|
||||
}
|
||||
}
|
||||
avformat_close_input(&pFormatCtx);
|
||||
delete [] filename;
|
||||
import_file(file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,26 +199,35 @@ void Project::remove_item(int i) {
|
||||
}
|
||||
delete m;
|
||||
ui->treeWidget->takeTopLevelItem(i);
|
||||
project_changed = true;
|
||||
}
|
||||
|
||||
void Project::clear() {
|
||||
int len = ui->treeWidget->topLevelItemCount();
|
||||
for (int i=0;i<len;i++) {
|
||||
remove_item(i);
|
||||
while (ui->treeWidget->topLevelItemCount() > 0) {
|
||||
remove_item(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Project::set_sequence(Sequence* s) {
|
||||
panel_timeline->set_sequence(s);
|
||||
panel_viewer->set_sequence(s);
|
||||
}
|
||||
|
||||
void Project::load_project() {
|
||||
void Project::new_project() {
|
||||
// clear existing project
|
||||
set_sequence(NULL);
|
||||
clear();
|
||||
project_changed = false;
|
||||
}
|
||||
|
||||
QFile file("C:/Users/Matt/Desktop/test.xml");
|
||||
#define LOAD_STATE_IDLE 0
|
||||
#define LOAD_STATE_MEDIA 1
|
||||
#define LOAD_STATE_FOOTAGE 2
|
||||
#define LOAD_STATE_TIMELINE 3
|
||||
#define LOAD_STATE_SEQUENCE 4
|
||||
#define LOAD_STATE_CLIP 5
|
||||
#define LOAD_STATE_CLIP_EFFECTS 6
|
||||
#define LOAD_STATE_EFFECT 7
|
||||
|
||||
void Project::load_project() {
|
||||
new_project();
|
||||
|
||||
QFile file(project_url);
|
||||
if (!file.open(QIODevice::ReadOnly/* | QIODevice::Text*/)) {
|
||||
qDebug() << "[ERROR] Could not open file";
|
||||
return;
|
||||
@@ -212,17 +235,174 @@ void Project::load_project() {
|
||||
|
||||
QXmlStreamReader stream(&file);
|
||||
|
||||
// temp variables for loading
|
||||
QVector<Media*> temp_media_list;
|
||||
QString temp_name;
|
||||
QString temp_url;
|
||||
int temp_media_id;
|
||||
Sequence* temp_seq;
|
||||
Clip* temp_clip;
|
||||
|
||||
int state = LOAD_STATE_IDLE;
|
||||
while (!stream.atEnd()) {
|
||||
stream.readNext();
|
||||
switch (state) {
|
||||
case LOAD_STATE_IDLE:
|
||||
if (stream.isStartElement()) {
|
||||
if (stream.name() == "footage") {
|
||||
for (int j=0;j<stream.attributes().size();j++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(j);
|
||||
if (attr.name() == "id") {
|
||||
temp_media_id = attr.value().toInt();
|
||||
}
|
||||
}
|
||||
state = LOAD_STATE_FOOTAGE;
|
||||
} else if (stream.name() == "sequence") {
|
||||
temp_seq = new Sequence();
|
||||
state = LOAD_STATE_SEQUENCE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LOAD_STATE_FOOTAGE:
|
||||
if (stream.isEndElement() && stream.name() == "footage") {
|
||||
Media* m = import_file(temp_url);
|
||||
m->save_id = temp_media_id;
|
||||
m->name = temp_name;
|
||||
temp_media_list.append(m);
|
||||
state = LOAD_STATE_IDLE;
|
||||
} else if (stream.isStartElement()) {
|
||||
if (stream.name() == "name") {
|
||||
stream.readNext();
|
||||
temp_name = stream.text().toString();
|
||||
} else if (stream.name() == "url") {
|
||||
stream.readNext();
|
||||
temp_url = stream.text().toString();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LOAD_STATE_SEQUENCE:
|
||||
if (stream.isEndElement() && stream.name() == "sequence") {
|
||||
new_sequence(temp_seq);
|
||||
state = LOAD_STATE_IDLE;
|
||||
} else if (stream.isStartElement()) {
|
||||
if (stream.name() == "name") {
|
||||
stream.readNext();
|
||||
temp_seq->name = stream.text().toString();
|
||||
} else if (stream.name() == "width") {
|
||||
stream.readNext();
|
||||
temp_seq->width = stream.text().toInt();
|
||||
} else if (stream.name() == "height") {
|
||||
stream.readNext();
|
||||
temp_seq->height = stream.text().toInt();
|
||||
} else if (stream.name() == "framerate") {
|
||||
stream.readNext();
|
||||
temp_seq->frame_rate = stream.text().toFloat();
|
||||
} else if (stream.name() == "afreq") {
|
||||
stream.readNext();
|
||||
temp_seq->audio_frequency = stream.text().toInt();
|
||||
} else if (stream.name() == "alayout") {
|
||||
stream.readNext();
|
||||
temp_seq->audio_layout = stream.text().toInt();
|
||||
} else if (stream.name() == "clip") {
|
||||
temp_clip = new Clip();
|
||||
temp_clip->sequence = temp_seq;
|
||||
state = LOAD_STATE_CLIP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LOAD_STATE_CLIP:
|
||||
if (stream.isEndElement() && stream.name() == "clip") {
|
||||
temp_seq->add_clip(temp_clip);
|
||||
state = LOAD_STATE_SEQUENCE;
|
||||
} else if (stream.isStartElement()) {
|
||||
if (stream.name() == "name") {
|
||||
stream.readNext();
|
||||
temp_clip->name = stream.text().toString();
|
||||
} else if (stream.name() == "clipin") {
|
||||
stream.readNext();
|
||||
temp_clip->clip_in = stream.text().toInt();
|
||||
} else if (stream.name() == "in") {
|
||||
stream.readNext();
|
||||
temp_clip->timeline_in = stream.text().toInt();
|
||||
} else if (stream.name() == "out") {
|
||||
stream.readNext();
|
||||
temp_clip->timeline_out = stream.text().toInt();
|
||||
} else if (stream.name() == "track") {
|
||||
stream.readNext();
|
||||
temp_clip->track = stream.text().toInt();
|
||||
} else if (stream.name() == "color") {
|
||||
for (int j=0;j<stream.attributes().size();j++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(j);
|
||||
if (attr.name().toString() == QLatin1String("r")) {
|
||||
temp_clip->color_r = attr.value().toInt();
|
||||
} else if (attr.name().toString() == QLatin1String("g")) {
|
||||
temp_clip->color_g = attr.value().toInt();
|
||||
} else if (attr.name().toString() == QLatin1String("b")) {
|
||||
temp_clip->color_b = attr.value().toInt();
|
||||
}
|
||||
}
|
||||
} else if (stream.name() == "media") {
|
||||
stream.readNext();
|
||||
for (int i=0;i<temp_media_list.size();i++) {
|
||||
Media* m = temp_media_list.at(i);
|
||||
if (m->save_id == stream.text().toInt()) {
|
||||
temp_clip->media = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (stream.name() == "stream") {
|
||||
// TODO very unintelligent code - i hate this
|
||||
int stream_index = stream.text().toInt();
|
||||
bool found = false;
|
||||
for (int i=0;i<temp_clip->media->video_tracks.size();i++) {
|
||||
if (temp_clip->media->video_tracks.at(i).file_index == stream_index) {
|
||||
temp_clip->media_stream = &temp_clip->media->video_tracks[i];
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
for (int i=0;i<temp_clip->media->audio_tracks.size();i++) {
|
||||
if (temp_clip->media->audio_tracks.at(i).file_index == stream_index) {
|
||||
temp_clip->media_stream = &temp_clip->media->audio_tracks[i];
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
qDebug() << "[WARNING] Could not load media stream - project file seems corrupt";
|
||||
}
|
||||
} else if (stream.name() == "effect") {
|
||||
int effect_id = -1;
|
||||
for (int j=0;j<stream.attributes().size();j++) {
|
||||
const QXmlStreamAttribute& attr = stream.attributes().at(j);
|
||||
if (attr.name().toString() == QLatin1String("id")) {
|
||||
effect_id = attr.value().toInt();
|
||||
}
|
||||
}
|
||||
if (effect_id != -1) {
|
||||
Effect* e = create_effect(effect_id, temp_clip);
|
||||
e->load(&stream);
|
||||
temp_clip->effects.append(e);
|
||||
state = LOAD_STATE_CLIP;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
qDebug() << "read element:" << stream.name() << "- text:" << stream.text() << "- start:" << stream.isStartElement() << "- end:" << stream.isEndElement();
|
||||
|
||||
}
|
||||
if (stream.hasError()) {
|
||||
qDebug() << "[ERROR] Error parsing XML." << stream.error();
|
||||
}
|
||||
|
||||
project_changed = false;
|
||||
}
|
||||
|
||||
void Project::save_project() {
|
||||
QFile file("C:/Users/Matt/Desktop/test.xml");
|
||||
QFile file(project_url);
|
||||
if (!file.open(QIODevice::WriteOnly/* | QIODevice::Text*/)) {
|
||||
qDebug() << "[ERROR] Could not open file";
|
||||
return;
|
||||
@@ -232,6 +412,10 @@ void Project::save_project() {
|
||||
stream.setAutoFormatting(true);
|
||||
stream.writeStartDocument();
|
||||
|
||||
stream.writeStartElement("project");
|
||||
|
||||
stream.writeTextElement("version", "180601");
|
||||
|
||||
int len = ui->treeWidget->topLevelItemCount();
|
||||
stream.writeStartElement("media");
|
||||
for (int i=0;i<len;i++) {
|
||||
@@ -292,7 +476,11 @@ void Project::save_project() {
|
||||
}
|
||||
stream.writeEndElement();
|
||||
|
||||
stream.writeEndElement();
|
||||
|
||||
stream.writeEndDocument();
|
||||
|
||||
file.close();
|
||||
|
||||
project_changed = false;
|
||||
}
|
||||
|
||||
+6
-2
@@ -15,6 +15,9 @@ namespace Ui {
|
||||
class Project;
|
||||
}
|
||||
|
||||
extern bool project_changed;
|
||||
extern QString project_url;
|
||||
|
||||
class Project : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -23,12 +26,13 @@ public:
|
||||
explicit Project(QWidget *parent = 0);
|
||||
~Project();
|
||||
void clear();
|
||||
void import_dialog();
|
||||
void set_sequence(Sequence* s);
|
||||
Media* import_file(QString url);
|
||||
void import_dialog();
|
||||
void new_sequence(Sequence* s);
|
||||
QString get_next_sequence_name();
|
||||
void remove_item(int i);
|
||||
|
||||
void new_project();
|
||||
void load_project();
|
||||
void save_project();
|
||||
|
||||
|
||||
+5
-15
@@ -2,6 +2,7 @@
|
||||
#include "ui_timeline.h"
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "panels/project.h"
|
||||
#include "panels/effectcontrols.h"
|
||||
#include "ui/timelinewidget.h"
|
||||
#include "project/sequence.h"
|
||||
@@ -38,8 +39,7 @@ Timeline::Timeline(QWidget *parent) :
|
||||
|
||||
zoom = 1.0f;
|
||||
|
||||
sequence = NULL;
|
||||
set_sequence(NULL);
|
||||
update_sequence();
|
||||
|
||||
connect(&playback_updater, SIGNAL(timeout()), this, SLOT(repaint_timeline()));
|
||||
}
|
||||
@@ -103,19 +103,8 @@ void Timeline::go_to_end() {
|
||||
seek(sequence->getEndFrame());
|
||||
}
|
||||
|
||||
void Timeline::set_sequence(Sequence *s) {
|
||||
if (sequence != NULL) {
|
||||
// clean up - close all open clips
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip* c = sequence->get_clip(i);
|
||||
if (c->open) {
|
||||
close_clip(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sequence = s;
|
||||
bool null_sequence = (s == NULL);
|
||||
void Timeline::update_sequence() {
|
||||
bool null_sequence = (sequence == NULL);
|
||||
|
||||
for (int i=0;i<tool_buttons.count();i++) {
|
||||
tool_buttons[i]->setEnabled(!null_sequence);
|
||||
@@ -173,6 +162,7 @@ void Timeline::repaint_timeline() {
|
||||
void Timeline::redraw_all_clips() {
|
||||
// add current sequence to the undo stack
|
||||
sequence->undo_add_current();
|
||||
project_changed = true;
|
||||
|
||||
ui->video_area->redraw_clips();
|
||||
ui->audio_area->redraw_clips();
|
||||
|
||||
+1
-2
@@ -67,14 +67,13 @@ public:
|
||||
void paste();
|
||||
bool split_selection();
|
||||
void split_at_playhead();
|
||||
void set_sequence(Sequence* s);
|
||||
void update_sequence();
|
||||
|
||||
int getScreenPointFromFrame(long frame);
|
||||
long getFrameFromScreenPoint(int x);
|
||||
|
||||
void snap_to_clip(long* l);
|
||||
|
||||
Sequence* sequence;
|
||||
long playhead;
|
||||
|
||||
// playback functions
|
||||
|
||||
+5
-7
@@ -19,19 +19,17 @@ Viewer::Viewer(QWidget *parent) :
|
||||
ui->setupUi(this);
|
||||
ui->glViewerPane->child = ui->openGLWidget;
|
||||
viewer_widget = ui->openGLWidget;
|
||||
set_sequence(NULL);
|
||||
update_sequence();
|
||||
}
|
||||
|
||||
Viewer::~Viewer()
|
||||
{
|
||||
init_audio(NULL);
|
||||
|
||||
init_audio();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void Viewer::set_sequence(Sequence* s) {
|
||||
bool null_sequence = (s == NULL);
|
||||
sequence = s;
|
||||
void Viewer::update_sequence() {
|
||||
bool null_sequence = (sequence == NULL);
|
||||
|
||||
ui->openGLWidget->setEnabled(!null_sequence);
|
||||
ui->openGLWidget->setVisible(!null_sequence);
|
||||
@@ -41,7 +39,7 @@ void Viewer::set_sequence(Sequence* s) {
|
||||
ui->pushButton_4->setEnabled(!null_sequence);
|
||||
ui->pushButton_5->setEnabled(!null_sequence);
|
||||
|
||||
init_audio(s);
|
||||
init_audio();
|
||||
|
||||
if (!null_sequence) {
|
||||
ui->glViewerPane->aspect_ratio = (float) sequence->width / (float) sequence->height;
|
||||
|
||||
+1
-2
@@ -18,10 +18,9 @@ class Viewer : public QDockWidget
|
||||
public:
|
||||
explicit Viewer(QWidget *parent = 0);
|
||||
~Viewer();
|
||||
void set_sequence(Sequence* s);
|
||||
void update_sequence();
|
||||
void compose();
|
||||
|
||||
Sequence* sequence;
|
||||
ViewerWidget* viewer_widget;
|
||||
|
||||
private slots:
|
||||
|
||||
+4
-4
@@ -17,17 +17,17 @@ qint8 audio_ibuffer[audio_ibuffer_size];
|
||||
int audio_ibuffer_read = 0;
|
||||
QVector<int> audio_ibuffer_write;
|
||||
|
||||
void init_audio(Sequence* s) {
|
||||
void init_audio() {
|
||||
if (audio_device_set) {
|
||||
audio_output->stop();
|
||||
delete audio_output;
|
||||
audio_device_set = false;
|
||||
}
|
||||
|
||||
if (s != NULL) {
|
||||
if (sequence != NULL) {
|
||||
QAudioFormat audio_format;
|
||||
audio_format.setSampleRate(s->audio_frequency);
|
||||
audio_format.setChannelCount(av_get_channel_layout_nb_channels(s->audio_layout));
|
||||
audio_format.setSampleRate(sequence->audio_frequency);
|
||||
audio_format.setChannelCount(av_get_channel_layout_nb_channels(sequence->audio_layout));
|
||||
audio_format.setSampleSize(16);
|
||||
audio_format.setCodec("audio/pcm");
|
||||
audio_format.setByteOrder(QAudioFormat::LittleEndian);
|
||||
|
||||
+1
-1
@@ -17,6 +17,6 @@ extern int audio_ibuffer_read;
|
||||
//extern QVector<int> audio_ibuffer_write;
|
||||
void clear_audio_ibuffer();
|
||||
|
||||
void init_audio(Sequence* s);
|
||||
void init_audio();
|
||||
|
||||
#endif // AUDIO_H
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
#include "io/media.h"
|
||||
#include "playback/audio.h"
|
||||
#include "playback/cacher.h"
|
||||
#include "panels/panels.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "panels/viewer.h"
|
||||
#include <algorithm>
|
||||
|
||||
extern "C" {
|
||||
@@ -287,3 +289,18 @@ void retrieve_next_frame_raw_data(Clip* c, AVFrame* output) {
|
||||
bool is_clip_active(Clip* c, long playhead) {
|
||||
return c->timeline_in < playhead + ceil(c->sequence->frame_rate) && c->timeline_out > playhead;
|
||||
}
|
||||
|
||||
void set_sequence(Sequence* s) {
|
||||
if (sequence != NULL) {
|
||||
// clean up - close all open clips
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip* c = sequence->get_clip(i);
|
||||
if (c->open) {
|
||||
close_clip(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
sequence = s;
|
||||
panel_timeline->update_sequence();
|
||||
panel_viewer->update_sequence();
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ int retrieve_next_frame(Clip* c, AVFrame* f);
|
||||
void retrieve_next_frame_raw_data(Clip* c, AVFrame* output);
|
||||
bool is_clip_active(Clip* c, long playhead);
|
||||
void get_next_audio(Clip* c, bool mix);
|
||||
void set_sequence(Sequence* s);
|
||||
|
||||
struct ClipCacheData {
|
||||
Clip& clip;
|
||||
|
||||
@@ -38,7 +38,6 @@ Clip* Clip::copy() {
|
||||
}
|
||||
|
||||
void Clip::init() {
|
||||
qDebug() << "init was called";
|
||||
reset();
|
||||
clip_in = timeline_in = timeline_out = track = undeletable = 0;
|
||||
texture = NULL;
|
||||
|
||||
@@ -29,6 +29,7 @@ void Effect::field_changed() {
|
||||
}
|
||||
|
||||
Effect* Effect::copy() {return NULL;}
|
||||
void Effect::load(QXmlStreamReader* stream) {}
|
||||
void Effect::save(QXmlStreamWriter *stream) {}
|
||||
|
||||
void Effect::process_gl(int*, int*) {}
|
||||
|
||||
@@ -7,6 +7,7 @@ class QWidget;
|
||||
class CollapsibleWidget;
|
||||
|
||||
struct Clip;
|
||||
class QXmlStreamReader;
|
||||
class QXmlStreamWriter;
|
||||
|
||||
enum EffectTypes { EFFECT_TYPE_INVALID, EFFECT_TYPE_VIDEO, EFFECT_TYPE_AUDIO };
|
||||
@@ -24,6 +25,7 @@ public:
|
||||
Clip* parent_clip;
|
||||
|
||||
virtual Effect* copy();
|
||||
virtual void load(QXmlStreamReader* stream);
|
||||
virtual void save(QXmlStreamWriter* stream);
|
||||
|
||||
virtual void process_gl(int* anchor_x, int* anchor_y);
|
||||
|
||||
@@ -162,3 +162,6 @@ void Sequence::redo() {
|
||||
set_undo(undo_pointer);
|
||||
}
|
||||
}
|
||||
|
||||
// static variable for the currently active sequence
|
||||
Sequence* sequence = NULL;
|
||||
|
||||
@@ -38,4 +38,7 @@ private:
|
||||
int undo_stack_start;
|
||||
};
|
||||
|
||||
// static variable for the currently active sequence
|
||||
extern Sequence* sequence;
|
||||
|
||||
#endif // SEQUENCE_H
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@
|
||||
#include "panels/timeline.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "panels/panels.h"
|
||||
#include "playback/playback.h"
|
||||
|
||||
#include <QDragEnterEvent>
|
||||
|
||||
@@ -19,7 +20,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_project->set_sequence(m->sequence);
|
||||
set_sequence(m->sequence);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,10 +37,10 @@ void TimelineHeader::mouseReleaseEvent(QMouseEvent *) {
|
||||
}
|
||||
|
||||
void TimelineHeader::paintEvent(QPaintEvent*) {
|
||||
if (panel_timeline->sequence != NULL) {
|
||||
if (sequence != NULL) {
|
||||
QPainter p(this);
|
||||
p.setPen(Qt::gray);
|
||||
int interval = panel_timeline->getScreenPointFromFrame(panel_timeline->sequence->frame_rate);
|
||||
int interval = panel_timeline->getScreenPointFromFrame(sequence->frame_rate);
|
||||
for (int i=0;i<width();i+=interval) {
|
||||
p.drawLine(i, 0, i, height());
|
||||
}
|
||||
|
||||
+30
-30
@@ -34,7 +34,7 @@ bool same_sign(int a, int b) {
|
||||
}
|
||||
|
||||
void TimelineWidget::resizeEvent(QResizeEvent*) {
|
||||
if (panel_timeline->sequence != NULL) redraw_clips();
|
||||
if (sequence != NULL) redraw_clips();
|
||||
}
|
||||
|
||||
void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
|
||||
@@ -48,7 +48,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
|
||||
for (int i=0;i<items.size();i++) {
|
||||
bool ignore_infinite_length = false;
|
||||
Media* m = panel_project->get_media_from_tree(items.at(i));
|
||||
long duration = m->get_length_in_frames(panel_timeline->sequence->frame_rate);
|
||||
long duration = m->get_length_in_frames(sequence->frame_rate);
|
||||
Ghost g = {NULL, entry_point, entry_point + duration};
|
||||
g.media = m;
|
||||
g.clip_in = 0;
|
||||
@@ -94,7 +94,7 @@ void TimelineWidget::dropEvent(QDropEvent* event) {
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
const Ghost& g = panel_timeline->ghosts.at(i);
|
||||
|
||||
panel_timeline->sequence->delete_area(g.in, g.out, g.track);
|
||||
sequence->delete_area(g.in, g.out, g.track);
|
||||
|
||||
Clip* c = new Clip();
|
||||
c->media = g.media;
|
||||
@@ -105,7 +105,7 @@ void TimelineWidget::dropEvent(QDropEvent* event) {
|
||||
c->color_r = 128;
|
||||
c->color_g = 128;
|
||||
c->color_b = 192;
|
||||
c->sequence = panel_timeline->sequence;
|
||||
c->sequence = sequence;
|
||||
c->track = g.track;
|
||||
c->name = c->media->name;
|
||||
|
||||
@@ -118,7 +118,7 @@ void TimelineWidget::dropEvent(QDropEvent* event) {
|
||||
c->effects.append(create_effect(AUDIO_PAN_EFFECT, c));
|
||||
}
|
||||
|
||||
panel_timeline->sequence->add_clip(c);
|
||||
sequence->add_clip(c);
|
||||
}
|
||||
|
||||
panel_timeline->ghosts.clear();
|
||||
@@ -156,7 +156,7 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) {
|
||||
panel_timeline->selections.clear();
|
||||
}
|
||||
|
||||
Clip* clip = panel_timeline->sequence->get_clip(clip_index);
|
||||
Clip* clip = sequence->get_clip(clip_index);
|
||||
panel_timeline->selections.append({clip->timeline_in, clip->timeline_out, clip->track});
|
||||
}
|
||||
panel_timeline->moving_init = true;
|
||||
@@ -173,7 +173,7 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) {
|
||||
case TIMELINE_TOOL_RAZOR:
|
||||
{
|
||||
if (clip_index >= 0) {
|
||||
panel_timeline->sequence->split_clip(clip_index, panel_timeline->drag_frame_start);
|
||||
sequence->split_clip(clip_index, panel_timeline->drag_frame_start);
|
||||
}
|
||||
panel_timeline->splitting = true;
|
||||
panel_timeline->redraw_all_clips();
|
||||
@@ -195,9 +195,9 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
c->track = g.track;
|
||||
|
||||
// step 2 - delete anything that exists in area that clip is moving to
|
||||
panel_timeline->sequence->delete_area(g.in, g.out, g.track);
|
||||
sequence->delete_area(g.in, g.out, g.track);
|
||||
|
||||
panel_timeline->sequence->add_clip(c);
|
||||
sequence->add_clip(c);
|
||||
}
|
||||
} else {
|
||||
// move clips
|
||||
@@ -212,7 +212,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_POINTER) {
|
||||
// step 2 - delete anything that exists in area that clip is moving to
|
||||
// note: ripples are non-destructive so this is pointer-tool exclusive
|
||||
panel_timeline->sequence->delete_area(g.in, g.out, g.track);
|
||||
sequence->delete_area(g.in, g.out, g.track);
|
||||
}
|
||||
|
||||
// step 3 - move clips
|
||||
@@ -270,7 +270,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
// find out how many clips are selected
|
||||
bool single_select = false;
|
||||
int selected_clip = 0;
|
||||
for (int i=0;i<panel_timeline->sequence->clip_count();i++) {
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
if (panel_timeline->is_clip_selected(i)) {
|
||||
if (!single_select) {
|
||||
// found ONE selected clip
|
||||
@@ -284,7 +284,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
}
|
||||
}
|
||||
if (single_select) {
|
||||
panel_effect_controls->set_clip(panel_timeline->sequence->get_clip(selected_clip));
|
||||
panel_effect_controls->set_clip(sequence->get_clip(selected_clip));
|
||||
} else {
|
||||
panel_effect_controls->set_clip(NULL);
|
||||
}
|
||||
@@ -301,7 +301,7 @@ void TimelineWidget::init_ghosts() {
|
||||
if (panel_timeline->trim_target > -1 || panel_timeline->tool == TIMELINE_TOOL_SLIP) {
|
||||
// used for trim ops
|
||||
g.ghost_length = g.old_out - g.old_in;
|
||||
g.media_length = g.clip->media->get_length_in_frames(panel_timeline->sequence->frame_rate);
|
||||
g.media_length = g.clip->media->get_length_in_frames(sequence->frame_rate);
|
||||
}
|
||||
}
|
||||
for (int i=0;i<panel_timeline->selections.size();i++) {
|
||||
@@ -335,8 +335,8 @@ void validate_snapping(Ghost& g, long* frame_diff) {
|
||||
panel_timeline->snapped = false;
|
||||
if (panel_timeline->snapping) {
|
||||
if (!subvalidate_snapping(g, frame_diff, panel_timeline->playhead)) {
|
||||
for (int j=0;j<panel_timeline->sequence->clip_count();j++) {
|
||||
Clip* c = panel_timeline->sequence->get_clip(j);
|
||||
for (int j=0;j<sequence->clip_count();j++) {
|
||||
Clip* c = sequence->get_clip(j);
|
||||
if (!subvalidate_snapping(g, frame_diff, c->timeline_in)) {
|
||||
subvalidate_snapping(g, frame_diff, c->timeline_out);
|
||||
}
|
||||
@@ -572,9 +572,9 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
} else {
|
||||
// set up movement
|
||||
// create ghosts
|
||||
for (int i=0;i<panel_timeline->sequence->clip_count();i++) {
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
if (panel_timeline->is_clip_selected(i)) {
|
||||
Clip* c = panel_timeline->sequence->get_clip(i);
|
||||
Clip* c = sequence->get_clip(i);
|
||||
panel_timeline->ghosts.append({c, c->timeline_in, c->timeline_out, c->track, c->clip_in});
|
||||
}
|
||||
}
|
||||
@@ -583,10 +583,10 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
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<panel_timeline->sequence->clip_count();j++) {
|
||||
for (int j=0;j<sequence->clip_count();j++) {
|
||||
// don't cache any currently selected clips
|
||||
Clip* c = panel_timeline->ghosts.at(i).clip;
|
||||
Clip* cc = panel_timeline->sequence->get_clip(j);
|
||||
Clip* cc = sequence->get_clip(j);
|
||||
bool is_selected = false;
|
||||
for (int k=0;k<panel_timeline->ghosts.size();k++) {
|
||||
if (panel_timeline->ghosts.at(k).clip == cc) {
|
||||
@@ -647,9 +647,9 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
} else if (panel_timeline->splitting) {
|
||||
int track = panel_timeline->cursor_track;
|
||||
bool repaint = false;
|
||||
for (int i=0;i<panel_timeline->sequence->clip_count();i++) {
|
||||
if (panel_timeline->sequence->get_clip(i)->track == track) {
|
||||
panel_timeline->sequence->split_clip(i, panel_timeline->drag_frame_start);
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
if (sequence->get_clip(i)->track == track) {
|
||||
sequence->split_clip(i, panel_timeline->drag_frame_start);
|
||||
repaint = true;
|
||||
}
|
||||
}
|
||||
@@ -664,8 +664,8 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
long mouse_frame_lower = panel_timeline->getFrameFromScreenPoint(pos.x()-lim)-1;
|
||||
long mouse_frame_upper = panel_timeline->getFrameFromScreenPoint(pos.x()+lim)+1;
|
||||
bool found = false;
|
||||
for (int i=0;i<panel_timeline->sequence->clip_count();i++) {
|
||||
Clip* c = panel_timeline->sequence->get_clip(i);
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip* c = sequence->get_clip(i);
|
||||
if (c->track == mouse_track) {
|
||||
if (c->timeline_in > mouse_frame_lower && c->timeline_in < mouse_frame_upper) {
|
||||
panel_timeline->trim_target = i;
|
||||
@@ -704,7 +704,7 @@ int color_brightness(int r, int g, int b) {
|
||||
|
||||
void TimelineWidget::redraw_clips() {
|
||||
// Draw clips
|
||||
int panel_width = panel_timeline->getScreenPointFromFrame(panel_timeline->sequence->getEndFrame()) + 100;
|
||||
int panel_width = panel_timeline->getScreenPointFromFrame(sequence->getEndFrame()) + 100;
|
||||
setMinimumWidth(panel_width);
|
||||
|
||||
clip_pixmap = QPixmap(panel_width, height());
|
||||
@@ -712,8 +712,8 @@ void TimelineWidget::redraw_clips() {
|
||||
QPainter clip_painter(&clip_pixmap);
|
||||
int video_track_limit = 0;
|
||||
int audio_track_limit = 0;
|
||||
for (int i=0;i<panel_timeline->sequence->clip_count();i++) {
|
||||
Clip* clip = panel_timeline->sequence->get_clip(i);
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip* clip = sequence->get_clip(i);
|
||||
if (is_track_visible(clip->track)) {
|
||||
if (clip->track < 0 && clip->track < video_track_limit) { // video clip
|
||||
video_track_limit = clip->track;
|
||||
@@ -765,7 +765,7 @@ void TimelineWidget::redraw_clips() {
|
||||
}
|
||||
|
||||
void TimelineWidget::paintEvent(QPaintEvent*) {
|
||||
if (panel_timeline->sequence != NULL) {
|
||||
if (sequence != NULL) {
|
||||
QPainter p(this);
|
||||
|
||||
p.drawPixmap(0, 0, minimumWidth(), height(), clip_pixmap);
|
||||
@@ -859,8 +859,8 @@ int TimelineWidget::getScreenPointFromTrack(int track) {
|
||||
}
|
||||
|
||||
int TimelineWidget::getClipIndexFromCoords(long frame, int track) {
|
||||
for (int i=0;i<panel_timeline->sequence->clip_count();i++) {
|
||||
Clip* c = panel_timeline->sequence->get_clip(i);
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip* c = sequence->get_clip(i);
|
||||
if (c->track == track) {
|
||||
if (frame >= c->timeline_in && frame < c->timeline_out) {
|
||||
return i;
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ void ViewerWidget::paintGL()
|
||||
|
||||
long playhead = panel_timeline->playhead;
|
||||
|
||||
handle_media(panel_viewer->sequence, playhead, multithreaded);
|
||||
handle_media(sequence, playhead, multithreaded);
|
||||
texture_failed = false;
|
||||
|
||||
bool render_audio = (panel_timeline->playing || force_audio);
|
||||
|
||||
Reference in New Issue
Block a user