merged with master

This commit is contained in:
itsmattkc
2019-03-25 12:43:23 +11:00
83 changed files with 7823 additions and 1469 deletions
+33 -3
View File
@@ -57,13 +57,14 @@ Config::Config()
hover_focus(false),
project_view_type(olive::PROJECT_VIEW_TREE),
set_name_with_marker(true),
show_project_toolbar(false),
show_project_toolbar(true),
previous_queue_size(3),
previous_queue_type(olive::FRAME_QUEUE_TYPE_FRAMES),
upcoming_queue_size(0.5),
upcoming_queue_type(olive::FRAME_QUEUE_TYPE_SECONDS),
loop(false),
seek_also_selects(false),
auto_seek_to_beginning(true),
effect_textbox_lines(3),
use_software_fallback(false),
center_timeline_timecodes(true),
@@ -73,7 +74,12 @@ Config::Config()
invert_timeline_scroll_axes(true),
enable_color_management(false),
style(olive::styling::kOliveDefaultDark),
use_native_menu_styling(true)
use_native_menu_styling(true),
default_sequence_width(1920),
default_sequence_height(1080),
default_sequence_framerate(29.97),
default_sequence_audio_frequency(48000),
default_sequence_audio_channel_layout(3)
{}
void Config::load(QString path) {
@@ -180,6 +186,9 @@ void Config::load(QString path) {
} else if (stream.name() == "SeekAlsoSelects") {
stream.readNext();
seek_also_selects = (stream.text() == "1");
} else if (stream.name() == "AutoSeekToBeginning") {
stream.readNext();
auto_seek_to_beginning = (stream.text() == "1");
} else if (stream.name() == "CSSPath") {
stream.readNext();
css_path = stream.text().toString();
@@ -222,6 +231,21 @@ void Config::load(QString path) {
} else if (stream.name() == "NativeMenuStyling") {
stream.readNext();
use_native_menu_styling = (stream.text() == "1");
} else if (stream.name() == "DefaultSequenceWidth") {
stream.readNext();
default_sequence_width = stream.text().toInt();
} else if (stream.name() == "DefaultSequenceHeight") {
stream.readNext();
default_sequence_height = stream.text().toInt();
} else if (stream.name() == "DefaultSequenceFrameRate") {
stream.readNext();
default_sequence_framerate = stream.text().toDouble();
} else if (stream.name() == "DefaultSequenceAudioFrequency") {
stream.readNext();
default_sequence_audio_frequency = stream.text().toInt();
} else if (stream.name() == "DefaultSequenceAudioLayout") {
stream.readNext();
default_sequence_audio_channel_layout = stream.text().toInt();
}
}
}
@@ -271,13 +295,14 @@ void Config::save(QString path) {
stream.writeTextElement("HoverFocus", QString::number(hover_focus));
stream.writeTextElement("ProjectViewType", QString::number(project_view_type));
stream.writeTextElement("SetNameWithMarker", QString::number(set_name_with_marker));
stream.writeTextElement("ShowProjectToolbar", QString::number(panel_project->toolbar_widget->isVisible()));
stream.writeTextElement("ShowProjectToolbar", QString::number(panel_project->IsToolbarVisible()));
stream.writeTextElement("PreviousFrameQueueSize", QString::number(previous_queue_size));
stream.writeTextElement("PreviousFrameQueueType", QString::number(previous_queue_type));
stream.writeTextElement("UpcomingFrameQueueSize", QString::number(upcoming_queue_size));
stream.writeTextElement("UpcomingFrameQueueType", QString::number(upcoming_queue_type));
stream.writeTextElement("Loop", QString::number(loop));
stream.writeTextElement("SeekAlsoSelects", QString::number(seek_also_selects));
stream.writeTextElement("AutoSeekToBeginning", QString::number(auto_seek_to_beginning));
stream.writeTextElement("CSSPath", css_path);
stream.writeTextElement("EffectTextboxLines", QString::number(effect_textbox_lines));
stream.writeTextElement("UseSoftwareFallback", QString::number(use_software_fallback));
@@ -292,6 +317,11 @@ void Config::save(QString path) {
stream.writeTextElement("OCIOConfigPath", ocio_config_path);
stream.writeTextElement("Style", QString::number(style));
stream.writeTextElement("NativeMenuStyling", QString::number(use_native_menu_styling));
stream.writeTextElement("DefaultSequenceWidth", QString::number(default_sequence_width));
stream.writeTextElement("DefaultSequenceHeight", QString::number(default_sequence_height));
stream.writeTextElement("DefaultSequenceFrameRate", QString::number(default_sequence_framerate));
stream.writeTextElement("DefaultSequenceAudioFrequency", QString::number(default_sequence_audio_frequency));
stream.writeTextElement("DefaultSequenceAudioLayout", QString::number(default_sequence_audio_channel_layout));
stream.writeEndElement(); // configuration
stream.writeEndDocument(); // doc
+36 -1
View File
@@ -120,7 +120,10 @@ namespace olive {
PROJECT_VIEW_TREE,
/** Display project media in icon browser */
PROJECT_VIEW_ICON
PROJECT_VIEW_ICON,
/** Display project media in list browser */
PROJECT_VIEW_LIST
};
/**
@@ -413,6 +416,13 @@ struct Config {
*/
bool seek_also_selects;
/**
* @brief Automatically seek to the beginning of a sequence if the user plays beyond the end of it
*
* TRUE if this behavior should be enabled.
*/
bool auto_seek_to_beginning;
/**
* @brief CSS Path
*
@@ -558,6 +568,31 @@ struct Config {
*/
bool use_native_menu_styling;
/**
* @brief Default Sequence video width
*/
int default_sequence_width;
/**
* @brief Default Sequence video height
*/
int default_sequence_height;
/**
* @brief Default Sequence video frame rate
*/
double default_sequence_framerate;
/**
* @brief Default Sequence audio frequency
*/
int default_sequence_audio_frequency;
/**
* @brief Default Sequence audio channel layout
*/
int default_sequence_audio_channel_layout;
/**
* @brief Load config from file
*
+85 -42
View File
@@ -39,6 +39,7 @@
#include "dialogs/speeddialog.h"
#include "dialogs/actionsearch.h"
#include "dialogs/loaddialog.h"
#include "dialogs/autocutsilencedialog.h"
#include "project/loadthread.h"
#include "timeline/sequence.h"
#include "ui/mediaiconservice.h"
@@ -91,7 +92,12 @@ void OliveGlobal::check_for_autorecovery_file() {
// detect auto-recovery file
autorecovery_filename = data_dir + "/autorecovery.ove";
if (QFile::exists(autorecovery_filename)) {
if (QMessageBox::question(nullptr, tr("Auto-recovery"), tr("Olive didn't close properly and an autorecovery file was detected. Would you like to open it?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
if (QMessageBox::question(nullptr,
tr("Auto-recovery"),
tr("Olive didn't close properly and an autorecovery file "
"was detected. Would you like to open it?"),
QMessageBox::Yes,
QMessageBox::No) == QMessageBox::Yes) {
enable_load_project_on_init = false;
OpenProjectWorker(autorecovery_filename, true);
}
@@ -166,18 +172,19 @@ void OliveGlobal::SetNativeStyling(QWidget *w)
#endif
}
void OliveGlobal::LoadProject(const QString &fn, bool autorecovery, bool clear)
void OliveGlobal::LoadProject(const QString &fn, bool autorecovery)
{
// Normally, the user will be closing the previous project to load a new one, but just in case the user
// is importing a new project
// QSortFilterProxyModels are not thread-safe, and as we'll be loading in another thread, leaving it connected
// can cause glitches in its presentation. Therefore for the duration of the loading process, we disconnect it,
// and reconnect it later once the loading is complete.
if (clear) {
new_project();
}
panel_project->DisconnectFilterToModel();
LoadDialog ld(olive::MainWindow);
LoadThread* lt = new LoadThread(fn, autorecovery, clear);
ld.open();
LoadThread* lt = new LoadThread(fn, autorecovery);
connect(&ld, SIGNAL(cancel()), lt, SLOT(cancel()));
connect(lt, SIGNAL(success()), &ld, SLOT(accept()));
connect(lt, SIGNAL(error()), &ld, SLOT(reject()));
@@ -185,40 +192,46 @@ void OliveGlobal::LoadProject(const QString &fn, bool autorecovery, bool clear)
connect(lt, SIGNAL(report_progress(int)), &ld, SLOT(setValue(int)));
lt->start();
ld.exec();
panel_project->ConnectFilterToModel();
}
void OliveGlobal::ClearProject()
{
// clear graph editor
panel_graph_editor->set_row(nullptr);
// clear effects panel
panel_effect_controls->Clear(true);
// clear existing project
olive::Global->set_sequence(nullptr);
panel_footage_viewer->set_media(nullptr);
// clear project contents (footage, sequences, etc.)
panel_project->clear();
// clear undo stack
olive::UndoStack.clear();
// empty current project filename
update_project_filename("");
// full update of all panels
update_ui(false);
// set to unmodified
olive::Global->set_modified(false);
}
void OliveGlobal::ImportProject(const QString &fn)
{
LoadProject(fn, false, false);
LoadProject(fn, false);
set_modified(true);
}
void OliveGlobal::new_project() {
if (can_close_project()) {
// clear graph editor
panel_graph_editor->set_row(nullptr);
// clear effects panel
panel_effect_controls->Clear(true);
// clear existing project
olive::Global->set_sequence(nullptr);
panel_footage_viewer->set_media(nullptr);
// clear project contents (footage, sequences, etc.)
panel_project->clear();
// clear undo stack
olive::UndoStack.clear();
// empty current project filename
update_project_filename("");
// full update of all panels
update_ui(false);
// set to unmodified
olive::Global->set_modified(false);
ClearProject();
}
}
@@ -289,12 +302,7 @@ bool OliveGlobal::can_close_project() {
}
void OliveGlobal::open_export_dialog() {
if (olive::ActiveSequence == nullptr) {
QMessageBox::information(olive::MainWindow,
tr("No active sequence"),
tr("Please open the sequence you wish to export."),
QMessageBox::Ok);
} else {
if (CheckForActiveSequence()) {
ExportDialog e(olive::MainWindow);
e.exec();
}
@@ -358,12 +366,29 @@ void OliveGlobal::set_sequence(SequencePtr s)
panel_timeline->setFocus();
}
void OliveGlobal::OpenProjectWorker(const QString& fn, bool autorecovery) {
void OliveGlobal::OpenProjectWorker(QString fn, bool autorecovery) {
ClearProject();
update_project_filename(fn);
LoadProject(fn, autorecovery, true);
LoadProject(fn, autorecovery);
olive::UndoStack.clear();
}
bool OliveGlobal::CheckForActiveSequence(bool show_msg)
{
if (olive::ActiveSequence == nullptr) {
if (show_msg) {
QMessageBox::information(olive::MainWindow,
tr("No active sequence"),
tr("Please open the sequence to perform this action."),
QMessageBox::Ok);
}
return false;
}
return true;
}
void OliveGlobal::undo() {
// workaround to prevent crash (and also users should never need to do this)
if (!panel_timeline->importing) {
@@ -413,6 +438,24 @@ void OliveGlobal::open_speed_dialog() {
}
}
void OliveGlobal::open_autocut_silence_dialog() {
if (CheckForActiveSequence()) {
QVector<Clip*> selected_clips = olive::ActiveSequence->SelectedClips();
if (selected_clips.isEmpty()) {
QMessageBox::critical(olive::MainWindow,
tr("No clips selected"),
tr("Select the clips you wish to auto-cut"),
QMessageBox::Ok);
} else {
AutoCutSilenceDialog s(olive::MainWindow, selected_clips);
s.exec();
}
}
}
void OliveGlobal::clear_undo_stack() {
olive::UndoStack.clear();
}
+27 -2
View File
@@ -275,6 +275,11 @@ public slots:
*/
void open_speed_dialog();
/**
* @brief Open the auto-cut silence dialog.
*/
void open_autocut_silence_dialog();
/**
* @brief Open the Action Search overlay.
*/
@@ -338,7 +343,19 @@ private:
* beside the original project file so that it does not overwrite the original and so that the user is not working
* on the autorecovery project in Olive's application data directory.
*/
void OpenProjectWorker(const QString& fn, bool autorecovery);
void OpenProjectWorker(QString fn, bool autorecovery);
/**
* @brief Returns whether a Sequence is currently active or not, and optionally displays a messagebox if not
*
* Checks whether a Sequence is active and can display a messagebox if not to inform users to make one active in
* order to perform said action.
*
* @return
*
* TRUE if there is an active Sequence, FALSE if not.
*/
bool CheckForActiveSequence(bool show_msg = true);
/**
* @brief Create a LoadDialog and start a LoadThread to load data from a project
@@ -366,7 +383,15 @@ private:
* TRUE if the current project should be closed before opening, FALSE if the project should be imported into the
* currently open one.
*/
void LoadProject(const QString& fn, bool autorecovery, bool clear);
void LoadProject(const QString& fn, bool autorecovery);
/**
* @brief Indiscriminately clear the project without prompting the user
*
* Will clear the entire project without prompting to save. This is dangerous, use new_project() instead for
* anything initiated by the user.
*/
void ClearProject();
/**
* @brief File filter used for any file dialogs relating to Olive project files.
+21 -2
View File
@@ -74,9 +74,28 @@ double cubic_t_from_x(double x_target, double a, double b, double c, double d) {
}
double amplitude_to_db(double amplitude) {
return (20.0*(qLn(amplitude)/qLn(10.0)));
return (20.0*(qLn(amplitude)/qLn(10.0)));
}
double db_to_amplitude(double db) {
return qPow(M_E, (db*qLn(10.0))/20.0);
return qPow(M_E, (db*qLn(10.0))/20.0);
}
QRect fit_size_into_rect(const QRect &r, int width, int height)
{
// Get aspect ratio of object we're fitting
double inner_ar = double(width) / double(height);
// Get aspect ratio of rectangle
double rect_ar = double(r.width()) / double(r.height());
if (rect_ar > inner_ar) {
// The rect is wider than the object, so we'll be limiting by height and scaling by width
int new_width = qRound(r.height() * inner_ar);
return QRect(r.x() + (r.width() / 2 - new_width / 2), r.y(), new_width, r.height());
} else {
// The rect is taller than the object, so we'll be limiting by width and scaling by height
int new_height = qRound(r.width() / inner_ar);
return QRect(r.x(), r.y() + (r.height() / 2 - new_height / 2), r.width(), new_height);
}
}
+4
View File
@@ -21,6 +21,8 @@
#ifndef MATH_H
#define MATH_H
#include <QRect>
int lerp(int a, int b, double t);
float float_lerp(float a, float b, float t);
double double_lerp(double a, double b, double t);
@@ -30,6 +32,8 @@ double cubic_from_t(double a, double b, double c, double d, double t);
double cubic_t_from_x(double x_target, double a, double b, double c, double d);
double solveCubicBezier(double p0, double p1, double p2, double p3, double x);
QRect fit_size_into_rect(const QRect& r, int width, int height);
// decibel conversion functions
double amplitude_to_db(double amplitude);
double db_to_amplitude(double db);