First commit of brand new rewrite
@@ -0,0 +1,14 @@
|
||||
#include "aboutdialog.h"
|
||||
#include "ui_aboutdialog.h"
|
||||
|
||||
AboutDialog::AboutDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AboutDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
AboutDialog::~AboutDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef ABOUTDIALOG_H
|
||||
#define ABOUTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class AboutDialog;
|
||||
}
|
||||
|
||||
class AboutDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AboutDialog(QWidget *parent = 0);
|
||||
~AboutDialog();
|
||||
|
||||
private:
|
||||
Ui::AboutDialog *ui;
|
||||
};
|
||||
|
||||
#endif // ABOUTDIALOG_H
|
||||
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AboutDialog</class>
|
||||
<widget class="QDialog" name="AboutDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>320</width>
|
||||
<height>180</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Olive is a professional video editor.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AboutDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AboutDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,437 @@
|
||||
#include "exportdialog.h"
|
||||
#include "ui_exportdialog.h"
|
||||
|
||||
#include <QOpenGLWidget>
|
||||
#include <QFileDialog>
|
||||
#include <QThread>
|
||||
#include <QDebug>
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
#include "project/sequence.h"
|
||||
#include "io/exportthread.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
}
|
||||
|
||||
enum ExportFormats {
|
||||
FORMAT_3GPP,
|
||||
FORMAT_AIFF,
|
||||
FORMAT_APNG,
|
||||
FORMAT_AVI,
|
||||
FORMAT_DNXHD,
|
||||
FORMAT_AC3,
|
||||
FORMAT_FLV,
|
||||
FORMAT_GIF,
|
||||
FORMAT_IMG,
|
||||
FORMAT_MP2,
|
||||
FORMAT_MP3,
|
||||
FORMAT_MPEG1,
|
||||
FORMAT_MPEG2,
|
||||
FORMAT_MPEG4,
|
||||
FORMAT_MPEGTS,
|
||||
FORMAT_MKV,
|
||||
FORMAT_OGG,
|
||||
FORMAT_MOV,
|
||||
FORMAT_WAV,
|
||||
FORMAT_WEBM,
|
||||
FORMAT_WMV,
|
||||
FORMAT_SIZE
|
||||
};
|
||||
|
||||
ExportDialog::ExportDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::ExportDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
format_strings.resize(FORMAT_SIZE);
|
||||
format_strings[FORMAT_3GPP] = "3GPP";
|
||||
format_strings[FORMAT_AIFF] = "AIFF";
|
||||
format_strings[FORMAT_APNG] = "Animated PNG";
|
||||
format_strings[FORMAT_AVI] = "AVI";
|
||||
format_strings[FORMAT_DNXHD] = "DNxHD";
|
||||
format_strings[FORMAT_AC3] = "Dolby Digital (AC3)";
|
||||
format_strings[FORMAT_FLV] = "FLV";
|
||||
format_strings[FORMAT_GIF] = "GIF";
|
||||
format_strings[FORMAT_IMG] = "Image Sequence";
|
||||
format_strings[FORMAT_MP2] = "MP2 Audio";
|
||||
format_strings[FORMAT_MP3] = "MP3 Audio";
|
||||
format_strings[FORMAT_MPEG1] = "MPEG-1 Video";
|
||||
format_strings[FORMAT_MPEG2] = "MPEG-2 Video";
|
||||
format_strings[FORMAT_MPEG4] = "MPEG-4 Video";
|
||||
format_strings[FORMAT_MPEGTS] = "MPEG-TS";
|
||||
format_strings[FORMAT_MKV] = "Matroska MKV";
|
||||
format_strings[FORMAT_OGG] = "Ogg";
|
||||
format_strings[FORMAT_MOV] = "QuickTime MOV";
|
||||
format_strings[FORMAT_WAV] = "WAVE Audio";
|
||||
format_strings[FORMAT_WEBM] = "WebM";
|
||||
format_strings[FORMAT_WMV] = "Windows Media";
|
||||
|
||||
for (int i=0;i<FORMAT_SIZE;i++) {
|
||||
ui->formatCombobox->addItem(format_strings[i]);
|
||||
}
|
||||
ui->formatCombobox->setCurrentIndex(FORMAT_MPEG4);
|
||||
}
|
||||
|
||||
ExportDialog::~ExportDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ExportDialog::on_formatCombobox_currentIndexChanged(int index)
|
||||
{
|
||||
format_vcodecs.clear();
|
||||
format_acodecs.clear();
|
||||
ui->vcodecCombobox->clear();
|
||||
ui->acodecCombobox->clear();
|
||||
|
||||
int default_vcodec = 0;
|
||||
int default_acodec = 0;
|
||||
|
||||
switch (index) {
|
||||
case FORMAT_3GPP:
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG4);
|
||||
format_vcodecs.append(AV_CODEC_ID_H264);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AAC);
|
||||
|
||||
default_vcodec = 1;
|
||||
break;
|
||||
case FORMAT_AIFF:
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
break;
|
||||
case FORMAT_APNG:
|
||||
format_vcodecs.append(AV_CODEC_ID_APNG);
|
||||
break;
|
||||
case FORMAT_AVI:
|
||||
format_vcodecs.append(AV_CODEC_ID_H264);
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG4);
|
||||
format_vcodecs.append(AV_CODEC_ID_MJPEG);
|
||||
format_vcodecs.append(AV_CODEC_ID_MSVIDEO1);
|
||||
format_vcodecs.append(AV_CODEC_ID_RAWVIDEO);
|
||||
format_vcodecs.append(AV_CODEC_ID_HUFFYUV);
|
||||
format_vcodecs.append(AV_CODEC_ID_DVVIDEO);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AAC);
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_FLAC);
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
|
||||
default_vcodec = 3;
|
||||
default_acodec = 5;
|
||||
break;
|
||||
case FORMAT_DNXHD:
|
||||
format_vcodecs.append(AV_CODEC_ID_DNXHD);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
break;
|
||||
case FORMAT_AC3:
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_EAC3);
|
||||
break;
|
||||
case FORMAT_FLV:
|
||||
format_vcodecs.append(AV_CODEC_ID_FLV1);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
break;
|
||||
case FORMAT_GIF:
|
||||
format_vcodecs.append(AV_CODEC_ID_GIF);
|
||||
break;
|
||||
case FORMAT_IMG:
|
||||
format_vcodecs.append(AV_CODEC_ID_BMP);
|
||||
format_vcodecs.append(AV_CODEC_ID_MJPEG);
|
||||
format_vcodecs.append(AV_CODEC_ID_JPEG2000);
|
||||
format_vcodecs.append(AV_CODEC_ID_PSD);
|
||||
format_vcodecs.append(AV_CODEC_ID_PNG);
|
||||
format_vcodecs.append(AV_CODEC_ID_TIFF);
|
||||
|
||||
default_vcodec = 4;
|
||||
break;
|
||||
case FORMAT_MP2:
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
break;
|
||||
case FORMAT_MP3:
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
break;
|
||||
case FORMAT_MPEG1:
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG1VIDEO);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
|
||||
default_acodec = 1;
|
||||
break;
|
||||
case FORMAT_MPEG2:
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG2VIDEO);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
|
||||
default_acodec = 1;
|
||||
break;
|
||||
case FORMAT_MPEG4:
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG4);
|
||||
format_vcodecs.append(AV_CODEC_ID_H264);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AAC);
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
|
||||
default_vcodec = 1;
|
||||
break;
|
||||
case FORMAT_MPEGTS:
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG2VIDEO);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AAC);
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
|
||||
default_acodec = 2;
|
||||
break;
|
||||
case FORMAT_MKV:
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG4);
|
||||
format_vcodecs.append(AV_CODEC_ID_H264);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AAC);
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_EAC3);
|
||||
format_acodecs.append(AV_CODEC_ID_FLAC);
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
format_acodecs.append(AV_CODEC_ID_OPUS);
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
format_acodecs.append(AV_CODEC_ID_VORBIS);
|
||||
format_acodecs.append(AV_CODEC_ID_WAVPACK);
|
||||
format_acodecs.append(AV_CODEC_ID_WMAV1);
|
||||
format_acodecs.append(AV_CODEC_ID_WMAV2);
|
||||
|
||||
default_vcodec = 1;
|
||||
break;
|
||||
case FORMAT_OGG:
|
||||
format_vcodecs.append(AV_CODEC_ID_THEORA);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_OPUS);
|
||||
format_acodecs.append(AV_CODEC_ID_VORBIS);
|
||||
|
||||
default_acodec = AV_CODEC_ID_VORBIS;
|
||||
break;
|
||||
case FORMAT_MOV:
|
||||
format_vcodecs.append(AV_CODEC_ID_QTRLE);
|
||||
format_vcodecs.append(AV_CODEC_ID_MPEG4);
|
||||
format_vcodecs.append(AV_CODEC_ID_H264);
|
||||
format_vcodecs.append(AV_CODEC_ID_MJPEG);
|
||||
format_vcodecs.append(AV_CODEC_ID_PRORES);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_AAC);
|
||||
format_acodecs.append(AV_CODEC_ID_AC3);
|
||||
format_acodecs.append(AV_CODEC_ID_MP2);
|
||||
format_acodecs.append(AV_CODEC_ID_MP3);
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
|
||||
default_vcodec = 2;
|
||||
break;
|
||||
case FORMAT_WAV:
|
||||
format_acodecs.append(AV_CODEC_ID_PCM_S16LE);
|
||||
break;
|
||||
case FORMAT_WEBM:
|
||||
format_vcodecs.append(AV_CODEC_ID_VP8);
|
||||
format_vcodecs.append(AV_CODEC_ID_VP9);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_OPUS);
|
||||
format_acodecs.append(AV_CODEC_ID_VORBIS);
|
||||
|
||||
default_vcodec = 1;
|
||||
break;
|
||||
case FORMAT_WMV:
|
||||
format_vcodecs.append(AV_CODEC_ID_WMV1);
|
||||
format_vcodecs.append(AV_CODEC_ID_WMV2);
|
||||
|
||||
format_acodecs.append(AV_CODEC_ID_WMAV1);
|
||||
format_acodecs.append(AV_CODEC_ID_WMAV2);
|
||||
|
||||
default_vcodec = 1;
|
||||
default_acodec = 1;
|
||||
break;
|
||||
default:
|
||||
qDebug() << "[ERROR] Invalid format selection - this is a bug, please inform the developers";
|
||||
}
|
||||
|
||||
AVCodec* codec_info;
|
||||
for (int i=0;i<format_vcodecs.size();i++) {
|
||||
codec_info = avcodec_find_encoder((enum AVCodecID) format_vcodecs.at(i));
|
||||
if (codec_info == NULL) {
|
||||
ui->vcodecCombobox->addItem("NULL");
|
||||
} else {
|
||||
ui->vcodecCombobox->addItem(codec_info->long_name);
|
||||
}
|
||||
}
|
||||
for (int i=0;i<format_acodecs.size();i++) {
|
||||
codec_info = avcodec_find_encoder((enum AVCodecID) format_acodecs.at(i));
|
||||
if (codec_info == NULL) {
|
||||
ui->acodecCombobox->addItem("NULL");
|
||||
} else {
|
||||
ui->acodecCombobox->addItem(codec_info->long_name);
|
||||
}
|
||||
}
|
||||
|
||||
ui->vcodecCombobox->setCurrentIndex(default_vcodec);
|
||||
ui->acodecCombobox->setCurrentIndex(default_acodec);
|
||||
|
||||
bool video_enabled = format_vcodecs.size() != 0;
|
||||
bool audio_enabled = format_acodecs.size() != 0;
|
||||
ui->videoGroupbox->setChecked(video_enabled);
|
||||
ui->audioGroupbox->setChecked(audio_enabled);
|
||||
ui->videoGroupbox->setEnabled(video_enabled);
|
||||
ui->audioGroupbox->setEnabled(audio_enabled);
|
||||
}
|
||||
|
||||
void ExportDialog::on_pushButton_2_clicked()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void ExportDialog::on_pushButton_clicked()
|
||||
{
|
||||
QString ext;
|
||||
switch (ui->formatCombobox->currentIndex()) {
|
||||
case FORMAT_3GPP:
|
||||
ext = "3gp";
|
||||
break;
|
||||
case FORMAT_AIFF:
|
||||
ext = "aiff";
|
||||
break;
|
||||
case FORMAT_APNG:
|
||||
ext = "apng";
|
||||
break;
|
||||
case FORMAT_AVI:
|
||||
ext = "avi";
|
||||
break;
|
||||
case FORMAT_DNXHD:
|
||||
ext = "mxf";
|
||||
break;
|
||||
case FORMAT_AC3:
|
||||
ext = "ac3";
|
||||
break;
|
||||
case FORMAT_FLV:
|
||||
ext = "flv";
|
||||
break;
|
||||
case FORMAT_GIF:
|
||||
ext = "gif";
|
||||
break;
|
||||
case FORMAT_IMG:
|
||||
// ext_name = "";
|
||||
// ext = "";
|
||||
// ext is determined from codec, but we prevent the switch from going to 'default' here
|
||||
qDebug() << "[INFO] Image export not implemented yet";
|
||||
return;
|
||||
break;
|
||||
case FORMAT_MP3:
|
||||
ext = "mp3";
|
||||
break;
|
||||
case FORMAT_MPEG1:
|
||||
if (ui->videoGroupbox->isChecked() && !ui->audioGroupbox->isChecked()) {
|
||||
ext = "m1v";
|
||||
} else if (!ui->videoGroupbox->isChecked() && ui->audioGroupbox->isChecked()) {
|
||||
ext = "m1a";
|
||||
} else {
|
||||
ext = "mpg";
|
||||
}
|
||||
break;
|
||||
case FORMAT_MPEG2:
|
||||
if (ui->videoGroupbox->isChecked() && !ui->audioGroupbox->isChecked()) {
|
||||
ext = "m2v";
|
||||
} else if (!ui->videoGroupbox->isChecked() && ui->audioGroupbox->isChecked()) {
|
||||
ext = "m2a";
|
||||
} else {
|
||||
ext = "mpg";
|
||||
}
|
||||
break;
|
||||
case FORMAT_MPEG4:
|
||||
if (ui->videoGroupbox->isChecked() && !ui->audioGroupbox->isChecked()) {
|
||||
ext = "m4v";
|
||||
} else if (!ui->videoGroupbox->isChecked() && ui->audioGroupbox->isChecked()) {
|
||||
ext = "m4a";
|
||||
} else {
|
||||
ext = "mp4";
|
||||
}
|
||||
break;
|
||||
case FORMAT_MPEGTS:
|
||||
ext = "ts";
|
||||
break;
|
||||
case FORMAT_MKV:
|
||||
if (!ui->videoGroupbox->isChecked()) {
|
||||
ext = "mka";
|
||||
} else {
|
||||
ext = "mkv";
|
||||
}
|
||||
break;
|
||||
case FORMAT_OGG:
|
||||
ext = "ogg";
|
||||
break;
|
||||
case FORMAT_MOV:
|
||||
ext = "mov";
|
||||
break;
|
||||
case FORMAT_WEBM:
|
||||
ext = "webm";
|
||||
break;
|
||||
case FORMAT_WMV:
|
||||
if (ui->videoGroupbox->isChecked()) {
|
||||
ext = "wmv";
|
||||
} else {
|
||||
ext = "wma";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
qDebug() << "[ERROR] Invalid format - this is a bug, please inform the developers";
|
||||
return;
|
||||
}
|
||||
QString filename = QFileDialog::getSaveFileName(this, "Export Media", "", format_strings[ui->formatCombobox->currentIndex()] + " (*." + ext + ")");
|
||||
if (!filename.isEmpty()) {
|
||||
ExportThread* et = new ExportThread();
|
||||
|
||||
et->surface.create();
|
||||
|
||||
connect(et, SIGNAL(finished()), et, SLOT(deleteLater()));
|
||||
connect(et, SIGNAL(progress_changed(int)), this, SLOT(update_progress_bar(int)));
|
||||
|
||||
panel_viewer->viewer_widget->context()->doneCurrent();
|
||||
panel_viewer->viewer_widget->context()->moveToThread(et);
|
||||
|
||||
et->filename = filename;
|
||||
et->video_enabled = ui->videoGroupbox->isChecked();
|
||||
et->video_codec = format_vcodecs.at(ui->vcodecCombobox->currentIndex());
|
||||
et->video_width = ui->widthSpinbox->value();
|
||||
et->video_height = ui->heightSpinbox->value();
|
||||
et->video_frame_rate = ui->framerateSpinbox->value();
|
||||
et->video_bitrate = ui->videobitrateSpinbox->value();
|
||||
et->audio_enabled = ui->audioGroupbox->isChecked();
|
||||
et->audio_codec = format_acodecs.at(ui->acodecCombobox->currentIndex());
|
||||
et->audio_sampling_rate = 48000;
|
||||
et->audio_bitrate = ui->audiobitrateSpinbox->value();
|
||||
|
||||
et->start();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef EXPORTDIALOG_H
|
||||
#define EXPORTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class ExportDialog;
|
||||
}
|
||||
|
||||
struct Sequence;
|
||||
|
||||
class ExportDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ExportDialog(QWidget *parent = 0);
|
||||
~ExportDialog();
|
||||
|
||||
void set_defaults(Sequence* s);
|
||||
|
||||
private slots:
|
||||
void on_formatCombobox_currentIndexChanged(int index);
|
||||
|
||||
void on_pushButton_2_clicked();
|
||||
|
||||
void on_pushButton_clicked();
|
||||
|
||||
void update_progress_bar(int value);
|
||||
|
||||
private:
|
||||
Ui::ExportDialog *ui;
|
||||
|
||||
QVector<QString> format_strings;
|
||||
QVector<int> format_vcodecs;
|
||||
QVector<int> format_acodecs;
|
||||
};
|
||||
|
||||
#endif // EXPORTDIALOG_H
|
||||
@@ -0,0 +1,232 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ExportDialog</class>
|
||||
<widget class="QDialog" name="ExportDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>299</width>
|
||||
<height>372</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Export</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Format: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="formatCombobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="videoGroupbox">
|
||||
<property name="title">
|
||||
<string>Video</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Codec:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="vcodecCombobox"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Width:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="widthSpinbox">
|
||||
<property name="maximum">
|
||||
<number>16777216</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Height:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="heightSpinbox">
|
||||
<property name="maximum">
|
||||
<number>16777216</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Frame Rate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QDoubleSpinBox" name="framerateSpinbox">
|
||||
<property name="maximum">
|
||||
<double>60.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Bitrate (Mbps/CBR):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QDoubleSpinBox" name="videobitrateSpinbox">
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>2.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="audioGroupbox">
|
||||
<property name="title">
|
||||
<string>Audio</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Codec:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="acodecCombobox"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Sampling Rate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="samplingRateSpinbox">
|
||||
<property name="maximum">
|
||||
<number>96000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Bitrate (Kbps/CBR):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="audiobitrateSpinbox">
|
||||
<property name="maximum">
|
||||
<number>320</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>256</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Export</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_2">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,110 @@
|
||||
#include "newsequencedialog.h"
|
||||
#include "ui_newsequencedialog.h"
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "panels/project.h"
|
||||
#include "project/sequence.h"
|
||||
|
||||
#include <QVariant>
|
||||
#include <QDebug>
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
NewSequenceDialog::NewSequenceDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::NewSequenceDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->frame_rate_combobox->addItem("10 FPS", 10.0f);
|
||||
ui->frame_rate_combobox->addItem("12.5 FPS", 12.5f);
|
||||
ui->frame_rate_combobox->addItem("15 FPS", 15.0f);
|
||||
ui->frame_rate_combobox->addItem("25 FPS", 25.0f);
|
||||
ui->frame_rate_combobox->addItem("29.97 FPS", 29.97f);
|
||||
ui->frame_rate_combobox->addItem("30 FPS", (float) 30.0f);
|
||||
ui->frame_rate_combobox->addItem("50 FPS", (float) 50.0f);
|
||||
ui->frame_rate_combobox->addItem("59.94 FPS", (float) 59.94f);
|
||||
ui->frame_rate_combobox->addItem("60 FPS", (float) 60.0f);
|
||||
ui->frame_rate_combobox->setCurrentIndex(4);
|
||||
|
||||
ui->audio_frequency_combobox->addItem("22050 Hz", 22050);
|
||||
ui->audio_frequency_combobox->addItem("24000 Hz", 24000);
|
||||
ui->audio_frequency_combobox->addItem("32000 Hz", 32000);
|
||||
ui->audio_frequency_combobox->addItem("44100 Hz", 44100);
|
||||
ui->audio_frequency_combobox->addItem("48000 Hz", 48000);
|
||||
ui->audio_frequency_combobox->addItem("88200 Hz", 88200);
|
||||
ui->audio_frequency_combobox->addItem("96000 Hz", 96000);
|
||||
ui->audio_frequency_combobox->setCurrentIndex(4);
|
||||
}
|
||||
|
||||
NewSequenceDialog::~NewSequenceDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NewSequenceDialog::set_sequence_name(const QString& s) {
|
||||
ui->lineEdit->setText(s);
|
||||
}
|
||||
|
||||
void NewSequenceDialog::on_buttonBox_accepted()
|
||||
{
|
||||
Sequence* s = new Sequence();
|
||||
|
||||
s->name = ui->lineEdit->text();
|
||||
s->width = ui->width_numeric->value();
|
||||
s->height = ui->height_numeric->value();
|
||||
s->frame_rate = ui->frame_rate_combobox->currentData().toFloat();
|
||||
s->audio_frequency = ui->audio_frequency_combobox->currentData().toInt();
|
||||
s->audio_layout = AV_CH_LAYOUT_STEREO;
|
||||
|
||||
panel_project->new_sequence(s);
|
||||
}
|
||||
|
||||
void NewSequenceDialog::on_comboBox_currentIndexChanged(int index)
|
||||
{
|
||||
switch (index) {
|
||||
case 0: // FILM 4K
|
||||
ui->width_numeric->setValue(4096);
|
||||
ui->height_numeric->setValue(2160);
|
||||
|
||||
break;
|
||||
case 1: // TV 4K
|
||||
ui->width_numeric->setValue(3840);
|
||||
ui->height_numeric->setValue(2160);
|
||||
break;
|
||||
case 2: // 1080p
|
||||
ui->width_numeric->setValue(1920);
|
||||
ui->height_numeric->setValue(1080);
|
||||
break;
|
||||
case 3: // 720p
|
||||
ui->width_numeric->setValue(1280);
|
||||
ui->height_numeric->setValue(720);
|
||||
break;
|
||||
case 4: // 480p
|
||||
ui->width_numeric->setValue(640);
|
||||
ui->height_numeric->setValue(480);
|
||||
break;
|
||||
case 5: // 360p
|
||||
ui->width_numeric->setValue(640);
|
||||
ui->height_numeric->setValue(360);
|
||||
break;
|
||||
case 6: // 240p
|
||||
ui->width_numeric->setValue(320);
|
||||
ui->height_numeric->setValue(240);
|
||||
break;
|
||||
case 7: // 144p
|
||||
ui->width_numeric->setValue(192);
|
||||
ui->height_numeric->setValue(144);
|
||||
break;
|
||||
case 8: // NTSC (480i)
|
||||
ui->width_numeric->setValue(720);
|
||||
ui->height_numeric->setValue(480);
|
||||
break;
|
||||
case 9: // PAL (576i)
|
||||
ui->width_numeric->setValue(720);
|
||||
ui->height_numeric->setValue(576);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef NEWSEQUENCEDIALOG_H
|
||||
#define NEWSEQUENCEDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class Project;
|
||||
|
||||
namespace Ui {
|
||||
class NewSequenceDialog;
|
||||
}
|
||||
|
||||
class NewSequenceDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NewSequenceDialog(QWidget *parent = 0);
|
||||
~NewSequenceDialog();
|
||||
void set_sequence_name(const QString& s);
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_accepted();
|
||||
|
||||
void on_comboBox_currentIndexChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::NewSequenceDialog *ui;
|
||||
};
|
||||
|
||||
#endif // NEWSEQUENCEDIALOG_H
|
||||
@@ -0,0 +1,360 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NewSequenceDialog</class>
|
||||
<widget class="QDialog" name="NewSequenceDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>298</width>
|
||||
<height>341</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>New Sequence</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Preset: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Film 4K</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>TV 4K (Ultra HD/2160p)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>1080p</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>720p</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>480p</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>360p</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>240p</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>144p</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>NTSC (480i)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>PAL (576i)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Custom</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Video</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="2" colspan="2">
|
||||
<widget class="QSpinBox" name="height_numeric">
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1080</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="2">
|
||||
<widget class="QSpinBox" name="width_numeric">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1920</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Width: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pixel Aspect Ratio: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Interlacing:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Height: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2" colspan="2">
|
||||
<widget class="QComboBox" name="par_combobox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Square Pixels (1.0)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2" colspan="2">
|
||||
<widget class="QComboBox" name="interlacing_combobox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None (Progressive)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Upper Field First</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Lower Field First</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="QComboBox" name="frame_rate_combobox"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Frame Rate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Audio</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sample Rate: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="audio_frequency_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Name: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit">
|
||||
<property name="text">
|
||||
<string>Sequence 01</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>NewSequenceDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>NewSequenceDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "effects/effects.h"
|
||||
|
||||
#include <QVector>
|
||||
|
||||
QVector<QString> video_effect_names;
|
||||
QVector<QString> audio_effect_names;
|
||||
|
||||
void init_effects() {
|
||||
video_effect_names.resize(VIDEO_EFFECT_COUNT);
|
||||
audio_effect_names.resize(AUDIO_EFFECT_COUNT);
|
||||
|
||||
video_effect_names[VIDEO_TRANSFORM_EFFECT] = "Transform";
|
||||
|
||||
audio_effect_names[AUDIO_VOLUME_EFFECT] = "Volume";
|
||||
audio_effect_names[AUDIO_PAN_EFFECT] = "Pan";
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#ifndef EFFECTS_H
|
||||
#define EFFECTS_H
|
||||
|
||||
#include "project/effect.h"
|
||||
|
||||
class QSpinBox;
|
||||
class QCheckBox;
|
||||
|
||||
enum VideoEffects {
|
||||
VIDEO_TRANSFORM_EFFECT,
|
||||
VIDEO_EFFECT_COUNT
|
||||
};
|
||||
|
||||
enum AudioEffects {
|
||||
AUDIO_VOLUME_EFFECT,
|
||||
AUDIO_PAN_EFFECT,
|
||||
AUDIO_EFFECT_COUNT
|
||||
};
|
||||
|
||||
extern QVector<QString> video_effect_names;
|
||||
extern QVector<QString> audio_effect_names;
|
||||
void init_effects();
|
||||
|
||||
// video effects
|
||||
class TransformEffect : public Effect {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TransformEffect(Clip* c);
|
||||
void process_gl(int* anchor_x, int* anchor_y);
|
||||
private:
|
||||
QSpinBox* position_x;
|
||||
QSpinBox* position_y;
|
||||
QSpinBox* scale_x;
|
||||
QSpinBox* scale_y;
|
||||
QCheckBox* uniform_scale_box;
|
||||
QSpinBox* rotation;
|
||||
QSpinBox* anchor_x_box;
|
||||
QSpinBox* anchor_y_box;
|
||||
QSpinBox* opacity;
|
||||
public slots:
|
||||
void toggle_uniform_scale(bool enabled);
|
||||
};
|
||||
|
||||
// audio effects
|
||||
class VolumeEffect : public Effect {
|
||||
public:
|
||||
VolumeEffect(Clip* c);
|
||||
void process_audio(uint8_t* samples, int nb_bytes);
|
||||
private:
|
||||
QSpinBox* volume_val;
|
||||
};
|
||||
|
||||
class PanEffect : public Effect {
|
||||
public:
|
||||
PanEffect(Clip* c);
|
||||
void process_audio(uint8_t* samples, int nb_bytes);
|
||||
private:
|
||||
QSpinBox* pan_val;
|
||||
};
|
||||
|
||||
#endif // EFFECTS_H
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "effects/effects.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QSpinBox>
|
||||
#include <QLabel>
|
||||
|
||||
#include "ui/collapsiblewidget.h"
|
||||
|
||||
PanEffect::PanEffect(Clip* c) : Effect(c) {
|
||||
container = new CollapsibleWidget();
|
||||
container->setText(audio_effect_names[AUDIO_PAN_EFFECT]);
|
||||
|
||||
ui = new QWidget();
|
||||
|
||||
QGridLayout* ui_layout = new QGridLayout();
|
||||
|
||||
ui_layout->addWidget(new QLabel("Pan:"), 0, 0);
|
||||
pan_val = new QSpinBox();
|
||||
pan_val->setMinimum(-100);
|
||||
pan_val->setMaximum(100);
|
||||
ui_layout->addWidget(pan_val, 0, 1);
|
||||
|
||||
ui->setLayout(ui_layout);
|
||||
|
||||
container->setContents(ui);
|
||||
|
||||
// set defaults
|
||||
pan_val->setValue(0);
|
||||
}
|
||||
|
||||
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]);
|
||||
int16_t right_sample = (int16_t) ((samples[i+3] << 8) | samples[i+2]);
|
||||
|
||||
float val = pan_val->value()*0.01;
|
||||
if (val < 0) {
|
||||
// affect right channel
|
||||
right_sample *= (1-abs(val));
|
||||
} else {
|
||||
// affect left channel
|
||||
left_sample *= (1-val);
|
||||
}
|
||||
|
||||
samples[i+3] = (uint8_t) (right_sample >> 8);
|
||||
samples[i+2] = (uint8_t) right_sample;
|
||||
samples[i+1] = (uint8_t) (left_sample >> 8);
|
||||
samples[i] = (uint8_t) left_sample;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
#include "effects/effects.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QWidget>
|
||||
#include <QLabel>
|
||||
#include <QGridLayout>
|
||||
#include <QSpinBox>
|
||||
#include <QCheckBox>
|
||||
#include <QOpenGLFunctions>
|
||||
|
||||
#include "ui/collapsiblewidget.h"
|
||||
#include "project/clip.h"
|
||||
#include "project/sequence.h"
|
||||
#include "io/media.h"
|
||||
|
||||
TransformEffect::TransformEffect(Clip* c) : Effect(c) {
|
||||
container = new CollapsibleWidget();
|
||||
container->setText(video_effect_names[VIDEO_TRANSFORM_EFFECT]);
|
||||
|
||||
ui = new QWidget();
|
||||
|
||||
QGridLayout* ui_layout = new QGridLayout();
|
||||
|
||||
ui_layout->addWidget(new QLabel("Position:"), 0, 0);
|
||||
position_x = new QSpinBox();
|
||||
position_x->setMinimum(-QWIDGETSIZE_MAX);
|
||||
position_x->setMaximum(QWIDGETSIZE_MAX);
|
||||
ui_layout->addWidget(position_x, 0, 1);
|
||||
position_y = new QSpinBox();
|
||||
position_y->setMinimum(-QWIDGETSIZE_MAX);
|
||||
position_y->setMaximum(QWIDGETSIZE_MAX);
|
||||
ui_layout->addWidget(position_y, 0, 2);
|
||||
|
||||
ui_layout->addWidget(new QLabel("Scale:"), 1, 0);
|
||||
scale_x = new QSpinBox();
|
||||
scale_x->setMinimum(0);
|
||||
scale_x->setMaximum(1200);
|
||||
ui_layout->addWidget(scale_x, 1, 1);
|
||||
scale_y = new QSpinBox();
|
||||
scale_y->setMinimum(0);
|
||||
scale_y->setMaximum(1200);
|
||||
ui_layout->addWidget(scale_y, 1, 2);
|
||||
|
||||
uniform_scale_box = new QCheckBox();
|
||||
uniform_scale_box->setText("Uniform Scale");
|
||||
ui_layout->addWidget(uniform_scale_box, 2, 1);
|
||||
|
||||
ui_layout->addWidget(new QLabel("Rotation:"), 3, 0);
|
||||
rotation = new QSpinBox();
|
||||
rotation->setMinimum(-QWIDGETSIZE_MAX);
|
||||
rotation->setMaximum(QWIDGETSIZE_MAX);
|
||||
ui_layout->addWidget(rotation, 3, 1);
|
||||
|
||||
ui_layout->addWidget(new QLabel("Anchor Point:"), 4, 0);
|
||||
anchor_x_box = new QSpinBox();
|
||||
anchor_x_box->setMinimum(-QWIDGETSIZE_MAX);
|
||||
anchor_x_box->setMaximum(QWIDGETSIZE_MAX);
|
||||
ui_layout->addWidget(anchor_x_box, 4, 1);
|
||||
anchor_y_box = new QSpinBox();
|
||||
anchor_y_box->setMinimum(-QWIDGETSIZE_MAX);
|
||||
anchor_y_box->setMaximum(QWIDGETSIZE_MAX);
|
||||
ui_layout->addWidget(anchor_y_box, 4, 2);
|
||||
|
||||
ui_layout->addWidget(new QLabel("Opacity:"), 5, 0);
|
||||
opacity = new QSpinBox();
|
||||
opacity->setMinimum(0);
|
||||
opacity->setMaximum(100);
|
||||
ui_layout->addWidget(opacity, 5, 1);
|
||||
|
||||
ui->setLayout(ui_layout);
|
||||
|
||||
container->setContents(ui);
|
||||
|
||||
// set defaults
|
||||
position_x->setValue(c->sequence->width/2);
|
||||
position_y->setValue(c->sequence->height/2);
|
||||
scale_x->setValue(100);
|
||||
scale_y->setValue(100);
|
||||
scale_y->setEnabled(false);
|
||||
uniform_scale_box->setChecked(true);
|
||||
anchor_x_box->setValue(c->media_stream->video_width/2);
|
||||
anchor_y_box->setValue(c->media_stream->video_height/2);
|
||||
opacity->setValue(100);
|
||||
|
||||
connect(position_x, SIGNAL(valueChanged(int)), this, SLOT(field_changed()));
|
||||
connect(position_y, SIGNAL(valueChanged(int)), this, SLOT(field_changed()));
|
||||
connect(rotation, SIGNAL(valueChanged(int)), this, SLOT(field_changed()));
|
||||
connect(scale_x, SIGNAL(valueChanged(int)), this, SLOT(field_changed()));
|
||||
connect(scale_y, SIGNAL(valueChanged(int)), this, SLOT(field_changed()));
|
||||
connect(anchor_x_box, SIGNAL(valueChanged(int)), this, SLOT(field_changed()));
|
||||
connect(anchor_y_box, SIGNAL(valueChanged(int)), this, SLOT(field_changed()));
|
||||
connect(opacity, SIGNAL(valueChanged(int)), this, SLOT(field_changed()));
|
||||
connect(uniform_scale_box, SIGNAL(toggled(bool)), this, SLOT(toggle_uniform_scale(bool)));
|
||||
connect(uniform_scale_box, SIGNAL(toggled(bool)), this, SLOT(field_changed()));
|
||||
}
|
||||
|
||||
void TransformEffect::toggle_uniform_scale(bool enabled) {
|
||||
scale_y->setEnabled(!enabled);
|
||||
}
|
||||
|
||||
void TransformEffect::process_gl(int* anchor_x, int* anchor_y) {
|
||||
// position
|
||||
glTranslatef(position_x->value()-(parent_clip->sequence->width/2), position_y->value()-(parent_clip->sequence->height/2), 0);
|
||||
|
||||
// anchor point
|
||||
*anchor_x += anchor_x_box->value();
|
||||
*anchor_y += anchor_y_box->value();
|
||||
|
||||
// rotation
|
||||
glRotatef(rotation->value(), 0, 0, 1);
|
||||
|
||||
// scale
|
||||
float sx = scale_x->value()*0.01;
|
||||
float sy = (uniform_scale_box->isChecked()) ? sx : scale_y->value()*0.01;
|
||||
glScalef(sx, sy, 1);
|
||||
|
||||
// opacity
|
||||
glColor4f(1.0, 1.0, 1.0, opacity->value()*0.01);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#include "effects/effects.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QSpinBox>
|
||||
#include <QLabel>
|
||||
|
||||
#include "ui/collapsiblewidget.h"
|
||||
|
||||
VolumeEffect::VolumeEffect(Clip* c) : Effect(c) {
|
||||
container = new CollapsibleWidget();
|
||||
container->setText(audio_effect_names[AUDIO_VOLUME_EFFECT]);
|
||||
|
||||
ui = new QWidget();
|
||||
|
||||
QGridLayout* ui_layout = new QGridLayout();
|
||||
|
||||
ui_layout->addWidget(new QLabel("Volume:"), 0, 0);
|
||||
volume_val = new QSpinBox();
|
||||
volume_val->setMinimum(0);
|
||||
volume_val->setMaximum(100);
|
||||
ui_layout->addWidget(volume_val, 0, 1);
|
||||
|
||||
ui->setLayout(ui_layout);
|
||||
|
||||
container->setContents(ui);
|
||||
|
||||
// set defaults
|
||||
volume_val->setValue(100);
|
||||
}
|
||||
|
||||
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]);
|
||||
full_sample *= volume_val->value()*0.01;
|
||||
samples[i+1] = (uint8_t) (full_sample >> 8);
|
||||
samples[i] = (uint8_t) full_sample;
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 21 KiB |
@@ -0,0 +1,19 @@
|
||||
<RCC>
|
||||
<qresource prefix="/icons">
|
||||
<file>play.png</file>
|
||||
<file>ff.png</file>
|
||||
<file>next.png</file>
|
||||
<file>pause.png</file>
|
||||
<file>prev.png</file>
|
||||
<file>rew.png</file>
|
||||
<file>arrow.png</file>
|
||||
<file>beam.png</file>
|
||||
<file>razor.png</file>
|
||||
<file>full-icon.png</file>
|
||||
<file>audiosource.png</file>
|
||||
<file>videosource.png</file>
|
||||
<file>ripple.png</file>
|
||||
<file>rolling.png</file>
|
||||
<file>slip.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
@@ -0,0 +1 @@
|
||||
olicon ICON "olive.ico"
|
||||
@@ -0,0 +1,49 @@
|
||||
#include "config.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
const char* version = "Olive (May 2018 | Pre-Alpha)";
|
||||
float scale = 1.0f;
|
||||
bool vsync = true;
|
||||
bool hwaccel = false;
|
||||
int padding = 8;
|
||||
bool custom_scale = false;
|
||||
bool saved_layout = false;
|
||||
bool left_mouse_dominant = true;
|
||||
bool show_track_lines = false;
|
||||
|
||||
void load_config() {
|
||||
/*if (!custom_scale) {
|
||||
#ifdef _WIN32
|
||||
// Get Windows UI scale - TODO may not be compatible with XP
|
||||
HDC screen = GetDC(0);
|
||||
int dpiX = GetDeviceCaps (screen, LOGPIXELSX);
|
||||
//int dpiY = GetDeviceCaps (screen, LOGPIXELSY);
|
||||
|
||||
scale = (float) dpiX / 96;
|
||||
|
||||
ReleaseDC (0, screen);
|
||||
#endif
|
||||
}*/
|
||||
|
||||
padding *= scale;
|
||||
|
||||
/*DIR* dir = opendir("conf");
|
||||
if (dir) {
|
||||
closedir(dir);
|
||||
} else if (ENOENT == errno) {
|
||||
// no config directory, assume this is the first time opening Olive
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "INFO", "NOTE: This version of Olive is INCOMPLETE and very likely to crash. It comes with NO WARRANTY or guarantee of functionality.\n\nRegardless, thanks for checking out the project and I hope you enjoy using it!", NULL);
|
||||
}*/
|
||||
}
|
||||
|
||||
void save_config() {
|
||||
/*#ifdef _WIN32
|
||||
_mkdir("conf");
|
||||
#else
|
||||
mkdir("conf", 0777);
|
||||
#endif*/
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
extern const char* version;
|
||||
extern float scale;
|
||||
extern bool vsync;
|
||||
extern bool hwaccel;
|
||||
extern int padding;
|
||||
extern bool custom_scale;
|
||||
extern bool saved_layout;
|
||||
extern bool show_track_lines;
|
||||
|
||||
void load_config();
|
||||
void save_config();
|
||||
|
||||
#endif // CONFIG_H
|
||||
@@ -0,0 +1,342 @@
|
||||
#include "exportthread.h"
|
||||
|
||||
#include "project/sequence.h"
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
#include "playback/playback.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswresample/swresample.h>
|
||||
#include <libswscale/swscale.h>
|
||||
}
|
||||
|
||||
#include <QDebug>
|
||||
#include <QApplication>
|
||||
#include <QOffscreenSurface>
|
||||
#include <QOpenGLFramebufferObject>
|
||||
#include <QOpenGlPaintDevice>
|
||||
#include <QPainter>
|
||||
|
||||
bool encode(AVFormatContext* fmt_ctx, AVCodecContext* codec_ctx, AVFrame* frame, AVPacket* packet, AVStream* stream) {
|
||||
int ret = avcodec_send_frame(codec_ctx, frame);
|
||||
if (ret < 0) {
|
||||
qDebug() << "[ERROR] Failed to send frame to encoder." << ret;
|
||||
return false;
|
||||
} else {
|
||||
while (ret >= 0) {
|
||||
ret = avcodec_receive_packet(codec_ctx, packet);
|
||||
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
|
||||
// do nothing, encoder needs more input
|
||||
} else if (ret < 0) {
|
||||
qDebug() << "[ERROR] Failed to receive packet from encoder." << ret;
|
||||
return false;
|
||||
} else {
|
||||
packet->stream_index = stream->index;
|
||||
av_interleaved_write_frame(fmt_ctx, packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExportThread::run() {
|
||||
Sequence* sequence = panel_timeline->sequence;
|
||||
|
||||
// TODO make customizable
|
||||
long start = 0;
|
||||
long end = sequence->getEndFrame();
|
||||
|
||||
if (panel_viewer->viewer_widget->context()->makeCurrent(&surface)) {
|
||||
qDebug() << "make current succeeded";
|
||||
} else {
|
||||
qDebug() << "make current failed";
|
||||
}
|
||||
panel_viewer->viewer_widget->multithreaded = false;
|
||||
panel_viewer->viewer_widget->initializeOpenGLFunctions();
|
||||
|
||||
AVFormatContext* fmt_ctx = NULL;
|
||||
QByteArray ba = filename.toLatin1();
|
||||
char* c_filename = new char[ba.size()+1];
|
||||
strcpy(c_filename, ba.data());
|
||||
|
||||
avformat_alloc_output_context2(&fmt_ctx, NULL, NULL, c_filename);
|
||||
if (!fmt_ctx) {
|
||||
qDebug() << "[ERROR] Could not create output context";
|
||||
} else {
|
||||
AVStream* video_stream;
|
||||
AVCodec* vcodec;
|
||||
AVCodecContext* vcodec_ctx;
|
||||
AVFrame* video_frame;
|
||||
SwsContext* sws_ctx = NULL;
|
||||
// AVStream* audio_stream;
|
||||
// AVCodec* acodec;
|
||||
// AVFrame* audio_frame;
|
||||
// AVCodecContext* acodec_ctx;
|
||||
AVPacket video_pkt;
|
||||
// AVPacket audio_pkt;
|
||||
// SwrContext* swr_ctx = NULL;
|
||||
int ret;
|
||||
|
||||
bool fail = false;
|
||||
|
||||
if (video_enabled) {
|
||||
// initialize array contain opengl data
|
||||
video_stream = avformat_new_stream(fmt_ctx, NULL);
|
||||
|
||||
if (!video_stream) {
|
||||
qDebug() << "[ERROR] Could not allocate output streams";
|
||||
fail = true;
|
||||
} else {
|
||||
vcodec = avcodec_find_encoder((enum AVCodecID) video_codec);
|
||||
|
||||
if (!vcodec) {
|
||||
qDebug() << "[ERROR] Could not find video encoder";
|
||||
fail = true;
|
||||
} else {
|
||||
vcodec_ctx = avcodec_alloc_context3(vcodec);
|
||||
|
||||
if (!vcodec_ctx) {
|
||||
qDebug() << "[ERROR] Could not find allocate video encoding context";
|
||||
fail = true;
|
||||
} else {
|
||||
vcodec_ctx->width = sequence->width;
|
||||
vcodec_ctx->height = sequence->height;
|
||||
vcodec_ctx->sample_aspect_ratio = av_d2q(sequence->width/sequence->height, INT_MAX);
|
||||
vcodec_ctx->pix_fmt = vcodec->pix_fmts[0]; // maybe be breakable code
|
||||
vcodec_ctx->framerate = av_d2q(sequence->frame_rate, INT_MAX);
|
||||
vcodec_ctx->bit_rate = video_bitrate * 1000000;
|
||||
vcodec_ctx->time_base = av_inv_q(vcodec_ctx->framerate);
|
||||
|
||||
ret = avcodec_open2(vcodec_ctx, vcodec, NULL);
|
||||
if (ret < 0) {
|
||||
qDebug() << "[ERROR] Could not open output video encoder." << ret;
|
||||
fail = true;
|
||||
} else {
|
||||
ret = avcodec_parameters_from_context(video_stream->codecpar, vcodec_ctx);
|
||||
if (ret < 0) {
|
||||
qDebug() << "[ERROR] Could not copy video encoder parameters to output stream." << ret;
|
||||
fail = true;
|
||||
} else {
|
||||
if (fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) {
|
||||
vcodec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||
}
|
||||
|
||||
video_stream->time_base = vcodec_ctx->time_base;
|
||||
|
||||
// initialize raw video frame
|
||||
video_frame = av_frame_alloc();
|
||||
av_frame_make_writable(video_frame);
|
||||
video_frame->format = AV_PIX_FMT_RGBA;
|
||||
video_frame->width = video_width;
|
||||
video_frame->height = video_height;
|
||||
av_frame_get_buffer(video_frame, 0);
|
||||
|
||||
av_init_packet(&video_pkt);
|
||||
|
||||
sws_ctx = sws_getContext(
|
||||
video_width,
|
||||
video_height,
|
||||
AV_PIX_FMT_RGBA,
|
||||
video_width,
|
||||
video_height,
|
||||
AV_PIX_FMT_YUV420P,
|
||||
SWS_FAST_BILINEAR,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if (audio_enabled && !fail) {
|
||||
// audio_stream = avformat_new_stream(fmt_ctx, NULL);
|
||||
// if (!audio_stream) {
|
||||
// qDebug() << "[ERROR] Could not allocate output streams";
|
||||
// fail = true;
|
||||
// } else {
|
||||
// acodec = avcodec_find_encoder((enum AVCodecID) audio_codec);
|
||||
// if (!acodec) {
|
||||
// qDebug() << "[ERROR] Could not find audio encoder";
|
||||
// fail = true;
|
||||
// } else {
|
||||
// acodec_ctx = avcodec_alloc_context3(acodec);
|
||||
// if (!acodec_ctx) {
|
||||
// qDebug() << "[ERROR] Could not find allocate audio encoding context";
|
||||
// fail = true;
|
||||
// } else {
|
||||
// acodec_ctx->sample_rate = audio_sampling_rate;
|
||||
// acodec_ctx->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
// acodec_ctx->channels = av_get_channel_layout_nb_channels(acodec_ctx->channel_layout);
|
||||
// acodec_ctx->sample_fmt = acodec->sample_fmts[0];
|
||||
// acodec_ctx->time_base = {1, audio_sampling_rate};
|
||||
// acodec_ctx->bit_rate = audio_bitrate * 1000;
|
||||
|
||||
// ret = avcodec_open2(acodec_ctx, acodec, NULL);
|
||||
// if (ret < 0) {
|
||||
// qDebug() << "[ERROR] Could not open output audio encoder." << ret;
|
||||
// fail = true;
|
||||
// } else {
|
||||
// ret = avcodec_parameters_from_context(audio_stream->codecpar, acodec_ctx);
|
||||
// if (ret < 0) {
|
||||
// qDebug() << "[ERROR] Could not copy audio encoder parameters to output stream." << ret;
|
||||
// fail = true;
|
||||
// } else {
|
||||
// if (fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) {
|
||||
// acodec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||
// }
|
||||
|
||||
// audio_stream->time_base = acodec_ctx->time_base;
|
||||
|
||||
// // init audio resampler context
|
||||
// swr_ctx = swr_alloc_set_opts(
|
||||
// NULL,
|
||||
// acodec_ctx->channel_layout,
|
||||
// acodec_ctx->sample_fmt,
|
||||
// acodec_ctx->sample_rate,
|
||||
// sequence->audio_layout,
|
||||
// AV_SAMPLE_FMT_S16,
|
||||
// sequence->audio_frequency,
|
||||
// 0,
|
||||
// NULL
|
||||
// );
|
||||
// swr_init(swr_ctx);
|
||||
|
||||
// // initialize raw audio frame
|
||||
// audio_frame = av_frame_alloc();
|
||||
// audio_frame->nb_samples = acodec_ctx->frame_size;
|
||||
// if (audio_frame->nb_samples == 0) audio_frame->nb_samples = 2048; // should probably be way smaller?
|
||||
// audio_frame->format = acodec_ctx->sample_fmt;
|
||||
// audio_frame->channels = acodec_ctx->channels;
|
||||
// audio_frame->channel_layout = acodec_ctx->channel_layout;
|
||||
// ret = av_frame_get_buffer(audio_frame, 0);
|
||||
// if (ret < 0) {
|
||||
// qDebug() << "[ERROR] Could not allocate audio buffer." << ret;
|
||||
// }
|
||||
// // av_samples_alloc(&audio_frame->data[0], NULL, av_get_channel_layout_nb_channels(audio_frame->channel_layout), audio_frame->nb_samples, acodec_ctx->sample_fmt, 0);
|
||||
// av_frame_make_writable(audio_frame);
|
||||
|
||||
// av_init_packet(&audio_pkt);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!fail) {
|
||||
av_dump_format(fmt_ctx, 0, c_filename, 1);
|
||||
|
||||
ret = avio_open(&fmt_ctx->pb, c_filename, AVIO_FLAG_WRITE);
|
||||
if (ret < 0) {
|
||||
qDebug() << "[ERROR] Could not open output file." << ret;
|
||||
} else {
|
||||
ret = avformat_write_header(fmt_ctx, NULL);
|
||||
if (ret < 0) {
|
||||
qDebug() << "[ERROR] Could not write output file header." << ret;
|
||||
} else {
|
||||
panel_timeline->seek(0);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
QOpenGLFramebufferObject fbo(video_width, video_height, QOpenGLFramebufferObject::CombinedDepthStencil, GL_TEXTURE_RECTANGLE);
|
||||
fbo.bind();
|
||||
QOpenGLPaintDevice fbo_dev(video_width, video_height);
|
||||
QPainter painter(&fbo_dev);
|
||||
painter.beginNativePainting();
|
||||
|
||||
AVFrame* sws_frame = av_frame_alloc();
|
||||
sws_frame->format = AV_PIX_FMT_YUV420P;
|
||||
sws_frame->width = video_frame->width;
|
||||
sws_frame->height = video_frame->height;
|
||||
av_frame_get_buffer(sws_frame, 0);
|
||||
uint8_t* flip_buffer = new uint8_t[video_frame->width * video_frame->height * 4];
|
||||
|
||||
while (panel_timeline->playhead < end && !fail) {
|
||||
panel_viewer->viewer_widget->paintGL();
|
||||
|
||||
double timecode_secs = (double) panel_timeline->playhead / sequence->frame_rate;
|
||||
if (video_enabled) {
|
||||
// get image from opengl
|
||||
glReadPixels(0, 0, video_width, video_height, GL_RGBA, GL_UNSIGNED_BYTE, flip_buffer);
|
||||
|
||||
// flip image vertically because opengl sucks ass
|
||||
int linesize = video_width*4;
|
||||
for (int i=video_height-1;i>=0;i--) {
|
||||
int src_index = i*linesize;
|
||||
int dst_index = (video_height-i)*linesize;
|
||||
memcpy(video_frame->data[0]+dst_index, flip_buffer+src_index, linesize);
|
||||
}
|
||||
|
||||
// change pixel format
|
||||
sws_scale(sws_ctx, video_frame->data, video_frame->linesize, 0, video_frame->height, sws_frame->data, sws_frame->linesize);
|
||||
sws_frame->pts = round(timecode_secs/av_q2d(video_stream->time_base));
|
||||
|
||||
// send to encoder
|
||||
if (!encode(fmt_ctx, vcodec_ctx, sws_frame, &video_pkt, video_stream)) fail = true;
|
||||
}
|
||||
emit progress_changed(((float) panel_timeline->playhead / (float) end) * 100);
|
||||
panel_timeline->playhead++;
|
||||
}
|
||||
|
||||
delete [] flip_buffer;
|
||||
painter.endNativePainting();
|
||||
fbo.release();
|
||||
|
||||
av_frame_free(&sws_frame);
|
||||
|
||||
if (!fail) {
|
||||
// flush remaining packets
|
||||
if (video_enabled) {
|
||||
if (!encode(fmt_ctx, vcodec_ctx, NULL, &video_pkt, video_stream)) fail = true;
|
||||
}
|
||||
// if (audio_enabled) {
|
||||
// if (!encode(fmt_ctx, acodec_ctx, NULL, &audio_pkt, audio_stream)) return false;
|
||||
// }
|
||||
}
|
||||
|
||||
if (!fail) {
|
||||
ret = av_write_trailer(fmt_ctx);
|
||||
if (ret < 0) {
|
||||
qDebug() << "[ERROR] Could not write output file trailer." << ret;
|
||||
}
|
||||
|
||||
emit progress_changed(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
av_packet_unref(&video_pkt);
|
||||
av_frame_free(&video_frame);
|
||||
avcodec_free_context(&vcodec_ctx);
|
||||
// avcodec_free_context(&acodec_ctx);
|
||||
avio_closep(&fmt_ctx->pb);
|
||||
avformat_free_context(fmt_ctx);
|
||||
|
||||
// qDebug() << "Render took: %ih %im %is\n", render_time/3600000, render_time/60000, render_time/1000;
|
||||
|
||||
if (sws_ctx != NULL) sws_freeContext(sws_ctx);
|
||||
// if (swr_ctx != NULL) swr_free(&swr_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
delete [] c_filename;
|
||||
|
||||
panel_viewer->viewer_widget->context()->doneCurrent();
|
||||
panel_viewer->viewer_widget->context()->moveToThread(qApp->thread());
|
||||
panel_viewer->viewer_widget->multithreaded = true;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef EXPORTTHREAD_H
|
||||
#define EXPORTTHREAD_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QOffscreenSurface>
|
||||
|
||||
class ExportThread : public QThread {
|
||||
Q_OBJECT
|
||||
public:
|
||||
void run() override;
|
||||
|
||||
// export parameters
|
||||
QString filename;
|
||||
bool video_enabled;
|
||||
int video_codec;
|
||||
int video_width;
|
||||
int video_height;
|
||||
double video_frame_rate;
|
||||
double video_bitrate;
|
||||
bool audio_enabled;
|
||||
int audio_codec;
|
||||
int audio_sampling_rate;
|
||||
int audio_bitrate;
|
||||
|
||||
QOffscreenSurface surface;
|
||||
signals:
|
||||
void progress_changed(int value);
|
||||
};
|
||||
|
||||
#endif // EXPORTTHREAD_H
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "media.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
}
|
||||
|
||||
long Media::get_length_in_frames(float frame_rate) {
|
||||
return ceil((float) length / (float) AV_TIME_BASE * frame_rate);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef MEDIA_H
|
||||
#define MEDIA_H
|
||||
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QMetaType>
|
||||
#include <QVariant>
|
||||
|
||||
struct Sequence;
|
||||
|
||||
struct MediaStream {
|
||||
int file_index;
|
||||
int video_width;
|
||||
int video_height;
|
||||
bool infinite_length;
|
||||
};
|
||||
|
||||
struct Media
|
||||
{
|
||||
QString url;
|
||||
QString name;
|
||||
bool is_sequence;
|
||||
int64_t length;
|
||||
QVector<MediaStream> video_tracks;
|
||||
QVector<MediaStream> audio_tracks;
|
||||
Sequence* sequence;
|
||||
long get_length_in_frames(float frame_rate);
|
||||
};
|
||||
|
||||
#endif // MEDIA_H
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "mainwindow.h"
|
||||
#include <QApplication>
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// init ffmpeg subsystem
|
||||
av_register_all();
|
||||
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include "io/config.h"
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "panels/project.h"
|
||||
#include "panels/effectcontrols.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "panels/timeline.h"
|
||||
|
||||
#include "dialogs/aboutdialog.h"
|
||||
#include "dialogs/newsequencedialog.h"
|
||||
#include "dialogs/exportdialog.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QStyleFactory>
|
||||
|
||||
void MainWindow::setup_layout() {
|
||||
panel_project = new Project(this);
|
||||
panel_effect_controls = new EffectControls(this);
|
||||
panel_viewer = new Viewer(this);
|
||||
panel_timeline = new Timeline(this);
|
||||
|
||||
addDockWidget(Qt::TopDockWidgetArea, panel_project);
|
||||
addDockWidget(Qt::TopDockWidgetArea, panel_effect_controls);
|
||||
addDockWidget(Qt::TopDockWidgetArea, panel_viewer);
|
||||
addDockWidget(Qt::BottomDockWidgetArea, panel_timeline);
|
||||
|
||||
setCentralWidget(NULL);
|
||||
}
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow)
|
||||
{
|
||||
// set up style?
|
||||
|
||||
qApp->setStyle(QStyleFactory::create("Fusion"));
|
||||
|
||||
QPalette darkPalette;
|
||||
darkPalette.setColor(QPalette::Window, QColor(53,53,53));
|
||||
darkPalette.setColor(QPalette::WindowText, Qt::white);
|
||||
darkPalette.setColor(QPalette::Base, QColor(25,25,25));
|
||||
darkPalette.setColor(QPalette::AlternateBase, QColor(53,53,53));
|
||||
darkPalette.setColor(QPalette::ToolTipBase, Qt::white);
|
||||
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
|
||||
darkPalette.setColor(QPalette::Text, Qt::white);
|
||||
darkPalette.setColor(QPalette::Button, QColor(53,53,53));
|
||||
darkPalette.setColor(QPalette::ButtonText, Qt::white); darkPalette.setColor(QPalette::BrightText, Qt::red);
|
||||
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(128, 128, 128));
|
||||
darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
|
||||
|
||||
darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
|
||||
darkPalette.setColor(QPalette::HighlightedText, Qt::black);
|
||||
|
||||
|
||||
|
||||
qApp->setPalette(darkPalette);
|
||||
|
||||
// end style
|
||||
|
||||
setWindowState(Qt::WindowMaximized);
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
setWindowTitle("Olive (May 2018 | Pre-Alpha)");
|
||||
statusBar()->showMessage("Welcome to Olive::Qt");
|
||||
|
||||
setup_layout();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Import_triggered()
|
||||
{
|
||||
panel_project->import_dialog();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionExit_triggered()
|
||||
{
|
||||
QApplication::quit();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAbout_triggered()
|
||||
{
|
||||
AboutDialog a(this);
|
||||
a.exec();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionDelete_triggered()
|
||||
{
|
||||
if (panel_timeline->focused()) {
|
||||
panel_timeline->delete_selection(false);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSelect_All_triggered()
|
||||
{
|
||||
if (panel_timeline->focused()) {
|
||||
panel_timeline->select_all();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSequence_triggered()
|
||||
{
|
||||
NewSequenceDialog nsd;
|
||||
nsd.set_sequence_name(panel_project->get_next_sequence_name());
|
||||
nsd.exec();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionZoom_In_triggered()
|
||||
{
|
||||
if (panel_timeline->focused()) {
|
||||
panel_timeline->zoom_in();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionZoom_out_triggered()
|
||||
{
|
||||
if (panel_timeline->focused()) {
|
||||
panel_timeline->zoom_out();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionTimeline_Track_Lines_toggled(bool e)
|
||||
{
|
||||
show_track_lines = e;
|
||||
panel_timeline->redraw_all_clips();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionExport_triggered()
|
||||
{
|
||||
ExportDialog e;
|
||||
if (panel_timeline->sequence != NULL) e.set_defaults(panel_timeline->sequence);
|
||||
e.exec();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionProject_2_toggled(bool arg1)
|
||||
{
|
||||
panel_project->setVisible(arg1);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionEffect_Controls_toggled(bool arg1)
|
||||
{
|
||||
panel_effect_controls->setVisible(arg1);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionViewer_toggled(bool arg1)
|
||||
{
|
||||
panel_viewer->setVisible(arg1);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionTimeline_toggled(bool arg1)
|
||||
{
|
||||
panel_timeline->setVisible(arg1);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionRipple_Delete_triggered()
|
||||
{
|
||||
panel_timeline->delete_selection(true);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
class Project;
|
||||
class EffectControls;
|
||||
class Viewer;
|
||||
class Timeline;
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
private slots:
|
||||
void on_action_Import_triggered();
|
||||
|
||||
void on_actionExit_triggered();
|
||||
|
||||
void on_actionAbout_triggered();
|
||||
|
||||
void on_actionDelete_triggered();
|
||||
|
||||
void on_actionSelect_All_triggered();
|
||||
|
||||
void on_actionSequence_triggered();
|
||||
|
||||
void on_actionZoom_In_triggered();
|
||||
|
||||
void on_actionZoom_out_triggered();
|
||||
|
||||
void on_actionTimeline_Track_Lines_toggled(bool arg1);
|
||||
|
||||
void on_actionExport_triggered();
|
||||
|
||||
void on_actionProject_2_toggled(bool arg1);
|
||||
|
||||
void on_actionEffect_Controls_toggled(bool arg1);
|
||||
|
||||
void on_actionViewer_toggled(bool arg1);
|
||||
|
||||
void on_actionTimeline_toggled(bool arg1);
|
||||
|
||||
void on_actionRipple_Delete_triggered();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
void setup_layout();
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
@@ -0,0 +1,296 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>653</width>
|
||||
<height>394</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="icons/icons.qrc">
|
||||
<normaloff>:/icons/full-icon.png</normaloff>:/icons/full-icon.png</iconset>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget"/>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>653</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
<property name="title">
|
||||
<string>&File</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_New">
|
||||
<property name="title">
|
||||
<string>&New</string>
|
||||
</property>
|
||||
<addaction name="actionProject"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionSequence"/>
|
||||
</widget>
|
||||
<addaction name="menu_New"/>
|
||||
<addaction name="action_Open_Project"/>
|
||||
<addaction name="action_Save_Project"/>
|
||||
<addaction name="actionSave_Project_As"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_Import"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionExport"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionExit"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuEdit">
|
||||
<property name="title">
|
||||
<string>&Edit</string>
|
||||
</property>
|
||||
<addaction name="action_Undo"/>
|
||||
<addaction name="action_Redo"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionCu_t"/>
|
||||
<addaction name="actionCop_y"/>
|
||||
<addaction name="action_Paste"/>
|
||||
<addaction name="actionDelete"/>
|
||||
<addaction name="actionRipple_Delete"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionSelect_All"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuWindow">
|
||||
<property name="title">
|
||||
<string>&Window</string>
|
||||
</property>
|
||||
<addaction name="actionProject_2"/>
|
||||
<addaction name="actionEffect_Controls"/>
|
||||
<addaction name="actionViewer"/>
|
||||
<addaction name="actionTimeline"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Help">
|
||||
<property name="title">
|
||||
<string>&Help</string>
|
||||
</property>
|
||||
<addaction name="actionAbout"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_View">
|
||||
<property name="title">
|
||||
<string>&View</string>
|
||||
</property>
|
||||
<addaction name="actionTimeline_Track_Lines"/>
|
||||
<addaction name="actionZoom_In"/>
|
||||
<addaction name="actionZoom_out"/>
|
||||
</widget>
|
||||
<addaction name="menu_File"/>
|
||||
<addaction name="menuEdit"/>
|
||||
<addaction name="menu_View"/>
|
||||
<addaction name="menuWindow"/>
|
||||
<addaction name="menu_Help"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar"/>
|
||||
<action name="action_Open_Project">
|
||||
<property name="text">
|
||||
<string>&Open Project</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+O</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Save_Project">
|
||||
<property name="text">
|
||||
<string>&Save Project</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+S</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave_Project_As">
|
||||
<property name="text">
|
||||
<string>Save Project &As</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Import">
|
||||
<property name="text">
|
||||
<string>&Import...</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+I</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExport">
|
||||
<property name="text">
|
||||
<string>&Export...</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+M</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExit">
|
||||
<property name="text">
|
||||
<string>E&xit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAbout">
|
||||
<property name="text">
|
||||
<string>About...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Undo">
|
||||
<property name="text">
|
||||
<string>&Undo</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Z</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Redo">
|
||||
<property name="text">
|
||||
<string>&Redo</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Y</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCu_t">
|
||||
<property name="text">
|
||||
<string>Cu&t</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+X</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCop_y">
|
||||
<property name="text">
|
||||
<string>Cop&y</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+C</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Paste">
|
||||
<property name="text">
|
||||
<string>&Paste</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+V</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDelete">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Del</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSelect_All">
|
||||
<property name="text">
|
||||
<string>Select &All</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+A</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTimeline_Track_Lines">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Track Lines</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionProject">
|
||||
<property name="text">
|
||||
<string>Project...</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+N</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSequence">
|
||||
<property name="text">
|
||||
<string>Sequence...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionZoom_In">
|
||||
<property name="text">
|
||||
<string>Zoom In</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>=</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionZoom_out">
|
||||
<property name="text">
|
||||
<string>Zoom Out</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionProject_2">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Project</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEffect_Controls">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Effect Controls</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionViewer">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Viewer</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTimeline">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Timeline</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRipple_Delete">
|
||||
<property name="text">
|
||||
<string>Ripple Delete</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Shift+Del</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
<include location="icons/icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,105 @@
|
||||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2018-05-11T10:31:59
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui multimedia opengl
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
TARGET = olive-qt
|
||||
TEMPLATE = app
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which has been marked as deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
# You can also make your code fail to compile if you use deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
mainwindow.cpp \
|
||||
panels/project.cpp \
|
||||
panels/effectcontrols.cpp \
|
||||
panels/viewer.cpp \
|
||||
panels/timeline.cpp \
|
||||
ui/sourcetable.cpp \
|
||||
dialogs/aboutdialog.cpp \
|
||||
ui/timelinewidget.cpp \
|
||||
io/media.cpp \
|
||||
project/sequence.cpp \
|
||||
project/clip.cpp \
|
||||
playback/playback.cpp \
|
||||
playback/audio.cpp \
|
||||
io/config.cpp \
|
||||
dialogs/newsequencedialog.cpp \
|
||||
ui/viewerwidget.cpp \
|
||||
ui/viewercontainer.cpp \
|
||||
dialogs/exportdialog.cpp \
|
||||
ui/collapsiblewidget.cpp \
|
||||
effects/transformeffect.cpp \
|
||||
panels/panels.cpp \
|
||||
effects/volumeeffect.cpp \
|
||||
effects/paneffect.cpp \
|
||||
project/effect.cpp \
|
||||
effects/effects.cpp \
|
||||
playback/cacher.cpp \
|
||||
io/exportthread.cpp
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h \
|
||||
panels/project.h \
|
||||
panels/effectcontrols.h \
|
||||
panels/viewer.h \
|
||||
panels/timeline.h \
|
||||
ui/sourcetable.h \
|
||||
dialogs/aboutdialog.h \
|
||||
ui/timelinewidget.h \
|
||||
io/media.h \
|
||||
project/sequence.h \
|
||||
project/clip.h \
|
||||
playback/playback.h \
|
||||
playback/audio.h \
|
||||
effects/effects.h \
|
||||
io/config.h \
|
||||
ui/timeline-tools.h \
|
||||
dialogs/newsequencedialog.h \
|
||||
ui/viewerwidget.h \
|
||||
ui/viewercontainer.h \
|
||||
dialogs/exportdialog.h \
|
||||
ui/collapsiblewidget.h \
|
||||
project/effect.h \
|
||||
panels/panels.h \
|
||||
playback/cacher.h \
|
||||
io/exportthread.h
|
||||
|
||||
FORMS += \
|
||||
mainwindow.ui \
|
||||
panels/project.ui \
|
||||
panels/effectcontrols.ui \
|
||||
panels/viewer.ui \
|
||||
panels/timeline.ui \
|
||||
dialogs/aboutdialog.ui \
|
||||
dialogs/newsequencedialog.ui \
|
||||
dialogs/exportdialog.ui
|
||||
|
||||
win32 {
|
||||
LIBS += -L../ffmpeg/lib -lavutil -lavformat -lavcodec -lswscale -lswresample opengl32.lib
|
||||
INCLUDEPATH = ../ffmpeg/include
|
||||
RC_FILE = icons/win.rc
|
||||
}
|
||||
|
||||
linux {
|
||||
LIBS += -lavutil -lavformat -lavcodec -lswscale -lswresample
|
||||
}
|
||||
|
||||
RESOURCES += \
|
||||
icons/icons.qrc \
|
||||
styles/styles.qrc
|
||||
@@ -0,0 +1,375 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.6.1, 2018-05-30T03:21:31. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{89fae42a-e0bc-4377-8782-ec7014933bdd}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuelist type="QVariantList" key="ClangStaticAnalyzer.SuppressedDiagnostics"/>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.10.1 MSVC2017 64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.10.1 MSVC2017 64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.5101.win64_msvc2017_64_kit</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:/olive/build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Debug</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:/build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Release</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:/build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Profile</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">true</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy Configuration</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
|
||||
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
|
||||
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Arguments"></value>
|
||||
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable">E:/olive/build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Debug/debug/olive-qt.exe</value>
|
||||
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory">E:/olive/build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Debug/debug/</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Run E:\olive\build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Debug\debug\olive-qt.exe</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">VC run</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
|
||||
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
|
||||
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
|
||||
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">olive</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:E:/olive/olive/olive.pro</value>
|
||||
<value type="bool" key="QmakeProjectManager.QmakeRunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">olive.pro</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory.default">E:/olive/build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Debug</value>
|
||||
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">2</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
@@ -0,0 +1,315 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.6.1, 2018-05-26T16:50:57. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{3af06612-75ce-48d7-b444-7dc372f1566d}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap"/>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.10.1 MSVC2017 64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.10.1 MSVC2017 64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.5101.win64_msvc2017_64_kit</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:/Users/Matt/Documents/temp</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">//neptune/build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Release</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">//neptune/build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Profile</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">true</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy Configuration</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
|
||||
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
|
||||
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Arguments"></value>
|
||||
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable"></value>
|
||||
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
@@ -0,0 +1,375 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.6.1, 2018-05-26T15:37:44. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{89fae42a-e0bc-4377-8782-ec7014933bdd}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuelist type="QVariantList" key="ClangStaticAnalyzer.SuppressedDiagnostics"/>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.10.1 MSVC2017 64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.10.1 MSVC2017 64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.5101.win64_msvc2017_64_kit</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:/olive/build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Debug</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:/build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Release</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:/build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Profile</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">true</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy Configuration</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
|
||||
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
|
||||
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Arguments"></value>
|
||||
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable">E:/olive/build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Debug/debug/olive-qt.exe</value>
|
||||
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory">E:/olive/build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Debug/debug/</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Run E:\olive\build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Debug\debug\olive-qt.exe</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">VC run</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
|
||||
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
|
||||
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
|
||||
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">olive-qt</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">olive-qt2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:E:/olive/olive-qt/olive-qt.pro</value>
|
||||
<value type="bool" key="QmakeProjectManager.QmakeRunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">olive-qt.pro</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory.default">E:/olive/build-olive-qt-Desktop_Qt_5_10_1_MSVC2017_64bit-Debug</value>
|
||||
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">2</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "effectcontrols.h"
|
||||
#include "ui_effectcontrols.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QDebug>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "effects/effects.h"
|
||||
#include "project/clip.h"
|
||||
#include "project/effect.h"
|
||||
#include "ui/collapsiblewidget.h"
|
||||
|
||||
|
||||
EffectControls::EffectControls(QWidget *parent) :
|
||||
QDockWidget(parent),
|
||||
ui(new Ui::EffectControls)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
init_effects();
|
||||
|
||||
clip = NULL;
|
||||
set_clip(NULL);
|
||||
}
|
||||
|
||||
EffectControls::~EffectControls()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void EffectControls::on_pushButton_clicked()
|
||||
{
|
||||
QMenu effects_menu(this);
|
||||
for (int i=0;i<video_effect_names.size();i++) {
|
||||
effects_menu.addAction(video_effect_names.at(i));
|
||||
}
|
||||
effects_menu.addSeparator();
|
||||
for (int i=0;i<audio_effect_names.size();i++) {
|
||||
effects_menu.addAction(audio_effect_names.at(i));
|
||||
}
|
||||
effects_menu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void EffectControls::set_clip(Clip* c) {
|
||||
// clear ui->scrollAreaWidgetContents
|
||||
if (clip != NULL) {
|
||||
for (int i=0;i<clip->effects.size();i++) {
|
||||
clip->effects.at(i)->container->setParent(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
ui->pushButton->setEnabled(c != NULL);
|
||||
if (c != NULL) {
|
||||
for (int i=0;i<c->effects.size();i++) {
|
||||
static_cast<QVBoxLayout*>(ui->scrollAreaWidgetContents->layout())->insertWidget(i, c->effects.at(i)->container);
|
||||
}
|
||||
}
|
||||
clip = c;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef EFFECTCONTROLS_H
|
||||
#define EFFECTCONTROLS_H
|
||||
|
||||
#include <QDockWidget>
|
||||
|
||||
struct Clip;
|
||||
|
||||
namespace Ui {
|
||||
class EffectControls;
|
||||
}
|
||||
|
||||
class EffectControls : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EffectControls(QWidget *parent = 0);
|
||||
~EffectControls();
|
||||
void set_clip(Clip* c);
|
||||
|
||||
private slots:
|
||||
void on_pushButton_clicked();
|
||||
|
||||
private:
|
||||
Ui::EffectControls *ui;
|
||||
Clip* clip;
|
||||
};
|
||||
|
||||
#endif // EFFECTCONTROLS_H
|
||||
@@ -0,0 +1,98 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EffectControls</class>
|
||||
<widget class="QDockWidget" name="EffectControls">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="features">
|
||||
<set>QDockWidget::AllDockWidgetFeatures</set>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Effect Controls</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>398</width>
|
||||
<height>253</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>[+] Add Effect</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "panels.h"
|
||||
|
||||
Project* panel_project;
|
||||
EffectControls* panel_effect_controls;
|
||||
Viewer* panel_viewer;
|
||||
Timeline* panel_timeline;
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef PANELS_H
|
||||
#define PANELS_H
|
||||
|
||||
class Project;
|
||||
class EffectControls;
|
||||
class Viewer;
|
||||
class Timeline;
|
||||
|
||||
extern Project* panel_project;
|
||||
extern EffectControls* panel_effect_controls;
|
||||
extern Viewer* panel_viewer;
|
||||
extern Timeline* panel_timeline;
|
||||
|
||||
#endif // PANELS_H
|
||||
@@ -0,0 +1,164 @@
|
||||
#include "project.h"
|
||||
#include "ui_project.h"
|
||||
#include "io/media.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
#include <QDebug>
|
||||
#include <QCharRef>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "panels/timeline.h"
|
||||
#include "project/sequence.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
Project::Project(QWidget *parent) :
|
||||
QDockWidget(parent),
|
||||
ui(new Ui::Project)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
Project::~Project()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QString Project::get_next_sequence_name() {
|
||||
int n = 1;
|
||||
bool found = true;
|
||||
QString name;
|
||||
while (found) {
|
||||
found = false;
|
||||
name = "Sequence ";
|
||||
if (n < 10) {
|
||||
name += "0";
|
||||
}
|
||||
name += QString::number(n);
|
||||
for (int i=0;i<ui->treeWidget->topLevelItemCount();i++) {
|
||||
if (QString::compare(ui->treeWidget->topLevelItem(i)->text(0), name, Qt::CaseInsensitive) == 0) {
|
||||
found = true;
|
||||
n++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
void Project::new_sequence(Sequence *s) {
|
||||
Media* m = new Media();
|
||||
m->is_sequence = true;
|
||||
m->sequence = s;
|
||||
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
item->setText(0, s->name);
|
||||
item->setData(0, Qt::UserRole + 1, QVariant::fromValue(reinterpret_cast<quintptr>(m)));
|
||||
|
||||
ui->treeWidget->addTopLevelItem(item);
|
||||
source_table = ui->treeWidget;
|
||||
}
|
||||
|
||||
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;
|
||||
if (file[lastcharindex].isDigit()) {
|
||||
bool is_img_sequence = false;
|
||||
QString sequence_test(file);
|
||||
char lastchar = sequence_test.at(lastcharindex).toLatin1();
|
||||
|
||||
sequence_test[lastcharindex] = lastchar + 1;
|
||||
if (QFileInfo::exists(sequence_test)) is_img_sequence = true;
|
||||
|
||||
sequence_test[lastcharindex] = lastchar - 1;
|
||||
if (QFileInfo::exists(sequence_test)) is_img_sequence = true;
|
||||
|
||||
if (is_img_sequence &&
|
||||
QMessageBox::question(this, "Image sequence detected", "The file '" + file + "' appears to be part of an image sequence. Would you like to import it as such?", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) {
|
||||
// change url to an image sequence instead
|
||||
int digit_count = 0;
|
||||
QString ext = file.mid(lastcharindex+1);
|
||||
while (file[lastcharindex].isDigit()) {
|
||||
digit_count++;
|
||||
lastcharindex--;
|
||||
}
|
||||
QString new_filename = file.left(lastcharindex+1) + "%";
|
||||
if (digit_count < 10) {
|
||||
new_filename += "0";
|
||||
}
|
||||
new_filename += QString::number(digit_count) + "d" + ext;
|
||||
file = new_filename;
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
item->setData(0, Qt::UserRole + 1, QVariant::fromValue(reinterpret_cast<quintptr>(m)));
|
||||
|
||||
ui->treeWidget->addTopLevelItem(item);
|
||||
}
|
||||
}
|
||||
avformat_close_input(&pFormatCtx);
|
||||
delete [] filename;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef PROJECT_H
|
||||
#define PROJECT_H
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QVector>
|
||||
|
||||
struct Media;
|
||||
struct Sequence;
|
||||
class Timeline;
|
||||
class Viewer;
|
||||
class SourceTable;
|
||||
|
||||
namespace Ui {
|
||||
class Project;
|
||||
}
|
||||
|
||||
class Project : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Project(QWidget *parent = 0);
|
||||
~Project();
|
||||
void import_dialog();
|
||||
void new_sequence(Sequence* s);
|
||||
QString get_next_sequence_name();
|
||||
|
||||
SourceTable* source_table;
|
||||
|
||||
private:
|
||||
Ui::Project *ui;
|
||||
};
|
||||
|
||||
#endif // PROJECT_H
|
||||
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Project</class>
|
||||
<widget class="QDockWidget" name="Project">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>504</width>
|
||||
<height>371</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Project</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="SourceTable" name="treeWidget">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::CurrentChanged|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragOnly</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="headerHidden">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="expandsOnDoubleClick">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>200</number>
|
||||
</attribute>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Duration</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SourceTable</class>
|
||||
<extends>QTreeWidget</extends>
|
||||
<header>ui/sourcetable.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,320 @@
|
||||
#include "timeline.h"
|
||||
#include "ui_timeline.h"
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "panels/effectcontrols.h"
|
||||
#include "ui/timelinewidget.h"
|
||||
#include "project/sequence.h"
|
||||
#include "project/clip.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
#include "playback/audio.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "playback/cacher.h"
|
||||
#include "playback/playback.h"
|
||||
|
||||
#include <QTime>
|
||||
|
||||
Timeline::Timeline(QWidget *parent) :
|
||||
QDockWidget(parent),
|
||||
ui(new Ui::Timeline)
|
||||
{
|
||||
selecting = moving_init = moving_proc = splitting = importing = playing = trim_in = false;
|
||||
last_frame = playhead = 0;
|
||||
trim_target = -1;
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->video_area->bottom_align = true;
|
||||
|
||||
tool_buttons.append(ui->toolArrowButton);
|
||||
tool_buttons.append(ui->toolEditButton);
|
||||
tool_buttons.append(ui->toolRippleButton);
|
||||
tool_buttons.append(ui->toolRazorButton);
|
||||
tool_buttons.append(ui->toolSlipButton);
|
||||
tool_buttons.append(ui->toolRollingButton);
|
||||
|
||||
ui->toolArrowButton->click();
|
||||
|
||||
zoom = 1.0f;
|
||||
|
||||
sequence = NULL;
|
||||
set_sequence(NULL);
|
||||
|
||||
connect(&playback_updater, SIGNAL(timeout()), this, SLOT(repaint_timeline()));
|
||||
}
|
||||
|
||||
Timeline::~Timeline()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void Timeline::go_to_start() {
|
||||
seek(0);
|
||||
}
|
||||
|
||||
void Timeline::previous_frame() {
|
||||
seek(playhead-1);
|
||||
}
|
||||
|
||||
void Timeline::next_frame() {
|
||||
seek(playhead+1);
|
||||
}
|
||||
|
||||
void Timeline::seek(long p) {
|
||||
pause();
|
||||
|
||||
// reset all clip audio
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip& c = sequence->get_clip(i);
|
||||
c.reset_audio = true;
|
||||
c.frame_sample_index = 0;
|
||||
}
|
||||
clear_cache(true, true);
|
||||
switch_audio_cache = true;
|
||||
reading_audio_cache_A = false;
|
||||
|
||||
playhead = p;
|
||||
}
|
||||
|
||||
bool Timeline::toggle_play() {
|
||||
if (playing) {
|
||||
pause();
|
||||
} else {
|
||||
play();
|
||||
}
|
||||
return playing;
|
||||
}
|
||||
|
||||
void Timeline::play() {
|
||||
playhead_start = playhead;
|
||||
playback_timer.start();
|
||||
playback_updater.start();
|
||||
playing = true;
|
||||
|
||||
if (switch_audio_cache) {
|
||||
// add something to pre-cache audio
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::pause() {
|
||||
playing = false;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
for (int i=0;i<tool_buttons.count();i++) {
|
||||
tool_buttons[i]->setEnabled(!null_sequence);
|
||||
}
|
||||
ui->pushButton_4->setEnabled(!null_sequence);
|
||||
ui->pushButton_5->setEnabled(!null_sequence);
|
||||
ui->video_area->setEnabled(!null_sequence);
|
||||
ui->audio_area->setEnabled(!null_sequence);
|
||||
|
||||
if (null_sequence) {
|
||||
setWindowTitle("Timeline: <none>");
|
||||
} else {
|
||||
setWindowTitle("Timeline: " + sequence->name);
|
||||
redraw_all_clips();
|
||||
playback_updater.setInterval(floor(1000 / sequence->frame_rate));
|
||||
}
|
||||
}
|
||||
|
||||
bool Timeline::focused() {
|
||||
return (ui->video_area->hasFocus() || ui->audio_area->hasFocus());
|
||||
}
|
||||
|
||||
void Timeline::repaint_timeline() {
|
||||
if (playing) {
|
||||
playhead = playhead_start + (playback_timer.elapsed() * 0.001 * sequence->frame_rate);
|
||||
}
|
||||
ui->video_area->update();
|
||||
ui->audio_area->update();
|
||||
if (last_frame != playhead) {
|
||||
panel_viewer->viewer_widget->update();
|
||||
last_frame = playhead;
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::redraw_all_clips() {
|
||||
ui->video_area->redraw_clips();
|
||||
ui->audio_area->redraw_clips();
|
||||
}
|
||||
|
||||
void Timeline::select_all() {
|
||||
selections.clear();
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip& c = sequence->get_clip(i);
|
||||
selections.append({c.timeline_in, c.timeline_out, c.track});
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::delete_selection(bool ripple_delete) {
|
||||
if (selections.size() > 0) {
|
||||
panel_effect_controls->set_clip(NULL);
|
||||
|
||||
long ripple_point = selections.at(0).in;
|
||||
long ripple_length = selections.at(0).out - selections.at(0).in;
|
||||
|
||||
for (int i=0;i<selections.size();i++) {
|
||||
const Selection& s = selections.at(i);
|
||||
sequence->delete_area(s.in, s.out, s.track);
|
||||
if (ripple_delete) {
|
||||
if (ripple_point > s.in) ripple_point = s.in;
|
||||
if (ripple_length > s.out - s.in) ripple_length = s.out - s.in;
|
||||
}
|
||||
}
|
||||
selections.clear();
|
||||
|
||||
if (ripple_delete) {
|
||||
long validator;
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
// check every clip after and see if it'll collide
|
||||
// NOTE, we could probably re-use the validation code for the ripple tool here for optimization (since it's technically better code I think)
|
||||
Clip& c = sequence->get_clip(i);
|
||||
if (c.timeline_in >= ripple_point) {
|
||||
for (int j=0;j<sequence->clip_count();j++) {
|
||||
Clip& cc = sequence->get_clip(j);
|
||||
if (cc.timeline_in < ripple_point) {
|
||||
validator = c.timeline_in - ripple_length - cc.timeline_out;
|
||||
if (validator < 0) ripple_length += validator;
|
||||
|
||||
if (ripple_length <= 0) {
|
||||
// we've seen all we need to see here (can't ripple so stop looping)
|
||||
i = j = sequence->clip_count();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ripple_length > 0) ripple(ripple_point, -ripple_length);
|
||||
}
|
||||
|
||||
redraw_all_clips();
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::zoom_in() {
|
||||
zoom *= 2;
|
||||
redraw_all_clips();
|
||||
}
|
||||
|
||||
void Timeline::zoom_out() {
|
||||
zoom /= 2;
|
||||
redraw_all_clips();
|
||||
}
|
||||
|
||||
void Timeline::ripple(long ripple_point, long ripple_length) {
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip& c = sequence->get_clip(i);
|
||||
if (c.timeline_in >= ripple_point) {
|
||||
c.timeline_in += ripple_length;
|
||||
c.timeline_out += ripple_length;
|
||||
}
|
||||
}
|
||||
for (int i=0;i<selections.size();i++) {
|
||||
Selection& s = selections[i];
|
||||
if (s.in >= ripple_point) {
|
||||
s.in += ripple_length;
|
||||
s.out += ripple_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::decheck_tool_buttons(QObject* sender) {
|
||||
for (int i=0;i<tool_buttons.count();i++) {
|
||||
if (tool_buttons[i] != sender) {
|
||||
tool_buttons[i]->setChecked(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::on_toolEditButton_toggled(bool checked)
|
||||
{
|
||||
if (checked) {
|
||||
decheck_tool_buttons(sender());
|
||||
ui->timeline_area->setCursor(Qt::IBeamCursor);
|
||||
tool = TIMELINE_TOOL_EDIT;
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::on_toolArrowButton_toggled(bool checked)
|
||||
{
|
||||
if (checked) {
|
||||
decheck_tool_buttons(sender());
|
||||
ui->timeline_area->setCursor(Qt::ArrowCursor);
|
||||
tool = TIMELINE_TOOL_POINTER;
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::on_toolRazorButton_toggled(bool checked)
|
||||
{
|
||||
if (checked) {
|
||||
decheck_tool_buttons(sender());
|
||||
ui->timeline_area->setCursor(Qt::IBeamCursor);
|
||||
tool = TIMELINE_TOOL_RAZOR;
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::on_pushButton_4_clicked()
|
||||
{
|
||||
zoom_in();
|
||||
}
|
||||
|
||||
void Timeline::on_pushButton_5_clicked()
|
||||
{
|
||||
zoom_out();
|
||||
}
|
||||
|
||||
bool Timeline::is_clip_selected(int clip_index) {
|
||||
Clip& clip = sequence->get_clip(clip_index);
|
||||
for (int i=0;i<selections.size();i++) {
|
||||
const Selection& s = selections.at(i);
|
||||
if (clip.track == s.track && clip.timeline_in >= s.in && clip.timeline_out <= s.out) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Timeline::on_toolRippleButton_toggled(bool checked)
|
||||
{
|
||||
if (checked) {
|
||||
decheck_tool_buttons(sender());
|
||||
ui->timeline_area->setCursor(Qt::ArrowCursor);
|
||||
tool = TIMELINE_TOOL_RIPPLE;
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::on_toolRollingButton_toggled(bool checked)
|
||||
{
|
||||
if (checked) {
|
||||
decheck_tool_buttons(sender());
|
||||
ui->timeline_area->setCursor(Qt::ArrowCursor);
|
||||
tool = TIMELINE_TOOL_ROLLING;
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::on_toolSlipButton_toggled(bool checked)
|
||||
{
|
||||
if (checked) {
|
||||
decheck_tool_buttons(sender());
|
||||
ui->timeline_area->setCursor(Qt::ArrowCursor);
|
||||
tool = TIMELINE_TOOL_SLIP;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
#ifndef TIMELINE_H
|
||||
#define TIMELINE_H
|
||||
|
||||
#include "ui/timeline-tools.h"
|
||||
#include <QDockWidget>
|
||||
#include <QVector>
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
|
||||
class QPushButton;
|
||||
class SourceTable;
|
||||
class ViewerWidget;
|
||||
struct Sequence;
|
||||
struct Clip;
|
||||
struct Media;
|
||||
struct MediaStream;
|
||||
|
||||
struct Ghost {
|
||||
Clip* clip;
|
||||
long in;
|
||||
long out;
|
||||
int track;
|
||||
long clip_in;
|
||||
|
||||
long old_in;
|
||||
long old_out;
|
||||
int old_track;
|
||||
long old_clip_in;
|
||||
|
||||
// importing variables
|
||||
Media* media;
|
||||
MediaStream* media_stream;
|
||||
|
||||
// other variables
|
||||
long ghost_length;
|
||||
long media_length;
|
||||
};
|
||||
|
||||
struct Selection {
|
||||
long in;
|
||||
long out;
|
||||
int track;
|
||||
|
||||
long old_in;
|
||||
long old_out;
|
||||
int old_track;
|
||||
};
|
||||
|
||||
namespace Ui {
|
||||
class Timeline;
|
||||
}
|
||||
|
||||
class Timeline : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Timeline(QWidget *parent = 0);
|
||||
~Timeline();
|
||||
|
||||
bool focused();
|
||||
void zoom_in();
|
||||
void zoom_out();
|
||||
void set_sequence(Sequence* s);
|
||||
|
||||
Sequence* sequence;
|
||||
long playhead;
|
||||
|
||||
// playback functions
|
||||
void go_to_start();
|
||||
void previous_frame();
|
||||
void next_frame();
|
||||
void seek(long p);
|
||||
bool toggle_play();
|
||||
void play();
|
||||
void pause();
|
||||
void go_to_end();
|
||||
bool playing;
|
||||
long playhead_start;
|
||||
QTime playback_timer;
|
||||
QTimer playback_updater;
|
||||
|
||||
// shared information
|
||||
int tool;
|
||||
float zoom;
|
||||
long drag_frame_start;
|
||||
int drag_track_start;
|
||||
void redraw_all_clips();
|
||||
|
||||
// selecting functions
|
||||
bool selecting;
|
||||
QVector<Selection> selections;
|
||||
bool is_clip_selected(int clip_index);
|
||||
void delete_selection(bool ripple);
|
||||
void select_all();
|
||||
|
||||
// moving
|
||||
bool moving_init;
|
||||
bool moving_proc;
|
||||
QVector<Ghost> ghosts;
|
||||
|
||||
// trimming
|
||||
int trim_target;
|
||||
bool trim_in;
|
||||
|
||||
// splitting
|
||||
bool splitting;
|
||||
|
||||
// importing
|
||||
bool importing;
|
||||
|
||||
// ripple
|
||||
void ripple(long ripple_point, long ripple_length);
|
||||
|
||||
public slots:
|
||||
void repaint_timeline();
|
||||
|
||||
private slots:
|
||||
void on_toolEditButton_toggled(bool checked);
|
||||
|
||||
void on_toolArrowButton_toggled(bool checked);
|
||||
|
||||
void on_toolRazorButton_toggled(bool checked);
|
||||
|
||||
void on_pushButton_4_clicked();
|
||||
|
||||
void on_pushButton_5_clicked();
|
||||
|
||||
void on_toolRippleButton_toggled(bool checked);
|
||||
|
||||
void on_toolRollingButton_toggled(bool checked);
|
||||
|
||||
void on_toolSlipButton_toggled(bool checked);
|
||||
|
||||
private:
|
||||
Ui::Timeline *ui;
|
||||
QVector<QPushButton*> tool_buttons;
|
||||
void decheck_tool_buttons(QObject* sender);
|
||||
void set_tool(int tool);
|
||||
long last_frame;
|
||||
};
|
||||
|
||||
#endif // TIMELINE_H
|
||||
@@ -0,0 +1,355 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Timeline</class>
|
||||
<widget class="QDockWidget" name="Timeline">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>840</width>
|
||||
<height>535</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Timeline</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="toolArrowButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Pointer Tool (V)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons/icons.qrc">
|
||||
<normaloff>:/icons/arrow.png</normaloff>:/icons/arrow.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="toolEditButton">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Edit Tool (X)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons/icons.qrc">
|
||||
<normaloff>:/icons/beam.png</normaloff>:/icons/beam.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="toolRippleButton">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Ripple Tool (B)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons/icons.qrc">
|
||||
<normaloff>:/icons/ripple.png</normaloff>:/icons/ripple.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="toolRollingButton">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Rolling Tool (N)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons/icons.qrc">
|
||||
<normaloff>:/icons/rolling.png</normaloff>:/icons/rolling.png</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="toolRazorButton">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Razor Tool (C)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons/icons.qrc">
|
||||
<normaloff>:/icons/razor.png</normaloff>:/icons/razor.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="toolSlipButton">
|
||||
<property name="toolTip">
|
||||
<string>Slip Tool (Y)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normalon>:/icons/slip.png</normalon>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_4">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Zoom In (=)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>+</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_5">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Zoom Out (-)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="timeline_area">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>789</width>
|
||||
<height>494</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="TimelineWidget" name="video_area" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="TimelineWidget" name="audio_area" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>TimelineWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>ui/timelinewidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../icons/icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,79 @@
|
||||
#include "viewer.h"
|
||||
#include "ui_viewer.h"
|
||||
|
||||
#include "playback/audio.h"
|
||||
#include "timeline.h"
|
||||
#include "project/sequence.h"
|
||||
#include "panels/panels.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
Viewer::Viewer(QWidget *parent) :
|
||||
QDockWidget(parent),
|
||||
ui(new Ui::Viewer)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->glViewerPane->child = ui->openGLWidget;
|
||||
viewer_widget = ui->openGLWidget;
|
||||
set_sequence(NULL);
|
||||
}
|
||||
|
||||
Viewer::~Viewer()
|
||||
{
|
||||
init_audio(NULL);
|
||||
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void Viewer::set_sequence(Sequence* s) {
|
||||
bool null_sequence = (s == NULL);
|
||||
sequence = s;
|
||||
|
||||
ui->openGLWidget->setEnabled(!null_sequence);
|
||||
ui->openGLWidget->setVisible(!null_sequence);
|
||||
ui->pushButton->setEnabled(!null_sequence);
|
||||
ui->pushButton_2->setEnabled(!null_sequence);
|
||||
ui->pushButton_3->setEnabled(!null_sequence);
|
||||
ui->pushButton_4->setEnabled(!null_sequence);
|
||||
ui->pushButton_5->setEnabled(!null_sequence);
|
||||
|
||||
if (!null_sequence) {
|
||||
ui->glViewerPane->aspect_ratio = (float) sequence->width / (float) sequence->height;
|
||||
ui->glViewerPane->adjust();
|
||||
}
|
||||
|
||||
init_audio(s);
|
||||
update();
|
||||
}
|
||||
|
||||
void Viewer::on_pushButton_clicked()
|
||||
{
|
||||
panel_timeline->go_to_start();
|
||||
}
|
||||
|
||||
void Viewer::on_pushButton_5_clicked()
|
||||
{
|
||||
panel_timeline->go_to_end();
|
||||
}
|
||||
|
||||
void Viewer::on_pushButton_2_clicked()
|
||||
{
|
||||
panel_timeline->previous_frame();
|
||||
}
|
||||
|
||||
void Viewer::on_pushButton_4_clicked()
|
||||
{
|
||||
panel_timeline->next_frame();
|
||||
}
|
||||
|
||||
void Viewer::on_pushButton_3_clicked()
|
||||
{
|
||||
if (panel_timeline->toggle_play()) {
|
||||
// playing
|
||||
ui->pushButton_3->setIcon(QIcon(":/icons/pause.png"));
|
||||
} else {
|
||||
ui->pushButton_3->setIcon(QIcon(":/icons/play.png"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef VIEWER_H
|
||||
#define VIEWER_H
|
||||
|
||||
#include <QDockWidget>
|
||||
|
||||
class Timeline;
|
||||
class ViewerWidget;
|
||||
struct Sequence;
|
||||
|
||||
namespace Ui {
|
||||
class Viewer;
|
||||
}
|
||||
|
||||
class Viewer : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Viewer(QWidget *parent = 0);
|
||||
~Viewer();
|
||||
void set_sequence(Sequence* s);
|
||||
void compose();
|
||||
|
||||
Sequence* sequence;
|
||||
ViewerWidget* viewer_widget;
|
||||
|
||||
private slots:
|
||||
void on_pushButton_clicked();
|
||||
|
||||
void on_pushButton_5_clicked();
|
||||
|
||||
void on_pushButton_2_clicked();
|
||||
|
||||
void on_pushButton_4_clicked();
|
||||
|
||||
void on_pushButton_3_clicked();
|
||||
|
||||
private:
|
||||
Ui::Viewer *ui;
|
||||
};
|
||||
|
||||
#endif // VIEWER_H
|
||||
@@ -0,0 +1,319 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Viewer</class>
|
||||
<widget class="QDockWidget" name="Viewer">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>583</width>
|
||||
<height>396</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Viewer</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="ViewerContainer" name="glViewerPane" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<widget class="ViewerWidget" name="openGLWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>130</x>
|
||||
<y>60</y>
|
||||
<width>301</width>
|
||||
<height>221</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="playbackControls" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>36</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons/icons.qrc">
|
||||
<normaloff>:/icons/prev.png</normaloff>:/icons/prev.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>14</width>
|
||||
<height>14</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>36</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons/icons.qrc">
|
||||
<normaloff>:/icons/rew.png</normaloff>:/icons/rew.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>14</width>
|
||||
<height>14</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>36</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normalon>:/icons/play.png</normalon>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>14</width>
|
||||
<height>14</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>36</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normalon>:/icons/ff.png</normalon>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>14</width>
|
||||
<height>14</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_5">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>36</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons/icons.qrc">
|
||||
<normaloff>:/icons/next.png</normaloff>:/icons/next.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>14</width>
|
||||
<height>14</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ViewerWidget</class>
|
||||
<extends>QOpenGLWidget</extends>
|
||||
<header>ui/viewerwidget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ViewerContainer</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>ui/viewercontainer.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../icons/icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "audio.h"
|
||||
|
||||
#include "project/sequence.h"
|
||||
|
||||
#include <QAudioOutput>
|
||||
#include <QDebug>
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
QAudioOutput* audio_output;
|
||||
QIODevice* audio_io_device;
|
||||
bool audio_device_set = false;
|
||||
|
||||
uint8_t* audio_cache_A = NULL;
|
||||
uint8_t* audio_cache_B = NULL;
|
||||
int audio_cache_size = 0;
|
||||
bool switch_audio_cache = true;
|
||||
bool reading_audio_cache_A = false;
|
||||
|
||||
void init_audio(Sequence* s) {
|
||||
if (audio_cache_A != NULL) {
|
||||
delete [] audio_cache_A;
|
||||
audio_cache_A = NULL;
|
||||
}
|
||||
|
||||
if (audio_cache_B != NULL) {
|
||||
delete [] audio_cache_B;
|
||||
audio_cache_B = NULL;
|
||||
}
|
||||
|
||||
if (audio_device_set) {
|
||||
audio_output->stop();
|
||||
delete audio_output;
|
||||
audio_device_set = false;
|
||||
}
|
||||
|
||||
if (s != NULL) {
|
||||
QAudioFormat audio_format;
|
||||
audio_format.setSampleRate(s->audio_frequency);
|
||||
audio_format.setChannelCount(av_get_channel_layout_nb_channels(s->audio_layout));
|
||||
audio_format.setSampleSize(16);
|
||||
audio_format.setCodec("audio/pcm");
|
||||
audio_format.setByteOrder(QAudioFormat::LittleEndian);
|
||||
audio_format.setSampleType(QAudioFormat::SignedInt);
|
||||
|
||||
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
|
||||
if (!info.isFormatSupported(audio_format)) {
|
||||
qWarning() << "[WARNING] Couldn't initialize audio. Audio format is not supported by backend";
|
||||
} else {
|
||||
audio_output = new QAudioOutput(audio_format);
|
||||
// connect
|
||||
audio_io_device = audio_output->start();
|
||||
audio_device_set = true;
|
||||
|
||||
audio_cache_size = av_samples_get_buffer_size(NULL, av_get_channel_layout_nb_channels(s->audio_layout), s->audio_frequency/8, AV_SAMPLE_FMT_S16, 1);
|
||||
audio_cache_A = new uint8_t[audio_cache_size];
|
||||
audio_cache_B = new uint8_t[audio_cache_size];
|
||||
clear_cache(true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clear_cache(bool clear_A, bool clear_B) {
|
||||
if (clear_A) {
|
||||
memset(audio_cache_A, 0, audio_cache_size);
|
||||
}
|
||||
if (clear_B) {
|
||||
memset(audio_cache_B, 0, audio_cache_size);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef AUDIO_H
|
||||
#define AUDIO_H
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QMutex>
|
||||
|
||||
struct Sequence;
|
||||
|
||||
extern QIODevice* audio_io_device;
|
||||
|
||||
extern uint8_t* audio_cache_A;
|
||||
extern uint8_t* audio_cache_B;
|
||||
extern int audio_cache_size;
|
||||
extern bool switch_audio_cache;
|
||||
extern bool reading_audio_cache_A;
|
||||
void init_audio(Sequence* s);
|
||||
void clear_cache(bool clear_A, bool clear_B);
|
||||
|
||||
#endif // AUDIO_H
|
||||
@@ -0,0 +1,339 @@
|
||||
#include "cacher.h"
|
||||
|
||||
#include "project/clip.h"
|
||||
#include "project/sequence.h"
|
||||
#include "io/media.h"
|
||||
#include "playback/audio.h"
|
||||
#include "playback/playback.h"
|
||||
#include "effects/effects.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libswscale/swscale.h>
|
||||
#include <libswresample/swresample.h>
|
||||
}
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
void cache_audio_worker(Clip* c, bool write_A) {
|
||||
// gets one frame worth of audio and sends it to the audio buffer
|
||||
AVFrame* frame = c->cache_A.frames[0];
|
||||
uint8_t* cache = (write_A) ? audio_cache_A : audio_cache_B;
|
||||
|
||||
int bytes_written = 0;
|
||||
int j = 0;
|
||||
while (bytes_written < audio_cache_size && !c->reached_end) {
|
||||
// is there audio left in the frame
|
||||
if (c->frame_sample_index == 0) {
|
||||
// no more audio left in frame, get a new one
|
||||
retrieve_next_frame_raw_data(c, frame);
|
||||
}
|
||||
if (!c->reached_end) {
|
||||
int nb_bytes = av_samples_get_buffer_size(NULL, frame->channels, frame->nb_samples, static_cast<AVSampleFormat>(frame->format), 1);
|
||||
int limit = std::min(c->frame_sample_index + audio_cache_size - bytes_written, nb_bytes);
|
||||
// perform all audio effects
|
||||
for (unsigned int j=0;j<c->effects.size();j++) {
|
||||
c->effects[j]->process_audio(frame->data[0], limit);
|
||||
}
|
||||
// mix audio into cache
|
||||
for (int i=c->frame_sample_index;i<limit;i++) {
|
||||
cache[j] += frame->data[0][i];
|
||||
j++;
|
||||
}
|
||||
bytes_written += limit - c->frame_sample_index;
|
||||
c->frame_sample_index = (limit == nb_bytes) ? 0 : limit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cache_video_worker(Clip* c, long playhead, ClipCache* cache) {
|
||||
cache->mutex.lock();
|
||||
|
||||
cache->offset = playhead;
|
||||
for (size_t i=0;i<c->cache_size;i++) {
|
||||
retrieve_next_frame_raw_data(c, cache->frames[i]);
|
||||
}
|
||||
cache->written = true;
|
||||
cache->unread = true;
|
||||
|
||||
cache->mutex.unlock();
|
||||
}
|
||||
|
||||
void reset_cache(Clip* c, long target_frame) {
|
||||
// if we seek to a whole other place in the timeline, we'll need to reset the cache with new values
|
||||
if (c->media_stream->infinite_length) {
|
||||
// if this clip is a still image, we only need one frame
|
||||
if (!c->cache_A.written) {
|
||||
retrieve_next_frame_raw_data(c, c->cache_A.frames[0]);
|
||||
c->cache_A.written = true;
|
||||
}
|
||||
} else {
|
||||
// flush ffmpeg codecs
|
||||
avcodec_flush_buffers(c->codecCtx);
|
||||
|
||||
double timebase = av_q2d(c->stream->time_base);
|
||||
|
||||
if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
// seeks to nearest keyframe (target_frame represents internal clip frame)
|
||||
av_seek_frame(c->formatCtx, c->media_stream->file_index, clip_frame_to_seconds(c, target_frame) / timebase, AVSEEK_FLAG_BACKWARD);
|
||||
|
||||
// play up to the frame we actually want
|
||||
long retrieved_frame = 0;
|
||||
AVFrame* temp = av_frame_alloc();
|
||||
do {
|
||||
retrieve_next_frame(c, temp);
|
||||
if (retrieved_frame == 0) {
|
||||
if (target_frame != 0) {
|
||||
// retrieved_frame = floor(av_frame_get_best_effort_timestamp(temp) * timebase * av_q2d(c->stream->avg_frame_rate));
|
||||
retrieved_frame = floor(temp->pts * timebase * av_q2d(av_guess_frame_rate(c->formatCtx, c->stream, temp)));
|
||||
}
|
||||
} else {
|
||||
retrieved_frame++;
|
||||
}
|
||||
} while (retrieved_frame < target_frame);
|
||||
av_frame_free(&temp);
|
||||
} else if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
// seek (target_frame represents timeline timecode in frames, not clip timecode)
|
||||
swr_drop_output(c->swr_ctx, swr_get_out_samples(c->swr_ctx, 0));
|
||||
av_seek_frame(c->formatCtx, c->media_stream->file_index, playhead_to_seconds(c, target_frame) / timebase, AVSEEK_FLAG_ANY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cacher::Cacher(Clip* c) : clip(c) {}
|
||||
|
||||
void open_clip_worker(Clip* clip) {
|
||||
// opens file resource for FFmpeg and prepares Clip struct for playback
|
||||
QByteArray ba = clip->media->url.toUtf8();
|
||||
const char* filename = ba.constData();
|
||||
|
||||
int errCode = avformat_open_input(
|
||||
&clip->formatCtx,
|
||||
filename,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
if (errCode != 0) {
|
||||
char err[1024];
|
||||
av_strerror(errCode, err, 1024);
|
||||
qDebug() << "[ERROR] Could not open" << filename << "-" << err;
|
||||
}
|
||||
|
||||
errCode = avformat_find_stream_info(clip->formatCtx, NULL);
|
||||
if (errCode < 0) {
|
||||
char err[1024];
|
||||
av_strerror(errCode, err, 1024);
|
||||
qDebug() << "[ERROR] Could not open" << filename << "-" << err;
|
||||
}
|
||||
|
||||
av_dump_format(clip->formatCtx, 0, filename, 0);
|
||||
|
||||
clip->stream = clip->formatCtx->streams[clip->media_stream->file_index];
|
||||
clip->codec = avcodec_find_decoder(clip->stream->codecpar->codec_id);
|
||||
clip->codecCtx = avcodec_alloc_context3(clip->codec);
|
||||
avcodec_parameters_to_context(clip->codecCtx, clip->stream->codecpar);
|
||||
|
||||
AVDictionary* opts = NULL;
|
||||
|
||||
// decoding optimization configuration
|
||||
if (clip->stream->codecpar->codec_id != AV_CODEC_ID_PNG &&
|
||||
clip->stream->codecpar->codec_id != AV_CODEC_ID_APNG &&
|
||||
clip->stream->codecpar->codec_id != AV_CODEC_ID_TIFF &&
|
||||
clip->stream->codecpar->codec_id != AV_CODEC_ID_PSD) {
|
||||
av_dict_set(&opts, "threads", "auto", 0);
|
||||
}
|
||||
if (clip->stream->codecpar->codec_id == AV_CODEC_ID_H264) {
|
||||
av_dict_set(&opts, "tune", "fastdecode", 0);
|
||||
av_dict_set(&opts, "tune", "zerolatency", 0);
|
||||
}
|
||||
|
||||
// Open codec
|
||||
if (avcodec_open2(clip->codecCtx, clip->codec, &opts) < 0) {
|
||||
qDebug() << "[ERROR] Could not open codec";
|
||||
}
|
||||
|
||||
if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
// set up swscale context - primarily used for colorspace conversion
|
||||
// as "scaling" is actually done by OpenGL
|
||||
int dest_format = AV_PIX_FMT_RGBA;
|
||||
|
||||
clip->sws_ctx = sws_getContext(
|
||||
clip->stream->codecpar->width,
|
||||
clip->stream->codecpar->height,
|
||||
static_cast<AVPixelFormat>(clip->stream->codecpar->format),
|
||||
ceil(clip->stream->codecpar->width/2)*2,
|
||||
ceil(clip->stream->codecpar->height/2)*2,
|
||||
static_cast<AVPixelFormat>(dest_format),
|
||||
SWS_FAST_BILINEAR,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
// create memory cache for video
|
||||
if (clip->media_stream->infinite_length) {
|
||||
clip->cache_size = 1;
|
||||
} else {
|
||||
clip->cache_size = ceil(av_q2d(av_guess_frame_rate(clip->formatCtx, clip->stream, NULL))/4); // cache is half a second in total
|
||||
|
||||
// infinite length doesn't need cache B
|
||||
clip->cache_B.frames = new AVFrame* [clip->cache_size];
|
||||
|
||||
}
|
||||
clip->cache_A.frames = new AVFrame* [clip->cache_size];
|
||||
|
||||
|
||||
for (size_t i=0;i<clip->cache_size;i++) {
|
||||
clip->cache_A.frames[i] = av_frame_alloc();
|
||||
av_frame_make_writable(clip->cache_A.frames[i]);
|
||||
clip->cache_A.frames[i]->width = clip->stream->codecpar->width;
|
||||
clip->cache_A.frames[i]->height = clip->stream->codecpar->height;
|
||||
clip->cache_A.frames[i]->format = dest_format;
|
||||
av_frame_get_buffer(clip->cache_A.frames[i], 0);
|
||||
clip->cache_A.frames[i]->linesize[0] = clip->stream->codecpar->width*4;
|
||||
|
||||
if (!clip->media_stream->infinite_length) {
|
||||
clip->cache_B.frames[i] = av_frame_alloc();
|
||||
av_frame_make_writable(clip->cache_B.frames[i]);
|
||||
clip->cache_B.frames[i]->width = clip->stream->codecpar->width;
|
||||
clip->cache_B.frames[i]->height = clip->stream->codecpar->height;
|
||||
clip->cache_B.frames[i]->format = dest_format;
|
||||
av_frame_get_buffer(clip->cache_B.frames[i], 0);
|
||||
clip->cache_B.frames[i]->linesize[0] = clip->stream->codecpar->width*4;
|
||||
}
|
||||
}
|
||||
} else if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
// if FFmpeg can't pick up the channel layout (usually WAV), assume
|
||||
// based on channel count (doesn't support surround sound sources yet)
|
||||
if (clip->codecCtx->channel_layout == 0) {
|
||||
switch (clip->stream->codecpar->channels) {
|
||||
case 1: clip->codecCtx->channel_layout = AV_CH_LAYOUT_MONO;
|
||||
default:
|
||||
clip->codecCtx->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
qDebug() << "[WARNING] Could not detect audio channel layout - assuming stereo";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int sample_format = AV_SAMPLE_FMT_S16;
|
||||
|
||||
// init resampling context
|
||||
clip->swr_ctx = swr_alloc_set_opts(
|
||||
NULL,
|
||||
clip->sequence->audio_layout,
|
||||
static_cast<AVSampleFormat>(sample_format),
|
||||
clip->sequence->audio_frequency,
|
||||
clip->stream->codecpar->channel_layout,
|
||||
static_cast<AVSampleFormat>(clip->stream->codecpar->format),
|
||||
clip->stream->codecpar->sample_rate,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
swr_init(clip->swr_ctx);
|
||||
|
||||
// set up cache
|
||||
clip->cache_A.frames = new AVFrame* [1];
|
||||
clip->cache_A.frames[0] = av_frame_alloc();
|
||||
clip->cache_A.frames[0]->format = sample_format;
|
||||
clip->cache_A.frames[0]->channel_layout = clip->sequence->audio_layout;
|
||||
clip->cache_A.frames[0]->channels = av_get_channel_layout_nb_channels(clip->cache_A.frames[0]->channel_layout);
|
||||
clip->cache_A.frames[0]->sample_rate = clip->sequence->audio_frequency;
|
||||
av_frame_make_writable(clip->cache_A.frames[0]);
|
||||
|
||||
clip->reset_audio = true;
|
||||
}
|
||||
|
||||
clip->frame = av_frame_alloc();
|
||||
|
||||
qDebug() << "[INFO] Clip opened on track" << clip->track;
|
||||
|
||||
clip->open = true;
|
||||
}
|
||||
|
||||
void cache_clip_worker(Clip* clip, long playhead, bool write_A, bool write_B, bool reset) {
|
||||
if (reset) {
|
||||
// note: for video, playhead is in "internal clip" frames - for audio, it's the timeline playhead
|
||||
reset_cache(clip, playhead);
|
||||
clip->reset_audio = false;
|
||||
}
|
||||
|
||||
if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
if (write_A) {
|
||||
cache_video_worker(clip, playhead, &clip->cache_A);
|
||||
playhead += clip->cache_size;
|
||||
}
|
||||
|
||||
if (write_B) {
|
||||
cache_video_worker(clip, playhead, &clip->cache_B);
|
||||
}
|
||||
} else if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
if (write_A) {
|
||||
cache_audio_worker(clip, true);
|
||||
}
|
||||
if (write_B) {
|
||||
cache_audio_worker(clip, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void close_clip_worker(Clip* clip) {
|
||||
// closes ffmpeg file handle and frees any memory used for caching
|
||||
if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
sws_freeContext(clip->sws_ctx);
|
||||
} else if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
swr_free(&clip->swr_ctx);
|
||||
}
|
||||
|
||||
avcodec_close(clip->codecCtx);
|
||||
avcodec_free_context(&clip->codecCtx);
|
||||
avformat_close_input(&clip->formatCtx);
|
||||
|
||||
for (size_t i=0;i<clip->cache_size;i++) {
|
||||
av_frame_free(&clip->cache_A.frames[i]);
|
||||
if (!clip->media_stream->infinite_length) av_frame_free(&clip->cache_B.frames[i]);
|
||||
}
|
||||
delete [] clip->cache_A.frames;
|
||||
if (!clip->media_stream->infinite_length) delete [] clip->cache_B.frames;
|
||||
|
||||
av_frame_free(&clip->frame);
|
||||
|
||||
clip->reset();
|
||||
|
||||
// remove clip from current_clips
|
||||
cc_lock.lock();
|
||||
bool found = false;
|
||||
for (int i=0;i<current_clips.count();i++) {
|
||||
if (current_clips[i] == clip) {
|
||||
current_clips.erase(current_clips.begin()+i);
|
||||
found = true;
|
||||
i = current_clips.count();
|
||||
}
|
||||
}
|
||||
cc_lock.unlock();
|
||||
if (!found) qDebug() << "[WARNING] Could not remove clip from current clips";
|
||||
|
||||
qDebug() << "[INFO] Clip closed on track" << clip->track;
|
||||
}
|
||||
|
||||
void Cacher::run() {
|
||||
// open_lock is used to prevent the clip from being destroyed before the cacher has closed it properly
|
||||
clip->open_lock.lock();
|
||||
|
||||
open_clip_worker(clip);
|
||||
|
||||
caching = true;
|
||||
while (true) {
|
||||
clip->can_cache.wait(&clip->lock);
|
||||
if (!caching) {
|
||||
break;
|
||||
} else {
|
||||
cache_clip_worker(clip, playhead, write_A, write_B, reset);
|
||||
}
|
||||
}
|
||||
|
||||
close_clip_worker(clip);
|
||||
clip->lock.unlock();
|
||||
|
||||
clip->open_lock.unlock();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef CACHER_H
|
||||
#define CACHER_H
|
||||
|
||||
#include <QThread>
|
||||
|
||||
struct Clip;
|
||||
|
||||
class Cacher : public QThread
|
||||
{
|
||||
// Q_OBJECT
|
||||
public:
|
||||
Cacher(Clip* c);
|
||||
void run() override;
|
||||
|
||||
bool caching;
|
||||
|
||||
// must be set before caching
|
||||
long playhead;
|
||||
bool write_A;
|
||||
bool write_B;
|
||||
bool reset;
|
||||
|
||||
private:
|
||||
Clip* clip;
|
||||
};
|
||||
|
||||
void open_clip_worker(Clip* clip);
|
||||
void cache_clip_worker(Clip* clip, long playhead, bool write_A, bool write_B, bool reset);
|
||||
void close_clip_worker(Clip* clip);
|
||||
|
||||
#endif // CACHER_H
|
||||
@@ -0,0 +1,288 @@
|
||||
#include "playback.h"
|
||||
|
||||
#include "project/clip.h"
|
||||
#include "project/sequence.h"
|
||||
#include "io/media.h"
|
||||
#include "playback/audio.h"
|
||||
#include "playback/cacher.h"
|
||||
#include "panels/timeline.h"
|
||||
#include <algorithm>
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libswscale/swscale.h>
|
||||
#include <libswresample/swresample.h>
|
||||
}
|
||||
|
||||
#include <QObject>
|
||||
#include <QOpenGLTexture>
|
||||
#include <QDebug>
|
||||
#include <QOpenGLPixelTransferOptions>
|
||||
|
||||
QList<Clip*> current_clips;
|
||||
bool texture_failed = false;
|
||||
|
||||
QMutex cc_lock;
|
||||
|
||||
void handle_media(Sequence* sequence, long playhead, bool multithreaded) {
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip& c = sequence->get_clip(i);
|
||||
|
||||
// if clip starts within one second and/or hasn't finished yet
|
||||
if (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
|
||||
if (!c.open) {
|
||||
if (c.lock.tryLock()) {
|
||||
open_clip(&c, multithreaded);
|
||||
|
||||
// add to current_clips, (insertion) sorted by track so composite them in order
|
||||
cc_lock.lock();
|
||||
bool found = false;
|
||||
for (int j=0;j<current_clips.size();j++) {
|
||||
if (current_clips[j]->track < c.track) {
|
||||
current_clips.insert(current_clips.begin()+j, &c);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
current_clips.push_back(&c);
|
||||
}
|
||||
cc_lock.unlock();
|
||||
}
|
||||
}
|
||||
} else if (c.open) {
|
||||
close_clip(&c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void open_clip(Clip* clip, bool multithreaded) {
|
||||
clip->multithreaded = multithreaded;
|
||||
if (multithreaded) {
|
||||
// maybe keep cacher instance in memory while clip exists for performance?
|
||||
clip->cacher = new Cacher(clip);
|
||||
QObject::connect(clip->cacher, SIGNAL(finished()), clip->cacher, SLOT(deleteLater()));
|
||||
|
||||
clip->cacher->start(QThread::LowPriority);
|
||||
} else {
|
||||
open_clip_worker(clip);
|
||||
clip->lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void close_clip(Clip* clip) {
|
||||
// destroy opengl texture in main thread
|
||||
if (clip->texture != NULL) {
|
||||
clip->texture->destroy();
|
||||
clip->texture = NULL;
|
||||
}
|
||||
|
||||
if (clip->multithreaded) {
|
||||
clip->cacher->caching = false;
|
||||
clip->can_cache.wakeAll();
|
||||
} else {
|
||||
close_clip_worker(clip);
|
||||
}
|
||||
}
|
||||
|
||||
void cache_clip(Clip* clip, long playhead, bool write_A, bool write_B, bool reset) {
|
||||
if (clip->multithreaded) {
|
||||
clip->cacher->playhead = playhead;
|
||||
clip->cacher->write_A = write_A;
|
||||
clip->cacher->write_B = write_B;
|
||||
clip->cacher->reset = reset;
|
||||
|
||||
clip->can_cache.wakeAll();
|
||||
} else {
|
||||
cache_clip_worker(clip, playhead, write_A, write_B, reset);
|
||||
}
|
||||
}
|
||||
|
||||
void get_clip_frame(Clip* c, long playhead) {
|
||||
if (c->open) {
|
||||
long clip_time = seconds_to_clip_frame(c, playhead_to_seconds(c, playhead));
|
||||
|
||||
// do we need to update the texture?
|
||||
if ((!c->media_stream->infinite_length && c->texture_frame != clip_time) ||
|
||||
(c->media_stream->infinite_length && c->texture_frame == -1)) {
|
||||
AVFrame* current_frame = NULL;
|
||||
|
||||
// get frame data
|
||||
if (c->media_stream->infinite_length) { // if clip is a still frame, we only need one
|
||||
if (c->cache_A.written) {
|
||||
// retrieve cached frame
|
||||
current_frame = c->cache_A.frames[0];
|
||||
} else if (c->multithreaded) {
|
||||
if (c->lock.tryLock()) {
|
||||
// grab image (multi-threaded)
|
||||
cache_clip(c, 0, false, false, true);
|
||||
c->lock.unlock();
|
||||
}
|
||||
} else {
|
||||
// grab image (single-threaded)
|
||||
reset_cache(c, playhead);
|
||||
}
|
||||
} else {
|
||||
// keeping a RAM cache improves performance, however it's detrimental when rendering
|
||||
// determine which cache contains the requested frame
|
||||
bool using_cache_A = false;
|
||||
bool using_cache_B = false;
|
||||
AVFrame** cache = NULL;
|
||||
long cache_offset = 0;
|
||||
bool cache_needs_reset = false;
|
||||
|
||||
if (c->cache_A.written && clip_time >= c->cache_A.offset && clip_time < c->cache_A.offset + c->cache_size) {
|
||||
if (c->cache_A.mutex.tryLock()) { // lock in case cacher is still writing to it
|
||||
using_cache_A = true;
|
||||
c->cache_A.unread = false;
|
||||
cache = c->cache_A.frames;
|
||||
cache_offset = c->cache_A.offset;
|
||||
c->cache_A.mutex.unlock();
|
||||
}
|
||||
} else if (c->cache_B.written && clip_time >= c->cache_B.offset && clip_time < c->cache_B.offset + c->cache_size) {
|
||||
if (c->cache_B.mutex.tryLock()) { // lock in case cacher is still writing to it
|
||||
using_cache_B = true;
|
||||
c->cache_B.unread = false;
|
||||
cache = c->cache_B.frames;
|
||||
cache_offset = c->cache_B.offset;
|
||||
c->cache_B.mutex.unlock();
|
||||
}
|
||||
} else {
|
||||
// this is technically bad, unless we just seeked
|
||||
c->cache_A.unread = c->cache_B.unread = false;
|
||||
cache_needs_reset = true;
|
||||
}
|
||||
|
||||
if (cache != NULL) {
|
||||
current_frame = cache[clip_time - cache_offset];
|
||||
}
|
||||
|
||||
// determine whether we should start filling the other cache
|
||||
if (!using_cache_A || !using_cache_B) {
|
||||
if (c->lock.tryLock()) {
|
||||
bool write_A = (!using_cache_A && !c->cache_A.unread);
|
||||
bool write_B = (!using_cache_B && !c->cache_B.unread);
|
||||
if (write_A || write_B) {
|
||||
long playhead;
|
||||
if (cache_needs_reset) {
|
||||
// if we have no cache and need to seek, start us at the current playhead...
|
||||
playhead = clip_time;
|
||||
} else {
|
||||
// ...otherwise start at the end of the current cache
|
||||
playhead = cache_offset + c->cache_size;
|
||||
}
|
||||
cache_clip(c, playhead, write_A, write_B, cache_needs_reset);
|
||||
}
|
||||
c->lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current_frame != NULL) {
|
||||
// set up opengl texture
|
||||
if (c->texture == NULL) {
|
||||
c->texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
|
||||
c->texture->setSize(c->media_stream->video_width, c->media_stream->video_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);
|
||||
}
|
||||
|
||||
c->texture->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, current_frame->data[0]);
|
||||
c->texture_frame = clip_time;
|
||||
} else {
|
||||
texture_failed = true;
|
||||
qDebug() << "[ERROR] Failed to retrieve frame from cache (R:" << clip_time << "| A:" << c->cache_A.offset << "-" << c->cache_A.offset+c->cache_size-1 << "| B:" << c->cache_B.offset << "-" << c->cache_B.offset+c->cache_size-1 << "| WA:" << c->cache_A.written << "| WB:" << c->cache_B.written << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float playhead_to_seconds(Clip* c, long playhead) {
|
||||
// returns time in seconds
|
||||
return (std::max((long) 0, playhead - c->timeline_in) + c->clip_in)/c->sequence->frame_rate;
|
||||
}
|
||||
|
||||
long seconds_to_clip_frame(Clip* c, float seconds) {
|
||||
// returns time as frame number (according to clip's frame rate)
|
||||
if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
return floor(seconds*av_q2d(av_guess_frame_rate(c->formatCtx, c->stream, c->frame)));
|
||||
} else {
|
||||
qDebug() << "[ERROR] seconds_to_clip_frame only works on video streams";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
float clip_frame_to_seconds(Clip* c, long clip_frame) {
|
||||
// returns frame number as seconds (decimal)
|
||||
if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
return (double) clip_frame / av_q2d(c->stream->avg_frame_rate);
|
||||
} else {
|
||||
qDebug() << "[ERROR] clip_frame_to_seconds only works on video streams";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int retrieve_next_frame(Clip* c, AVFrame* f) {
|
||||
int result = 0;
|
||||
int receive_ret;
|
||||
|
||||
// could be optimized if "linked stream" shares timeline_in and clip_in, only use one read_frame?
|
||||
// depends how much time av_read_frame needs, the decoding is probably far more consuming anyway
|
||||
|
||||
// do we need to retrieve a new packet for a new frame?
|
||||
while ((receive_ret = avcodec_receive_frame(c->codecCtx, f)) == AVERROR(EAGAIN)) {
|
||||
int read_ret = 0;
|
||||
do {
|
||||
if (c->pkt_written) {
|
||||
av_packet_unref(c->pkt);
|
||||
}
|
||||
read_ret = av_read_frame(c->formatCtx, c->pkt);
|
||||
c->pkt_written = true;
|
||||
} while (read_ret >= 0 && c->pkt->stream_index != c->media_stream->file_index);
|
||||
|
||||
if (read_ret >= 0) {
|
||||
int send_ret = avcodec_send_packet(c->codecCtx, c->pkt);
|
||||
if (send_ret < 0) {
|
||||
qDebug() << "[ERROR] Failed to send packet to decoder." << send_ret;
|
||||
result = send_ret;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (read_ret != AVERROR_EOF) qDebug() << "[ERROR] Could not read frame." << read_ret;
|
||||
return read_ret; // skips trying to find a frame at all
|
||||
}
|
||||
}
|
||||
if (receive_ret < 0) {
|
||||
qDebug() << "[ERROR] Failed to receive packet from decoder." << receive_ret;
|
||||
result = receive_ret;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void retrieve_next_frame_raw_data(Clip* c, AVFrame* output) {
|
||||
int ret = retrieve_next_frame(c, c->frame);
|
||||
if (ret >= 0) {
|
||||
if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
sws_scale(c->sws_ctx, c->frame->data, c->frame->linesize, 0, c->stream->codecpar->height, output->data, output->linesize);
|
||||
} else if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
ret = swr_convert_frame(c->swr_ctx, output, c->frame);
|
||||
if (ret < 0) {
|
||||
qDebug() << "[ERROR] Failed to resample audio." << ret;
|
||||
}
|
||||
}
|
||||
} else if (ret == AVERROR_EOF) {
|
||||
c->reached_end = true;
|
||||
} else {
|
||||
qDebug() << "[WARNING] Raw frame data could not be retrieved." << ret;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_clip_active(Clip* c, long playhead) {
|
||||
return c->timeline_in < playhead + ceil(c->sequence->frame_rate) && c->timeline_out > playhead;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#ifndef PLAYBACK_H
|
||||
#define PLAYBACK_H
|
||||
|
||||
#include <QVector>
|
||||
#include <QMutex>
|
||||
|
||||
struct Clip;
|
||||
struct ClipCache;
|
||||
struct Sequence;
|
||||
struct AVFrame;
|
||||
|
||||
extern QList<Clip*> current_clips;
|
||||
extern QMutex cc_lock;
|
||||
|
||||
extern bool texture_failed;
|
||||
|
||||
void open_clip(Clip* clip, bool multithreaded);
|
||||
void cache_clip(Clip* clip, long playhead, bool write_A, bool write_B, bool reset);
|
||||
void close_clip(Clip* clip);
|
||||
void cache_audio_worker(Clip* c, bool write_A);
|
||||
void cache_video_worker(Clip* c, long playhead, ClipCache* cache);
|
||||
void handle_media(Sequence* sequence, long playhead, bool multithreaded);
|
||||
void reset_cache(Clip* c, long target_frame);
|
||||
void get_clip_frame(Clip* c, long playhead);
|
||||
float playhead_to_seconds(Clip* c, long playhead);
|
||||
long seconds_to_clip_frame(Clip* c, float seconds);
|
||||
float clip_frame_to_seconds(Clip* c, long clip_frame);
|
||||
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);
|
||||
|
||||
struct ClipCacheData {
|
||||
Clip& clip;
|
||||
long playhead;
|
||||
bool write_A;
|
||||
bool write_B;
|
||||
bool reset;
|
||||
};
|
||||
|
||||
#endif // PLAYBACK_H
|
||||
@@ -0,0 +1,81 @@
|
||||
#include "clip.h"
|
||||
|
||||
#include "project/effect.h"
|
||||
#include "io/media.h"
|
||||
#include "playback/playback.h"
|
||||
#include "playback/cacher.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
}
|
||||
|
||||
Clip::Clip() {
|
||||
init();
|
||||
}
|
||||
|
||||
Clip::Clip(const Clip &c) {
|
||||
init();
|
||||
copy(c);
|
||||
}
|
||||
|
||||
Clip& Clip::operator= (const Clip& c) {
|
||||
init();
|
||||
copy(c);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Clip::copy(const Clip& c) {
|
||||
name = c.name;
|
||||
clip_in = c.clip_in;
|
||||
timeline_in = c.timeline_in;
|
||||
timeline_out = c.timeline_out;
|
||||
track = c.track;
|
||||
color_r = c.color_r;
|
||||
color_g = c.color_g;
|
||||
color_b = c.color_b;
|
||||
sequence = c.sequence;
|
||||
media = c.media;
|
||||
media_stream = c.media_stream;
|
||||
}
|
||||
|
||||
void Clip::init() {
|
||||
reset();
|
||||
clip_in = timeline_in = timeline_out = track = undeletable = 0;
|
||||
texture = NULL;
|
||||
pkt = new AVPacket();
|
||||
}
|
||||
|
||||
void Clip::reset() {
|
||||
cache_size = cache_A.offset = cache_B.offset = open = pkt_written = cache_A.written = cache_B.written = cache_A.unread = cache_B.unread = reached_end = reset_audio = frame_sample_index = 0;
|
||||
texture_frame = -1;
|
||||
formatCtx = NULL;
|
||||
stream = NULL;
|
||||
codec = NULL;
|
||||
codecCtx = NULL;
|
||||
texture = NULL;
|
||||
cache_A.frames = NULL;
|
||||
cache_B.frames = NULL;
|
||||
}
|
||||
|
||||
Clip::~Clip() {
|
||||
if (open) {
|
||||
close_clip(this);
|
||||
}
|
||||
|
||||
// make sure clip has closed before clip is destroyed
|
||||
open_lock.lock();
|
||||
open_lock.unlock();
|
||||
|
||||
for (int i=0;i<effects.size();i++) {
|
||||
delete effects.at(i);
|
||||
}
|
||||
av_packet_unref(pkt);
|
||||
delete pkt;
|
||||
}
|
||||
|
||||
// timeline functions
|
||||
long Clip::getLength() {
|
||||
return timeline_out - timeline_in;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
#ifndef CLIP_H
|
||||
#define CLIP_H
|
||||
|
||||
#include <QWaitCondition>
|
||||
#include <QMutex>
|
||||
#include <QVector>
|
||||
|
||||
class Cacher;
|
||||
class Effect;
|
||||
struct Sequence;
|
||||
struct Media;
|
||||
struct MediaStream;
|
||||
|
||||
struct AVFormatContext;
|
||||
struct AVStream;
|
||||
struct AVCodec;
|
||||
struct AVCodecContext;
|
||||
struct AVFrame;
|
||||
struct AVPacket;
|
||||
struct SwsContext;
|
||||
struct SwrContext;
|
||||
class QOpenGLTexture;
|
||||
|
||||
struct ClipCache {
|
||||
AVFrame** frames;
|
||||
long offset;
|
||||
bool written;
|
||||
bool unread;
|
||||
QMutex mutex;
|
||||
};
|
||||
|
||||
struct Clip
|
||||
{
|
||||
Clip();
|
||||
Clip(const Clip &c);
|
||||
Clip& operator= (const Clip&); // explicitly defaulted copy assignment
|
||||
~Clip();
|
||||
void copy(const Clip& c);
|
||||
void init();
|
||||
void reset();
|
||||
bool undeletable;
|
||||
|
||||
// timeline variables
|
||||
QString name;
|
||||
long clip_in;
|
||||
long timeline_in;
|
||||
long timeline_out;
|
||||
int track;
|
||||
uint8_t color_r;
|
||||
uint8_t color_g;
|
||||
uint8_t color_b;
|
||||
long getLength();
|
||||
|
||||
// inherited information (should be copied in copy())
|
||||
Media* media; // attached media
|
||||
MediaStream* media_stream;
|
||||
Sequence* sequence;
|
||||
|
||||
// other variables (should be "duplicated" in copy())
|
||||
QList<Effect*> effects;
|
||||
// QVector<Clip&> linkedClips;
|
||||
|
||||
// media handling
|
||||
AVFormatContext* formatCtx;
|
||||
AVStream* stream;
|
||||
AVCodec* codec;
|
||||
AVCodecContext* codecCtx;
|
||||
AVPacket* pkt;
|
||||
AVFrame* frame;
|
||||
bool pkt_written;
|
||||
bool reached_end;
|
||||
bool open;
|
||||
|
||||
// caching functions
|
||||
bool multithreaded;
|
||||
Cacher* cacher;
|
||||
QWaitCondition can_cache;
|
||||
uint16_t cache_size;
|
||||
ClipCache cache_A;
|
||||
ClipCache cache_B;
|
||||
QMutex lock;
|
||||
QMutex open_lock;
|
||||
|
||||
// video playback variables
|
||||
SwsContext* sws_ctx;
|
||||
QOpenGLTexture* texture;
|
||||
long texture_frame;
|
||||
|
||||
// audio playback variables
|
||||
SwrContext* swr_ctx;
|
||||
int frame_sample_index;
|
||||
bool reset_audio;
|
||||
};
|
||||
|
||||
#endif // CLIP_H
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "effect.h"
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
|
||||
Effect::Effect(Clip* c) : parent_clip(c)
|
||||
{
|
||||
name = "<unnamed effect>";
|
||||
type = EFFECT_TYPE_INVALID;
|
||||
}
|
||||
|
||||
void Effect::field_changed() {
|
||||
panel_viewer->viewer_widget->update();
|
||||
}
|
||||
|
||||
void Effect::process_gl(int* anchor_x, int* anchor_y) {}
|
||||
void Effect::process_audio(uint8_t* samples, int nb_bytes) {}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef EFFECT_H
|
||||
#define EFFECT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
class QWidget;
|
||||
class CollapsibleWidget;
|
||||
|
||||
struct Clip;
|
||||
|
||||
enum EffectTypes { EFFECT_TYPE_INVALID, EFFECT_TYPE_VIDEO, EFFECT_TYPE_AUDIO };
|
||||
|
||||
class Effect : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Effect(Clip* c);
|
||||
int type;
|
||||
QString name;
|
||||
CollapsibleWidget* container;
|
||||
QWidget* ui;
|
||||
Clip* parent_clip;
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
#endif // EFFECT_H
|
||||
@@ -0,0 +1,122 @@
|
||||
#include "sequence.h"
|
||||
|
||||
#include "project/clip.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
Sequence::Sequence() {
|
||||
}
|
||||
|
||||
Sequence::~Sequence() {
|
||||
}
|
||||
|
||||
Clip& Sequence::new_clip() {
|
||||
clips.append(Clip());
|
||||
return clips[clips.size() - 1];
|
||||
}
|
||||
|
||||
Clip& Sequence::insert_clip(const Clip& c) {
|
||||
clips.append(c);
|
||||
return clips[clips.size() - 1];
|
||||
}
|
||||
|
||||
int Sequence::clip_count() {
|
||||
return clips.count();
|
||||
}
|
||||
|
||||
Clip& Sequence::get_clip(int i) {
|
||||
return clips[i];
|
||||
}
|
||||
|
||||
void Sequence::delete_clip(int i) {
|
||||
// remove any potential link references to clip
|
||||
// for (size_t j=0;j<clip_count();j++) {
|
||||
// Clip* c = getClip(j);
|
||||
// for (size_t k=0;k<c->linkedClips.size();k++) {
|
||||
// if (c->linkedClips[k] == clips[i]) {
|
||||
// c->linkedClips.erase(c->linkedClips.begin()+k);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// finally remove from vector
|
||||
clips.removeAt(i);
|
||||
}
|
||||
|
||||
long Sequence::getEndFrame() {
|
||||
long end = 0;
|
||||
for (int j=0;j<clip_count();j++) {
|
||||
Clip& c = get_clip(j);
|
||||
if (c.timeline_out > end) {
|
||||
end = c.timeline_out;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
void Sequence::get_track_limits(int* video_tracks, int* audio_tracks) {
|
||||
int vt = 0;
|
||||
int at = 0;
|
||||
for (int j=0;j<clip_count();j++) {
|
||||
Clip& c = get_clip(j);
|
||||
if (c.track < 0 && c.track < vt) { // video clip
|
||||
vt = c.track;
|
||||
} else if (c.track > at) {
|
||||
at = c.track;
|
||||
}
|
||||
}
|
||||
if (video_tracks != NULL) *video_tracks = vt;
|
||||
if (audio_tracks != NULL) *audio_tracks = at;
|
||||
}
|
||||
|
||||
void Sequence::delete_area(long in, long out, int track) {
|
||||
for (int i=0;i<clip_count();i++) {
|
||||
Clip& c = get_clip(i);
|
||||
if (c.track == track && !c.undeletable) {
|
||||
if (c.timeline_in >= in && c.timeline_out <= out) {
|
||||
// clips falls entirely within deletion area
|
||||
delete_clip(i);
|
||||
i--;
|
||||
} else if (c.timeline_in < in && c.timeline_out > out) {
|
||||
// middle of clip is within deletion area
|
||||
clips.append(clips.at(i)); // copy clip
|
||||
|
||||
Clip& pre = get_clip(i);
|
||||
Clip& post = get_clip(clips.size()-1);
|
||||
|
||||
pre.timeline_out = in;
|
||||
post.timeline_in = out;
|
||||
post.clip_in = pre.clip_in + pre.getLength() + (out - in);
|
||||
} else if (c.timeline_in < in && c.timeline_out > in) {
|
||||
// only out point is in deletion area
|
||||
c.timeline_out = in;
|
||||
} else if (c.timeline_in < out && c.timeline_out > out) {
|
||||
// only in point is in deletion area
|
||||
c.clip_in += out - c.timeline_in;
|
||||
c.timeline_in = out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::split_clip(int i, long frame) {
|
||||
Clip& pre = get_clip(i);
|
||||
if (pre.timeline_in < frame && pre.timeline_out > frame) { // guard against attempts to split at in/out points
|
||||
clips.append(pre); // copy clip
|
||||
|
||||
Clip& post = get_clip(clips.size()-1);
|
||||
|
||||
pre.timeline_out = frame;
|
||||
post.timeline_in = frame;
|
||||
post.clip_in = pre.clip_in + pre.getLength();
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::split_at_playhead(long frame) {
|
||||
for (int j=0;j<clip_count();j++) {
|
||||
Clip& c = get_clip(j);
|
||||
if (c.timeline_in < frame && c.timeline_out > frame) {
|
||||
split_clip(j, frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef SEQUENCE_H
|
||||
#define SEQUENCE_H
|
||||
|
||||
#include <QVector>
|
||||
|
||||
#include "project/clip.h"
|
||||
|
||||
struct Sequence {
|
||||
public:
|
||||
Sequence();
|
||||
~Sequence();
|
||||
QString name;
|
||||
Clip& new_clip();
|
||||
Clip& insert_clip(const Clip& c);
|
||||
int clip_count();
|
||||
Clip& get_clip(int i);
|
||||
void delete_clip(int i);
|
||||
void delete_area(long in, long out, int track);
|
||||
void split_clip(int i, long frame);
|
||||
void split_at_playhead(long frame);
|
||||
void get_track_limits(int* video_tracks, int* audio_tracks);
|
||||
long getEndFrame();
|
||||
int width;
|
||||
int height;
|
||||
float frame_rate;
|
||||
int audio_frequency;
|
||||
int audio_layout;
|
||||
private:
|
||||
QList<Clip> clips;
|
||||
};
|
||||
|
||||
#endif // SEQUENCE_H
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "collapsiblewidget.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QLabel>
|
||||
#include <QCheckBox>
|
||||
#include <QLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QPushButton>
|
||||
|
||||
CollapsibleWidget::CollapsibleWidget(QWidget* parent) : QWidget(parent)
|
||||
{
|
||||
layout = new QVBoxLayout(this);
|
||||
layout->setMargin(0);
|
||||
|
||||
title_bar = new QHBoxLayout();
|
||||
title_bar->setMargin(0);
|
||||
enabled_check = new QCheckBox();
|
||||
enabled_check->setChecked(true);
|
||||
header = new QLabel();
|
||||
collapse_button = new QPushButton("-");
|
||||
collapse_button->setMaximumWidth(25);
|
||||
setText("<untitled>");
|
||||
title_bar->addWidget(collapse_button);
|
||||
title_bar->addWidget(enabled_check);
|
||||
title_bar->addWidget(header);
|
||||
title_bar->addStretch();
|
||||
layout->addLayout(title_bar);
|
||||
|
||||
line = new QFrame();
|
||||
line->setFrameShape(QFrame::HLine);
|
||||
line->setFrameShadow(QFrame::Sunken);
|
||||
layout->addWidget(line);
|
||||
|
||||
contents = NULL;
|
||||
}
|
||||
|
||||
void CollapsibleWidget::setContents(QWidget* c) {
|
||||
bool existing = (contents != NULL);
|
||||
contents = c;
|
||||
if (!existing) {
|
||||
layout->addWidget(contents);
|
||||
connect(enabled_check, SIGNAL(toggled(bool)), this, SLOT(on_enabled_change(bool)));
|
||||
connect(collapse_button, SIGNAL(clicked()), this, SLOT(on_visible_change()));
|
||||
}
|
||||
}
|
||||
|
||||
void CollapsibleWidget::setText(const QString &s) {
|
||||
header->setText(s);
|
||||
}
|
||||
|
||||
void CollapsibleWidget::on_enabled_change(bool b) {
|
||||
contents->setEnabled(b);
|
||||
}
|
||||
|
||||
void CollapsibleWidget::on_visible_change() {
|
||||
contents->setVisible(!contents->isVisible());
|
||||
collapse_button->setText(contents->isVisible() ? "-" : "+");
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef COLLAPSIBLEWIDGET_H
|
||||
#define COLLAPSIBLEWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
class QLabel;
|
||||
class QCheckBox;
|
||||
class QHBoxLayout;
|
||||
class QVBoxLayout;
|
||||
class QPushButton;
|
||||
class QFrame;
|
||||
|
||||
class CollapsibleWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CollapsibleWidget(QWidget* parent = 0);
|
||||
void setContents(QWidget* c);
|
||||
void setText(const QString &);
|
||||
private:
|
||||
QLabel* header;
|
||||
QCheckBox* enabled_check;
|
||||
QHBoxLayout* title_bar;
|
||||
QVBoxLayout* layout;
|
||||
QPushButton* collapse_button;
|
||||
QWidget* contents;
|
||||
QFrame* line;
|
||||
|
||||
private slots:
|
||||
void on_enabled_change(bool b);
|
||||
void on_visible_change();
|
||||
};
|
||||
|
||||
#endif // COLLAPSIBLEWIDGET_H
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "playbutton.h"
|
||||
|
||||
PlayButton::PlayButton(QWidget* parent) : QPushButton(parent)
|
||||
{
|
||||
play_text = ">";
|
||||
pause_text = "||";
|
||||
|
||||
setText(play_text);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef PLAYBUTTON_H
|
||||
#define PLAYBUTTON_H
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
class PlayButton : public QPushButton
|
||||
{
|
||||
public:
|
||||
PlayButton(QWidget* parent = 0);
|
||||
private:
|
||||
QString play_text;
|
||||
QString pause_text;
|
||||
};
|
||||
|
||||
#endif // PLAYBUTTON_H
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "sourcetable.h"
|
||||
#include "panels/project.h"
|
||||
|
||||
#include "io/media.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "panels/panels.h"
|
||||
|
||||
#include <QDragEnterEvent>
|
||||
|
||||
SourceTable::SourceTable(QWidget* parent) : QTreeWidget(parent) {
|
||||
this->sortByColumn(0, Qt::AscendingOrder);
|
||||
}
|
||||
|
||||
void SourceTable::mouseDoubleClickEvent(QMouseEvent* )
|
||||
{
|
||||
if (selectedItems().count() == 0) {
|
||||
panel_project->import_dialog();
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void SourceTable::dragEnterEvent(QDragEnterEvent *event) {
|
||||
// event->accept();
|
||||
//}
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef SOURCETABLE_H
|
||||
#define SOURCETABLE_H
|
||||
|
||||
#include <QTreeWidget>
|
||||
|
||||
class Project;
|
||||
|
||||
class SourceTable : public QTreeWidget
|
||||
{
|
||||
public:
|
||||
SourceTable(QWidget* parent = 0);
|
||||
protected:
|
||||
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
// void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // SOURCETABLE_H
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef TIMELINETOOLS_H
|
||||
#define TIMELINETOOLS_H
|
||||
|
||||
enum TimelineTools {
|
||||
TIMELINE_TOOL_POINTER,
|
||||
TIMELINE_TOOL_EDIT,
|
||||
TIMELINE_TOOL_RAZOR,
|
||||
TIMELINE_TOOL_RIPPLE,
|
||||
TIMELINE_TOOL_ROLLING,
|
||||
TIMELINE_TOOL_SLIP,
|
||||
TIMELINE_TOOL_HAND,
|
||||
TIMELINE_TOOL_ZOOM
|
||||
};
|
||||
|
||||
#endif // TIMELINETOOLS_H
|
||||
@@ -0,0 +1,799 @@
|
||||
#include "timelinewidget.h"
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "io/config.h"
|
||||
#include "project/sequence.h"
|
||||
#include "project/clip.h"
|
||||
#include "panels/project.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "io/media.h"
|
||||
#include "ui/sourcetable.h"
|
||||
#include "panels/effectcontrols.h"
|
||||
|
||||
#include "effects/effects.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QColor>
|
||||
#include <QDebug>
|
||||
#include <QMouseEvent>
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
#include <QPointF>
|
||||
|
||||
TimelineWidget::TimelineWidget(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
bottom_align = false;
|
||||
setMouseTracking(true);
|
||||
track_height = 40;
|
||||
|
||||
clip_pixmap = NULL;
|
||||
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
|
||||
bool same_sign(int a, int b) {
|
||||
return (a < 0) == (b < 0);
|
||||
}
|
||||
|
||||
void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
|
||||
if (static_cast<SourceTable*>(event->source()) == panel_project->source_table) {
|
||||
QPoint pos = event->pos();
|
||||
event->accept();
|
||||
QList<QTreeWidgetItem*> items = panel_project->source_table->selectedItems();
|
||||
long entry_point = getFrameFromScreenPoint(pos.x(), false);
|
||||
panel_timeline->drag_frame_start = entry_point + getFrameFromScreenPoint(50, false);
|
||||
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>());
|
||||
long duration = m->get_length_in_frames(panel_timeline->sequence->frame_rate);
|
||||
Ghost g = {NULL, entry_point, entry_point + duration};
|
||||
g.media = m;
|
||||
g.clip_in = 0;
|
||||
for (int j=0;j<m->audio_tracks.size();j++) {
|
||||
g.track = j;
|
||||
g.media_stream = &m->audio_tracks[j];
|
||||
ignore_infinite_length = true;
|
||||
panel_timeline->ghosts.append(g);
|
||||
}
|
||||
for (int j=0;j<m->video_tracks.size();j++) {
|
||||
g.track = -1-j;
|
||||
g.media_stream = &m->video_tracks[j];
|
||||
if (m->video_tracks[j].infinite_length && !ignore_infinite_length) g.out = g.in + 100;
|
||||
panel_timeline->ghosts.append(g);
|
||||
}
|
||||
entry_point += duration;
|
||||
}
|
||||
init_ghosts();
|
||||
panel_timeline->importing = true;
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::dragMoveEvent(QDragMoveEvent *event) {
|
||||
if (panel_timeline->importing) {
|
||||
QPoint pos = event->pos();
|
||||
update_ghosts(pos);
|
||||
panel_timeline->repaint_timeline();
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::dragLeaveEvent(QDragLeaveEvent *event) {
|
||||
if (panel_timeline->importing) {
|
||||
panel_timeline->ghosts.clear();
|
||||
panel_timeline->importing = false;
|
||||
panel_timeline->repaint_timeline();
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::dropEvent(QDropEvent* event) {
|
||||
if (panel_timeline->importing) {
|
||||
event->accept();
|
||||
|
||||
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);
|
||||
|
||||
Clip& c = panel_timeline->sequence->new_clip();
|
||||
c.media = g.media;
|
||||
c.media_stream = g.media_stream;
|
||||
c.timeline_in = g.in;
|
||||
c.timeline_out = g.out;
|
||||
c.clip_in = g.clip_in;
|
||||
c.color_r = 128;
|
||||
c.color_g = 128;
|
||||
c.color_b = 192;
|
||||
c.sequence = panel_timeline->sequence;
|
||||
c.track = g.track;
|
||||
c.name = c.media->name;
|
||||
|
||||
if (c.track < 0) {
|
||||
// add default video effects
|
||||
c.effects.append(new TransformEffect(&c));
|
||||
} else {
|
||||
// add default audio effects
|
||||
c.effects.append(new VolumeEffect(&c));
|
||||
c.effects.append(new PanEffect(&c));
|
||||
}
|
||||
}
|
||||
|
||||
panel_timeline->ghosts.clear();
|
||||
panel_timeline->importing = false;
|
||||
|
||||
panel_timeline->redraw_all_clips();
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::mousePressEvent(QMouseEvent *event) {
|
||||
QPoint pos = event->pos();
|
||||
|
||||
panel_timeline->drag_frame_start = getFrameFromScreenPoint(pos.x(), false);
|
||||
panel_timeline->drag_track_start = getTrackFromScreenPoint(pos.y());
|
||||
int clip_index = panel_timeline->trim_target;
|
||||
if (clip_index == -1) clip_index = getClipIndexFromCoords(panel_timeline->drag_frame_start, panel_timeline->drag_track_start);
|
||||
|
||||
switch (panel_timeline->tool) {
|
||||
case TIMELINE_TOOL_POINTER:
|
||||
case TIMELINE_TOOL_RIPPLE:
|
||||
{
|
||||
if (clip_index >= 0) {
|
||||
if (panel_timeline->is_clip_selected(clip_index)) {
|
||||
// TODO if shift is down, deselect it
|
||||
} else {
|
||||
// if "shift" is not down
|
||||
if (!(event->modifiers() & Qt::ShiftModifier)) {
|
||||
panel_timeline->selections.clear();
|
||||
}
|
||||
|
||||
Clip& clip = panel_timeline->sequence->get_clip(clip_index);
|
||||
panel_timeline->selections.append({clip.timeline_in, clip.timeline_out, clip.track});
|
||||
}
|
||||
panel_timeline->moving_init = true;
|
||||
} else {
|
||||
panel_timeline->selections.clear();
|
||||
}
|
||||
panel_timeline->repaint_timeline();
|
||||
}
|
||||
break;
|
||||
case TIMELINE_TOOL_EDIT:
|
||||
panel_timeline->seek(panel_timeline->drag_frame_start);
|
||||
panel_timeline->selecting = true;
|
||||
panel_timeline->repaint_timeline();
|
||||
break;
|
||||
case TIMELINE_TOOL_RAZOR:
|
||||
{
|
||||
if (clip_index >= 0) {
|
||||
panel_timeline->sequence->split_clip(clip_index, panel_timeline->drag_frame_start);
|
||||
}
|
||||
panel_timeline->splitting = true;
|
||||
panel_timeline->redraw_all_clips();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
if (panel_timeline->moving_proc) {
|
||||
if (event->modifiers() & Qt::AltModifier) { // if holding alt, duplicate rather than move
|
||||
// duplicate clips
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
Ghost& g = panel_timeline->ghosts[i];
|
||||
Clip& c = panel_timeline->sequence->insert_clip(*g.clip);
|
||||
|
||||
c.timeline_in = g.in;
|
||||
c.timeline_out = g.out;
|
||||
c.track = g.track;
|
||||
c.undeletable = true;
|
||||
|
||||
// step 2 - delete anything that exists in area that clip is moving to
|
||||
panel_timeline->sequence->delete_area(g.in, g.out, g.track);
|
||||
|
||||
c.undeletable = false;
|
||||
}
|
||||
} else {
|
||||
// move clips
|
||||
// TODO can we do this better than 3 consecutive for loops?
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
// step 1 - set clips that are moving to "undeletable" (to avoid step 2 deleting any part of them)
|
||||
panel_timeline->ghosts[i].clip->undeletable = true;
|
||||
}
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
Ghost& g = panel_timeline->ghosts[i];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// step 3 - move clips
|
||||
g.clip->timeline_in = g.in;
|
||||
g.clip->timeline_out = g.out;
|
||||
g.clip->track = g.track;
|
||||
g.clip->clip_in = g.clip_in;
|
||||
}
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
// step 4 - set clips back to deletable
|
||||
panel_timeline->ghosts[i].clip->undeletable = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ripple ops
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) {
|
||||
long ripple_length, ripple_point;
|
||||
if (panel_timeline->trim_in) {
|
||||
ripple_length = panel_timeline->ghosts.at(0).old_in - panel_timeline->ghosts.at(0).in;
|
||||
ripple_point = (ripple_length < 0) ? panel_timeline->ghosts.at(0).old_in : panel_timeline->ghosts.at(0).in;
|
||||
} else {
|
||||
ripple_length = panel_timeline->ghosts.at(0).old_out - panel_timeline->ghosts.at(0).out;
|
||||
ripple_point = (ripple_length < 0) ? panel_timeline->ghosts.at(0).old_out : panel_timeline->ghosts.at(0).out;
|
||||
}
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
long comp_point;
|
||||
if (panel_timeline->trim_in) {
|
||||
comp_point = (ripple_length < 0) ? panel_timeline->ghosts.at(i).old_in : panel_timeline->ghosts.at(i).in;
|
||||
} else {
|
||||
comp_point = (ripple_length < 0) ? panel_timeline->ghosts.at(i).old_out : panel_timeline->ghosts.at(i).out;
|
||||
}
|
||||
if (ripple_point > comp_point) ripple_point = comp_point;
|
||||
}
|
||||
if (panel_timeline->trim_in) {
|
||||
panel_timeline->ripple(ripple_point, ripple_length);
|
||||
} else {
|
||||
panel_timeline->ripple(ripple_point, -ripple_length);
|
||||
}
|
||||
}
|
||||
|
||||
panel_timeline->redraw_all_clips();
|
||||
}
|
||||
|
||||
// destroy all ghosts
|
||||
panel_timeline->ghosts.clear();
|
||||
|
||||
panel_timeline->selecting = false;
|
||||
panel_timeline->moving_proc = false;
|
||||
panel_timeline->moving_init = false;
|
||||
panel_timeline->splitting = false;
|
||||
pre_clips.clear();
|
||||
post_clips.clear();
|
||||
|
||||
// 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++) {
|
||||
if (panel_timeline->is_clip_selected(i)) {
|
||||
if (!single_select) {
|
||||
// found ONE selected clip
|
||||
selected_clip = i;
|
||||
single_select = true;
|
||||
} else {
|
||||
// more than one clip is selected
|
||||
single_select = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (single_select) {
|
||||
panel_effect_controls->set_clip(&panel_timeline->sequence->get_clip(selected_clip));
|
||||
} else {
|
||||
panel_effect_controls->set_clip(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::init_ghosts() {
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
Ghost& g = panel_timeline->ghosts[i];
|
||||
g.old_in = g.in;
|
||||
g.old_out = g.out;
|
||||
g.old_track = g.track;
|
||||
g.old_clip_in = g.clip_in;
|
||||
|
||||
if (panel_timeline->trim_target > -1) {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
for (int i=0;i<panel_timeline->selections.size();i++) {
|
||||
Selection& s = panel_timeline->selections[i];
|
||||
s.old_in = s.in;
|
||||
s.old_out = s.out;
|
||||
s.old_track = s.track;
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::update_ghosts(QPoint& mouse_pos) {
|
||||
int mouse_track = getTrackFromScreenPoint(mouse_pos.y());
|
||||
long frame_diff = getFrameFromScreenPoint(mouse_pos.x(), false) - panel_timeline->drag_frame_start;
|
||||
int track_diff = mouse_track - panel_timeline->drag_track_start;
|
||||
|
||||
long validator;
|
||||
if (panel_timeline->trim_target > -1) {
|
||||
// trim ops
|
||||
|
||||
// validate ghosts
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
Ghost& g = panel_timeline->ghosts[i];
|
||||
|
||||
if (panel_timeline->trim_in) {
|
||||
// prevent clip length from being less than 1 frame long
|
||||
validator = g.ghost_length - frame_diff;
|
||||
if (validator < 1) frame_diff -= (1 - validator);
|
||||
|
||||
// prevent timeline in from going below 0
|
||||
validator = g.old_in + frame_diff;
|
||||
if (validator < 0) frame_diff -= validator;
|
||||
|
||||
if (!g.clip->media_stream->infinite_length) {
|
||||
// prevent clip_in from going below 0
|
||||
validator = g.old_clip_in + frame_diff;
|
||||
if (validator < 0) frame_diff -= validator;
|
||||
}
|
||||
|
||||
// ripple ops
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) {
|
||||
for (int j=0;j<post_clips.size();j++) {
|
||||
// prevent any rippled clip from going below 0
|
||||
Clip* post = post_clips.at(j);
|
||||
validator = post->timeline_in - frame_diff;
|
||||
if (validator < 0) frame_diff += validator;
|
||||
|
||||
// prevent any post-clips colliding with pre-clips
|
||||
for (int k=0;k<pre_clips.size();k++) {
|
||||
Clip* pre = pre_clips.at(k);
|
||||
if (pre->track == post->track) {
|
||||
validator = post->timeline_in - frame_diff - pre->timeline_out;
|
||||
if (validator < 0) frame_diff += validator;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// prevent clip length from being less than 1 frame long
|
||||
validator = g.ghost_length + frame_diff;
|
||||
if (validator < 1) frame_diff += (1 - validator);
|
||||
|
||||
if (!g.clip->media_stream->infinite_length) {
|
||||
// prevent clip length exceeding media length
|
||||
validator = g.ghost_length + frame_diff;
|
||||
if (validator > g.media_length) frame_diff -= validator - g.media_length;
|
||||
}
|
||||
|
||||
// ripple ops
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) {
|
||||
for (int j=0;j<post_clips.size();j++) {
|
||||
Clip* post = post_clips.at(j);
|
||||
|
||||
// prevent any post-clips colliding with pre-clips
|
||||
for (int k=0;k<pre_clips.size();k++) {
|
||||
Clip* pre = pre_clips.at(k);
|
||||
if (pre->track == post->track) {
|
||||
validator = post->timeline_in + frame_diff - pre->timeline_out;
|
||||
if (validator < 0) frame_diff -= validator;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// resize ghosts
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
Ghost& g = panel_timeline->ghosts[i];
|
||||
|
||||
if (panel_timeline->trim_in) {
|
||||
g.in = g.old_in + frame_diff;
|
||||
g.clip_in = g.old_clip_in + frame_diff;
|
||||
} else {
|
||||
g.out = g.old_out + frame_diff;
|
||||
}
|
||||
}
|
||||
|
||||
// resize selections
|
||||
for (int i=0;i<panel_timeline->selections.size();i++) {
|
||||
Selection& s = panel_timeline->selections[i];
|
||||
|
||||
if (panel_timeline->trim_in) {
|
||||
s.in = s.old_in + frame_diff;
|
||||
} else {
|
||||
s.out = s.old_out + frame_diff;
|
||||
}
|
||||
}
|
||||
} else if (panel_timeline->tool == TIMELINE_TOOL_POINTER || panel_timeline->importing) { // only move clips on pointer (not ripple or rolling)
|
||||
// validate ghosts
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
Ghost& g = panel_timeline->ghosts[i];
|
||||
|
||||
// prevent clips from moving below 0 on the timeline
|
||||
validator = g.old_in + frame_diff;
|
||||
if (validator < 0) frame_diff -= validator;
|
||||
|
||||
// prevent clips from crossing tracks
|
||||
if (same_sign(g.old_track, panel_timeline->drag_track_start)) {
|
||||
while (!same_sign(g.old_track, g.old_track + track_diff)) {
|
||||
if (g.old_track < 0) {
|
||||
track_diff--;
|
||||
} else {
|
||||
track_diff++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// move ghosts
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
Ghost& g = panel_timeline->ghosts[i];
|
||||
g.in = g.old_in + frame_diff;
|
||||
g.out = g.old_out + frame_diff;
|
||||
|
||||
g.track = g.old_track;
|
||||
|
||||
if (panel_timeline->importing) {
|
||||
int abs_track_diff = abs(track_diff);
|
||||
if (g.old_track < 0) { // clip is video
|
||||
g.track -= abs_track_diff;
|
||||
} else { // clip is audio
|
||||
g.track += abs_track_diff;
|
||||
}
|
||||
} else {
|
||||
if (same_sign(g.old_track, panel_timeline->drag_track_start)) g.track += track_diff;
|
||||
}
|
||||
}
|
||||
|
||||
// move selections
|
||||
if (!panel_timeline->importing) {
|
||||
for (int i=0;i<panel_timeline->selections.size();i++) {
|
||||
Selection& s = panel_timeline->selections[i];
|
||||
s.in = s.old_in + frame_diff;
|
||||
s.out = s.old_out + frame_diff;
|
||||
s.track = s.old_track;
|
||||
if (panel_timeline->importing) {
|
||||
int abs_track_diff = abs(track_diff);
|
||||
if (s.old_track < 0) {
|
||||
s.track -= abs_track_diff;
|
||||
} else {
|
||||
s.track += abs_track_diff;
|
||||
}
|
||||
} else {
|
||||
if (same_sign(s.track, panel_timeline->drag_track_start)) s.track += track_diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
if (panel_timeline->selecting) {
|
||||
QPoint pos = event->pos();
|
||||
|
||||
int current_selection_track = getTrackFromScreenPoint(pos.y());
|
||||
long current_selection_frame = getFrameFromScreenPoint(pos.x(), false);;
|
||||
int selection_count = 1 + qMax(current_selection_track, panel_timeline->drag_track_start) - qMin(current_selection_track, panel_timeline->drag_track_start);
|
||||
if (panel_timeline->selections.size() != selection_count) {
|
||||
panel_timeline->selections.resize(selection_count);
|
||||
}
|
||||
int minimum_selection_track = qMin(current_selection_track, panel_timeline->drag_track_start);
|
||||
for (int i=0;i<selection_count;i++) {
|
||||
Selection* s = &panel_timeline->selections[i];
|
||||
s->track = minimum_selection_track + i;
|
||||
long in = panel_timeline->drag_frame_start;
|
||||
long out = current_selection_frame;
|
||||
s->in = qMin(in, out);
|
||||
s->out = qMax(in, out);
|
||||
}
|
||||
panel_timeline->playhead = qMin(panel_timeline->drag_frame_start, current_selection_frame);
|
||||
panel_timeline->repaint_timeline();
|
||||
} else if (panel_timeline->moving_init) {
|
||||
QPoint pos = event->pos();
|
||||
|
||||
if (panel_timeline->moving_proc) {
|
||||
update_ghosts(pos);
|
||||
} else {
|
||||
// set up movement
|
||||
// create ghosts
|
||||
for (int i=0;i<panel_timeline->sequence->clip_count();i++) {
|
||||
if (panel_timeline->is_clip_selected(i)) {
|
||||
Clip& c = panel_timeline->sequence->get_clip(i);
|
||||
panel_timeline->ghosts.append({&c, c.timeline_in, c.timeline_out, c.track, c.clip_in});
|
||||
}
|
||||
}
|
||||
|
||||
// ripple edit prep
|
||||
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++) {
|
||||
// don't cache any currently selected clips
|
||||
Clip* c = panel_timeline->ghosts.at(i).clip;
|
||||
Clip& cc = panel_timeline->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) {
|
||||
is_selected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_selected) {
|
||||
if (cc.timeline_in < c->timeline_in) {
|
||||
// add clip to pre-cache UNLESS there is already a clip on that track closer to the ripple point
|
||||
bool found = false;
|
||||
for (int k=0;k<pre_clips.size();k++) {
|
||||
Clip* ccc = pre_clips.at(k);
|
||||
if (ccc->track == cc.track) {
|
||||
if (ccc->timeline_in < cc.timeline_in) {
|
||||
// clip is closer to ripple point than the one in cache, replace it
|
||||
ccc = &cc;
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// no clip from that track in the cache, add it
|
||||
pre_clips.append(&cc);
|
||||
}
|
||||
} else {
|
||||
// add clip to post-cache UNLESS there is already a clip on that track closer to the ripple point
|
||||
bool found = false;
|
||||
for (int k=0;k<post_clips.size();k++) {
|
||||
Clip* ccc = post_clips.at(k);
|
||||
if (ccc->track == cc.track) {
|
||||
if (ccc->timeline_in > cc.timeline_in) {
|
||||
// clip is closer to ripple point than the one in cache, replace it
|
||||
ccc = &cc;
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// no clip from that track in the cache, add it
|
||||
post_clips.append(&cc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// debug code - print the information we got
|
||||
qDebug() << "found" << pre_clips.size() << "preceding clips and" << post_clips.size() << "following";
|
||||
}
|
||||
|
||||
init_ghosts();
|
||||
|
||||
panel_timeline->moving_proc = true;
|
||||
}
|
||||
panel_timeline->repaint_timeline();
|
||||
} else if (panel_timeline->splitting) {
|
||||
QPoint pos = event->pos();
|
||||
|
||||
int track = getTrackFromScreenPoint(pos.y());
|
||||
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);
|
||||
repaint = true;
|
||||
}
|
||||
}
|
||||
|
||||
// redraw clips since we changed them
|
||||
if (repaint) panel_timeline->redraw_all_clips();
|
||||
} else if (panel_timeline->tool == TIMELINE_TOOL_POINTER || panel_timeline->tool == TIMELINE_TOOL_RIPPLE) {
|
||||
QPoint pos = event->pos();
|
||||
|
||||
int lim = 5;
|
||||
int mouse_track = getTrackFromScreenPoint(pos.y());
|
||||
long mouse_frame_lower = getFrameFromScreenPoint(pos.x()-lim, false)-1;
|
||||
long mouse_frame_upper = getFrameFromScreenPoint(pos.x()+lim, false)+1;
|
||||
bool found = false;
|
||||
for (int i=0;i<panel_timeline->sequence->clip_count();i++) {
|
||||
Clip& c = panel_timeline->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;
|
||||
panel_timeline->trim_in = true;
|
||||
found = true;
|
||||
break;
|
||||
} else if (c.timeline_out > mouse_frame_lower && c.timeline_out < mouse_frame_upper) {
|
||||
panel_timeline->trim_target = i;
|
||||
panel_timeline->trim_in = false;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
setCursor(Qt::SizeHorCursor);
|
||||
} else {
|
||||
unsetCursor();
|
||||
panel_timeline->trim_target = -1;
|
||||
}
|
||||
} else if (panel_timeline->tool == TIMELINE_TOOL_EDIT || panel_timeline->tool == TIMELINE_TOOL_RAZOR) {
|
||||
// redraw because we have a cursor
|
||||
panel_timeline->repaint_timeline();
|
||||
}
|
||||
}
|
||||
|
||||
int color_brightness(int r, int g, int b) {
|
||||
return (0.2126*r + 0.7152*g + 0.0722*b);
|
||||
}
|
||||
|
||||
void TimelineWidget::redraw_clips() {
|
||||
// Draw clips
|
||||
if (clip_pixmap != NULL) delete clip_pixmap;
|
||||
|
||||
int panel_width = getScreenPointFromFrame(panel_timeline->sequence->getEndFrame()) + 100;
|
||||
setMinimumWidth(panel_width);
|
||||
|
||||
clip_pixmap = new QPixmap(panel_width, height());
|
||||
clip_pixmap->fill(Qt::transparent);
|
||||
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);
|
||||
if (is_track_visible(clip.track)) {
|
||||
if (clip.track < 0 && clip.track < video_track_limit) { // video clip
|
||||
video_track_limit = clip.track;
|
||||
} else if (clip.track > audio_track_limit) {
|
||||
audio_track_limit = clip.track;
|
||||
}
|
||||
|
||||
QRect clip_rect(getScreenPointFromFrame(clip.timeline_in), getScreenPointFromTrack(clip.track), clip.getLength() * panel_timeline->zoom, track_height);
|
||||
clip_painter.fillRect(clip_rect, QColor(clip.color_r, clip.color_g, clip.color_b));
|
||||
clip_painter.setPen(Qt::white);
|
||||
clip_painter.drawLine(clip_rect.bottomLeft(), clip_rect.topLeft());
|
||||
clip_painter.drawLine(clip_rect.topLeft(), clip_rect.topRight());
|
||||
clip_painter.setPen(QColor(0, 0, 0, 128));
|
||||
clip_painter.drawLine(clip_rect.bottomLeft(), clip_rect.bottomRight());
|
||||
clip_painter.drawLine(clip_rect.bottomRight(), clip_rect.topRight());
|
||||
|
||||
if (color_brightness(clip.color_r, clip.color_g, clip.color_b) > 160) {
|
||||
clip_painter.setPen(Qt::black);
|
||||
} else {
|
||||
clip_painter.setPen(Qt::white);
|
||||
}
|
||||
QRect text_rect(clip_rect.left() + CLIP_TEXT_PADDING, clip_rect.top() + CLIP_TEXT_PADDING, clip_rect.width() - CLIP_TEXT_PADDING - CLIP_TEXT_PADDING, clip_rect.height() - CLIP_TEXT_PADDING - CLIP_TEXT_PADDING);
|
||||
clip_painter.drawText(text_rect, 0, clip.name, &text_rect);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw track lines
|
||||
if (show_track_lines) {
|
||||
clip_painter.setPen(QColor(0, 0, 0, 96));
|
||||
audio_track_limit++;
|
||||
if (video_track_limit == 0) video_track_limit--;
|
||||
|
||||
if (bottom_align) {
|
||||
// only draw lines for video tracks
|
||||
for (int i=video_track_limit;i<0;i++) {
|
||||
int line_y = getScreenPointFromTrack(i) - 1;
|
||||
clip_painter.drawLine(0, line_y, rect().width(), line_y);
|
||||
}
|
||||
} else {
|
||||
// only draw lines for audio tracks
|
||||
for (int i=0;i<audio_track_limit;i++) {
|
||||
int line_y = getScreenPointFromTrack(i) + track_height;
|
||||
clip_painter.drawLine(0, line_y, rect().width(), line_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void TimelineWidget::paintEvent(QPaintEvent*) {
|
||||
if (panel_timeline->sequence != NULL) {
|
||||
QPainter p(this);
|
||||
|
||||
if (clip_pixmap != NULL) p.drawPixmap(0, 0, minimumWidth(), height(), *clip_pixmap);
|
||||
|
||||
// Draw selections
|
||||
for (int i=0;i<panel_timeline->selections.size();i++) {
|
||||
const Selection& s = panel_timeline->selections.at(i);
|
||||
if (is_track_visible(s.track)) {
|
||||
int selection_y = getScreenPointFromTrack(s.track);
|
||||
int selection_x = getScreenPointFromFrame(s.in);
|
||||
p.fillRect(selection_x, selection_y, getScreenPointFromFrame(s.out) - selection_x, track_height, QColor(0, 0, 0, 64));
|
||||
}
|
||||
}
|
||||
|
||||
// Draw ghosts
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
const Ghost& g = panel_timeline->ghosts.at(i);
|
||||
if (is_track_visible(g.track)) {
|
||||
int ghost_x = getScreenPointFromFrame(g.in);
|
||||
int ghost_y = getScreenPointFromTrack(g.track);
|
||||
int ghost_width = getScreenPointFromFrame(g.out - g.in) - 1;
|
||||
int ghost_height = track_height - 1;
|
||||
p.setPen(QColor(255, 255, 0));
|
||||
for (int j=0;j<GHOST_THICKNESS;j++) {
|
||||
p.drawRect(ghost_x+j, ghost_y+j, ghost_width-j-j, ghost_height-j-j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw edit cursor
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_EDIT || panel_timeline->tool == TIMELINE_TOOL_RAZOR) {
|
||||
QPoint mouse_pos = mapFromGlobal(QCursor::pos());
|
||||
int track = getTrackFromScreenPoint(mouse_pos.y());
|
||||
if (is_track_visible(track)) {
|
||||
int cursor_x = getScreenPointFromFrame(getFrameFromScreenPoint(mouse_pos.x(), false));
|
||||
int cursor_y = getScreenPointFromTrack(track);
|
||||
|
||||
p.setPen(Qt::gray);
|
||||
p.drawLine(cursor_x, cursor_y, cursor_x, cursor_y + track_height);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw playhead
|
||||
p.setPen(Qt::red);
|
||||
int playhead_x = getScreenPointFromFrame(panel_timeline->playhead);
|
||||
p.drawLine(playhead_x, rect().top(), playhead_x, rect().bottom());
|
||||
|
||||
p.setPen(QColor(0, 0, 0, 64));
|
||||
int edge_y = (bottom_align) ? rect().height()-1 : 0;
|
||||
p.drawLine(0, edge_y, rect().width(), edge_y);
|
||||
}
|
||||
}
|
||||
|
||||
bool TimelineWidget::is_track_visible(int track) {
|
||||
return ((bottom_align && track < 0) || (!bottom_align && track >= 0));
|
||||
}
|
||||
|
||||
// **************************************
|
||||
// screen point <-> frame/track functions
|
||||
// **************************************
|
||||
|
||||
long TimelineWidget::getFrameFromScreenPoint(int x, bool f) {
|
||||
float div = (float) x / panel_timeline->zoom;
|
||||
if (div < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (f) {
|
||||
return floor(div);
|
||||
} else {
|
||||
return round(div);
|
||||
}
|
||||
}
|
||||
|
||||
int TimelineWidget::getTrackFromScreenPoint(int y) {
|
||||
if (bottom_align) {
|
||||
y -= rect().bottom();
|
||||
if (show_track_lines) y -= 1;
|
||||
} else {
|
||||
y -= 1;
|
||||
}
|
||||
int temp_track_height = track_height;
|
||||
if (show_track_lines) temp_track_height--;
|
||||
return (int)floor((float) (y)/ (float) temp_track_height);
|
||||
}
|
||||
|
||||
int TimelineWidget::getScreenPointFromFrame(long frame) {
|
||||
return (int) round(frame*panel_timeline->zoom);
|
||||
}
|
||||
|
||||
int TimelineWidget::getScreenPointFromTrack(int track) {
|
||||
int temp_track_height = track_height;
|
||||
if (show_track_lines) temp_track_height++;
|
||||
int y = track * temp_track_height;
|
||||
|
||||
if (bottom_align) { // video track
|
||||
y += rect().bottom();
|
||||
if (show_track_lines) y += 1;
|
||||
} else { // audio track
|
||||
y += 1;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
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);
|
||||
if (c.track == track) {
|
||||
if (frame >= c.timeline_in && frame < c.timeline_out) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#ifndef TIMELINEWIDGET_H
|
||||
#define TIMELINEWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include "timeline-tools.h"
|
||||
|
||||
#define GHOST_THICKNESS 2 // thiccccc
|
||||
#define CLIP_TEXT_PADDING 3
|
||||
|
||||
struct Sequence;
|
||||
struct Clip;
|
||||
class Timeline;
|
||||
|
||||
class TimelineWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TimelineWidget(QWidget *parent = nullptr);
|
||||
|
||||
bool bottom_align;
|
||||
|
||||
void redraw_clips();
|
||||
protected:
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
void dragLeaveEvent(QDragLeaveEvent *event);
|
||||
void dropEvent(QDropEvent* event);
|
||||
void dragMoveEvent(QDragMoveEvent *event);
|
||||
private:
|
||||
void init_ghosts();
|
||||
void update_ghosts(QPoint& mouse_pos);
|
||||
bool is_track_visible(int track);
|
||||
long getFrameFromScreenPoint(int x, bool floor);
|
||||
int getTrackFromScreenPoint(int y);
|
||||
int getScreenPointFromFrame(long frame);
|
||||
int getScreenPointFromTrack(int track);
|
||||
int getClipIndexFromCoords(long frame, int track);
|
||||
int track_height;
|
||||
|
||||
QList<Clip*> pre_clips;
|
||||
QList<Clip*> post_clips;
|
||||
|
||||
QPixmap* clip_pixmap;
|
||||
// QPixmap selection_pixmap;
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
};
|
||||
|
||||
#endif // TIMELINEWIDGET_H
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "viewercontainer.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QResizeEvent>
|
||||
|
||||
// enforces aspect ratio
|
||||
ViewerContainer::ViewerContainer(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
child = NULL;
|
||||
aspect_ratio = 1;
|
||||
}
|
||||
|
||||
void ViewerContainer::adjust() {
|
||||
if (child != NULL) {
|
||||
QSize widget_size = size();
|
||||
int widget_x = 0;
|
||||
int widget_y = 0;
|
||||
int widget_width = widget_size.width();
|
||||
int widget_height = widget_size.height();
|
||||
float widget_ar = (float) widget_width /(float) widget_height;
|
||||
|
||||
bool widget_is_larger_than_sequence = widget_ar > aspect_ratio;
|
||||
|
||||
if (widget_is_larger_than_sequence) {
|
||||
widget_width = widget_height * aspect_ratio;
|
||||
widget_x = (widget_size.width() / 2) - (widget_width / 2);
|
||||
} else {
|
||||
widget_height = widget_width / aspect_ratio;
|
||||
widget_y = (widget_size.height() / 2) - (widget_height / 2);
|
||||
}
|
||||
|
||||
child->move(widget_x, widget_y);
|
||||
child->resize(widget_width, widget_height);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerContainer::resizeEvent(QResizeEvent *event) {
|
||||
event->accept();
|
||||
adjust();
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef VIEWERCONTAINER_H
|
||||
#define VIEWERCONTAINER_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class ViewerContainer : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ViewerContainer(QWidget *parent = nullptr);
|
||||
float aspect_ratio;
|
||||
QWidget* child;
|
||||
void adjust();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
};
|
||||
|
||||
#endif // VIEWERCONTAINER_H
|
||||
@@ -0,0 +1,157 @@
|
||||
#include "viewerwidget.h"
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "project/sequence.h"
|
||||
#include "project/effect.h"
|
||||
#include "playback/playback.h"
|
||||
#include "playback/audio.h"
|
||||
#include "io/media.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
}
|
||||
|
||||
ViewerWidget::ViewerWidget(QWidget *parent) : QOpenGLWidget(parent)
|
||||
{
|
||||
multithreaded = true;
|
||||
|
||||
QSurfaceFormat format;
|
||||
format.setDepthBufferSize(24);
|
||||
setFormat(format);
|
||||
|
||||
// error handler - retries after 200ms if we couldn't get the entire image
|
||||
retry_timer.setInterval(200);
|
||||
connect(&retry_timer, SIGNAL(timeout()), this, SLOT(retry()));
|
||||
}
|
||||
|
||||
void ViewerWidget::retry() {
|
||||
update();
|
||||
}
|
||||
|
||||
void ViewerWidget::initializeGL() {
|
||||
initializeOpenGLFunctions();
|
||||
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
//void ViewerWidget::resizeGL(int w, int h)
|
||||
//{
|
||||
//}
|
||||
|
||||
int audio_bytes_written = 0;
|
||||
|
||||
void ViewerWidget::paintGL()
|
||||
{
|
||||
if (multithreaded) retry_timer.stop();
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
long playhead = panel_timeline->playhead;
|
||||
|
||||
handle_media(panel_viewer->sequence, playhead, multithreaded);
|
||||
texture_failed = false;
|
||||
|
||||
bool render_audio = (panel_timeline->playing);
|
||||
|
||||
if (render_audio && switch_audio_cache) {
|
||||
reading_audio_cache_A = !reading_audio_cache_A;
|
||||
audio_bytes_written = 0;
|
||||
clear_cache(!reading_audio_cache_A, reading_audio_cache_A);
|
||||
}
|
||||
|
||||
cc_lock.lock();
|
||||
for (int i=0;i<current_clips.size();i++) {
|
||||
Clip* c = current_clips.at(i);
|
||||
|
||||
if (!c->open) {
|
||||
qDebug() << "[WARNING] Tried to display clip" << i << "but it's closed";
|
||||
texture_failed = true;
|
||||
} else if (is_clip_active(c, playhead)) {
|
||||
if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
// start preparing cache
|
||||
get_clip_frame(c, playhead);
|
||||
|
||||
if (c->texture == NULL) {
|
||||
qDebug() << "[WARNING] Texture hasn't been created yet";
|
||||
texture_failed = true;
|
||||
} else if (playhead >= c->timeline_in) {
|
||||
glLoadIdentity();
|
||||
int half_width = c->sequence->width/2;
|
||||
int half_height = c->sequence->height/2;
|
||||
glOrtho(-half_width, half_width, half_height,- half_height, -1, 1);
|
||||
int anchor_x = 0;
|
||||
int anchor_y = 0;
|
||||
|
||||
// perform all transform effects
|
||||
for (unsigned int j=0;j<c->effects.size();j++) {
|
||||
c->effects.at(j)->process_gl(&anchor_x, &anchor_y);
|
||||
}
|
||||
|
||||
int anchor_right = c->media_stream->video_width - anchor_x;
|
||||
int anchor_bottom = c->media_stream->video_height - anchor_y;
|
||||
|
||||
c->texture->bind();
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 0.0);
|
||||
glVertex2f(-anchor_x, -anchor_y);
|
||||
glTexCoord2f(1.0, 0.0);
|
||||
glVertex2f(anchor_right, -anchor_y);
|
||||
glTexCoord2f(1.0, 1.0);
|
||||
glVertex2f(anchor_right, anchor_bottom);
|
||||
glTexCoord2f(0.0, 1.0);
|
||||
glVertex2f(-anchor_x, anchor_bottom);
|
||||
glEnd();
|
||||
|
||||
c->texture->release();
|
||||
}
|
||||
} else if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
|
||||
playhead >= c->timeline_in &&
|
||||
render_audio &&
|
||||
!c->reached_end &&
|
||||
(switch_audio_cache || c->reset_audio)) {
|
||||
// TODO doesn't new clips appearing in the timeline (they'll ALWAYS end up in the other cache with a 1/8 sec delay)
|
||||
|
||||
// cache audio
|
||||
if (c->lock.tryLock()) {
|
||||
// clip is not caching, start cache
|
||||
c->lock.unlock();
|
||||
cache_clip(c, playhead, !reading_audio_cache_A, reading_audio_cache_A, c->reset_audio);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (render_audio) {
|
||||
switch_audio_cache = false;
|
||||
|
||||
if (audio_cache_A != NULL && audio_bytes_written < audio_cache_size) {
|
||||
// send cached/buffered audio to QIODevice/QAudioOutput
|
||||
uint8_t* cache = reading_audio_cache_A ? audio_cache_A : audio_cache_B;
|
||||
audio_bytes_written += audio_io_device->write((const char*) cache+audio_bytes_written, audio_cache_size-audio_bytes_written);
|
||||
}
|
||||
|
||||
if (audio_bytes_written == audio_cache_size) {
|
||||
// switch_cache
|
||||
switch_audio_cache = true;
|
||||
}
|
||||
}
|
||||
|
||||
cc_lock.unlock();
|
||||
|
||||
if (texture_failed) {
|
||||
if (multithreaded) {
|
||||
retry_timer.start();
|
||||
} else {
|
||||
paintGL();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef VIEWERWIDGET_H
|
||||
#define VIEWERWIDGET_H
|
||||
|
||||
#include <QOpenGLWidget>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QMatrix4x4>
|
||||
#include <QOpenGLTexture>
|
||||
#include <QTimer>
|
||||
|
||||
class Viewer;
|
||||
|
||||
class ViewerWidget : public QOpenGLWidget, public QOpenGLFunctions
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ViewerWidget(QWidget *parent = 0);
|
||||
void initializeGL();
|
||||
// void resizeGL(int w, int h);
|
||||
void paintGL();
|
||||
|
||||
bool multithreaded;
|
||||
private:
|
||||
QTimer retry_timer;
|
||||
private slots:
|
||||
void retry();
|
||||
};
|
||||
|
||||
#endif // VIEWERWIDGET_H
|
||||